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,71 @@
1
+ const BASE = "https://api.travis-ci.com";
2
+ async function apiRequest(token, method, endpoint, body, qs) {
3
+ const url = new URL(`${BASE}${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 init = {
11
+ method,
12
+ headers: { Authorization: `token ${token}`, "Travis-API-Version": "3", Accept: "application/json", "Content-Type": "application/json" },
13
+ };
14
+ if (body !== undefined)
15
+ init.body = typeof body === "string" ? body : JSON.stringify(body);
16
+ const res = await fetch(url.toString(), init);
17
+ if (!res.ok)
18
+ throw new Error(`TravisCI error ${res.status}: ${await res.text()}`);
19
+ return res.json();
20
+ }
21
+ export default function travisci(rl) {
22
+ rl.setName("travisci");
23
+ rl.setVersion("0.1.0");
24
+ rl.setConnectionSchema({ apiToken: { type: "string", required: true, description: "Travis CI API token", env: "TRAVISCI_API_TOKEN" } });
25
+ const key = (ctx) => ctx.connection.config.apiToken;
26
+ rl.registerAction("build.get", {
27
+ description: "Get a build by ID",
28
+ inputSchema: { buildId: { type: "string", required: true } },
29
+ async execute(input, ctx) { return apiRequest(key(ctx), "GET", `/build/${input.buildId}`); },
30
+ });
31
+ rl.registerAction("build.list", {
32
+ description: "List builds for the current user",
33
+ inputSchema: { limit: { type: "number", required: false }, sortBy: { type: "string", required: false } },
34
+ async execute(input, ctx) {
35
+ const p = (input ?? {});
36
+ const qs = {};
37
+ if (p.limit)
38
+ qs.limit = p.limit;
39
+ if (p.sortBy)
40
+ qs.sort_by = p.sortBy;
41
+ const data = (await apiRequest(key(ctx), "GET", "/builds", undefined, qs));
42
+ return data.builds;
43
+ },
44
+ });
45
+ rl.registerAction("build.cancel", {
46
+ description: "Cancel a build",
47
+ inputSchema: { buildId: { type: "string", required: true } },
48
+ async execute(input, ctx) { return apiRequest(key(ctx), "POST", `/build/${input.buildId}/cancel`); },
49
+ });
50
+ rl.registerAction("build.restart", {
51
+ description: "Restart a build",
52
+ inputSchema: { buildId: { type: "string", required: true } },
53
+ async execute(input, ctx) { return apiRequest(key(ctx), "POST", `/build/${input.buildId}/restart`); },
54
+ });
55
+ rl.registerAction("build.trigger", {
56
+ description: "Trigger a build for a repository",
57
+ inputSchema: {
58
+ slug: { type: "string", required: true, description: "Repository slug (owner/name)" },
59
+ branch: { type: "string", required: true },
60
+ message: { type: "string", required: false },
61
+ },
62
+ async execute(input, ctx) {
63
+ const p = input;
64
+ const slug = p.slug.replace(/\//g, "%2F");
65
+ const request = { branch: p.branch };
66
+ if (p.message)
67
+ request.message = p.message;
68
+ return apiRequest(key(ctx), "POST", `/repo/${slug}/requests`, { request });
69
+ },
70
+ });
71
+ }
@@ -0,0 +1,341 @@
1
+ const BASE = "https://api.trello.com/1";
2
+ function getConn(ctx) {
3
+ return { apiKey: ctx.connection.config.apiKey, token: ctx.connection.config.token };
4
+ }
5
+ async function apiRequest(conn, method, endpoint, body, qs) {
6
+ const url = new URL(`${BASE}/${endpoint}`);
7
+ url.searchParams.set("key", conn.apiKey);
8
+ url.searchParams.set("token", conn.token);
9
+ if (qs) {
10
+ for (const [k, v] of Object.entries(qs)) {
11
+ if (v !== undefined && v !== null)
12
+ url.searchParams.set(k, String(v));
13
+ }
14
+ }
15
+ const init = { method, headers: { "Content-Type": "application/json" } };
16
+ if (body && Object.keys(body).length > 0 && method !== "GET")
17
+ init.body = JSON.stringify(body);
18
+ const res = await fetch(url.toString(), init);
19
+ if (!res.ok)
20
+ throw new Error(`Trello error ${res.status}: ${await res.text()}`);
21
+ const text = await res.text();
22
+ return text ? JSON.parse(text) : {};
23
+ }
24
+ export default function trello(rl) {
25
+ rl.setName("trello");
26
+ rl.setVersion("0.1.0");
27
+ rl.setConnectionSchema({
28
+ apiKey: { type: "string", required: true, description: "Trello API key", env: "TRELLO_API_KEY" },
29
+ token: { type: "string", required: true, description: "Trello API token", env: "TRELLO_TOKEN" },
30
+ });
31
+ // ── Board ───────────────────────────────────────────
32
+ rl.registerAction("board.create", {
33
+ description: "Create a board",
34
+ inputSchema: { name: { type: "string", required: true }, description: { type: "string", required: false } },
35
+ async execute(input, ctx) {
36
+ const p = input;
37
+ return apiRequest(getConn(ctx), "POST", "boards", { name: p.name, desc: p.description });
38
+ },
39
+ });
40
+ rl.registerAction("board.get", {
41
+ description: "Get a board by ID",
42
+ inputSchema: { id: { type: "string", required: true } },
43
+ async execute(input, ctx) { return apiRequest(getConn(ctx), "GET", `boards/${input.id}`); },
44
+ });
45
+ rl.registerAction("board.update", {
46
+ description: "Update a board",
47
+ inputSchema: { id: { type: "string", required: true }, name: { type: "string", required: false }, description: { type: "string", required: false }, closed: { type: "boolean", required: false } },
48
+ async execute(input, ctx) {
49
+ const { id, ...fields } = input;
50
+ const qs = {};
51
+ if (fields.name)
52
+ qs.name = fields.name;
53
+ if (fields.description !== undefined)
54
+ qs.desc = fields.description;
55
+ if (fields.closed !== undefined)
56
+ qs.closed = fields.closed;
57
+ return apiRequest(getConn(ctx), "PUT", `boards/${id}`, undefined, qs);
58
+ },
59
+ });
60
+ rl.registerAction("board.delete", {
61
+ description: "Delete a board",
62
+ inputSchema: { id: { type: "string", required: true } },
63
+ async execute(input, ctx) { return apiRequest(getConn(ctx), "DELETE", `boards/${input.id}`); },
64
+ });
65
+ // ── Board Member ────────────────────────────────────
66
+ rl.registerAction("boardMember.list", {
67
+ description: "List members of a board",
68
+ inputSchema: { boardId: { type: "string", required: true }, limit: { type: "number", required: false } },
69
+ async execute(input, ctx) {
70
+ const p = (input ?? {});
71
+ const data = (await apiRequest(getConn(ctx), "GET", `boards/${p.boardId}/members`));
72
+ return p.limit ? data.slice(0, p.limit) : data;
73
+ },
74
+ });
75
+ rl.registerAction("boardMember.add", {
76
+ description: "Add a member to a board",
77
+ inputSchema: { boardId: { type: "string", required: true }, memberId: { type: "string", required: true }, type: { type: "string", required: true, description: "admin, normal, or observer" } },
78
+ async execute(input, ctx) {
79
+ const p = input;
80
+ return apiRequest(getConn(ctx), "PUT", `boards/${p.boardId}/members/${p.memberId}`, undefined, { type: p.type });
81
+ },
82
+ });
83
+ rl.registerAction("boardMember.remove", {
84
+ description: "Remove a member from a board",
85
+ inputSchema: { boardId: { type: "string", required: true }, memberId: { type: "string", required: true } },
86
+ async execute(input, ctx) {
87
+ const p = input;
88
+ return apiRequest(getConn(ctx), "DELETE", `boards/${p.boardId}/members/${p.memberId}`);
89
+ },
90
+ });
91
+ // ── Card ────────────────────────────────────────────
92
+ rl.registerAction("card.create", {
93
+ description: "Create a card",
94
+ inputSchema: { listId: { type: "string", required: true }, name: { type: "string", required: true }, description: { type: "string", required: false }, due: { type: "string", required: false } },
95
+ async execute(input, ctx) {
96
+ const p = input;
97
+ const body = { idList: p.listId, name: p.name };
98
+ if (p.description)
99
+ body.desc = p.description;
100
+ if (p.due)
101
+ body.due = p.due;
102
+ return apiRequest(getConn(ctx), "POST", "cards", body);
103
+ },
104
+ });
105
+ rl.registerAction("card.get", {
106
+ description: "Get a card by ID",
107
+ inputSchema: { id: { type: "string", required: true } },
108
+ async execute(input, ctx) { return apiRequest(getConn(ctx), "GET", `cards/${input.id}`); },
109
+ });
110
+ rl.registerAction("card.update", {
111
+ description: "Update a card",
112
+ inputSchema: { id: { type: "string", required: true }, name: { type: "string", required: false }, description: { type: "string", required: false }, closed: { type: "boolean", required: false }, idList: { type: "string", required: false }, due: { type: "string", required: false } },
113
+ async execute(input, ctx) {
114
+ const { id, ...fields } = input;
115
+ const qs = {};
116
+ if (fields.name)
117
+ qs.name = fields.name;
118
+ if (fields.description !== undefined)
119
+ qs.desc = fields.description;
120
+ if (fields.closed !== undefined)
121
+ qs.closed = fields.closed;
122
+ if (fields.idList)
123
+ qs.idList = fields.idList;
124
+ if (fields.due)
125
+ qs.due = fields.due;
126
+ return apiRequest(getConn(ctx), "PUT", `cards/${id}`, undefined, qs);
127
+ },
128
+ });
129
+ rl.registerAction("card.delete", {
130
+ description: "Delete a card",
131
+ inputSchema: { id: { type: "string", required: true } },
132
+ async execute(input, ctx) { return apiRequest(getConn(ctx), "DELETE", `cards/${input.id}`); },
133
+ });
134
+ // ── Card Comment ────────────────────────────────────
135
+ rl.registerAction("cardComment.create", {
136
+ description: "Add a comment to a card",
137
+ inputSchema: { cardId: { type: "string", required: true }, text: { type: "string", required: true } },
138
+ async execute(input, ctx) {
139
+ const p = input;
140
+ return apiRequest(getConn(ctx), "POST", `cards/${p.cardId}/actions/comments`, { text: p.text });
141
+ },
142
+ });
143
+ rl.registerAction("cardComment.update", {
144
+ description: "Update a comment on a card",
145
+ inputSchema: { cardId: { type: "string", required: true }, commentId: { type: "string", required: true }, text: { type: "string", required: true } },
146
+ async execute(input, ctx) {
147
+ const p = input;
148
+ return apiRequest(getConn(ctx), "PUT", `cards/${p.cardId}/actions/${p.commentId}/comments`, undefined, { text: p.text });
149
+ },
150
+ });
151
+ rl.registerAction("cardComment.delete", {
152
+ description: "Delete a comment from a card",
153
+ inputSchema: { cardId: { type: "string", required: true }, commentId: { type: "string", required: true } },
154
+ async execute(input, ctx) {
155
+ const p = input;
156
+ return apiRequest(getConn(ctx), "DELETE", `cards/${p.cardId}/actions/${p.commentId}/comments`);
157
+ },
158
+ });
159
+ // ── List ────────────────────────────────────────────
160
+ rl.registerAction("list.create", {
161
+ description: "Create a list on a board",
162
+ inputSchema: { boardId: { type: "string", required: true }, name: { type: "string", required: true } },
163
+ async execute(input, ctx) {
164
+ const p = input;
165
+ return apiRequest(getConn(ctx), "POST", "lists", { idBoard: p.boardId, name: p.name });
166
+ },
167
+ });
168
+ rl.registerAction("list.get", {
169
+ description: "Get a list by ID",
170
+ inputSchema: { id: { type: "string", required: true } },
171
+ async execute(input, ctx) { return apiRequest(getConn(ctx), "GET", `lists/${input.id}`); },
172
+ });
173
+ rl.registerAction("list.listAll", {
174
+ description: "List all lists on a board",
175
+ inputSchema: { boardId: { type: "string", required: true }, limit: { type: "number", required: false } },
176
+ async execute(input, ctx) {
177
+ const p = (input ?? {});
178
+ const data = (await apiRequest(getConn(ctx), "GET", `boards/${p.boardId}/lists`));
179
+ return p.limit ? data.slice(0, p.limit) : data;
180
+ },
181
+ });
182
+ rl.registerAction("list.getCards", {
183
+ description: "Get cards in a list",
184
+ inputSchema: { listId: { type: "string", required: true }, limit: { type: "number", required: false } },
185
+ async execute(input, ctx) {
186
+ const p = (input ?? {});
187
+ const data = (await apiRequest(getConn(ctx), "GET", `lists/${p.listId}/cards`));
188
+ return p.limit ? data.slice(0, p.limit) : data;
189
+ },
190
+ });
191
+ rl.registerAction("list.update", {
192
+ description: "Update a list",
193
+ inputSchema: { id: { type: "string", required: true }, name: { type: "string", required: false }, closed: { type: "boolean", required: false } },
194
+ async execute(input, ctx) {
195
+ const { id, ...fields } = input;
196
+ const qs = {};
197
+ if (fields.name)
198
+ qs.name = fields.name;
199
+ if (fields.closed !== undefined)
200
+ qs.closed = fields.closed;
201
+ return apiRequest(getConn(ctx), "PUT", `lists/${id}`, undefined, qs);
202
+ },
203
+ });
204
+ // ── Attachment ──────────────────────────────────────
205
+ rl.registerAction("attachment.create", {
206
+ description: "Add a URL attachment to a card",
207
+ inputSchema: { cardId: { type: "string", required: true }, url: { type: "string", required: true }, name: { type: "string", required: false } },
208
+ async execute(input, ctx) {
209
+ const p = input;
210
+ const body = { url: p.url };
211
+ if (p.name)
212
+ body.name = p.name;
213
+ return apiRequest(getConn(ctx), "POST", `cards/${p.cardId}/attachments`, body);
214
+ },
215
+ });
216
+ rl.registerAction("attachment.get", {
217
+ description: "Get an attachment",
218
+ inputSchema: { cardId: { type: "string", required: true }, id: { type: "string", required: true } },
219
+ async execute(input, ctx) {
220
+ const p = input;
221
+ return apiRequest(getConn(ctx), "GET", `cards/${p.cardId}/attachments/${p.id}`);
222
+ },
223
+ });
224
+ rl.registerAction("attachment.list", {
225
+ description: "List attachments on a card",
226
+ inputSchema: { cardId: { type: "string", required: true } },
227
+ async execute(input, ctx) { return apiRequest(getConn(ctx), "GET", `cards/${input.cardId}/attachments`); },
228
+ });
229
+ rl.registerAction("attachment.delete", {
230
+ description: "Delete an attachment from a card",
231
+ inputSchema: { cardId: { type: "string", required: true }, id: { type: "string", required: true } },
232
+ async execute(input, ctx) {
233
+ const p = input;
234
+ return apiRequest(getConn(ctx), "DELETE", `cards/${p.cardId}/attachments/${p.id}`);
235
+ },
236
+ });
237
+ // ── Checklist ───────────────────────────────────────
238
+ rl.registerAction("checklist.create", {
239
+ description: "Create a checklist on a card",
240
+ inputSchema: { cardId: { type: "string", required: true }, name: { type: "string", required: true } },
241
+ async execute(input, ctx) {
242
+ const p = input;
243
+ return apiRequest(getConn(ctx), "POST", `cards/${p.cardId}/checklists`, { name: p.name });
244
+ },
245
+ });
246
+ rl.registerAction("checklist.get", {
247
+ description: "Get a checklist by ID",
248
+ inputSchema: { id: { type: "string", required: true } },
249
+ async execute(input, ctx) { return apiRequest(getConn(ctx), "GET", `checklists/${input.id}`); },
250
+ });
251
+ rl.registerAction("checklist.list", {
252
+ description: "List checklists on a card",
253
+ inputSchema: { cardId: { type: "string", required: true } },
254
+ async execute(input, ctx) { return apiRequest(getConn(ctx), "GET", `cards/${input.cardId}/checklists`); },
255
+ });
256
+ rl.registerAction("checklist.delete", {
257
+ description: "Delete a checklist from a card",
258
+ inputSchema: { cardId: { type: "string", required: true }, id: { type: "string", required: true } },
259
+ async execute(input, ctx) {
260
+ const p = input;
261
+ return apiRequest(getConn(ctx), "DELETE", `cards/${p.cardId}/checklists/${p.id}`);
262
+ },
263
+ });
264
+ rl.registerAction("checklist.createItem", {
265
+ description: "Create a check item in a checklist",
266
+ inputSchema: { checklistId: { type: "string", required: true }, name: { type: "string", required: true } },
267
+ async execute(input, ctx) {
268
+ const p = input;
269
+ return apiRequest(getConn(ctx), "POST", `checklists/${p.checklistId}/checkItems`, { name: p.name });
270
+ },
271
+ });
272
+ rl.registerAction("checklist.updateItem", {
273
+ description: "Update a check item on a card",
274
+ inputSchema: { cardId: { type: "string", required: true }, checkItemId: { type: "string", required: true }, state: { type: "string", required: false, description: "complete or incomplete" }, name: { type: "string", required: false } },
275
+ async execute(input, ctx) {
276
+ const p = input;
277
+ const qs = {};
278
+ if (p.state)
279
+ qs.state = p.state;
280
+ if (p.name)
281
+ qs.name = p.name;
282
+ return apiRequest(getConn(ctx), "PUT", `cards/${p.cardId}/checkItem/${p.checkItemId}`, undefined, qs);
283
+ },
284
+ });
285
+ rl.registerAction("checklist.deleteItem", {
286
+ description: "Delete a check item from a card",
287
+ inputSchema: { cardId: { type: "string", required: true }, checkItemId: { type: "string", required: true } },
288
+ async execute(input, ctx) {
289
+ const p = input;
290
+ return apiRequest(getConn(ctx), "DELETE", `cards/${p.cardId}/checkItem/${p.checkItemId}`);
291
+ },
292
+ });
293
+ // ── Label ───────────────────────────────────────────
294
+ rl.registerAction("label.create", {
295
+ description: "Create a label on a board",
296
+ inputSchema: { boardId: { type: "string", required: true }, name: { type: "string", required: true }, color: { type: "string", required: true, description: "green, yellow, orange, red, purple, blue, sky, lime, pink, black, null" } },
297
+ async execute(input, ctx) {
298
+ const p = input;
299
+ return apiRequest(getConn(ctx), "POST", "labels", { idBoard: p.boardId, name: p.name, color: p.color });
300
+ },
301
+ });
302
+ rl.registerAction("label.get", {
303
+ description: "Get a label by ID",
304
+ inputSchema: { id: { type: "string", required: true } },
305
+ async execute(input, ctx) { return apiRequest(getConn(ctx), "GET", `labels/${input.id}`); },
306
+ });
307
+ rl.registerAction("label.list", {
308
+ description: "List labels on a board",
309
+ inputSchema: { boardId: { type: "string", required: true } },
310
+ async execute(input, ctx) { return apiRequest(getConn(ctx), "GET", `board/${input.boardId}/labels`); },
311
+ });
312
+ rl.registerAction("label.update", {
313
+ description: "Update a label",
314
+ inputSchema: { id: { type: "string", required: true }, name: { type: "string", required: false }, color: { type: "string", required: false } },
315
+ async execute(input, ctx) {
316
+ const { id, ...fields } = input;
317
+ return apiRequest(getConn(ctx), "PUT", `labels/${id}`, undefined, fields);
318
+ },
319
+ });
320
+ rl.registerAction("label.delete", {
321
+ description: "Delete a label",
322
+ inputSchema: { id: { type: "string", required: true } },
323
+ async execute(input, ctx) { return apiRequest(getConn(ctx), "DELETE", `labels/${input.id}`); },
324
+ });
325
+ rl.registerAction("label.addToCard", {
326
+ description: "Add a label to a card",
327
+ inputSchema: { cardId: { type: "string", required: true }, labelId: { type: "string", required: true } },
328
+ async execute(input, ctx) {
329
+ const p = input;
330
+ return apiRequest(getConn(ctx), "POST", `cards/${p.cardId}/idLabels`, { value: p.labelId });
331
+ },
332
+ });
333
+ rl.registerAction("label.removeFromCard", {
334
+ description: "Remove a label from a card",
335
+ inputSchema: { cardId: { type: "string", required: true }, labelId: { type: "string", required: true } },
336
+ async execute(input, ctx) {
337
+ const p = input;
338
+ return apiRequest(getConn(ctx), "DELETE", `cards/${p.cardId}/idLabels/${p.labelId}`);
339
+ },
340
+ });
341
+ }
@@ -0,0 +1,40 @@
1
+ export default function twake(rl) {
2
+ rl.setName("twake");
3
+ rl.setVersion("0.1.0");
4
+ rl.setConnectionSchema({
5
+ apiKey: { type: "string", required: true, description: "Twake workspace API key", env: "TWAKE_API_KEY" },
6
+ });
7
+ rl.registerAction("message.send", {
8
+ description: "Send a message to a Twake channel",
9
+ inputSchema: {
10
+ channelId: { type: "string", required: true },
11
+ content: { type: "string", required: true },
12
+ senderName: { type: "string", required: false },
13
+ senderIcon: { type: "string", required: false },
14
+ },
15
+ async execute(input, ctx) {
16
+ const p = input;
17
+ const hiddenData = { allow_delete: "everyone" };
18
+ if (p.senderName)
19
+ hiddenData.custom_title = p.senderName;
20
+ if (p.senderIcon)
21
+ hiddenData.custom_icon = p.senderIcon;
22
+ const body = {
23
+ object: {
24
+ channel_id: p.channelId,
25
+ content: { formatted: p.content },
26
+ hidden_data: hiddenData,
27
+ },
28
+ };
29
+ const res = await fetch("https://plugins.twake.app/plugins/runline/actions/message/save", {
30
+ method: "POST",
31
+ headers: { Authorization: `Bearer ${ctx.connection.config.apiKey}`, "Content-Type": "application/json" },
32
+ body: JSON.stringify(body),
33
+ });
34
+ if (!res.ok)
35
+ throw new Error(`Twake error ${res.status}: ${await res.text()}`);
36
+ const data = (await res.json());
37
+ return data.object;
38
+ },
39
+ });
40
+ }
@@ -0,0 +1,75 @@
1
+ function getConn(ctx) {
2
+ const c = ctx.connection.config;
3
+ return { accountSid: c.accountSid, authToken: c.authToken };
4
+ }
5
+ async function apiRequest(conn, method, endpoint, body) {
6
+ const url = `https://api.twilio.com/2010-04-01/Accounts/${conn.accountSid}${endpoint}`;
7
+ const form = new URLSearchParams();
8
+ for (const [k, v] of Object.entries(body)) {
9
+ if (v !== undefined && v !== null && v !== "")
10
+ form.set(k, String(v));
11
+ }
12
+ const res = await fetch(url, {
13
+ method,
14
+ headers: {
15
+ Authorization: `Basic ${btoa(`${conn.accountSid}:${conn.authToken}`)}`,
16
+ "Content-Type": "application/x-www-form-urlencoded",
17
+ },
18
+ body: form,
19
+ });
20
+ if (!res.ok)
21
+ throw new Error(`Twilio error ${res.status}: ${await res.text()}`);
22
+ return res.json();
23
+ }
24
+ function escapeXml(str) {
25
+ return str.replace(/[<>&"']/g, (ch) => ({ "<": "&lt;", ">": "&gt;", "&": "&amp;", '"': "&quot;", "'": "&apos;" })[ch] || ch);
26
+ }
27
+ export default function twilio(rl) {
28
+ rl.setName("twilio");
29
+ rl.setVersion("0.1.0");
30
+ rl.setConnectionSchema({
31
+ accountSid: { type: "string", required: true, description: "Twilio Account SID", env: "TWILIO_ACCOUNT_SID" },
32
+ authToken: { type: "string", required: true, description: "Twilio Auth Token", env: "TWILIO_AUTH_TOKEN" },
33
+ });
34
+ rl.registerAction("sms.send", {
35
+ description: "Send an SMS, MMS, or WhatsApp message",
36
+ inputSchema: {
37
+ from: { type: "string", required: true, description: "Sender phone number" },
38
+ to: { type: "string", required: true, description: "Recipient phone number" },
39
+ body: { type: "string", required: true, description: "Message text" },
40
+ whatsapp: { type: "boolean", required: false, description: "Send via WhatsApp" },
41
+ statusCallback: { type: "string", required: false },
42
+ },
43
+ async execute(input, ctx) {
44
+ const p = input;
45
+ let from = p.from;
46
+ let to = p.to;
47
+ if (p.whatsapp) {
48
+ from = `whatsapp:${from}`;
49
+ to = `whatsapp:${to}`;
50
+ }
51
+ return apiRequest(getConn(ctx), "POST", "/Messages.json", {
52
+ From: from, To: to, Body: p.body, StatusCallback: p.statusCallback,
53
+ });
54
+ },
55
+ });
56
+ rl.registerAction("call.make", {
57
+ description: "Make a phone call",
58
+ inputSchema: {
59
+ from: { type: "string", required: true },
60
+ to: { type: "string", required: true },
61
+ message: { type: "string", required: true, description: "Text to speak or TwiML" },
62
+ twiml: { type: "boolean", required: false, description: "If true, message is treated as raw TwiML" },
63
+ statusCallback: { type: "string", required: false },
64
+ },
65
+ async execute(input, ctx) {
66
+ const p = input;
67
+ const twiml = p.twiml
68
+ ? p.message
69
+ : `<Response><Say>${escapeXml(p.message)}</Say></Response>`;
70
+ return apiRequest(getConn(ctx), "POST", "/Calls.json", {
71
+ From: p.from, To: p.to, Twiml: twiml, StatusCallback: p.statusCallback,
72
+ });
73
+ },
74
+ });
75
+ }
@@ -0,0 +1,90 @@
1
+ const BASE = "https://api.twist.com/api/v3";
2
+ async function api(token, method, endpoint, body, qs) {
3
+ const url = new URL(`${BASE}${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 init = { method, headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" } };
11
+ if (body && Object.keys(body).length > 0)
12
+ init.body = JSON.stringify(body);
13
+ const res = await fetch(url.toString(), init);
14
+ if (!res.ok)
15
+ throw new Error(`Twist error ${res.status}: ${await res.text()}`);
16
+ return res.json();
17
+ }
18
+ export default function twist(rl) {
19
+ rl.setName("twist");
20
+ rl.setVersion("0.1.0");
21
+ rl.setConnectionSchema({ accessToken: { type: "string", required: true, description: "Twist OAuth2 access token", env: "TWIST_ACCESS_TOKEN" } });
22
+ const t = (ctx) => ctx.connection.config.accessToken;
23
+ // ── Channel ─────────────────────────────────────────
24
+ rl.registerAction("channel.create", { description: "Create a channel", inputSchema: { workspaceId: { type: "number", required: true }, name: { type: "string", required: true } },
25
+ async execute(input, ctx) { return api(t(ctx), "POST", "/channels/add", { workspace_id: input.workspaceId, name: input.name }); } });
26
+ rl.registerAction("channel.get", { description: "Get a channel", inputSchema: { id: { type: "number", required: true } },
27
+ async execute(input, ctx) { return api(t(ctx), "GET", "/channels/getone", undefined, { id: input.id }); } });
28
+ rl.registerAction("channel.list", { description: "List channels in a workspace", inputSchema: { workspaceId: { type: "number", required: true }, limit: { type: "number", required: false } },
29
+ async execute(input, ctx) {
30
+ const p = input;
31
+ const data = (await api(t(ctx), "GET", "/channels/get", undefined, { workspace_id: p.workspaceId }));
32
+ return p.limit ? data.slice(0, p.limit) : data;
33
+ } });
34
+ rl.registerAction("channel.update", { description: "Update a channel", inputSchema: { id: { type: "number", required: true }, name: { type: "string", required: false }, description: { type: "string", required: false } },
35
+ async execute(input, ctx) { return api(t(ctx), "POST", "/channels/update", input); } });
36
+ rl.registerAction("channel.delete", { description: "Delete a channel", inputSchema: { id: { type: "number", required: true } },
37
+ async execute(input, ctx) { return api(t(ctx), "POST", "/channels/remove", undefined, { id: input.id }); } });
38
+ rl.registerAction("channel.archive", { description: "Archive a channel", inputSchema: { id: { type: "number", required: true } },
39
+ async execute(input, ctx) { return api(t(ctx), "POST", "/channels/archive", undefined, { id: input.id }); } });
40
+ rl.registerAction("channel.unarchive", { description: "Unarchive a channel", inputSchema: { id: { type: "number", required: true } },
41
+ async execute(input, ctx) { return api(t(ctx), "POST", "/channels/unarchive", undefined, { id: input.id }); } });
42
+ // ── Thread ──────────────────────────────────────────
43
+ rl.registerAction("thread.create", { description: "Create a thread", inputSchema: { channelId: { type: "number", required: true }, title: { type: "string", required: true }, content: { type: "string", required: true } },
44
+ async execute(input, ctx) { const p = input; return api(t(ctx), "POST", "/threads/add", { channel_id: p.channelId, title: p.title, content: p.content }); } });
45
+ rl.registerAction("thread.get", { description: "Get a thread", inputSchema: { id: { type: "number", required: true } },
46
+ async execute(input, ctx) { return api(t(ctx), "GET", "/threads/getone", undefined, { id: input.id }); } });
47
+ rl.registerAction("thread.list", { description: "List threads in a channel", inputSchema: { channelId: { type: "number", required: true }, limit: { type: "number", required: false } },
48
+ async execute(input, ctx) {
49
+ const p = input;
50
+ const qs = { channel_id: p.channelId };
51
+ if (p.limit)
52
+ qs.limit = p.limit;
53
+ return api(t(ctx), "GET", "/threads/get", undefined, qs);
54
+ } });
55
+ rl.registerAction("thread.update", { description: "Update a thread", inputSchema: { id: { type: "number", required: true }, title: { type: "string", required: false }, content: { type: "string", required: false } },
56
+ async execute(input, ctx) { return api(t(ctx), "POST", "/threads/update", input); } });
57
+ rl.registerAction("thread.delete", { description: "Delete a thread", inputSchema: { id: { type: "number", required: true } },
58
+ async execute(input, ctx) { return api(t(ctx), "POST", "/threads/remove", undefined, { id: input.id }); } });
59
+ // ── Comment ─────────────────────────────────────────
60
+ rl.registerAction("comment.create", { description: "Add a comment to a thread", inputSchema: { threadId: { type: "number", required: true }, content: { type: "string", required: true } },
61
+ async execute(input, ctx) { const p = input; return api(t(ctx), "POST", "/comments/add", { thread_id: p.threadId, content: p.content }); } });
62
+ rl.registerAction("comment.get", { description: "Get a comment", inputSchema: { id: { type: "number", required: true } },
63
+ async execute(input, ctx) {
64
+ const data = (await api(t(ctx), "GET", "/comments/getone", undefined, { id: input.id }));
65
+ return data.comment ?? data;
66
+ } });
67
+ rl.registerAction("comment.list", { description: "List comments in a thread", inputSchema: { threadId: { type: "number", required: true }, limit: { type: "number", required: false } },
68
+ async execute(input, ctx) {
69
+ const p = input;
70
+ const qs = { thread_id: p.threadId };
71
+ if (p.limit)
72
+ qs.limit = p.limit;
73
+ return api(t(ctx), "GET", "/comments/get", undefined, qs);
74
+ } });
75
+ rl.registerAction("comment.update", { description: "Update a comment", inputSchema: { id: { type: "number", required: true }, content: { type: "string", required: false } },
76
+ async execute(input, ctx) { return api(t(ctx), "POST", "/comments/update", input); } });
77
+ rl.registerAction("comment.delete", { description: "Delete a comment", inputSchema: { id: { type: "number", required: true } },
78
+ async execute(input, ctx) { return api(t(ctx), "POST", "/comments/remove", undefined, { id: input.id }); } });
79
+ // ── Message Conversation ────────────────────────────
80
+ rl.registerAction("messageConversation.create", { description: "Send a message in a conversation", inputSchema: { workspaceId: { type: "number", required: true }, conversationId: { type: "number", required: true }, content: { type: "string", required: true } },
81
+ async execute(input, ctx) { const p = input; return api(t(ctx), "POST", "/conversation_messages/add", { workspace_id: p.workspaceId, conversation_id: p.conversationId, content: p.content }); } });
82
+ rl.registerAction("messageConversation.get", { description: "Get a conversation message", inputSchema: { id: { type: "number", required: true } },
83
+ async execute(input, ctx) { return api(t(ctx), "GET", "/conversation_messages/getone", undefined, { id: input.id }); } });
84
+ rl.registerAction("messageConversation.list", { description: "List messages in a conversation", inputSchema: { conversationId: { type: "number", required: true } },
85
+ async execute(input, ctx) { return api(t(ctx), "GET", "/conversation_messages/get", undefined, { conversation_id: input.conversationId }); } });
86
+ rl.registerAction("messageConversation.update", { description: "Update a conversation message", inputSchema: { id: { type: "number", required: true }, content: { type: "string", required: false } },
87
+ async execute(input, ctx) { return api(t(ctx), "POST", "/conversation_messages/update", input); } });
88
+ rl.registerAction("messageConversation.delete", { description: "Delete a conversation message", inputSchema: { id: { type: "number", required: true } },
89
+ async execute(input, ctx) { return api(t(ctx), "POST", "/conversation_messages/remove", undefined, { id: input.id }); } });
90
+ }