stackos-connectors 0.1.0__py3-none-any.whl

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 (388) hide show
  1. stackos_connectors/__init__.py +99 -0
  2. stackos_connectors/catalog/index.json +54 -0
  3. stackos_connectors/catalog/schema.json +80 -0
  4. stackos_connectors/catalog.py +160 -0
  5. stackos_connectors/connectors/__init__.py +1 -0
  6. stackos_connectors/connectors/ahrefs/__init__.py +1 -0
  7. stackos_connectors/connectors/ahrefs/actions.py +107 -0
  8. stackos_connectors/connectors/ahrefs/assets/icon.png +0 -0
  9. stackos_connectors/connectors/ahrefs/catalog.json +186 -0
  10. stackos_connectors/connectors/ahrefs/integration.py +184 -0
  11. stackos_connectors/connectors/aignc/__init__.py +1 -0
  12. stackos_connectors/connectors/aignc/actions.py +82 -0
  13. stackos_connectors/connectors/aignc/catalog.json +662 -0
  14. stackos_connectors/connectors/aignc/contract.py +31 -0
  15. stackos_connectors/connectors/aignc/docs/aignc.md +33 -0
  16. stackos_connectors/connectors/aignc/integration.py +572 -0
  17. stackos_connectors/connectors/alibaba_wan/__init__.py +1 -0
  18. stackos_connectors/connectors/alibaba_wan/actions.py +85 -0
  19. stackos_connectors/connectors/alibaba_wan/assets/icon.png +0 -0
  20. stackos_connectors/connectors/alibaba_wan/catalog.json +221 -0
  21. stackos_connectors/connectors/alibaba_wan/integration.py +392 -0
  22. stackos_connectors/connectors/apollo/__init__.py +1 -0
  23. stackos_connectors/connectors/apollo/actions.py +213 -0
  24. stackos_connectors/connectors/apollo/assets/icon.png +0 -0
  25. stackos_connectors/connectors/apollo/catalog.json +313 -0
  26. stackos_connectors/connectors/apollo/docs/protocol.md +19 -0
  27. stackos_connectors/connectors/aws_s3/__init__.py +1 -0
  28. stackos_connectors/connectors/aws_s3/actions.py +3082 -0
  29. stackos_connectors/connectors/aws_s3/assets/icon.png +0 -0
  30. stackos_connectors/connectors/aws_s3/catalog.json +1048 -0
  31. stackos_connectors/connectors/aws_s3/contract.py +89 -0
  32. stackos_connectors/connectors/aws_s3/docs/s3.md +49 -0
  33. stackos_connectors/connectors/aws_s3/integration.py +369 -0
  34. stackos_connectors/connectors/byteplus_seedance/__init__.py +1 -0
  35. stackos_connectors/connectors/byteplus_seedance/actions.py +85 -0
  36. stackos_connectors/connectors/byteplus_seedance/catalog.json +246 -0
  37. stackos_connectors/connectors/byteplus_seedream/__init__.py +1 -0
  38. stackos_connectors/connectors/byteplus_seedream/actions.py +88 -0
  39. stackos_connectors/connectors/byteplus_seedream/catalog.json +292 -0
  40. stackos_connectors/connectors/clay/__init__.py +1 -0
  41. stackos_connectors/connectors/clay/actions.py +100 -0
  42. stackos_connectors/connectors/clay/assets/icon.png +0 -0
  43. stackos_connectors/connectors/clay/catalog.json +139 -0
  44. stackos_connectors/connectors/clay/docs/protocol.md +16 -0
  45. stackos_connectors/connectors/cloudflare/__init__.py +1 -0
  46. stackos_connectors/connectors/cloudflare/actions.py +705 -0
  47. stackos_connectors/connectors/cloudflare/assets/icon.png +0 -0
  48. stackos_connectors/connectors/cloudflare/catalog.json +6381 -0
  49. stackos_connectors/connectors/cloudflare/docs/cloudflare-dns.md +37 -0
  50. stackos_connectors/connectors/cloudflare/integration.py +397 -0
  51. stackos_connectors/connectors/dataforseo/__init__.py +1 -0
  52. stackos_connectors/connectors/dataforseo/actions.py +147 -0
  53. stackos_connectors/connectors/dataforseo/assets/icon.jpeg +0 -0
  54. stackos_connectors/connectors/dataforseo/catalog.json +1275 -0
  55. stackos_connectors/connectors/dataforseo/integration.py +252 -0
  56. stackos_connectors/connectors/firecrawl/__init__.py +1 -0
  57. stackos_connectors/connectors/firecrawl/actions.py +100 -0
  58. stackos_connectors/connectors/firecrawl/assets/icon.png +0 -0
  59. stackos_connectors/connectors/firecrawl/catalog.json +189 -0
  60. stackos_connectors/connectors/firecrawl/integration.py +168 -0
  61. stackos_connectors/connectors/ftp/__init__.py +1 -0
  62. stackos_connectors/connectors/ftp/actions.py +1190 -0
  63. stackos_connectors/connectors/ftp/assets/icon.svg +7 -0
  64. stackos_connectors/connectors/ftp/catalog.json +1091 -0
  65. stackos_connectors/connectors/ftp/docs/ftp.md +40 -0
  66. stackos_connectors/connectors/ftp/integration.py +271 -0
  67. stackos_connectors/connectors/ftp/remote_tree.py +342 -0
  68. stackos_connectors/connectors/ghost/__init__.py +1 -0
  69. stackos_connectors/connectors/ghost/actions.py +80 -0
  70. stackos_connectors/connectors/ghost/assets/icon.png +0 -0
  71. stackos_connectors/connectors/ghost/catalog.json +214 -0
  72. stackos_connectors/connectors/ghost/integration.py +159 -0
  73. stackos_connectors/connectors/google_ads/__init__.py +1 -0
  74. stackos_connectors/connectors/google_ads/actions.py +279 -0
  75. stackos_connectors/connectors/google_ads/assets/icon.png +0 -0
  76. stackos_connectors/connectors/google_ads/catalog.json +797 -0
  77. stackos_connectors/connectors/google_ads/docs/protocol.md +22 -0
  78. stackos_connectors/connectors/google_analytics/__init__.py +1 -0
  79. stackos_connectors/connectors/google_analytics/actions.py +224 -0
  80. stackos_connectors/connectors/google_analytics/assets/icon.png +0 -0
  81. stackos_connectors/connectors/google_analytics/catalog.json +442 -0
  82. stackos_connectors/connectors/google_analytics/integration.py +112 -0
  83. stackos_connectors/connectors/google_gemini_image/__init__.py +1 -0
  84. stackos_connectors/connectors/google_gemini_image/actions.py +90 -0
  85. stackos_connectors/connectors/google_gemini_image/assets/icon.webp +0 -0
  86. stackos_connectors/connectors/google_gemini_image/catalog.json +275 -0
  87. stackos_connectors/connectors/google_gemini_image/integration.py +420 -0
  88. stackos_connectors/connectors/google_indexing/__init__.py +1 -0
  89. stackos_connectors/connectors/google_indexing/actions.py +148 -0
  90. stackos_connectors/connectors/google_indexing/catalog.json +224 -0
  91. stackos_connectors/connectors/google_indexing/docs/google-indexing.md +38 -0
  92. stackos_connectors/connectors/google_indexing/integration.py +261 -0
  93. stackos_connectors/connectors/google_search_console/__init__.py +1 -0
  94. stackos_connectors/connectors/google_search_console/actions.py +486 -0
  95. stackos_connectors/connectors/google_search_console/assets/icon.png +0 -0
  96. stackos_connectors/connectors/google_search_console/catalog.json +714 -0
  97. stackos_connectors/connectors/google_search_console/docs/google-search-console.md +37 -0
  98. stackos_connectors/connectors/google_search_console/integration.py +367 -0
  99. stackos_connectors/connectors/google_tag_manager/__init__.py +1 -0
  100. stackos_connectors/connectors/google_tag_manager/actions.py +241 -0
  101. stackos_connectors/connectors/google_tag_manager/assets/icon.png +0 -0
  102. stackos_connectors/connectors/google_tag_manager/catalog.json +477 -0
  103. stackos_connectors/connectors/google_tag_manager/integration.py +133 -0
  104. stackos_connectors/connectors/google_veo/__init__.py +1 -0
  105. stackos_connectors/connectors/google_veo/actions.py +85 -0
  106. stackos_connectors/connectors/google_veo/assets/icon.png +0 -0
  107. stackos_connectors/connectors/google_veo/catalog.json +211 -0
  108. stackos_connectors/connectors/google_veo/integration.py +337 -0
  109. stackos_connectors/connectors/google_workspace/__init__.py +1 -0
  110. stackos_connectors/connectors/google_workspace/actions.py +148 -0
  111. stackos_connectors/connectors/google_workspace/assets/icon.png +0 -0
  112. stackos_connectors/connectors/google_workspace/catalog.json +302 -0
  113. stackos_connectors/connectors/google_workspace/docs/protocol.md +19 -0
  114. stackos_connectors/connectors/http/__init__.py +1 -0
  115. stackos_connectors/connectors/http/actions.py +280 -0
  116. stackos_connectors/connectors/http/catalog.json +100 -0
  117. stackos_connectors/connectors/hubspot/__init__.py +1 -0
  118. stackos_connectors/connectors/hubspot/actions.py +144 -0
  119. stackos_connectors/connectors/hubspot/assets/icon.png +0 -0
  120. stackos_connectors/connectors/hubspot/catalog.json +4959 -0
  121. stackos_connectors/connectors/hubspot/contract.py +534 -0
  122. stackos_connectors/connectors/hubspot/docs/hubspot.md +41 -0
  123. stackos_connectors/connectors/hubspot/integration.py +209 -0
  124. stackos_connectors/connectors/ideogram/__init__.py +1 -0
  125. stackos_connectors/connectors/ideogram/actions.py +88 -0
  126. stackos_connectors/connectors/ideogram/assets/icon.png +0 -0
  127. stackos_connectors/connectors/ideogram/catalog.json +282 -0
  128. stackos_connectors/connectors/ideogram/integration.py +310 -0
  129. stackos_connectors/connectors/imap/__init__.py +1 -0
  130. stackos_connectors/connectors/imap/actions.py +1186 -0
  131. stackos_connectors/connectors/imap/assets/icon.svg +7 -0
  132. stackos_connectors/connectors/imap/catalog.json +520 -0
  133. stackos_connectors/connectors/imap/docs/protocol.md +19 -0
  134. stackos_connectors/connectors/imap/integration.py +300 -0
  135. stackos_connectors/connectors/jina/__init__.py +1 -0
  136. stackos_connectors/connectors/jina/actions.py +57 -0
  137. stackos_connectors/connectors/jina/assets/icon.png +0 -0
  138. stackos_connectors/connectors/jina/catalog.json +102 -0
  139. stackos_connectors/connectors/jina/integration.py +63 -0
  140. stackos_connectors/connectors/kling_video/__init__.py +1 -0
  141. stackos_connectors/connectors/kling_video/actions.py +86 -0
  142. stackos_connectors/connectors/kling_video/assets/icon.png +0 -0
  143. stackos_connectors/connectors/kling_video/catalog.json +232 -0
  144. stackos_connectors/connectors/kling_video/integration.py +413 -0
  145. stackos_connectors/connectors/linear/__init__.py +1 -0
  146. stackos_connectors/connectors/linear/actions.py +103 -0
  147. stackos_connectors/connectors/linear/assets/graphql/auth/viewer-organization.graphql +10 -0
  148. stackos_connectors/connectors/linear/assets/graphql/comments/create.graphql +25 -0
  149. stackos_connectors/connectors/linear/assets/graphql/comments/delete.graphql +6 -0
  150. stackos_connectors/connectors/linear/assets/graphql/comments/get.graphql +25 -0
  151. stackos_connectors/connectors/linear/assets/graphql/comments/list.graphql +45 -0
  152. stackos_connectors/connectors/linear/assets/graphql/comments/resolve.graphql +11 -0
  153. stackos_connectors/connectors/linear/assets/graphql/comments/unresolve.graphql +11 -0
  154. stackos_connectors/connectors/linear/assets/graphql/comments/update.graphql +14 -0
  155. stackos_connectors/connectors/linear/assets/graphql/cycles/get.graphql +17 -0
  156. stackos_connectors/connectors/linear/assets/graphql/cycles/list.graphql +37 -0
  157. stackos_connectors/connectors/linear/assets/graphql/issue-labels/get.graphql +15 -0
  158. stackos_connectors/connectors/linear/assets/graphql/issue-labels/list.graphql +35 -0
  159. stackos_connectors/connectors/linear/assets/graphql/issue-relations/create.graphql +21 -0
  160. stackos_connectors/connectors/linear/assets/graphql/issue-relations/delete.graphql +6 -0
  161. stackos_connectors/connectors/linear/assets/graphql/issue-relations/get.graphql +19 -0
  162. stackos_connectors/connectors/linear/assets/graphql/issue-relations/list.graphql +42 -0
  163. stackos_connectors/connectors/linear/assets/graphql/issue-relations/update.graphql +21 -0
  164. stackos_connectors/connectors/linear/assets/graphql/issues/add-label.graphql +17 -0
  165. stackos_connectors/connectors/linear/assets/graphql/issues/archive.graphql +11 -0
  166. stackos_connectors/connectors/linear/assets/graphql/issues/create.graphql +27 -0
  167. stackos_connectors/connectors/linear/assets/graphql/issues/get.graphql +51 -0
  168. stackos_connectors/connectors/linear/assets/graphql/issues/list.graphql +71 -0
  169. stackos_connectors/connectors/linear/assets/graphql/issues/remove-label.graphql +17 -0
  170. stackos_connectors/connectors/linear/assets/graphql/issues/search.graphql +62 -0
  171. stackos_connectors/connectors/linear/assets/graphql/issues/unarchive.graphql +11 -0
  172. stackos_connectors/connectors/linear/assets/graphql/issues/update.graphql +23 -0
  173. stackos_connectors/connectors/linear/assets/graphql/projects/get.graphql +18 -0
  174. stackos_connectors/connectors/linear/assets/graphql/projects/list.graphql +38 -0
  175. stackos_connectors/connectors/linear/assets/graphql/teams/get.graphql +12 -0
  176. stackos_connectors/connectors/linear/assets/graphql/teams/list.graphql +30 -0
  177. stackos_connectors/connectors/linear/assets/graphql/users/get.graphql +10 -0
  178. stackos_connectors/connectors/linear/assets/graphql/users/list.graphql +30 -0
  179. stackos_connectors/connectors/linear/assets/graphql/viewer/get.graphql +14 -0
  180. stackos_connectors/connectors/linear/assets/graphql/workflow-states/get.graphql +16 -0
  181. stackos_connectors/connectors/linear/assets/graphql/workflow-states/list.graphql +36 -0
  182. stackos_connectors/connectors/linear/assets/icon.png +0 -0
  183. stackos_connectors/connectors/linear/catalog.json +2794 -0
  184. stackos_connectors/connectors/linear/contract.py +101 -0
  185. stackos_connectors/connectors/linear/docs/linear.md +35 -0
  186. stackos_connectors/connectors/linear/integration.py +518 -0
  187. stackos_connectors/connectors/linear/schemas/introspection-2026-07-23.json +1 -0
  188. stackos_connectors/connectors/linear/schemas/introspection-2026-07-23.metadata.json +18 -0
  189. stackos_connectors/connectors/linear/schemas/root-policy-2026-07-23.json +552 -0
  190. stackos_connectors/connectors/meta_ads/__init__.py +1 -0
  191. stackos_connectors/connectors/meta_ads/actions.py +357 -0
  192. stackos_connectors/connectors/meta_ads/assets/icon.png +0 -0
  193. stackos_connectors/connectors/meta_ads/catalog.json +977 -0
  194. stackos_connectors/connectors/microsoft_365/__init__.py +1 -0
  195. stackos_connectors/connectors/microsoft_365/actions.py +121 -0
  196. stackos_connectors/connectors/microsoft_365/assets/icon.png +0 -0
  197. stackos_connectors/connectors/microsoft_365/catalog.json +261 -0
  198. stackos_connectors/connectors/microsoft_365/docs/protocol.md +17 -0
  199. stackos_connectors/connectors/openai_images/__init__.py +1 -0
  200. stackos_connectors/connectors/openai_images/actions.py +85 -0
  201. stackos_connectors/connectors/openai_images/assets/icon.webp +0 -0
  202. stackos_connectors/connectors/openai_images/catalog.json +282 -0
  203. stackos_connectors/connectors/openai_images/integration.py +327 -0
  204. stackos_connectors/connectors/openrouter/__init__.py +1 -0
  205. stackos_connectors/connectors/openrouter/assets/icon.png +0 -0
  206. stackos_connectors/connectors/openrouter/catalog.json +114 -0
  207. stackos_connectors/connectors/openrouter/integration.py +69 -0
  208. stackos_connectors/connectors/outreach/__init__.py +1 -0
  209. stackos_connectors/connectors/outreach/actions.py +107 -0
  210. stackos_connectors/connectors/outreach/assets/icon.png +0 -0
  211. stackos_connectors/connectors/outreach/catalog.json +197 -0
  212. stackos_connectors/connectors/outreach/docs/protocol.md +18 -0
  213. stackos_connectors/connectors/pipedrive/__init__.py +1 -0
  214. stackos_connectors/connectors/pipedrive/actions.py +173 -0
  215. stackos_connectors/connectors/pipedrive/assets/icon.png +0 -0
  216. stackos_connectors/connectors/pipedrive/catalog.json +449 -0
  217. stackos_connectors/connectors/pipedrive/docs/protocol.md +22 -0
  218. stackos_connectors/connectors/pipedrive/integration.py +160 -0
  219. stackos_connectors/connectors/reddit/__init__.py +1 -0
  220. stackos_connectors/connectors/reddit/actions.py +85 -0
  221. stackos_connectors/connectors/reddit/assets/icon.png +0 -0
  222. stackos_connectors/connectors/reddit/catalog.json +173 -0
  223. stackos_connectors/connectors/reddit/integration.py +117 -0
  224. stackos_connectors/connectors/reve/__init__.py +1 -0
  225. stackos_connectors/connectors/reve/actions.py +89 -0
  226. stackos_connectors/connectors/reve/assets/icon.png +0 -0
  227. stackos_connectors/connectors/reve/catalog.json +354 -0
  228. stackos_connectors/connectors/reve/integration.py +463 -0
  229. stackos_connectors/connectors/salesforce/__init__.py +1 -0
  230. stackos_connectors/connectors/salesforce/actions.py +173 -0
  231. stackos_connectors/connectors/salesforce/assets/icon.png +0 -0
  232. stackos_connectors/connectors/salesforce/catalog.json +490 -0
  233. stackos_connectors/connectors/salesforce/docs/protocol.md +17 -0
  234. stackos_connectors/connectors/salesloft/__init__.py +1 -0
  235. stackos_connectors/connectors/salesloft/actions.py +96 -0
  236. stackos_connectors/connectors/salesloft/assets/icon.jpeg +0 -0
  237. stackos_connectors/connectors/salesloft/catalog.json +239 -0
  238. stackos_connectors/connectors/salesloft/docs/protocol.md +17 -0
  239. stackos_connectors/connectors/salesloft/integration.py +119 -0
  240. stackos_connectors/connectors/serper/__init__.py +1 -0
  241. stackos_connectors/connectors/serper/actions.py +71 -0
  242. stackos_connectors/connectors/serper/assets/icon.svg +6 -0
  243. stackos_connectors/connectors/serper/catalog.json +124 -0
  244. stackos_connectors/connectors/serper/integration.py +83 -0
  245. stackos_connectors/connectors/shopify/__init__.py +1 -0
  246. stackos_connectors/connectors/shopify/actions.py +430 -0
  247. stackos_connectors/connectors/shopify/assets/graphql/customers/add-customer-tag.graphql +11 -0
  248. stackos_connectors/connectors/shopify/assets/graphql/customers/create-customer.graphql +24 -0
  249. stackos_connectors/connectors/shopify/assets/graphql/customers/get-customer-lifetime-value.graphql +30 -0
  250. stackos_connectors/connectors/shopify/assets/graphql/customers/get-customer-orders.graphql +27 -0
  251. stackos_connectors/connectors/shopify/assets/graphql/customers/get-customer.graphql +45 -0
  252. stackos_connectors/connectors/shopify/assets/graphql/customers/list-customers.graphql +29 -0
  253. stackos_connectors/connectors/shopify/assets/graphql/customers/remove-customer-tag.graphql +11 -0
  254. stackos_connectors/connectors/shopify/assets/graphql/customers/search-customers.graphql +29 -0
  255. stackos_connectors/connectors/shopify/assets/graphql/customers/update-customer.graphql +24 -0
  256. stackos_connectors/connectors/shopify/assets/graphql/inventory/adjust-inventory.graphql +25 -0
  257. stackos_connectors/connectors/shopify/assets/graphql/inventory/get-inventory-by-sku.graphql +28 -0
  258. stackos_connectors/connectors/shopify/assets/graphql/inventory/get-inventory-item.graphql +26 -0
  259. stackos_connectors/connectors/shopify/assets/graphql/inventory/get-location-inventory.graphql +26 -0
  260. stackos_connectors/connectors/shopify/assets/graphql/inventory/list-inventory-item-availability.graphql +40 -0
  261. stackos_connectors/connectors/shopify/assets/graphql/inventory/list-inventory-levels.graphql +30 -0
  262. stackos_connectors/connectors/shopify/assets/graphql/inventory/list-product-variant-inventory.graphql +20 -0
  263. stackos_connectors/connectors/shopify/assets/graphql/inventory/set-inventory-level.graphql +25 -0
  264. stackos_connectors/connectors/shopify/assets/graphql/orders/add-order-note.graphql +13 -0
  265. stackos_connectors/connectors/shopify/assets/graphql/orders/add-order-tag.graphql +11 -0
  266. stackos_connectors/connectors/shopify/assets/graphql/orders/create-draft-order.graphql +67 -0
  267. stackos_connectors/connectors/shopify/assets/graphql/orders/get-order-by-name.graphql +91 -0
  268. stackos_connectors/connectors/shopify/assets/graphql/orders/get-order-fulfillment-status.graphql +17 -0
  269. stackos_connectors/connectors/shopify/assets/graphql/orders/get-order-timeline.graphql +15 -0
  270. stackos_connectors/connectors/shopify/assets/graphql/orders/get-order.graphql +87 -0
  271. stackos_connectors/connectors/shopify/assets/graphql/orders/list-order-variant-quantities.graphql +18 -0
  272. stackos_connectors/connectors/shopify/assets/graphql/orders/list-orders.graphql +54 -0
  273. stackos_connectors/connectors/shopify/assets/graphql/orders/mark-order-paid.graphql +13 -0
  274. stackos_connectors/connectors/shopify/assets/graphql/orders/search-orders.graphql +54 -0
  275. stackos_connectors/connectors/shopify/assets/graphql/orders/update-order-note.graphql +13 -0
  276. stackos_connectors/connectors/shopify/assets/graphql/orders/update-order-tags.graphql +13 -0
  277. stackos_connectors/connectors/shopify/assets/graphql/products/create-collection.graphql +17 -0
  278. stackos_connectors/connectors/shopify/assets/graphql/products/create-product-variant.graphql +20 -0
  279. stackos_connectors/connectors/shopify/assets/graphql/products/create-product.graphql +29 -0
  280. stackos_connectors/connectors/shopify/assets/graphql/products/get-collection.graphql +41 -0
  281. stackos_connectors/connectors/shopify/assets/graphql/products/get-product-by-handle.graphql +61 -0
  282. stackos_connectors/connectors/shopify/assets/graphql/products/get-product-variant.graphql +31 -0
  283. stackos_connectors/connectors/shopify/assets/graphql/products/get-product.graphql +61 -0
  284. stackos_connectors/connectors/shopify/assets/graphql/products/list-collections.graphql +24 -0
  285. stackos_connectors/connectors/shopify/assets/graphql/products/list-product-variants.graphql +27 -0
  286. stackos_connectors/connectors/shopify/assets/graphql/products/list-products.graphql +38 -0
  287. stackos_connectors/connectors/shopify/assets/graphql/products/search-products.graphql +38 -0
  288. stackos_connectors/connectors/shopify/assets/graphql/products/update-product-status.graphql +14 -0
  289. stackos_connectors/connectors/shopify/assets/graphql/products/update-product-variant.graphql +20 -0
  290. stackos_connectors/connectors/shopify/assets/graphql/products/update-product.graphql +19 -0
  291. stackos_connectors/connectors/shopify/assets/graphql/shopifyql.graphql +13 -0
  292. stackos_connectors/connectors/shopify/assets/icon.png +0 -0
  293. stackos_connectors/connectors/shopify/catalog.json +3178 -0
  294. stackos_connectors/connectors/shopify/docs/shopify.md +51 -0
  295. stackos_connectors/connectors/shopify/integration.py +228 -0
  296. stackos_connectors/connectors/shopify/payloads.py +592 -0
  297. stackos_connectors/connectors/sitemap/__init__.py +1 -0
  298. stackos_connectors/connectors/sitemap/actions.py +88 -0
  299. stackos_connectors/connectors/sitemap/catalog.json +72 -0
  300. stackos_connectors/connectors/sitemap/integration.py +324 -0
  301. stackos_connectors/connectors/slack_bot/__init__.py +1 -0
  302. stackos_connectors/connectors/slack_bot/actions.py +47 -0
  303. stackos_connectors/connectors/slack_bot/assets/icon.png +0 -0
  304. stackos_connectors/connectors/slack_bot/catalog.json +557 -0
  305. stackos_connectors/connectors/slack_bot/constants.py +14 -0
  306. stackos_connectors/connectors/slack_bot/docs/protocol.md +20 -0
  307. stackos_connectors/connectors/slack_bot/files.py +111 -0
  308. stackos_connectors/connectors/slack_bot/http.py +163 -0
  309. stackos_connectors/connectors/slack_bot/integration.py +87 -0
  310. stackos_connectors/connectors/slack_bot/payloads.py +38 -0
  311. stackos_connectors/connectors/slack_bot/results.py +30 -0
  312. stackos_connectors/connectors/slack_bot/validation.py +145 -0
  313. stackos_connectors/connectors/smtp/__init__.py +1 -0
  314. stackos_connectors/connectors/smtp/actions.py +324 -0
  315. stackos_connectors/connectors/smtp/assets/icon.svg +7 -0
  316. stackos_connectors/connectors/smtp/catalog.json +238 -0
  317. stackos_connectors/connectors/smtp/docs/protocol.md +13 -0
  318. stackos_connectors/connectors/smtp/integration.py +104 -0
  319. stackos_connectors/connectors/stripe/__init__.py +1 -0
  320. stackos_connectors/connectors/stripe/actions.py +265 -0
  321. stackos_connectors/connectors/stripe/assets/icon.jpeg +0 -0
  322. stackos_connectors/connectors/stripe/catalog.json +2315 -0
  323. stackos_connectors/connectors/stripe/contract.py +92 -0
  324. stackos_connectors/connectors/stripe/docs/stripe.md +58 -0
  325. stackos_connectors/connectors/stripe/integration.py +668 -0
  326. stackos_connectors/connectors/taboola/__init__.py +1 -0
  327. stackos_connectors/connectors/taboola/actions.py +286 -0
  328. stackos_connectors/connectors/taboola/assets/icon.svg +18 -0
  329. stackos_connectors/connectors/taboola/catalog.json +593 -0
  330. stackos_connectors/connectors/telegram/__init__.py +1 -0
  331. stackos_connectors/connectors/telegram/actions.py +291 -0
  332. stackos_connectors/connectors/telegram/assets/icon.png +0 -0
  333. stackos_connectors/connectors/telegram/catalog.json +2121 -0
  334. stackos_connectors/connectors/telegram/docs/protocol.md +20 -0
  335. stackos_connectors/connectors/telegram/payloads.py +278 -0
  336. stackos_connectors/connectors/telegram/schema.py +35 -0
  337. stackos_connectors/connectors/telegram/tdlib/__init__.py +1 -0
  338. stackos_connectors/connectors/telegram/tdlib/native.py +513 -0
  339. stackos_connectors/connectors/telegram/tdlib/proxy.py +347 -0
  340. stackos_connectors/connectors/telegram/tdlib/sessions.py +256 -0
  341. stackos_connectors/connectors/trackbooth/__init__.py +5 -0
  342. stackos_connectors/connectors/trackbooth/actions.py +220 -0
  343. stackos_connectors/connectors/trackbooth/assets/agent-api/catalog.json +53858 -0
  344. stackos_connectors/connectors/trackbooth/assets/agent-api/openapi.json +25942 -0
  345. stackos_connectors/connectors/trackbooth/assets/agent-api/stackos-tools.json +17122 -0
  346. stackos_connectors/connectors/trackbooth/assets/icon.png +0 -0
  347. stackos_connectors/connectors/trackbooth/assets.py +279 -0
  348. stackos_connectors/connectors/trackbooth/catalog.json +168 -0
  349. stackos_connectors/connectors/trackbooth/contract.py +8 -0
  350. stackos_connectors/connectors/trackbooth/docs/agent-api/README.md +17 -0
  351. stackos_connectors/connectors/trackbooth/docs/trackbooth.md +33 -0
  352. stackos_connectors/connectors/trackbooth/integration.py +202 -0
  353. stackos_connectors/connectors/trackbooth/schema.py +78 -0
  354. stackos_connectors/connectors/trackbooth/transport.py +107 -0
  355. stackos_connectors/connectors/wordpress/__init__.py +1 -0
  356. stackos_connectors/connectors/wordpress/actions.py +69 -0
  357. stackos_connectors/connectors/wordpress/assets/icon.png +0 -0
  358. stackos_connectors/connectors/wordpress/catalog.json +183 -0
  359. stackos_connectors/connectors/wordpress/integration.py +121 -0
  360. stackos_connectors/connectors/xai_imagine/__init__.py +1 -0
  361. stackos_connectors/connectors/xai_imagine/actions.py +89 -0
  362. stackos_connectors/connectors/xai_imagine/assets/icon.png +0 -0
  363. stackos_connectors/connectors/xai_imagine/catalog.json +402 -0
  364. stackos_connectors/connectors/xai_imagine/integration.py +420 -0
  365. stackos_connectors/contracts.py +177 -0
  366. stackos_connectors/errors.py +63 -0
  367. stackos_connectors/probe.py +26 -0
  368. stackos_connectors/py.typed +0 -0
  369. stackos_connectors/redaction.py +140 -0
  370. stackos_connectors/registry.py +419 -0
  371. stackos_connectors/shared/__init__.py +1 -0
  372. stackos_connectors/shared/base.py +380 -0
  373. stackos_connectors/shared/byteplus/__init__.py +1 -0
  374. stackos_connectors/shared/byteplus/ark.py +794 -0
  375. stackos_connectors/shared/byteplus/media.py +178 -0
  376. stackos_connectors/shared/google/__init__.py +1 -0
  377. stackos_connectors/shared/google/batch.py +219 -0
  378. stackos_connectors/shared/google/oauth.py +51 -0
  379. stackos_connectors/shared/icons/integration.svg +8 -0
  380. stackos_connectors/shared/media.py +263 -0
  381. stackos_connectors/shared/provider_utils.py +350 -0
  382. stackos_connectors/shared/rate_limit.py +72 -0
  383. stackos_connectors/shared/vendor_utils.py +182 -0
  384. stackos_connectors/validation.py +25 -0
  385. stackos_connectors-0.1.0.dist-info/METADATA +160 -0
  386. stackos_connectors-0.1.0.dist-info/RECORD +388 -0
  387. stackos_connectors-0.1.0.dist-info/WHEEL +4 -0
  388. stackos_connectors-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,99 @@
