runline 0.1.0

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 (230) hide show
  1. package/.pi/extensions/runline-context/index.ts +135 -0
  2. package/.pi/extensions/runline-context/package.json +17 -0
  3. package/README.md +273 -0
  4. package/dist/commands/actions.d.ts +3 -0
  5. package/dist/commands/actions.js +43 -0
  6. package/dist/commands/connection.d.ts +11 -0
  7. package/dist/commands/connection.js +56 -0
  8. package/dist/commands/exec.d.ts +5 -0
  9. package/dist/commands/exec.js +46 -0
  10. package/dist/commands/init.d.ts +4 -0
  11. package/dist/commands/init.js +26 -0
  12. package/dist/commands/plugin.d.ts +10 -0
  13. package/dist/commands/plugin.js +57 -0
  14. package/dist/config/index.d.ts +3 -0
  15. package/dist/config/index.js +2 -0
  16. package/dist/config/loader.d.ts +11 -0
  17. package/dist/config/loader.js +82 -0
  18. package/dist/config/types.d.ts +9 -0
  19. package/dist/config/types.js +5 -0
  20. package/dist/core/engine.d.ts +21 -0
  21. package/dist/core/engine.js +280 -0
  22. package/dist/index.d.ts +16 -0
  23. package/dist/index.js +9 -0
  24. package/dist/main.d.ts +2 -0
  25. package/dist/main.js +127 -0
  26. package/dist/plugin/api.d.ts +32 -0
  27. package/dist/plugin/api.js +68 -0
  28. package/dist/plugin/installer.d.ts +27 -0
  29. package/dist/plugin/installer.js +181 -0
  30. package/dist/plugin/loader.d.ts +13 -0
  31. package/dist/plugin/loader.js +164 -0
  32. package/dist/plugin/registry.d.ts +18 -0
  33. package/dist/plugin/registry.js +43 -0
  34. package/dist/plugin/types.d.ts +40 -0
  35. package/dist/plugin/types.js +1 -0
  36. package/dist/plugins/actionNetwork/src/index.js +353 -0
  37. package/dist/plugins/activeCampaign/src/index.js +711 -0
  38. package/dist/plugins/adalo/src/index.js +131 -0
  39. package/dist/plugins/affinity/src/index.js +279 -0
  40. package/dist/plugins/agileCrm/src/index.js +415 -0
  41. package/dist/plugins/airtable/src/index.js +280 -0
  42. package/dist/plugins/airtop/src/index.js +527 -0
  43. package/dist/plugins/apiTemplateIo/src/index.js +86 -0
  44. package/dist/plugins/asana/src/index.js +413 -0
  45. package/dist/plugins/autopilot/src/index.js +203 -0
  46. package/dist/plugins/bambooHr/src/index.js +252 -0
  47. package/dist/plugins/bannerbear/src/index.js +100 -0
  48. package/dist/plugins/baserow/src/index.js +180 -0
  49. package/dist/plugins/beeminder/src/index.js +298 -0
  50. package/dist/plugins/bitly/src/index.js +107 -0
  51. package/dist/plugins/bitwarden/src/index.js +383 -0
  52. package/dist/plugins/box/src/index.js +300 -0
  53. package/dist/plugins/brandfetch/src/index.js +80 -0
  54. package/dist/plugins/brevo/src/index.js +305 -0
  55. package/dist/plugins/bubble/src/index.js +181 -0
  56. package/dist/plugins/chargebee/src/index.js +126 -0
  57. package/dist/plugins/circleci/src/index.js +111 -0
  58. package/dist/plugins/ciscoWebex/src/index.js +245 -0
  59. package/dist/plugins/clearbit/src/index.js +103 -0
  60. package/dist/plugins/clickup/src/index.js +1043 -0
  61. package/dist/plugins/clockify/src/index.js +443 -0
  62. package/dist/plugins/cloudflare/src/index.js +93 -0
  63. package/dist/plugins/cockpit/src/index.js +131 -0
  64. package/dist/plugins/coda/src/index.js +327 -0
  65. package/dist/plugins/coingecko/src/index.js +244 -0
  66. package/dist/plugins/contentful/src/index.js +146 -0
  67. package/dist/plugins/convertkit/src/index.js +270 -0
  68. package/dist/plugins/copper/src/index.js +140 -0
  69. package/dist/plugins/cortex/src/index.js +147 -0
  70. package/dist/plugins/currents/src/index.js +405 -0
  71. package/dist/plugins/customerIo/src/index.js +184 -0
  72. package/dist/plugins/databricks/src/index.js +342 -0
  73. package/dist/plugins/deepl/src/index.js +87 -0
  74. package/dist/plugins/demio/src/index.js +111 -0
  75. package/dist/plugins/dhl/src/index.js +40 -0
  76. package/dist/plugins/discord/src/index.js +275 -0
  77. package/dist/plugins/discourse/src/index.js +273 -0
  78. package/dist/plugins/disqus/src/index.js +145 -0
  79. package/dist/plugins/docker/src/index.js +76 -0
  80. package/dist/plugins/drift/src/index.js +89 -0
  81. package/dist/plugins/dropbox/src/index.js +159 -0
  82. package/dist/plugins/dropcontact/src/index.js +59 -0
  83. package/dist/plugins/egoi/src/index.js +151 -0
  84. package/dist/plugins/elasticsearch/src/index.js +157 -0
  85. package/dist/plugins/emelia/src/index.js +174 -0
  86. package/dist/plugins/erpnext/src/index.js +121 -0
  87. package/dist/plugins/facebookGraph/src/index.js +57 -0
  88. package/dist/plugins/freshdesk/src/index.js +320 -0
  89. package/dist/plugins/freshservice/src/index.js +146 -0
  90. package/dist/plugins/freshworksCrm/src/index.js +149 -0
  91. package/dist/plugins/getresponse/src/index.js +140 -0
  92. package/dist/plugins/ghost/src/index.js +192 -0
  93. package/dist/plugins/github/src/index.js +630 -0
  94. package/dist/plugins/gitlab/src/index.js +358 -0
  95. package/dist/plugins/gong/src/index.js +126 -0
  96. package/dist/plugins/gotify/src/index.js +77 -0
  97. package/dist/plugins/gotowebinar/src/index.js +316 -0
  98. package/dist/plugins/grafana/src/index.js +250 -0
  99. package/dist/plugins/graphql/src/index.js +78 -0
  100. package/dist/plugins/grist/src/index.js +106 -0
  101. package/dist/plugins/hackernews/src/index.js +89 -0
  102. package/dist/plugins/halopsa/src/index.js +79 -0
  103. package/dist/plugins/harvest/src/index.js +163 -0
  104. package/dist/plugins/helpscout/src/index.js +176 -0
  105. package/dist/plugins/highlevel/src/index.js +172 -0
  106. package/dist/plugins/homeAssistant/src/index.js +148 -0
  107. package/dist/plugins/hubspot/src/index.js +176 -0
  108. package/dist/plugins/humanticAi/src/index.js +60 -0
  109. package/dist/plugins/hunter/src/index.js +59 -0
  110. package/dist/plugins/intercom/src/index.js +156 -0
  111. package/dist/plugins/iterable/src/index.js +139 -0
  112. package/dist/plugins/jenkins/src/index.js +132 -0
  113. package/dist/plugins/jira/src/index.js +229 -0
  114. package/dist/plugins/keap/src/index.js +502 -0
  115. package/dist/plugins/kobotoolbox/src/index.js +281 -0
  116. package/dist/plugins/lemlist/src/index.js +231 -0
  117. package/dist/plugins/linear/src/index.js +133 -0
  118. package/dist/plugins/lingvanex/src/index.js +31 -0
  119. package/dist/plugins/linkedin/src/index.js +80 -0
  120. package/dist/plugins/lonescale/src/index.js +119 -0
  121. package/dist/plugins/magento/src/index.js +300 -0
  122. package/dist/plugins/mailcheck/src/index.js +27 -0
  123. package/dist/plugins/mailchimp/src/index.js +321 -0
  124. package/dist/plugins/mailerlite/src/index.js +123 -0
  125. package/dist/plugins/mailgun/src/index.js +48 -0
  126. package/dist/plugins/mailjet/src/index.js +155 -0
  127. package/dist/plugins/mandrill/src/index.js +145 -0
  128. package/dist/plugins/marketstack/src/index.js +97 -0
  129. package/dist/plugins/matrix/src/index.js +194 -0
  130. package/dist/plugins/mattermost/src/index.js +331 -0
  131. package/dist/plugins/mautic/src/index.js +311 -0
  132. package/dist/plugins/medium/src/index.js +77 -0
  133. package/dist/plugins/messagebird/src/index.js +57 -0
  134. package/dist/plugins/metabase/src/index.js +130 -0
  135. package/dist/plugins/misp/src/index.js +476 -0
  136. package/dist/plugins/mocean/src/index.js +67 -0
  137. package/dist/plugins/monday/src/index.js +231 -0
  138. package/dist/plugins/monicaCrm/src/index.js +52 -0
  139. package/dist/plugins/msg91/src/index.js +31 -0
  140. package/dist/plugins/nasa/src/index.js +146 -0
  141. package/dist/plugins/netlify/src/index.js +151 -0
  142. package/dist/plugins/netscalerAdc/src/index.js +131 -0
  143. package/dist/plugins/nextcloud/src/index.js +263 -0
  144. package/dist/plugins/nocodb/src/index.js +130 -0
  145. package/dist/plugins/notion/src/index.js +112 -0
  146. package/dist/plugins/npm/src/index.js +104 -0
  147. package/dist/plugins/odoo/src/index.js +157 -0
  148. package/dist/plugins/okta/src/index.js +141 -0
  149. package/dist/plugins/oneSimpleApi/src/index.js +155 -0
  150. package/dist/plugins/onfleet/src/index.js +254 -0
  151. package/dist/plugins/openThesaurus/src/index.js +32 -0
  152. package/dist/plugins/openweathermap/src/index.js +60 -0
  153. package/dist/plugins/oura/src/index.js +62 -0
  154. package/dist/plugins/paddle/src/index.js +247 -0
  155. package/dist/plugins/pagerduty/src/index.js +201 -0
  156. package/dist/plugins/paypal/src/index.js +106 -0
  157. package/dist/plugins/peekalink/src/index.js +35 -0
  158. package/dist/plugins/phantombuster/src/index.js +94 -0
  159. package/dist/plugins/philipsHue/src/index.js +98 -0
  160. package/dist/plugins/pipedrive/src/index.js +169 -0
  161. package/dist/plugins/plivo/src/index.js +66 -0
  162. package/dist/plugins/postbin/src/index.js +93 -0
  163. package/dist/plugins/posthog/src/index.js +113 -0
  164. package/dist/plugins/profitwell/src/index.js +50 -0
  165. package/dist/plugins/pushbullet/src/index.js +102 -0
  166. package/dist/plugins/pushcut/src/index.js +39 -0
  167. package/dist/plugins/pushover/src/index.js +65 -0
  168. package/dist/plugins/quickbase/src/index.js +153 -0
  169. package/dist/plugins/quickbooks/src/index.js +73 -0
  170. package/dist/plugins/quickchart/src/index.js +36 -0
  171. package/dist/plugins/raindrop/src/index.js +209 -0
  172. package/dist/plugins/reddit/src/index.js +185 -0
  173. package/dist/plugins/rocketchat/src/index.js +53 -0
  174. package/dist/plugins/rundeck/src/index.js +62 -0
  175. package/dist/plugins/salesforce/src/index.js +94 -0
  176. package/dist/plugins/salesmate/src/index.js +83 -0
  177. package/dist/plugins/securityScorecard/src/index.js +200 -0
  178. package/dist/plugins/segment/src/index.js +125 -0
  179. package/dist/plugins/sendgrid/src/index.js +187 -0
  180. package/dist/plugins/sendy/src/index.js +138 -0
  181. package/dist/plugins/sentry/src/index.js +233 -0
  182. package/dist/plugins/servicenow/src/index.js +108 -0
  183. package/dist/plugins/shopify/src/index.js +222 -0
  184. package/dist/plugins/signl4/src/index.js +61 -0
  185. package/dist/plugins/slack/src/index.js +236 -0
  186. package/dist/plugins/sms77/src/index.js +63 -0
  187. package/dist/plugins/splunk/src/index.js +207 -0
  188. package/dist/plugins/spotify/src/index.js +188 -0
  189. package/dist/plugins/stackby/src/index.js +82 -0
  190. package/dist/plugins/storyblok/src/index.js +141 -0
  191. package/dist/plugins/strapi/src/index.js +152 -0
  192. package/dist/plugins/strava/src/index.js +137 -0
  193. package/dist/plugins/stripe/src/index.js +222 -0
  194. package/dist/plugins/supabase/src/index.js +121 -0
  195. package/dist/plugins/syncromsp/src/index.js +255 -0
  196. package/dist/plugins/tapfiliate/src/index.js +125 -0
  197. package/dist/plugins/telegram/src/index.js +233 -0
  198. package/dist/plugins/thehive/src/index.js +142 -0
  199. package/dist/plugins/thehiveProject/src/index.js +194 -0
  200. package/dist/plugins/todoist/src/index.js +244 -0
  201. package/dist/plugins/travisci/src/index.js +71 -0
  202. package/dist/plugins/trello/src/index.js +341 -0
  203. package/dist/plugins/twake/src/index.js +40 -0
  204. package/dist/plugins/twilio/src/index.js +75 -0
  205. package/dist/plugins/twist/src/index.js +90 -0
  206. package/dist/plugins/twitter/src/index.js +123 -0
  207. package/dist/plugins/unleashedSoftware/src/index.js +84 -0
  208. package/dist/plugins/uplead/src/index.js +59 -0
  209. package/dist/plugins/uproc/src/index.js +34 -0
  210. package/dist/plugins/uptimerobot/src/index.js +264 -0
  211. package/dist/plugins/urlscanio/src/index.js +64 -0
  212. package/dist/plugins/vero/src/index.js +80 -0
  213. package/dist/plugins/vonage/src/index.js +42 -0
  214. package/dist/plugins/wekan/src/index.js +91 -0
  215. package/dist/plugins/woocommerce/src/index.js +92 -0
  216. package/dist/plugins/wordpress/src/index.js +121 -0
  217. package/dist/plugins/xero/src/index.js +136 -0
  218. package/dist/plugins/yourls/src/index.js +56 -0
  219. package/dist/plugins/zammad/src/index.js +91 -0
  220. package/dist/plugins/zendesk/src/index.js +137 -0
  221. package/dist/plugins/zoho/src/index.js +85 -0
  222. package/dist/plugins/zoom/src/index.js +122 -0
  223. package/dist/plugins/zulip/src/index.js +170 -0
  224. package/dist/sdk.d.ts +38 -0
  225. package/dist/sdk.js +105 -0
  226. package/dist/utils/cli.d.ts +13 -0
  227. package/dist/utils/cli.js +32 -0
  228. package/dist/utils/output.d.ts +4 -0
  229. package/dist/utils/output.js +13 -0
  230. package/package.json +57 -0
