@5ss/ai-tools 2.11.1

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 (342) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/LICENSE +21 -0
  3. package/README.md +221 -0
  4. package/dist/ai-sdk/index.d.ts +15 -0
  5. package/dist/ai-sdk/index.d.ts.map +1 -0
  6. package/dist/ai-sdk/index.js +24 -0
  7. package/dist/ai-sdk/index.js.map +1 -0
  8. package/dist/artifact-D064mHfK.js +44 -0
  9. package/dist/artifact-D064mHfK.js.map +1 -0
  10. package/dist/artifacts-O8g-40Pw.js +404 -0
  11. package/dist/artifacts-O8g-40Pw.js.map +1 -0
  12. package/dist/aws-json-CecFqzqX.js +23 -0
  13. package/dist/aws-json-CecFqzqX.js.map +1 -0
  14. package/dist/aws-service-msttbPrz.js +58 -0
  15. package/dist/aws-service-msttbPrz.js.map +1 -0
  16. package/dist/batch-BMM5dXqL.d.ts +22 -0
  17. package/dist/batch-BMM5dXqL.d.ts.map +1 -0
  18. package/dist/batch-Co1ujeAW.js +67 -0
  19. package/dist/batch-Co1ujeAW.js.map +1 -0
  20. package/dist/bedrock-agentcore-browser-a_qOs-NR.js +182 -0
  21. package/dist/bedrock-agentcore-browser-a_qOs-NR.js.map +1 -0
  22. package/dist/bedrock-agentcore-code-interpreter-MWK-8RhA.js +357 -0
  23. package/dist/bedrock-agentcore-code-interpreter-MWK-8RhA.js.map +1 -0
  24. package/dist/bytes-BxpimpQx.js +45 -0
  25. package/dist/bytes-BxpimpQx.js.map +1 -0
  26. package/dist/client-CCKGsTeI.js +743 -0
  27. package/dist/client-CCKGsTeI.js.map +1 -0
  28. package/dist/cloudflare/index.d.ts +37 -0
  29. package/dist/cloudflare/index.d.ts.map +1 -0
  30. package/dist/cloudflare/index.js +41 -0
  31. package/dist/cloudflare/index.js.map +1 -0
  32. package/dist/cloudflare-browser-B6Yolpin.js +428 -0
  33. package/dist/cloudflare-browser-B6Yolpin.js.map +1 -0
  34. package/dist/cloudflare-email-Dy0KHeDf.js +197 -0
  35. package/dist/cloudflare-email-Dy0KHeDf.js.map +1 -0
  36. package/dist/cloudflare-sandbox-Dp_uNaqW.js +982 -0
  37. package/dist/cloudflare-sandbox-Dp_uNaqW.js.map +1 -0
  38. package/dist/content-type-CORxaxcv.js +49 -0
  39. package/dist/content-type-CORxaxcv.js.map +1 -0
  40. package/dist/core/index.d.ts +4 -0
  41. package/dist/core/index.js +204 -0
  42. package/dist/core/index.js.map +1 -0
  43. package/dist/define-CvpJ_pNP.js +115 -0
  44. package/dist/define-CvpJ_pNP.js.map +1 -0
  45. package/dist/errors-DoSpNHvs.js +20 -0
  46. package/dist/errors-DoSpNHvs.js.map +1 -0
  47. package/dist/errors-aKhko9T1.d.ts +18 -0
  48. package/dist/errors-aKhko9T1.d.ts.map +1 -0
  49. package/dist/eventbridge-scheduler-Bh6GqZY2.js +349 -0
  50. package/dist/eventbridge-scheduler-Bh6GqZY2.js.map +1 -0
  51. package/dist/framework-context-DVIIY8ZO.js +24 -0
  52. package/dist/framework-context-DVIIY8ZO.js.map +1 -0
  53. package/dist/gotenberg-NuJjxyln.js +291 -0
  54. package/dist/gotenberg-NuJjxyln.js.map +1 -0
  55. package/dist/http/index.d.ts +47 -0
  56. package/dist/http/index.d.ts.map +1 -0
  57. package/dist/http/index.js +3 -0
  58. package/dist/http-service-DDNCO1s4.js +254 -0
  59. package/dist/http-service-DDNCO1s4.js.map +1 -0
  60. package/dist/http-service-T7E5UjP8.d.ts +80 -0
  61. package/dist/http-service-T7E5UjP8.d.ts.map +1 -0
  62. package/dist/imessage-BSAFOI8Z.js +154 -0
  63. package/dist/imessage-BSAFOI8Z.js.map +1 -0
  64. package/dist/index-BU4gmYO8.d.ts +254 -0
  65. package/dist/index-BU4gmYO8.d.ts.map +1 -0
  66. package/dist/index-CCivzmxO.d.ts +188 -0
  67. package/dist/index-CCivzmxO.d.ts.map +1 -0
  68. package/dist/index-CLmTrcu5.d.ts +22 -0
  69. package/dist/index-CLmTrcu5.d.ts.map +1 -0
  70. package/dist/index-CZX5OeOF.d.ts +235 -0
  71. package/dist/index-CZX5OeOF.d.ts.map +1 -0
  72. package/dist/index-CdFmEfZO.d.ts +359 -0
  73. package/dist/index-CdFmEfZO.d.ts.map +1 -0
  74. package/dist/index-Cuh6eMWc.d.ts +285 -0
  75. package/dist/index-Cuh6eMWc.d.ts.map +1 -0
  76. package/dist/index-DuOGj7vc.d.ts +107 -0
  77. package/dist/index-DuOGj7vc.d.ts.map +1 -0
  78. package/dist/index-ccZ1XOHw.d.ts +69 -0
  79. package/dist/index-ccZ1XOHw.d.ts.map +1 -0
  80. package/dist/index-n8JTpNf1.d.ts +247 -0
  81. package/dist/index-n8JTpNf1.d.ts.map +1 -0
  82. package/dist/index-pwW1OsOx.d.ts +134 -0
  83. package/dist/index-pwW1OsOx.d.ts.map +1 -0
  84. package/dist/index-zK1ZwS4m.d.ts +347 -0
  85. package/dist/index-zK1ZwS4m.d.ts.map +1 -0
  86. package/dist/limits-hjrO8zUG.js +80 -0
  87. package/dist/limits-hjrO8zUG.js.map +1 -0
  88. package/dist/mastra/index.d.ts +14 -0
  89. package/dist/mastra/index.d.ts.map +1 -0
  90. package/dist/mastra/index.js +26 -0
  91. package/dist/mastra/index.js.map +1 -0
  92. package/dist/mastra-vector-Dhc6XZ8l.js +234 -0
  93. package/dist/mastra-vector-Dhc6XZ8l.js.map +1 -0
  94. package/dist/mcp/index.d.ts +80 -0
  95. package/dist/mcp/index.d.ts.map +1 -0
  96. package/dist/mcp/index.js +97 -0
  97. package/dist/mcp/index.js.map +1 -0
  98. package/dist/modules/artifacts/index.d.ts +337 -0
  99. package/dist/modules/artifacts/index.d.ts.map +1 -0
  100. package/dist/modules/artifacts/index.js +348 -0
  101. package/dist/modules/artifacts/index.js.map +1 -0
  102. package/dist/modules/browser/index.d.ts +516 -0
  103. package/dist/modules/browser/index.d.ts.map +1 -0
  104. package/dist/modules/browser/index.js +475 -0
  105. package/dist/modules/browser/index.js.map +1 -0
  106. package/dist/modules/calendar/index.d.ts +93 -0
  107. package/dist/modules/calendar/index.d.ts.map +1 -0
  108. package/dist/modules/calendar/index.js +131 -0
  109. package/dist/modules/calendar/index.js.map +1 -0
  110. package/dist/modules/code-sandbox/index.d.ts +317 -0
  111. package/dist/modules/code-sandbox/index.d.ts.map +1 -0
  112. package/dist/modules/code-sandbox/index.js +537 -0
  113. package/dist/modules/code-sandbox/index.js.map +1 -0
  114. package/dist/modules/content-type/index.d.ts +22 -0
  115. package/dist/modules/content-type/index.d.ts.map +1 -0
  116. package/dist/modules/content-type/index.js +66 -0
  117. package/dist/modules/content-type/index.js.map +1 -0
  118. package/dist/modules/crypto/index.d.ts +115 -0
  119. package/dist/modules/crypto/index.d.ts.map +1 -0
  120. package/dist/modules/crypto/index.js +139 -0
  121. package/dist/modules/crypto/index.js.map +1 -0
  122. package/dist/modules/document/index.d.ts +575 -0
  123. package/dist/modules/document/index.d.ts.map +1 -0
  124. package/dist/modules/document/index.js +444 -0
  125. package/dist/modules/document/index.js.map +1 -0
  126. package/dist/modules/document-extract/index.d.ts +438 -0
  127. package/dist/modules/document-extract/index.d.ts.map +1 -0
  128. package/dist/modules/document-extract/index.js +127 -0
  129. package/dist/modules/document-extract/index.js.map +1 -0
  130. package/dist/modules/document-render/index.d.ts +336 -0
  131. package/dist/modules/document-render/index.d.ts.map +1 -0
  132. package/dist/modules/document-render/index.js +155 -0
  133. package/dist/modules/document-render/index.js.map +1 -0
  134. package/dist/modules/email/index.d.ts +311 -0
  135. package/dist/modules/email/index.d.ts.map +1 -0
  136. package/dist/modules/email/index.js +167 -0
  137. package/dist/modules/email/index.js.map +1 -0
  138. package/dist/modules/email-message/index.d.ts +95 -0
  139. package/dist/modules/email-message/index.d.ts.map +1 -0
  140. package/dist/modules/email-message/index.js +264 -0
  141. package/dist/modules/email-message/index.js.map +1 -0
  142. package/dist/modules/file-convert/index.d.ts +273 -0
  143. package/dist/modules/file-convert/index.d.ts.map +1 -0
  144. package/dist/modules/file-convert/index.js +103 -0
  145. package/dist/modules/file-convert/index.js.map +1 -0
  146. package/dist/modules/files/index.d.ts +452 -0
  147. package/dist/modules/files/index.d.ts.map +1 -0
  148. package/dist/modules/files/index.js +733 -0
  149. package/dist/modules/files/index.js.map +1 -0
  150. package/dist/modules/image/index.d.ts +342 -0
  151. package/dist/modules/image/index.d.ts.map +1 -0
  152. package/dist/modules/image/index.js +281 -0
  153. package/dist/modules/image/index.js.map +1 -0
  154. package/dist/modules/messaging/index.d.ts +608 -0
  155. package/dist/modules/messaging/index.d.ts.map +1 -0
  156. package/dist/modules/messaging/index.js +1067 -0
  157. package/dist/modules/messaging/index.js.map +1 -0
  158. package/dist/modules/pdf/index.d.ts +287 -0
  159. package/dist/modules/pdf/index.d.ts.map +1 -0
  160. package/dist/modules/pdf/index.js +259 -0
  161. package/dist/modules/pdf/index.js.map +1 -0
  162. package/dist/modules/presentation/index.d.ts +247 -0
  163. package/dist/modules/presentation/index.d.ts.map +1 -0
  164. package/dist/modules/presentation/index.js +12657 -0
  165. package/dist/modules/presentation/index.js.map +1 -0
  166. package/dist/modules/queue/index.d.ts +129 -0
  167. package/dist/modules/queue/index.d.ts.map +1 -0
  168. package/dist/modules/queue/index.js +131 -0
  169. package/dist/modules/queue/index.js.map +1 -0
  170. package/dist/modules/rag/index.d.ts +250 -0
  171. package/dist/modules/rag/index.d.ts.map +1 -0
  172. package/dist/modules/rag/index.js +366 -0
  173. package/dist/modules/rag/index.js.map +1 -0
  174. package/dist/modules/scheduler/index.d.ts +216 -0
  175. package/dist/modules/scheduler/index.d.ts.map +1 -0
  176. package/dist/modules/scheduler/index.js +153 -0
  177. package/dist/modules/scheduler/index.js.map +1 -0
  178. package/dist/modules/skills/index.d.ts +205 -0
  179. package/dist/modules/skills/index.d.ts.map +1 -0
  180. package/dist/modules/skills/index.js +203 -0
  181. package/dist/modules/skills/index.js.map +1 -0
  182. package/dist/modules/tasks/index.d.ts +287 -0
  183. package/dist/modules/tasks/index.d.ts.map +1 -0
  184. package/dist/modules/tasks/index.js +207 -0
  185. package/dist/modules/tasks/index.js.map +1 -0
  186. package/dist/modules/vector-store/index.d.ts +3 -0
  187. package/dist/modules/vector-store/index.js +3 -0
  188. package/dist/modules/web-fetch/index.d.ts +99 -0
  189. package/dist/modules/web-fetch/index.d.ts.map +1 -0
  190. package/dist/modules/web-fetch/index.js +242 -0
  191. package/dist/modules/web-fetch/index.js.map +1 -0
  192. package/dist/object-artifact-store-CMTzCm_G.d.ts +7 -0
  193. package/dist/object-artifact-store-CMTzCm_G.d.ts.map +1 -0
  194. package/dist/object-artifact-store-wZ2j9cto.js +28 -0
  195. package/dist/object-artifact-store-wZ2j9cto.js.map +1 -0
  196. package/dist/pinecone-umY4t6OF.js +190 -0
  197. package/dist/pinecone-umY4t6OF.js.map +1 -0
  198. package/dist/provider-CgDAlg6K.js +34 -0
  199. package/dist/provider-CgDAlg6K.js.map +1 -0
  200. package/dist/qdrant-DMp4NhKR.js +253 -0
  201. package/dist/qdrant-DMp4NhKR.js.map +1 -0
  202. package/dist/resend-BAC38_dA.js +155 -0
  203. package/dist/resend-BAC38_dA.js.map +1 -0
  204. package/dist/s3-CsOaPWMP.js +955 -0
  205. package/dist/s3-CsOaPWMP.js.map +1 -0
  206. package/dist/schemas-ChOAhdo9.js +192 -0
  207. package/dist/schemas-ChOAhdo9.js.map +1 -0
  208. package/dist/slack-Di5BBNpt.js +1455 -0
  209. package/dist/slack-Di5BBNpt.js.map +1 -0
  210. package/dist/sqs-DCwS1i2N.js +225 -0
  211. package/dist/sqs-DCwS1i2N.js.map +1 -0
  212. package/dist/supabase-vector-Dpp9mmJR.js +218 -0
  213. package/dist/supabase-vector-Dpp9mmJR.js.map +1 -0
  214. package/dist/tanstack/index.d.ts +15 -0
  215. package/dist/tanstack/index.d.ts.map +1 -0
  216. package/dist/tanstack/index.js +28 -0
  217. package/dist/tanstack/index.js.map +1 -0
  218. package/dist/teams-DYAHNb39.js +835 -0
  219. package/dist/teams-DYAHNb39.js.map +1 -0
  220. package/dist/telegram-DDXWzkfL.js +734 -0
  221. package/dist/telegram-DDXWzkfL.js.map +1 -0
  222. package/dist/textract-CPLiB22H.js +554 -0
  223. package/dist/textract-CPLiB22H.js.map +1 -0
  224. package/dist/transport-B4vn-XiQ.js +157 -0
  225. package/dist/transport-B4vn-XiQ.js.map +1 -0
  226. package/dist/transport-i96ACAI_.d.ts +46 -0
  227. package/dist/transport-i96ACAI_.d.ts.map +1 -0
  228. package/dist/types-Ccb0DXY9.d.ts +150 -0
  229. package/dist/types-Ccb0DXY9.d.ts.map +1 -0
  230. package/dist/unique-EwBH1JPB.js +19 -0
  231. package/dist/unique-EwBH1JPB.js.map +1 -0
  232. package/dist/vector-store-C3nEO80e.js +193 -0
  233. package/dist/vector-store-C3nEO80e.js.map +1 -0
  234. package/dist/vendors/amazon-sp-api/index.d.ts +526 -0
  235. package/dist/vendors/amazon-sp-api/index.d.ts.map +1 -0
  236. package/dist/vendors/amazon-sp-api/index.js +975 -0
  237. package/dist/vendors/amazon-sp-api/index.js.map +1 -0
  238. package/dist/vendors/bedrock-agentcore-browser/index.d.ts +2 -0
  239. package/dist/vendors/bedrock-agentcore-browser/index.js +2 -0
  240. package/dist/vendors/bedrock-agentcore-code-interpreter/index.d.ts +228 -0
  241. package/dist/vendors/bedrock-agentcore-code-interpreter/index.d.ts.map +1 -0
  242. package/dist/vendors/bedrock-agentcore-code-interpreter/index.js +2 -0
  243. package/dist/vendors/cloudflare-browser/index.d.ts +2 -0
  244. package/dist/vendors/cloudflare-browser/index.js +2 -0
  245. package/dist/vendors/cloudflare-email/index.d.ts +260 -0
  246. package/dist/vendors/cloudflare-email/index.d.ts.map +1 -0
  247. package/dist/vendors/cloudflare-email/index.js +3 -0
  248. package/dist/vendors/cloudflare-sandbox/index.d.ts +565 -0
  249. package/dist/vendors/cloudflare-sandbox/index.d.ts.map +1 -0
  250. package/dist/vendors/cloudflare-sandbox/index.js +2 -0
  251. package/dist/vendors/eventbridge-scheduler/index.d.ts +2 -0
  252. package/dist/vendors/eventbridge-scheduler/index.js +2 -0
  253. package/dist/vendors/gotenberg/index.d.ts +306 -0
  254. package/dist/vendors/gotenberg/index.d.ts.map +1 -0
  255. package/dist/vendors/gotenberg/index.js +2 -0
  256. package/dist/vendors/imessage/index.d.ts +420 -0
  257. package/dist/vendors/imessage/index.d.ts.map +1 -0
  258. package/dist/vendors/imessage/index.js +4 -0
  259. package/dist/vendors/katana/index.d.ts +1570 -0
  260. package/dist/vendors/katana/index.d.ts.map +1 -0
  261. package/dist/vendors/katana/index.js +1639 -0
  262. package/dist/vendors/katana/index.js.map +1 -0
  263. package/dist/vendors/mastra-vector/index.d.ts +120 -0
  264. package/dist/vendors/mastra-vector/index.d.ts.map +1 -0
  265. package/dist/vendors/mastra-vector/index.js +3 -0
  266. package/dist/vendors/pinecone/index.d.ts +75 -0
  267. package/dist/vendors/pinecone/index.d.ts.map +1 -0
  268. package/dist/vendors/pinecone/index.js +3 -0
  269. package/dist/vendors/qdrant/index.d.ts +75 -0
  270. package/dist/vendors/qdrant/index.d.ts.map +1 -0
  271. package/dist/vendors/qdrant/index.js +3 -0
  272. package/dist/vendors/resend/index.d.ts +3 -0
  273. package/dist/vendors/resend/index.js +3 -0
  274. package/dist/vendors/s3/index.d.ts +2 -0
  275. package/dist/vendors/s3/index.js +2 -0
  276. package/dist/vendors/slack/index.d.ts +576 -0
  277. package/dist/vendors/slack/index.d.ts.map +1 -0
  278. package/dist/vendors/slack/index.js +3 -0
  279. package/dist/vendors/sqs/index.d.ts +2 -0
  280. package/dist/vendors/sqs/index.js +2 -0
  281. package/dist/vendors/supabase-vector/index.d.ts +89 -0
  282. package/dist/vendors/supabase-vector/index.d.ts.map +1 -0
  283. package/dist/vendors/supabase-vector/index.js +3 -0
  284. package/dist/vendors/teams/index.d.ts +303 -0
  285. package/dist/vendors/teams/index.d.ts.map +1 -0
  286. package/dist/vendors/teams/index.js +3 -0
  287. package/dist/vendors/telegram/index.d.ts +319 -0
  288. package/dist/vendors/telegram/index.d.ts.map +1 -0
  289. package/dist/vendors/telegram/index.js +3 -0
  290. package/dist/vendors/textract/index.d.ts +2 -0
  291. package/dist/vendors/textract/index.js +2 -0
  292. package/dist/vendors/woocommerce/index.d.ts +1700 -0
  293. package/dist/vendors/woocommerce/index.d.ts.map +1 -0
  294. package/dist/vendors/woocommerce/index.js +1427 -0
  295. package/dist/vendors/woocommerce/index.js.map +1 -0
  296. package/dist/with-auth-CpKqTrGK.js +240 -0
  297. package/dist/with-auth-CpKqTrGK.js.map +1 -0
  298. package/logos/LUCIDE-ATTRIBUTION.txt +4 -0
  299. package/logos/README.md +89 -0
  300. package/logos/amazon.svg +6 -0
  301. package/logos/artifacts.svg +9 -0
  302. package/logos/browser.svg +9 -0
  303. package/logos/calendar.svg +15 -0
  304. package/logos/cloudflare-browser.svg +5 -0
  305. package/logos/cloudflare-email.svg +5 -0
  306. package/logos/cloudflare.svg +4 -0
  307. package/logos/code-sandbox.svg +8 -0
  308. package/logos/content-type.svg +10 -0
  309. package/logos/crypto.svg +7 -0
  310. package/logos/document-extract.svg +12 -0
  311. package/logos/document-render.svg +8 -0
  312. package/logos/document.svg +10 -0
  313. package/logos/email-message.svg +8 -0
  314. package/logos/email.svg +7 -0
  315. package/logos/file-convert.svg +9 -0
  316. package/logos/files.svg +6 -0
  317. package/logos/gotenberg.svg +340 -0
  318. package/logos/image.svg +8 -0
  319. package/logos/imessage.svg +7 -0
  320. package/logos/katana.svg +13 -0
  321. package/logos/mastra.svg +7 -0
  322. package/logos/messaging.svg +7 -0
  323. package/logos/pack-logos.json +48 -0
  324. package/logos/pdf.svg +10 -0
  325. package/logos/pinecone.svg +25 -0
  326. package/logos/presentation.svg +8 -0
  327. package/logos/qdrant.svg +4 -0
  328. package/logos/queue.svg +11 -0
  329. package/logos/rag.svg +18 -0
  330. package/logos/resend.svg +5 -0
  331. package/logos/scheduler.svg +7 -0
  332. package/logos/skills.svg +10 -0
  333. package/logos/slack.svg +14 -0
  334. package/logos/supabase.svg +4 -0
  335. package/logos/tasks.svg +10 -0
  336. package/logos/teams.svg +6 -0
  337. package/logos/telegram.svg +10 -0
  338. package/logos/textract.svg +5 -0
  339. package/logos/vector-store.svg +8 -0
  340. package/logos/web-fetch.svg +8 -0
  341. package/logos/woocommerce.svg +4 -0
  342. package/package.json +373 -0
