@hasna/connectors 1.3.2 → 1.3.3

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 (843) hide show
  1. package/bin/index.js +2116 -248
  2. package/bin/mcp.js +1620 -172
  3. package/bin/serve.js +1230 -128
  4. package/connectors/connect-aiagenttool/src/api/client.ts +18 -205
  5. package/connectors/connect-aiagenttool/src/api/index.ts +32 -43
  6. package/connectors/connect-aiagenttool/src/types/index.ts +7 -233
  7. package/connectors/connect-airbrake/src/api/client.ts +25 -208
  8. package/connectors/connect-airbrake/src/api/index.ts +31 -44
  9. package/connectors/connect-airbrake/src/types/index.ts +10 -233
  10. package/connectors/connect-airnow/src/api/client.ts +16 -204
  11. package/connectors/connect-airnow/src/api/index.ts +32 -43
  12. package/connectors/connect-airnow/src/types/index.ts +5 -233
  13. package/connectors/connect-airtop/src/api/client.ts +18 -205
  14. package/connectors/connect-airtop/src/api/index.ts +35 -41
  15. package/connectors/connect-airtop/src/types/index.ts +9 -233
  16. package/connectors/connect-aitableai/src/api/client.ts +18 -205
  17. package/connectors/connect-aitableai/src/api/index.ts +35 -43
  18. package/connectors/connect-aitableai/src/types/index.ts +10 -233
  19. package/connectors/connect-alchemy/src/api/client.ts +33 -207
  20. package/connectors/connect-alchemy/src/api/index.ts +38 -44
  21. package/connectors/connect-alchemy/src/types/index.ts +13 -235
  22. package/connectors/connect-alerty/src/api/client.ts +18 -205
  23. package/connectors/connect-alerty/src/api/index.ts +29 -44
  24. package/connectors/connect-alerty/src/types/index.ts +9 -233
  25. package/connectors/connect-alienvault/src/api/client.ts +18 -205
  26. package/connectors/connect-alienvault/src/api/index.ts +34 -44
  27. package/connectors/connect-alienvault/src/types/index.ts +9 -233
  28. package/connectors/connect-alphamoon/src/api/client.ts +19 -206
  29. package/connectors/connect-alphamoon/src/api/index.ts +30 -42
  30. package/connectors/connect-alphamoon/src/types/index.ts +10 -233
  31. package/connectors/connect-alttextai/src/api/client.ts +18 -205
  32. package/connectors/connect-alttextai/src/api/index.ts +20 -43
  33. package/connectors/connect-alttextai/src/types/index.ts +7 -233
  34. package/connectors/connect-amadeus/src/api/client.ts +2 -2
  35. package/connectors/connect-amilia/src/api/client.ts +26 -211
  36. package/connectors/connect-amilia/src/api/index.ts +27 -44
  37. package/connectors/connect-amilia/src/types/index.ts +9 -233
  38. package/connectors/connect-amqpsender/src/api/client.ts +35 -212
  39. package/connectors/connect-amqpsender/src/api/index.ts +35 -42
  40. package/connectors/connect-amqpsender/src/types/index.ts +8 -233
  41. package/connectors/connect-announcekit/src/api/client.ts +19 -206
  42. package/connectors/connect-announcekit/src/api/index.ts +30 -43
  43. package/connectors/connect-announcekit/src/types/index.ts +8 -233
  44. package/connectors/connect-anthropic/src/api/messages.ts +2 -2
  45. package/connectors/connect-apiary/src/api/client.ts +19 -206
  46. package/connectors/connect-apiary/src/api/index.ts +23 -44
  47. package/connectors/connect-apiary/src/types/index.ts +9 -233
  48. package/connectors/connect-apiflash/src/api/client.ts +19 -204
  49. package/connectors/connect-apiflash/src/api/index.ts +48 -43
  50. package/connectors/connect-apiflash/src/types/index.ts +29 -235
  51. package/connectors/connect-apitemplateio/src/api/client.ts +18 -205
  52. package/connectors/connect-apitemplateio/src/api/index.ts +27 -43
  53. package/connectors/connect-apitemplateio/src/types/index.ts +8 -233
  54. package/connectors/connect-apptivegrid/src/api/client.ts +19 -205
  55. package/connectors/connect-apptivegrid/src/api/index.ts +32 -43
  56. package/connectors/connect-apptivegrid/src/types/index.ts +9 -233
  57. package/connectors/connect-auth0/src/api/client.ts +20 -206
  58. package/connectors/connect-auth0/src/api/index.ts +47 -45
  59. package/connectors/connect-auth0/src/types/index.ts +9 -233
  60. package/connectors/connect-autom/src/api/client.ts +18 -205
  61. package/connectors/connect-autom/src/api/index.ts +33 -43
  62. package/connectors/connect-autom/src/types/index.ts +8 -233
  63. package/connectors/connect-automizy/src/api/client.ts +19 -206
  64. package/connectors/connect-automizy/src/api/index.ts +37 -45
  65. package/connectors/connect-automizy/src/types/index.ts +10 -233
  66. package/connectors/connect-autopilot/src/api/client.ts +18 -205
  67. package/connectors/connect-autopilot/src/api/index.ts +34 -42
  68. package/connectors/connect-autopilot/src/types/index.ts +8 -233
  69. package/connectors/connect-azureaisearchvectorstore/src/api/client.ts +21 -204
  70. package/connectors/connect-azureaisearchvectorstore/src/api/index.ts +31 -41
  71. package/connectors/connect-azureaisearchvectorstore/src/types/index.ts +9 -233
  72. package/connectors/connect-azurecosmosdb/src/api/client.ts +32 -204
  73. package/connectors/connect-azurecosmosdb/src/api/index.ts +42 -43
  74. package/connectors/connect-azurecosmosdb/src/types/index.ts +9 -233
  75. package/connectors/connect-botstar/src/api/client.ts +19 -206
  76. package/connectors/connect-botstar/src/api/index.ts +36 -43
  77. package/connectors/connect-botstar/src/types/index.ts +9 -233
  78. package/connectors/connect-breezyhr/src/api/client.ts +19 -206
  79. package/connectors/connect-breezyhr/src/api/index.ts +40 -41
  80. package/connectors/connect-breezyhr/src/types/index.ts +9 -233
  81. package/connectors/connect-browseai/src/api/client.ts +18 -205
  82. package/connectors/connect-browseai/src/api/index.ts +22 -43
  83. package/connectors/connect-browseai/src/types/index.ts +6 -233
  84. package/connectors/connect-browserless/src/api/client.ts +20 -203
  85. package/connectors/connect-browserless/src/api/index.ts +32 -43
  86. package/connectors/connect-browserless/src/types/index.ts +8 -233
  87. package/connectors/connect-browserstack/src/api/client.ts +19 -206
  88. package/connectors/connect-browserstack/src/api/index.ts +28 -43
  89. package/connectors/connect-browserstack/src/types/index.ts +8 -233
  90. package/connectors/connect-bugbug/src/api/client.ts +18 -205
  91. package/connectors/connect-bugbug/src/api/index.ts +27 -42
  92. package/connectors/connect-bugbug/src/types/index.ts +9 -233
  93. package/connectors/connect-bugherd/src/api/client.ts +24 -211
  94. package/connectors/connect-bugherd/src/api/index.ts +33 -43
  95. package/connectors/connect-bugherd/src/types/index.ts +8 -233
  96. package/connectors/connect-bugreplay/src/api/client.ts +18 -205
  97. package/connectors/connect-bugreplay/src/api/index.ts +24 -43
  98. package/connectors/connect-bugreplay/src/types/index.ts +7 -233
  99. package/connectors/connect-buildkite/src/api/client.ts +19 -206
  100. package/connectors/connect-buildkite/src/api/index.ts +37 -43
  101. package/connectors/connect-buildkite/src/types/index.ts +8 -233
  102. package/connectors/connect-bunnycdn/src/api/client.ts +18 -207
  103. package/connectors/connect-bunnycdn/src/api/index.ts +29 -44
  104. package/connectors/connect-bunnycdn/src/types/index.ts +7 -233
  105. package/connectors/connect-carbonblack/src/api/client.ts +19 -205
  106. package/connectors/connect-carbonblack/src/api/index.ts +34 -43
  107. package/connectors/connect-carbonblack/src/types/index.ts +9 -233
  108. package/connectors/connect-chargify/src/api/client.ts +21 -204
  109. package/connectors/connect-chargify/src/api/index.ts +49 -42
  110. package/connectors/connect-chargify/src/types/index.ts +8 -233
  111. package/connectors/connect-chatling/src/api/client.ts +18 -205
  112. package/connectors/connect-chatling/src/api/index.ts +35 -42
  113. package/connectors/connect-chatling/src/types/index.ts +8 -233
  114. package/connectors/connect-chekhub/src/api/client.ts +19 -206
  115. package/connectors/connect-chekhub/src/api/index.ts +33 -44
  116. package/connectors/connect-chekhub/src/types/index.ts +9 -233
  117. package/connectors/connect-chromavectorstore/src/api/client.ts +28 -206
  118. package/connectors/connect-chromavectorstore/src/api/index.ts +41 -44
  119. package/connectors/connect-chromavectorstore/src/types/index.ts +7 -233
  120. package/connectors/connect-ciscoumbrella/src/api/client.ts +24 -207
  121. package/connectors/connect-ciscoumbrella/src/api/index.ts +33 -43
  122. package/connectors/connect-ciscoumbrella/src/types/index.ts +8 -233
  123. package/connectors/connect-clicksendsms/src/api/client.ts +19 -206
  124. package/connectors/connect-clicksendsms/src/api/index.ts +32 -43
  125. package/connectors/connect-clicksendsms/src/types/index.ts +9 -233
  126. package/connectors/connect-cloudboost/src/api/client.ts +23 -208
  127. package/connectors/connect-cloudboost/src/api/index.ts +36 -43
  128. package/connectors/connect-cloudboost/src/types/index.ts +9 -233
  129. package/connectors/connect-cloudlayer/src/api/client.ts +20 -209
  130. package/connectors/connect-cloudlayer/src/api/index.ts +25 -42
  131. package/connectors/connect-cloudlayer/src/types/index.ts +8 -233
  132. package/connectors/connect-cody/src/api/client.ts +19 -205
  133. package/connectors/connect-cody/src/api/index.ts +23 -42
  134. package/connectors/connect-cody/src/types/index.ts +6 -233
  135. package/connectors/connect-confluent/src/api/client.ts +21 -205
  136. package/connectors/connect-confluent/src/api/index.ts +36 -43
  137. package/connectors/connect-confluent/src/types/index.ts +9 -233
  138. package/connectors/connect-convertapi/src/api/client.ts +17 -205
  139. package/connectors/connect-convertapi/src/api/index.ts +20 -44
  140. package/connectors/connect-convertapi/src/types/index.ts +7 -233
  141. package/connectors/connect-copper/src/api/client.ts +20 -205
  142. package/connectors/connect-copper/src/api/index.ts +38 -42
  143. package/connectors/connect-copper/src/types/index.ts +8 -233
  144. package/connectors/connect-cortex/src/api/client.ts +19 -206
  145. package/connectors/connect-cortex/src/api/index.ts +33 -43
  146. package/connectors/connect-cortex/src/types/index.ts +10 -233
  147. package/connectors/connect-craftdraft/src/api/client.ts +18 -205
  148. package/connectors/connect-craftdraft/src/api/index.ts +27 -43
  149. package/connectors/connect-craftdraft/src/types/index.ts +7 -233
  150. package/connectors/connect-crisp/src/api/client.ts +24 -207
  151. package/connectors/connect-crisp/src/api/index.ts +34 -42
  152. package/connectors/connect-crisp/src/types/index.ts +7 -233
  153. package/connectors/connect-crossmint/src/api/client.ts +20 -208
  154. package/connectors/connect-crossmint/src/api/index.ts +29 -43
  155. package/connectors/connect-crossmint/src/types/index.ts +7 -233
  156. package/connectors/connect-crowddev/src/api/client.ts +18 -204
  157. package/connectors/connect-crowddev/src/api/index.ts +23 -43
  158. package/connectors/connect-crowddev/src/types/index.ts +8 -233
  159. package/connectors/connect-crowdpower/src/api/client.ts +18 -205
  160. package/connectors/connect-crowdpower/src/api/index.ts +28 -44
  161. package/connectors/connect-crowdpower/src/types/index.ts +9 -233
  162. package/connectors/connect-cryptolens/src/api/client.ts +20 -211
  163. package/connectors/connect-cryptolens/src/api/index.ts +34 -44
  164. package/connectors/connect-cryptolens/src/types/index.ts +7 -233
  165. package/connectors/connect-customerio/src/api/client.ts +37 -211
  166. package/connectors/connect-customerio/src/api/index.ts +34 -44
  167. package/connectors/connect-customerio/src/types/index.ts +9 -233
  168. package/connectors/connect-daffy/src/api/client.ts +18 -205
  169. package/connectors/connect-daffy/src/api/index.ts +25 -42
  170. package/connectors/connect-daffy/src/types/index.ts +8 -233
  171. package/connectors/connect-datasoap/src/api/client.ts +18 -205
  172. package/connectors/connect-datasoap/src/api/index.ts +28 -42
  173. package/connectors/connect-datasoap/src/types/index.ts +8 -233
  174. package/connectors/connect-dayschedule/src/api/client.ts +18 -205
  175. package/connectors/connect-dayschedule/src/api/index.ts +25 -43
  176. package/connectors/connect-dayschedule/src/types/index.ts +8 -233
  177. package/connectors/connect-deepl/src/api/client.ts +46 -185
  178. package/connectors/connect-deepl/src/api/index.ts +18 -40
  179. package/connectors/connect-deepl/src/api/translate.ts +98 -0
  180. package/connectors/connect-deepl/src/types/index.ts +33 -217
  181. package/connectors/connect-demio/src/api/client.ts +19 -204
  182. package/connectors/connect-demio/src/api/index.ts +29 -42
  183. package/connectors/connect-demio/src/types/index.ts +7 -233
  184. package/connectors/connect-dhl/src/api/client.ts +22 -201
  185. package/connectors/connect-dhl/src/api/index.ts +23 -42
  186. package/connectors/connect-dhl/src/types/index.ts +10 -233
  187. package/connectors/connect-docsbotai/src/api/client.ts +21 -206
  188. package/connectors/connect-docsbotai/src/api/index.ts +55 -39
  189. package/connectors/connect-docsbotai/src/types/index.ts +7 -233
  190. package/connectors/connect-drift/src/api/client.ts +19 -203
  191. package/connectors/connect-drift/src/api/index.ts +41 -42
  192. package/connectors/connect-drift/src/types/index.ts +7 -233
  193. package/connectors/connect-dropcontact/src/api/client.ts +21 -209
  194. package/connectors/connect-dropcontact/src/api/index.ts +23 -42
  195. package/connectors/connect-dropcontact/src/types/index.ts +8 -233
  196. package/connectors/connect-eartho/src/api/client.ts +21 -206
  197. package/connectors/connect-eartho/src/api/index.ts +24 -44
  198. package/connectors/connect-eartho/src/types/index.ts +6 -233
  199. package/connectors/connect-echowin/src/api/client.ts +18 -205
  200. package/connectors/connect-echowin/src/api/index.ts +29 -43
  201. package/connectors/connect-echowin/src/types/index.ts +8 -233
  202. package/connectors/connect-ecwid/src/api/client.ts +20 -205
  203. package/connectors/connect-ecwid/src/api/index.ts +36 -42
  204. package/connectors/connect-ecwid/src/types/index.ts +9 -233
  205. package/connectors/connect-elasticsearch/src/api/client.ts +29 -204
  206. package/connectors/connect-elasticsearch/src/api/index.ts +40 -41
  207. package/connectors/connect-elasticsearch/src/types/index.ts +9 -233
  208. package/connectors/connect-emelia/src/api/client.ts +23 -199
  209. package/connectors/connect-emelia/src/api/index.ts +60 -41
  210. package/connectors/connect-emelia/src/types/index.ts +24 -220
  211. package/connectors/connect-engati/src/api/client.ts +20 -205
  212. package/connectors/connect-engati/src/api/index.ts +31 -42
  213. package/connectors/connect-engati/src/types/index.ts +9 -233
  214. package/connectors/connect-erpnext/src/api/client.ts +21 -204
  215. package/connectors/connect-erpnext/src/api/index.ts +34 -43
  216. package/connectors/connect-erpnext/src/types/index.ts +6 -233
  217. package/connectors/connect-evervault/src/api/client.ts +22 -211
  218. package/connectors/connect-evervault/src/api/index.ts +28 -42
  219. package/connectors/connect-evervault/src/types/index.ts +9 -233
  220. package/connectors/connect-faros/src/api/client.ts +18 -204
  221. package/connectors/connect-faros/src/api/index.ts +31 -43
  222. package/connectors/connect-faros/src/types/index.ts +9 -233
  223. package/connectors/connect-fastbots/src/api/client.ts +18 -205
  224. package/connectors/connect-fastbots/src/api/index.ts +31 -42
  225. package/connectors/connect-fastbots/src/types/index.ts +8 -233
  226. package/connectors/connect-flagship/src/api/client.ts +24 -209
  227. package/connectors/connect-flagship/src/api/index.ts +24 -42
  228. package/connectors/connect-flagship/src/types/index.ts +7 -233
  229. package/connectors/connect-float/src/api/client.ts +19 -206
  230. package/connectors/connect-float/src/api/index.ts +38 -42
  231. package/connectors/connect-float/src/types/index.ts +9 -233
  232. package/connectors/connect-flotiq/src/api/client.ts +18 -205
  233. package/connectors/connect-flotiq/src/api/index.ts +38 -42
  234. package/connectors/connect-flotiq/src/types/index.ts +9 -233
  235. package/connectors/connect-formcarry/src/api/client.ts +20 -210
  236. package/connectors/connect-formcarry/src/api/index.ts +25 -46
  237. package/connectors/connect-formcarry/src/types/index.ts +5 -235
  238. package/connectors/connect-formdesk/src/api/client.ts +19 -204
  239. package/connectors/connect-formdesk/src/api/index.ts +23 -44
  240. package/connectors/connect-formdesk/src/types/index.ts +7 -233
  241. package/connectors/connect-formsonfire/src/api/client.ts +18 -205
  242. package/connectors/connect-formsonfire/src/api/index.ts +21 -44
  243. package/connectors/connect-formsonfire/src/types/index.ts +8 -233
  244. package/connectors/connect-fortinetfortigate/src/api/client.ts +19 -205
  245. package/connectors/connect-fortinetfortigate/src/api/index.ts +33 -43
  246. package/connectors/connect-fortinetfortigate/src/types/index.ts +8 -233
  247. package/connectors/connect-freedictionary/src/api/client.ts +11 -205
  248. package/connectors/connect-freedictionary/src/api/index.ts +29 -42
  249. package/connectors/connect-freedictionary/src/types/index.ts +5 -233
  250. package/connectors/connect-freshworkscrm/src/api/client.ts +18 -204
  251. package/connectors/connect-freshworkscrm/src/api/index.ts +41 -41
  252. package/connectors/connect-freshworkscrm/src/types/index.ts +8 -233
  253. package/connectors/connect-fusioo/src/api/client.ts +19 -206
  254. package/connectors/connect-fusioo/src/api/index.ts +29 -43
  255. package/connectors/connect-fusioo/src/types/index.ts +8 -233
  256. package/connectors/connect-genderapi/src/api/client.ts +14 -205
  257. package/connectors/connect-genderapi/src/api/index.ts +23 -42
  258. package/connectors/connect-genderapi/src/types/index.ts +5 -233
  259. package/connectors/connect-ghost/src/api/client.ts +45 -211
  260. package/connectors/connect-ghost/src/api/index.ts +38 -43
  261. package/connectors/connect-ghost/src/types/index.ts +9 -233
  262. package/connectors/connect-gitea/src/api/client.ts +19 -205
  263. package/connectors/connect-gitea/src/api/index.ts +39 -43
  264. package/connectors/connect-gitea/src/types/index.ts +9 -233
  265. package/connectors/connect-github/src/api/client.ts +11 -0
  266. package/connectors/connect-github/src/api/commits.ts +169 -0
  267. package/connectors/connect-github/src/api/index.ts +12 -0
  268. package/connectors/connect-github/src/api/releases.ts +158 -0
  269. package/connectors/connect-github/src/api/workflows.ts +169 -0
  270. package/connectors/connect-github/src/types/index.ts +190 -0
  271. package/connectors/connect-gmail/src/cli/index.ts +3 -32
  272. package/connectors/connect-googleads/src/api/adGroups.ts +3 -3
  273. package/connectors/connect-googleads/src/api/ads.ts +3 -3
  274. package/connectors/connect-googleads/src/api/campaigns.ts +4 -4
  275. package/connectors/connect-googleads/src/api/client.ts +1 -1
  276. package/connectors/connect-googleads/src/api/keywords.ts +6 -6
  277. package/connectors/connect-googlebigquery/src/api/client.ts +24 -204
  278. package/connectors/connect-googlebigquery/src/api/index.ts +39 -42
  279. package/connectors/connect-googlebigquery/src/types/index.ts +8 -233
  280. package/connectors/connect-googletranslate/src/api/client.ts +20 -204
  281. package/connectors/connect-googletranslate/src/api/index.ts +22 -43
  282. package/connectors/connect-googletranslate/src/types/index.ts +9 -233
  283. package/connectors/connect-gotowebinar/src/api/client.ts +24 -207
  284. package/connectors/connect-gotowebinar/src/api/index.ts +36 -43
  285. package/connectors/connect-gotowebinar/src/types/index.ts +7 -233
  286. package/connectors/connect-gptea/src/api/client.ts +20 -209
  287. package/connectors/connect-gptea/src/api/index.ts +23 -42
  288. package/connectors/connect-gptea/src/types/index.ts +6 -233
  289. package/connectors/connect-grain/src/api/client.ts +19 -206
  290. package/connectors/connect-grain/src/api/index.ts +29 -43
  291. package/connectors/connect-grain/src/types/index.ts +8 -233
  292. package/connectors/connect-grist/src/api/client.ts +18 -204
  293. package/connectors/connect-grist/src/api/index.ts +27 -43
  294. package/connectors/connect-grist/src/types/index.ts +10 -233
  295. package/connectors/connect-handwrytten/src/api/client.ts +18 -205
  296. package/connectors/connect-handwrytten/src/api/index.ts +23 -43
  297. package/connectors/connect-handwrytten/src/types/index.ts +8 -233
  298. package/connectors/connect-harrypotterapi/src/api/client.ts +9 -206
  299. package/connectors/connect-harrypotterapi/src/api/index.ts +15 -45
  300. package/connectors/connect-harrypotterapi/src/types/index.ts +5 -233
  301. package/connectors/connect-helcim/src/api/client.ts +20 -210
  302. package/connectors/connect-helcim/src/api/index.ts +38 -43
  303. package/connectors/connect-helcim/src/types/index.ts +15 -228
  304. package/connectors/connect-heysummit/src/api/client.ts +22 -209
  305. package/connectors/connect-heysummit/src/api/index.ts +23 -44
  306. package/connectors/connect-heysummit/src/types/index.ts +8 -233
  307. package/connectors/connect-hubplanner/src/api/client.ts +18 -205
  308. package/connectors/connect-hubplanner/src/api/index.ts +33 -42
  309. package/connectors/connect-hubplanner/src/types/index.ts +8 -233
  310. package/connectors/connect-huggingface/src/api/client.ts +5 -0
  311. package/connectors/connect-huggingface/src/api/datasets.ts +73 -0
  312. package/connectors/connect-huggingface/src/api/index.ts +17 -19
  313. package/connectors/connect-huggingface/src/api/inference.ts +199 -0
  314. package/connectors/connect-huggingface/src/api/models.ts +66 -0
  315. package/connectors/connect-huggingface/src/api/spaces.ts +42 -0
  316. package/connectors/connect-huggingface/src/cli/index.ts +148 -36
  317. package/connectors/connect-hunter/src/api/client.ts +14 -205
  318. package/connectors/connect-hunter/src/api/index.ts +25 -42
  319. package/connectors/connect-hunter/src/types/index.ts +8 -233
  320. package/connectors/connect-hybridanalysis/src/api/client.ts +24 -204
  321. package/connectors/connect-hybridanalysis/src/api/index.ts +24 -43
  322. package/connectors/connect-hybridanalysis/src/types/index.ts +7 -233
  323. package/connectors/connect-ideta/src/api/client.ts +18 -205
  324. package/connectors/connect-ideta/src/api/index.ts +25 -42
  325. package/connectors/connect-ideta/src/types/index.ts +8 -233
  326. package/connectors/connect-invoiced/src/api/client.ts +19 -208
  327. package/connectors/connect-invoiced/src/api/index.ts +22 -49
  328. package/connectors/connect-invoiced/src/types/index.ts +5 -237
  329. package/connectors/connect-ip2location/src/api/client.ts +14 -205
  330. package/connectors/connect-ip2location/src/api/index.ts +20 -43
  331. package/connectors/connect-ip2location/src/types/index.ts +5 -233
  332. package/connectors/connect-ipinfo/src/api/client.ts +16 -206
  333. package/connectors/connect-ipinfo/src/api/index.ts +21 -47
  334. package/connectors/connect-ipinfo/src/types/index.ts +6 -233
  335. package/connectors/connect-jasper/src/api/client.ts +18 -202
  336. package/connectors/connect-jasper/src/api/index.ts +41 -43
  337. package/connectors/connect-jasper/src/types/index.ts +7 -233
  338. package/connectors/connect-jenkins/src/api/client.ts +25 -205
  339. package/connectors/connect-jenkins/src/api/index.ts +38 -43
  340. package/connectors/connect-jenkins/src/types/index.ts +8 -233
  341. package/connectors/connect-jinaai/src/api/client.ts +21 -204
  342. package/connectors/connect-jinaai/src/api/index.ts +23 -42
  343. package/connectors/connect-jinaai/src/types/index.ts +9 -233
  344. package/connectors/connect-jira/src/api/client.ts +57 -0
  345. package/connectors/connect-jira/src/api/index.ts +22 -63
  346. package/connectors/connect-kafka/src/api/client.ts +27 -206
  347. package/connectors/connect-kafka/src/api/index.ts +29 -42
  348. package/connectors/connect-kafka/src/types/index.ts +9 -233
  349. package/connectors/connect-kaggle/src/api/client.ts +15 -205
  350. package/connectors/connect-kaggle/src/api/index.ts +27 -43
  351. package/connectors/connect-kaggle/src/types/index.ts +7 -233
  352. package/connectors/connect-kanbantool/src/api/client.ts +19 -205
  353. package/connectors/connect-kanbantool/src/api/index.ts +34 -43
  354. package/connectors/connect-kanbantool/src/types/index.ts +8 -233
  355. package/connectors/connect-keygen/src/api/client.ts +19 -205
  356. package/connectors/connect-keygen/src/api/index.ts +33 -43
  357. package/connectors/connect-keygen/src/types/index.ts +8 -233
  358. package/connectors/connect-kibana/src/api/client.ts +24 -204
  359. package/connectors/connect-kibana/src/api/index.ts +36 -42
  360. package/connectors/connect-kibana/src/types/index.ts +9 -233
  361. package/connectors/connect-lambdatest/src/api/client.ts +19 -206
  362. package/connectors/connect-lambdatest/src/api/index.ts +29 -44
  363. package/connectors/connect-lambdatest/src/types/index.ts +8 -233
  364. package/connectors/connect-laposta/src/api/client.ts +19 -206
  365. package/connectors/connect-laposta/src/api/index.ts +39 -42
  366. package/connectors/connect-laposta/src/types/index.ts +8 -233
  367. package/connectors/connect-launch27/src/api/client.ts +18 -207
  368. package/connectors/connect-launch27/src/api/index.ts +31 -42
  369. package/connectors/connect-launch27/src/types/index.ts +7 -233
  370. package/connectors/connect-leadboxer/src/api/client.ts +18 -205
  371. package/connectors/connect-leadboxer/src/api/index.ts +20 -44
  372. package/connectors/connect-leadboxer/src/types/index.ts +7 -233
  373. package/connectors/connect-leadpops/src/api/client.ts +18 -205
  374. package/connectors/connect-leadpops/src/api/index.ts +25 -45
  375. package/connectors/connect-leadpops/src/types/index.ts +7 -233
  376. package/connectors/connect-lighthouse/src/api/client.ts +18 -205
  377. package/connectors/connect-lighthouse/src/api/index.ts +33 -41
  378. package/connectors/connect-lighthouse/src/types/index.ts +9 -233
  379. package/connectors/connect-limego/src/api/client.ts +18 -205
  380. package/connectors/connect-limego/src/api/index.ts +25 -44
  381. package/connectors/connect-limego/src/types/index.ts +8 -233
  382. package/connectors/connect-line/src/api/client.ts +23 -205
  383. package/connectors/connect-line/src/api/index.ts +34 -44
  384. package/connectors/connect-line/src/types/index.ts +9 -233
  385. package/connectors/connect-linear/src/api/comments.ts +148 -0
  386. package/connectors/connect-linear/src/api/index.ts +8 -0
  387. package/connectors/connect-linear/src/api/states.ts +88 -0
  388. package/connectors/connect-linear/src/types/index.ts +68 -0
  389. package/connectors/connect-lingvanex/src/api/client.ts +19 -209
  390. package/connectors/connect-lingvanex/src/api/index.ts +24 -42
  391. package/connectors/connect-lingvanex/src/types/index.ts +7 -233
  392. package/connectors/connect-liveagent/src/api/client.ts +18 -204
  393. package/connectors/connect-liveagent/src/api/index.ts +34 -42
  394. package/connectors/connect-liveagent/src/types/index.ts +9 -233
  395. package/connectors/connect-loginradius/src/api/client.ts +23 -202
  396. package/connectors/connect-loginradius/src/api/index.ts +35 -43
  397. package/connectors/connect-loginradius/src/types/index.ts +9 -233
  398. package/connectors/connect-mailerlite/src/api/client.ts +18 -205
  399. package/connectors/connect-mailerlite/src/api/index.ts +35 -42
  400. package/connectors/connect-mailerlite/src/types/index.ts +9 -233
  401. package/connectors/connect-mailgun/src/api/client.ts +29 -201
  402. package/connectors/connect-mailgun/src/api/index.ts +37 -43
  403. package/connectors/connect-mailgun/src/types/index.ts +10 -233
  404. package/connectors/connect-malcore/src/api/client.ts +18 -205
  405. package/connectors/connect-malcore/src/api/index.ts +30 -43
  406. package/connectors/connect-malcore/src/types/index.ts +7 -233
  407. package/connectors/connect-marketplacer/src/api/client.ts +18 -204
  408. package/connectors/connect-marketplacer/src/api/index.ts +30 -44
  409. package/connectors/connect-marketplacer/src/types/index.ts +9 -233
  410. package/connectors/connect-matrix/src/api/client.ts +21 -204
  411. package/connectors/connect-matrix/src/api/index.ts +34 -41
  412. package/connectors/connect-matrix/src/types/index.ts +10 -233
  413. package/connectors/connect-mattermost/src/api/client.ts +19 -205
  414. package/connectors/connect-mattermost/src/api/index.ts +34 -42
  415. package/connectors/connect-mattermost/src/types/index.ts +8 -233
  416. package/connectors/connect-mem/src/api/client.ts +18 -205
  417. package/connectors/connect-mem/src/api/index.ts +20 -43
  418. package/connectors/connect-mem/src/types/index.ts +6 -233
  419. package/connectors/connect-mercury/CLAUDE.md +0 -1
  420. package/connectors/connect-microsoftentraid/src/api/client.ts +21 -205
  421. package/connectors/connect-microsoftentraid/src/api/index.ts +29 -44
  422. package/connectors/connect-microsoftentraid/src/types/index.ts +8 -233
  423. package/connectors/connect-microsoftentraidazureactivedirectory/src/api/client.ts +21 -205
  424. package/connectors/connect-microsoftentraidazureactivedirectory/src/api/index.ts +37 -44
  425. package/connectors/connect-microsoftentraidazureactivedirectory/src/types/index.ts +10 -233
  426. package/connectors/connect-microsoftgraphsecurity/src/api/client.ts +21 -205
  427. package/connectors/connect-microsoftgraphsecurity/src/api/index.ts +28 -43
  428. package/connectors/connect-microsoftgraphsecurity/src/types/index.ts +8 -233
  429. package/connectors/connect-microsoftonedrive/src/api/client.ts +21 -205
  430. package/connectors/connect-microsoftonedrive/src/api/index.ts +41 -41
  431. package/connectors/connect-microsoftonedrive/src/types/index.ts +8 -233
  432. package/connectors/connect-microsofttodo/src/api/client.ts +21 -205
  433. package/connectors/connect-microsofttodo/src/api/index.ts +35 -43
  434. package/connectors/connect-microsofttodo/src/types/index.ts +6 -233
  435. package/connectors/connect-miestro/src/api/client.ts +18 -205
  436. package/connectors/connect-miestro/src/api/index.ts +30 -43
  437. package/connectors/connect-miestro/src/types/index.ts +8 -233
  438. package/connectors/connect-miro/src/api/client.ts +19 -206
  439. package/connectors/connect-miro/src/api/index.ts +32 -41
  440. package/connectors/connect-miro/src/types/index.ts +10 -233
  441. package/connectors/connect-missive/src/api/client.ts +19 -206
  442. package/connectors/connect-missive/src/api/index.ts +35 -42
  443. package/connectors/connect-missive/src/types/index.ts +13 -235
  444. package/connectors/connect-mist/src/api/client.ts +19 -205
  445. package/connectors/connect-mist/src/api/index.ts +24 -43
  446. package/connectors/connect-mist/src/types/index.ts +8 -233
  447. package/connectors/connect-mistral/src/api/chat.ts +2 -1
  448. package/connectors/connect-mistral/src/api/embeddings.ts +2 -1
  449. package/connectors/connect-monday/src/api/index.ts +120 -1
  450. package/connectors/connect-moonmail/src/api/client.ts +18 -205
  451. package/connectors/connect-moonmail/src/api/index.ts +31 -43
  452. package/connectors/connect-moonmail/src/types/index.ts +7 -233
  453. package/connectors/connect-mxtoolbox/src/api/client.ts +15 -204
  454. package/connectors/connect-mxtoolbox/src/api/index.ts +25 -45
  455. package/connectors/connect-mxtoolbox/src/types/index.ts +10 -233
  456. package/connectors/connect-myaskai/src/api/client.ts +18 -205
  457. package/connectors/connect-myaskai/src/api/index.ts +28 -42
  458. package/connectors/connect-myaskai/src/types/index.ts +7 -233
  459. package/connectors/connect-myphoner/src/api/client.ts +18 -205
  460. package/connectors/connect-myphoner/src/api/index.ts +30 -43
  461. package/connectors/connect-myphoner/src/types/index.ts +8 -233
  462. package/connectors/connect-nanonetsocr/src/api/client.ts +19 -206
  463. package/connectors/connect-nanonetsocr/src/api/index.ts +22 -42
  464. package/connectors/connect-nanonetsocr/src/types/index.ts +8 -233
  465. package/connectors/connect-nocodb/src/api/client.ts +22 -208
  466. package/connectors/connect-nocodb/src/api/index.ts +40 -42
  467. package/connectors/connect-nocodb/src/types/index.ts +10 -233
  468. package/connectors/connect-npm/src/api/client.ts +22 -203
  469. package/connectors/connect-npm/src/api/index.ts +24 -43
  470. package/connectors/connect-npm/src/types/index.ts +8 -233
  471. package/connectors/connect-nuclia/src/api/client.ts +19 -205
  472. package/connectors/connect-nuclia/src/api/index.ts +32 -43
  473. package/connectors/connect-nuclia/src/types/index.ts +8 -233
  474. package/connectors/connect-nyota/src/api/client.ts +18 -205
  475. package/connectors/connect-nyota/src/api/index.ts +24 -43
  476. package/connectors/connect-nyota/src/types/index.ts +8 -233
  477. package/connectors/connect-offalerts/src/api/client.ts +18 -205
  478. package/connectors/connect-offalerts/src/api/index.ts +25 -44
  479. package/connectors/connect-offalerts/src/types/index.ts +7 -233
  480. package/connectors/connect-okta/src/api/client.ts +21 -204
  481. package/connectors/connect-okta/src/api/index.ts +40 -42
  482. package/connectors/connect-okta/src/types/index.ts +10 -233
  483. package/connectors/connect-omnimind/src/api/client.ts +18 -205
  484. package/connectors/connect-omnimind/src/api/index.ts +31 -43
  485. package/connectors/connect-omnimind/src/types/index.ts +7 -233
  486. package/connectors/connect-on2air/src/api/client.ts +18 -205
  487. package/connectors/connect-on2air/src/api/index.ts +26 -44
  488. package/connectors/connect-on2air/src/types/index.ts +7 -233
  489. package/connectors/connect-oneai/src/api/client.ts +19 -209
  490. package/connectors/connect-oneai/src/api/index.ts +36 -39
  491. package/connectors/connect-oneai/src/types/index.ts +7 -233
  492. package/connectors/connect-onesimpleapi/src/api/client.ts +17 -204
  493. package/connectors/connect-onesimpleapi/src/api/index.ts +30 -43
  494. package/connectors/connect-onesimpleapi/src/types/index.ts +8 -233
  495. package/connectors/connect-openai/src/api/chat.ts +2 -2
  496. package/connectors/connect-openai/src/api/images.ts +52 -8
  497. package/connectors/connect-openai/src/types/index.ts +0 -10
  498. package/connectors/connect-ortto/src/api/client.ts +19 -204
  499. package/connectors/connect-ortto/src/api/index.ts +28 -44
  500. package/connectors/connect-ortto/src/types/index.ts +9 -233
  501. package/connectors/connect-oura/src/api/client.ts +16 -205
  502. package/connectors/connect-oura/src/api/index.ts +25 -42
  503. package/connectors/connect-oura/src/types/index.ts +9 -233
  504. package/connectors/connect-papyrs/src/api/client.ts +18 -204
  505. package/connectors/connect-papyrs/src/api/index.ts +30 -43
  506. package/connectors/connect-papyrs/src/types/index.ts +8 -233
  507. package/connectors/connect-paymo/src/api/client.ts +19 -206
  508. package/connectors/connect-paymo/src/api/index.ts +34 -43
  509. package/connectors/connect-paymo/src/types/index.ts +9 -233
  510. package/connectors/connect-personalai/src/api/client.ts +18 -205
  511. package/connectors/connect-personalai/src/api/index.ts +26 -43
  512. package/connectors/connect-personalai/src/types/index.ts +8 -233
  513. package/connectors/connect-phantombuster/src/api/client.ts +18 -205
  514. package/connectors/connect-phantombuster/src/api/index.ts +28 -43
  515. package/connectors/connect-phantombuster/src/types/index.ts +6 -233
  516. package/connectors/connect-planyoonlinebooking/src/api/client.ts +19 -209
  517. package/connectors/connect-planyoonlinebooking/src/api/index.ts +34 -43
  518. package/connectors/connect-planyoonlinebooking/src/types/index.ts +8 -233
  519. package/connectors/connect-plivo/src/api/client.ts +22 -208
  520. package/connectors/connect-plivo/src/api/index.ts +32 -44
  521. package/connectors/connect-plivo/src/types/index.ts +9 -233
  522. package/connectors/connect-posthog/src/api/client.ts +22 -205
  523. package/connectors/connect-posthog/src/api/index.ts +65 -39
  524. package/connectors/connect-posthog/src/types/index.ts +8 -233
  525. package/connectors/connect-practitest/src/api/client.ts +19 -206
  526. package/connectors/connect-practitest/src/api/index.ts +36 -40
  527. package/connectors/connect-practitest/src/types/index.ts +9 -233
  528. package/connectors/connect-predisai/src/api/client.ts +18 -205
  529. package/connectors/connect-predisai/src/api/index.ts +25 -43
  530. package/connectors/connect-predisai/src/types/index.ts +7 -233
  531. package/connectors/connect-prodia/src/api/client.ts +18 -205
  532. package/connectors/connect-prodia/src/api/index.ts +26 -43
  533. package/connectors/connect-prodia/src/types/index.ts +7 -233
  534. package/connectors/connect-profitwell/src/api/client.ts +18 -205
  535. package/connectors/connect-profitwell/src/api/index.ts +28 -44
  536. package/connectors/connect-profitwell/src/types/index.ts +7 -233
  537. package/connectors/connect-projectbubbleproprofsproject/src/api/client.ts +18 -205
  538. package/connectors/connect-projectbubbleproprofsproject/src/api/index.ts +32 -43
  539. package/connectors/connect-projectbubbleproprofsproject/src/types/index.ts +8 -233
  540. package/connectors/connect-pulsetic/src/api/client.ts +18 -205
  541. package/connectors/connect-pulsetic/src/api/index.ts +25 -43
  542. package/connectors/connect-pulsetic/src/types/index.ts +8 -233
  543. package/connectors/connect-pusher/src/api/client.ts +36 -205
  544. package/connectors/connect-pusher/src/api/index.ts +29 -41
  545. package/connectors/connect-pusher/src/types/index.ts +8 -233
  546. package/connectors/connect-pushover/src/api/client.ts +24 -207
  547. package/connectors/connect-pushover/src/api/index.ts +27 -46
  548. package/connectors/connect-pushover/src/types/index.ts +5 -237
  549. package/connectors/connect-qualys/src/api/client.ts +21 -205
  550. package/connectors/connect-qualys/src/api/index.ts +35 -42
  551. package/connectors/connect-qualys/src/types/index.ts +8 -233
  552. package/connectors/connect-quentn/src/api/client.ts +18 -204
  553. package/connectors/connect-quentn/src/api/index.ts +35 -44
  554. package/connectors/connect-quentn/src/types/index.ts +9 -233
  555. package/connectors/connect-questdb/src/api/client.ts +22 -204
  556. package/connectors/connect-questdb/src/api/index.ts +35 -43
  557. package/connectors/connect-questdb/src/types/index.ts +7 -233
  558. package/connectors/connect-quintadb/src/api/client.ts +21 -207
  559. package/connectors/connect-quintadb/src/api/index.ts +32 -43
  560. package/connectors/connect-quintadb/src/types/index.ts +6 -233
  561. package/connectors/connect-rapid7insightvm/src/api/client.ts +19 -205
  562. package/connectors/connect-rapid7insightvm/src/api/index.ts +34 -42
  563. package/connectors/connect-rapid7insightvm/src/types/index.ts +9 -233
  564. package/connectors/connect-raventools/src/api/client.ts +20 -209
  565. package/connectors/connect-raventools/src/api/index.ts +24 -44
  566. package/connectors/connect-raventools/src/types/index.ts +8 -233
  567. package/connectors/connect-rdstationcrm/src/api/client.ts +20 -206
  568. package/connectors/connect-rdstationcrm/src/api/index.ts +34 -43
  569. package/connectors/connect-rdstationcrm/src/types/index.ts +9 -233
  570. package/connectors/connect-realphonevalidation/src/api/client.ts +15 -205
  571. package/connectors/connect-realphonevalidation/src/api/index.ts +21 -43
  572. package/connectors/connect-realphonevalidation/src/types/index.ts +5 -233
  573. package/connectors/connect-recharge/src/api/client.ts +19 -206
  574. package/connectors/connect-recharge/src/api/index.ts +35 -42
  575. package/connectors/connect-recharge/src/types/index.ts +10 -233
  576. package/connectors/connect-relevanceai/src/api/client.ts +21 -204
  577. package/connectors/connect-relevanceai/src/api/index.ts +28 -41
  578. package/connectors/connect-relevanceai/src/types/index.ts +8 -233
  579. package/connectors/connect-relinkurlshortener/src/api/client.ts +18 -205
  580. package/connectors/connect-relinkurlshortener/src/api/index.ts +25 -44
  581. package/connectors/connect-relinkurlshortener/src/types/index.ts +6 -233
  582. package/connectors/connect-reply/src/api/client.ts +18 -205
  583. package/connectors/connect-reply/src/api/index.ts +31 -44
  584. package/connectors/connect-reply/src/types/index.ts +9 -233
  585. package/connectors/connect-ritekit/src/api/client.ts +15 -206
  586. package/connectors/connect-ritekit/src/api/index.ts +32 -43
  587. package/connectors/connect-ritekit/src/types/index.ts +7 -233
  588. package/connectors/connect-rocketchat/src/api/client.ts +20 -205
  589. package/connectors/connect-rocketchat/src/api/index.ts +39 -41
  590. package/connectors/connect-rocketchat/src/types/index.ts +8 -233
  591. package/connectors/connect-rundeck/src/api/client.ts +20 -205
  592. package/connectors/connect-rundeck/src/api/index.ts +30 -43
  593. package/connectors/connect-rundeck/src/types/index.ts +8 -233
  594. package/connectors/connect-salesforce/src/api/client.ts +49 -0
  595. package/connectors/connect-salesforce/src/api/index.ts +18 -15
  596. package/connectors/connect-samsungsmartthings/src/api/client.ts +19 -206
  597. package/connectors/connect-samsungsmartthings/src/api/index.ts +26 -44
  598. package/connectors/connect-samsungsmartthings/src/types/index.ts +10 -233
  599. package/connectors/connect-scrapeitcloud/src/api/client.ts +18 -205
  600. package/connectors/connect-scrapeitcloud/src/api/index.ts +22 -43
  601. package/connectors/connect-scrapeitcloud/src/types/index.ts +7 -233
  602. package/connectors/connect-seamlessai/src/api/client.ts +18 -205
  603. package/connectors/connect-seamlessai/src/api/index.ts +28 -43
  604. package/connectors/connect-seamlessai/src/types/index.ts +8 -233
  605. package/connectors/connect-sekoia/src/api/client.ts +18 -205
  606. package/connectors/connect-sekoia/src/api/index.ts +31 -41
  607. package/connectors/connect-sekoia/src/types/index.ts +9 -233
  608. package/connectors/connect-sellix/src/api/client.ts +18 -205
  609. package/connectors/connect-sellix/src/api/index.ts +32 -42
  610. package/connectors/connect-sellix/src/types/index.ts +10 -233
  611. package/connectors/connect-servicenow/src/api/client.ts +21 -204
  612. package/connectors/connect-servicenow/src/api/index.ts +45 -41
  613. package/connectors/connect-servicenow/src/types/index.ts +9 -233
  614. package/connectors/connect-shopify/src/api/products.ts +79 -2
  615. package/connectors/connect-shuffler/src/api/client.ts +18 -204
  616. package/connectors/connect-shuffler/src/api/index.ts +29 -44
  617. package/connectors/connect-shuffler/src/types/index.ts +8 -233
  618. package/connectors/connect-signaturit/src/api/client.ts +19 -205
  619. package/connectors/connect-signaturit/src/api/index.ts +30 -42
  620. package/connectors/connect-signaturit/src/types/index.ts +10 -233
  621. package/connectors/connect-simplehash/src/api/client.ts +14 -204
  622. package/connectors/connect-simplehash/src/api/index.ts +29 -43
  623. package/connectors/connect-simplehash/src/types/index.ts +7 -233
  624. package/connectors/connect-simplelocalize/src/api/client.ts +18 -205
  625. package/connectors/connect-simplelocalize/src/api/index.ts +33 -42
  626. package/connectors/connect-simplelocalize/src/types/index.ts +13 -235
  627. package/connectors/connect-sitespeakai/src/api/client.ts +18 -205
  628. package/connectors/connect-sitespeakai/src/api/index.ts +29 -41
  629. package/connectors/connect-sitespeakai/src/types/index.ts +8 -233
  630. package/connectors/connect-smaily/src/api/client.ts +19 -205
  631. package/connectors/connect-smaily/src/api/index.ts +29 -44
  632. package/connectors/connect-smaily/src/types/index.ts +8 -233
  633. package/connectors/connect-snatchbot/src/api/client.ts +19 -206
  634. package/connectors/connect-snatchbot/src/api/index.ts +25 -42
  635. package/connectors/connect-snatchbot/src/types/index.ts +8 -233
  636. package/connectors/connect-solvedata/src/api/client.ts +18 -205
  637. package/connectors/connect-solvedata/src/api/index.ts +26 -43
  638. package/connectors/connect-solvedata/src/types/index.ts +7 -233
  639. package/connectors/connect-specter/src/api/client.ts +24 -209
  640. package/connectors/connect-specter/src/api/index.ts +27 -43
  641. package/connectors/connect-specter/src/types/index.ts +10 -233
  642. package/connectors/connect-spike/src/api/client.ts +18 -205
  643. package/connectors/connect-spike/src/api/index.ts +28 -45
  644. package/connectors/connect-spike/src/types/index.ts +8 -233
  645. package/connectors/connect-sportsdata/src/api/client.ts +14 -206
  646. package/connectors/connect-sportsdata/src/api/index.ts +32 -46
  647. package/connectors/connect-sportsdata/src/types/index.ts +8 -233
  648. package/connectors/connect-sslmatecertspotterapi/src/api/client.ts +15 -204
  649. package/connectors/connect-sslmatecertspotterapi/src/api/index.ts +23 -43
  650. package/connectors/connect-sslmatecertspotterapi/src/types/index.ts +5 -233
  651. package/connectors/connect-starton/src/api/client.ts +18 -205
  652. package/connectors/connect-starton/src/api/index.ts +34 -42
  653. package/connectors/connect-starton/src/types/index.ts +8 -233
  654. package/connectors/connect-statuscake/src/api/client.ts +18 -205
  655. package/connectors/connect-statuscake/src/api/index.ts +30 -44
  656. package/connectors/connect-statuscake/src/types/index.ts +9 -233
  657. package/connectors/connect-strapi/src/api/client.ts +21 -204
  658. package/connectors/connect-strapi/src/api/index.ts +38 -42
  659. package/connectors/connect-strapi/src/types/index.ts +9 -233
  660. package/connectors/connect-supernormal/src/api/client.ts +18 -205
  661. package/connectors/connect-supernormal/src/api/index.ts +28 -43
  662. package/connectors/connect-supernormal/src/types/index.ts +8 -233
  663. package/connectors/connect-supportivekoala/src/api/client.ts +18 -205
  664. package/connectors/connect-supportivekoala/src/api/index.ts +21 -43
  665. package/connectors/connect-supportivekoala/src/types/index.ts +7 -233
  666. package/connectors/connect-surveysparrow/src/api/client.ts +20 -210
  667. package/connectors/connect-surveysparrow/src/api/index.ts +39 -42
  668. package/connectors/connect-surveysparrow/src/types/index.ts +7 -233
  669. package/connectors/connect-swagup/src/api/client.ts +18 -205
  670. package/connectors/connect-swagup/src/api/index.ts +30 -42
  671. package/connectors/connect-swagup/src/types/index.ts +8 -233
  672. package/connectors/connect-switchboard/src/api/client.ts +18 -205
  673. package/connectors/connect-switchboard/src/api/index.ts +27 -43
  674. package/connectors/connect-switchboard/src/types/index.ts +7 -233
  675. package/connectors/connect-syncly/src/api/client.ts +18 -205
  676. package/connectors/connect-syncly/src/api/index.ts +21 -44
  677. package/connectors/connect-syncly/src/types/index.ts +8 -233
  678. package/connectors/connect-syncromsp/src/api/client.ts +19 -204
  679. package/connectors/connect-syncromsp/src/api/index.ts +35 -42
  680. package/connectors/connect-syncromsp/src/types/index.ts +8 -233
  681. package/connectors/connect-talentlms/src/api/client.ts +19 -205
  682. package/connectors/connect-talentlms/src/api/index.ts +30 -42
  683. package/connectors/connect-talentlms/src/types/index.ts +8 -233
  684. package/connectors/connect-tdameritrade/src/api/client.ts +22 -205
  685. package/connectors/connect-tdameritrade/src/api/index.ts +32 -41
  686. package/connectors/connect-tdameritrade/src/types/index.ts +9 -233
  687. package/connectors/connect-teamdeck/src/api/client.ts +20 -210
  688. package/connectors/connect-teamdeck/src/api/index.ts +39 -41
  689. package/connectors/connect-teamdeck/src/types/index.ts +8 -233
  690. package/connectors/connect-teamgate/src/api/client.ts +21 -206
  691. package/connectors/connect-teamgate/src/api/index.ts +37 -43
  692. package/connectors/connect-teamgate/src/types/index.ts +9 -233
  693. package/connectors/connect-teamup/src/api/client.ts +24 -209
  694. package/connectors/connect-teamup/src/api/index.ts +25 -45
  695. package/connectors/connect-teamup/src/types/index.ts +6 -233
  696. package/connectors/connect-testmonitor/src/api/client.ts +19 -205
  697. package/connectors/connect-testmonitor/src/api/index.ts +38 -42
  698. package/connectors/connect-testmonitor/src/types/index.ts +8 -233
  699. package/connectors/connect-textcortexai/src/api/client.ts +18 -205
  700. package/connectors/connect-textcortexai/src/api/index.ts +33 -43
  701. package/connectors/connect-textcortexai/src/types/index.ts +7 -233
  702. package/connectors/connect-textmagic/src/api/client.ts +20 -205
  703. package/connectors/connect-textmagic/src/api/index.ts +34 -43
  704. package/connectors/connect-textmagic/src/types/index.ts +9 -233
  705. package/connectors/connect-thankster/src/api/client.ts +18 -205
  706. package/connectors/connect-thankster/src/api/index.ts +27 -43
  707. package/connectors/connect-thankster/src/types/index.ts +8 -233
  708. package/connectors/connect-thecustomerfactor/src/api/client.ts +18 -205
  709. package/connectors/connect-thecustomerfactor/src/api/index.ts +34 -42
  710. package/connectors/connect-thecustomerfactor/src/types/index.ts +7 -233
  711. package/connectors/connect-theleap/src/api/client.ts +18 -205
  712. package/connectors/connect-theleap/src/api/index.ts +23 -43
  713. package/connectors/connect-theleap/src/types/index.ts +6 -233
  714. package/connectors/connect-thoughtfulgpt/src/api/client.ts +18 -205
  715. package/connectors/connect-thoughtfulgpt/src/api/index.ts +22 -44
  716. package/connectors/connect-thoughtfulgpt/src/types/index.ts +7 -233
  717. package/connectors/connect-tilda/src/api/client.ts +18 -206
  718. package/connectors/connect-tilda/src/api/index.ts +22 -46
  719. package/connectors/connect-tilda/src/types/index.ts +7 -233
  720. package/connectors/connect-tisanelabs/src/api/client.ts +13 -206
  721. package/connectors/connect-tisanelabs/src/api/index.ts +26 -41
  722. package/connectors/connect-tisanelabs/src/types/index.ts +8 -233
  723. package/connectors/connect-trackvia/src/api/client.ts +22 -206
  724. package/connectors/connect-trackvia/src/api/index.ts +35 -43
  725. package/connectors/connect-trackvia/src/types/index.ts +9 -233
  726. package/connectors/connect-travisci/src/api/client.ts +19 -205
  727. package/connectors/connect-travisci/src/api/index.ts +28 -43
  728. package/connectors/connect-travisci/src/types/index.ts +7 -233
  729. package/connectors/connect-turbohire/src/api/client.ts +18 -205
  730. package/connectors/connect-turbohire/src/api/index.ts +34 -42
  731. package/connectors/connect-turbohire/src/types/index.ts +8 -233
  732. package/connectors/connect-tuskr/src/api/client.ts +19 -206
  733. package/connectors/connect-tuskr/src/api/index.ts +37 -42
  734. package/connectors/connect-tuskr/src/types/index.ts +8 -233
  735. package/connectors/connect-unisender/src/api/client.ts +19 -209
  736. package/connectors/connect-unisender/src/api/index.ts +37 -42
  737. package/connectors/connect-unisender/src/types/index.ts +10 -233
  738. package/connectors/connect-uproc/src/api/client.ts +18 -205
  739. package/connectors/connect-uproc/src/api/index.ts +25 -43
  740. package/connectors/connect-uproc/src/types/index.ts +7 -233
  741. package/connectors/connect-uptimerobot/src/api/client.ts +22 -208
  742. package/connectors/connect-uptimerobot/src/api/index.ts +43 -39
  743. package/connectors/connect-uptimerobot/src/types/index.ts +8 -233
  744. package/connectors/connect-uservoice/src/api/client.ts +19 -205
  745. package/connectors/connect-uservoice/src/api/index.ts +31 -43
  746. package/connectors/connect-uservoice/src/types/index.ts +13 -235
  747. package/connectors/connect-verifalia/src/api/client.ts +20 -206
  748. package/connectors/connect-verifalia/src/api/index.ts +31 -41
  749. package/connectors/connect-verifalia/src/types/index.ts +6 -233
  750. package/connectors/connect-virustotal/src/api/client.ts +21 -204
  751. package/connectors/connect-virustotal/src/api/index.ts +27 -42
  752. package/connectors/connect-virustotal/src/types/index.ts +8 -233
  753. package/connectors/connect-vivifyscrum/src/api/client.ts +19 -206
  754. package/connectors/connect-vivifyscrum/src/api/index.ts +28 -44
  755. package/connectors/connect-vivifyscrum/src/types/index.ts +9 -233
  756. package/connectors/connect-voicit/src/api/client.ts +18 -205
  757. package/connectors/connect-voicit/src/api/index.ts +19 -45
  758. package/connectors/connect-voicit/src/types/index.ts +7 -233
  759. package/connectors/connect-vowel/src/api/client.ts +18 -205
  760. package/connectors/connect-vowel/src/api/index.ts +22 -44
  761. package/connectors/connect-vowel/src/types/index.ts +8 -233
  762. package/connectors/connect-watchsignals/src/api/client.ts +15 -205
  763. package/connectors/connect-watchsignals/src/api/index.ts +24 -42
  764. package/connectors/connect-watchsignals/src/types/index.ts +8 -233
  765. package/connectors/connect-wavelineextract/src/api/client.ts +18 -205
  766. package/connectors/connect-wavelineextract/src/api/index.ts +21 -45
  767. package/connectors/connect-wavelineextract/src/types/index.ts +6 -233
  768. package/connectors/connect-webinarjam/src/api/client.ts +15 -206
  769. package/connectors/connect-webinarjam/src/api/index.ts +18 -44
  770. package/connectors/connect-webinarjam/src/types/index.ts +6 -233
  771. package/connectors/connect-wikipedia/src/api/client.ts +22 -202
  772. package/connectors/connect-wikipedia/src/api/index.ts +49 -43
  773. package/connectors/connect-wikipedia/src/types/index.ts +22 -228
  774. package/connectors/connect-wubookratechecker/src/api/client.ts +14 -204
  775. package/connectors/connect-wubookratechecker/src/api/index.ts +18 -46
  776. package/connectors/connect-wubookratechecker/src/types/index.ts +6 -233
  777. package/connectors/connect-xai/src/api/chat.ts +2 -1
  778. package/connectors/connect-yodiz/src/api/client.ts +20 -205
  779. package/connectors/connect-yodiz/src/api/index.ts +36 -41
  780. package/connectors/connect-yodiz/src/types/index.ts +8 -233
  781. package/connectors/connect-yourls/src/api/client.ts +25 -211
  782. package/connectors/connect-yourls/src/api/index.ts +33 -41
  783. package/connectors/connect-yourls/src/types/index.ts +7 -233
  784. package/connectors/connect-zammad/src/api/client.ts +19 -208
  785. package/connectors/connect-zammad/src/api/index.ts +32 -44
  786. package/connectors/connect-zammad/src/types/index.ts +8 -233
  787. package/connectors/connect-zohobooks/src/api/client.ts +21 -205
  788. package/connectors/connect-zohobooks/src/api/index.ts +36 -42
  789. package/connectors/connect-zohobooks/src/types/index.ts +10 -233
  790. package/connectors/connect-zohocrm/src/api/client.ts +21 -204
  791. package/connectors/connect-zohocrm/src/api/index.ts +36 -41
  792. package/connectors/connect-zohocrm/src/types/index.ts +10 -233
  793. package/connectors/connect-zohoworkdrive/src/api/client.ts +24 -206
  794. package/connectors/connect-zohoworkdrive/src/api/index.ts +31 -42
  795. package/connectors/connect-zohoworkdrive/src/types/index.ts +7 -233
  796. package/connectors/connect-zoom/src/api/users.ts +95 -1
  797. package/connectors/connect-zulip/src/api/client.ts +22 -206
  798. package/connectors/connect-zulip/src/api/index.ts +35 -44
  799. package/connectors/connect-zulip/src/types/index.ts +7 -233
  800. package/dist/db/agents.d.ts +38 -0
  801. package/dist/db/agents.test.d.ts +1 -0
  802. package/dist/db/database.d.ts +7 -0
  803. package/dist/db/jobs.d.ts +53 -0
  804. package/dist/db/jobs.test.d.ts +1 -0
  805. package/dist/db/locks.d.ts +59 -0
  806. package/dist/db/locks.test.d.ts +1 -0
  807. package/dist/db/promotions.d.ts +5 -0
  808. package/dist/db/promotions.test.d.ts +1 -0
  809. package/dist/db/rate.d.ts +57 -0
  810. package/dist/db/rate.test.d.ts +1 -0
  811. package/dist/db/usage.d.ts +17 -0
  812. package/dist/db/usage.test.d.ts +1 -0
  813. package/dist/db/workflows.d.ts +26 -0
  814. package/dist/db/workflows.test.d.ts +1 -0
  815. package/dist/index.d.ts +1 -1
  816. package/dist/index.js +312 -22
  817. package/dist/lib/fuzzy.d.ts +16 -0
  818. package/dist/lib/fuzzy.test.d.ts +1 -0
  819. package/dist/lib/installer.d.ts +6 -7
  820. package/dist/lib/llm.d.ts +38 -0
  821. package/dist/lib/llm.test.d.ts +1 -0
  822. package/dist/lib/lock.d.ts +22 -0
  823. package/dist/lib/lock.test.d.ts +1 -0
  824. package/dist/lib/registry.d.ts +22 -1
  825. package/dist/lib/scheduler.d.ts +20 -0
  826. package/dist/lib/scheduler.test.d.ts +1 -0
  827. package/dist/lib/strip.d.ts +20 -0
  828. package/dist/lib/strip.test.d.ts +1 -0
  829. package/dist/lib/synonyms.d.ts +12 -0
  830. package/dist/lib/synonyms.test.d.ts +1 -0
  831. package/dist/lib/workflow-runner.d.ts +22 -0
  832. package/dist/server/auth.d.ts +4 -2
  833. package/package.json +2 -1
  834. package/connectors/connect-huggingface/src/api/example.ts +0 -48
  835. package/connectors/connect-yousign/CLAUDE.md +0 -48
  836. package/connectors/connect-yousign/package.json +0 -52
  837. package/connectors/connect-yousign/src/api/client.ts +0 -119
  838. package/connectors/connect-yousign/src/api/index.ts +0 -221
  839. package/connectors/connect-yousign/src/cli/index.ts +0 -555
  840. package/connectors/connect-yousign/src/index.ts +0 -21
  841. package/connectors/connect-yousign/src/types/index.ts +0 -275
  842. package/connectors/connect-yousign/src/utils/config.ts +0 -121
  843. package/connectors/connect-yousign/tsconfig.json +0 -16
