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,231 @@
1
+ async function gql(token, query, variables = {}) {
2
+ const res = await fetch("https://api.monday.com/v2/", {
3
+ method: "POST",
4
+ headers: { Authorization: token, "API-Version": "2023-10", "Content-Type": "application/json" },
5
+ body: JSON.stringify({ query, variables }),
6
+ });
7
+ if (!res.ok)
8
+ throw new Error(`Monday.com API error ${res.status}: ${await res.text()}`);
9
+ const data = (await res.json());
10
+ if (data.errors)
11
+ throw new Error(`Monday.com GraphQL errors: ${JSON.stringify(data.errors)}`);
12
+ return data.data;
13
+ }
14
+ export default function monday(rl) {
15
+ rl.setName("monday");
16
+ rl.setVersion("0.1.0");
17
+ rl.setConnectionSchema({
18
+ apiToken: { type: "string", required: true, description: "Monday.com API token (v2)", env: "MONDAY_API_TOKEN" },
19
+ });
20
+ const tok = (ctx) => ctx.connection.config.apiToken;
21
+ // ── Board ───────────────────────────────────────────
22
+ rl.registerAction("board.create", {
23
+ description: "Create a board",
24
+ inputSchema: {
25
+ name: { type: "string", required: true },
26
+ kind: { type: "string", required: true, description: "public, private, or share" },
27
+ templateId: { type: "number", required: false },
28
+ },
29
+ async execute(input, ctx) {
30
+ const { name, kind, templateId } = input;
31
+ const vars = { name, kind };
32
+ if (templateId)
33
+ vars.templateId = templateId;
34
+ const data = await gql(tok(ctx), `mutation ($name: String!, $kind: BoardKind!, $templateId: ID) { create_board (board_name: $name, board_kind: $kind, template_id: $templateId) { id } }`, vars);
35
+ return data.create_board;
36
+ },
37
+ });
38
+ rl.registerAction("board.archive", {
39
+ description: "Archive a board",
40
+ inputSchema: { boardId: { type: "string", required: true } },
41
+ async execute(input, ctx) {
42
+ const data = await gql(tok(ctx), `mutation ($id: ID!) { archive_board (board_id: $id) { id } }`, { id: input.boardId });
43
+ return data.archive_board;
44
+ },
45
+ });
46
+ rl.registerAction("board.get", {
47
+ description: "Get a board by ID",
48
+ inputSchema: { boardId: { type: "string", required: true } },
49
+ async execute(input, ctx) {
50
+ const data = await gql(tok(ctx), `query ($id: [ID!]) { boards (ids: $id) { id name description state board_folder_id board_kind owners { id } } }`, { id: input.boardId });
51
+ return data.boards?.[0];
52
+ },
53
+ });
54
+ rl.registerAction("board.list", {
55
+ description: "List boards",
56
+ inputSchema: { limit: { type: "number", required: false } },
57
+ async execute(input, ctx) {
58
+ const { limit } = (input ?? {});
59
+ const data = await gql(tok(ctx), `query ($limit: Int) { boards (limit: $limit) { id name description state board_folder_id board_kind owners { id } } }`, limit ? { limit } : {});
60
+ return data.boards;
61
+ },
62
+ });
63
+ // ── Board Column ────────────────────────────────────
64
+ rl.registerAction("boardColumn.create", {
65
+ description: "Create a column on a board",
66
+ inputSchema: {
67
+ boardId: { type: "string", required: true },
68
+ title: { type: "string", required: true },
69
+ columnType: { type: "string", required: true, description: "Column type (status, text, numbers, date, etc.) in snake_case" },
70
+ defaults: { type: "string", required: false, description: "Default values as JSON string" },
71
+ },
72
+ async execute(input, ctx) {
73
+ const { boardId, title, columnType, defaults } = input;
74
+ const vars = { boardId, title, columnType };
75
+ if (defaults)
76
+ vars.defaults = JSON.stringify(JSON.parse(defaults));
77
+ const data = await gql(tok(ctx), `mutation ($boardId: ID!, $title: String!, $columnType: ColumnType!, $defaults: JSON) { create_column (board_id: $boardId, title: $title, column_type: $columnType, defaults: $defaults) { id } }`, vars);
78
+ return data.create_column;
79
+ },
80
+ });
81
+ rl.registerAction("boardColumn.list", {
82
+ description: "List columns on a board",
83
+ inputSchema: { boardId: { type: "string", required: true } },
84
+ async execute(input, ctx) {
85
+ const data = await gql(tok(ctx), `query ($boardId: [ID!]) { boards (ids: $boardId) { columns { id title type settings_str archived } } }`, { boardId: input.boardId });
86
+ return data.boards?.[0]?.columns;
87
+ },
88
+ });
89
+ // ── Board Group ─────────────────────────────────────
90
+ rl.registerAction("boardGroup.create", {
91
+ description: "Create a group on a board",
92
+ inputSchema: { boardId: { type: "string", required: true }, name: { type: "string", required: true } },
93
+ async execute(input, ctx) {
94
+ const { boardId, name } = input;
95
+ const data = await gql(tok(ctx), `mutation ($boardId: ID!, $groupName: String!) { create_group (board_id: $boardId, group_name: $groupName) { id } }`, { boardId, groupName: name });
96
+ return data.create_group;
97
+ },
98
+ });
99
+ rl.registerAction("boardGroup.delete", {
100
+ description: "Delete a group from a board",
101
+ inputSchema: { boardId: { type: "string", required: true }, groupId: { type: "string", required: true } },
102
+ async execute(input, ctx) {
103
+ const { boardId, groupId } = input;
104
+ const data = await gql(tok(ctx), `mutation ($boardId: ID!, $groupId: String!) { delete_group (board_id: $boardId, group_id: $groupId) { id } }`, { boardId, groupId });
105
+ return data.delete_group;
106
+ },
107
+ });
108
+ rl.registerAction("boardGroup.list", {
109
+ description: "List groups on a board",
110
+ inputSchema: { boardId: { type: "string", required: true } },
111
+ async execute(input, ctx) {
112
+ const data = await gql(tok(ctx), `query ($boardId: [ID!]) { boards (ids: $boardId) { id groups { id title color position archived } } }`, { boardId: input.boardId });
113
+ return data.boards?.[0]?.groups;
114
+ },
115
+ });
116
+ // ── Board Item ──────────────────────────────────────
117
+ rl.registerAction("boardItem.create", {
118
+ description: "Create an item in a board group",
119
+ inputSchema: {
120
+ boardId: { type: "string", required: true },
121
+ groupId: { type: "string", required: true },
122
+ name: { type: "string", required: true, description: "Item name" },
123
+ columnValues: { type: "string", required: false, description: "Column values as JSON string" },
124
+ },
125
+ async execute(input, ctx) {
126
+ const { boardId, groupId, name, columnValues } = input;
127
+ const vars = { boardId, groupId, itemName: name };
128
+ if (columnValues)
129
+ vars.columnValues = JSON.stringify(JSON.parse(columnValues));
130
+ const data = await gql(tok(ctx), `mutation ($boardId: ID!, $groupId: String!, $itemName: String!, $columnValues: JSON) { create_item (board_id: $boardId, group_id: $groupId, item_name: $itemName, column_values: $columnValues) { id } }`, vars);
131
+ return data.create_item;
132
+ },
133
+ });
134
+ rl.registerAction("boardItem.get", {
135
+ description: "Get item(s) by ID",
136
+ inputSchema: { itemIds: { type: "string", required: true, description: "Comma-separated item IDs" } },
137
+ async execute(input, ctx) {
138
+ const ids = input.itemIds.split(",").map((s) => s.trim());
139
+ const data = await gql(tok(ctx), `query ($itemId: [ID!]) { items (ids: $itemId) { id name created_at state column_values { id text type value column { title archived description settings_str } } } }`, { itemId: ids });
140
+ return data.items;
141
+ },
142
+ });
143
+ rl.registerAction("boardItem.list", {
144
+ description: "List items in a board group",
145
+ inputSchema: {
146
+ boardId: { type: "string", required: true },
147
+ groupId: { type: "string", required: true },
148
+ limit: { type: "number", required: false },
149
+ },
150
+ async execute(input, ctx) {
151
+ const { boardId, groupId, limit = 100 } = input;
152
+ const data = await gql(tok(ctx), `query ($boardId: [ID!], $groupId: [String], $limit: Int) { boards(ids: $boardId) { groups(ids: $groupId) { id items_page(limit: $limit) { cursor items { id name created_at state column_values { id text type value column { title archived description settings_str } } } } } } }`, { boardId, groupId, limit });
153
+ return data.boards?.[0]
154
+ ? data.boards[0].groups?.[0]
155
+ ? data.boards[0].groups[0]
156
+ ? data.boards[0].groups[0].items_page
157
+ ? data.boards[0].groups[0].items_page
158
+ : []
159
+ : []
160
+ : []
161
+ : [];
162
+ },
163
+ });
164
+ rl.registerAction("boardItem.delete", {
165
+ description: "Delete an item",
166
+ inputSchema: { itemId: { type: "string", required: true } },
167
+ async execute(input, ctx) {
168
+ const data = await gql(tok(ctx), `mutation ($itemId: ID!) { delete_item (item_id: $itemId) { id } }`, { itemId: input.itemId });
169
+ return data.delete_item;
170
+ },
171
+ });
172
+ rl.registerAction("boardItem.move", {
173
+ description: "Move an item to a different group",
174
+ inputSchema: { itemId: { type: "string", required: true }, groupId: { type: "string", required: true } },
175
+ async execute(input, ctx) {
176
+ const { itemId, groupId } = input;
177
+ const data = await gql(tok(ctx), `mutation ($groupId: String!, $itemId: ID!) { move_item_to_group (group_id: $groupId, item_id: $itemId) { id } }`, { groupId, itemId });
178
+ return data.move_item_to_group;
179
+ },
180
+ });
181
+ rl.registerAction("boardItem.addUpdate", {
182
+ description: "Add an update (comment) to an item",
183
+ inputSchema: { itemId: { type: "string", required: true }, value: { type: "string", required: true, description: "Update body text" } },
184
+ async execute(input, ctx) {
185
+ const { itemId, value } = input;
186
+ const data = await gql(tok(ctx), `mutation ($itemId: ID!, $value: String!) { create_update (item_id: $itemId, body: $value) { id } }`, { itemId, value });
187
+ return data.create_update;
188
+ },
189
+ });
190
+ rl.registerAction("boardItem.changeColumnValue", {
191
+ description: "Change a single column value on an item",
192
+ inputSchema: {
193
+ boardId: { type: "string", required: true },
194
+ itemId: { type: "string", required: true },
195
+ columnId: { type: "string", required: true },
196
+ value: { type: "string", required: true, description: "Column value as JSON string" },
197
+ },
198
+ async execute(input, ctx) {
199
+ const { boardId, itemId, columnId, value } = input;
200
+ const data = await gql(tok(ctx), `mutation ($boardId: ID!, $itemId: ID!, $columnId: String!, $value: JSON!) { change_column_value (board_id: $boardId, item_id: $itemId, column_id: $columnId, value: $value) { id } }`, { boardId, itemId, columnId, value: JSON.stringify(JSON.parse(value)) });
201
+ return data.change_column_value;
202
+ },
203
+ });
204
+ rl.registerAction("boardItem.changeMultipleColumnValues", {
205
+ description: "Change multiple column values on an item",
206
+ inputSchema: {
207
+ boardId: { type: "string", required: true },
208
+ itemId: { type: "string", required: true },
209
+ columnValues: { type: "string", required: true, description: "Column values as JSON string" },
210
+ },
211
+ async execute(input, ctx) {
212
+ const { boardId, itemId, columnValues } = input;
213
+ const data = await gql(tok(ctx), `mutation ($boardId: ID!, $itemId: ID!, $columnValues: JSON!) { change_multiple_column_values (board_id: $boardId, item_id: $itemId, column_values: $columnValues) { id } }`, { boardId, itemId, columnValues: JSON.stringify(JSON.parse(columnValues)) });
214
+ return data.change_multiple_column_values;
215
+ },
216
+ });
217
+ rl.registerAction("boardItem.getByColumnValue", {
218
+ description: "Search items by column value",
219
+ inputSchema: {
220
+ boardId: { type: "string", required: true },
221
+ columnId: { type: "string", required: true },
222
+ columnValue: { type: "string", required: true },
223
+ limit: { type: "number", required: false },
224
+ },
225
+ async execute(input, ctx) {
226
+ const { boardId, columnId, columnValue, limit = 100 } = input;
227
+ const data = await gql(tok(ctx), `query ($boardId: ID!, $columnId: String!, $columnValue: String!, $limit: Int) { items_page_by_column_values (limit: $limit, board_id: $boardId, columns: [{column_id: $columnId, column_values: [$columnValue]}]) { cursor items { id name created_at state board { id } column_values { id text type value column { title archived description settings_str } } } } }`, { boardId, columnId, columnValue, limit });
228
+ return data.items_page_by_column_values?.items;
229
+ },
230
+ });
231
+ }
@@ -0,0 +1,52 @@
1
+ function getConn(ctx) {
2
+ const c = ctx.connection.config;
3
+ const base = (c.url || "https://app.monicahq.com").replace(/\/$/, "");
4
+ return { url: base, token: c.apiToken };
5
+ }
6
+ async function api(conn, method, endpoint, body, qs) {
7
+ const url = new URL(`${conn.url}/api${endpoint}`);
8
+ if (qs) {
9
+ for (const [k, v] of Object.entries(qs)) {
10
+ if (v !== undefined && v !== null)
11
+ url.searchParams.set(k, String(v));
12
+ }
13
+ }
14
+ const init = { method, headers: { Authorization: `Bearer ${conn.token}`, "Content-Type": "application/json" } };
15
+ if (body && Object.keys(body).length > 0)
16
+ init.body = JSON.stringify(body);
17
+ const res = await fetch(url.toString(), init);
18
+ if (!res.ok)
19
+ throw new Error(`Monica CRM error ${res.status}: ${await res.text()}`);
20
+ if (res.status === 204)
21
+ return { success: true };
22
+ return res.json();
23
+ }
24
+ function registerCrud(rl, resource, plural, conn, createSchema) {
25
+ rl.registerAction(`${resource}.create`, { description: `Create a ${resource}`, inputSchema: createSchema,
26
+ async execute(input, ctx) { const data = (await api(conn(ctx), "POST", `/${plural}`, input)); return data.data; } });
27
+ rl.registerAction(`${resource}.get`, { description: `Get a ${resource}`, inputSchema: { id: { type: "string", required: true } },
28
+ async execute(input, ctx) { const data = (await api(conn(ctx), "GET", `/${plural}/${input.id}`)); return data.data; } });
29
+ rl.registerAction(`${resource}.list`, { description: `List ${plural}`, inputSchema: { limit: { type: "number", required: false } },
30
+ async execute(input, ctx) { const qs = { limit: (input ?? {}).limit ?? 100 }; const data = (await api(conn(ctx), "GET", `/${plural}`, undefined, qs)); return data.data; } });
31
+ rl.registerAction(`${resource}.update`, { description: `Update a ${resource}`, inputSchema: { id: { type: "string", required: true }, data: { type: "object", required: true } },
32
+ async execute(input, ctx) { const p = input; const data = (await api(conn(ctx), "PUT", `/${plural}/${p.id}`, p.data)); return data.data; } });
33
+ rl.registerAction(`${resource}.delete`, { description: `Delete a ${resource}`, inputSchema: { id: { type: "string", required: true } },
34
+ async execute(input, ctx) { await api(conn(ctx), "DELETE", `/${plural}/${input.id}`); return { success: true }; } });
35
+ }
36
+ export default function monicaCrm(rl) {
37
+ rl.setName("monicaCrm");
38
+ rl.setVersion("0.1.0");
39
+ rl.setConnectionSchema({
40
+ apiToken: { type: "string", required: true, description: "Monica API token", env: "MONICA_API_TOKEN" },
41
+ url: { type: "string", required: false, description: "Monica URL (default: https://app.monicahq.com)", env: "MONICA_URL" },
42
+ });
43
+ registerCrud(rl, "contact", "contacts", getConn, { first_name: { type: "string", required: true }, last_name: { type: "string", required: false }, gender_id: { type: "number", required: false } });
44
+ registerCrud(rl, "activity", "activities", getConn, { summary: { type: "string", required: true }, description: { type: "string", required: false }, activity_type_id: { type: "number", required: false } });
45
+ registerCrud(rl, "note", "notes", getConn, { contact_id: { type: "number", required: true }, body: { type: "string", required: true } });
46
+ registerCrud(rl, "task", "tasks", getConn, { title: { type: "string", required: true }, contact_id: { type: "number", required: false } });
47
+ registerCrud(rl, "tag", "tags", getConn, { name: { type: "string", required: true } });
48
+ registerCrud(rl, "journalEntry", "journal", getConn, { title: { type: "string", required: true }, post: { type: "string", required: true } });
49
+ registerCrud(rl, "reminder", "reminders", getConn, { contact_id: { type: "number", required: true }, title: { type: "string", required: true }, initial_date: { type: "string", required: true }, frequency_type: { type: "string", required: true, description: "one_time, week, month, year" } });
50
+ registerCrud(rl, "call", "calls", getConn, { contact_id: { type: "number", required: true }, content: { type: "string", required: false }, called_at: { type: "string", required: false } });
51
+ registerCrud(rl, "conversation", "conversations", getConn, { contact_id: { type: "number", required: true }, contact_field_type_id: { type: "number", required: true }, happened_at: { type: "string", required: true } });
52
+ }
@@ -0,0 +1,31 @@
1
+ export default function msg91(rl) {
2
+ rl.setName("msg91");
3
+ rl.setVersion("0.1.0");
4
+ rl.setConnectionSchema({
5
+ authkey: { type: "string", required: true, description: "MSG91 auth key", env: "MSG91_AUTHKEY" },
6
+ });
7
+ rl.registerAction("sms.send", {
8
+ description: "Send a transactional SMS via MSG91",
9
+ inputSchema: {
10
+ from: { type: "string", required: true, description: "Sender ID" },
11
+ to: { type: "string", required: true, description: "Recipient number with country code" },
12
+ message: { type: "string", required: true },
13
+ },
14
+ async execute(input, ctx) {
15
+ const { from, to, message } = input;
16
+ const authkey = ctx.connection.config.authkey;
17
+ const url = new URL("https://api.msg91.com/api/sendhttp.php");
18
+ url.searchParams.set("authkey", authkey);
19
+ url.searchParams.set("route", "4");
20
+ url.searchParams.set("country", "0");
21
+ url.searchParams.set("sender", from);
22
+ url.searchParams.set("mobiles", to);
23
+ url.searchParams.set("message", message);
24
+ const res = await fetch(url.toString());
25
+ if (!res.ok)
26
+ throw new Error(`MSG91 API error ${res.status}: ${await res.text()}`);
27
+ const text = await res.text();
28
+ return { requestId: text };
29
+ },
30
+ });
31
+ }
@@ -0,0 +1,146 @@
1
+ const BASE_URL = "https://api.nasa.gov";
2
+ async function apiRequest(apiKey, endpoint, qs = {}) {
3
+ const url = new URL(`${BASE_URL}${endpoint}`);
4
+ url.searchParams.set("api_key", apiKey);
5
+ for (const [k, v] of Object.entries(qs)) {
6
+ if (v !== undefined && v !== null)
7
+ url.searchParams.set(k, String(v));
8
+ }
9
+ const res = await fetch(url.toString());
10
+ if (!res.ok)
11
+ throw new Error(`NASA API error ${res.status}: ${await res.text()}`);
12
+ return res.json();
13
+ }
14
+ function today() {
15
+ return new Date().toISOString().split("T")[0];
16
+ }
17
+ function formatDate(d) {
18
+ if (!d)
19
+ return undefined;
20
+ return String(d).split("T")[0];
21
+ }
22
+ export default function nasa(rl) {
23
+ rl.setName("nasa");
24
+ rl.setVersion("0.1.0");
25
+ rl.setConnectionSchema({
26
+ apiKey: { type: "string", required: true, description: "NASA API key (get one at https://api.nasa.gov)", env: "NASA_API_KEY" },
27
+ });
28
+ const key = (ctx) => ctx.connection.config.apiKey;
29
+ rl.registerAction("apod.get", {
30
+ description: "Get the Astronomy Picture of the Day (returns metadata; image URL in 'hdurl' field)",
31
+ inputSchema: { date: { type: "string", required: false, description: "Date (YYYY-MM-DD), defaults to today" } },
32
+ async execute(input, ctx) {
33
+ const qs = { date: formatDate(input?.date) ?? today() };
34
+ return apiRequest(key(ctx), "/planetary/apod", qs);
35
+ },
36
+ });
37
+ rl.registerAction("asteroidNeoFeed.get", {
38
+ description: "Get a list of asteroids based on closest approach date to Earth",
39
+ inputSchema: {
40
+ startDate: { type: "string", required: false, description: "Start date (YYYY-MM-DD), defaults to today" },
41
+ endDate: { type: "string", required: false, description: "End date (YYYY-MM-DD), defaults to today" },
42
+ },
43
+ async execute(input, ctx) {
44
+ const p = (input ?? {});
45
+ const qs = {
46
+ start_date: formatDate(p.startDate) ?? today(),
47
+ end_date: formatDate(p.endDate) ?? today(),
48
+ };
49
+ const data = (await apiRequest(key(ctx), "/neo/rest/v1/feed", qs));
50
+ return data.near_earth_objects;
51
+ },
52
+ });
53
+ rl.registerAction("asteroidNeoLookup.get", {
54
+ description: "Look up an asteroid by its NASA SPK-ID",
55
+ inputSchema: {
56
+ asteroidId: { type: "string", required: true },
57
+ includeCloseApproachData: { type: "boolean", required: false, description: "Include close approach data (default false)" },
58
+ },
59
+ async execute(input, ctx) {
60
+ const { asteroidId, includeCloseApproachData } = input;
61
+ const data = (await apiRequest(key(ctx), `/neo/rest/v1/neo/${asteroidId}`));
62
+ if (!includeCloseApproachData)
63
+ delete data.close_approach_data;
64
+ return data;
65
+ },
66
+ });
67
+ rl.registerAction("asteroidNeoBrowse.list", {
68
+ description: "Browse the overall asteroid dataset",
69
+ inputSchema: { limit: { type: "number", required: false, description: "Max results (default 20)" } },
70
+ async execute(input, ctx) {
71
+ const qs = {};
72
+ if (input?.limit)
73
+ qs.size = input.limit;
74
+ const data = (await apiRequest(key(ctx), "/neo/rest/v1/neo/browse", qs));
75
+ return data.near_earth_objects;
76
+ },
77
+ });
78
+ // ── DONKI endpoints ─────────────────────────────────
79
+ const donkiEndpoints = [
80
+ { name: "coronalMassEjection", path: "/DONKI/CME", description: "DONKI Coronal Mass Ejection data" },
81
+ { name: "solarFlare", path: "/DONKI/FLR", description: "DONKI Solar Flare data" },
82
+ { name: "solarEnergeticParticle", path: "/DONKI/SEP", description: "DONKI Solar Energetic Particle data" },
83
+ { name: "magnetopauseCrossing", path: "/DONKI/MPC", description: "DONKI Magnetopause Crossing data" },
84
+ { name: "radiationBeltEnhancement", path: "/DONKI/RBE", description: "DONKI Radiation Belt Enhancement data" },
85
+ { name: "highSpeedStream", path: "/DONKI/HSS", description: "DONKI High Speed Stream data" },
86
+ { name: "wsaEnlilSimulation", path: "/DONKI/WSAEnlilSimulations", description: "DONKI WSA+Enlil Simulation data" },
87
+ { name: "notifications", path: "/DONKI/notifications", description: "DONKI Notifications data" },
88
+ ];
89
+ for (const ep of donkiEndpoints) {
90
+ rl.registerAction(`donki.${ep.name}`, {
91
+ description: ep.description,
92
+ inputSchema: {
93
+ startDate: { type: "string", required: false, description: "Start date (YYYY-MM-DD), defaults to 30 days ago" },
94
+ endDate: { type: "string", required: false, description: "End date (YYYY-MM-DD), defaults to today" },
95
+ },
96
+ async execute(input, ctx) {
97
+ const p = (input ?? {});
98
+ const qs = {};
99
+ if (p.startDate)
100
+ qs.startDate = formatDate(p.startDate);
101
+ if (p.endDate)
102
+ qs.endDate = formatDate(p.endDate);
103
+ return apiRequest(key(ctx), ep.path, qs);
104
+ },
105
+ });
106
+ }
107
+ rl.registerAction("donki.interplanetaryShock", {
108
+ description: "DONKI Interplanetary Shock data",
109
+ inputSchema: {
110
+ startDate: { type: "string", required: false },
111
+ endDate: { type: "string", required: false },
112
+ location: { type: "string", required: false, description: "ALL (default), earth, MESSENGER, STEREO A, STEREO B" },
113
+ catalog: { type: "string", required: false, description: "ALL (default), SWRC_CATALOG, WINSLOW_MESSENGER_ICME_CATALOG" },
114
+ },
115
+ async execute(input, ctx) {
116
+ const p = (input ?? {});
117
+ const qs = {};
118
+ if (p.startDate)
119
+ qs.startDate = formatDate(p.startDate);
120
+ if (p.endDate)
121
+ qs.endDate = formatDate(p.endDate);
122
+ if (p.location)
123
+ qs.location = p.location;
124
+ if (p.catalog)
125
+ qs.catalog = p.catalog;
126
+ return apiRequest(key(ctx), "/DONKI/IPS", qs);
127
+ },
128
+ });
129
+ // ── Earth ───────────────────────────────────────────
130
+ rl.registerAction("earthAssets.get", {
131
+ description: "Get Earth asset metadata for a location",
132
+ inputSchema: {
133
+ lat: { type: "number", required: true, description: "Latitude" },
134
+ lon: { type: "number", required: true, description: "Longitude" },
135
+ date: { type: "string", required: false, description: "Date (YYYY-MM-DD)" },
136
+ dim: { type: "number", required: false, description: "Width/height in degrees (default 0.025)" },
137
+ },
138
+ async execute(input, ctx) {
139
+ const { lat, lon, date, dim } = input;
140
+ const qs = { lat, lon, dim: dim ?? 0.025 };
141
+ if (date)
142
+ qs.date = formatDate(date);
143
+ return apiRequest(key(ctx), "/planetary/earth/assets", qs);
144
+ },
145
+ });
146
+ }
@@ -0,0 +1,151 @@
1
+ const BASE = "https://api.netlify.com/api/v1";
2
+ function getToken(ctx) {
3
+ return ctx.connection.config.accessToken;
4
+ }
5
+ async function apiRequest(token, method, endpoint, body, qs) {
6
+ const url = new URL(`${BASE}${endpoint}`);
7
+ if (qs) {
8
+ for (const [k, v] of Object.entries(qs)) {
9
+ if (v !== undefined && v !== null)
10
+ url.searchParams.set(k, String(v));
11
+ }
12
+ }
13
+ const init = {
14
+ method,
15
+ headers: {
16
+ Authorization: `Bearer ${token}`,
17
+ "Content-Type": "application/json",
18
+ },
19
+ };
20
+ if (body && Object.keys(body).length > 0)
21
+ init.body = JSON.stringify(body);
22
+ const res = await fetch(url.toString(), init);
23
+ if (!res.ok)
24
+ throw new Error(`Netlify API error ${res.status}: ${await res.text()}`);
25
+ const text = await res.text();
26
+ return text ? JSON.parse(text) : {};
27
+ }
28
+ async function paginate(token, endpoint, qs = {}) {
29
+ const all = [];
30
+ let page = 0;
31
+ const perPage = 100;
32
+ // eslint-disable-next-line no-constant-condition
33
+ while (true) {
34
+ const url = new URL(`${BASE}${endpoint}`);
35
+ url.searchParams.set("page", String(page));
36
+ url.searchParams.set("per_page", String(perPage));
37
+ for (const [k, v] of Object.entries(qs)) {
38
+ if (v !== undefined && v !== null)
39
+ url.searchParams.set(k, String(v));
40
+ }
41
+ const res = await fetch(url.toString(), {
42
+ headers: { Authorization: `Bearer ${token}` },
43
+ });
44
+ if (!res.ok)
45
+ throw new Error(`Netlify API error ${res.status}: ${await res.text()}`);
46
+ const items = (await res.json());
47
+ all.push(...items);
48
+ const link = res.headers.get("link") ?? "";
49
+ if (!link.includes("next"))
50
+ break;
51
+ page++;
52
+ }
53
+ return all;
54
+ }
55
+ export default function netlify(rl) {
56
+ rl.setName("netlify");
57
+ rl.setVersion("0.1.0");
58
+ rl.setConnectionSchema({
59
+ accessToken: { type: "string", required: true, description: "Netlify personal access token", env: "NETLIFY_ACCESS_TOKEN" },
60
+ });
61
+ // ── Deploy ──────────────────────────────────────────
62
+ rl.registerAction("deploy.cancel", {
63
+ description: "Cancel a deployment",
64
+ inputSchema: {
65
+ deployId: { type: "string", required: true, description: "Deploy ID" },
66
+ },
67
+ async execute(input, ctx) {
68
+ const { deployId } = input;
69
+ return apiRequest(getToken(ctx), "POST", `/deploys/${deployId}/cancel`);
70
+ },
71
+ });
72
+ rl.registerAction("deploy.create", {
73
+ description: "Create a new deployment for a site",
74
+ inputSchema: {
75
+ siteId: { type: "string", required: true, description: "Site ID" },
76
+ branch: { type: "string", required: false, description: "Branch to deploy" },
77
+ title: { type: "string", required: false, description: "Deploy title" },
78
+ },
79
+ async execute(input, ctx) {
80
+ const { siteId, branch, title } = input;
81
+ const body = {};
82
+ const qs = {};
83
+ if (branch)
84
+ body.branch = branch;
85
+ if (title)
86
+ qs.title = title;
87
+ return apiRequest(getToken(ctx), "POST", `/sites/${siteId}/deploys`, body, qs);
88
+ },
89
+ });
90
+ rl.registerAction("deploy.get", {
91
+ description: "Get a deployment",
92
+ inputSchema: {
93
+ siteId: { type: "string", required: true, description: "Site ID" },
94
+ deployId: { type: "string", required: true, description: "Deploy ID" },
95
+ },
96
+ async execute(input, ctx) {
97
+ const { siteId, deployId } = input;
98
+ return apiRequest(getToken(ctx), "GET", `/sites/${siteId}/deploys/${deployId}`);
99
+ },
100
+ });
101
+ rl.registerAction("deploy.list", {
102
+ description: "List deployments for a site",
103
+ inputSchema: {
104
+ siteId: { type: "string", required: true, description: "Site ID" },
105
+ limit: { type: "number", required: false, description: "Max results (default all)" },
106
+ },
107
+ async execute(input, ctx) {
108
+ const { siteId, limit } = input;
109
+ const token = getToken(ctx);
110
+ if (limit) {
111
+ return apiRequest(token, "GET", `/sites/${siteId}/deploys`, undefined, { per_page: limit });
112
+ }
113
+ return paginate(token, `/sites/${siteId}/deploys`);
114
+ },
115
+ });
116
+ // ── Site ────────────────────────────────────────────
117
+ rl.registerAction("site.delete", {
118
+ description: "Delete a site",
119
+ inputSchema: {
120
+ siteId: { type: "string", required: true, description: "Site ID" },
121
+ },
122
+ async execute(input, ctx) {
123
+ const { siteId } = input;
124
+ return apiRequest(getToken(ctx), "DELETE", `/sites/${siteId}`);
125
+ },
126
+ });
127
+ rl.registerAction("site.get", {
128
+ description: "Get a site",
129
+ inputSchema: {
130
+ siteId: { type: "string", required: true, description: "Site ID" },
131
+ },
132
+ async execute(input, ctx) {
133
+ const { siteId } = input;
134
+ return apiRequest(getToken(ctx), "GET", `/sites/${siteId}`);
135
+ },
136
+ });
137
+ rl.registerAction("site.list", {
138
+ description: "List all sites",
139
+ inputSchema: {
140
+ limit: { type: "number", required: false, description: "Max results (default all)" },
141
+ },
142
+ async execute(input, ctx) {
143
+ const token = getToken(ctx);
144
+ const limit = input?.limit;
145
+ if (limit) {
146
+ return apiRequest(token, "GET", "/sites", undefined, { filter: "all", per_page: limit });
147
+ }
148
+ return paginate(token, "/sites", { filter: "all" });
149
+ },
150
+ });
151
+ }