@@ -0,0 +1,554 @@
1
+ import { t as ToolError } from "./errors-DoSpNHvs.js";
2
+ import { n as defineModule, r as defineTool } from "./define-CvpJ_pNP.js";
3
+ import { n as requireAuth } from "./provider-CgDAlg6K.js";
4
+ import { t as artifactRefSchema } from "./artifact-D064mHfK.js";
5
+ import { t as AwsService } from "./aws-service-msttbPrz.js";
6
+ import { o as utf8ToBytes } from "./bytes-BxpimpQx.js";
7
+ import { H as resolveObjectKey, V as normalizeKeyPrefix, p as S3Client } from "./s3-CsOaPWMP.js";
8
+ import { n as runBatchItems, t as batchResultSchema } from "./batch-Co1ujeAW.js";
9
+ import { t as parseAwsJsonBody } from "./aws-json-CecFqzqX.js";
10
+ import { isPlainObject, isString } from "es-toolkit";
11
+ import { isArray } from "es-toolkit/compat";
12
+ import { z } from "zod";
13
+ //#region src/vendors/textract/contracts.ts
14
+ const MAX_BATCH_EXTRACT = 10;
15
+ const DEFAULT_POLL_TIMEOUT_MS = 6e4;
16
+ const DEFAULT_POLL_INTERVAL_MS = 2e3;
17
+ const MAX_POLL_TIMEOUT_MS = 9e5;
18
+ const MAX_POLL_INTERVAL_MS = 3e4;
19
+ /** Hard cap for inline extract text returned to the model. */
20
+ const MAX_INLINE_EXTRACT_CHARS = 1e5;
21
+ const DEFAULT_EXTRACT_CHUNK_MAX_CHARS = 1200;
22
+ const DEFAULT_EXTRACT_CHUNK_OVERLAP = 200;
23
+ const MAX_EXTRACT_CHUNK_MAX_CHARS = 8e3;
24
+ const textractAuthSchema = z.object({
25
+ access_key_id: z.string().min(1).describe("AWS access key id"),
26
+ secret_access_key: z.string().min(1).describe("AWS secret access key"),
27
+ region: z.string().min(1).describe("AWS region for Textract and the source S3 bucket"),
28
+ bucket: z.string().min(1).describe("AWS S3 bucket containing source documents"),
29
+ session_token: z.string().min(1).optional().describe("Optional session token"),
30
+ key_prefix: z.string().min(1).optional().describe("Optional object-key root matching the bound S3 storage (no leading slash). ArtifactRef.key is logical; DocumentLocation uses the wire key under this prefix."),
31
+ poll_timeout_ms: z.int().min(1e3).max(MAX_POLL_TIMEOUT_MS).optional().describe("Max time to wait for Textract before returning pending plus job_id (default 60000)"),
32
+ poll_interval_ms: z.int().min(200).max(MAX_POLL_INTERVAL_MS).optional().describe("Delay between GetDocumentTextDetection polls (default 2000)")
33
+ });
34
+ const textractOutputModeSchema = z.enum([
35
+ "inline",
36
+ "artifact",
37
+ "chunks"
38
+ ]).describe("How to return extracted text: inline (default, fails if over inline limit), artifact (write to object storage), chunks (split for RAG handoff)");
39
+ const textractChunkOptionsSchema = z.object({
40
+ max_chars: z.int().min(200).max(MAX_EXTRACT_CHUNK_MAX_CHARS).optional().describe(`Chunk size in characters (default ${DEFAULT_EXTRACT_CHUNK_MAX_CHARS})`),
41
+ overlap: z.int().min(0).max(2e3).optional().describe(`Overlap in characters between chunks (default 200)`)
42
+ });
43
+ const textractTextChunkSchema = z.object({
44
+ id: z.string().describe("Stable chunk id (document-scoped)"),
45
+ index: z.number().int().nonnegative(),
46
+ text: z.string().describe("Chunk text")
47
+ });
48
+ const outputModeFields = {
49
+ output: textractOutputModeSchema.optional(),
50
+ destination_key: z.string().min(1).optional().describe("Object key for artifact mode (logical under key_prefix when set). Default extracts/{job_id}.txt"),
51
+ chunk: textractChunkOptionsSchema.optional().describe("Chunking options when output is chunks")
52
+ };
53
+ const textractExtractResultSchema = z.object({
54
+ status: z.enum([
55
+ "succeeded",
56
+ "pending",
57
+ "failed"
58
+ ]).describe("Job status"),
59
+ job_id: z.string().optional().describe("Textract job id when started or polled"),
60
+ text: z.string().optional().describe("Extracted LINE text when succeeded and output is inline"),
61
+ page_count: z.int().optional().describe("Document page count when known"),
62
+ error: z.string().optional().describe("Failure message when status is failed"),
63
+ source: artifactRefSchema.optional().describe("Source ArtifactRef when known"),
64
+ output: textractOutputModeSchema.optional().describe("Presentation mode used for this result"),
65
+ artifact: artifactRefSchema.optional().describe("Object-store ArtifactRef when output is artifact and status is succeeded"),
66
+ chunks: z.array(textractTextChunkSchema).optional().describe("Text chunks when output is chunks and status is succeeded")
67
+ });
68
+ const textractExtractTextInputSchema = z.object({
69
+ source: artifactRefSchema.describe("Document ArtifactRef in object storage (store must be object)"),
70
+ ...outputModeFields
71
+ });
72
+ const textractExtractTextBatchInputSchema = z.object({
73
+ sources: z.array(artifactRefSchema).min(1).max(10).describe("Document ArtifactRefs to extract (max 10)"),
74
+ ...outputModeFields,
75
+ destination_key_prefix: z.string().min(1).optional().describe("Prefix for per-item artifact keys in batch artifact mode (default extracts/)")
76
+ });
77
+ const textractStatusInputSchema = z.object({
78
+ job_id: z.string().min(1).describe("Job id from a prior extract call"),
79
+ ...outputModeFields
80
+ });
81
+ const textractExtractTextBatchOutputSchema = batchResultSchema(textractExtractResultSchema);
82
+ //#endregion
83
+ //#region src/vendors/textract/domain.ts
84
+ /**
85
+ * Textract payload helpers + extract presentation (no HTTP).
86
+ * inline | artifact | chunks — product logic lives in the vendor, not the seam.
87
+ */
88
+ function lineTextFromBlocks(payload) {
89
+ const blocks = payload["Blocks"];
90
+ const lines = [];
91
+ if (isArray(blocks)) for (const block of blocks) {
92
+ if (!isPlainObject(block)) continue;
93
+ if (block["BlockType"] !== "LINE") continue;
94
+ const t = block["Text"];
95
+ if (isString(t) && t.length > 0) lines.push(t);
96
+ }
97
+ const meta = payload["DocumentMetadata"];
98
+ let page_count;
99
+ if (isPlainObject(meta) && typeof meta["Pages"] === "number" && Number.isFinite(meta["Pages"])) page_count = meta["Pages"];
100
+ return {
101
+ text: lines.join("\n"),
102
+ ...page_count !== void 0 && { page_count }
103
+ };
104
+ }
105
+ function mapJobStatus(jobStatus) {
106
+ if (jobStatus === "SUCCEEDED" || jobStatus === "PARTIAL_SUCCESS") return "succeeded";
107
+ if (jobStatus === "FAILED") return "failed";
108
+ return "pending";
109
+ }
110
+ function sleep(ms, signal) {
111
+ return new Promise((resolve, reject) => {
112
+ if (signal?.aborted) {
113
+ reject(new DOMException("Aborted", "AbortError"));
114
+ return;
115
+ }
116
+ const timer = setTimeout(() => {
117
+ signal?.removeEventListener("abort", onAbort);
118
+ resolve();
119
+ }, ms);
120
+ const onAbort = () => {
121
+ clearTimeout(timer);
122
+ reject(new DOMException("Aborted", "AbortError"));
123
+ };
124
+ signal?.addEventListener("abort", onAbort, { once: true });
125
+ });
126
+ }
127
+ /**
128
+ * Apply output mode to a raw extract result.
129
+ * - inline: fail with too_large when text exceeds MAX_INLINE_EXTRACT_CHARS
130
+ * - artifact: caller must pass writeArtifact; text is stripped from the result
131
+ * - chunks: split text for RAG handoff; full text stripped
132
+ */
133
+ async function presentExtractResult(raw, options, writeArtifact) {
134
+ const mode = options.output ?? "inline";
135
+ if (raw.status !== "succeeded" || raw.text === void 0) return baseResult(raw, mode);
136
+ const text = raw.text;
137
+ if (mode === "inline") {
138
+ if (text.length > 1e5) throw new ToolError(`Extracted text exceeds inline limit (${MAX_INLINE_EXTRACT_CHARS} characters); use output: "artifact" or "chunks"`, {
139
+ code: "too_large",
140
+ details: {
141
+ max_inline_chars: MAX_INLINE_EXTRACT_CHARS,
142
+ char_count: text.length,
143
+ suggested_output: "artifact"
144
+ }
145
+ });
146
+ return baseResult(raw, "inline");
147
+ }
148
+ if (mode === "chunks") {
149
+ const pieces = chunkText(text, {
150
+ max_chars: options.chunk?.max_chars ?? 1200,
151
+ overlap: options.chunk?.overlap ?? 200
152
+ });
153
+ const docId = options.source_key ?? raw.job_id ?? "extract";
154
+ const chunks = pieces.map((piece, index) => ({
155
+ id: chunkId(docId, index),
156
+ index,
157
+ text: piece
158
+ }));
159
+ const out = baseResult(raw, "chunks");
160
+ delete out.text;
161
+ out.chunks = chunks;
162
+ return out;
163
+ }
164
+ if (!writeArtifact) throw new ToolError("Artifact output requires object storage credentials on extract auth", { code: "bad_auth" });
165
+ const artifact = await writeArtifact(options.destination_key ?? `extracts/${raw.job_id ?? sanitizeKeySegment(options.source_key ?? "document")}.txt`, text);
166
+ const out = baseResult(raw, "artifact");
167
+ delete out.text;
168
+ out.artifact = artifact;
169
+ return out;
170
+ }
171
+ function baseResult(raw, mode) {
172
+ const out = {
173
+ status: raw.status,
174
+ output: mode
175
+ };
176
+ if (raw.job_id !== void 0) out.job_id = raw.job_id;
177
+ if (raw.text !== void 0) out.text = raw.text;
178
+ if (raw.page_count !== void 0) out.page_count = raw.page_count;
179
+ if (raw.error !== void 0) out.error = raw.error;
180
+ if (raw.source !== void 0) out.source = raw.source;
181
+ return out;
182
+ }
183
+ function sanitizeKeySegment(value) {
184
+ const base = value.replace(/^.*\//, "").replace(/[^\w.-]+/g, "_");
185
+ return base.length > 0 ? base.slice(0, 120) : "document";
186
+ }
187
+ function chunkId(documentId, index) {
188
+ return `${documentId}#${index}`;
189
+ }
190
+ /** Overlapping character windows; prefers paragraph/newline soft breaks. */
191
+ function chunkText(text, options) {
192
+ const maxChars = options.max_chars;
193
+ const overlap = Math.min(options.overlap, Math.max(0, maxChars - 1));
194
+ const normalized = text.replace(/\r\n/g, "\n").trim();
195
+ if (normalized.length === 0) return [];
196
+ if (normalized.length <= maxChars) return [normalized];
197
+ const chunks = [];
198
+ let start = 0;
199
+ while (start < normalized.length) {
200
+ let end = Math.min(start + maxChars, normalized.length);
201
+ if (end < normalized.length) {
202
+ const window = normalized.slice(start, end);
203
+ const para = window.lastIndexOf("\n\n");
204
+ const line = window.lastIndexOf("\n");
205
+ const soft = para >= maxChars * .5 ? para : line >= maxChars * .5 ? line : -1;
206
+ if (soft > 0) end = start + soft;
207
+ }
208
+ const piece = normalized.slice(start, end).trim();
209
+ if (piece.length > 0) chunks.push(piece);
210
+ if (end >= normalized.length) break;
211
+ const next = end - overlap;
212
+ start = next <= start ? end : next;
213
+ }
214
+ return chunks;
215
+ }
216
+ //#endregion
217
+ //#region src/vendors/textract/client.ts
218
+ /**
219
+ * Amazon Textract vendor client (async text detection + presentation).
220
+ * Host: `new TextractClient(auth)`. Agent tools: `fromContext(ctx)`.
221
+ * Output modes (inline | artifact | chunks) live here — not in the seam module.
222
+ */
223
+ var TextractClient = class TextractClient {
224
+ #auth;
225
+ #aws;
226
+ #storage;
227
+ #signal;
228
+ /** Normalized key_prefix with trailing `/`, or undefined when unbound. */
229
+ #keyPrefix;
230
+ constructor(auth, options = {}) {
231
+ const parsed = textractAuthSchema.safeParse(auth);
232
+ if (!parsed.success) throw new ToolError("Invalid Textract auth credentials", {
233
+ code: "bad_auth",
234
+ details: { issues: parsed.error.issues.map((issue) => issue.message) }
235
+ });
236
+ this.#auth = parsed.data;
237
+ this.#keyPrefix = parsed.data.key_prefix !== void 0 ? normalizeKeyPrefix(parsed.data.key_prefix) : void 0;
238
+ this.#signal = options.signal;
239
+ this.#aws = new AwsService({
240
+ ...options,
241
+ accessKeyId: this.#auth.access_key_id,
242
+ secretAccessKey: this.#auth.secret_access_key,
243
+ region: this.#auth.region,
244
+ service: "textract",
245
+ baseURL: `https://textract.${this.#auth.region}.amazonaws.com`,
246
+ label: "Textract",
247
+ ...this.#auth.session_token && { sessionToken: this.#auth.session_token }
248
+ });
249
+ this.#storage = new S3Client({
250
+ access_key_id: this.#auth.access_key_id,
251
+ secret_access_key: this.#auth.secret_access_key,
252
+ region: this.#auth.region,
253
+ bucket: this.#auth.bucket,
254
+ ...this.#auth.session_token && { session_token: this.#auth.session_token },
255
+ ...this.#auth.key_prefix && { key_prefix: this.#auth.key_prefix }
256
+ }, options);
257
+ }
258
+ static fromContext(ctx) {
259
+ const auth = requireAuth(ctx, textractAuthSchema);
260
+ return new TextractClient(auth, {
261
+ ...ctx.fetch && { fetch: ctx.fetch },
262
+ ...ctx.signal && { signal: ctx.signal }
263
+ });
264
+ }
265
+ /** StartDocumentTextDetection + poll until done, failed, or timeout → pending; then present. */
266
+ async extractText(input) {
267
+ return presentExtractResult(await this.#extractRaw(input.source), presentOpts(input.output, input.destination_key, input.chunk, input.source.key), (key, text) => this.#writeExtractArtifact(key, text, input.source.filename));
268
+ }
269
+ /** GetDocumentTextDetection (paged) for an existing job; then present. */
270
+ async getStatus(input) {
271
+ const raw = await this.#statusRaw(input.job_id);
272
+ return presentExtractResult(raw, presentOpts(input.output, input.destination_key, input.chunk, raw.source?.key), (key, text) => this.#writeExtractArtifact(key, text, raw.source?.filename));
273
+ }
274
+ async extractTextBatch(input) {
275
+ const prefix = input.destination_key_prefix ?? "extracts/";
276
+ const rawBatch = await runBatchItems(input.sources, (source) => this.#extractRaw(source));
277
+ const results = [];
278
+ let succeeded = 0;
279
+ let failed = 0;
280
+ for (const row of rawBatch.results) {
281
+ if (!row.ok || row.value === void 0) {
282
+ results.push(row);
283
+ failed += 1;
284
+ continue;
285
+ }
286
+ const source = input.sources[row.index];
287
+ const destKey = input.destination_key ?? `${prefix.replace(/\/?$/, "/")}${source?.key.replace(/^.*\//, "") || `item-${row.index}`}.txt`;
288
+ try {
289
+ const presented = await presentExtractResult(row.value, presentOpts(input.output, destKey, input.chunk, source?.key), (key, text) => this.#writeExtractArtifact(key, text, source?.filename));
290
+ results.push({
291
+ index: row.index,
292
+ ok: true,
293
+ value: presented
294
+ });
295
+ succeeded += 1;
296
+ } catch (error) {
297
+ const message = error instanceof Error ? error.message : "Presentation failed";
298
+ const code = error instanceof Error && "code" in error && typeof error.code === "string" ? error.code : "internal";
299
+ results.push({
300
+ index: row.index,
301
+ ok: false,
302
+ error: {
303
+ code,
304
+ message
305
+ }
306
+ });
307
+ failed += 1;
308
+ }
309
+ }
310
+ return {
311
+ results,
312
+ succeeded,
313
+ failed
314
+ };
315
+ }
316
+ async #extractRaw(source) {
317
+ if (source.store !== "object") throw new ToolError("Textract requires source.store \"object\"", { code: "bad_input" });
318
+ const wireName = resolveObjectKey(source.key, this.#keyPrefix);
319
+ let start;
320
+ try {
321
+ start = await this.#call("Textract.StartDocumentTextDetection", { DocumentLocation: { S3Object: {
322
+ Bucket: this.#auth.bucket,
323
+ Name: wireName
324
+ } } });
325
+ } catch (error) {
326
+ if (error instanceof ToolError) throw new ToolError(error.message, {
327
+ code: error.code,
328
+ retryable: error.retryable,
329
+ cause: error.cause,
330
+ details: {
331
+ ...isPlainObject(error.details) ? error.details : {},
332
+ key: source.key
333
+ }
334
+ });
335
+ throw error;
336
+ }
337
+ const jobId = start["JobId"];
338
+ if (!isString(jobId) || jobId.length === 0) throw new ToolError("Textract did not return a JobId", { code: "upstream" });
339
+ const timeoutMs = this.#auth.poll_timeout_ms ?? 6e4;
340
+ const intervalMs = this.#auth.poll_interval_ms ?? 2e3;
341
+ const deadline = Date.now() + timeoutMs;
342
+ try {
343
+ while (Date.now() < deadline) {
344
+ const payload = await this.#getJobPayload(jobId);
345
+ const statusRaw = payload["JobStatus"];
346
+ const status = isString(statusRaw) ? mapJobStatus(statusRaw) : "pending";
347
+ if (status === "succeeded") {
348
+ const lines = lineTextFromBlocks(payload);
349
+ return textractExtractResultSchema.parse({
350
+ status: "succeeded",
351
+ job_id: jobId,
352
+ text: lines.text,
353
+ ...lines.page_count !== void 0 && { page_count: lines.page_count },
354
+ source
355
+ });
356
+ }
357
+ if (status === "failed") {
358
+ const msg = payload["StatusMessage"];
359
+ return textractExtractResultSchema.parse({
360
+ status: "failed",
361
+ job_id: jobId,
362
+ error: isString(msg) ? msg : "Textract job failed",
363
+ source
364
+ });
365
+ }
366
+ const remaining = deadline - Date.now();
367
+ if (remaining <= 0) break;
368
+ await sleep(Math.min(intervalMs, remaining), this.#signal);
369
+ }
370
+ } catch (error) {
371
+ if (error instanceof ToolError) throw error;
372
+ if (error instanceof Error && error.name === "AbortError") throw new ToolError("Textract extract was aborted", {
373
+ code: "timeout",
374
+ retryable: true,
375
+ cause: error
376
+ });
377
+ throw error;
378
+ }
379
+ return textractExtractResultSchema.parse({
380
+ status: "pending",
381
+ job_id: jobId,
382
+ source
383
+ });
384
+ }
385
+ async #statusRaw(jobId) {
386
+ const payload = await this.#getJobPayload(jobId);
387
+ const statusRaw = payload["JobStatus"];
388
+ const status = isString(statusRaw) ? mapJobStatus(statusRaw) : "pending";
389
+ if (status === "succeeded") {
390
+ const lines = lineTextFromBlocks(payload);
391
+ return textractExtractResultSchema.parse({
392
+ status: "succeeded",
393
+ job_id: jobId,
394
+ text: lines.text,
395
+ ...lines.page_count !== void 0 && { page_count: lines.page_count }
396
+ });
397
+ }
398
+ if (status === "failed") {
399
+ const msg = payload["StatusMessage"];
400
+ return textractExtractResultSchema.parse({
401
+ status: "failed",
402
+ job_id: jobId,
403
+ error: isString(msg) ? msg : "Textract job failed"
404
+ });
405
+ }
406
+ return textractExtractResultSchema.parse({
407
+ status: "pending",
408
+ job_id: jobId
409
+ });
410
+ }
411
+ async #writeExtractArtifact(key, text, filename) {
412
+ const bytes = utf8ToBytes(text);
413
+ await this.#storage.putBytes(key, bytes, "text/plain; charset=utf-8");
414
+ return {
415
+ store: "object",
416
+ key,
417
+ media_type: "text/plain",
418
+ byte_length: bytes.byteLength,
419
+ ...filename && { filename: filename.replace(/\.[^.]+$/, "") + ".txt" }
420
+ };
421
+ }
422
+ async #getJobPayload(jobId) {
423
+ const allBlocks = [];
424
+ let nextToken;
425
+ let jobStatus = "IN_PROGRESS";
426
+ let page_count;
427
+ do {
428
+ const body = {
429
+ JobId: jobId,
430
+ MaxResults: 1e3,
431
+ ...nextToken && { NextToken: nextToken }
432
+ };
433
+ const page = await this.#call("Textract.GetDocumentTextDetection", body);
434
+ const status = page["JobStatus"];
435
+ if (isString(status)) jobStatus = status;
436
+ const blocks = page["Blocks"];
437
+ if (isArray(blocks)) allBlocks.push(...blocks);
438
+ const meta = page["DocumentMetadata"];
439
+ if (isPlainObject(meta) && typeof meta["Pages"] === "number") page_count = meta["Pages"];
440
+ const token = page["NextToken"];
441
+ nextToken = isString(token) && token.length > 0 ? token : void 0;
442
+ if (jobStatus !== "SUCCEEDED" && jobStatus !== "PARTIAL_SUCCESS") nextToken = void 0;
443
+ } while (nextToken);
444
+ return {
445
+ JobStatus: jobStatus,
446
+ Blocks: allBlocks,
447
+ ...page_count !== void 0 && { DocumentMetadata: { Pages: page_count } }
448
+ };
449
+ }
450
+ async #call(target, body) {
451
+ const res = await this.#aws.post("/", JSON.stringify(body), {
452
+ headers: {
453
+ "Content-Type": "application/x-amz-json-1.1",
454
+ "X-Amz-Target": target
455
+ },
456
+ label: `Textract ${target}`,
457
+ noThrow: true
458
+ });
459
+ const payload = await parseAwsJsonBody(res.data);
460
+ if (!res.ok) throw new ToolError(formatTextractError(target, res.status, payload), {
461
+ code: res.status === 401 || res.status === 403 ? "bad_auth" : "upstream",
462
+ retryable: res.status >= 500 || res.status === 429,
463
+ details: {
464
+ status: res.status,
465
+ ...isPlainObject(payload) && isString(payload["__type"]) && { aws_type: payload["__type"] },
466
+ bucket: this.#auth.bucket,
467
+ region: this.#auth.region
468
+ }
469
+ });
470
+ if (!isPlainObject(payload)) throw new ToolError("Textract returned a non-object payload", { code: "upstream" });
471
+ return payload;
472
+ }
473
+ };
474
+ function presentOpts(output, destinationKey, chunk, sourceKey) {
475
+ const opts = {};
476
+ if (output !== void 0) opts.output = output;
477
+ if (destinationKey !== void 0) opts.destination_key = destinationKey;
478
+ if (chunk !== void 0) {
479
+ const c = {};
480
+ if (chunk.max_chars !== void 0) c.max_chars = chunk.max_chars;
481
+ if (chunk.overlap !== void 0) c.overlap = chunk.overlap;
482
+ opts.chunk = c;
483
+ }
484
+ if (sourceKey !== void 0) opts.source_key = sourceKey;
485
+ return opts;
486
+ }
487
+ function formatTextractError(target, status, payload) {
488
+ if (isPlainObject(payload)) {
489
+ const type = isString(payload["__type"]) ? payload["__type"].split("#").pop() : void 0;
490
+ const message = isString(payload["message"]) && payload["message"] || isString(payload["Message"]) && payload["Message"] || void 0;
491
+ if (type && message) return `Textract ${target}: ${type}: ${message}`;
492
+ if (message) return `Textract ${target}: ${message}`;
493
+ if (type) return `Textract ${target}: ${type} (HTTP ${status})`;
494
+ }
495
+ return `Textract ${target} failed with HTTP ${status}`;
496
+ }
497
+ //#endregion
498
+ //#region src/vendors/textract/module.ts
499
+ const textractExtractTextTool = defineTool({
500
+ id: "textract-extract-text",
501
+ name: "textractExtractText",
502
+ description: "Extract text from a document ArtifactRef in S3 via Amazon Textract. Polls until done or timeout. Optional output: inline (default; fails if over size limit), artifact (write text to S3), or chunks (split for RAG). If still running after the wait budget, returns status pending and a job_id for textract-get-status. Source store must be object.",
503
+ inputSchema: textractExtractTextInputSchema,
504
+ outputSchema: textractExtractResultSchema,
505
+ sideEffect: "read",
506
+ runtime: "both",
507
+ execute: async (input, ctx) => TextractClient.fromContext(ctx).extractText(input)
508
+ });
509
+ const textractGetStatusTool = defineTool({
510
+ id: "textract-get-status",
511
+ name: "textractGetStatus",
512
+ description: "Check a Textract text-detection job by job_id from textract-extract-text. Same optional output modes as extract (inline, artifact, chunks). Does not start a new job.",
513
+ inputSchema: textractStatusInputSchema,
514
+ outputSchema: textractExtractResultSchema,
515
+ sideEffect: "read",
516
+ runtime: "both",
517
+ execute: async (input, ctx) => TextractClient.fromContext(ctx).getStatus(input)
518
+ });
519
+ const textractExtractTextBatchTool = defineTool({
520
+ id: "textract-extract-text-batch",
521
+ name: "textractExtractTextBatch",
522
+ description: "Extract text from up to 10 document ArtifactRefs via Amazon Textract with optional output modes (inline, artifact, chunks). Returns per-item status without aborting the batch.",
523
+ inputSchema: textractExtractTextBatchInputSchema,
524
+ outputSchema: textractExtractTextBatchOutputSchema,
525
+ sideEffect: "read",
526
+ runtime: "both",
527
+ execute: async (input, ctx) => TextractClient.fromContext(ctx).extractTextBatch(input)
528
+ });
529
+ const textractModule = defineModule({
530
+ id: "textract",
531
+ title: "Amazon Textract",
532
+ description: "Amazon Textract vendor pack: async document text detection from S3 objects with inline, artifact, and chunks output modes (batch supported). Full Textract surface can grow over time.",
533
+ runtime: "both",
534
+ auth: {
535
+ type: "custom",
536
+ schema: textractAuthSchema
537
+ },
538
+ categories: [
539
+ "documents",
540
+ "ocr",
541
+ "aws"
542
+ ],
543
+ classification: "pii",
544
+ tags: ["textract"],
545
+ tools: [
546
+ textractExtractTextTool,
547
+ textractGetStatusTool,
548
+ textractExtractTextBatchTool
549
+ ]
550
+ });
551
+ //#endregion
552
+ export { textractTextChunkSchema as C, textractStatusInputSchema as S, textractExtractResultSchema as _, TextractClient as a, textractExtractTextInputSchema as b, DEFAULT_POLL_INTERVAL_MS as c, MAX_EXTRACT_CHUNK_MAX_CHARS as d, MAX_INLINE_EXTRACT_CHARS as f, textractChunkOptionsSchema as g, textractAuthSchema as h, textractModule as i, DEFAULT_POLL_TIMEOUT_MS as l, MAX_POLL_TIMEOUT_MS as m, textractExtractTextTool as n, DEFAULT_EXTRACT_CHUNK_MAX_CHARS as o, MAX_POLL_INTERVAL_MS as p, textractGetStatusTool as r, DEFAULT_EXTRACT_CHUNK_OVERLAP as s, textractExtractTextBatchTool as t, MAX_BATCH_EXTRACT as u, textractExtractTextBatchInputSchema as v, textractOutputModeSchema as x, textractExtractTextBatchOutputSchema as y };
553
+
554
+ //# sourceMappingURL=textract-CPLiB22H.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textract-CPLiB22H.js","names":["#auth","#aws","#storage","#signal","#keyPrefix","#extractRaw","#writeExtractArtifact","#statusRaw","#call","#getJobPayload"],"sources":["../src/vendors/textract/contracts.ts","../src/vendors/textract/domain.ts","../src/vendors/textract/client.ts","../src/vendors/textract/module.ts"],"sourcesContent":["import { z } from 'zod'\n\nimport { artifactRefSchema } from '../../shared/artifact'\nimport { batchResultSchema } from '../../shared/batch'\n\nexport const MAX_BATCH_EXTRACT = 10\nexport const DEFAULT_POLL_TIMEOUT_MS = 60_000\nexport const DEFAULT_POLL_INTERVAL_MS = 2_000\nexport const MAX_POLL_TIMEOUT_MS = 900_000\nexport const MAX_POLL_INTERVAL_MS = 30_000\n\n/** Hard cap for inline extract text returned to the model. */\nexport const MAX_INLINE_EXTRACT_CHARS = 100_000\nexport const DEFAULT_EXTRACT_CHUNK_MAX_CHARS = 1_200\nexport const DEFAULT_EXTRACT_CHUNK_OVERLAP = 200\nexport const MAX_EXTRACT_CHUNK_MAX_CHARS = 8_000\n\nexport const textractAuthSchema = z.object({\n\taccess_key_id: z.string().min(1).describe('AWS access key id'),\n\tsecret_access_key: z.string().min(1).describe('AWS secret access key'),\n\tregion: z.string().min(1).describe('AWS region for Textract and the source S3 bucket'),\n\tbucket: z.string().min(1).describe('AWS S3 bucket containing source documents'),\n\tsession_token: z.string().min(1).optional().describe('Optional session token'),\n\tkey_prefix: z\n\t\t.string()\n\t\t.min(1)\n\t\t.optional()\n\t\t.describe(\n\t\t\t'Optional object-key root matching the bound S3 storage (no leading slash). ArtifactRef.key is logical; DocumentLocation uses the wire key under this prefix.'\n\t\t),\n\tpoll_timeout_ms: z\n\t\t.int()\n\t\t.min(1_000)\n\t\t.max(MAX_POLL_TIMEOUT_MS)\n\t\t.optional()\n\t\t.describe('Max time to wait for Textract before returning pending plus job_id (default 60000)'),\n\tpoll_interval_ms: z\n\t\t.int()\n\t\t.min(200)\n\t\t.max(MAX_POLL_INTERVAL_MS)\n\t\t.optional()\n\t\t.describe('Delay between GetDocumentTextDetection polls (default 2000)')\n})\n\nexport type TextractAuth = z.infer<typeof textractAuthSchema>\n\nexport const textractOutputModeSchema = z\n\t.enum(['inline', 'artifact', 'chunks'])\n\t.describe(\n\t\t'How to return extracted text: inline (default, fails if over inline limit), artifact (write to object storage), chunks (split for RAG handoff)'\n\t)\n\nexport type TextractOutputMode = z.infer<typeof textractOutputModeSchema>\n\nexport const textractChunkOptionsSchema = z.object({\n\tmax_chars: z\n\t\t.int()\n\t\t.min(200)\n\t\t.max(MAX_EXTRACT_CHUNK_MAX_CHARS)\n\t\t.optional()\n\t\t.describe(`Chunk size in characters (default ${DEFAULT_EXTRACT_CHUNK_MAX_CHARS})`),\n\toverlap: z\n\t\t.int()\n\t\t.min(0)\n\t\t.max(2_000)\n\t\t.optional()\n\t\t.describe(`Overlap in characters between chunks (default ${DEFAULT_EXTRACT_CHUNK_OVERLAP})`)\n})\n\nexport const textractTextChunkSchema = z.object({\n\tid: z.string().describe('Stable chunk id (document-scoped)'),\n\tindex: z.number().int().nonnegative(),\n\ttext: z.string().describe('Chunk text')\n})\n\nexport type TextractTextChunk = z.infer<typeof textractTextChunkSchema>\n\nconst outputModeFields = {\n\toutput: textractOutputModeSchema.optional(),\n\tdestination_key: z\n\t\t.string()\n\t\t.min(1)\n\t\t.optional()\n\t\t.describe('Object key for artifact mode (logical under key_prefix when set). Default extracts/{job_id}.txt'),\n\tchunk: textractChunkOptionsSchema.optional().describe('Chunking options when output is chunks')\n}\n\nexport const textractExtractResultSchema = z.object({\n\tstatus: z.enum(['succeeded', 'pending', 'failed']).describe('Job status'),\n\tjob_id: z.string().optional().describe('Textract job id when started or polled'),\n\ttext: z.string().optional().describe('Extracted LINE text when succeeded and output is inline'),\n\tpage_count: z.int().optional().describe('Document page count when known'),\n\terror: z.string().optional().describe('Failure message when status is failed'),\n\tsource: artifactRefSchema.optional().describe('Source ArtifactRef when known'),\n\toutput: textractOutputModeSchema.optional().describe('Presentation mode used for this result'),\n\tartifact: artifactRefSchema\n\t\t.optional()\n\t\t.describe('Object-store ArtifactRef when output is artifact and status is succeeded'),\n\tchunks: z\n\t\t.array(textractTextChunkSchema)\n\t\t.optional()\n\t\t.describe('Text chunks when output is chunks and status is succeeded')\n})\n\nexport const textractExtractTextInputSchema = z.object({\n\tsource: artifactRefSchema.describe('Document ArtifactRef in object storage (store must be object)'),\n\t...outputModeFields\n})\n\nexport const textractExtractTextBatchInputSchema = z.object({\n\tsources: z\n\t\t.array(artifactRefSchema)\n\t\t.min(1)\n\t\t.max(MAX_BATCH_EXTRACT)\n\t\t.describe('Document ArtifactRefs to extract (max 10)'),\n\t...outputModeFields,\n\tdestination_key_prefix: z\n\t\t.string()\n\t\t.min(1)\n\t\t.optional()\n\t\t.describe('Prefix for per-item artifact keys in batch artifact mode (default extracts/)')\n})\n\nexport const textractStatusInputSchema = z.object({\n\tjob_id: z.string().min(1).describe('Job id from a prior extract call'),\n\t...outputModeFields\n})\n\nexport const textractExtractTextBatchOutputSchema = batchResultSchema(textractExtractResultSchema)\n\nexport type TextractExtractResult = z.infer<typeof textractExtractResultSchema>\nexport type TextractExtractTextInput = z.infer<typeof textractExtractTextInputSchema>\nexport type TextractExtractTextBatchInput = z.infer<typeof textractExtractTextBatchInputSchema>\nexport type TextractStatusInput = z.infer<typeof textractStatusInputSchema>\nexport type TextractExtractTextBatchOutput = z.infer<typeof textractExtractTextBatchOutputSchema>\n","/**\n * Textract payload helpers + extract presentation (no HTTP).\n * inline | artifact | chunks — product logic lives in the vendor, not the seam.\n */\n\nimport { isPlainObject, isString } from 'es-toolkit'\nimport { isArray } from 'es-toolkit/compat'\n\nimport { ToolError } from '../../core/errors'\nimport type { ArtifactRef } from '../../shared/artifact'\nimport { DEFAULT_EXTRACT_CHUNK_MAX_CHARS, DEFAULT_EXTRACT_CHUNK_OVERLAP, MAX_INLINE_EXTRACT_CHARS } from './contracts'\nimport type { TextractExtractResult, TextractOutputMode, TextractTextChunk } from './contracts'\n\nexport function lineTextFromBlocks(payload: Record<string, unknown>): {\n\ttext: string\n\tpage_count?: number\n} {\n\tconst blocks = payload['Blocks']\n\tconst lines: string[] = []\n\tif (isArray(blocks)) {\n\t\tfor (const block of blocks) {\n\t\t\tif (!isPlainObject(block)) continue\n\t\t\tif (block['BlockType'] !== 'LINE') continue\n\t\t\tconst t = block['Text']\n\t\t\tif (isString(t) && t.length > 0) lines.push(t)\n\t\t}\n\t}\n\tconst meta = payload['DocumentMetadata']\n\tlet page_count: number | undefined\n\tif (isPlainObject(meta) && typeof meta['Pages'] === 'number' && Number.isFinite(meta['Pages'])) {\n\t\tpage_count = meta['Pages']\n\t}\n\treturn {\n\t\ttext: lines.join('\\n'),\n\t\t...(page_count !== undefined && { page_count })\n\t}\n}\n\nexport function mapJobStatus(jobStatus: string): 'succeeded' | 'pending' | 'failed' {\n\tif (jobStatus === 'SUCCEEDED' || jobStatus === 'PARTIAL_SUCCESS') return 'succeeded'\n\tif (jobStatus === 'FAILED') return 'failed'\n\treturn 'pending'\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal?.aborted) {\n\t\t\treject(new DOMException('Aborted', 'AbortError'))\n\t\t\treturn\n\t\t}\n\t\tconst timer = setTimeout(() => {\n\t\t\tsignal?.removeEventListener('abort', onAbort)\n\t\t\tresolve()\n\t\t}, ms)\n\t\tconst onAbort = () => {\n\t\t\tclearTimeout(timer)\n\t\t\treject(new DOMException('Aborted', 'AbortError'))\n\t\t}\n\t\tsignal?.addEventListener('abort', onAbort, { once: true })\n\t})\n}\n\nexport type PresentOptions = {\n\toutput?: TextractOutputMode\n\tdestination_key?: string\n\tchunk?: { max_chars?: number; overlap?: number }\n\t/** Source key hint for default artifact destination. */\n\tsource_key?: string\n}\n\n/**\n * Apply output mode to a raw extract result.\n * - inline: fail with too_large when text exceeds MAX_INLINE_EXTRACT_CHARS\n * - artifact: caller must pass writeArtifact; text is stripped from the result\n * - chunks: split text for RAG handoff; full text stripped\n */\nexport async function presentExtractResult(\n\traw: TextractExtractResult,\n\toptions: PresentOptions,\n\twriteArtifact?: (key: string, text: string) => Promise<ArtifactRef>\n): Promise<TextractExtractResult> {\n\tconst mode: TextractOutputMode = options.output ?? 'inline'\n\n\tif (raw.status !== 'succeeded' || raw.text === undefined) {\n\t\treturn baseResult(raw, mode)\n\t}\n\n\tconst text = raw.text\n\n\tif (mode === 'inline') {\n\t\tif (text.length > MAX_INLINE_EXTRACT_CHARS) {\n\t\t\tthrow new ToolError(\n\t\t\t\t`Extracted text exceeds inline limit (${MAX_INLINE_EXTRACT_CHARS} characters); use output: \"artifact\" or \"chunks\"`,\n\t\t\t\t{\n\t\t\t\t\tcode: 'too_large',\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tmax_inline_chars: MAX_INLINE_EXTRACT_CHARS,\n\t\t\t\t\t\tchar_count: text.length,\n\t\t\t\t\t\tsuggested_output: 'artifact'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t)\n\t\t}\n\t\treturn baseResult(raw, 'inline')\n\t}\n\n\tif (mode === 'chunks') {\n\t\tconst maxChars = options.chunk?.max_chars ?? DEFAULT_EXTRACT_CHUNK_MAX_CHARS\n\t\tconst overlap = options.chunk?.overlap ?? DEFAULT_EXTRACT_CHUNK_OVERLAP\n\t\tconst pieces = chunkText(text, { max_chars: maxChars, overlap })\n\t\tconst docId = options.source_key ?? raw.job_id ?? 'extract'\n\t\tconst chunks: TextractTextChunk[] = pieces.map((piece, index) => ({\n\t\t\tid: chunkId(docId, index),\n\t\t\tindex,\n\t\t\ttext: piece\n\t\t}))\n\t\tconst out = baseResult(raw, 'chunks')\n\t\tdelete out.text\n\t\tout.chunks = chunks\n\t\treturn out\n\t}\n\n\t// artifact\n\tif (!writeArtifact) {\n\t\tthrow new ToolError('Artifact output requires object storage credentials on extract auth', {\n\t\t\tcode: 'bad_auth'\n\t\t})\n\t}\n\tconst key =\n\t\toptions.destination_key ?? `extracts/${raw.job_id ?? sanitizeKeySegment(options.source_key ?? 'document')}.txt`\n\tconst artifact = await writeArtifact(key, text)\n\tconst out = baseResult(raw, 'artifact')\n\tdelete out.text\n\tout.artifact = artifact\n\treturn out\n}\n\nfunction baseResult(raw: TextractExtractResult, mode: TextractOutputMode): TextractExtractResult {\n\tconst out: TextractExtractResult = {\n\t\tstatus: raw.status,\n\t\toutput: mode\n\t}\n\tif (raw.job_id !== undefined) out.job_id = raw.job_id\n\tif (raw.text !== undefined) out.text = raw.text\n\tif (raw.page_count !== undefined) out.page_count = raw.page_count\n\tif (raw.error !== undefined) out.error = raw.error\n\tif (raw.source !== undefined) out.source = raw.source\n\treturn out\n}\n\nfunction sanitizeKeySegment(value: string): string {\n\tconst base = value.replace(/^.*\\//, '').replace(/[^\\w.-]+/g, '_')\n\treturn base.length > 0 ? base.slice(0, 120) : 'document'\n}\n\nfunction chunkId(documentId: string, index: number): string {\n\treturn `${documentId}#${index}`\n}\n\n/** Overlapping character windows; prefers paragraph/newline soft breaks. */\nfunction chunkText(text: string, options: { max_chars: number; overlap: number }): string[] {\n\tconst maxChars = options.max_chars\n\tconst overlap = Math.min(options.overlap, Math.max(0, maxChars - 1))\n\tconst normalized = text.replace(/\\r\\n/g, '\\n').trim()\n\tif (normalized.length === 0) return []\n\tif (normalized.length <= maxChars) return [normalized]\n\n\tconst chunks: string[] = []\n\tlet start = 0\n\twhile (start < normalized.length) {\n\t\tlet end = Math.min(start + maxChars, normalized.length)\n\t\tif (end < normalized.length) {\n\t\t\tconst window = normalized.slice(start, end)\n\t\t\tconst para = window.lastIndexOf('\\n\\n')\n\t\t\tconst line = window.lastIndexOf('\\n')\n\t\t\tconst soft = para >= maxChars * 0.5 ? para : line >= maxChars * 0.5 ? line : -1\n\t\t\tif (soft > 0) {\n\t\t\t\tend = start + soft\n\t\t\t}\n\t\t}\n\t\tconst piece = normalized.slice(start, end).trim()\n\t\tif (piece.length > 0) chunks.push(piece)\n\t\tif (end >= normalized.length) break\n\t\tconst next = end - overlap\n\t\tstart = next <= start ? end : next\n\t}\n\treturn chunks\n}\n","/**\n * Amazon Textract vendor client (async text detection + presentation).\n * Host: `new TextractClient(auth)`. Agent tools: `fromContext(ctx)`.\n * Output modes (inline | artifact | chunks) live here — not in the seam module.\n */\n\nimport { isPlainObject, isString } from 'es-toolkit'\nimport { isArray } from 'es-toolkit/compat'\n\nimport { ToolError } from '../../core/errors'\nimport { requireAuth } from '../../core/provider'\nimport type { ToolContext } from '../../core/types'\nimport { runBatchItems } from '../../shared/batch'\nimport { utf8ToBytes } from '../../shared/bytes'\nimport { parseAwsJsonBody } from '../../transport/aws-json'\nimport { AwsService } from '../../transport/aws-service'\nimport type { HttpServiceOptions } from '../../transport/http-service'\nimport { normalizeKeyPrefix, resolveObjectKey } from '../_storage'\nimport { S3Client } from '../s3'\nimport type {\n\tTextractAuth,\n\tTextractExtractResult,\n\tTextractExtractTextBatchInput,\n\tTextractExtractTextBatchOutput,\n\tTextractExtractTextInput,\n\tTextractStatusInput\n} from './contracts'\nimport {\n\tDEFAULT_POLL_INTERVAL_MS,\n\tDEFAULT_POLL_TIMEOUT_MS,\n\ttextractAuthSchema,\n\ttextractExtractResultSchema\n} from './contracts'\nimport { lineTextFromBlocks, mapJobStatus, presentExtractResult, sleep } from './domain'\nimport type { PresentOptions } from './domain'\n\nexport type TextractClientOptions = Pick<HttpServiceOptions, 'fetch' | 'signal'>\n\nexport class TextractClient {\n\treadonly #auth: TextractAuth\n\treadonly #aws: AwsService\n\treadonly #storage: S3Client\n\treadonly #signal: AbortSignal | undefined\n\t/** Normalized key_prefix with trailing `/`, or undefined when unbound. */\n\treadonly #keyPrefix: string | undefined\n\n\tconstructor(auth: TextractAuth, options: TextractClientOptions = {}) {\n\t\tconst parsed = textractAuthSchema.safeParse(auth)\n\t\tif (!parsed.success) {\n\t\t\tthrow new ToolError('Invalid Textract auth credentials', {\n\t\t\t\tcode: 'bad_auth',\n\t\t\t\tdetails: { issues: parsed.error.issues.map((issue) => issue.message) }\n\t\t\t})\n\t\t}\n\t\tthis.#auth = parsed.data\n\t\tthis.#keyPrefix = parsed.data.key_prefix !== undefined ? normalizeKeyPrefix(parsed.data.key_prefix) : undefined\n\t\tthis.#signal = options.signal\n\t\tthis.#aws = new AwsService({\n\t\t\t...options,\n\t\t\taccessKeyId: this.#auth.access_key_id,\n\t\t\tsecretAccessKey: this.#auth.secret_access_key,\n\t\t\tregion: this.#auth.region,\n\t\t\tservice: 'textract',\n\t\t\tbaseURL: `https://textract.${this.#auth.region}.amazonaws.com`,\n\t\t\tlabel: 'Textract',\n\t\t\t...(this.#auth.session_token && { sessionToken: this.#auth.session_token })\n\t\t})\n\t\tthis.#storage = new S3Client(\n\t\t\t{\n\t\t\t\taccess_key_id: this.#auth.access_key_id,\n\t\t\t\tsecret_access_key: this.#auth.secret_access_key,\n\t\t\t\tregion: this.#auth.region,\n\t\t\t\tbucket: this.#auth.bucket,\n\t\t\t\t...(this.#auth.session_token && { session_token: this.#auth.session_token }),\n\t\t\t\t...(this.#auth.key_prefix && { key_prefix: this.#auth.key_prefix })\n\t\t\t},\n\t\t\toptions\n\t\t)\n\t}\n\n\tstatic fromContext(ctx: ToolContext): TextractClient {\n\t\tconst auth = requireAuth(ctx, textractAuthSchema)\n\t\treturn new TextractClient(auth, {\n\t\t\t...(ctx.fetch && { fetch: ctx.fetch }),\n\t\t\t...(ctx.signal && { signal: ctx.signal })\n\t\t})\n\t}\n\n\t/** StartDocumentTextDetection + poll until done, failed, or timeout → pending; then present. */\n\tasync extractText(input: TextractExtractTextInput): Promise<TextractExtractResult> {\n\t\tconst raw = await this.#extractRaw(input.source)\n\t\treturn presentExtractResult(\n\t\t\traw,\n\t\t\tpresentOpts(input.output, input.destination_key, input.chunk, input.source.key),\n\t\t\t(key, text) => this.#writeExtractArtifact(key, text, input.source.filename)\n\t\t)\n\t}\n\n\t/** GetDocumentTextDetection (paged) for an existing job; then present. */\n\tasync getStatus(input: TextractStatusInput): Promise<TextractExtractResult> {\n\t\tconst raw = await this.#statusRaw(input.job_id)\n\t\treturn presentExtractResult(\n\t\t\traw,\n\t\t\tpresentOpts(input.output, input.destination_key, input.chunk, raw.source?.key),\n\t\t\t(key, text) => this.#writeExtractArtifact(key, text, raw.source?.filename)\n\t\t)\n\t}\n\n\tasync extractTextBatch(input: TextractExtractTextBatchInput): Promise<TextractExtractTextBatchOutput> {\n\t\tconst prefix = input.destination_key_prefix ?? 'extracts/'\n\t\tconst rawBatch = await runBatchItems(input.sources, (source) => this.#extractRaw(source))\n\t\tconst results: TextractExtractTextBatchOutput['results'] = []\n\t\tlet succeeded = 0\n\t\tlet failed = 0\n\n\t\tfor (const row of rawBatch.results) {\n\t\t\tif (!row.ok || row.value === undefined) {\n\t\t\t\tresults.push(row)\n\t\t\t\tfailed += 1\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst source = input.sources[row.index]\n\t\t\tconst destKey =\n\t\t\t\tinput.destination_key ??\n\t\t\t\t`${prefix.replace(/\\/?$/, '/')}${source?.key.replace(/^.*\\//, '') || `item-${row.index}`}.txt`\n\t\t\ttry {\n\t\t\t\tconst presented = await presentExtractResult(\n\t\t\t\t\trow.value,\n\t\t\t\t\tpresentOpts(input.output, destKey, input.chunk, source?.key),\n\t\t\t\t\t(key, text) => this.#writeExtractArtifact(key, text, source?.filename)\n\t\t\t\t)\n\t\t\t\tresults.push({ index: row.index, ok: true, value: presented })\n\t\t\t\tsucceeded += 1\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof Error ? error.message : 'Presentation failed'\n\t\t\t\tconst code =\n\t\t\t\t\terror instanceof Error && 'code' in error && typeof error.code === 'string' ? error.code : 'internal'\n\t\t\t\tresults.push({\n\t\t\t\t\tindex: row.index,\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: { code, message }\n\t\t\t\t})\n\t\t\t\tfailed += 1\n\t\t\t}\n\t\t}\n\n\t\treturn { results, succeeded, failed }\n\t}\n\n\tasync #extractRaw(source: TextractExtractTextInput['source']): Promise<TextractExtractResult> {\n\t\tif (source.store !== 'object') {\n\t\t\tthrow new ToolError('Textract requires source.store \"object\"', { code: 'bad_input' })\n\t\t}\n\n\t\t// Logical ArtifactRef.key → wire S3 object name under optional key_prefix.\n\t\tconst wireName = resolveObjectKey(source.key, this.#keyPrefix)\n\n\t\tlet start: Record<string, unknown>\n\t\ttry {\n\t\t\tstart = await this.#call('Textract.StartDocumentTextDetection', {\n\t\t\t\tDocumentLocation: {\n\t\t\t\t\tS3Object: {\n\t\t\t\t\t\tBucket: this.#auth.bucket,\n\t\t\t\t\t\tName: wireName\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t} catch (error) {\n\t\t\tif (error instanceof ToolError) {\n\t\t\t\tthrow new ToolError(error.message, {\n\t\t\t\t\tcode: error.code,\n\t\t\t\t\tretryable: error.retryable,\n\t\t\t\t\tcause: error.cause,\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\t...(isPlainObject(error.details) ? error.details : {}),\n\t\t\t\t\t\t// Surface logical key to callers (not wire path).\n\t\t\t\t\t\tkey: source.key\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\n\t\tconst jobId = start['JobId']\n\t\tif (!isString(jobId) || jobId.length === 0) {\n\t\t\tthrow new ToolError('Textract did not return a JobId', { code: 'upstream' })\n\t\t}\n\n\t\tconst timeoutMs = this.#auth.poll_timeout_ms ?? DEFAULT_POLL_TIMEOUT_MS\n\t\tconst intervalMs = this.#auth.poll_interval_ms ?? DEFAULT_POLL_INTERVAL_MS\n\t\tconst deadline = Date.now() + timeoutMs\n\n\t\ttry {\n\t\t\twhile (Date.now() < deadline) {\n\t\t\t\tconst payload = await this.#getJobPayload(jobId)\n\t\t\t\tconst statusRaw = payload['JobStatus']\n\t\t\t\tconst status = isString(statusRaw) ? mapJobStatus(statusRaw) : 'pending'\n\n\t\t\t\tif (status === 'succeeded') {\n\t\t\t\t\tconst lines = lineTextFromBlocks(payload)\n\t\t\t\t\treturn textractExtractResultSchema.parse({\n\t\t\t\t\t\tstatus: 'succeeded',\n\t\t\t\t\t\tjob_id: jobId,\n\t\t\t\t\t\ttext: lines.text,\n\t\t\t\t\t\t...(lines.page_count !== undefined && { page_count: lines.page_count }),\n\t\t\t\t\t\tsource\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tif (status === 'failed') {\n\t\t\t\t\tconst msg = payload['StatusMessage']\n\t\t\t\t\treturn textractExtractResultSchema.parse({\n\t\t\t\t\t\tstatus: 'failed',\n\t\t\t\t\t\tjob_id: jobId,\n\t\t\t\t\t\terror: isString(msg) ? msg : 'Textract job failed',\n\t\t\t\t\t\tsource\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tconst remaining = deadline - Date.now()\n\t\t\t\tif (remaining <= 0) break\n\t\t\t\tawait sleep(Math.min(intervalMs, remaining), this.#signal)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (error instanceof ToolError) throw error\n\t\t\tif (error instanceof Error && error.name === 'AbortError') {\n\t\t\t\tthrow new ToolError('Textract extract was aborted', {\n\t\t\t\t\tcode: 'timeout',\n\t\t\t\t\tretryable: true,\n\t\t\t\t\tcause: error\n\t\t\t\t})\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\n\t\treturn textractExtractResultSchema.parse({\n\t\t\tstatus: 'pending',\n\t\t\tjob_id: jobId,\n\t\t\tsource\n\t\t})\n\t}\n\n\tasync #statusRaw(jobId: string): Promise<TextractExtractResult> {\n\t\tconst payload = await this.#getJobPayload(jobId)\n\t\tconst statusRaw = payload['JobStatus']\n\t\tconst status = isString(statusRaw) ? mapJobStatus(statusRaw) : 'pending'\n\n\t\tif (status === 'succeeded') {\n\t\t\tconst lines = lineTextFromBlocks(payload)\n\t\t\treturn textractExtractResultSchema.parse({\n\t\t\t\tstatus: 'succeeded',\n\t\t\t\tjob_id: jobId,\n\t\t\t\ttext: lines.text,\n\t\t\t\t...(lines.page_count !== undefined && { page_count: lines.page_count })\n\t\t\t})\n\t\t}\n\t\tif (status === 'failed') {\n\t\t\tconst msg = payload['StatusMessage']\n\t\t\treturn textractExtractResultSchema.parse({\n\t\t\t\tstatus: 'failed',\n\t\t\t\tjob_id: jobId,\n\t\t\t\terror: isString(msg) ? msg : 'Textract job failed'\n\t\t\t})\n\t\t}\n\t\treturn textractExtractResultSchema.parse({\n\t\t\tstatus: 'pending',\n\t\t\tjob_id: jobId\n\t\t})\n\t}\n\n\tasync #writeExtractArtifact(key: string, text: string, filename?: string) {\n\t\tconst bytes = utf8ToBytes(text)\n\t\tawait this.#storage.putBytes(key, bytes, 'text/plain; charset=utf-8')\n\t\treturn {\n\t\t\tstore: 'object' as const,\n\t\t\tkey,\n\t\t\tmedia_type: 'text/plain',\n\t\t\tbyte_length: bytes.byteLength,\n\t\t\t...(filename && { filename: filename.replace(/\\.[^.]+$/, '') + '.txt' })\n\t\t}\n\t}\n\n\tasync #getJobPayload(jobId: string): Promise<Record<string, unknown>> {\n\t\tconst allBlocks: unknown[] = []\n\t\tlet nextToken: string | undefined\n\t\tlet jobStatus = 'IN_PROGRESS'\n\t\tlet page_count: number | undefined\n\n\t\tdo {\n\t\t\tconst body: Record<string, unknown> = {\n\t\t\t\tJobId: jobId,\n\t\t\t\tMaxResults: 1000,\n\t\t\t\t...(nextToken && { NextToken: nextToken })\n\t\t\t}\n\t\t\tconst page = await this.#call('Textract.GetDocumentTextDetection', body)\n\t\t\tconst status = page['JobStatus']\n\t\t\tif (isString(status)) jobStatus = status\n\n\t\t\tconst blocks = page['Blocks']\n\t\t\tif (isArray(blocks)) allBlocks.push(...blocks)\n\n\t\t\tconst meta = page['DocumentMetadata']\n\t\t\tif (isPlainObject(meta) && typeof meta['Pages'] === 'number') {\n\t\t\t\tpage_count = meta['Pages']\n\t\t\t}\n\n\t\t\tconst token = page['NextToken']\n\t\t\tnextToken = isString(token) && token.length > 0 ? token : undefined\n\t\t\tif (jobStatus !== 'SUCCEEDED' && jobStatus !== 'PARTIAL_SUCCESS') {\n\t\t\t\tnextToken = undefined\n\t\t\t}\n\t\t} while (nextToken)\n\n\t\treturn {\n\t\t\tJobStatus: jobStatus,\n\t\t\tBlocks: allBlocks,\n\t\t\t...(page_count !== undefined && { DocumentMetadata: { Pages: page_count } })\n\t\t}\n\t}\n\n\tasync #call(target: string, body: Record<string, unknown>): Promise<Record<string, unknown>> {\n\t\tconst res = await this.#aws.post('/', JSON.stringify(body), {\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/x-amz-json-1.1',\n\t\t\t\t'X-Amz-Target': target\n\t\t\t},\n\t\t\tlabel: `Textract ${target}`,\n\t\t\t// Surface AWS __type / Message instead of a bare \"HTTP 400\"\n\t\t\tnoThrow: true\n\t\t})\n\t\t// ofetch does not JSON-parse application/x-amz-json-1.1 (returns Blob/string)\n\t\tconst payload = await parseAwsJsonBody(res.data)\n\t\tif (!res.ok) {\n\t\t\tthrow new ToolError(formatTextractError(target, res.status, payload), {\n\t\t\t\tcode: res.status === 401 || res.status === 403 ? 'bad_auth' : 'upstream',\n\t\t\t\tretryable: res.status >= 500 || res.status === 429,\n\t\t\t\tdetails: {\n\t\t\t\t\tstatus: res.status,\n\t\t\t\t\t...(isPlainObject(payload) && isString(payload['__type']) && { aws_type: payload['__type'] }),\n\t\t\t\t\tbucket: this.#auth.bucket,\n\t\t\t\t\tregion: this.#auth.region\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tif (!isPlainObject(payload)) {\n\t\t\tthrow new ToolError('Textract returned a non-object payload', { code: 'upstream' })\n\t\t}\n\t\treturn payload\n\t}\n}\n\nfunction presentOpts(\n\toutput: TextractExtractTextInput['output'],\n\tdestinationKey: string | undefined,\n\tchunk: TextractExtractTextInput['chunk'],\n\tsourceKey: string | undefined\n): PresentOptions {\n\tconst opts: PresentOptions = {}\n\tif (output !== undefined) opts.output = output\n\tif (destinationKey !== undefined) opts.destination_key = destinationKey\n\tif (chunk !== undefined) {\n\t\tconst c: NonNullable<PresentOptions['chunk']> = {}\n\t\tif (chunk.max_chars !== undefined) c.max_chars = chunk.max_chars\n\t\tif (chunk.overlap !== undefined) c.overlap = chunk.overlap\n\t\topts.chunk = c\n\t}\n\tif (sourceKey !== undefined) opts.source_key = sourceKey\n\treturn opts\n}\n\nfunction formatTextractError(target: string, status: number, payload: unknown): string {\n\tif (isPlainObject(payload)) {\n\t\tconst type = isString(payload['__type']) ? payload['__type'].split('#').pop() : undefined\n\t\tconst message =\n\t\t\t(isString(payload['message']) && payload['message']) ||\n\t\t\t(isString(payload['Message']) && payload['Message']) ||\n\t\t\tundefined\n\t\tif (type && message) return `Textract ${target}: ${type}: ${message}`\n\t\tif (message) return `Textract ${target}: ${message}`\n\t\tif (type) return `Textract ${target}: ${type} (HTTP ${status})`\n\t}\n\treturn `Textract ${target} failed with HTTP ${status}`\n}\n","import { defineModule, defineTool } from '../../core/define'\nimport { TextractClient } from './client'\nimport {\n\ttextractAuthSchema,\n\ttextractExtractResultSchema,\n\ttextractExtractTextBatchInputSchema,\n\ttextractExtractTextBatchOutputSchema,\n\ttextractExtractTextInputSchema,\n\ttextractStatusInputSchema\n} from './contracts'\n\nexport const textractExtractTextTool = defineTool({\n\tid: 'textract-extract-text',\n\tname: 'textractExtractText',\n\tdescription:\n\t\t'Extract text from a document ArtifactRef in S3 via Amazon Textract. Polls until done or timeout. Optional output: inline (default; fails if over size limit), artifact (write text to S3), or chunks (split for RAG). If still running after the wait budget, returns status pending and a job_id for textract-get-status. Source store must be object.',\n\tinputSchema: textractExtractTextInputSchema,\n\toutputSchema: textractExtractResultSchema,\n\tsideEffect: 'read',\n\truntime: 'both',\n\texecute: async (input, ctx) => TextractClient.fromContext(ctx).extractText(input)\n})\n\nexport const textractGetStatusTool = defineTool({\n\tid: 'textract-get-status',\n\tname: 'textractGetStatus',\n\tdescription:\n\t\t'Check a Textract text-detection job by job_id from textract-extract-text. Same optional output modes as extract (inline, artifact, chunks). Does not start a new job.',\n\tinputSchema: textractStatusInputSchema,\n\toutputSchema: textractExtractResultSchema,\n\tsideEffect: 'read',\n\truntime: 'both',\n\texecute: async (input, ctx) => TextractClient.fromContext(ctx).getStatus(input)\n})\n\nexport const textractExtractTextBatchTool = defineTool({\n\tid: 'textract-extract-text-batch',\n\tname: 'textractExtractTextBatch',\n\tdescription:\n\t\t'Extract text from up to 10 document ArtifactRefs via Amazon Textract with optional output modes (inline, artifact, chunks). Returns per-item status without aborting the batch.',\n\tinputSchema: textractExtractTextBatchInputSchema,\n\toutputSchema: textractExtractTextBatchOutputSchema,\n\tsideEffect: 'read',\n\truntime: 'both',\n\texecute: async (input, ctx) => TextractClient.fromContext(ctx).extractTextBatch(input)\n})\n\nexport const textractModule = defineModule({\n\tid: 'textract',\n\ttitle: 'Amazon Textract',\n\tdescription:\n\t\t'Amazon Textract vendor pack: async document text detection from S3 objects with inline, artifact, and chunks output modes (batch supported). Full Textract surface can grow over time.',\n\truntime: 'both',\n\tauth: { type: 'custom', schema: textractAuthSchema },\n\tcategories: ['documents', 'ocr', 'aws'],\n\tclassification: 'pii',\n\ttags: ['textract'],\n\ttools: [textractExtractTextTool, textractGetStatusTool, textractExtractTextBatchTool]\n})\n"],"mappings":"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"}