package/bin/index.js CHANGED
@@ -4,6 +4,7 @@ var __create = Object.create;
4
4
  var __getProtoOf = Object.getPrototypeOf;
5
5
  var __defProp = Object.defineProperty;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
9
  var __toESM = (mod, isNodeMode, target) => {
9
10
  target = mod != null ? __create(__getProtoOf(mod)) : {};
@@ -16,6 +17,20 @@ var __toESM = (mod, isNodeMode, target) => {
16
17
  });
17
18
  return to;
18
19
  };
20
+ var __moduleCache = /* @__PURE__ */ new WeakMap;
21
+ var __toCommonJS = (from) => {
22
+ var entry = __moduleCache.get(from), desc;
23
+ if (entry)
24
+ return entry;
25
+ entry = __defProp({}, "__esModule", { value: true });
26
+ if (from && typeof from === "object" || typeof from === "function")
27
+ __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
28
+ get: () => from[key],
29
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
30
+ }));
31
+ __moduleCache.set(from, entry);
32
+ return entry;
33
+ };
19
34
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
20
35
  var __export = (target, all) => {
21
36
  for (var name in all)
@@ -1868,16 +1883,820 @@ var require_commander = __commonJS((exports) => {
1868
1883
  exports.InvalidOptionArgumentError = InvalidArgumentError;
1869
1884
  });
1870
1885
 
1886
+ // src/lib/llm.ts
1887
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
1888
+ import { join } from "path";
1889
+ import { homedir } from "os";
1890
+ function getLlmConfigPath() {
1891
+ return join(homedir(), ".connectors", "llm.json");
1892
+ }
1893
+ function getLlmConfig() {
1894
+ const path = getLlmConfigPath();
1895
+ if (!existsSync(path))
1896
+ return null;
1897
+ try {
1898
+ return JSON.parse(readFileSync(path, "utf-8"));
1899
+ } catch {
1900
+ return null;
1901
+ }
1902
+ }
1903
+ function saveLlmConfig(config) {
1904
+ const dir = join(homedir(), ".connectors");
1905
+ mkdirSync(dir, { recursive: true });
1906
+ writeFileSync(getLlmConfigPath(), JSON.stringify(config, null, 2));
1907
+ }
1908
+ function setLlmStrip(enabled) {
1909
+ const config = getLlmConfig();
1910
+ if (!config)
1911
+ throw new Error("No LLM config found. Run: connectors llm set --provider <provider> --key <key>");
1912
+ saveLlmConfig({ ...config, strip: enabled });
1913
+ }
1914
+ function maskKey(key) {
1915
+ if (key.length <= 8)
1916
+ return "***";
1917
+ return key.slice(0, 8) + "***";
1918
+ }
1919
+
1920
+ class LLMClient {
1921
+ config;
1922
+ constructor(config) {
1923
+ this.config = config;
1924
+ }
1925
+ static fromConfig() {
1926
+ const config = getLlmConfig();
1927
+ if (!config)
1928
+ return null;
1929
+ return new LLMClient(config);
1930
+ }
1931
+ async complete(prompt, content) {
1932
+ const start = Date.now();
1933
+ const { provider, model, api_key } = this.config;
1934
+ if (provider === "anthropic") {
1935
+ return this._anthropicComplete(prompt, content, start);
1936
+ }
1937
+ const baseUrl = PROVIDER_BASE_URLS[provider];
1938
+ const response = await fetch(`${baseUrl}/chat/completions`, {
1939
+ method: "POST",
1940
+ headers: {
1941
+ "Content-Type": "application/json",
1942
+ Authorization: `Bearer ${api_key}`
1943
+ },
1944
+ body: JSON.stringify({
1945
+ model,
1946
+ messages: [
1947
+ { role: "system", content: prompt },
1948
+ { role: "user", content }
1949
+ ],
1950
+ temperature: 0,
1951
+ max_tokens: 4096
1952
+ })
1953
+ });
1954
+ if (!response.ok) {
1955
+ const error = await response.text();
1956
+ throw new Error(`LLM request failed (${provider} ${response.status}): ${error}`);
1957
+ }
1958
+ const data = await response.json();
1959
+ return {
1960
+ content: data.choices[0].message.content,
1961
+ provider,
1962
+ model,
1963
+ latency_ms: Date.now() - start
1964
+ };
1965
+ }
1966
+ async _anthropicComplete(prompt, content, start) {
1967
+ const { model, api_key } = this.config;
1968
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
1969
+ method: "POST",
1970
+ headers: {
1971
+ "Content-Type": "application/json",
1972
+ "x-api-key": api_key,
1973
+ "anthropic-version": "2023-06-01"
1974
+ },
1975
+ body: JSON.stringify({
1976
+ model,
1977
+ system: prompt,
1978
+ messages: [{ role: "user", content }],
1979
+ max_tokens: 4096
1980
+ })
1981
+ });
1982
+ if (!response.ok) {
1983
+ const error = await response.text();
1984
+ throw new Error(`LLM request failed (anthropic ${response.status}): ${error}`);
1985
+ }
1986
+ const data = await response.json();
1987
+ return {
1988
+ content: data.content[0].text,
1989
+ provider: "anthropic",
1990
+ model,
1991
+ latency_ms: Date.now() - start
1992
+ };
1993
+ }
1994
+ }
1995
+ var PROVIDER_BASE_URLS, PROVIDER_DEFAULTS;
1996
+ var init_llm = __esm(() => {
1997
+ PROVIDER_BASE_URLS = {
1998
+ cerebras: "https://api.cerebras.ai/v1",
1999
+ groq: "https://api.groq.com/openai/v1",
2000
+ openai: "https://api.openai.com/v1"
2001
+ };
2002
+ PROVIDER_DEFAULTS = {
2003
+ cerebras: { model: "qwen-3-32b" },
2004
+ groq: { model: "llama-3.3-70b-versatile" },
2005
+ openai: { model: "gpt-4o-mini" },
2006
+ anthropic: { model: "claude-haiku-4-5-20251001" }
2007
+ };
2008
+ });
2009
+
2010
+ // src/db/database.ts
2011
+ var exports_database = {};
2012
+ __export(exports_database, {
2013
+ shortUuid: () => shortUuid,
2014
+ now: () => now,
2015
+ getDatabase: () => getDatabase,
2016
+ closeDatabase: () => closeDatabase
2017
+ });
2018
+ import { Database } from "bun:sqlite";
2019
+ import { join as join2 } from "path";
2020
+ import { homedir as homedir2 } from "os";
2021
+ import { mkdirSync as mkdirSync2 } from "fs";
2022
+ function getDatabase(path) {
2023
+ if (_db)
2024
+ return _db;
2025
+ const dbPath = path ?? DB_PATH;
2026
+ mkdirSync2(join2(dbPath, ".."), { recursive: true });
2027
+ _db = new Database(dbPath);
2028
+ _db.run("PRAGMA journal_mode = WAL");
2029
+ migrate(_db);
2030
+ return _db;
2031
+ }
2032
+ function closeDatabase() {
2033
+ _db?.close();
2034
+ _db = null;
2035
+ }
2036
+ function now() {
2037
+ return new Date().toISOString();
2038
+ }
2039
+ function shortUuid() {
2040
+ return crypto.randomUUID().slice(0, 8);
2041
+ }
2042
+ function migrate(db) {
2043
+ db.run(`
2044
+ CREATE TABLE IF NOT EXISTS agents (
2045
+ id TEXT PRIMARY KEY,
2046
+ name TEXT UNIQUE NOT NULL,
2047
+ session_id TEXT,
2048
+ role TEXT NOT NULL DEFAULT 'agent',
2049
+ last_seen_at TEXT NOT NULL,
2050
+ created_at TEXT NOT NULL
2051
+ )
2052
+ `);
2053
+ db.run(`
2054
+ CREATE TABLE IF NOT EXISTS resource_locks (
2055
+ id TEXT PRIMARY KEY,
2056
+ resource_type TEXT NOT NULL CHECK(resource_type IN ('connector', 'agent', 'profile', 'token')),
2057
+ resource_id TEXT NOT NULL,
2058
+ agent_id TEXT NOT NULL,
2059
+ lock_type TEXT NOT NULL DEFAULT 'exclusive' CHECK(lock_type IN ('advisory', 'exclusive')),
2060
+ locked_at TEXT NOT NULL DEFAULT (datetime('now')),
2061
+ expires_at TEXT NOT NULL
2062
+ )
2063
+ `);
2064
+ db.run(`
2065
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_resource_locks_exclusive
2066
+ ON resource_locks(resource_type, resource_id)
2067
+ WHERE lock_type = 'exclusive'
2068
+ `);
2069
+ db.run(`CREATE INDEX IF NOT EXISTS idx_resource_locks_agent ON resource_locks(agent_id)`);
2070
+ db.run(`CREATE INDEX IF NOT EXISTS idx_resource_locks_expires ON resource_locks(expires_at)`);
2071
+ db.run(`
2072
+ CREATE TABLE IF NOT EXISTS connector_rate_usage (
2073
+ agent_id TEXT NOT NULL,
2074
+ connector TEXT NOT NULL,
2075
+ window_start TEXT NOT NULL,
2076
+ call_count INTEGER NOT NULL DEFAULT 0,
2077
+ PRIMARY KEY (agent_id, connector, window_start)
2078
+ )
2079
+ `);
2080
+ db.run(`CREATE INDEX IF NOT EXISTS idx_rate_usage_window ON connector_rate_usage(connector, window_start)`);
2081
+ db.run(`
2082
+ CREATE TABLE IF NOT EXISTS connector_jobs (
2083
+ id TEXT PRIMARY KEY,
2084
+ name TEXT UNIQUE NOT NULL,
2085
+ connector TEXT NOT NULL,
2086
+ command TEXT NOT NULL,
2087
+ args TEXT NOT NULL DEFAULT '[]',
2088
+ cron TEXT NOT NULL,
2089
+ enabled INTEGER NOT NULL DEFAULT 1,
2090
+ strip INTEGER NOT NULL DEFAULT 0,
2091
+ created_at TEXT NOT NULL,
2092
+ last_run_at TEXT
2093
+ )
2094
+ `);
2095
+ db.run(`CREATE INDEX IF NOT EXISTS idx_jobs_enabled ON connector_jobs(enabled)`);
2096
+ db.run(`
2097
+ CREATE TABLE IF NOT EXISTS connector_job_runs (
2098
+ id TEXT PRIMARY KEY,
2099
+ job_id TEXT NOT NULL REFERENCES connector_jobs(id) ON DELETE CASCADE,
2100
+ started_at TEXT NOT NULL,
2101
+ finished_at TEXT,
2102
+ exit_code INTEGER,
2103
+ raw_output TEXT,
2104
+ stripped_output TEXT
2105
+ )
2106
+ `);
2107
+ db.run(`CREATE INDEX IF NOT EXISTS idx_job_runs_job ON connector_job_runs(job_id, started_at DESC)`);
2108
+ db.run(`
2109
+ CREATE TABLE IF NOT EXISTS connector_workflows (
2110
+ id TEXT PRIMARY KEY,
2111
+ name TEXT UNIQUE NOT NULL,
2112
+ steps TEXT NOT NULL DEFAULT '[]',
2113
+ enabled INTEGER NOT NULL DEFAULT 1,
2114
+ created_at TEXT NOT NULL
2115
+ )
2116
+ `);
2117
+ db.run(`
2118
+ CREATE TABLE IF NOT EXISTS connector_usage (
2119
+ id TEXT PRIMARY KEY,
2120
+ connector TEXT NOT NULL,
2121
+ action TEXT NOT NULL,
2122
+ agent_id TEXT,
2123
+ timestamp TEXT NOT NULL
2124
+ )
2125
+ `);
2126
+ db.run(`CREATE INDEX IF NOT EXISTS idx_usage_connector ON connector_usage(connector, timestamp DESC)`);
2127
+ db.run(`
2128
+ CREATE TABLE IF NOT EXISTS connector_promotions (
2129
+ connector TEXT UNIQUE NOT NULL,
2130
+ promoted_at TEXT NOT NULL
2131
+ )
2132
+ `);
2133
+ }
2134
+ var DB_DIR, DB_PATH, _db = null;
2135
+ var init_database = __esm(() => {
2136
+ DB_DIR = join2(homedir2(), ".connectors");
2137
+ DB_PATH = join2(DB_DIR, "connectors.db");
2138
+ });
2139
+
2140
+ // src/db/jobs.ts
2141
+ function rowToJob(row) {
2142
+ return {
2143
+ ...row,
2144
+ args: JSON.parse(row.args || "[]"),
2145
+ enabled: row.enabled === 1,
2146
+ strip: row.strip === 1
2147
+ };
2148
+ }
2149
+ function createJob(input, db) {
2150
+ const d = db ?? getDatabase();
2151
+ const id = shortUuid();
2152
+ const ts = now();
2153
+ d.run("INSERT INTO connector_jobs (id, name, connector, command, args, cron, enabled, strip, created_at) VALUES (?, ?, ?, ?, ?, ?, 1, ?, ?)", [id, input.name, input.connector, input.command, JSON.stringify(input.args ?? []), input.cron, input.strip ? 1 : 0, ts]);
2154
+ return getJob(id, d);
2155
+ }
2156
+ function getJob(id, db) {
2157
+ const d = db ?? getDatabase();
2158
+ const row = d.query("SELECT * FROM connector_jobs WHERE id = ?").get(id);
2159
+ return row ? rowToJob(row) : null;
2160
+ }
2161
+ function getJobByName(name, db) {
2162
+ const d = db ?? getDatabase();
2163
+ const row = d.query("SELECT * FROM connector_jobs WHERE name = ?").get(name);
2164
+ return row ? rowToJob(row) : null;
2165
+ }
2166
+ function listJobs(db) {
2167
+ const d = db ?? getDatabase();
2168
+ return d.query("SELECT * FROM connector_jobs ORDER BY name").all().map(rowToJob);
2169
+ }
2170
+ function listEnabledJobs(db) {
2171
+ const d = db ?? getDatabase();
2172
+ return d.query("SELECT * FROM connector_jobs WHERE enabled = 1").all().map(rowToJob);
2173
+ }
2174
+ function updateJob(id, input, db) {
2175
+ const d = db ?? getDatabase();
2176
+ const sets = [];
2177
+ const params = [];
2178
+ if (input.name !== undefined) {
2179
+ sets.push("name = ?");
2180
+ params.push(input.name);
2181
+ }
2182
+ if (input.connector !== undefined) {
2183
+ sets.push("connector = ?");
2184
+ params.push(input.connector);
2185
+ }
2186
+ if (input.command !== undefined) {
2187
+ sets.push("command = ?");
2188
+ params.push(input.command);
2189
+ }
2190
+ if (input.args !== undefined) {
2191
+ sets.push("args = ?");
2192
+ params.push(JSON.stringify(input.args));
2193
+ }
2194
+ if (input.cron !== undefined) {
2195
+ sets.push("cron = ?");
2196
+ params.push(input.cron);
2197
+ }
2198
+ if (input.enabled !== undefined) {
2199
+ sets.push("enabled = ?");
2200
+ params.push(input.enabled ? 1 : 0);
2201
+ }
2202
+ if (input.strip !== undefined) {
2203
+ sets.push("strip = ?");
2204
+ params.push(input.strip ? 1 : 0);
2205
+ }
2206
+ if (sets.length === 0)
2207
+ return getJob(id, d);
2208
+ params.push(id);
2209
+ d.run(`UPDATE connector_jobs SET ${sets.join(", ")} WHERE id = ?`, params);
2210
+ return getJob(id, d);
2211
+ }
2212
+ function deleteJob(id, db) {
2213
+ const d = db ?? getDatabase();
2214
+ return d.run("DELETE FROM connector_jobs WHERE id = ?", [id]).changes > 0;
2215
+ }
2216
+ function touchJobLastRun(id, db) {
2217
+ const d = db ?? getDatabase();
2218
+ d.run("UPDATE connector_jobs SET last_run_at = ? WHERE id = ?", [now(), id]);
2219
+ }
2220
+ function createJobRun(jobId, db) {
2221
+ const d = db ?? getDatabase();
2222
+ const id = shortUuid();
2223
+ const ts = now();
2224
+ d.run("INSERT INTO connector_job_runs (id, job_id, started_at) VALUES (?, ?, ?)", [id, jobId, ts]);
2225
+ return { id, job_id: jobId, started_at: ts, finished_at: null, exit_code: null, raw_output: null, stripped_output: null };
2226
+ }
2227
+ function finishJobRun(id, result, db) {
2228
+ const d = db ?? getDatabase();
2229
+ d.run("UPDATE connector_job_runs SET finished_at = ?, exit_code = ?, raw_output = ?, stripped_output = ? WHERE id = ?", [now(), result.exit_code, result.raw_output, result.stripped_output ?? null, id]);
2230
+ }
2231
+ function listJobRuns(jobId, limit = 20, db) {
2232
+ const d = db ?? getDatabase();
2233
+ return d.query("SELECT * FROM connector_job_runs WHERE job_id = ? ORDER BY started_at DESC LIMIT ?").all(jobId, limit);
2234
+ }
2235
+ var init_jobs = __esm(() => {
2236
+ init_database();
2237
+ });
2238
+
2239
+ // src/db/workflows.ts
2240
+ function rowToWorkflow(row) {
2241
+ return {
2242
+ ...row,
2243
+ steps: JSON.parse(row.steps || "[]"),
2244
+ enabled: row.enabled === 1
2245
+ };
2246
+ }
2247
+ function createWorkflow(input, db) {
2248
+ const d = db ?? getDatabase();
2249
+ const id = shortUuid();
2250
+ d.run("INSERT INTO connector_workflows (id, name, steps, enabled, created_at) VALUES (?, ?, ?, 1, ?)", [id, input.name, JSON.stringify(input.steps), now()]);
2251
+ return getWorkflow(id, d);
2252
+ }
2253
+ function getWorkflow(id, db) {
2254
+ const d = db ?? getDatabase();
2255
+ const row = d.query("SELECT * FROM connector_workflows WHERE id = ?").get(id);
2256
+ return row ? rowToWorkflow(row) : null;
2257
+ }
2258
+ function getWorkflowByName(name, db) {
2259
+ const d = db ?? getDatabase();
2260
+ const row = d.query("SELECT * FROM connector_workflows WHERE name = ?").get(name);
2261
+ return row ? rowToWorkflow(row) : null;
2262
+ }
2263
+ function listWorkflows(db) {
2264
+ const d = db ?? getDatabase();
2265
+ return d.query("SELECT * FROM connector_workflows ORDER BY name").all().map(rowToWorkflow);
2266
+ }
2267
+ function deleteWorkflow(id, db) {
2268
+ const d = db ?? getDatabase();
2269
+ return d.run("DELETE FROM connector_workflows WHERE id = ?", [id]).changes > 0;
2270
+ }
2271
+ var init_workflows = __esm(() => {
2272
+ init_database();
2273
+ });
2274
+
2275
+ // src/lib/strip.ts
2276
+ async function maybeStrip(output, _type = "json") {
2277
+ const config = getLlmConfig();
2278
+ if (!config?.strip)
2279
+ return output;
2280
+ if (!output || output.trim().length === 0)
2281
+ return output;
2282
+ const client = LLMClient.fromConfig();
2283
+ if (!client)
2284
+ return output;
2285
+ try {
2286
+ const result = await client.complete(STRIP_PROMPT, output);
2287
+ return result.content.trim();
2288
+ } catch {
2289
+ return output;
2290
+ }
2291
+ }
2292
+ var STRIP_PROMPT = `You are a data extraction assistant. Your job is to take raw API output and return ONLY the essential, structured data.
2293
+
2294
+ Rules:
2295
+ - Return valid JSON only (no markdown, no explanation)
2296
+ - Remove pagination metadata, rate limit headers, empty fields, null values
2297
+ - Keep all meaningful data fields
2298
+ - If the input is already minimal, return it unchanged
2299
+ - If input is not JSON, extract key facts as a JSON object
2300
+ - Never truncate actual data values`;
2301
+ var init_strip = __esm(() => {
2302
+ init_llm();
2303
+ });
2304
+
2305
+ // src/lib/scheduler.ts
2306
+ var exports_scheduler = {};
2307
+ __export(exports_scheduler, {
2308
+ triggerJob: () => triggerJob,
2309
+ stopScheduler: () => stopScheduler,
2310
+ startScheduler: () => startScheduler
2311
+ });
2312
+ import { spawn } from "child_process";
2313
+ function cronMatches(cron, d) {
2314
+ const parts = cron.trim().split(/\s+/);
2315
+ if (parts.length !== 5)
2316
+ return false;
2317
+ const [min, hour, dom, mon, dow] = parts;
2318
+ function matches(field, value, min_v, max_v) {
2319
+ if (field === "*")
2320
+ return true;
2321
+ if (field.startsWith("*/")) {
2322
+ const step = parseInt(field.slice(2));
2323
+ return value % step === 0;
2324
+ }
2325
+ if (field.includes("-")) {
2326
+ const [a, b] = field.split("-").map(Number);
2327
+ return value >= a && value <= b;
2328
+ }
2329
+ if (field.includes(",")) {
2330
+ return field.split(",").map(Number).includes(value);
2331
+ }
2332
+ return parseInt(field) === value;
2333
+ }
2334
+ return matches(min, d.getMinutes(), 0, 59) && matches(hour, d.getHours(), 0, 23) && matches(dom, d.getDate(), 1, 31) && matches(mon, d.getMonth() + 1, 1, 12) && matches(dow, d.getDay(), 0, 6);
2335
+ }
2336
+ async function runConnectorCommand(connector, command, args) {
2337
+ return new Promise((resolve) => {
2338
+ const cmdArgs = [connector, command, ...args, "--format", "json"];
2339
+ const proc = spawn("connectors", ["run", ...cmdArgs], { shell: false });
2340
+ let output = "";
2341
+ proc.stdout.on("data", (d) => {
2342
+ output += d.toString();
2343
+ });
2344
+ proc.stderr.on("data", (d) => {
2345
+ output += d.toString();
2346
+ });
2347
+ proc.on("close", (code) => resolve({ exitCode: code ?? 1, output }));
2348
+ proc.on("error", () => resolve({ exitCode: 1, output: `Failed to spawn connectors run` }));
2349
+ setTimeout(() => {
2350
+ proc.kill();
2351
+ resolve({ exitCode: 124, output: output + `
2352
+ [timeout]` });
2353
+ }, 60000);
2354
+ });
2355
+ }
2356
+ async function executeJob(job, db) {
2357
+ const run = createJobRun(job.id, db);
2358
+ try {
2359
+ const { exitCode, output } = await runConnectorCommand(job.connector, job.command, job.args);
2360
+ const stripped = job.strip ? await maybeStrip(output) : undefined;
2361
+ finishJobRun(run.id, { exit_code: exitCode, raw_output: output, stripped_output: stripped }, db);
2362
+ touchJobLastRun(job.id, db);
2363
+ } catch (e) {
2364
+ finishJobRun(run.id, { exit_code: 1, raw_output: String(e) }, db);
2365
+ }
2366
+ }
2367
+ function startScheduler(db) {
2368
+ if (_interval)
2369
+ return;
2370
+ _interval = setInterval(async () => {
2371
+ const now2 = new Date;
2372
+ const currentMinute = now2.getMinutes() + now2.getHours() * 60;
2373
+ if (currentMinute === _lastCheckedMinute)
2374
+ return;
2375
+ _lastCheckedMinute = currentMinute;
2376
+ const jobs = listEnabledJobs(db);
2377
+ for (const job of jobs) {
2378
+ if (cronMatches(job.cron, now2)) {
2379
+ executeJob(job, db).catch(() => {});
2380
+ }
2381
+ }
2382
+ }, 30000);
2383
+ }
2384
+ function stopScheduler() {
2385
+ if (_interval) {
2386
+ clearInterval(_interval);
2387
+ _interval = null;
2388
+ _lastCheckedMinute = -1;
2389
+ }
2390
+ }
2391
+ async function triggerJob(job, db) {
2392
+ const run = createJobRun(job.id, db);
2393
+ const { exitCode, output } = await runConnectorCommand(job.connector, job.command, job.args);
2394
+ const stripped = job.strip ? await maybeStrip(output) : undefined;
2395
+ finishJobRun(run.id, { exit_code: exitCode, raw_output: output, stripped_output: stripped }, db);
2396
+ touchJobLastRun(job.id, db);
2397
+ return { run_id: run.id, exit_code: exitCode, output: stripped ?? output };
2398
+ }
2399
+ var _interval = null, _lastCheckedMinute = -1;
2400
+ var init_scheduler = __esm(() => {
2401
+ init_jobs();
2402
+ init_strip();
2403
+ });
2404
+
2405
+ // src/lib/workflow-runner.ts
2406
+ import { spawn as spawn2 } from "child_process";
2407
+ async function runStep(step, previousOutput) {
2408
+ return new Promise((resolve) => {
2409
+ const args = [...step.args ?? []];
2410
+ if (previousOutput && previousOutput.trim()) {
2411
+ args.push("--input", previousOutput.trim().slice(0, 4096));
2412
+ }
2413
+ const cmdArgs = ["run", step.connector, step.command, ...args, "--format", "json"];
2414
+ const proc = spawn2("connectors", cmdArgs, { shell: false });
2415
+ let output = "";
2416
+ proc.stdout.on("data", (d) => {
2417
+ output += d.toString();
2418
+ });
2419
+ proc.stderr.on("data", (d) => {
2420
+ output += d.toString();
2421
+ });
2422
+ proc.on("close", (code) => resolve({ exitCode: code ?? 1, output }));
2423
+ proc.on("error", () => resolve({ exitCode: 1, output: "Failed to spawn connectors" }));
2424
+ setTimeout(() => {
2425
+ proc.kill();
2426
+ resolve({ exitCode: 124, output: output + `
2427
+ [timeout]` });
2428
+ }, 60000);
2429
+ });
2430
+ }
2431
+ async function runWorkflow(workflow) {
2432
+ const results = [];
2433
+ let previousOutput;
2434
+ let success = true;
2435
+ for (let i = 0;i < workflow.steps.length; i++) {
2436
+ const step = workflow.steps[i];
2437
+ const { exitCode, output } = await runStep(step, previousOutput);
2438
+ const stripped = await maybeStrip(output);
2439
+ results.push({ step: i + 1, connector: step.connector, command: step.command, exit_code: exitCode, output: stripped });
2440
+ if (exitCode !== 0) {
2441
+ success = false;
2442
+ break;
2443
+ }
2444
+ previousOutput = stripped;
2445
+ }
2446
+ return {
2447
+ workflow_id: workflow.id,
2448
+ workflow_name: workflow.name,
2449
+ steps: results,
2450
+ success,
2451
+ final_output: results[results.length - 1]?.output ?? ""
2452
+ };
2453
+ }
2454
+ var init_workflow_runner = __esm(() => {
2455
+ init_strip();
2456
+ });
2457
+
2458
+ // src/lib/fuzzy.ts
2459
+ function levenshtein(a, b) {
2460
+ const m = a.length;
2461
+ const n = b.length;
2462
+ if (m === 0)
2463
+ return n;
2464
+ if (n === 0)
2465
+ return m;
2466
+ let prev = new Array(n + 1);
2467
+ let curr = new Array(n + 1);
2468
+ for (let j = 0;j <= n; j++)
2469
+ prev[j] = j;
2470
+ for (let i = 1;i <= m; i++) {
2471
+ curr[0] = i;
2472
+ for (let j = 1;j <= n; j++) {
2473
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
2474
+ curr[j] = Math.min(curr[j - 1] + 1, prev[j] + 1, prev[j - 1] + cost);
2475
+ }
2476
+ [prev, curr] = [curr, prev];
2477
+ }
2478
+ return prev[n];
2479
+ }
2480
+ function bestFuzzyScore(token, candidates, maxDistance = 2) {
2481
+ if (token.length < 3)
2482
+ return 0;
2483
+ let bestDist = maxDistance + 1;
2484
+ for (const c of candidates) {
2485
+ if (Math.abs(token.length - c.length) > maxDistance)
2486
+ continue;
2487
+ const d = levenshtein(token, c);
2488
+ if (d < bestDist)
2489
+ bestDist = d;
2490
+ if (d === 0)
2491
+ return maxDistance + 1;
2492
+ }
2493
+ if (bestDist > maxDistance)
2494
+ return 0;
2495
+ return maxDistance - bestDist + 1;
2496
+ }
2497
+
2498
+ // src/lib/synonyms.ts
2499
+ function expandQuery(tokens) {
2500
+ const synonyms = new Set;
2501
+ for (const token of tokens) {
2502
+ const matches = SYNONYM_MAP[token];
2503
+ if (matches) {
2504
+ for (const syn of matches) {
2505
+ if (!tokens.includes(syn))
2506
+ synonyms.add(syn);
2507
+ }
2508
+ }
2509
+ for (const [key, values] of Object.entries(SYNONYM_MAP)) {
2510
+ if (values.includes(token) && !tokens.includes(key)) {
2511
+ synonyms.add(key);
2512
+ }
2513
+ }
2514
+ }
2515
+ return { original: tokens, expanded: [...synonyms] };
2516
+ }
2517
+ var SYNONYM_MAP;
2518
+ var init_synonyms = __esm(() => {
2519
+ SYNONYM_MAP = {
2520
+ email: ["smtp", "mail", "inbox", "resend", "ses"],
2521
+ chat: ["messaging", "im", "slack", "discord", "teams"],
2522
+ sms: ["text", "twilio", "messaging"],
2523
+ payment: ["billing", "invoicing", "commerce", "checkout", "stripe"],
2524
+ payments: ["billing", "invoicing", "commerce", "checkout", "stripe"],
2525
+ ecommerce: ["shop", "store", "commerce", "shopify"],
2526
+ finance: ["banking", "accounting", "invoicing"],
2527
+ crypto: ["blockchain", "web3", "wallet"],
2528
+ ai: ["llm", "ml", "model", "gpt", "claude", "anthropic", "openai"],
2529
+ llm: ["ai", "model", "gpt", "claude"],
2530
+ auth: ["oauth", "sso", "login", "identity", "authentication"],
2531
+ database: ["db", "sql", "nosql", "postgres", "mongo", "supabase"],
2532
+ deploy: ["hosting", "infrastructure", "ci", "cd", "vercel"],
2533
+ storage: ["files", "drive", "s3", "bucket", "upload"],
2534
+ cloud: ["aws", "gcp", "azure", "infrastructure"],
2535
+ api: ["rest", "graphql", "endpoint", "webhook"],
2536
+ monitoring: ["logs", "observability", "alerting", "datadog", "sentry"],
2537
+ ci: ["cd", "deploy", "pipeline", "github", "actions"],
2538
+ crm: ["sales", "leads", "contacts", "hubspot", "salesforce"],
2539
+ analytics: ["data", "metrics", "tracking", "mixpanel", "amplitude"],
2540
+ project: ["task", "issue", "board", "jira", "linear", "asana"],
2541
+ docs: ["documentation", "wiki", "notion", "confluence"],
2542
+ design: ["figma", "sketch", "ui", "ux"],
2543
+ security: ["auth", "encryption", "compliance", "vault"]
2544
+ };
2545
+ });
2546
+
1871
2547
  // src/lib/registry.ts