1
+ """Execute a named connector action using plain data and resolved authentication."""
2
+
3
+ from collections.abc import Mapping
4
+ from functools import lru_cache
5
+ from typing import Any
6
+
7
+ from .contracts import (
8
+ ActionDefinition,
9
+ AuthMethodDefinition,
10
+ CallOptions,
11
+ Connector,
12
+ ConnectorAuth,
13
+ ConnectorFile,
14
+ ConnectorRequest,
15
+ ConnectorResult,
16
+ NativeSession,
17
+ RateLimiter,
18
+ ValidationIssue,
19
+ )
20
+ from .errors import ConnectorError, IntegrationDownError, RateLimitedError, ValidationError
21
+ from .registry import ConnectorClient, ConnectorRegistry
22
+
23
+
24
+ @lru_cache(maxsize=1)
25
+ def get_default_client() -> ConnectorClient:
26
+ """Load reviewed builtin descriptions on first use, without provider imports."""
27
+ from .catalog import default_registry
28
+
29
+ return ConnectorClient(registry=default_registry())
30
+
31
+
32
+ async def execute(
33
+ connector: str,
34
+ action: str,
35
+ data: Mapping[str, Any],
36
+ auth: ConnectorAuth | Mapping[str, Any] | None = None,
37
+ options: CallOptions | None = None,
38
+ ) -> ConnectorResult:
39
+ return await get_default_client().execute(connector, action, data, auth, options)
40
+
41
+
42
+ def validate(
43
+ connector: str,
44
+ action: str,
45
+ data: Mapping[str, Any],
46
+ auth: ConnectorAuth | Mapping[str, Any] | None = None,
47
+ options: CallOptions | None = None,
48
+ ) -> list[ValidationIssue]:
49
+ return get_default_client().validate(connector, action, data, auth, options)
50
+
51
+
52
+ def validate_data(connector: str, action: str, data: Mapping[str, Any]) -> list[ValidationIssue]:
53
+ return get_default_client().validate_data(connector, action, data)
54
+
55
+
56
+ def estimate_cost(
57
+ connector: str,
58
+ action: str,
59
+ data: Mapping[str, Any],
60
+ auth: ConnectorAuth | Mapping[str, Any] | None = None,
61
+ options: CallOptions | None = None,
62
+ ) -> int:
63
+ return get_default_client().estimate_cost(connector, action, data, auth, options)
64
+
65
+
66
+ def list_connectors() -> list[str]:
67
+ return get_default_client().list_connectors()
68
+
69
+
70
+ def describe(connector: str, action: str | None = None) -> dict[str, Any]:
71
+ return get_default_client().describe(connector, action)
72
+
73
+
74
+ __all__ = [
75
+ "ActionDefinition",
76
+ "AuthMethodDefinition",
77
+ "CallOptions",
78
+ "Connector",
79
+ "ConnectorAuth",
80
+ "ConnectorClient",
81
+ "ConnectorError",
82
+ "ConnectorFile",
83
+ "ConnectorRegistry",
84
+ "ConnectorRequest",
85
+ "ConnectorResult",
86
+ "IntegrationDownError",
87
+ "NativeSession",
88
+ "RateLimitedError",
89
+ "RateLimiter",
90
+ "ValidationError",
91
+ "ValidationIssue",
92
+ "describe",
93
+ "estimate_cost",
94
+ "execute",
95
+ "get_default_client",
96
+ "list_connectors",
97
+ "validate",
98
+ "validate_data",
99
+ ]
@@ -0,0 +1,54 @@
1
+ {
2
+ "schema_version": "stackos.connectors.index.v1",
3
+ "connectors": [
4
+ "connectors/ahrefs/catalog.json",
5
+ "connectors/aignc/catalog.json",
6
+ "connectors/alibaba_wan/catalog.json",
7
+ "connectors/apollo/catalog.json",
8
+ "connectors/aws_s3/catalog.json",
9
+ "connectors/byteplus_seedance/catalog.json",
10
+ "connectors/byteplus_seedream/catalog.json",
11
+ "connectors/clay/catalog.json",
12
+ "connectors/cloudflare/catalog.json",
13
+ "connectors/dataforseo/catalog.json",
14
+ "connectors/firecrawl/catalog.json",
15
+ "connectors/ftp/catalog.json",
16
+ "connectors/ghost/catalog.json",
17
+ "connectors/google_ads/catalog.json",
18
+ "connectors/google_analytics/catalog.json",
19
+ "connectors/google_gemini_image/catalog.json",
20
+ "connectors/google_indexing/catalog.json",
21
+ "connectors/google_search_console/catalog.json",
22
+ "connectors/google_tag_manager/catalog.json",
23
+ "connectors/google_veo/catalog.json",
24
+ "connectors/google_workspace/catalog.json",
25
+ "connectors/http/catalog.json",
26
+ "connectors/hubspot/catalog.json",
27
+ "connectors/ideogram/catalog.json",
28
+ "connectors/imap/catalog.json",
29
+ "connectors/jina/catalog.json",
30
+ "connectors/kling_video/catalog.json",
31
+ "connectors/linear/catalog.json",
32
+ "connectors/meta_ads/catalog.json",
33
+ "connectors/microsoft_365/catalog.json",
34
+ "connectors/openai_images/catalog.json",
35
+ "connectors/openrouter/catalog.json",
36
+ "connectors/outreach/catalog.json",
37
+ "connectors/pipedrive/catalog.json",
38
+ "connectors/reddit/catalog.json",
39
+ "connectors/reve/catalog.json",
40
+ "connectors/salesforce/catalog.json",
41
+ "connectors/salesloft/catalog.json",
42
+ "connectors/serper/catalog.json",
43
+ "connectors/shopify/catalog.json",
44
+ "connectors/sitemap/catalog.json",
45
+ "connectors/slack_bot/catalog.json",
46
+ "connectors/smtp/catalog.json",
47
+ "connectors/stripe/catalog.json",
48
+ "connectors/taboola/catalog.json",
49
+ "connectors/telegram/catalog.json",
50
+ "connectors/trackbooth/catalog.json",
51
+ "connectors/wordpress/catalog.json",
52
+ "connectors/xai_imagine/catalog.json"
53
+ ]
54
+ }
@@ -0,0 +1,80 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$defs": {
4
+ "icon": {
5
+ "type": "object",
6
+ "required": ["path", "media_type", "kind"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "path": {"type": "string", "pattern": "^(?:[A-Za-z0-9_][A-Za-z0-9_-]*/)*[A-Za-z0-9_][A-Za-z0-9_-]*\\.(?:svg|png|jpg|jpeg|webp)$", "not": {"pattern": "[\\r\\n]"}},
10
+ "media_type": {"enum": ["image/svg+xml", "image/png", "image/jpeg", "image/webp"]},
11
+ "kind": {"enum": ["icon", "wordmark", "wordmark-dark", "wordmark-inverse", "fallback"]}
12
+ },
13
+ "allOf": [
14
+ {"if": {"properties": {"path": {"pattern": "\\.svg$"}}}, "then": {"properties": {"media_type": {"const": "image/svg+xml"}}}},
15
+ {"if": {"properties": {"path": {"pattern": "\\.png$"}}}, "then": {"properties": {"media_type": {"const": "image/png"}}}},
16
+ {"if": {"properties": {"path": {"pattern": "\\.jpe?g$"}}}, "then": {"properties": {"media_type": {"const": "image/jpeg"}}}},
17
+ {"if": {"properties": {"path": {"pattern": "\\.webp$"}}}, "then": {"properties": {"media_type": {"const": "image/webp"}}}}
18
+ ]
19
+ },
20
+ "presentation_metadata": {
21
+ "type": "object",
22
+ "properties": {"icon": {"$ref": "#/$defs/icon"}}
23
+ },
24
+ "index": {
25
+ "type": "object",
26
+ "required": ["schema_version", "connectors"],
27
+ "additionalProperties": false,
28
+ "properties": {
29
+ "schema_version": {"const": "stackos.connectors.index.v1"},
30
+ "connectors": {"type": "array", "uniqueItems": true, "items": {"type": "string", "pattern": "^(?:[a-z0-9][a-z0-9_-]*/)*[a-z0-9][a-z0-9_-]*\\.json$"}}
31
+ }
32
+ },
33
+ "auth_method": {
34
+ "type": "object",
35
+ "required": ["key", "fields_schema"],
36
+ "properties": {
37
+ "key": {"type": "string", "minLength": 1},
38
+ "description": {"type": "string"},
39
+ "payload_format": {"enum": ["raw", "json", "none"]},
40
+ "payload_field": {"type": "string", "minLength": 1},
41
+ "fields_schema": {"type": "object"},
42
+ "config_schema": {"type": "object"}
43
+ }
44
+ },
45
+ "action": {
46
+ "type": "object",
47
+ "required": ["key", "operation", "input_schema", "auth_methods", "config"],
48
+ "properties": {
49
+ "key": {"type": "string", "minLength": 1},
50
+ "operation": {"type": "string", "minLength": 1},
51
+ "description": {"type": "string"},
52
+ "guidance": {"type": "string"},
53
+ "icon": {"$ref": "#/$defs/icon"},
54
+ "input_schema": {"type": "object"},
55
+ "output_schema": {"type": "object"},
56
+ "auth_methods": {"type": "array", "uniqueItems": true, "items": {"type": "string", "minLength": 1}},
57
+ "auth_optional": {"type": "boolean"},
58
+ "config": {"type": "object"},
59
+ "examples": {"type": "array", "items": {"type": "object"}},
60
+ "metadata": {"$ref": "#/$defs/presentation_metadata"}
61
+ }
62
+ },
63
+ "connector": {
64
+ "type": "object",
65
+ "required": ["schema_version", "connector", "name", "description", "auth_methods", "actions"],
66
+ "properties": {
67
+ "schema_version": {"const": "stackos.connector.v1"},
68
+ "connector": {"type": "string", "pattern": "^[a-z0-9][a-z0-9_-]*$"},
69
+ "name": {"type": "string", "minLength": 1},
70
+ "description": {"type": "string"},
71
+ "icon": {"$ref": "#/$defs/icon"},
72
+ "implementation": {"type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_.]*:[A-Za-z_][A-Za-z0-9_]*$"},
73
+ "auth_methods": {"type": "array", "items": {"$ref": "#/$defs/auth_method"}},
74
+ "actions": {"type": "array", "items": {"$ref": "#/$defs/action"}},
75
+ "metadata": {"$ref": "#/$defs/presentation_metadata"}
76
+ }
77
+ }
78
+ },
79
+ "$ref": "#/$defs/connector"
80
+ }
@@ -0,0 +1,160 @@
1
+ """Load portable connector descriptions and lazy bindings from packaged JSON.
2
+
3
+ Provider packages use ``load_registry("connectors/provider/catalog.json")``;
4
+ the default registry reads the reviewed resource list in ``catalog/index.json``.
5
+ Execution auth schemas describe resolved credentials, while setup metadata is
6
+ retained separately for discovery and never used as an execution schema.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ import re
13
+ from collections.abc import Iterable, Mapping
14
+ from importlib.resources import files
15
+ from importlib.resources.abc import Traversable
16
+ from typing import Any
17
+
18
+ from jsonschema import Draft202012Validator
19
+ from jsonschema.exceptions import SchemaError
20
+
21
+ from .contracts import ActionDefinition, AuthMethodDefinition, freeze, thaw
22
+ from .registry import ConnectorRegistry
23
+
24
+ _RESOURCE_PATH = re.compile(r"(?:[a-z0-9][a-z0-9_-]*/)*[a-z0-9][a-z0-9_-]*\.json\Z")
25
+ _ACTION_FIELDS = {
26
+ "key",
27
+ "operation",
28
+ "input_schema",
29
+ "output_schema",
30
+ "auth_methods",
31
+ "config",
32
+ "description",
33
+ "guidance",
34
+ "examples",
35
+ "metadata",
36
+ "auth_optional",
37
+ }
38
+
39
+
40
+ def _read(resource: Traversable) -> Any:
41
+ try:
42
+ return json.loads(resource.read_text(encoding="utf-8"))
43
+ except (OSError, ValueError) as exc:
44
+ raise ValueError(f"could not read connector catalog resource: {resource.name}") from exc
45
+
46
+
47
+ def _validate(document: Any, definition: str) -> None:
48
+ schema = _read(files("stackos_connectors").joinpath("catalog", "schema.json"))
49
+ validator = Draft202012Validator({"$ref": f"#/$defs/{definition}", "$defs": schema["$defs"]})
50
+ error = next(validator.iter_errors(document), None)
51
+ if error is not None:
52
+ path = ".".join(str(item) for item in error.absolute_path) or "$"
53
+ raise ValueError(f"invalid connector catalog {definition} at {path}")
54
+
55
+
56
+ def registry_from_documents(documents: Iterable[Mapping[str, Any]]) -> ConnectorRegistry:
57
+ """Build one immutable registry without importing any provider implementation."""
58
+ actions: list[ActionDefinition] = []
59
+ implementations: dict[str, str] = {}
60
+ metadata: dict[str, dict[str, Any]] = {}
61
+ for original in documents:
62
+ document = thaw(freeze(original))
63
+ _validate(document, "connector")
64
+ key = document["connector"]
65
+ if key in metadata:
66
+ raise ValueError(f"duplicate connector registration: {key}")
67
+ methods: dict[str, AuthMethodDefinition] = {}
68
+ for method in document["auth_methods"]:
69
+ if method["key"] in methods:
70
+ raise ValueError(f"duplicate auth method registration: {key}/{method['key']}")
71
+ methods[method["key"]] = AuthMethodDefinition(
72
+ key=method["key"],
73
+ fields_schema=method["fields_schema"],
74
+ config_schema=method.get("config_schema", {"type": "object"}),
75
+ description=method.get("description", ""),
76
+ )
77
+ try:
78
+ Draft202012Validator.check_schema(method["fields_schema"])
79
+ Draft202012Validator.check_schema(method.get("config_schema", {"type": "object"}))
80
+ except SchemaError as exc:
81
+ raise ValueError("invalid connector auth schema") from exc
82
+ metadata[key] = {
83
+ **document.get("metadata", {}),
84
+ **{
85
+ name: value
86
+ for name, value in document.items()
87
+ if name not in {"connector", "implementation", "actions", "metadata"}
88
+ },
89
+ }
90
+ if binding := document.get("implementation"):
91
+ implementations[key] = binding
92
+ for action in document["actions"]:
93
+ unknown = set(action["auth_methods"]) - methods.keys()
94
+ if unknown:
95
+ raise ValueError(f"action selects an unknown auth method: {key}/{action['key']}")
96
+ extra = {
97
+ **action.get("metadata", {}),
98
+ **{name: value for name, value in action.items() if name not in _ACTION_FIELDS},
99
+ }
100
+ actions.append(
101
+ ActionDefinition(
102
+ connector=key,
103
+ key=action["key"],
104
+ operation=action["operation"],
105
+ input_schema=action["input_schema"],
106
+ output_schema=action.get("output_schema", {}),
107
+ auth_methods=tuple(methods[name] for name in action["auth_methods"]),
108
+ config=action["config"],
109
+ description=action.get("description", ""),
110
+ guidance=action.get("guidance", ""),
111
+ examples=tuple(action.get("examples", [])),
112
+ metadata=extra,
113
+ auth_optional=action.get("auth_optional", False),
114
+ )
115
+ )
116
+ try:
117
+ return ConnectorRegistry(
118
+ actions=actions,
119
+ implementations=implementations,
120
+ connector_metadata=metadata,
121
+ )
122
+ except SchemaError as exc:
123
+ raise ValueError("invalid connector action schema") from exc
124
+
125
+
126
+ def load_registry(*resource_names: str, root: Traversable | None = None) -> ConnectorRegistry:
127
+ """Read explicit provider resources, or the index when none are named.
128
+
129
+ ``root`` is an explicit local resource root, useful for a consumer's declared
130
+ catalog and for deterministic tests. Resource names are package-relative JSON
131
+ paths; absolute paths, empty segments and traversal are rejected.
132
+ """
133
+ source = root if root is not None else files("stackos_connectors")
134
+ if not resource_names:
135
+ index = _read(source.joinpath("catalog", "index.json"))
136
+ _validate(index, "index")
137
+ resource_names = tuple(index["connectors"])
138
+ for name in resource_names:
139
+ if not _RESOURCE_PATH.fullmatch(name) or name.rsplit("/", 1)[-1] in {
140
+ "index.json",
141
+ "schema.json",
142
+ }:
143
+ raise ValueError("invalid connector catalog resource name")
144
+ if len(set(resource_names)) != len(resource_names):
145
+ raise ValueError("duplicate connector catalog resource name")
146
+ registry = registry_from_documents(
147
+ _read(source.joinpath(*name.split("/"))) for name in resource_names
148
+ )
149
+ presentations = [*registry.connector_metadata.values()]
150
+ presentations.extend(action.metadata for action in registry.actions.values())
151
+ for metadata in presentations:
152
+ if (icon := metadata.get("icon")) and not source.joinpath(
153
+ *icon["path"].split("/")
154
+ ).is_file():
155
+ raise ValueError(f"missing connector icon resource: {icon['path']}")
156
+ return registry
157
+
158
+
159
+ def default_registry() -> ConnectorRegistry:
160
+ return load_registry()
@@ -0,0 +1 @@
1
+ """connectors components."""
@@ -0,0 +1 @@
1
+ """connectors ahrefs components."""
@@ -0,0 +1,107 @@
1
+ """Named native Ahrefs API requests; admission decisions belong to the caller."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from contextlib import nullcontext
6
+
7
+ import httpx
8
+
9
+ from stackos_connectors.connectors.ahrefs.integration import AhrefsIntegration
10
+ from stackos_connectors.contracts import ConnectorRequest, ConnectorResult, ValidationIssue
11
+ from stackos_connectors.errors import ValidationError
12
+ from stackos_connectors.shared.provider_utils import credential_value
13
+ from stackos_connectors.shared.vendor_utils import (
14
+ issue,
15
+ optional_str,
16
+ required_str,
17
+ unknown_operation,
18
+ )
19
+
20
+ AHREFS_DEFAULT_ROWS = 100
21
+ AHREFS_MODE_VALUES = ("exact", "prefix", "domain", "subdomains")
22
+
23
+
24
+ def _positive_limit(payload, issues):
25
+ value = payload.get("limit")
26
+ if value is not None and (not isinstance(value, int) or isinstance(value, bool) or value < 1):
27
+ issues.append(issue("$.limit", "limit must be a positive integer", "range"))
28
+
29
+
30
+ class AhrefsActionConnector:
31
+ key = "ahrefs"
32
+
33
+ def validate(self, request: ConnectorRequest) -> list[ValidationIssue]:
34
+ payload = request.input_json
35
+ issues = []
36
+ match request.operation:
37
+ case "limits_and_usage":
38
+ pass
39
+ case "competitor.keywords" | "keywords_for_site":
40
+ required_str(payload, "target", issues)
41
+ optional_str(payload, "country", issues)
42
+ optional_str(payload, "date", issues)
43
+ _positive_limit(payload, issues)
44
+ case "backlink.research" | "top_backlinks":
45
+ required_str(payload, "target", issues)
46
+ optional_str(payload, "mode", issues)
47
+ if (
48
+ isinstance(payload.get("mode"), str)
49
+ and payload["mode"] not in AHREFS_MODE_VALUES
50
+ ):
51
+ issues.append(
52
+ issue(
53
+ "$.mode",
54
+ "mode must be one of exact, prefix, domain, subdomains",
55
+ "enum_mismatch",
56
+ )
57
+ )
58
+ _positive_limit(payload, issues)
59
+ case _:
60
+ issues.extend(unknown_operation(request))
61
+ return issues
62
+
63
+ def estimate_cost_cents(self, _request: ConnectorRequest) -> int:
64
+ return 0
65
+
66
+ async def execute(self, request: ConnectorRequest) -> ConnectorResult:
67
+ payload = request.input_json
68
+ async with (
69
+ nullcontext(request.options.http)
70
+ if request.options.http is not None
71
+ else httpx.AsyncClient(
72
+ timeout=request.options.timeout if request.options.timeout is not None else 60.0
73
+ )
74
+ ) as http:
75
+ client = AhrefsIntegration(
76
+ payload=credential_value(request, "api_key").encode(),
77
+ http=http,
78
+ rate_limiter=request.options.rate_limiter,
79
+ timeout=request.options.timeout,
80
+ )
81
+ match request.operation:
82
+ case "limits_and_usage":
83
+ result = await client.limits_and_usage()
84
+ case "competitor.keywords" | "keywords_for_site":
85
+ result = await client.keywords_for_site(
86
+ target=str(payload["target"]),
87
+ country=str(payload.get("country", "us")),
88
+ limit=int(payload.get("limit", AHREFS_DEFAULT_ROWS)),
89
+ date_=payload.get("date"),
90
+ )
91
+ case "backlink.research" | "top_backlinks":
92
+ result = await client.top_backlinks(
93
+ target=str(payload["target"]),
94
+ mode=str(payload.get("mode", "domain")),
95
+ limit=int(payload.get("limit", AHREFS_DEFAULT_ROWS)),
96
+ )
97
+ case _:
98
+ raise ValidationError(f"unsupported Ahrefs operation {request.operation!r}")
99
+ return ConnectorResult(
100
+ output_json=result.data if isinstance(result.data, dict) else {"data": result.data},
101
+ metadata_json={
102
+ "vendor": "ahrefs",
103
+ "operation": request.operation,
104
+ **(result.metadata or {}),
105
+ },
106
+ cost_cents=0,
107
+ )