@@ -0,0 +1,172 @@
1
+ const BASE = "https://services.leadconnectorhq.com";
2
+ function getConn(ctx) {
3
+ return {
4
+ token: ctx.connection.config.accessToken,
5
+ locationId: ctx.connection.config.locationId,
6
+ };
7
+ }
8
+ async function api(token, method, path, body, qs) {
9
+ const url = new URL(`${BASE}${path}`);
10
+ if (qs) {
11
+ for (const [k, v] of Object.entries(qs)) {
12
+ if (v !== undefined && v !== null)
13
+ url.searchParams.set(k, String(v));
14
+ }
15
+ }
16
+ const init = { method, headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", Accept: "application/json", Version: "2021-07-28" } };
17
+ if (body && Object.keys(body).length > 0)
18
+ init.body = JSON.stringify(body);
19
+ const res = await fetch(url.toString(), init);
20
+ if (!res.ok)
21
+ throw new Error(`HighLevel error ${res.status}: ${await res.text()}`);
22
+ const text = await res.text();
23
+ return text ? JSON.parse(text) : { success: true };
24
+ }
25
+ export default function highlevel(rl) {
26
+ rl.setName("highlevel");
27
+ rl.setVersion("0.1.0");
28
+ rl.setConnectionSchema({
29
+ accessToken: { type: "string", required: true, description: "OAuth2 access token", env: "HIGHLEVEL_ACCESS_TOKEN" },
30
+ locationId: { type: "string", required: true, description: "Location ID", env: "HIGHLEVEL_LOCATION_ID" },
31
+ });
32
+ // ── Contact ─────────────────────────────────────────
33
+ rl.registerAction("contact.upsert", { description: "Create or update a contact (upsert by email/phone)",
34
+ inputSchema: { email: { type: "string", required: false }, phone: { type: "string", required: false }, firstName: { type: "string", required: false }, lastName: { type: "string", required: false }, name: { type: "string", required: false }, address1: { type: "string", required: false }, city: { type: "string", required: false }, state: { type: "string", required: false }, postalCode: { type: "string", required: false }, website: { type: "string", required: false }, tags: { type: "object", required: false, description: "Array of tag strings" }, timezone: { type: "string", required: false }, dnd: { type: "boolean", required: false }, source: { type: "string", required: false }, customFields: { type: "object", required: false, description: "Array of {id, field_value}" } },
35
+ async execute(input, ctx) {
36
+ const { token, locationId } = getConn(ctx);
37
+ const body = { ...input, locationId };
38
+ if (typeof body.tags === "string")
39
+ body.tags = body.tags.split(",").map((t) => t.trim());
40
+ const res = await api(token, "POST", "/contacts/upsert/", body);
41
+ return res.contact ?? res;
42
+ } });
43
+ rl.registerAction("contact.get", { description: "Get a contact by ID", inputSchema: { id: { type: "string", required: true } },
44
+ async execute(input, ctx) { const { token } = getConn(ctx); const res = await api(token, "GET", `/contacts/${input.id}/`); return res.contact ?? res; } });
45
+ rl.registerAction("contact.list", { description: "List contacts",
46
+ inputSchema: { limit: { type: "number", required: false }, query: { type: "string", required: false, description: "Search by name, phone, email, tags, company" }, sortBy: { type: "string", required: false, description: "date_added or date_updated" }, order: { type: "string", required: false, description: "asc or desc" } },
47
+ async execute(input, ctx) {
48
+ const { token, locationId } = getConn(ctx);
49
+ const p = (input ?? {});
50
+ const qs = { locationId };
51
+ if (p.limit)
52
+ qs.limit = p.limit;
53
+ if (p.query)
54
+ qs.query = p.query;
55
+ if (p.sortBy)
56
+ qs.sortBy = p.sortBy;
57
+ if (p.order)
58
+ qs.order = p.order;
59
+ const res = await api(token, "GET", "/contacts/", undefined, qs);
60
+ return res.contacts ?? res;
61
+ } });
62
+ rl.registerAction("contact.update", { description: "Update a contact",
63
+ inputSchema: { id: { type: "string", required: true }, email: { type: "string", required: false }, phone: { type: "string", required: false }, firstName: { type: "string", required: false }, lastName: { type: "string", required: false }, name: { type: "string", required: false }, address1: { type: "string", required: false }, city: { type: "string", required: false }, state: { type: "string", required: false }, postalCode: { type: "string", required: false }, website: { type: "string", required: false }, tags: { type: "object", required: false }, timezone: { type: "string", required: false }, customFields: { type: "object", required: false } },
64
+ async execute(input, ctx) {
65
+ const { token } = getConn(ctx);
66
+ const { id, ...body } = input;
67
+ if (typeof body.tags === "string")
68
+ body.tags = body.tags.split(",").map((t) => t.trim());
69
+ const res = await api(token, "PUT", `/contacts/${id}/`, body);
70
+ return res.contact ?? res;
71
+ } });
72
+ rl.registerAction("contact.delete", { description: "Delete a contact", inputSchema: { id: { type: "string", required: true } },
73
+ async execute(input, ctx) { const { token } = getConn(ctx); await api(token, "DELETE", `/contacts/${input.id}/`); return { success: true }; } });
74
+ // ── Opportunity ─────────────────────────────────────
75
+ rl.registerAction("opportunity.create", { description: "Create an opportunity",
76
+ inputSchema: { contactId: { type: "string", required: true }, name: { type: "string", required: true }, status: { type: "string", required: true, description: "open, won, lost, or abandoned" }, pipelineId: { type: "string", required: true }, stageId: { type: "string", required: false, description: "Pipeline stage ID" }, monetaryValue: { type: "number", required: false }, assignedTo: { type: "string", required: false }, companyName: { type: "string", required: false }, tags: { type: "object", required: false } },
77
+ async execute(input, ctx) {
78
+ const { token, locationId } = getConn(ctx);
79
+ const body = { ...input, locationId };
80
+ if (body.stageId) {
81
+ body.pipelineStageId = body.stageId;
82
+ delete body.stageId;
83
+ }
84
+ if (typeof body.tags === "string")
85
+ body.tags = body.tags.split(",").map((t) => t.trim());
86
+ return api(token, "POST", "/opportunities/", body);
87
+ } });
88
+ rl.registerAction("opportunity.get", { description: "Get an opportunity", inputSchema: { id: { type: "string", required: true } },
89
+ async execute(input, ctx) { const { token } = getConn(ctx); return api(token, "GET", `/opportunities/${input.id}`); } });
90
+ rl.registerAction("opportunity.list", { description: "List opportunities",
91
+ inputSchema: { limit: { type: "number", required: false }, pipelineId: { type: "string", required: false }, stageId: { type: "string", required: false }, status: { type: "string", required: false }, assignedTo: { type: "string", required: false }, query: { type: "string", required: false }, startDate: { type: "string", required: false }, endDate: { type: "string", required: false } },
92
+ async execute(input, ctx) {
93
+ const { token, locationId } = getConn(ctx);
94
+ const p = (input ?? {});
95
+ const qs = { location_id: locationId };
96
+ if (p.limit)
97
+ qs.limit = p.limit;
98
+ if (p.pipelineId)
99
+ qs.pipeline_id = p.pipelineId;
100
+ if (p.stageId)
101
+ qs.pipeline_stage_id = p.stageId;
102
+ if (p.status)
103
+ qs.status = p.status;
104
+ if (p.assignedTo)
105
+ qs.assigned_to = p.assignedTo;
106
+ if (p.query)
107
+ qs.q = p.query;
108
+ if (p.startDate)
109
+ qs.startDate = new Date(p.startDate).getTime();
110
+ if (p.endDate)
111
+ qs.endDate = new Date(p.endDate).getTime();
112
+ const res = await api(token, "GET", "/opportunities/search", undefined, qs);
113
+ return res.opportunities ?? res;
114
+ } });
115
+ rl.registerAction("opportunity.update", { description: "Update an opportunity",
116
+ inputSchema: { id: { type: "string", required: true }, name: { type: "string", required: false }, status: { type: "string", required: false }, pipelineId: { type: "string", required: false }, stageId: { type: "string", required: false }, monetaryValue: { type: "number", required: false }, assignedTo: { type: "string", required: false } },
117
+ async execute(input, ctx) {
118
+ const { token } = getConn(ctx);
119
+ const { id, ...body } = input;
120
+ if (body.stageId) {
121
+ body.pipelineStageId = body.stageId;
122
+ delete body.stageId;
123
+ }
124
+ return api(token, "PUT", `/opportunities/${id}`, body);
125
+ } });
126
+ rl.registerAction("opportunity.delete", { description: "Delete an opportunity", inputSchema: { id: { type: "string", required: true } },
127
+ async execute(input, ctx) { const { token } = getConn(ctx); await api(token, "DELETE", `/opportunities/${input.id}`); return { success: true }; } });
128
+ // ── Task (scoped to contact) ────────────────────────
129
+ rl.registerAction("task.create", { description: "Create a task for a contact",
130
+ inputSchema: { contactId: { type: "string", required: true }, title: { type: "string", required: true }, dueDate: { type: "string", required: true, description: "ISO datetime" }, completed: { type: "boolean", required: false }, body: { type: "string", required: false }, assignedTo: { type: "string", required: false } },
131
+ async execute(input, ctx) {
132
+ const { token } = getConn(ctx);
133
+ const { contactId, ...body } = input;
134
+ return api(token, "POST", `/contacts/${contactId}/tasks/`, body);
135
+ } });
136
+ rl.registerAction("task.get", { description: "Get a task",
137
+ inputSchema: { contactId: { type: "string", required: true }, taskId: { type: "string", required: true } },
138
+ async execute(input, ctx) { const { token } = getConn(ctx); const p = input; return api(token, "GET", `/contacts/${p.contactId}/tasks/${p.taskId}/`); } });
139
+ rl.registerAction("task.list", { description: "List tasks for a contact",
140
+ inputSchema: { contactId: { type: "string", required: true } },
141
+ async execute(input, ctx) {
142
+ const { token } = getConn(ctx);
143
+ const res = await api(token, "GET", `/contacts/${input.contactId}/tasks/`);
144
+ return res.tasks ?? res;
145
+ } });
146
+ rl.registerAction("task.update", { description: "Update a task",
147
+ inputSchema: { contactId: { type: "string", required: true }, taskId: { type: "string", required: true }, title: { type: "string", required: false }, dueDate: { type: "string", required: false }, completed: { type: "boolean", required: false }, body: { type: "string", required: false }, assignedTo: { type: "string", required: false } },
148
+ async execute(input, ctx) {
149
+ const { token } = getConn(ctx);
150
+ const { contactId, taskId, ...body } = input;
151
+ return api(token, "PUT", `/contacts/${contactId}/tasks/${taskId}/`, body);
152
+ } });
153
+ rl.registerAction("task.delete", { description: "Delete a task",
154
+ inputSchema: { contactId: { type: "string", required: true }, taskId: { type: "string", required: true } },
155
+ async execute(input, ctx) { const { token } = getConn(ctx); const p = input; await api(token, "DELETE", `/contacts/${p.contactId}/tasks/${p.taskId}/`); return { success: true }; } });
156
+ // ── Calendar ────────────────────────────────────────
157
+ rl.registerAction("calendar.bookAppointment", { description: "Book a calendar appointment",
158
+ inputSchema: { calendarId: { type: "string", required: true }, locationId: { type: "string", required: true }, contactId: { type: "string", required: true }, startTime: { type: "string", required: true, description: "ISO datetime with timezone offset" }, endTime: { type: "string", required: false }, title: { type: "string", required: false }, appointmentStatus: { type: "string", required: false, description: "new, confirmed, cancelled, showed, noshow, invalid" }, assignedUserId: { type: "string", required: false }, address: { type: "string", required: false }, toNotify: { type: "boolean", required: false } },
159
+ async execute(input, ctx) { const { token } = getConn(ctx); return api(token, "POST", "/calendars/events/appointments", input); } });
160
+ rl.registerAction("calendar.getFreeSlots", { description: "Get free slots for a calendar",
161
+ inputSchema: { calendarId: { type: "string", required: true }, startDate: { type: "number", required: true, description: "Start date as epoch ms" }, endDate: { type: "number", required: true, description: "End date as epoch ms" }, timezone: { type: "string", required: false }, userId: { type: "string", required: false } },
162
+ async execute(input, ctx) {
163
+ const { token } = getConn(ctx);
164
+ const p = input;
165
+ const qs = { startDate: p.startDate, endDate: p.endDate };
166
+ if (p.timezone)
167
+ qs.timezone = p.timezone;
168
+ if (p.userId)
169
+ qs.userId = p.userId;
170
+ return api(token, "GET", `/calendars/${p.calendarId}/free-slots`, undefined, qs);
171
+ } });
172
+ }
@@ -0,0 +1,148 @@
1
+ async function apiRequest(baseUrl, token, method, endpoint, body, qs) {
2
+ const url = new URL(`${baseUrl}/api${endpoint}`);
3
+ if (qs) {
4
+ for (const [k, v] of Object.entries(qs)) {
5
+ if (v !== undefined && v !== null)
6
+ url.searchParams.set(k, String(v));
7
+ }
8
+ }
9
+ const opts = { method, headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" } };
10
+ if (body && Object.keys(body).length > 0 && method !== "GET" && method !== "DELETE")
11
+ opts.body = JSON.stringify(body);
12
+ const res = await fetch(url.toString(), opts);
13
+ if (!res.ok)
14
+ throw new Error(`Home Assistant API error ${res.status}: ${await res.text()}`);
15
+ return res.json();
16
+ }
17
+ function getConn(ctx) {
18
+ const cfg = ctx.connection.config;
19
+ const ssl = cfg.ssl === true || cfg.ssl === "true";
20
+ const proto = ssl ? "https" : "http";
21
+ return { baseUrl: `${proto}://${cfg.host}:${cfg.port ?? 8123}`, token: cfg.accessToken };
22
+ }
23
+ function ha(ctx, method, endpoint, body, qs) {
24
+ const { baseUrl, token } = getConn(ctx);
25
+ return apiRequest(baseUrl, token, method, endpoint, body, qs);
26
+ }
27
+ export default function homeAssistant(rl) {
28
+ rl.setName("homeAssistant");
29
+ rl.setVersion("0.1.0");
30
+ rl.setConnectionSchema({
31
+ host: { type: "string", required: true, description: "Home Assistant host (e.g. 192.168.1.100)", env: "HASS_HOST" },
32
+ port: { type: "number", required: false, description: "Port (default: 8123)", default: "8123" },
33
+ ssl: { type: "boolean", required: false, description: "Use HTTPS", default: "false" },
34
+ accessToken: { type: "string", required: true, description: "Long-lived access token", env: "HASS_TOKEN" },
35
+ });
36
+ rl.registerAction("config.get", {
37
+ description: "Get Home Assistant configuration",
38
+ async execute(_input, ctx) { return ha(ctx, "GET", "/config"); },
39
+ });
40
+ rl.registerAction("config.check", {
41
+ description: "Check if configuration is valid",
42
+ async execute(_input, ctx) { return ha(ctx, "POST", "/config/core/check_config"); },
43
+ });
44
+ rl.registerAction("service.list", {
45
+ description: "List available services",
46
+ async execute(_input, ctx) { return ha(ctx, "GET", "/services"); },
47
+ });
48
+ rl.registerAction("service.call", {
49
+ description: "Call a service",
50
+ inputSchema: {
51
+ domain: { type: "string", required: true, description: "Service domain (e.g. light, switch)" },
52
+ service: { type: "string", required: true, description: "Service name (e.g. turn_on)" },
53
+ serviceData: { type: "object", required: false, description: "Service data (e.g. {entity_id: 'light.kitchen'})" },
54
+ },
55
+ async execute(input, ctx) {
56
+ const { domain, service, serviceData } = input;
57
+ return ha(ctx, "POST", `/services/${domain}/${service}`, serviceData ?? {});
58
+ },
59
+ });
60
+ rl.registerAction("state.list", {
61
+ description: "List all entity states",
62
+ async execute(_input, ctx) { return ha(ctx, "GET", "/states"); },
63
+ });
64
+ rl.registerAction("state.get", {
65
+ description: "Get state of an entity",
66
+ inputSchema: { entityId: { type: "string", required: true, description: "Entity ID (e.g. light.kitchen)" } },
67
+ async execute(input, ctx) { return ha(ctx, "GET", `/states/${input.entityId}`); },
68
+ });
69
+ rl.registerAction("state.set", {
70
+ description: "Set/update state of an entity",
71
+ inputSchema: {
72
+ entityId: { type: "string", required: true, description: "Entity ID" },
73
+ state: { type: "string", required: true, description: "New state value" },
74
+ attributes: { type: "object", required: false, description: "State attributes" },
75
+ },
76
+ async execute(input, ctx) {
77
+ const { entityId, state, attributes } = input;
78
+ const body = { state };
79
+ if (attributes)
80
+ body.attributes = attributes;
81
+ return ha(ctx, "POST", `/states/${entityId}`, body);
82
+ },
83
+ });
84
+ rl.registerAction("event.list", {
85
+ description: "List event types",
86
+ async execute(_input, ctx) { return ha(ctx, "GET", "/events"); },
87
+ });
88
+ rl.registerAction("event.fire", {
89
+ description: "Fire an event",
90
+ inputSchema: {
91
+ eventType: { type: "string", required: true, description: "Event type" },
92
+ eventData: { type: "object", required: false, description: "Event data" },
93
+ },
94
+ async execute(input, ctx) {
95
+ const { eventType, eventData } = input;
96
+ return ha(ctx, "POST", `/events/${eventType}`, eventData ?? {});
97
+ },
98
+ });
99
+ rl.registerAction("log.getErrors", {
100
+ description: "Get error log",
101
+ async execute(_input, ctx) { return ha(ctx, "GET", "/error_log"); },
102
+ });
103
+ rl.registerAction("log.getLogbook", {
104
+ description: "Get logbook entries",
105
+ inputSchema: {
106
+ entityId: { type: "string", required: false, description: "Filter by entity ID" },
107
+ startTime: { type: "string", required: false, description: "Start time (ISO 8601)" },
108
+ endTime: { type: "string", required: false, description: "End time (ISO 8601)" },
109
+ },
110
+ async execute(input, ctx) {
111
+ const { entityId, startTime, endTime } = (input ?? {});
112
+ let endpoint = "/logbook";
113
+ if (startTime)
114
+ endpoint += `/${startTime}`;
115
+ const qs = {};
116
+ if (entityId)
117
+ qs.entity = entityId;
118
+ if (endTime)
119
+ qs.end_time = endTime;
120
+ return ha(ctx, "GET", endpoint, undefined, qs);
121
+ },
122
+ });
123
+ rl.registerAction("template.render", {
124
+ description: "Render a Jinja2 template",
125
+ inputSchema: { template: { type: "string", required: true, description: "Jinja2 template string" } },
126
+ async execute(input, ctx) { return ha(ctx, "POST", "/template", { template: input.template }); },
127
+ });
128
+ rl.registerAction("history.get", {
129
+ description: "Get state history for entities",
130
+ inputSchema: {
131
+ entityIds: { type: "string", required: false, description: "Comma-separated entity IDs" },
132
+ startTime: { type: "string", required: false, description: "Start time (ISO 8601)" },
133
+ endTime: { type: "string", required: false, description: "End time" },
134
+ },
135
+ async execute(input, ctx) {
136
+ const { entityIds, startTime, endTime } = (input ?? {});
137
+ let endpoint = "/history/period";
138
+ if (startTime)
139
+ endpoint += `/${startTime}`;
140
+ const qs = {};
141
+ if (entityIds)
142
+ qs.filter_entity_id = entityIds;
143
+ if (endTime)
144
+ qs.end_time = endTime;
145
+ return ha(ctx, "GET", endpoint, undefined, qs);
146
+ },
147
+ });
148
+ }
@@ -0,0 +1,176 @@
1
+ const BASE_URL = "https://api.hubapi.com";
2
+ async function apiRequest(token, method, endpoint, body, qs) {
3
+ const url = new URL(`${BASE_URL}${endpoint}`);
4
+ if (qs) {
5
+ for (const [k, v] of Object.entries(qs)) {
6
+ if (v !== undefined && v !== null)
7
+ url.searchParams.set(k, String(v));
8
+ }
9
+ }
10
+ const opts = { method, headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" } };
11
+ if (body && Object.keys(body).length > 0 && method !== "GET" && method !== "DELETE")
12
+ opts.body = JSON.stringify(body);
13
+ const res = await fetch(url.toString(), opts);
14
+ if (!res.ok)
15
+ throw new Error(`HubSpot API error ${res.status}: ${await res.text()}`);
16
+ if (res.status === 204)
17
+ return { success: true };
18
+ return res.json();
19
+ }
20
+ export default function hubspot(rl) {
21
+ rl.setName("hubspot");
22
+ rl.setVersion("0.1.0");
23
+ rl.setConnectionSchema({
24
+ accessToken: { type: "string", required: true, description: "HubSpot private app access token", env: "HUBSPOT_ACCESS_TOKEN" },
25
+ });
26
+ const tok = (ctx) => ctx.connection.config.accessToken;
27
+ // Helper for CRM objects (contacts, companies, deals, tickets)
28
+ function registerCrmObject(resource, objectType) {
29
+ rl.registerAction(`${resource}.create`, {
30
+ description: `Create a ${resource}`, inputSchema: { properties: { type: "object", required: true, description: "Properties as key-value pairs" } },
31
+ async execute(input, ctx) { return apiRequest(tok(ctx), "POST", `/crm/v3/objects/${objectType}`, { properties: input.properties }); },
32
+ });
33
+ rl.registerAction(`${resource}.get`, {
34
+ description: `Get a ${resource}`, inputSchema: { id: { type: "string", required: true, description: `${resource} ID` }, properties: { type: "array", required: false, description: "Properties to return" } },
35
+ async execute(input, ctx) {
36
+ const { id, properties } = input;
37
+ const qs = {};
38
+ if (properties && Array.isArray(properties))
39
+ qs.properties = properties.join(",");
40
+ return apiRequest(tok(ctx), "GET", `/crm/v3/objects/${objectType}/${id}`, undefined, qs);
41
+ },
42
+ });
43
+ rl.registerAction(`${resource}.list`, {
44
+ description: `List ${resource}s`, inputSchema: { limit: { type: "number", required: false, description: "Max results (max 100)" }, after: { type: "string", required: false, description: "Pagination cursor" }, properties: { type: "array", required: false, description: "Properties to return" } },
45
+ async execute(input, ctx) {
46
+ const { limit, after, properties } = (input ?? {});
47
+ const qs = {};
48
+ if (limit)
49
+ qs.limit = limit;
50
+ if (after)
51
+ qs.after = after;
52
+ if (properties && Array.isArray(properties))
53
+ qs.properties = properties.join(",");
54
+ return apiRequest(tok(ctx), "GET", `/crm/v3/objects/${objectType}`, undefined, qs);
55
+ },
56
+ });
57
+ rl.registerAction(`${resource}.update`, {
58
+ description: `Update a ${resource}`, inputSchema: { id: { type: "string", required: true, description: `${resource} ID` }, properties: { type: "object", required: true, description: "Properties to update" } },
59
+ async execute(input, ctx) { const { id, properties } = input; return apiRequest(tok(ctx), "PATCH", `/crm/v3/objects/${objectType}/${id}`, { properties }); },
60
+ });
61
+ rl.registerAction(`${resource}.delete`, {
62
+ description: `Delete a ${resource}`, inputSchema: { id: { type: "string", required: true, description: `${resource} ID` } },
63
+ async execute(input, ctx) { await apiRequest(tok(ctx), "DELETE", `/crm/v3/objects/${objectType}/${input.id}`); return { success: true }; },
64
+ });
65
+ rl.registerAction(`${resource}.search`, {
66
+ description: `Search ${resource}s`,
67
+ inputSchema: {
68
+ filterGroups: { type: "array", required: true, description: "Filter groups [{filters: [{propertyName, operator, value}]}]" },
69
+ properties: { type: "array", required: false, description: "Properties to return" },
70
+ limit: { type: "number", required: false, description: "Max results" },
71
+ after: { type: "string", required: false, description: "Pagination" },
72
+ },
73
+ async execute(input, ctx) {
74
+ const { filterGroups, properties, limit, after } = input;
75
+ const body = { filterGroups };
76
+ if (properties)
77
+ body.properties = properties;
78
+ if (limit)
79
+ body.limit = limit;
80
+ if (after)
81
+ body.after = after;
82
+ return apiRequest(tok(ctx), "POST", `/crm/v3/objects/${objectType}/search`, body);
83
+ },
84
+ });
85
+ }
86
+ registerCrmObject("contact", "contacts");
87
+ registerCrmObject("company", "companies");
88
+ registerCrmObject("deal", "deals");
89
+ registerCrmObject("ticket", "tickets");
90
+ // ── Contact List ────────────────────────────────────
91
+ rl.registerAction("contactList.addContacts", {
92
+ description: "Add contacts to a list",
93
+ inputSchema: {
94
+ listId: { type: "string", required: true, description: "List ID" },
95
+ contactIds: { type: "array", required: true, description: "Array of contact IDs" },
96
+ },
97
+ async execute(input, ctx) {
98
+ const { listId, contactIds } = input;
99
+ return apiRequest(tok(ctx), "POST", `/contacts/v1/lists/${listId}/add`, { vids: contactIds });
100
+ },
101
+ });
102
+ rl.registerAction("contactList.removeContacts", {
103
+ description: "Remove contacts from a list",
104
+ inputSchema: {
105
+ listId: { type: "string", required: true, description: "List ID" },
106
+ contactIds: { type: "array", required: true, description: "Array of contact IDs" },
107
+ },
108
+ async execute(input, ctx) {
109
+ const { listId, contactIds } = input;
110
+ return apiRequest(tok(ctx), "POST", `/contacts/v1/lists/${listId}/remove`, { vids: contactIds });
111
+ },
112
+ });
113
+ // ── Engagement ──────────────────────────────────────
114
+ rl.registerAction("engagement.create", {
115
+ description: "Create an engagement (note, email, task, meeting, call)",
116
+ inputSchema: {
117
+ type: { type: "string", required: true, description: "NOTE, EMAIL, TASK, MEETING, CALL" },
118
+ properties: { type: "object", required: true, description: "Engagement metadata" },
119
+ associations: { type: "object", required: false, description: "{contactIds, companyIds, dealIds, ticketIds}" },
120
+ },
121
+ async execute(input, ctx) {
122
+ const { type, properties, associations } = input;
123
+ const body = {
124
+ engagement: { type, ...properties },
125
+ };
126
+ if (associations)
127
+ body.associations = associations;
128
+ return apiRequest(tok(ctx), "POST", "/engagements/v1/engagements", body);
129
+ },
130
+ });
131
+ rl.registerAction("engagement.get", {
132
+ description: "Get an engagement",
133
+ inputSchema: { engagementId: { type: "string", required: true, description: "Engagement ID" } },
134
+ async execute(input, ctx) { return apiRequest(tok(ctx), "GET", `/engagements/v1/engagements/${input.engagementId}`); },
135
+ });
136
+ rl.registerAction("engagement.list", {
137
+ description: "List engagements",
138
+ inputSchema: { limit: { type: "number", required: false, description: "Max results" }, offset: { type: "number", required: false, description: "Offset" } },
139
+ async execute(input, ctx) {
140
+ const { limit, offset } = (input ?? {});
141
+ const qs = {};
142
+ if (limit)
143
+ qs.limit = limit;
144
+ if (offset)
145
+ qs.offset = offset;
146
+ return apiRequest(tok(ctx), "GET", "/engagements/v1/engagements/paged", undefined, qs);
147
+ },
148
+ });
149
+ rl.registerAction("engagement.delete", {
150
+ description: "Delete an engagement",
151
+ inputSchema: { engagementId: { type: "string", required: true, description: "Engagement ID" } },
152
+ async execute(input, ctx) { await apiRequest(tok(ctx), "DELETE", `/engagements/v1/engagements/${input.engagementId}`); return { success: true }; },
153
+ });
154
+ // ── Form ────────────────────────────────────────────
155
+ rl.registerAction("form.submit", {
156
+ description: "Submit a HubSpot form",
157
+ inputSchema: {
158
+ portalId: { type: "string", required: true, description: "Portal (Hub) ID" },
159
+ formId: { type: "string", required: true, description: "Form GUID" },
160
+ fields: { type: "array", required: true, description: "Array of {name, value} objects" },
161
+ context: { type: "object", required: false, description: "Submission context (hutk, pageUri, pageName)" },
162
+ },
163
+ async execute(input, ctx) {
164
+ const { portalId, formId, fields, context } = input;
165
+ const body = { fields };
166
+ if (context)
167
+ body.context = context;
168
+ return apiRequest(tok(ctx), "POST", `/submissions/v3/integration/secure/submit/${portalId}/${formId}`, body);
169
+ },
170
+ });
171
+ rl.registerAction("form.getFields", {
172
+ description: "Get form fields",
173
+ inputSchema: { formId: { type: "string", required: true, description: "Form GUID" } },
174
+ async execute(input, ctx) { return apiRequest(tok(ctx), "GET", `/forms/v2/fields/${input.formId}`); },
175
+ });
176
+ }
@@ -0,0 +1,60 @@
1
+ const BASE_URL = "https://api.humantic.ai/v1";
2
+ async function apiRequest(apiKey, method, endpoint, body, qs) {
3
+ const url = new URL(`${BASE_URL}${endpoint}`);
4
+ url.searchParams.set("apikey", apiKey);
5
+ if (qs) {
6
+ for (const [k, v] of Object.entries(qs)) {
7
+ if (v !== undefined && v !== null)
8
+ url.searchParams.set(k, String(v));
9
+ }
10
+ }
11
+ const opts = { method, headers: { "Content-Type": "application/json" } };
12
+ if (body && Object.keys(body).length > 0 && method !== "GET")
13
+ opts.body = JSON.stringify(body);
14
+ const res = await fetch(url.toString(), opts);
15
+ if (!res.ok)
16
+ throw new Error(`Humantic AI error ${res.status}: ${await res.text()}`);
17
+ return res.json();
18
+ }
19
+ export default function humanticAi(rl) {
20
+ rl.setName("humanticAi");
21
+ rl.setVersion("0.1.0");
22
+ rl.setConnectionSchema({ apiKey: { type: "string", required: true, description: "Humantic AI API key", env: "HUMANTIC_AI_API_KEY" } });
23
+ rl.registerAction("profile.create", {
24
+ description: "Create a user profile from LinkedIn URL or text",
25
+ inputSchema: { userId: { type: "string", required: true, description: "Unique user identifier" }, linkedinUrl: { type: "string", required: false, description: "LinkedIn profile URL" }, text: { type: "string", required: false, description: "Text content to analyze" } },
26
+ async execute(input, ctx) {
27
+ const { userId, linkedinUrl, text } = input;
28
+ const body = { userid: userId };
29
+ if (linkedinUrl)
30
+ body.linkedin_url = linkedinUrl;
31
+ if (text)
32
+ body.text = text;
33
+ return apiRequest(ctx.connection.config.apiKey, "POST", "/user-profile/create", body);
34
+ },
35
+ });
36
+ rl.registerAction("profile.get", {
37
+ description: "Get a user profile/personality analysis",
38
+ inputSchema: { userId: { type: "string", required: true, description: "User identifier" }, persona: { type: "string", required: false, description: "Persona type: sales, hiring, default" } },
39
+ async execute(input, ctx) {
40
+ const { userId, persona } = input;
41
+ const qs = { userid: userId };
42
+ if (persona)
43
+ qs.persona = persona;
44
+ return apiRequest(ctx.connection.config.apiKey, "GET", "/user-profile", undefined, qs);
45
+ },
46
+ });
47
+ rl.registerAction("profile.update", {
48
+ description: "Update a user profile with new data",
49
+ inputSchema: { userId: { type: "string", required: true, description: "User identifier" }, text: { type: "string", required: false, description: "Additional text" }, linkedinUrl: { type: "string", required: false, description: "LinkedIn URL" } },
50
+ async execute(input, ctx) {
51
+ const { userId, text, linkedinUrl } = input;
52
+ const body = { userid: userId };
53
+ if (text)
54
+ body.text = text;
55
+ if (linkedinUrl)
56
+ body.linkedin_url = linkedinUrl;
57
+ return apiRequest(ctx.connection.config.apiKey, "POST", "/user-profile/create", body);
58
+ },
59
+ });
60
+ }
@@ -0,0 +1,59 @@
1
+ const BASE_URL = "https://api.hunter.io/v2";
2
+ async function apiRequest(apiKey, endpoint, qs) {
3
+ const url = new URL(`${BASE_URL}${endpoint}`);
4
+ url.searchParams.set("api_key", apiKey);
5
+ if (qs) {
6
+ for (const [k, v] of Object.entries(qs)) {
7
+ if (v !== undefined && v !== null)
8
+ url.searchParams.set(k, String(v));
9
+ }
10
+ }
11
+ const res = await fetch(url.toString());
12
+ if (!res.ok)
13
+ throw new Error(`Hunter API error ${res.status}: ${await res.text()}`);
14
+ return res.json();
15
+ }
16
+ export default function hunter(rl) {
17
+ rl.setName("hunter");
18
+ rl.setVersion("0.1.0");
19
+ rl.setConnectionSchema({ apiKey: { type: "string", required: true, description: "Hunter.io API key", env: "HUNTER_API_KEY" } });
20
+ rl.registerAction("domainSearch", {
21
+ description: "Search for email addresses associated with a domain",
22
+ inputSchema: {
23
+ domain: { type: "string", required: true, description: "Domain name (e.g. example.com)" },
24
+ type: { type: "string", required: false, description: "personal or generic" },
25
+ limit: { type: "number", required: false, description: "Max results" },
26
+ },
27
+ async execute(input, ctx) {
28
+ const { domain, type, limit } = input;
29
+ const qs = { domain };
30
+ if (type)
31
+ qs.type = type;
32
+ if (limit)
33
+ qs.limit = limit;
34
+ const data = (await apiRequest(ctx.connection.config.apiKey, "/domain-search", qs));
35
+ return data.data;
36
+ },
37
+ });
38
+ rl.registerAction("emailFinder", {
39
+ description: "Find the email address of a person",
40
+ inputSchema: {
41
+ domain: { type: "string", required: true, description: "Domain" },
42
+ firstName: { type: "string", required: true, description: "First name" },
43
+ lastName: { type: "string", required: true, description: "Last name" },
44
+ },
45
+ async execute(input, ctx) {
46
+ const { domain, firstName, lastName } = input;
47
+ const data = (await apiRequest(ctx.connection.config.apiKey, "/email-finder", { domain, first_name: firstName, last_name: lastName }));
48
+ return data.data;
49
+ },
50
+ });
51
+ rl.registerAction("emailVerifier", {
52
+ description: "Verify an email address",
53
+ inputSchema: { email: { type: "string", required: true, description: "Email to verify" } },
54
+ async execute(input, ctx) {
55
+ const data = (await apiRequest(ctx.connection.config.apiKey, "/email-verifier", { email: input.email }));
56
+ return data.data;
57
+ },
58
+ });
59
+ }