1872
- import { existsSync, readFileSync } from "fs";
1873
- import { join, dirname } from "path";
2548
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
2549
+ import { join as join3, dirname } from "path";
1874
2550
  import { fileURLToPath } from "url";
1875
2551
  function getConnectorsByCategory(category) {
1876
2552
  return CONNECTORS.filter((c) => c.category === category);
1877
2553
  }
1878
- function searchConnectors(query) {
1879
- const q = query.toLowerCase();
1880
- return CONNECTORS.filter((c) => c.name.toLowerCase().includes(q) || c.displayName.toLowerCase().includes(q) || c.description.toLowerCase().includes(q) || c.tags.some((t) => t.includes(q)));
2554
+ function searchConnectors(query, context) {
2555
+ const tokens = query.toLowerCase().trim().split(/\s+/).filter(Boolean);
2556
+ if (tokens.length === 0)
2557
+ return [];
2558
+ const limit = context?.limit ?? 20;
2559
+ const installed = new Set(context?.installed ?? []);
2560
+ const promoted = new Set(context?.promoted ?? []);
2561
+ const usage = context?.usage ?? new Map;
2562
+ const results = [];
2563
+ for (const c of CONNECTORS) {
2564
+ const nameLow = c.name.toLowerCase();
2565
+ const displayLow = c.displayName.toLowerCase();
2566
+ const descLow = c.description.toLowerCase();
2567
+ const tagsLow = c.tags.map((t) => t.toLowerCase());
2568
+ let score = 0;
2569
+ const matchReasons = [];
2570
+ let allTokensMatch = true;
2571
+ for (const token of tokens) {
2572
+ let tokenMatched = false;
2573
+ if (nameLow === token) {
2574
+ score += 100;
2575
+ matchReasons.push(`name="${token}"`);
2576
+ tokenMatched = true;
2577
+ } else if (nameLow.includes(token)) {
2578
+ score += 10;
2579
+ matchReasons.push(`name~${token}`);
2580
+ tokenMatched = true;
2581
+ }
2582
+ if (tagsLow.includes(token)) {
2583
+ score += 8;
2584
+ if (!tokenMatched)
2585
+ matchReasons.push(`tag="${token}"`);
2586
+ tokenMatched = true;
2587
+ } else if (tagsLow.some((t) => t.includes(token))) {
2588
+ score += 5;
2589
+ if (!tokenMatched)
2590
+ matchReasons.push(`tag~${token}`);
2591
+ tokenMatched = true;
2592
+ }
2593
+ if (displayLow.includes(token)) {
2594
+ score += 3;
2595
+ if (!tokenMatched)
2596
+ matchReasons.push(`display~${token}`);
2597
+ tokenMatched = true;
2598
+ }
2599
+ if (descLow.includes(token)) {
2600
+ score += 1;
2601
+ if (!tokenMatched)
2602
+ matchReasons.push(`desc~${token}`);
2603
+ tokenMatched = true;
2604
+ }
2605
+ if (!tokenMatched && token.length >= 3) {
2606
+ const nameFuzzy = bestFuzzyScore(token, [nameLow], 1);
2607
+ if (nameFuzzy > 0) {
2608
+ score += nameFuzzy * 6;
2609
+ matchReasons.push(`fuzzy:name\u2248${token}`);
2610
+ tokenMatched = true;
2611
+ }
2612
+ if (!tokenMatched) {
2613
+ const tagFuzzy = bestFuzzyScore(token, tagsLow, 2);
2614
+ if (tagFuzzy > 0) {
2615
+ score += tagFuzzy * 3;
2616
+ matchReasons.push(`fuzzy:tag\u2248${token}`);
2617
+ tokenMatched = true;
2618
+ }
2619
+ }
2620
+ if (!tokenMatched) {
2621
+ const displayFuzzy = bestFuzzyScore(token, [displayLow], 2);
2622
+ if (displayFuzzy > 0) {
2623
+ score += displayFuzzy * 2;
2624
+ matchReasons.push(`fuzzy:display\u2248${token}`);
2625
+ tokenMatched = true;
2626
+ }
2627
+ }
2628
+ }
2629
+ if (!tokenMatched) {
2630
+ allTokensMatch = false;
2631
+ break;
2632
+ }
2633
+ }
2634
+ if (!allTokensMatch)
2635
+ continue;
2636
+ const badges = [];
2637
+ if (installed.has(c.name)) {
2638
+ score += 50;
2639
+ badges.push("installed");
2640
+ }
2641
+ if (promoted.has(c.name)) {
2642
+ score += 30;
2643
+ badges.push("promoted");
2644
+ }
2645
+ const usageCount = usage.get(c.name) ?? 0;
2646
+ if (usageCount > 0) {
2647
+ score += Math.min(usageCount * 2, 40);
2648
+ if (usageCount >= 5)
2649
+ badges.push("hot");
2650
+ }
2651
+ results.push({ ...c, score, matchReasons, badges });
2652
+ }
2653
+ const matchedNames = new Set(results.map((r) => r.name));
2654
+ if (results.length < limit) {
2655
+ const { expanded } = expandQuery(tokens);
2656
+ if (expanded.length > 0) {
2657
+ for (const c of CONNECTORS) {
2658
+ if (matchedNames.has(c.name))
2659
+ continue;
2660
+ const nameLow2 = c.name.toLowerCase();
2661
+ const tagsLow2 = c.tags.map((t) => t.toLowerCase());
2662
+ const descLow2 = c.description.toLowerCase();
2663
+ let synScore = 0;
2664
+ const synReasons = [];
2665
+ for (const syn of expanded) {
2666
+ if (nameLow2.includes(syn)) {
2667
+ synScore += 2;
2668
+ synReasons.push(`syn:name~${syn}`);
2669
+ } else if (tagsLow2.some((t) => t.includes(syn))) {
2670
+ synScore += 1;
2671
+ synReasons.push(`syn:tag~${syn}`);
2672
+ } else if (descLow2.includes(syn)) {
2673
+ synScore += 1;
2674
+ synReasons.push(`syn:desc~${syn}`);
2675
+ }
2676
+ }
2677
+ if (synScore > 0) {
2678
+ const badges = [];
2679
+ if (installed.has(c.name)) {
2680
+ synScore += 50;
2681
+ badges.push("installed");
2682
+ }
2683
+ if (promoted.has(c.name)) {
2684
+ synScore += 30;
2685
+ badges.push("promoted");
2686
+ }
2687
+ const usageCount = usage.get(c.name) ?? 0;
2688
+ if (usageCount > 0) {
2689
+ synScore += Math.min(usageCount * 2, 40);
2690
+ if (usageCount >= 5)
2691
+ badges.push("hot");
2692
+ }
2693
+ results.push({ ...c, score: synScore, matchReasons: synReasons, badges });
2694
+ }
2695
+ }
2696
+ }
2697
+ }
2698
+ results.sort((a, b) => b.score - a.score);
2699
+ return results.slice(0, limit);
1881
2700
  }
1882
2701
  function getConnector(name) {
1883
2702
  return CONNECTORS.find((c) => c.name === name);
@@ -1888,17 +2707,17 @@ function loadConnectorVersions() {
1888
2707
  versionsLoaded = true;
1889
2708
  const thisDir = dirname(fileURLToPath(import.meta.url));
1890
2709
  const candidates = [
1891
- join(thisDir, "..", "connectors"),
1892
- join(thisDir, "..", "..", "connectors")
2710
+ join3(thisDir, "..", "connectors"),
2711
+ join3(thisDir, "..", "..", "connectors")
1893
2712
  ];
1894
- const connectorsDir = candidates.find((d) => existsSync(d));
2713
+ const connectorsDir = candidates.find((d) => existsSync2(d));
1895
2714
  if (!connectorsDir)
1896
2715
  return;
1897
2716
  for (const connector of CONNECTORS) {
1898
2717
  try {
1899
- const pkgPath = join(connectorsDir, `connect-${connector.name}`, "package.json");
1900
- if (existsSync(pkgPath)) {
1901
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
2718
+ const pkgPath = join3(connectorsDir, `connect-${connector.name}`, "package.json");
2719
+ if (existsSync2(pkgPath)) {
2720
+ const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
1902
2721
  connector.version = pkg.version || "0.0.0";
1903
2722
  }
1904
2723
  } catch {}
@@ -1906,6 +2725,7 @@ function loadConnectorVersions() {
1906
2725
  }
1907
2726
  var CATEGORIES, CONNECTORS, versionsLoaded = false;
1908
2727
  var init_registry = __esm(() => {
2728
+ init_synonyms();
1909
2729
  CATEGORIES = [
1910
2730
  "AI & ML",
1911
2731
  "Developer Tools",
@@ -6791,13 +7611,6 @@ var init_registry = __esm(() => {
6791
7611
  category: "Business Tools",
6792
7612
  tags: ["e-signature", "contracts", "digital", "documents", "legal"]
6793
7613
  },
6794
- {
6795
- name: "yousign",
6796
- displayName: "Yousign",
6797
- description: "eIDAS-compliant electronic signature API for EU workflows",
6798
- category: "Business Tools",
6799
- tags: ["e-signature", "eidas", "contracts", "documents", "legal", "eu"]
6800
- },
6801
7614
  {
6802
7615
  name: "signl4",
6803
7616
  displayName: "SIGNL4",
@@ -9471,23 +10284,28 @@ var require_cli_spinners = __commonJS((exports, module) => {
9471
10284
  });
9472
10285
 
9473
10286
  // src/lib/installer.ts
9474
- import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync, statSync } from "fs";
9475
- import { join as join2, dirname as dirname2 } from "path";
10287
+ import { existsSync as existsSync3, cpSync, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2, readdirSync, statSync, rmSync } from "fs";
10288
+ import { homedir as homedir3 } from "os";
10289
+ import { join as join4, dirname as dirname2 } from "path";
9476
10290
  import { fileURLToPath as fileURLToPath2 } from "url";
9477
10291
  function resolveConnectorsDir() {
9478
- const fromBin = join2(__dirname2, "..", "connectors");
9479
- if (existsSync2(fromBin))
10292
+ const fromBin = join4(__dirname2, "..", "connectors");
10293
+ if (existsSync3(fromBin))
9480
10294
  return fromBin;
9481
- const fromSrc = join2(__dirname2, "..", "..", "connectors");
9482
- if (existsSync2(fromSrc))
10295
+ const fromSrc = join4(__dirname2, "..", "..", "connectors");
10296
+ if (existsSync3(fromSrc))
9483
10297
  return fromSrc;
9484
10298
  return fromBin;
9485
10299
  }
9486
10300
  function getConnectorPath(name) {
9487
10301
  const connectorName = name.startsWith("connect-") ? name : `connect-${name}`;
9488
- return join2(CONNECTORS_DIR, connectorName);
10302
+ return join4(CONNECTORS_DIR, connectorName);
10303
+ }
10304
+ function connectorExists(name) {
10305
+ return existsSync3(getConnectorPath(name));
9489
10306
  }
9490
10307
  function installConnector(name, options = {}) {
10308
+ const { targetDir = process.cwd(), overwrite = false } = options;
9491
10309
  if (!/^[a-z0-9-]+$/.test(name)) {
9492
10310
  return {
9493
10311
  connector: name,
@@ -9495,35 +10313,91 @@ function installConnector(name, options = {}) {
9495
10313
  error: `Invalid connector name '${name}'`
9496
10314
  };
9497
10315
  }
10316
+ const connectorName = name.startsWith("connect-") ? name : `connect-${name}`;
9498
10317
  const sourcePath = getConnectorPath(name);
9499
- if (!existsSync2(sourcePath)) {
10318
+ const destDir = join4(targetDir, ".connectors");
10319
+ const destPath = join4(destDir, connectorName);
10320
+ if (!existsSync3(sourcePath)) {
9500
10321
  return {
9501
10322
  connector: name,
9502
10323
  success: false,
9503
10324
  error: `Connector '${name}' not found`
9504
10325
  };
9505
10326
  }
9506
- return {
9507
- connector: name,
9508
- success: true,
9509
- path: sourcePath
9510
- };
10327
+ if (existsSync3(destPath) && !overwrite) {
10328
+ return {
10329
+ connector: name,
10330
+ success: false,
10331
+ error: `Already installed. Use --overwrite to replace.`,
10332
+ path: destPath
10333
+ };
10334
+ }
10335
+ try {
10336
+ if (!existsSync3(destDir)) {
10337
+ mkdirSync3(destDir, { recursive: true });
10338
+ }
10339
+ cpSync(sourcePath, destPath, { recursive: true });
10340
+ const homeCredDir = join4(homedir3(), ".connectors", connectorName);
10341
+ if (existsSync3(homeCredDir)) {
10342
+ const filesToCopy = ["credentials.json", "current_profile"];
10343
+ for (const file of filesToCopy) {
10344
+ const src = join4(homeCredDir, file);
10345
+ if (existsSync3(src)) {
10346
+ cpSync(src, join4(destPath, file));
10347
+ }
10348
+ }
10349
+ const profilesDir = join4(homeCredDir, "profiles");
10350
+ if (existsSync3(profilesDir)) {
10351
+ cpSync(profilesDir, join4(destPath, "profiles"), { recursive: true });
10352
+ }
10353
+ }
10354
+ updateConnectorsIndex(destDir);
10355
+ return {
10356
+ connector: name,
10357
+ success: true,
10358
+ path: destPath
10359
+ };
10360
+ } catch (error) {
10361
+ return {
10362
+ connector: name,
10363
+ success: false,
10364
+ error: error instanceof Error ? error.message : "Unknown error"
10365
+ };
10366
+ }
10367
+ }
10368
+ function updateConnectorsIndex(connectorsDir) {
10369
+ const indexPath = join4(connectorsDir, "index.ts");
10370
+ const connectors = readdirSync(connectorsDir).filter((f) => f.startsWith("connect-") && !f.includes("."));
10371
+ const exports = connectors.map((c) => {
10372
+ const name = c.replace("connect-", "");
10373
+ return `export * as ${name} from './${c}/src/index.js';`;
10374
+ }).join(`
10375
+ `);
10376
+ const content = `/**
10377
+ * Auto-generated index of installed connectors
10378
+ * Do not edit manually - run 'connectors install' to update
10379
+ */
10380
+
10381
+ ${exports}
10382
+ `;
10383
+ writeFileSync2(indexPath, content);
9511
10384
  }
9512
- function getInstalledConnectors() {
9513
- if (!existsSync2(CONNECTORS_DIR)) {
10385
+ function getInstalledConnectors(targetDir = process.cwd()) {
10386
+ const connectorsDir = join4(targetDir, ".connectors");
10387
+ if (!existsSync3(connectorsDir)) {
9514
10388
  return [];
9515
10389
  }
9516
- return readdirSync(CONNECTORS_DIR).filter((f) => {
9517
- const fullPath = join2(CONNECTORS_DIR, f);
10390
+ return readdirSync(connectorsDir).filter((f) => {
10391
+ const fullPath = join4(connectorsDir, f);
9518
10392
  return f.startsWith("connect-") && statSync(fullPath).isDirectory();
9519
10393
  }).map((f) => f.replace("connect-", ""));
9520
10394
  }
9521
10395
  function getConnectorDocs(name) {
9522
10396
  const connectorPath = getConnectorPath(name);
9523
- const claudeMdPath = join2(connectorPath, "CLAUDE.md");
9524
- if (!existsSync2(claudeMdPath))
10397
+ const claudeMdPath = join4(connectorPath, "CLAUDE.md");
10398
+ if (!existsSync3(claudeMdPath))
9525
10399
  return null;
9526
- const raw = readFileSync2(claudeMdPath, "utf-8");
10400
+ const raw = readFileSync3(claudeMdPath, "utf-8");
9527
10401
  return {
9528
10402
  overview: extractSection(raw, "Project Overview"),
9529
10403
  auth: extractSection(raw, "Authentication"),
@@ -9560,8 +10434,16 @@ function parseEnvVarsTable(section) {
9560
10434
  }
9561
10435
  return vars;
9562
10436
  }
9563
- function removeConnector(name) {
9564
- return false;
10437
+ function removeConnector(name, targetDir = process.cwd()) {
10438
+ const connectorName = name.startsWith("connect-") ? name : `connect-${name}`;
10439
+ const connectorsDir = join4(targetDir, ".connectors");
10440
+ const connectorPath = join4(connectorsDir, connectorName);
10441
+ if (!existsSync3(connectorPath)) {
10442
+ return false;
10443
+ }
10444
+ rmSync(connectorPath, { recursive: true });
10445
+ updateConnectorsIndex(connectorsDir);
10446
+ return true;
9565
10447
  }
9566
10448
  var __dirname2, CONNECTORS_DIR;
9567
10449
  var init_installer = __esm(() => {
@@ -9569,11 +10451,77 @@ var init_installer = __esm(() => {
9569
10451
  CONNECTORS_DIR = resolveConnectorsDir();
9570
10452
  });
9571
10453
 
10454
+ // src/lib/lock.ts
10455
+ import { openSync, closeSync, unlinkSync, existsSync as existsSync4, statSync as statSync2 } from "fs";
10456
+ import { join as join5 } from "path";
10457
+ import { homedir as homedir4 } from "os";
10458
+ import { mkdirSync as mkdirSync4 } from "fs";
10459
+ function lockPath(connector) {
10460
+ const dir = join5(homedir4(), ".connectors", `connect-${connector}`);
10461
+ mkdirSync4(dir, { recursive: true });
10462
+ return join5(dir, ".write.lock");
10463
+ }
10464
+ function isStale(path) {
10465
+ try {
10466
+ const stat = statSync2(path);
10467
+ return Date.now() - stat.mtimeMs > STALE_LOCK_MS;
10468
+ } catch {
10469
+ return false;
10470
+ }
10471
+ }
10472
+ function tryAcquire(path) {
10473
+ if (existsSync4(path) && isStale(path)) {
10474
+ try {
10475
+ unlinkSync(path);
10476
+ } catch {}
10477
+ }
10478
+ try {
10479
+ const fd = openSync(path, "wx");
10480
+ closeSync(fd);
10481
+ return true;
10482
+ } catch (e) {
10483
+ if (e.code === "EEXIST")
10484
+ return false;
10485
+ throw e;
10486
+ }
10487
+ }
10488
+ function release(path) {
10489
+ try {
10490
+ unlinkSync(path);
10491
+ } catch {}
10492
+ }
10493
+ async function withWriteLock(connector, fn) {
10494
+ const path = lockPath(connector);
10495
+ const deadline = Date.now() + LOCK_TIMEOUT_MS;
10496
+ while (Date.now() < deadline) {
10497
+ if (tryAcquire(path)) {
10498
+ try {
10499
+ return await fn();
10500
+ } finally {
10501
+ release(path);
10502
+ }
10503
+ }
10504
+ await new Promise((resolve) => setTimeout(resolve, LOCK_RETRY_MS));
10505
+ }
10506
+ throw new LockTimeoutError(connector);
10507
+ }
10508
+ var LOCK_TIMEOUT_MS = 5000, LOCK_RETRY_MS = 100, STALE_LOCK_MS = 30000, LockTimeoutError;
10509
+ var init_lock = __esm(() => {
10510
+ LockTimeoutError = class LockTimeoutError extends Error {
10511
+ connector;
10512
+ constructor(connector) {
10513
+ super(`Could not acquire write lock for connector "${connector}" within ${LOCK_TIMEOUT_MS}ms. Another agent may be writing. Try again shortly.`);
10514
+ this.connector = connector;
10515
+ this.name = "LockTimeoutError";
10516
+ }
10517
+ };
10518
+ });
10519
+
9572
10520
  // src/server/auth.ts
9573
- import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync, mkdirSync, readdirSync as readdirSync2, rmSync, statSync as statSync2 } from "fs";
10521
+ import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync5, readdirSync as readdirSync2, rmSync as rmSync2, statSync as statSync3 } from "fs";
9574
10522
  import { randomBytes } from "crypto";
9575
- import { homedir } from "os";
9576
- import { join as join3 } from "path";
10523
+ import { homedir as homedir5 } from "os";
10524
+ import { join as join6 } from "path";
9577
10525
  function getAuthType(name) {
9578
10526
  const docs = getConnectorDocs(name);
9579
10527
  if (!docs?.auth)
@@ -9587,14 +10535,14 @@ function getAuthType(name) {
9587
10535
  }
9588
10536
  function getConnectorConfigDir(name) {
9589
10537
  const connectorName = name.startsWith("connect-") ? name : `connect-${name}`;
9590
- return join3(homedir(), ".connectors", connectorName);
10538
+ return join6(homedir5(), ".connectors", connectorName);
9591
10539
  }
9592
10540
  function getCurrentProfile(name) {
9593
10541
  const configDir = getConnectorConfigDir(name);
9594
- const currentProfileFile = join3(configDir, "current_profile");
9595
- if (existsSync3(currentProfileFile)) {
10542
+ const currentProfileFile = join6(configDir, "current_profile");
10543
+ if (existsSync5(currentProfileFile)) {
9596
10544
  try {
9597
- return readFileSync3(currentProfileFile, "utf-8").trim() || "default";
10545
+ return readFileSync4(currentProfileFile, "utf-8").trim() || "default";
9598
10546
  } catch {
9599
10547
  return "default";
9600
10548
  }
@@ -9606,16 +10554,16 @@ function loadProfileConfig(name) {
9606
10554
  const profile = getCurrentProfile(name);
9607
10555
  let flatConfig = {};
9608
10556
  let dirConfig = {};
9609
- const profileFile = join3(configDir, "profiles", `${profile}.json`);
9610
- if (existsSync3(profileFile)) {
10557
+ const profileFile = join6(configDir, "profiles", `${profile}.json`);
10558
+ if (existsSync5(profileFile)) {
9611
10559
  try {
9612
- flatConfig = JSON.parse(readFileSync3(profileFile, "utf-8"));
10560
+ flatConfig = JSON.parse(readFileSync4(profileFile, "utf-8"));
9613
10561
  } catch {}
9614
10562
  }
9615
- const profileDirConfig = join3(configDir, "profiles", profile, "config.json");
9616
- if (existsSync3(profileDirConfig)) {
10563
+ const profileDirConfig = join6(configDir, "profiles", profile, "config.json");
10564
+ if (existsSync5(profileDirConfig)) {
9617
10565
  try {
9618
- dirConfig = JSON.parse(readFileSync3(profileDirConfig, "utf-8"));
10566
+ dirConfig = JSON.parse(readFileSync4(profileDirConfig, "utf-8"));
9619
10567
  } catch {}
9620
10568
  }
9621
10569
  if (Object.keys(flatConfig).length === 0 && Object.keys(dirConfig).length === 0) {
@@ -9626,14 +10574,24 @@ function loadProfileConfig(name) {
9626
10574
  function loadTokens(name) {
9627
10575
  const configDir = getConnectorConfigDir(name);
9628
10576
  const profile = getCurrentProfile(name);
9629
- const tokensFile = join3(configDir, "profiles", profile, "tokens.json");
9630
- if (existsSync3(tokensFile)) {
10577
+ const tokensFile = join6(configDir, "profiles", profile, "tokens.json");
10578
+ if (existsSync5(tokensFile)) {
9631
10579
  try {
9632
- return JSON.parse(readFileSync3(tokensFile, "utf-8"));
10580
+ return JSON.parse(readFileSync4(tokensFile, "utf-8"));
9633
10581
  } catch {
9634
10582
  return null;
9635
10583
  }
9636
10584
  }
10585
+ const profileConfig = loadProfileConfig(name);
10586
+ if (profileConfig.refreshToken || profileConfig.accessToken) {
10587
+ return {
10588
+ accessToken: profileConfig.accessToken ?? "",
10589
+ refreshToken: profileConfig.refreshToken,
10590
+ expiresAt: profileConfig.expiresAt ?? 0,
10591
+ tokenType: profileConfig.tokenType,
10592
+ scope: profileConfig.scope
10593
+ };
10594
+ }
9637
10595
  return null;
9638
10596
  }
9639
10597
  function getAuthStatus(name) {
@@ -9678,48 +10636,51 @@ function getEnvVars(name) {
9678
10636
  const docs = getConnectorDocs(name);
9679
10637
  return docs?.envVars || [];
9680
10638
  }
9681
- function saveApiKey(name, key, field) {
10639
+ async function saveApiKey(name, key, field) {
10640
+ return withWriteLock(name, () => _saveApiKey(name, key, field));
10641
+ }
10642
+ function _saveApiKey(name, key, field) {
9682
10643
  const configDir = getConnectorConfigDir(name);
9683
10644
  const profile = getCurrentProfile(name);
9684
10645
  const keyField = field || guessKeyField(name);
9685
10646
  if (keyField === "clientId" || keyField === "clientSecret") {
9686
- const credentialsFile = join3(configDir, "credentials.json");
9687
- mkdirSync(configDir, { recursive: true });
10647
+ const credentialsFile = join6(configDir, "credentials.json");
10648
+ mkdirSync5(configDir, { recursive: true });
9688
10649
  let creds = {};
9689
- if (existsSync3(credentialsFile)) {
10650
+ if (existsSync5(credentialsFile)) {
9690
10651
  try {
9691
- creds = JSON.parse(readFileSync3(credentialsFile, "utf-8"));
10652
+ creds = JSON.parse(readFileSync4(credentialsFile, "utf-8"));
9692
10653
  } catch {}
9693
10654
  }
9694
10655
  creds[keyField] = key;
9695
- writeFileSync(credentialsFile, JSON.stringify(creds, null, 2));
10656
+ writeFileSync3(credentialsFile, JSON.stringify(creds, null, 2));
9696
10657
  return;
9697
10658
  }
9698
- const profileFile = join3(configDir, "profiles", `${profile}.json`);
9699
- const profileDir = join3(configDir, "profiles", profile);
9700
- if (existsSync3(profileFile)) {
10659
+ const profileFile = join6(configDir, "profiles", `${profile}.json`);
10660
+ const profileDir = join6(configDir, "profiles", profile);
10661
+ if (existsSync5(profileFile)) {
9701
10662
  let config = {};
9702
10663
  try {
9703
- config = JSON.parse(readFileSync3(profileFile, "utf-8"));
10664
+ config = JSON.parse(readFileSync4(profileFile, "utf-8"));
9704
10665
  } catch {}
9705
10666
  config[keyField] = key;
9706
- writeFileSync(profileFile, JSON.stringify(config, null, 2));
10667
+ writeFileSync3(profileFile, JSON.stringify(config, null, 2));
9707
10668
  return;
9708
10669
  }
9709
- if (existsSync3(profileDir)) {
9710
- const configFile = join3(profileDir, "config.json");
10670
+ if (existsSync5(profileDir)) {
10671
+ const configFile = join6(profileDir, "config.json");
9711
10672
  let config = {};
9712
- if (existsSync3(configFile)) {
10673
+ if (existsSync5(configFile)) {
9713
10674
  try {
9714
- config = JSON.parse(readFileSync3(configFile, "utf-8"));
10675
+ config = JSON.parse(readFileSync4(configFile, "utf-8"));
9715
10676
  } catch {}
9716
10677
  }
9717
10678
  config[keyField] = key;
9718
- writeFileSync(configFile, JSON.stringify(config, null, 2));
10679
+ writeFileSync3(configFile, JSON.stringify(config, null, 2));
9719
10680
  return;
9720
10681
  }
9721
- mkdirSync(profileDir, { recursive: true });
9722
- writeFileSync(join3(profileDir, "config.json"), JSON.stringify({ [keyField]: key }, null, 2));
10682
+ mkdirSync5(profileDir, { recursive: true });
10683
+ writeFileSync3(join6(profileDir, "config.json"), JSON.stringify({ [keyField]: key }, null, 2));
9723
10684
  }
9724
10685
  function guessKeyField(name) {
9725
10686
  const docs = getConnectorDocs(name);
@@ -9737,10 +10698,10 @@ function guessKeyField(name) {
9737
10698
  }
9738
10699
  function getOAuthConfig(name) {
9739
10700
  const configDir = getConnectorConfigDir(name);
9740
- const credentialsFile = join3(configDir, "credentials.json");
9741
- if (existsSync3(credentialsFile)) {
10701
+ const credentialsFile = join6(configDir, "credentials.json");
10702
+ if (existsSync5(credentialsFile)) {
9742
10703
  try {
9743
- const creds = JSON.parse(readFileSync3(credentialsFile, "utf-8"));
10704
+ const creds = JSON.parse(readFileSync4(credentialsFile, "utf-8"));
9744
10705
  return { clientId: creds.clientId, clientSecret: creds.clientSecret };
9745
10706
  } catch {}
9746
10707
  }
@@ -9819,12 +10780,15 @@ async function exchangeOAuthCode(name, code, redirectUri) {
9819
10780
  function saveOAuthTokens(name, tokens) {
9820
10781
  const configDir = getConnectorConfigDir(name);
9821
10782
  const profile = getCurrentProfile(name);
9822
- const profileDir = join3(configDir, "profiles", profile);
9823
- mkdirSync(profileDir, { recursive: true });
9824
- const tokensFile = join3(profileDir, "tokens.json");
9825
- writeFileSync(tokensFile, JSON.stringify(tokens, null, 2), { mode: 384 });
10783
+ const profileDir = join6(configDir, "profiles", profile);
10784
+ mkdirSync5(profileDir, { recursive: true });
10785
+ const tokensFile = join6(profileDir, "tokens.json");
10786
+ writeFileSync3(tokensFile, JSON.stringify(tokens, null, 2), { mode: 384 });
9826
10787
  }
9827
10788
  async function refreshOAuthToken(name) {
10789
+ return withWriteLock(name, () => _refreshOAuthToken(name));
10790
+ }
10791
+ async function _refreshOAuthToken(name) {
9828
10792
  const oauthConfig = getOAuthConfig(name);
9829
10793
  const currentTokens = loadTokens(name);
9830
10794
  if (!oauthConfig.clientId || !oauthConfig.clientSecret) {
@@ -9861,15 +10825,15 @@ async function refreshOAuthToken(name) {
9861
10825
  }
9862
10826
  function listProfiles(name) {
9863
10827
  const configDir = getConnectorConfigDir(name);
9864
- const profilesDir = join3(configDir, "profiles");
9865
- if (!existsSync3(profilesDir))
10828
+ const profilesDir = join6(configDir, "profiles");
10829
+ if (!existsSync5(profilesDir))
9866
10830
  return ["default"];
9867
10831
  const seen = new Set;
9868
10832
  try {
9869
10833
  const entries = readdirSync2(profilesDir);
9870
10834
  for (const entry of entries) {
9871
- const fullPath = join3(profilesDir, entry);
9872
- const stat = statSync2(fullPath);
10835
+ const fullPath = join6(profilesDir, entry);
10836
+ const stat = statSync3(fullPath);
9873
10837
  if (stat.isDirectory()) {
9874
10838
  seen.add(entry);
9875
10839
  } else if (entry.endsWith(".json")) {
@@ -9882,25 +10846,25 @@ function listProfiles(name) {
9882
10846
  }
9883
10847
  function switchProfile(name, profile) {
9884
10848
  const configDir = getConnectorConfigDir(name);
9885
- mkdirSync(configDir, { recursive: true });
9886
- writeFileSync(join3(configDir, "current_profile"), profile);
10849
+ mkdirSync5(configDir, { recursive: true });
10850
+ writeFileSync3(join6(configDir, "current_profile"), profile);
9887
10851
  }
9888
10852
  function deleteProfile(name, profile) {
9889
10853
  if (profile === "default")
9890
10854
  return false;
9891
10855
  const configDir = getConnectorConfigDir(name);
9892
- const profilesDir = join3(configDir, "profiles");
9893
- const profileFile = join3(profilesDir, `${profile}.json`);
9894
- if (existsSync3(profileFile)) {
9895
- rmSync(profileFile);
10856
+ const profilesDir = join6(configDir, "profiles");
10857
+ const profileFile = join6(profilesDir, `${profile}.json`);
10858
+ if (existsSync5(profileFile)) {
10859
+ rmSync2(profileFile);
9896
10860
  if (getCurrentProfile(name) === profile) {
9897
10861
  switchProfile(name, "default");
9898
10862
  }
9899
10863
  return true;
9900
10864
  }
9901
- const profileDir = join3(profilesDir, profile);
9902
- if (existsSync3(profileDir)) {
9903
- rmSync(profileDir, { recursive: true });
10865
+ const profileDir = join6(profilesDir, profile);
10866
+ if (existsSync5(profileDir)) {
10867
+ rmSync2(profileDir, { recursive: true });
9904
10868
  if (getCurrentProfile(name) === profile) {
9905
10869
  switchProfile(name, "default");
9906
10870
  }
@@ -9911,6 +10875,7 @@ function deleteProfile(name, profile) {
9911
10875
  var FETCH_TIMEOUT = 1e4, oauthStateStore, GOOGLE_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth", GOOGLE_TOKEN_URL = "https://oauth2.googleapis.com/token", GOOGLE_SCOPES;
9912
10876
  var init_auth = __esm(() => {
9913
10877
  init_installer();
10878
+ init_lock();
9914
10879
  oauthStateStore = new Map;
9915
10880
  GOOGLE_SCOPES = {
9916
10881
  gmail: [
@@ -9952,15 +10917,222 @@ var init_auth = __esm(() => {
9952
10917
  };
9953
10918
  });
9954
10919
 
10920
+ // src/db/promotions.ts
10921
+ var exports_promotions = {};
10922
+ __export(exports_promotions, {
10923
+ promoteConnector: () => promoteConnector,
10924
+ isPromoted: () => isPromoted,
10925
+ getPromotedConnectors: () => getPromotedConnectors,
10926
+ demoteConnector: () => demoteConnector
10927
+ });
10928
+ function promoteConnector(name, db) {
10929
+ const d = db ?? getDatabase();
10930
+ d.run("INSERT OR REPLACE INTO connector_promotions (connector, promoted_at) VALUES (?, ?)", [name, now()]);
10931
+ }
10932
+ function demoteConnector(name, db) {
10933
+ const d = db ?? getDatabase();
10934
+ return d.run("DELETE FROM connector_promotions WHERE connector = ?", [name]).changes > 0;
10935
+ }
10936
+ function getPromotedConnectors(db) {
10937
+ const d = db ?? getDatabase();
10938
+ return d.query("SELECT connector FROM connector_promotions ORDER BY promoted_at DESC").all().map((r) => r.connector);
10939
+ }
10940
+ function isPromoted(name, db) {
10941
+ const d = db ?? getDatabase();
10942
+ const row = d.query("SELECT 1 FROM connector_promotions WHERE connector = ?").get(name);
10943
+ return !!row;
10944
+ }
10945
+ var init_promotions = __esm(() => {
10946
+ init_database();
10947
+ });
10948
+
10949
+ // src/db/usage.ts
10950
+ var exports_usage = {};
10951
+ __export(exports_usage, {
10952
+ logUsage: () => logUsage,
10953
+ getUsageStats: () => getUsageStats,
10954
+ getUsageMap: () => getUsageMap,
10955
+ getTopConnectors: () => getTopConnectors,
10956
+ cleanOldUsage: () => cleanOldUsage
10957
+ });
10958
+ function logUsage(connector, action, agentId, db) {
10959
+ const d = db ?? getDatabase();
10960
+ d.run("INSERT INTO connector_usage (id, connector, action, agent_id, timestamp) VALUES (?, ?, ?, ?, ?)", [shortUuid(), connector, action, agentId ?? null, now()]);
10961
+ }
10962
+ function getUsageStats(connector, db) {
10963
+ const d = db ?? getDatabase();
10964
+ const total = d.query("SELECT COUNT(*) as c FROM connector_usage WHERE connector = ?").get(connector).c;
10965
+ const d7 = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
10966
+ const last7d = d.query("SELECT COUNT(*) as c FROM connector_usage WHERE connector = ? AND timestamp > ?").get(connector, d7).c;
10967
+ const d1 = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
10968
+ const last24h = d.query("SELECT COUNT(*) as c FROM connector_usage WHERE connector = ? AND timestamp > ?").get(connector, d1).c;
10969
+ return { connector, total, last7d, last24h };
10970
+ }
10971
+ function getTopConnectors(limit = 10, days = 7, db) {
10972
+ const d = db ?? getDatabase();
10973
+ const since = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();
10974
+ return d.query("SELECT connector, COUNT(*) as count FROM connector_usage WHERE timestamp > ? GROUP BY connector ORDER BY count DESC LIMIT ?").all(since, limit);
10975
+ }
10976
+ function getUsageMap(days = 7, db) {
10977
+ const top = getTopConnectors(100, days, db);
10978
+ return new Map(top.map((t) => [t.connector, t.count]));
10979
+ }
10980
+ function cleanOldUsage(days = 30, db) {
10981
+ const d = db ?? getDatabase();
10982
+ const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();
10983
+ return d.run("DELETE FROM connector_usage WHERE timestamp < ?", [cutoff]).changes;
10984
+ }
10985
+ var init_usage = __esm(() => {
10986
+ init_database();
10987
+ });
10988
+
10989
+ // src/db/agents.ts
10990
+ function shortUuid2() {
10991
+ return crypto.randomUUID().slice(0, 8);
10992
+ }
10993
+ function isAgentConflict(result) {
10994
+ return result.conflict === true;
10995
+ }
10996
+ function registerAgent(input, db) {
10997
+ const d = db ?? getDatabase();
10998
+ const normalizedName = input.name.trim().toLowerCase();
10999
+ const existing = getAgentByName(normalizedName, d);
11000
+ if (existing) {
11001
+ const lastSeenMs = new Date(existing.last_seen_at).getTime();
11002
+ const isActive = Date.now() - lastSeenMs < AGENT_ACTIVE_WINDOW_MS;
11003
+ const sameSession = input.session_id && existing.session_id && input.session_id === existing.session_id;
11004
+ const differentSession = input.session_id && existing.session_id && input.session_id !== existing.session_id;
11005
+ if (isActive && differentSession) {
11006
+ const minutesAgo = Math.round((Date.now() - lastSeenMs) / 60000);
11007
+ return {
11008
+ conflict: true,
11009
+ existing_id: existing.id,
11010
+ existing_name: existing.name,
11011
+ last_seen_at: existing.last_seen_at,
11012
+ session_hint: existing.session_id ? existing.session_id.slice(0, 8) : null,
11013
+ working_dir: null,
11014
+ message: `Agent "${normalizedName}" is already active (last seen ${minutesAgo}m ago). Pass session_id="${existing.session_id}" to reclaim it, or choose a different name.`
11015
+ };
11016
+ }
11017
+ const updates = ["last_seen_at = ?"];
11018
+ const params = [now()];
11019
+ if (input.session_id && !sameSession) {
11020
+ updates.push("session_id = ?");
11021
+ params.push(input.session_id);
11022
+ }
11023
+ params.push(existing.id);
11024
+ d.run(`UPDATE agents SET ${updates.join(", ")} WHERE id = ?`, params);
11025
+ return getAgent(existing.id, d);
11026
+ }
11027
+ const id = shortUuid2();
11028
+ const ts = now();
11029
+ d.run(`INSERT INTO agents (id, name, session_id, role, last_seen_at, created_at)
11030
+ VALUES (?, ?, ?, ?, ?, ?)`, [id, normalizedName, input.session_id ?? null, input.role ?? "agent", ts, ts]);
11031
+ return getAgent(id, d);
11032
+ }
11033
+ function getAgent(id, db) {
11034
+ const d = db ?? getDatabase();
11035
+ return d.query("SELECT * FROM agents WHERE id = ?").get(id);
11036
+ }
11037
+ function getAgentByName(name, db) {
11038
+ const d = db ?? getDatabase();
11039
+ return d.query("SELECT * FROM agents WHERE LOWER(name) = ?").get(name.trim().toLowerCase());
11040
+ }
11041
+ function listAgents(db) {
11042
+ const d = db ?? getDatabase();
11043
+ return d.query("SELECT * FROM agents ORDER BY name").all();
11044
+ }
11045
+ function deleteAgent(id, db) {
11046
+ const d = db ?? getDatabase();
11047
+ return d.run("DELETE FROM agents WHERE id = ?", [id]).changes > 0;
11048
+ }
11049
+ var AGENT_ACTIVE_WINDOW_MS;
11050
+ var init_agents = __esm(() => {
11051
+ init_database();
11052
+ AGENT_ACTIVE_WINDOW_MS = 30 * 60 * 1000;
11053
+ });
11054
+
11055
+ // src/db/rate.ts
11056
+ function ensureRateTable(db) {
11057
+ db.run(`
11058
+ CREATE TABLE IF NOT EXISTS connector_rate_usage (
11059
+ agent_id TEXT NOT NULL,
11060
+ connector TEXT NOT NULL,
11061
+ window_start TEXT NOT NULL,
11062
+ call_count INTEGER NOT NULL DEFAULT 0,
11063
+ PRIMARY KEY (agent_id, connector, window_start)
11064
+ )
11065
+ `);
11066
+ db.run(`CREATE INDEX IF NOT EXISTS idx_rate_usage_window ON connector_rate_usage(connector, window_start)`);
11067
+ }
11068
+ function countActiveAgents(db) {
11069
+ const cutoff = new Date(Date.now() - AGENT_ACTIVE_WINDOW_MS2).toISOString();
11070
+ const row = db.query("SELECT COUNT(*) as count FROM agents WHERE last_seen_at > ?").get(cutoff);
11071
+ return Math.max(1, row?.count ?? 1);
11072
+ }
11073
+ function currentWindowStart() {
11074
+ const now3 = Date.now();
11075
+ const windowMs = WINDOW_SECONDS * 1000;
11076
+ return new Date(Math.floor(now3 / windowMs) * windowMs).toISOString();
11077
+ }
11078
+ function checkRateBudget(agentId, connector, connectorLimit, consume = true, db) {
11079
+ const d = db ?? getDatabase();
11080
+ ensureRateTable(d);
11081
+ const activeAgents = countActiveAgents(d);
11082
+ const budget = Math.max(1, Math.floor(connectorLimit / activeAgents));
11083
+ const windowStart = currentWindowStart();
11084
+ const windowMs = WINDOW_SECONDS * 1000;
11085
+ const windowEnd = new Date(Math.floor(Date.now() / windowMs) * windowMs + windowMs);
11086
+ const windowResetsIn = windowEnd.getTime() - Date.now();
11087
+ const row = d.query("SELECT call_count FROM connector_rate_usage WHERE agent_id = ? AND connector = ? AND window_start = ?").get(agentId, connector, windowStart);
11088
+ const used = row?.call_count ?? 0;
11089
+ if (used >= budget) {
11090
+ return {
11091
+ exceeded: true,
11092
+ connector,
11093
+ agent_id: agentId,
11094
+ budget,
11095
+ used,
11096
+ active_agents: activeAgents,
11097
+ window_resets_in_ms: windowResetsIn,
11098
+ message: `Rate budget exceeded for "${connector}" (${used}/${budget} calls used, ${activeAgents} active agent${activeAgents === 1 ? "" : "s"} sharing limit of ${connectorLimit}/min). Resets in ${Math.ceil(windowResetsIn / 1000)}s.`
11099
+ };
11100
+ }
11101
+ if (consume) {
11102
+ d.run(`INSERT INTO connector_rate_usage (agent_id, connector, window_start, call_count)
11103
+ VALUES (?, ?, ?, 1)
11104
+ ON CONFLICT(agent_id, connector, window_start) DO UPDATE SET call_count = call_count + 1`, [agentId, connector, windowStart]);
11105
+ }
11106
+ return {
11107
+ connector,
11108
+ agent_id: agentId,
11109
+ limit: connectorLimit,
11110
+ active_agents: activeAgents,
11111
+ budget,
11112
+ used: consume ? used + 1 : used,
11113
+ remaining: consume ? budget - used - 1 : budget - used,
11114
+ window_start: windowStart,
11115
+ window_resets_in_ms: windowResetsIn
11116
+ };
11117
+ }
11118
+ function getRateBudget(agentId, connector, connectorLimit, db) {
11119
+ return checkRateBudget(agentId, connector, connectorLimit, false, db);
11120
+ }
11121
+ var AGENT_ACTIVE_WINDOW_MS2, WINDOW_SECONDS = 60;
11122
+ var init_rate = __esm(() => {
11123
+ init_database();
11124
+ AGENT_ACTIVE_WINDOW_MS2 = 30 * 60 * 1000;
11125
+ });
11126
+
9955
11127
  // src/server/serve.ts
9956
11128
  var exports_serve = {};
9957
11129
  __export(exports_serve, {
9958
11130
  startServer: () => startServer
9959
11131
  });
9960
- import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
9961
- import { join as join5, dirname as dirname4, extname, basename } from "path";
11132
+ import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync6 } from "fs";
11133
+ import { join as join8, dirname as dirname4, extname, basename } from "path";
9962
11134
  import { fileURLToPath as fileURLToPath4 } from "url";
9963
- import { homedir as homedir2 } from "os";
11135
+ import { homedir as homedir6 } from "os";
9964
11136
  function logActivity(action, connector, detail) {
9965
11137
  activityLog.unshift({ action, connector, timestamp: Date.now(), detail });
9966
11138
  if (activityLog.length > MAX_ACTIVITY_LOG) {
@@ -9971,20 +11143,20 @@ function resolveDashboardDir() {
9971
11143
  const candidates = [];
9972
11144
  try {
9973
11145
  const scriptDir = dirname4(fileURLToPath4(import.meta.url));
9974
- candidates.push(join5(scriptDir, "..", "dashboard", "dist"));
9975
- candidates.push(join5(scriptDir, "..", "..", "dashboard", "dist"));
11146
+ candidates.push(join8(scriptDir, "..", "dashboard", "dist"));
11147
+ candidates.push(join8(scriptDir, "..", "..", "dashboard", "dist"));
9976
11148
  } catch {}
9977
11149
  if (process.argv[1]) {
9978
11150
  const mainDir = dirname4(process.argv[1]);
9979
- candidates.push(join5(mainDir, "..", "dashboard", "dist"));
9980
- candidates.push(join5(mainDir, "..", "..", "dashboard", "dist"));
11151
+ candidates.push(join8(mainDir, "..", "dashboard", "dist"));
11152
+ candidates.push(join8(mainDir, "..", "..", "dashboard", "dist"));
9981
11153
  }
9982
- candidates.push(join5(process.cwd(), "dashboard", "dist"));
11154
+ candidates.push(join8(process.cwd(), "dashboard", "dist"));
9983
11155
  for (const candidate of candidates) {
9984
- if (existsSync5(candidate))
11156
+ if (existsSync7(candidate))
9985
11157
  return candidate;
9986
11158
  }
9987
- return join5(process.cwd(), "dashboard", "dist");
11159
+ return join8(process.cwd(), "dashboard", "dist");
9988
11160
  }
9989
11161
  function json(data, status = 200, port) {
9990
11162
  return new Response(JSON.stringify(data), {
@@ -9996,6 +11168,18 @@ function json(data, status = 200, port) {
9996
11168
  }
9997
11169
  });
9998
11170
  }
11171
+ async function jsonStripped(data, status = 200, port) {
11172
+ const raw = JSON.stringify(data);
11173
+ const body = await maybeStrip(raw);
11174
+ return new Response(body, {
11175
+ status,
11176
+ headers: {
11177
+ "Content-Type": "application/json",
11178
+ "Access-Control-Allow-Origin": port ? `http://localhost:${port}` : "*",
11179
+ ...SECURITY_HEADERS
11180
+ }
11181
+ });
11182
+ }
9999
11183
  function htmlResponse(content, status = 200) {
10000
11184
  return new Response(content, {
10001
11185
  status,
@@ -10057,7 +11241,7 @@ function oauthPage(type, title, message, hint, extra) {
10057
11241
  </body></html>`;
10058
11242
  }
10059
11243
  function serveStaticFile(filePath) {
10060
- if (!existsSync5(filePath))
11244
+ if (!existsSync7(filePath))
10061
11245
  return null;
10062
11246
  const ext = extname(filePath);
10063
11247
  const contentType = MIME_TYPES[ext] || "application/octet-stream";
@@ -10081,7 +11265,7 @@ async function startServer(requestedPort, options) {
10081
11265
  const shouldOpen = options?.open ?? true;
10082
11266
  loadConnectorVersions();
10083
11267
  const dashboardDir = resolveDashboardDir();
10084
- const dashboardExists = existsSync5(dashboardDir);
11268
+ const dashboardExists = existsSync7(dashboardDir);
10085
11269
  if (!dashboardExists) {
10086
11270
  console.error(`
10087
11271
  Dashboard not found at: ${dashboardDir}`);
@@ -10110,10 +11294,10 @@ Dashboard not found at: ${dashboardDir}`);
10110
11294
  const fields = fieldsParam ? new Set(fieldsParam.split(",").map((f) => f.trim())) : null;
10111
11295
  const data = getAllConnectorsWithAuth();
10112
11296
  if (compact) {
10113
- return json(data.map((c) => ({ name: c.name, category: c.category, installed: c.installed })), 200, port);
11297
+ return jsonStripped(data.map((c) => ({ name: c.name, category: c.category, installed: c.installed })), 200, port);
10114
11298
  }
10115
11299
  if (fields) {
10116
- return json(data.map((c) => {
11300
+ return jsonStripped(data.map((c) => {
10117
11301
  const out = {};
10118
11302
  for (const f of fields) {
10119
11303
  if (f in c)
@@ -10122,7 +11306,7 @@ Dashboard not found at: ${dashboardDir}`);
10122
11306
  return out;
10123
11307
  }), 200, port);
10124
11308
  }
10125
- return json(data, 200, port);
11309
+ return jsonStripped(data, 200, port);
10126
11310
  }
10127
11311
  const singleMatch = path.match(/^\/api\/connectors\/([^/]+)$/);
10128
11312
  if (singleMatch && method === "GET") {
@@ -10156,7 +11340,7 @@ Dashboard not found at: ${dashboardDir}`);
10156
11340
  const body = await req.json();
10157
11341
  if (!body.key)
10158
11342
  return json({ error: "Missing 'key' in request body" }, 400, port);
10159
- saveApiKey(name, body.key, body.field);
11343
+ await saveApiKey(name, body.key, body.field);
10160
11344
  logActivity("key_saved", name, body.field ? `Field: ${body.field}` : undefined);
10161
11345
  return json({ success: true }, 200, port);
10162
11346
  } catch (e) {
@@ -10201,7 +11385,10 @@ Dashboard not found at: ${dashboardDir}`);
10201
11385
  if (!isValidConnectorName(name))
10202
11386
  return json({ error: "Invalid connector name" }, 400, port);
10203
11387
  try {
10204
- removeConnector(name);
11388
+ const removed = removeConnector(name);
11389
+ if (!removed) {
11390
+ return json({ error: `Connector '${name}' is not installed` }, 404, port);
11391
+ }
10205
11392
  logActivity("uninstalled", name);
10206
11393
  return json({ success: true, name }, 200, port);
10207
11394
  } catch (e) {
@@ -10227,6 +11414,167 @@ Dashboard not found at: ${dashboardDir}`);
10227
11414
  if (path === "/api/activity" && method === "GET") {
10228
11415
  return json(activityLog, 200, port);
10229
11416
  }
11417
+ if (path === "/api/hot" && method === "GET") {
11418
+ const { getTopConnectors: getTopConnectors2 } = await Promise.resolve().then(() => (init_usage(), exports_usage));
11419
+ const { getPromotedConnectors: getPromotedConnectors2 } = await Promise.resolve().then(() => (init_promotions(), exports_promotions));
11420
+ const limit = parseInt(url2.searchParams.get("limit") || "10", 10);
11421
+ const days = parseInt(url2.searchParams.get("days") || "7", 10);
11422
+ const db = getDatabase2();
11423
+ const top = getTopConnectors2(limit, days, db);
11424
+ const promoted = new Set(getPromotedConnectors2(db));
11425
+ return json(top.map((t) => ({ ...t, promoted: promoted.has(t.connector) })), 200, port);
11426
+ }
11427
+ const promoteMatch = path.match(/^\/api\/connectors\/([^/]+)\/promote$/);
11428
+ if (promoteMatch && method === "POST") {
11429
+ const name = promoteMatch[1];
11430
+ if (!getConnector(name))
11431
+ return json({ error: "Connector not found" }, 404, port);
11432
+ const { promoteConnector: promoteConnector2 } = await Promise.resolve().then(() => (init_promotions(), exports_promotions));
11433
+ promoteConnector2(name, getDatabase2());
11434
+ return json({ success: true, connector: name }, 200, port);
11435
+ }
11436
+ if (promoteMatch && method === "DELETE") {
11437
+ const { demoteConnector: demoteConnector2 } = await Promise.resolve().then(() => (init_promotions(), exports_promotions));
11438
+ const removed = demoteConnector2(promoteMatch[1], getDatabase2());
11439
+ return json({ success: removed, connector: promoteMatch[1] }, 200, port);
11440
+ }
11441
+ if (path === "/api/llm" && method === "GET") {
11442
+ const config = getLlmConfig();
11443
+ if (!config)
11444
+ return json({ configured: false }, 200, port);
11445
+ return json({ configured: true, provider: config.provider, model: config.model, key: maskKey(config.api_key), strip: config.strip }, 200, port);
11446
+ }
11447
+ if (path === "/api/llm" && method === "POST") {
11448
+ const body = await req.json().catch(() => ({}));
11449
+ const validProviders = ["cerebras", "groq", "openai", "anthropic"];
11450
+ const provider = body.provider;
11451
+ if (!provider || !validProviders.includes(provider))
11452
+ return json({ error: "provider must be one of: " + validProviders.join(", ") }, 400, port);
11453
+ const api_key = body.api_key;
11454
+ if (!api_key)
11455
+ return json({ error: "api_key is required" }, 400, port);
11456
+ const model = body.model || getLlmConfig()?.model || "qwen-3-32b";
11457
+ const strip = typeof body.strip === "boolean" ? body.strip : getLlmConfig()?.strip ?? false;
11458
+ saveLlmConfig({ provider, model, api_key, strip });
11459
+ return json({ success: true, provider, model, strip }, 200, port);
11460
+ }
11461
+ if (path === "/api/llm/test" && method === "POST") {
11462
+ const config = getLlmConfig();
11463
+ if (!config)
11464
+ return json({ error: "No LLM configured" }, 400, port);
11465
+ try {
11466
+ const client = new LLMClient(config);
11467
+ const result = await client.complete('Respond with exactly: {"status":"ok"}', "ping");
11468
+ return json({ success: true, provider: result.provider, model: result.model, latency_ms: result.latency_ms, response: result.content }, 200, port);
11469
+ } catch (e) {
11470
+ return json({ success: false, error: e instanceof Error ? e.message : String(e) }, 500, port);
11471
+ }
11472
+ }
11473
+ if (path === "/api/jobs" && method === "GET") {
11474
+ return json(listJobs(getDatabase2()), 200, port);
11475
+ }
11476
+ if (path === "/api/jobs" && method === "POST") {
11477
+ const body = await req.json().catch(() => ({}));
11478
+ if (!body.name || !body.connector || !body.command || !body.cron)
11479
+ return json({ error: "name, connector, command, cron required" }, 400, port);
11480
+ const job = createJob({ name: body.name, connector: body.connector, command: body.command, args: body.args ?? [], cron: body.cron, strip: !!body.strip }, getDatabase2());
11481
+ return json(job, 201, port);
11482
+ }
11483
+ const jobMatch = path.match(/^\/api\/jobs\/([^/]+)$/);
11484
+ if (jobMatch) {
11485
+ const db = getDatabase2();
11486
+ const job = getJobByName(jobMatch[1]) ?? getDatabase2().query("SELECT * FROM connector_jobs WHERE id = ?").get(jobMatch[1]);
11487
+ if (!job && method !== "DELETE")
11488
+ return json({ error: "Job not found" }, 404, port);
11489
+ if (method === "GET")
11490
+ return json(listJobRuns(job.id, 20, db), 200, port);
11491
+ if (method === "DELETE") {
11492
+ const j = getJobByName(jobMatch[1], db);
11493
+ if (!j)
11494
+ return json({ error: "Job not found" }, 404, port);
11495
+ deleteJob(j.id, db);
11496
+ return json({ success: true }, 200, port);
11497
+ }
11498
+ if (method === "PATCH") {
11499
+ const body = await req.json().catch(() => ({}));
11500
+ const j = getJobByName(jobMatch[1], db);
11501
+ const updated = updateJob(j.id, { enabled: typeof body.enabled === "boolean" ? body.enabled : undefined, strip: typeof body.strip === "boolean" ? body.strip : undefined }, db);
11502
+ return json(updated, 200, port);
11503
+ }
11504
+ }
11505
+ const jobRunMatch = path.match(/^\/api\/jobs\/([^/]+)\/run$/);
11506
+ if (jobRunMatch && method === "POST") {
11507
+ const db = getDatabase2();
11508
+ const job = getJobByName(jobRunMatch[1], db);
11509
+ if (!job)
11510
+ return json({ error: "Job not found" }, 404, port);
11511
+ const result = await triggerJob(job, db);
11512
+ return json(result, 200, port);
11513
+ }
11514
+ if (path === "/api/workflows" && method === "GET") {
11515
+ return json(listWorkflows(getDatabase2()), 200, port);
11516
+ }
11517
+ if (path === "/api/workflows" && method === "POST") {
11518
+ const body = await req.json().catch(() => ({}));
11519
+ if (!body.name || !body.steps)
11520
+ return json({ error: "name and steps required" }, 400, port);
11521
+ const wf = createWorkflow({ name: body.name, steps: body.steps }, getDatabase2());
11522
+ return json(wf, 201, port);
11523
+ }
11524
+ const wfMatch = path.match(/^\/api\/workflows\/([^/]+)$/);
11525
+ if (wfMatch) {
11526
+ const db = getDatabase2();
11527
+ const wf = getWorkflowByName(wfMatch[1], db);
11528
+ if (!wf)
11529
+ return json({ error: "Workflow not found" }, 404, port);
11530
+ if (method === "GET")
11531
+ return json(wf, 200, port);
11532
+ if (method === "DELETE") {
11533
+ deleteWorkflow(wf.id, db);
11534
+ return json({ success: true }, 200, port);
11535
+ }
11536
+ }
11537
+ const wfRunMatch = path.match(/^\/api\/workflows\/([^/]+)\/run$/);
11538
+ if (wfRunMatch && method === "POST") {
11539
+ const wf = getWorkflowByName(wfRunMatch[1], getDatabase2());
11540
+ if (!wf)
11541
+ return json({ error: "Workflow not found" }, 404, port);
11542
+ const result = await runWorkflow(wf);
11543
+ return json(result, 200, port);
11544
+ }
11545
+ if (path === "/api/agents" && method === "GET") {
11546
+ return json(listAgents(), 200, port);
11547
+ }
11548
+ if (path === "/api/agents/register" && method === "POST") {
11549
+ const body = await req.json().catch(() => ({}));
11550
+ const name = typeof body.name === "string" ? body.name : null;
11551
+ if (!name)
11552
+ return json({ error: "name is required" }, 400, port);
11553
+ const result = registerAgent({
11554
+ name,
11555
+ session_id: typeof body.session_id === "string" ? body.session_id : undefined,
11556
+ role: typeof body.role === "string" ? body.role : undefined
11557
+ });
11558
+ if (isAgentConflict(result))
11559
+ return json(result, 409, port);
11560
+ return json(result, 200, port);
11561
+ }
11562
+ if (path.startsWith("/api/agents/") && method === "DELETE") {
11563
+ const agentName = path.slice("/api/agents/".length);
11564
+ const agent = getAgentByName(agentName);
11565
+ if (!agent)
11566
+ return json({ error: "Agent not found" }, 404, port);
11567
+ deleteAgent(agent.id);
11568
+ return json({ success: true }, 200, port);
11569
+ }
11570
+ const rateMatch = path.match(/^\/api\/rate\/([^/]+)\/([^/]+)$/);
11571
+ if (rateMatch && method === "GET") {
11572
+ const [, agentId, connector] = rateMatch;
11573
+ const limit = parseInt(url2.searchParams.get("limit") || "60", 10);
11574
+ const consume = url2.searchParams.get("consume") === "true";
11575
+ const result = consume ? checkRateBudget(agentId, connector, limit) : getRateBudget(agentId, connector, limit);
11576
+ return json(result, 200, port);
11577
+ }
10230
11578
  const profilesMatch = path.match(/^\/api\/connectors\/([^/]+)\/profiles$/);
10231
11579
  if (profilesMatch && method === "GET") {
10232
11580
  const name = profilesMatch[1];
@@ -10234,12 +11582,12 @@ Dashboard not found at: ${dashboardDir}`);
10234
11582
  return json({ error: "Invalid connector name" }, 400, port);
10235
11583
  try {
10236
11584
  const profiles = listProfiles(name);
10237
- const configDir = join5(homedir2(), ".connectors", name.startsWith("connect-") ? name : `connect-${name}`);
10238
- const currentProfileFile = join5(configDir, "current_profile");
11585
+ const configDir = join8(homedir6(), ".connectors", name.startsWith("connect-") ? name : `connect-${name}`);
11586
+ const currentProfileFile = join8(configDir, "current_profile");
10239
11587
  let current = "default";
10240
- if (existsSync5(currentProfileFile)) {
11588
+ if (existsSync7(currentProfileFile)) {
10241
11589
  try {
10242
- current = readFileSync4(currentProfileFile, "utf-8").trim() || "default";
11590
+ current = readFileSync5(currentProfileFile, "utf-8").trim() || "default";
10243
11591
  } catch {}
10244
11592
  }
10245
11593
  return json({ current, profiles }, 200, port);
@@ -10286,16 +11634,16 @@ Dashboard not found at: ${dashboardDir}`);
10286
11634
  }
10287
11635
  if (path === "/api/export" && method === "GET") {
10288
11636
  try {
10289
- const connectDir = join5(homedir2(), ".connectors");
11637
+ const connectDir = join8(homedir6(), ".connectors");
10290
11638
  const result = {};
10291
- if (existsSync5(connectDir)) {
11639
+ if (existsSync7(connectDir)) {
10292
11640
  const entries = readdirSync3(connectDir, { withFileTypes: true });
10293
11641
  for (const entry of entries) {
10294
11642
  if (!entry.isDirectory() || !entry.name.startsWith("connect-"))
10295
11643
  continue;
10296
11644
  const connectorName = entry.name.replace(/^connect-/, "");
10297
- const profilesDir = join5(connectDir, entry.name, "profiles");
10298
- if (!existsSync5(profilesDir))
11645
+ const profilesDir = join8(connectDir, entry.name, "profiles");
11646
+ if (!existsSync7(profilesDir))
10299
11647
  continue;
10300
11648
  const profiles = {};
10301
11649
  const profileEntries = readdirSync3(profilesDir, { withFileTypes: true });
@@ -10303,15 +11651,15 @@ Dashboard not found at: ${dashboardDir}`);
10303
11651
  if (pEntry.isFile() && pEntry.name.endsWith(".json")) {
10304
11652
  const profileName = basename(pEntry.name, ".json");
10305
11653
  try {
10306
- const config = JSON.parse(readFileSync4(join5(profilesDir, pEntry.name), "utf-8"));
11654
+ const config = JSON.parse(readFileSync5(join8(profilesDir, pEntry.name), "utf-8"));
10307
11655
  profiles[profileName] = config;
10308
11656
  } catch {}
10309
11657
  }
10310
11658
  if (pEntry.isDirectory()) {
10311
- const configPath = join5(profilesDir, pEntry.name, "config.json");
10312
- if (existsSync5(configPath)) {
11659
+ const configPath = join8(profilesDir, pEntry.name, "config.json");
11660
+ if (existsSync7(configPath)) {
10313
11661
  try {
10314
- const config = JSON.parse(readFileSync4(configPath, "utf-8"));
11662
+ const config = JSON.parse(readFileSync5(configPath, "utf-8"));
10315
11663
  profiles[pEntry.name] = config;
10316
11664
  } catch {}
10317
11665
  }
@@ -10346,20 +11694,20 @@ Dashboard not found at: ${dashboardDir}`);
10346
11694
  return json({ error: "Invalid import format: missing 'connectors' object" }, 400, port);
10347
11695
  }
10348
11696
  let imported = 0;
10349
- const connectDir = join5(homedir2(), ".connectors");
11697
+ const connectDir = join8(homedir6(), ".connectors");
10350
11698
  for (const [connectorName, data] of Object.entries(body.connectors)) {
10351
11699
  if (!isValidConnectorName(connectorName))
10352
11700
  continue;
10353
11701
  if (!data.profiles || typeof data.profiles !== "object")
10354
11702
  continue;
10355
- const connectorDir = join5(connectDir, `connect-${connectorName}`);
10356
- const profilesDir = join5(connectorDir, "profiles");
11703
+ const connectorDir = join8(connectDir, `connect-${connectorName}`);
11704
+ const profilesDir = join8(connectorDir, "profiles");
10357
11705
  for (const [profileName, config] of Object.entries(data.profiles)) {
10358
11706
  if (!config || typeof config !== "object")
10359
11707
  continue;
10360
- mkdirSync2(profilesDir, { recursive: true });
10361
- const profileFile = join5(profilesDir, `${profileName}.json`);
10362
- writeFileSync2(profileFile, JSON.stringify(config, null, 2));
11708
+ mkdirSync6(profilesDir, { recursive: true });
11709
+ const profileFile = join8(profilesDir, `${profileName}.json`);
11710
+ writeFileSync4(profileFile, JSON.stringify(config, null, 2));
10363
11711
  imported++;
10364
11712
  }
10365
11713
  }
@@ -10414,12 +11762,12 @@ Dashboard not found at: ${dashboardDir}`);
10414
11762
  }
10415
11763
  if (dashboardExists && (method === "GET" || method === "HEAD")) {
10416
11764
  if (path !== "/") {
10417
- const filePath = join5(dashboardDir, path);
11765
+ const filePath = join8(dashboardDir, path);
10418
11766
  const res2 = serveStaticFile(filePath);
10419
11767
  if (res2)
10420
11768
  return res2;
10421
11769
  }
10422
- const indexPath = join5(dashboardDir, "index.html");
11770
+ const indexPath = join8(dashboardDir, "index.html");
10423
11771
  const res = serveStaticFile(indexPath);
10424
11772
  if (res)
10425
11773
  return res;
@@ -10433,6 +11781,9 @@ Dashboard not found at: ${dashboardDir}`);
10433
11781
  };
10434
11782
  process.on("SIGINT", shutdown);
10435
11783
  process.on("SIGTERM", shutdown);
11784
+ const { startScheduler: startScheduler2 } = await Promise.resolve().then(() => (init_scheduler(), exports_scheduler));
11785
+ const { getDatabase: getDatabase2 } = await Promise.resolve().then(() => (init_database(), exports_database));
11786
+ startScheduler2(getDatabase2());
10436
11787
  const url = `http://localhost:${port}`;
10437
11788
  console.log(`Connectors Dashboard running at ${url}`);
10438
11789
  if (shouldOpen) {
@@ -10445,6 +11796,14 @@ Dashboard not found at: ${dashboardDir}`);
10445
11796
  }
10446
11797
  var activityLog, MAX_ACTIVITY_LOG = 100, MIME_TYPES, SECURITY_HEADERS, MAX_BODY_SIZE;
10447
11798
  var init_serve = __esm(() => {
11799
+ init_agents();
11800
+ init_rate();
11801
+ init_strip();
11802
+ init_llm();
11803
+ init_jobs();
11804
+ init_workflows();
11805
+ init_scheduler();
11806
+ init_workflow_runner();
10448
11807
  init_registry();
10449
11808
  init_installer();
10450
11809
  init_auth();
@@ -10489,6 +11848,101 @@ var {
10489
11848
 
10490
11849
  // src/cli/index.tsx
10491
11850
  import chalk2 from "chalk";
11851
+ // package.json
11852
+ var package_default = {
11853
+ name: "@hasna/connectors",
11854
+ version: "1.3.3",
11855
+ description: "Open source connector library - Install API connectors with a single command",
11856
+ type: "module",
11857
+ bin: {
11858
+ connectors: "./bin/index.js",
11859
+ "connectors-mcp": "./bin/mcp.js",
11860
+ "connectors-serve": "./bin/serve.js"
11861
+ },
11862
+ files: [
11863
+ "bin/",
11864
+ "dist/",
11865
+ "dashboard/dist/",
11866
+ "connectors/",
11867
+ "README.md"
11868
+ ],
11869
+ exports: {
11870
+ ".": {
11871
+ import: "./dist/index.js",
11872
+ types: "./dist/index.d.ts"
11873
+ }
11874
+ },
11875
+ main: "./dist/index.js",
11876
+ types: "./dist/index.d.ts",
11877
+ scripts: {
11878
+ build: "cd dashboard && bun run build && cd .. && bun build ./src/cli/index.tsx --outdir ./bin --target bun --external ink --external react --external chalk --external conf && bun build ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun build ./src/server/index.ts --outfile ./bin/serve.js --target bun && bun build ./src/index.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --outDir ./dist",
11879
+ "build:dashboard": "cd dashboard && bun run build",
11880
+ postinstall: '[ "$SKIP_DASHBOARD" = "1" ] || [ ! -f dashboard/package.json ] || [ -d dashboard/node_modules ] || (cd dashboard && bun install)',
11881
+ dev: "bun run ./src/cli/index.tsx",
11882
+ typecheck: "tsc --noEmit",
11883
+ test: "bun test",
11884
+ "sdk:build": "cd sdk && bun run build",
11885
+ prepublishOnly: "bun test && bun run build"
11886
+ },
11887
+ keywords: [
11888
+ "connectors",
11889
+ "api",
11890
+ "cli",
11891
+ "typescript",
11892
+ "bun",
11893
+ "figma",
11894
+ "stripe",
11895
+ "github",
11896
+ "openai",
11897
+ "mcp",
11898
+ "model-context-protocol"
11899
+ ],
11900
+ author: "Hasna",
11901
+ license: "Apache-2.0",
11902
+ devDependencies: {
11903
+ "@types/bun": "latest",
11904
+ "@types/react": "^18.2.0",
11905
+ "ink-testing-library": "^4.0.0",
11906
+ typescript: "^5"
11907
+ },
11908
+ dependencies: {
11909
+ "@modelcontextprotocol/sdk": "^1.26.0",
11910
+ chalk: "^5.3.0",
11911
+ commander: "^12.1.0",
11912
+ conf: "^13.0.1",
11913
+ "fast-xml-parser": "^5.5.3",
11914
+ ink: "^5.0.1",
11915
+ "ink-select-input": "^6.0.0",
11916
+ "ink-spinner": "^5.0.0",
11917
+ "ink-text-input": "^6.0.0",
11918
+ open: "^11.0.0",
11919
+ react: "^18.2.0",
11920
+ zod: "3"
11921
+ },
11922
+ engines: {
11923
+ bun: ">=1.0.0"
11924
+ },
11925
+ publishConfig: {
11926
+ registry: "https://registry.npmjs.org",
11927
+ access: "public"
11928
+ },
11929
+ repository: {
11930
+ type: "git",
11931
+ url: "git+https://github.com/hasna/connectors.git"
11932
+ },
11933
+ homepage: "https://github.com/hasna/connectors#readme",
11934
+ bugs: {
11935
+ url: "https://github.com/hasna/connectors/issues"
11936
+ }
11937
+ };
11938
+
11939
+ // src/cli/index.tsx
11940
+ init_llm();
11941
+ init_jobs();
11942
+ init_workflows();
11943
+ init_scheduler();
11944
+ init_workflow_runner();
11945
+ init_database();
10492
11946
 
10493
11947
  // src/cli/components/App.tsx
10494
11948
  import { useState as useState7 } from "react";
@@ -11962,9 +13416,9 @@ function App({ initialConnectors, overwrite = false }) {
11962
13416
  init_registry();
11963
13417
  init_installer();
11964
13418
  init_auth();
11965
- import { readdirSync as readdirSync4, existsSync as existsSync6, statSync as statSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
11966
- import { homedir as homedir3 } from "os";
11967
- import { join as join6, relative } from "path";
13419
+ import { readdirSync as readdirSync4, existsSync as existsSync8, statSync as statSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync5, mkdirSync as mkdirSync7 } from "fs";
13420
+ import { homedir as homedir7 } from "os";
13421
+ import { join as join9, relative } from "path";
11968
13422
 
11969
13423
  // src/lib/test-endpoints.ts
11970
13424
  var TEST_ENDPOINTS = {
@@ -12165,17 +13619,17 @@ var TEST_ENDPOINTS = {
12165
13619
  import { createInterface } from "readline";
12166
13620
 
12167
13621
  // src/lib/runner.ts
12168
- import { existsSync as existsSync4 } from "fs";
12169
- import { join as join4, dirname as dirname3 } from "path";
13622
+ import { existsSync as existsSync6 } from "fs";
13623
+ import { join as join7, dirname as dirname3 } from "path";
12170
13624
  import { fileURLToPath as fileURLToPath3 } from "url";
12171
- import { spawn } from "child_process";
13625
+ import { spawn as spawn3 } from "child_process";
12172
13626
  var __dirname3 = dirname3(fileURLToPath3(import.meta.url));
12173
13627
  function resolveConnectorsDir2() {
12174
- const fromBin = join4(__dirname3, "..", "connectors");
12175
- if (existsSync4(fromBin))
13628
+ const fromBin = join7(__dirname3, "..", "connectors");
13629
+ if (existsSync6(fromBin))
12176
13630
  return fromBin;
12177
- const fromSrc = join4(__dirname3, "..", "..", "connectors");
12178
- if (existsSync4(fromSrc))
13631
+ const fromSrc = join7(__dirname3, "..", "..", "connectors");
13632
+ if (existsSync6(fromSrc))
12179
13633
  return fromSrc;
12180
13634
  return fromBin;
12181
13635
  }
@@ -12215,13 +13669,13 @@ function buildEnvWithCredentials(connectorName, baseEnv) {
12215
13669
  }
12216
13670
  function getConnectorCliPath(name) {
12217
13671
  const safeName = name.replace(/[^a-z0-9-]/g, "");
12218
- const connectorDir = join4(CONNECTORS_DIR2, `connect-${safeName}`);
12219
- const cliPath = join4(connectorDir, "src", "cli", "index.ts");
12220
- if (existsSync4(cliPath))
13672
+ const connectorDir = join7(CONNECTORS_DIR2, `connect-${safeName}`);
13673
+ const cliPath = join7(connectorDir, "src", "cli", "index.ts");
13674
+ if (existsSync6(cliPath))
12221
13675
  return cliPath;
12222
13676
  return null;
12223
13677
  }
12224
- function runConnectorCommand(name, args, timeoutMs = 30000) {
13678
+ function runConnectorCommand2(name, args, timeoutMs = 30000) {
12225
13679
  const cliPath = getConnectorCliPath(name);
12226
13680
  if (!cliPath) {
12227
13681
  return Promise.resolve({
@@ -12232,7 +13686,7 @@ function runConnectorCommand(name, args, timeoutMs = 30000) {
12232
13686
  });
12233
13687
  }
12234
13688
  return new Promise((resolve) => {
12235
- const proc = spawn("bun", ["run", cliPath, ...args], {
13689
+ const proc = spawn3("bun", ["run", cliPath, ...args], {
12236
13690
  timeout: timeoutMs,
12237
13691
  env: buildEnvWithCredentials(name, process.env),
12238
13692
  stdio: ["pipe", "pipe", "pipe"]
@@ -12268,7 +13722,7 @@ async function getConnectorOperations(name) {
12268
13722
  if (!cliPath) {
12269
13723
  return { commands: [], helpText: "", hasCli: false };
12270
13724
  }
12271
- const result = await runConnectorCommand(name, ["--help"]);
13725
+ const result = await runConnectorCommand2(name, ["--help"]);
12272
13726
  const helpText = result.stdout || result.stderr;
12273
13727
  const commands = [];
12274
13728
  const lines = helpText.split(`
@@ -12292,7 +13746,7 @@ async function getConnectorOperations(name) {
12292
13746
  return { commands, helpText, hasCli: true };
12293
13747
  }
12294
13748
  async function getConnectorCommandHelp(name, command) {
12295
- const result = await runConnectorCommand(name, [command, "--help"]);
13749
+ const result = await runConnectorCommand2(name, [command, "--help"]);
12296
13750
  return result.stdout || result.stderr;
12297
13751
  }
12298
13752
 
@@ -12309,7 +13763,7 @@ var PRESETS = {
12309
13763
  commerce: { description: "Commerce and finance", connectors: ["stripe", "shopify", "revolut", "mercury", "pandadoc"] }
12310
13764
  };
12311
13765
  var program2 = new Command;
12312
- program2.name("connectors").description("Install API connectors for your project").version("1.3.2").enablePositionalOptions();
13766
+ program2.name("connectors").description("Install API connectors for your project").version(package_default.version).enablePositionalOptions();
12313
13767
  program2.command("interactive", { isDefault: true }).alias("i").description("Interactive connector browser").action(() => {
12314
13768
  if (!isTTY) {
12315
13769
  console.log(`Non-interactive environment detected. Use a subcommand:
@@ -12330,8 +13784,8 @@ Run 'connectors --help' for full usage.`);
12330
13784
  function listFilesRecursive(dir, base = dir) {
12331
13785
  const files = [];
12332
13786
  for (const entry of readdirSync4(dir)) {
12333
- const fullPath = join6(dir, entry);
12334
- if (statSync3(fullPath).isDirectory()) {
13787
+ const fullPath = join9(dir, entry);
13788
+ if (statSync4(fullPath).isDirectory()) {
12335
13789
  files.push(...listFilesRecursive(fullPath, base));
12336
13790
  } else {
12337
13791
  files.push(relative(base, fullPath));
@@ -12339,7 +13793,7 @@ function listFilesRecursive(dir, base = dir) {
12339
13793
  }
12340
13794
  return files;
12341
13795
  }
12342
- program2.command("install").alias("add").argument("[connectors...]", "Connectors to verify").option("-c, --category <category>", "Verify all connectors in a category").option("--preset <preset>", "Verify a preset bundle (e.g. ai, fullstack, google)").option("--json", "Output results as JSON", false).description("Verify connectors are available in the global package").action((connectors, options) => {
13796
+ program2.command("install").alias("add").argument("[connectors...]", "Connectors to install").option("-o, --overwrite", "Overwrite existing connectors", false).option("-d, --dry-run", "Preview what would be installed without making changes", false).option("-c, --category <category>", "Install all connectors in a category").option("--preset <preset>", "Install a preset bundle (e.g. ai, fullstack, google)").option("--json", "Output results as JSON", false).description("Install one or more connectors").action((connectors, options) => {
12343
13797
  if (options.category) {
12344
13798
  const category = CATEGORIES.find((c) => c.toLowerCase() === options.category.toLowerCase());
12345
13799
  if (!category) {
@@ -12352,7 +13806,8 @@ program2.command("install").alias("add").argument("[connectors...]", "Connectors
12352
13806
  process.exit(1);
12353
13807
  return;
12354
13808
  }
12355
- connectors.push(...getConnectorsByCategory(category).map((c) => c.name));
13809
+ const categoryConnectors = getConnectorsByCategory(category).map((c) => c.name);
13810
+ connectors.push(...categoryConnectors);
12356
13811
  }
12357
13812
  if (options.preset) {
12358
13813
  const preset = PRESETS[options.preset.toLowerCase()];
@@ -12370,25 +13825,133 @@ program2.command("install").alias("add").argument("[connectors...]", "Connectors
12370
13825
  }
12371
13826
  if (connectors.length === 0) {
12372
13827
  if (!isTTY) {
12373
- console.error("Error: specify connectors to verify. Example: connectors install figma stripe");
13828
+ console.error("Error: specify connectors to install. Example: connectors install figma stripe");
12374
13829
  process.exit(1);
12375
13830
  }
12376
13831
  render(/* @__PURE__ */ jsxDEV7(App, {}, undefined, false, undefined, this));
12377
13832
  return;
12378
13833
  }
12379
- const results = connectors.map((name) => installConnector(name));
13834
+ if (options.dryRun) {
13835
+ const installed = getInstalledConnectors();
13836
+ const destDir = join9(process.cwd(), ".connectors");
13837
+ const actions = [];
13838
+ for (const name of connectors) {
13839
+ if (!/^[a-z0-9-]+$/.test(name)) {
13840
+ actions.push({ connector: name, action: "error", reason: `Invalid connector name '${name}'` });
13841
+ continue;
13842
+ }
13843
+ const meta = getConnector(name);
13844
+ if (!meta) {
13845
+ actions.push({ connector: name, action: "error", reason: `Connector '${name}' not found in registry` });
13846
+ continue;
13847
+ }
13848
+ if (!connectorExists(name)) {
13849
+ actions.push({ connector: name, action: "error", reason: `Connector '${name}' source files not found` });
13850
+ continue;
13851
+ }
13852
+ const connectorDirName = name.startsWith("connect-") ? name : `connect-${name}`;
13853
+ const sourcePath = getConnectorPath(name);
13854
+ const destPath = join9(destDir, connectorDirName);
13855
+ const alreadyInstalled = installed.includes(name);
13856
+ const files = listFilesRecursive(sourcePath);
13857
+ const importLine = `export * as ${name} from './${connectorDirName}/src/index.js';`;
13858
+ if (alreadyInstalled && !options.overwrite) {
13859
+ actions.push({
13860
+ connector: name,
13861
+ action: "skip",
13862
+ reason: "Already installed. Use --overwrite to replace.",
13863
+ sourcePath,
13864
+ destPath
13865
+ });
13866
+ } else {
13867
+ actions.push({
13868
+ connector: name,
13869
+ action: alreadyInstalled ? "overwrite" : "install",
13870
+ sourcePath,
13871
+ destPath,
13872
+ files,
13873
+ importLine
13874
+ });
13875
+ }
13876
+ }
13877
+ if (options.json) {
13878
+ console.log(JSON.stringify({ dryRun: true, actions }, null, 2));
13879
+ process.exit(actions.every((a) => a.action !== "error") ? 0 : 1);
13880
+ return;
13881
+ }
13882
+ console.log(chalk2.bold(`
13883
+ Dry run \u2014 no changes will be made
13884
+ `));
13885
+ for (const a of actions) {
13886
+ if (a.action === "error") {
13887
+ console.log(chalk2.red(` \u2717 ${a.connector}: ${a.reason}`));
13888
+ continue;
13889
+ }
13890
+ if (a.action === "skip") {
13891
+ console.log(chalk2.yellow(` \u2298 ${a.connector}: ${a.reason}`));
13892
+ continue;
13893
+ }
13894
+ const actionLabel = a.action === "overwrite" ? chalk2.yellow("overwrite") : chalk2.green("install");
13895
+ console.log(` ${actionLabel} ${chalk2.cyan(a.connector)}`);
13896
+ console.log(chalk2.dim(` source: ${a.sourcePath}`));
13897
+ console.log(chalk2.dim(` dest: ${a.destPath}`));
13898
+ if (a.files && a.files.length > 0) {
13899
+ console.log(chalk2.dim(` files (${a.files.length}):`));
13900
+ for (const f of a.files) {
13901
+ console.log(chalk2.dim(` ${f}`));
13902
+ }
13903
+ }
13904
+ if (a.importLine) {
13905
+ console.log(` ${chalk2.dim("index.ts:")} ${a.importLine}`);
13906
+ }
13907
+ console.log();
13908
+ }
13909
+ const installCount = actions.filter((a) => a.action === "install").length;
13910
+ const overwriteCount = actions.filter((a) => a.action === "overwrite").length;
13911
+ const skipCount = actions.filter((a) => a.action === "skip").length;
13912
+ const errorCount = actions.filter((a) => a.action === "error").length;
13913
+ const parts = [];
13914
+ if (installCount)
13915
+ parts.push(chalk2.green(`${installCount} to install`));
13916
+ if (overwriteCount)
13917
+ parts.push(chalk2.yellow(`${overwriteCount} to overwrite`));
13918
+ if (skipCount)
13919
+ parts.push(chalk2.yellow(`${skipCount} skipped`));
13920
+ if (errorCount)
13921
+ parts.push(chalk2.red(`${errorCount} failed`));
13922
+ console.log(` ${chalk2.bold("Summary:")} ${parts.join(", ")}`);
13923
+ console.log(chalk2.dim(`
13924
+ Run without --dry-run to apply.
13925
+ `));
13926
+ process.exit(errorCount > 0 ? 1 : 0);
13927
+ return;
13928
+ }
13929
+ const results = connectors.map((name) => installConnector(name, { overwrite: options.overwrite }));
12380
13930
  if (options.json) {
12381
13931
  console.log(JSON.stringify(results, null, 2));
12382
13932
  process.exit(results.every((r) => r.success) ? 0 : 1);
12383
13933
  return;
12384
13934
  }
13935
+ console.log(chalk2.bold(`
13936
+ Installing connectors...
13937
+ `));
13938
+ const succeeded = [];
12385
13939
  for (const result of results) {
12386
13940
  if (result.success) {
12387
- console.log(chalk2.green(`\u2713 ${result.connector}`) + chalk2.dim(` \u2014 available at ${result.path}`));
13941
+ console.log(chalk2.green(`\u2713 ${result.connector}`));
13942
+ succeeded.push(result.connector);
12388
13943
  } else {
12389
13944
  console.log(chalk2.red(`\u2717 ${result.connector}: ${result.error}`));
12390
13945
  }
12391
13946
  }
13947
+ if (succeeded.length > 0) {
13948
+ console.log(chalk2.bold(`
13949
+ Next steps:`));
13950
+ const importNames = succeeded.join(", ");
13951
+ console.log(chalk2.dim(` 1. Import: `) + `import { ${importNames} } from './.connectors'`);
13952
+ console.log(chalk2.dim(` 2. Set key: `) + `connectors docs ${succeeded[0]}` + chalk2.dim(` (see env vars)`));
13953
+ console.log(chalk2.dim(` 3. Explore: `) + `connectors serve` + chalk2.dim(` (dashboard for auth management)`));
13954
+ }
12392
13955
  process.exit(results.every((r) => r.success) ? 0 : 1);
12393
13956
  });
12394
13957
  program2.command("list").alias("ls").option("-c, --category <category>", "Filter by category").option("-a, --all", "Show all available connectors", false).option("-i, --installed", "Show only installed connectors", false).option("-b, --brief", "Output only connector names", false).option("--json", "Output as JSON", false).description("List available or installed connectors").action((options) => {
@@ -12542,10 +14105,18 @@ Available connectors (${CONNECTORS.length}):
12542
14105
  console.log();
12543
14106
  }
12544
14107
  });
12545
- program2.command("search").argument("<query>", "Search term").option("--json", "Output as JSON", false).description("Search for connectors").action((query, options) => {
12546
- const results = searchConnectors(query);
14108
+ program2.command("search").argument("<query>", "Search term").option("--json", "Output as JSON", false).option("--limit <n>", "Max results", "20").description("Search for connectors (ranked with fuzzy matching)").action((query, options) => {
14109
+ const installed = getInstalledConnectors();
14110
+ const { getPromotedConnectors: getPromotedConnectors2 } = (init_promotions(), __toCommonJS(exports_promotions));
14111
+ const { getUsageMap: getUsageMap2 } = (init_usage(), __toCommonJS(exports_usage));
14112
+ const results = searchConnectors(query, {
14113
+ installed,
14114
+ promoted: getPromotedConnectors2(),
14115
+ usage: getUsageMap2(),
14116
+ limit: parseInt(options.limit)
14117
+ });
12547
14118
  if (options.json) {
12548
- console.log(JSON.stringify(results));
14119
+ console.log(JSON.stringify(results.map((c) => ({ name: c.name, displayName: c.displayName, version: c.version, category: c.category, description: c.description, score: c.score, badges: c.badges, matchReasons: c.matchReasons }))));
12549
14120
  return;
12550
14121
  }
12551
14122
  if (results.length === 0) {
@@ -12555,10 +14126,12 @@ program2.command("search").argument("<query>", "Search term").option("--json", "
12555
14126
  console.log(chalk2.bold(`
12556
14127
  Found ${results.length} connector(s):
12557
14128
  `));
12558
- console.log(` ${chalk2.dim("Name".padEnd(20))}${chalk2.dim("Version".padEnd(10))}${chalk2.dim("Category".padEnd(20))}${chalk2.dim("Description")}`);
12559
- console.log(chalk2.dim(` ${"\u2500".repeat(70)}`));
14129
+ console.log(` ${chalk2.dim("Name".padEnd(22))}${chalk2.dim("Score".padEnd(7))}${chalk2.dim("Category".padEnd(20))}${chalk2.dim("Description")}`);
14130
+ console.log(chalk2.dim(` ${"\u2500".repeat(75)}`));
12560
14131
  for (const c of results) {
12561
- console.log(` ${chalk2.cyan(c.name.padEnd(20))}${chalk2.dim((c.version || "-").padEnd(10))}${chalk2.dim(c.category.padEnd(20))}${c.description}`);
14132
+ const badges = c.badges.map((b) => b === "installed" ? chalk2.green("[INS]") : b === "hot" ? chalk2.red("[HOT]") : b === "promoted" ? chalk2.yellow("[PRO]") : "").join(" ");
14133
+ const badgeStr = badges ? " " + badges : "";
14134
+ console.log(` ${chalk2.cyan(c.name.padEnd(22))}${String(c.score).padEnd(7)}${chalk2.dim(c.category.padEnd(20))}${c.description}${badgeStr}`);
12562
14135
  }
12563
14136
  });
12564
14137
  program2.command("info").argument("<connector>", "Connector name").option("--json", "Output as JSON", false).description("Show detailed info about a connector").action((connector, options) => {
@@ -12792,17 +14365,17 @@ Updating ${toUpdate.length} connector(s)...
12792
14365
  });
12793
14366
  program2.command("status").option("--json", "Output as JSON", false).description("Show auth status of all configured connectors (project + global)").action((options) => {
12794
14367
  const installed = getInstalledConnectors();
12795
- const configDir = join6(homedir3(), ".connectors");
14368
+ const configDir = join9(homedir7(), ".connectors");
12796
14369
  const seen = new Set;
12797
14370
  const allStatuses = [];
12798
14371
  function buildStatusEntry(name, source) {
12799
14372
  const auth = getAuthStatus(name);
12800
14373
  const connectorName = name.startsWith("connect-") ? name : `connect-${name}`;
12801
- const currentProfileFile = join6(configDir, connectorName, "current_profile");
14374
+ const currentProfileFile = join9(configDir, connectorName, "current_profile");
12802
14375
  let profile = "default";
12803
- if (existsSync6(currentProfileFile)) {
14376
+ if (existsSync8(currentProfileFile)) {
12804
14377
  try {
12805
- profile = readFileSync5(currentProfileFile, "utf-8").trim() || "default";
14378
+ profile = readFileSync6(currentProfileFile, "utf-8").trim() || "default";
12806
14379
  } catch {}
12807
14380
  }
12808
14381
  let expiryLabel = null;
@@ -12838,13 +14411,13 @@ program2.command("status").option("--json", "Output as JSON", false).description
12838
14411
  seen.add(name);
12839
14412
  allStatuses.push(buildStatusEntry(name, "project"));
12840
14413
  }
12841
- if (existsSync6(configDir)) {
14414
+ if (existsSync8(configDir)) {
12842
14415
  try {
12843
14416
  const globalDirs = readdirSync4(configDir).filter((f) => {
12844
14417
  if (!f.startsWith("connect-"))
12845
14418
  return false;
12846
14419
  try {
12847
- return statSync3(join6(configDir, f)).isDirectory();
14420
+ return statSync4(join9(configDir, f)).isDirectory();
12848
14421
  } catch {
12849
14422
  return false;
12850
14423
  }
@@ -13118,7 +14691,7 @@ Open this URL to authenticate:
13118
14691
  return;
13119
14692
  }
13120
14693
  if (options.key) {
13121
- saveApiKey(connector, options.key, options.field || undefined);
14694
+ await saveApiKey(connector, options.key, options.field || undefined);
13122
14695
  const statusAfter2 = getAuthStatus(connector);
13123
14696
  if (options.json) {
13124
14697
  console.log(JSON.stringify({
@@ -13192,7 +14765,7 @@ Open this URL to authenticate:
13192
14765
  process.exit(1);
13193
14766
  return;
13194
14767
  }
13195
- saveApiKey(connector, key.trim(), options.field || undefined);
14768
+ await saveApiKey(connector, key.trim(), options.field || undefined);
13196
14769
  const statusAfter = getAuthStatus(connector);
13197
14770
  console.log(chalk2.green(`
13198
14771
  \u2713 API key saved for ${meta.displayName}`));
@@ -13209,15 +14782,15 @@ program2.command("init").option("--json", "Output presets and suggestions as JSO
13209
14782
  { key: "commerce", emoji: "\uD83D\uDCB3", label: "Commerce", connectors: ["stripe", "shopify", "paypal", "revolut", "mercury"], description: "Commerce and finance" },
13210
14783
  { key: "google", emoji: "\uD83D\uDCC1", label: "Google Workspace", connectors: ["gmail", "googledrive", "googlecalendar", "googledocs", "googlesheets"], description: "Google Workspace suite" }
13211
14784
  ];
13212
- const connectorsHome = join6(homedir3(), ".connectors");
14785
+ const connectorsHome = join9(homedir7(), ".connectors");
13213
14786
  let configuredCount = 0;
13214
14787
  const configuredNames = [];
13215
14788
  try {
13216
- if (existsSync6(connectorsHome)) {
13217
- const entries = readdirSync4(connectorsHome).filter((e) => e.startsWith("connect-") && statSync3(join6(connectorsHome, e)).isDirectory());
14789
+ if (existsSync8(connectorsHome)) {
14790
+ const entries = readdirSync4(connectorsHome).filter((e) => e.startsWith("connect-") && statSync4(join9(connectorsHome, e)).isDirectory());
13218
14791
  for (const entry of entries) {
13219
- const profilesDir = join6(connectorsHome, entry, "profiles");
13220
- if (existsSync6(profilesDir)) {
14792
+ const profilesDir = join9(connectorsHome, entry, "profiles");
14793
+ if (existsSync8(profilesDir)) {
13221
14794
  configuredCount++;
13222
14795
  configuredNames.push(entry.replace(/^connect-/, ""));
13223
14796
  }
@@ -13315,44 +14888,44 @@ function redactSecrets(obj) {
13315
14888
  return obj;
13316
14889
  }
13317
14890
  program2.command("export").option("-o, --output <file>", "Write to file instead of stdout").option("--include-secrets", "Include secrets in plaintext (dangerous \u2014 use only for backup/restore)").description("Export all connector credentials as JSON backup").action((options) => {
13318
- const connectDir = join6(homedir3(), ".connectors");
14891
+ const connectDir = join9(homedir7(), ".connectors");
13319
14892
  const result = {};
13320
- if (existsSync6(connectDir)) {
14893
+ if (existsSync8(connectDir)) {
13321
14894
  for (const entry of readdirSync4(connectDir)) {
13322
- const entryPath = join6(connectDir, entry);
13323
- if (!statSync3(entryPath).isDirectory() || !entry.startsWith("connect-"))
14895
+ const entryPath = join9(connectDir, entry);
14896
+ if (!statSync4(entryPath).isDirectory() || !entry.startsWith("connect-"))
13324
14897
  continue;
13325
14898
  const connectorName = entry.replace(/^connect-/, "");
13326
14899
  let credentials = undefined;
13327
- const credentialsPath = join6(entryPath, "credentials.json");
13328
- if (existsSync6(credentialsPath)) {
14900
+ const credentialsPath = join9(entryPath, "credentials.json");
14901
+ if (existsSync8(credentialsPath)) {
13329
14902
  try {
13330
- credentials = JSON.parse(readFileSync5(credentialsPath, "utf-8"));
14903
+ credentials = JSON.parse(readFileSync6(credentialsPath, "utf-8"));
13331
14904
  } catch {}
13332
14905
  }
13333
- const profilesDir = join6(entryPath, "profiles");
13334
- if (!existsSync6(profilesDir) && !credentials)
14906
+ const profilesDir = join9(entryPath, "profiles");
14907
+ if (!existsSync8(profilesDir) && !credentials)
13335
14908
  continue;
13336
14909
  const profiles = {};
13337
- if (existsSync6(profilesDir)) {
14910
+ if (existsSync8(profilesDir)) {
13338
14911
  for (const pEntry of readdirSync4(profilesDir)) {
13339
- const pPath = join6(profilesDir, pEntry);
13340
- if (statSync3(pPath).isFile() && pEntry.endsWith(".json")) {
14912
+ const pPath = join9(profilesDir, pEntry);
14913
+ if (statSync4(pPath).isFile() && pEntry.endsWith(".json")) {
13341
14914
  try {
13342
- profiles[pEntry.replace(/\.json$/, "")] = JSON.parse(readFileSync5(pPath, "utf-8"));
14915
+ profiles[pEntry.replace(/\.json$/, "")] = JSON.parse(readFileSync6(pPath, "utf-8"));
13343
14916
  } catch {}
13344
- } else if (statSync3(pPath).isDirectory()) {
13345
- const configPath = join6(pPath, "config.json");
13346
- const tokensPath = join6(pPath, "tokens.json");
14917
+ } else if (statSync4(pPath).isDirectory()) {
14918
+ const configPath = join9(pPath, "config.json");
14919
+ const tokensPath = join9(pPath, "tokens.json");
13347
14920
  let merged = {};
13348
- if (existsSync6(configPath)) {
14921
+ if (existsSync8(configPath)) {
13349
14922
  try {
13350
- merged = { ...merged, ...JSON.parse(readFileSync5(configPath, "utf-8")) };
14923
+ merged = { ...merged, ...JSON.parse(readFileSync6(configPath, "utf-8")) };
13351
14924
  } catch {}
13352
14925
  }
13353
- if (existsSync6(tokensPath)) {
14926
+ if (existsSync8(tokensPath)) {
13354
14927
  try {
13355
- merged = { ...merged, ...JSON.parse(readFileSync5(tokensPath, "utf-8")) };
14928
+ merged = { ...merged, ...JSON.parse(readFileSync6(tokensPath, "utf-8")) };
13356
14929
  } catch {}
13357
14930
  }
13358
14931
  if (Object.keys(merged).length > 0)
@@ -13373,7 +14946,7 @@ program2.command("export").option("-o, --output <file>", "Write to file instead
13373
14946
  }
13374
14947
  const exportData = JSON.stringify(exportPayload, null, 2);
13375
14948
  if (options.output) {
13376
- writeFileSync3(options.output, exportData);
14949
+ writeFileSync5(options.output, exportData);
13377
14950
  console.log(chalk2.green(`\u2713 Exported to ${options.output}`));
13378
14951
  } else {
13379
14952
  console.log(exportData);
@@ -13387,7 +14960,7 @@ program2.command("import").argument("<file>", "JSON backup file to import (use -
13387
14960
  chunks.push(chunk.toString());
13388
14961
  raw = chunks.join("");
13389
14962
  } else {
13390
- if (!existsSync6(file)) {
14963
+ if (!existsSync8(file)) {
13391
14964
  if (options.json) {
13392
14965
  console.log(JSON.stringify({ error: `File not found: ${file}` }));
13393
14966
  } else {
@@ -13396,7 +14969,7 @@ program2.command("import").argument("<file>", "JSON backup file to import (use -
13396
14969
  process.exit(1);
13397
14970
  return;
13398
14971
  }
13399
- raw = readFileSync5(file, "utf-8");
14972
+ raw = readFileSync6(file, "utf-8");
13400
14973
  }
13401
14974
  let data;
13402
14975
  try {
@@ -13419,25 +14992,25 @@ program2.command("import").argument("<file>", "JSON backup file to import (use -
13419
14992
  process.exit(1);
13420
14993
  return;
13421
14994
  }
13422
- const connectDir = join6(homedir3(), ".connectors");
14995
+ const connectDir = join9(homedir7(), ".connectors");
13423
14996
  let imported = 0;
13424
14997
  for (const [connectorName, connData] of Object.entries(data.connectors)) {
13425
14998
  if (!/^[a-z0-9-]+$/.test(connectorName))
13426
14999
  continue;
13427
- const connectorDir = join6(connectDir, `connect-${connectorName}`);
15000
+ const connectorDir = join9(connectDir, `connect-${connectorName}`);
13428
15001
  if (connData.credentials && typeof connData.credentials === "object") {
13429
- mkdirSync3(connectorDir, { recursive: true });
13430
- writeFileSync3(join6(connectorDir, "credentials.json"), JSON.stringify(connData.credentials, null, 2));
15002
+ mkdirSync7(connectorDir, { recursive: true });
15003
+ writeFileSync5(join9(connectorDir, "credentials.json"), JSON.stringify(connData.credentials, null, 2));
13431
15004
  imported++;
13432
15005
  }
13433
15006
  if (!connData.profiles || typeof connData.profiles !== "object")
13434
15007
  continue;
13435
- const profilesDir = join6(connectorDir, "profiles");
15008
+ const profilesDir = join9(connectorDir, "profiles");
13436
15009
  for (const [profileName, config] of Object.entries(connData.profiles)) {
13437
15010
  if (!config || typeof config !== "object")
13438
15011
  continue;
13439
- mkdirSync3(profilesDir, { recursive: true });
13440
- writeFileSync3(join6(profilesDir, `${profileName}.json`), JSON.stringify(config, null, 2));
15012
+ mkdirSync7(profilesDir, { recursive: true });
15013
+ writeFileSync5(join9(profilesDir, `${profileName}.json`), JSON.stringify(config, null, 2));
13441
15014
  imported++;
13442
15015
  }
13443
15016
  }
@@ -13448,9 +15021,9 @@ program2.command("import").argument("<file>", "JSON backup file to import (use -
13448
15021
  }
13449
15022
  });
13450
15023
  program2.command("auth-import").option("--json", "Output as JSON", false).option("-d, --dry-run", "Preview what would be imported without copying", false).option("--force", "Overwrite existing files in ~/.connectors/", false).description("Migrate auth tokens from ~/.connect/ to ~/.connectors/").action((options) => {
13451
- const oldBase = join6(homedir3(), ".connect");
13452
- const newBase = join6(homedir3(), ".connectors");
13453
- if (!existsSync6(oldBase)) {
15024
+ const oldBase = join9(homedir7(), ".connect");
15025
+ const newBase = join9(homedir7(), ".connectors");
15026
+ if (!existsSync8(oldBase)) {
13454
15027
  if (options.json) {
13455
15028
  console.log(JSON.stringify({ imported: [], skipped: [], error: null, message: "No ~/.connect/ directory found" }));
13456
15029
  } else {
@@ -13462,7 +15035,7 @@ program2.command("auth-import").option("--json", "Output as JSON", false).option
13462
15035
  if (!name.startsWith("connect-"))
13463
15036
  return false;
13464
15037
  try {
13465
- return statSync3(join6(oldBase, name)).isDirectory();
15038
+ return statSync4(join9(oldBase, name)).isDirectory();
13466
15039
  } catch {
13467
15040
  return false;
13468
15041
  }
@@ -13478,8 +15051,8 @@ program2.command("auth-import").option("--json", "Output as JSON", false).option
13478
15051
  const imported = [];
13479
15052
  const skipped = [];
13480
15053
  for (const dirName of entries) {
13481
- const oldDir = join6(oldBase, dirName);
13482
- const newDir = join6(newBase, dirName);
15054
+ const oldDir = join9(oldBase, dirName);
15055
+ const newDir = join9(newBase, dirName);
13483
15056
  const connectorName = dirName.replace(/^connect-/, "");
13484
15057
  const allFiles = listFilesRecursive(oldDir);
13485
15058
  const authFiles = allFiles.filter((f) => {
@@ -13490,17 +15063,17 @@ program2.command("auth-import").option("--json", "Output as JSON", false).option
13490
15063
  const copiedFiles = [];
13491
15064
  const skippedFiles = [];
13492
15065
  for (const relFile of authFiles) {
13493
- const srcPath = join6(oldDir, relFile);
13494
- const destPath = join6(newDir, relFile);
13495
- if (existsSync6(destPath) && !options.force) {
15066
+ const srcPath = join9(oldDir, relFile);
15067
+ const destPath = join9(newDir, relFile);
15068
+ if (existsSync8(destPath) && !options.force) {
13496
15069
  skippedFiles.push(relFile);
13497
15070
  continue;
13498
15071
  }
13499
15072
  if (!options.dryRun) {
13500
- const parentDir = join6(destPath, "..");
13501
- mkdirSync3(parentDir, { recursive: true });
13502
- const content = readFileSync5(srcPath);
13503
- writeFileSync3(destPath, content);
15073
+ const parentDir = join9(destPath, "..");
15074
+ mkdirSync7(parentDir, { recursive: true });
15075
+ const content = readFileSync6(srcPath);
15076
+ writeFileSync5(destPath, content);
13504
15077
  }
13505
15078
  copiedFiles.push(relFile);
13506
15079
  }
@@ -13745,7 +15318,7 @@ program2.command("env").option("-o, --output <file>", "Write to file instead of
13745
15318
  `) + `
13746
15319
  `;
13747
15320
  if (options.output) {
13748
- writeFileSync3(options.output, output);
15321
+ writeFileSync5(options.output, output);
13749
15322
  console.log(chalk2.green(`\u2713 Written to ${options.output} (${vars.length} variables)`));
13750
15323
  } else {
13751
15324
  console.log(output);
@@ -13773,7 +15346,7 @@ Available presets:
13773
15346
  `));
13774
15347
  });
13775
15348
  program2.command("whoami").option("--json", "Output as JSON", false).description("Show current setup: config dir, installed connectors, auth status").action((options) => {
13776
- const configDir = join6(homedir3(), ".connectors");
15349
+ const configDir = join9(homedir7(), ".connectors");
13777
15350
  const installed = getInstalledConnectors();
13778
15351
  const version = "0.3.1";
13779
15352
  let configured = 0;
@@ -13787,23 +15360,23 @@ program2.command("whoami").option("--json", "Output as JSON", false).description
13787
15360
  configured++;
13788
15361
  else
13789
15362
  unconfigured++;
13790
- const connectorConfigDir = join6(configDir, name.startsWith("connect-") ? name : `connect-${name}`);
13791
- const currentProfileFile = join6(connectorConfigDir, "current_profile");
15363
+ const connectorConfigDir = join9(configDir, name.startsWith("connect-") ? name : `connect-${name}`);
15364
+ const currentProfileFile = join9(connectorConfigDir, "current_profile");
13792
15365
  let profile = "default";
13793
- if (existsSync6(currentProfileFile)) {
15366
+ if (existsSync8(currentProfileFile)) {
13794
15367
  try {
13795
- profile = readFileSync5(currentProfileFile, "utf-8").trim() || "default";
15368
+ profile = readFileSync6(currentProfileFile, "utf-8").trim() || "default";
13796
15369
  } catch {}
13797
15370
  }
13798
15371
  connectorDetails.push({ name, configured: auth.configured, authType: auth.type, profile, source: "project" });
13799
15372
  }
13800
- if (existsSync6(configDir)) {
15373
+ if (existsSync8(configDir)) {
13801
15374
  try {
13802
15375
  const globalDirs = readdirSync4(configDir).filter((f) => {
13803
15376
  if (!f.startsWith("connect-"))
13804
15377
  return false;
13805
15378
  try {
13806
- return statSync3(join6(configDir, f)).isDirectory();
15379
+ return statSync4(join9(configDir, f)).isDirectory();
13807
15380
  } catch {
13808
15381
  return false;
13809
15382
  }
@@ -13817,11 +15390,11 @@ program2.command("whoami").option("--json", "Output as JSON", false).description
13817
15390
  continue;
13818
15391
  seen.add(name);
13819
15392
  configured++;
13820
- const currentProfileFile = join6(configDir, dir, "current_profile");
15393
+ const currentProfileFile = join9(configDir, dir, "current_profile");
13821
15394
  let profile = "default";
13822
- if (existsSync6(currentProfileFile)) {
15395
+ if (existsSync8(currentProfileFile)) {
13823
15396
  try {
13824
- profile = readFileSync5(currentProfileFile, "utf-8").trim() || "default";
15397
+ profile = readFileSync6(currentProfileFile, "utf-8").trim() || "default";
13825
15398
  } catch {}
13826
15399
  }
13827
15400
  connectorDetails.push({ name, configured: true, authType: auth.type, profile, source: "global" });
@@ -13832,7 +15405,7 @@ program2.command("whoami").option("--json", "Output as JSON", false).description
13832
15405
  console.log(JSON.stringify({
13833
15406
  version,
13834
15407
  configDir,
13835
- configDirExists: existsSync6(configDir),
15408
+ configDirExists: existsSync8(configDir),
13836
15409
  installed: installed.length,
13837
15410
  configured,
13838
15411
  unconfigured,
@@ -13844,7 +15417,7 @@ program2.command("whoami").option("--json", "Output as JSON", false).description
13844
15417
  Connectors Setup
13845
15418
  `));
13846
15419
  console.log(` Version: ${chalk2.cyan(version)}`);
13847
- console.log(` Config: ${configDir}${existsSync6(configDir) ? "" : chalk2.dim(" (not created yet)")}`);
15420
+ console.log(` Config: ${configDir}${existsSync8(configDir) ? "" : chalk2.dim(" (not created yet)")}`);
13848
15421
  console.log(` Installed: ${installed.length} connector${installed.length !== 1 ? "s" : ""}`);
13849
15422
  console.log(` Configured: ${chalk2.green(String(configured))} ready, ${unconfigured > 0 ? chalk2.red(String(unconfigured)) : chalk2.dim("0")} need auth`);
13850
15423
  const projectConnectors = connectorDetails.filter((c) => c.source === "project");
@@ -13934,18 +15507,18 @@ Testing connector credentials...
13934
15507
  }
13935
15508
  }
13936
15509
  if (!apiKey) {
13937
- const connectorConfigDir = join6(homedir3(), ".connectors", name.startsWith("connect-") ? name : `connect-${name}`);
15510
+ const connectorConfigDir = join9(homedir7(), ".connectors", name.startsWith("connect-") ? name : `connect-${name}`);
13938
15511
  let currentProfile = "default";
13939
- const currentProfileFile = join6(connectorConfigDir, "current_profile");
13940
- if (existsSync6(currentProfileFile)) {
15512
+ const currentProfileFile = join9(connectorConfigDir, "current_profile");
15513
+ if (existsSync8(currentProfileFile)) {
13941
15514
  try {
13942
- currentProfile = readFileSync5(currentProfileFile, "utf-8").trim() || "default";
15515
+ currentProfile = readFileSync6(currentProfileFile, "utf-8").trim() || "default";
13943
15516
  } catch {}
13944
15517
  }
13945
- const tokensFile = join6(connectorConfigDir, "profiles", currentProfile, "tokens.json");
13946
- if (existsSync6(tokensFile)) {
15518
+ const tokensFile = join9(connectorConfigDir, "profiles", currentProfile, "tokens.json");
15519
+ if (existsSync8(tokensFile)) {
13947
15520
  try {
13948
- const tokens = JSON.parse(readFileSync5(tokensFile, "utf-8"));
15521
+ const tokens = JSON.parse(readFileSync6(tokensFile, "utf-8"));
13949
15522
  const isExpired = tokens.expiresAt && Date.now() >= tokens.expiresAt - 60000;
13950
15523
  if (isExpired && tokens.refreshToken) {
13951
15524
  try {
@@ -13963,19 +15536,19 @@ Testing connector credentials...
13963
15536
  } catch {}
13964
15537
  }
13965
15538
  if (!apiKey) {
13966
- const profileFile = join6(connectorConfigDir, "profiles", `${currentProfile}.json`);
13967
- if (existsSync6(profileFile)) {
15539
+ const profileFile = join9(connectorConfigDir, "profiles", `${currentProfile}.json`);
15540
+ if (existsSync8(profileFile)) {
13968
15541
  try {
13969
- const config = JSON.parse(readFileSync5(profileFile, "utf-8"));
15542
+ const config = JSON.parse(readFileSync6(profileFile, "utf-8"));
13970
15543
  apiKey = Object.values(config).find((v) => typeof v === "string" && v.length > 0);
13971
15544
  } catch {}
13972
15545
  }
13973
15546
  }
13974
15547
  if (!apiKey) {
13975
- const profileDirConfig = join6(connectorConfigDir, "profiles", currentProfile, "config.json");
13976
- if (existsSync6(profileDirConfig)) {
15548
+ const profileDirConfig = join9(connectorConfigDir, "profiles", currentProfile, "config.json");
15549
+ if (existsSync8(profileDirConfig)) {
13977
15550
  try {
13978
- const config = JSON.parse(readFileSync5(profileDirConfig, "utf-8"));
15551
+ const config = JSON.parse(readFileSync6(profileDirConfig, "utf-8"));
13979
15552
  apiKey = Object.values(config).find((v) => typeof v === "string" && v.length > 0);
13980
15553
  } catch {}
13981
15554
  }
@@ -14112,7 +15685,7 @@ program2.command("run").description("Execute an API operation on a connector").a
14112
15685
  console.error(chalk2.yellow(`No command specified. Run ${chalk2.white(`connectors ops ${name}`)} to see available operations.`));
14113
15686
  process.exit(1);
14114
15687
  }
14115
- const result = await runConnectorCommand(name, args, parseInt(options.timeout));
15688
+ const result = await runConnectorCommand2(name, args, parseInt(options.timeout));
14116
15689
  if (result.stdout) {
14117
15690
  console.log(result.stdout);
14118
15691
  }
@@ -14142,7 +15715,7 @@ Setting up ${meta.displayName}...
14142
15715
  const alreadyInstalled = installed.includes(meta.name);
14143
15716
  let installResult;
14144
15717
  if (alreadyInstalled && !options.overwrite) {
14145
- installResult = { success: true, path: join6(process.cwd(), ".connectors", `connect-${meta.name}`) };
15718
+ installResult = { success: true, path: join9(process.cwd(), ".connectors", `connect-${meta.name}`) };
14146
15719
  if (!options.json) {
14147
15720
  console.log(` ${chalk2.green("\u2713")} Already installed`);
14148
15721
  }
@@ -14167,7 +15740,7 @@ Setting up ${meta.displayName}...
14167
15740
  let authConfigured = false;
14168
15741
  if (authType === "oauth") {
14169
15742
  if (options.key) {
14170
- saveApiKey(name, options.key, options.field || undefined);
15743
+ await saveApiKey(name, options.key, options.field || undefined);
14171
15744
  authConfigured = true;
14172
15745
  if (!options.json) {
14173
15746
  console.log(` ${chalk2.green("\u2713")} Token saved`);
@@ -14225,7 +15798,7 @@ Setting up ${meta.displayName}...
14225
15798
  }
14226
15799
  } else {
14227
15800
  if (options.key) {
14228
- saveApiKey(name, options.key, options.field || undefined);
15801
+ await saveApiKey(name, options.key, options.field || undefined);
14229
15802
  authConfigured = true;
14230
15803
  if (!options.json) {
14231
15804
  console.log(` ${chalk2.green("\u2713")} ${authType === "bearer" ? "Bearer token" : "API key"} saved`);
@@ -14268,4 +15841,299 @@ Setting up ${meta.displayName}...
14268
15841
  }
14269
15842
  process.exit(0);
14270
15843
  });
15844
+ program2.command("hot").description("Show top connectors by usage").option("--limit <n>", "Max results", "10").option("--days <n>", "Time window in days", "7").option("--json", "Output as JSON").action((options) => {
15845
+ const { getTopConnectors: getTopConnectors2 } = (init_usage(), __toCommonJS(exports_usage));
15846
+ const { getPromotedConnectors: getPromotedConnectors2 } = (init_promotions(), __toCommonJS(exports_promotions));
15847
+ const top = getTopConnectors2(parseInt(options.limit), parseInt(options.days), getDatabase());
15848
+ const promoted = new Set(getPromotedConnectors2(getDatabase()));
15849
+ if (options.json) {
15850
+ console.log(JSON.stringify(top.map((t) => ({ ...t, promoted: promoted.has(t.connector) }))));
15851
+ return;
15852
+ }
15853
+ if (top.length === 0) {
15854
+ console.log(chalk2.dim("No usage data yet. Use connectors to build up stats."));
15855
+ return;
15856
+ }
15857
+ console.log(chalk2.bold(`
15858
+ Top connectors (last ${options.days} days):
15859
+ `));
15860
+ console.log(` ${chalk2.dim("#".padEnd(4))}${chalk2.dim("Connector".padEnd(22))}${chalk2.dim("Usage".padEnd(8))}${chalk2.dim("Badges")}`);
15861
+ console.log(chalk2.dim(` ${"\u2500".repeat(45)}`));
15862
+ for (let i = 0;i < top.length; i++) {
15863
+ const t = top[i];
15864
+ const badges = [
15865
+ t.count >= 5 ? chalk2.red("[HOT]") : "",
15866
+ promoted.has(t.connector) ? chalk2.yellow("[PRO]") : ""
15867
+ ].filter(Boolean).join(" ");
15868
+ console.log(` ${String(i + 1).padEnd(4)}${chalk2.cyan(t.connector.padEnd(22))}${String(t.count).padEnd(8)}${badges}`);
15869
+ }
15870
+ });
15871
+ program2.command("promote").argument("<connector>", "Connector to promote").description("Mark a connector as promoted (boosted in search)").action((connector) => {
15872
+ const meta = getConnector(connector);
15873
+ if (!meta) {
15874
+ console.error(chalk2.red(`Connector '${connector}' not found`));
15875
+ process.exit(1);
15876
+ }
15877
+ const { promoteConnector: promoteConnector2 } = (init_promotions(), __toCommonJS(exports_promotions));
15878
+ promoteConnector2(connector, getDatabase());
15879
+ console.log(chalk2.green("\u2713") + ` ${meta.displayName} promoted \u2014 will rank higher in search`);
15880
+ });
15881
+ program2.command("demote").argument("<connector>", "Connector to demote").description("Remove promotion from a connector").action((connector) => {
15882
+ const { demoteConnector: demoteConnector2 } = (init_promotions(), __toCommonJS(exports_promotions));
15883
+ const removed = demoteConnector2(connector, getDatabase());
15884
+ if (removed)
15885
+ console.log(chalk2.green("\u2713") + ` ${connector} demoted`);
15886
+ else
15887
+ console.log(chalk2.dim(`${connector} was not promoted`));
15888
+ });
15889
+ var jobsCmd = program2.command("jobs").description("Manage scheduled connector jobs");
15890
+ jobsCmd.command("add").description("Add a scheduled job").requiredOption("--name <name>", "Job name").requiredOption("--connector <connector>", "Connector name").requiredOption("--command <command>", "Command to run").requiredOption("--cron <cron>", "Cron expression (5-field)").option("--args <args>", "Command args (space-separated)").option("--strip", "Apply LLM stripping to output").option("--json", "Output as JSON").action((options) => {
15891
+ const db = getDatabase();
15892
+ const args = options.args ? options.args.split(" ") : [];
15893
+ const job = createJob({ name: options.name, connector: options.connector, command: options.command, args, cron: options.cron, strip: !!options.strip }, db);
15894
+ if (options.json) {
15895
+ console.log(JSON.stringify(job));
15896
+ return;
15897
+ }
15898
+ console.log(chalk2.green("\u2713") + ` Job created: ${job.name} (${job.cron})`);
15899
+ });
15900
+ jobsCmd.command("list").description("List all jobs").option("--json", "Output as JSON").action((options) => {
15901
+ const jobs = listJobs(getDatabase());
15902
+ if (options.json) {
15903
+ console.log(JSON.stringify(jobs));
15904
+ return;
15905
+ }
15906
+ if (jobs.length === 0) {
15907
+ console.log(chalk2.dim("No jobs configured."));
15908
+ return;
15909
+ }
15910
+ for (const j of jobs) {
15911
+ const status = j.enabled ? chalk2.green("enabled") : chalk2.dim("disabled");
15912
+ const strip = j.strip ? chalk2.cyan(" [strip]") : "";
15913
+ console.log(` ${j.name.padEnd(20)} ${j.connector}.${j.command.padEnd(16)} ${j.cron.padEnd(15)} ${status}${strip}`);
15914
+ }
15915
+ });
15916
+ jobsCmd.command("run").description("Manually trigger a job").argument("<name>", "Job name").option("--json", "Output as JSON").action(async (name, options) => {
15917
+ const db = getDatabase();
15918
+ const job = getJobByName(name, db);
15919
+ if (!job) {
15920
+ console.error(chalk2.red(`Job "${name}" not found`));
15921
+ process.exit(1);
15922
+ }
15923
+ if (!options.json)
15924
+ console.log(chalk2.dim(`Running ${job.connector} ${job.command}...`));
15925
+ const result = await triggerJob(job, db);
15926
+ if (options.json) {
15927
+ console.log(JSON.stringify(result));
15928
+ return;
15929
+ }
15930
+ const icon = result.exit_code === 0 ? chalk2.green("\u2713") : chalk2.red("\u2717");
15931
+ console.log(`${icon} Run ${result.run_id} \u2014 exit ${result.exit_code}`);
15932
+ if (result.output)
15933
+ console.log(result.output.slice(0, 2000));
15934
+ });
15935
+ jobsCmd.command("logs").description("Show recent runs for a job").argument("<name>", "Job name").option("--limit <n>", "Max results", "10").option("--json", "Output as JSON").action((name, options) => {
15936
+ const db = getDatabase();
15937
+ const job = getJobByName(name, db);
15938
+ if (!job) {
15939
+ console.error(chalk2.red(`Job "${name}" not found`));
15940
+ process.exit(1);
15941
+ }
15942
+ const runs = listJobRuns(job.id, parseInt(options.limit), db);
15943
+ if (options.json) {
15944
+ console.log(JSON.stringify(runs));
15945
+ return;
15946
+ }
15947
+ if (runs.length === 0) {
15948
+ console.log(chalk2.dim("No runs yet."));
15949
+ return;
15950
+ }
15951
+ for (const r of runs) {
15952
+ const icon = r.exit_code === 0 ? chalk2.green("\u2713") : chalk2.red("\u2717");
15953
+ console.log(` ${icon} ${r.started_at.slice(0, 19)} \u2014 exit ${r.exit_code ?? "?"}`);
15954
+ }
15955
+ });
15956
+ jobsCmd.command("enable").description("Enable a job").argument("<name>").action((name) => {
15957
+ const db = getDatabase();
15958
+ const job = getJobByName(name, db);
15959
+ if (!job) {
15960
+ console.error(chalk2.red(`Job "${name}" not found`));
15961
+ process.exit(1);
15962
+ }
15963
+ updateJob(job.id, { enabled: true }, db);
15964
+ console.log(chalk2.green("\u2713") + ` Job "${name}" enabled`);
15965
+ });
15966
+ jobsCmd.command("disable").description("Disable a job").argument("<name>").action((name) => {
15967
+ const db = getDatabase();
15968
+ const job = getJobByName(name, db);
15969
+ if (!job) {
15970
+ console.error(chalk2.red(`Job "${name}" not found`));
15971
+ process.exit(1);
15972
+ }
15973
+ updateJob(job.id, { enabled: false }, db);
15974
+ console.log(chalk2.green("\u2713") + ` Job "${name}" disabled`);
15975
+ });
15976
+ jobsCmd.command("delete").description("Delete a job").argument("<name>").action((name) => {
15977
+ const db = getDatabase();
15978
+ const job = getJobByName(name, db);
15979
+ if (!job) {
15980
+ console.error(chalk2.red(`Job "${name}" not found`));
15981
+ process.exit(1);
15982
+ }
15983
+ deleteJob(job.id, db);
15984
+ console.log(chalk2.green("\u2713") + ` Job "${name}" deleted`);
15985
+ });
15986
+ var workflowsCmd = program2.command("workflows").description("Manage connector workflows (sequential pipelines)");
15987
+ workflowsCmd.command("add").description("Create a workflow from a JSON steps array").requiredOption("--name <name>", "Workflow name").requiredOption("--steps <json>", `Steps JSON array, e.g. '[{"connector":"stripe","command":"products list"}]'`).option("--json", "Output as JSON").action((options) => {
15988
+ let steps;
15989
+ try {
15990
+ steps = JSON.parse(options.steps);
15991
+ } catch {
15992
+ console.error(chalk2.red("Invalid JSON for --steps"));
15993
+ process.exit(1);
15994
+ }
15995
+ const wf = createWorkflow({ name: options.name, steps }, getDatabase());
15996
+ if (options.json) {
15997
+ console.log(JSON.stringify(wf));
15998
+ return;
15999
+ }
16000
+ console.log(chalk2.green("\u2713") + ` Workflow "${wf.name}" created (${wf.steps.length} steps)`);
16001
+ });
16002
+ workflowsCmd.command("list").description("List all workflows").option("--json", "Output as JSON").action((options) => {
16003
+ const wfs = listWorkflows(getDatabase());
16004
+ if (options.json) {
16005
+ console.log(JSON.stringify(wfs));
16006
+ return;
16007
+ }
16008
+ if (wfs.length === 0) {
16009
+ console.log(chalk2.dim("No workflows configured."));
16010
+ return;
16011
+ }
16012
+ for (const wf of wfs) {
16013
+ const status = wf.enabled ? chalk2.green("enabled") : chalk2.dim("disabled");
16014
+ console.log(` ${wf.name.padEnd(20)} ${String(wf.steps.length).padStart(2)} steps ${status}`);
16015
+ }
16016
+ });
16017
+ workflowsCmd.command("run").description("Run a workflow").argument("<name>", "Workflow name").option("--json", "Output as JSON").action(async (name, options) => {
16018
+ const wf = getWorkflowByName(name, getDatabase());
16019
+ if (!wf) {
16020
+ console.error(chalk2.red(`Workflow "${name}" not found`));
16021
+ process.exit(1);
16022
+ }
16023
+ if (!options.json)
16024
+ console.log(chalk2.dim(`Running workflow "${wf.name}" (${wf.steps.length} steps)...`));
16025
+ const result = await runWorkflow(wf);
16026
+ if (options.json) {
16027
+ console.log(JSON.stringify(result));
16028
+ return;
16029
+ }
16030
+ for (const step of result.steps) {
16031
+ const icon = step.exit_code === 0 ? chalk2.green("\u2713") : chalk2.red("\u2717");
16032
+ console.log(` ${icon} Step ${step.step}: ${step.connector} ${step.command}`);
16033
+ }
16034
+ console.log(result.success ? chalk2.green(`
16035
+ Workflow completed`) : chalk2.red(`
16036
+ Workflow failed`));
16037
+ });
16038
+ workflowsCmd.command("delete").description("Delete a workflow").argument("<name>").action((name) => {
16039
+ const wf = getWorkflowByName(name, getDatabase());
16040
+ if (!wf) {
16041
+ console.error(chalk2.red(`Workflow "${name}" not found`));
16042
+ process.exit(1);
16043
+ }
16044
+ deleteWorkflow(wf.id, getDatabase());
16045
+ console.log(chalk2.green("\u2713") + ` Workflow "${name}" deleted`);
16046
+ });
16047
+ var llmCmd = program2.command("llm").description("Manage LLM provider for output stripping");
16048
+ llmCmd.command("set").description("Configure LLM provider and API key").requiredOption("--provider <provider>", "Provider: cerebras, groq, openai, anthropic").requiredOption("--key <key>", "API key").option("--model <model>", "Model name (defaults to provider default)").option("--json", "Output as JSON").action((options) => {
16049
+ const provider = options.provider;
16050
+ const validProviders = ["cerebras", "groq", "openai", "anthropic"];
16051
+ if (!validProviders.includes(provider)) {
16052
+ console.error(chalk2.red(`Unknown provider "${provider}". Valid: ${validProviders.join(", ")}`));
16053
+ process.exit(1);
16054
+ }
16055
+ const model = options.model || PROVIDER_DEFAULTS[provider].model;
16056
+ const existing = getLlmConfig();
16057
+ saveLlmConfig({ provider, model, api_key: options.key, strip: existing?.strip ?? false });
16058
+ if (options.json) {
16059
+ console.log(JSON.stringify({ provider, model, key: maskKey(options.key), strip: existing?.strip ?? false }));
16060
+ } else {
16061
+ console.log(chalk2.green("\u2713") + ` LLM configured: ${provider} / ${model}`);
16062
+ console.log(` Key: ${maskKey(options.key)}`);
16063
+ console.log(` Strip: ${existing?.strip ? chalk2.green("enabled") : chalk2.dim("disabled")} (run 'connectors llm strip enable' to turn on)`);
16064
+ }
16065
+ });
16066
+ llmCmd.command("status").description("Show current LLM configuration").option("--json", "Output as JSON").action((options) => {
16067
+ const config = getLlmConfig();
16068
+ if (!config) {
16069
+ if (options.json)
16070
+ console.log(JSON.stringify({ configured: false }));
16071
+ else
16072
+ console.log(chalk2.dim("No LLM configured. Run: connectors llm set --provider <provider> --key <key>"));
16073
+ return;
16074
+ }
16075
+ if (options.json) {
16076
+ console.log(JSON.stringify({ configured: true, provider: config.provider, model: config.model, key: maskKey(config.api_key), strip: config.strip }));
16077
+ } else {
16078
+ console.log(chalk2.bold("LLM Configuration"));
16079
+ console.log(` Provider : ${config.provider}`);
16080
+ console.log(` Model : ${config.model}`);
16081
+ console.log(` Key : ${maskKey(config.api_key)}`);
16082
+ console.log(` Strip : ${config.strip ? chalk2.green("enabled") : chalk2.red("disabled")}`);
16083
+ }
16084
+ });
16085
+ llmCmd.command("strip").description("Enable or disable global output stripping").argument("<action>", "enable or disable").action((action) => {
16086
+ if (action !== "enable" && action !== "disable") {
16087
+ console.error(chalk2.red('Action must be "enable" or "disable"'));
16088
+ process.exit(1);
16089
+ }
16090
+ try {
16091
+ setLlmStrip(action === "enable");
16092
+ console.log(chalk2.green("\u2713") + ` Output stripping ${action}d`);
16093
+ } catch (e) {
16094
+ console.error(chalk2.red(String(e instanceof Error ? e.message : e)));
16095
+ process.exit(1);
16096
+ }
16097
+ });
16098
+ llmCmd.command("test").description("Test current LLM configuration with a sample prompt").option("--json", "Output as JSON").action(async (options) => {
16099
+ const config = getLlmConfig();
16100
+ if (!config) {
16101
+ console.error(chalk2.red("No LLM configured. Run: connectors llm set --provider <provider> --key <key>"));
16102
+ process.exit(1);
16103
+ }
16104
+ if (!options.json)
16105
+ console.log(chalk2.dim(`Testing ${config.provider} / ${config.model}...`));
16106
+ try {
16107
+ const client = new LLMClient(config);
16108
+ const result = await client.complete('You are a helpful assistant. Respond with exactly: {"status":"ok"}', "ping");
16109
+ if (options.json) {
16110
+ console.log(JSON.stringify({ success: true, provider: result.provider, model: result.model, latency_ms: result.latency_ms, response: result.content }));
16111
+ } else {
16112
+ console.log(chalk2.green("\u2713") + ` Response received in ${result.latency_ms}ms`);
16113
+ console.log(` ${result.content.trim()}`);
16114
+ }
16115
+ } catch (e) {
16116
+ if (options.json)
16117
+ console.log(JSON.stringify({ success: false, error: String(e instanceof Error ? e.message : e) }));
16118
+ else
16119
+ console.error(chalk2.red("\u2717 " + String(e instanceof Error ? e.message : e)));
16120
+ process.exit(1);
16121
+ }
16122
+ });
16123
+ llmCmd.command("providers").description("List supported LLM providers").option("--json", "Output as JSON").action((options) => {
16124
+ const providers = [
16125
+ { name: "cerebras", baseUrl: "https://api.cerebras.ai/v1", defaultModel: PROVIDER_DEFAULTS.cerebras.model, compatible: "OpenAI" },
16126
+ { name: "groq", baseUrl: "https://api.groq.com/openai/v1", defaultModel: PROVIDER_DEFAULTS.groq.model, compatible: "OpenAI" },
16127
+ { name: "openai", baseUrl: "https://api.openai.com/v1", defaultModel: PROVIDER_DEFAULTS.openai.model, compatible: "OpenAI" },
16128
+ { name: "anthropic", baseUrl: "https://api.anthropic.com/v1", defaultModel: PROVIDER_DEFAULTS.anthropic.model, compatible: "Anthropic" }
16129
+ ];
16130
+ if (options.json) {
16131
+ console.log(JSON.stringify(providers));
16132
+ return;
16133
+ }
16134
+ console.log(chalk2.bold("Supported LLM Providers"));
16135
+ for (const p of providers) {
16136
+ console.log(` ${chalk2.cyan(p.name.padEnd(12))} ${p.defaultModel.padEnd(30)} ${chalk2.dim(p.baseUrl)}`);
16137
+ }
16138
+ });
14271
16139
  program2.parse();