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,630 @@
1
+ async function apiRequest(token, baseUrl, method, endpoint, body, qs) {
2
+ const url = new URL(`${baseUrl}${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 = {
10
+ method,
11
+ headers: {
12
+ Authorization: `Bearer ${token}`,
13
+ Accept: "application/vnd.github+json",
14
+ "Content-Type": "application/json",
15
+ "X-GitHub-Api-Version": "2022-11-28",
16
+ },
17
+ };
18
+ if (body && Object.keys(body).length > 0 && method !== "GET" && method !== "DELETE") {
19
+ opts.body = JSON.stringify(body);
20
+ }
21
+ const res = await fetch(url.toString(), opts);
22
+ if (!res.ok)
23
+ throw new Error(`GitHub API error ${res.status}: ${await res.text()}`);
24
+ if (res.status === 204)
25
+ return { success: true };
26
+ const ct = res.headers.get("content-type") ?? "";
27
+ if (ct.includes("application/json"))
28
+ return res.json();
29
+ return { success: true };
30
+ }
31
+ function getConn(ctx) {
32
+ const cfg = ctx.connection.config;
33
+ return {
34
+ token: cfg.token,
35
+ baseUrl: (cfg.baseUrl ?? "https://api.github.com").replace(/\/$/, ""),
36
+ };
37
+ }
38
+ function gh(ctx, method, endpoint, body, qs) {
39
+ const { token, baseUrl } = getConn(ctx);
40
+ return apiRequest(token, baseUrl, method, endpoint, body, qs);
41
+ }
42
+ export default function github(rl) {
43
+ rl.setName("github");
44
+ rl.setVersion("0.1.0");
45
+ rl.setConnectionSchema({
46
+ token: { type: "string", required: true, description: "GitHub personal access token", env: "GITHUB_TOKEN" },
47
+ baseUrl: { type: "string", required: false, description: "API base URL (default: https://api.github.com)", env: "GITHUB_API_URL", default: "https://api.github.com" },
48
+ });
49
+ // ── File ────────────────────────────────────────────
50
+ rl.registerAction("file.get", {
51
+ description: "Get a file's content from a repository",
52
+ inputSchema: {
53
+ owner: { type: "string", required: true, description: "Repository owner" },
54
+ repo: { type: "string", required: true, description: "Repository name" },
55
+ path: { type: "string", required: true, description: "File path" },
56
+ ref: { type: "string", required: false, description: "Branch, tag, or commit SHA" },
57
+ },
58
+ async execute(input, ctx) {
59
+ const { owner, repo, path, ref } = input;
60
+ const qs = {};
61
+ if (ref)
62
+ qs.ref = ref;
63
+ return gh(ctx, "GET", `/repos/${owner}/${repo}/contents/${path}`, undefined, qs);
64
+ },
65
+ });
66
+ rl.registerAction("file.createOrUpdate", {
67
+ description: "Create or update a file in a repository",
68
+ inputSchema: {
69
+ owner: { type: "string", required: true, description: "Repository owner" },
70
+ repo: { type: "string", required: true, description: "Repository name" },
71
+ path: { type: "string", required: true, description: "File path" },
72
+ content: { type: "string", required: true, description: "File content (will be base64 encoded)" },
73
+ message: { type: "string", required: true, description: "Commit message" },
74
+ sha: { type: "string", required: false, description: "SHA of file being replaced (required for updates)" },
75
+ branch: { type: "string", required: false, description: "Branch name" },
76
+ },
77
+ async execute(input, ctx) {
78
+ const { owner, repo, path, content, message, sha, branch } = input;
79
+ const body = { message, content: btoa(content) };
80
+ if (sha)
81
+ body.sha = sha;
82
+ if (branch)
83
+ body.branch = branch;
84
+ return gh(ctx, "PUT", `/repos/${owner}/${repo}/contents/${path}`, body);
85
+ },
86
+ });
87
+ rl.registerAction("file.delete", {
88
+ description: "Delete a file from a repository",
89
+ inputSchema: {
90
+ owner: { type: "string", required: true, description: "Repository owner" },
91
+ repo: { type: "string", required: true, description: "Repository name" },
92
+ path: { type: "string", required: true, description: "File path" },
93
+ sha: { type: "string", required: true, description: "SHA of file to delete" },
94
+ message: { type: "string", required: true, description: "Commit message" },
95
+ branch: { type: "string", required: false, description: "Branch name" },
96
+ },
97
+ async execute(input, ctx) {
98
+ const { owner, repo, path, sha, message, branch } = input;
99
+ const body = { sha, message };
100
+ if (branch)
101
+ body.branch = branch;
102
+ return gh(ctx, "DELETE", `/repos/${owner}/${repo}/contents/${path}`, body);
103
+ },
104
+ });
105
+ rl.registerAction("file.list", {
106
+ description: "List contents of a directory",
107
+ inputSchema: {
108
+ owner: { type: "string", required: true, description: "Repository owner" },
109
+ repo: { type: "string", required: true, description: "Repository name" },
110
+ path: { type: "string", required: false, description: "Directory path (default: root)" },
111
+ ref: { type: "string", required: false, description: "Branch, tag, or SHA" },
112
+ },
113
+ async execute(input, ctx) {
114
+ const { owner, repo, path = "", ref } = (input ?? {});
115
+ const qs = {};
116
+ if (ref)
117
+ qs.ref = ref;
118
+ return gh(ctx, "GET", `/repos/${owner}/${repo}/contents/${path}`, undefined, qs);
119
+ },
120
+ });
121
+ // ── Issue ───────────────────────────────────────────
122
+ rl.registerAction("issue.create", {
123
+ description: "Create an issue",
124
+ inputSchema: {
125
+ owner: { type: "string", required: true, description: "Repository owner" },
126
+ repo: { type: "string", required: true, description: "Repository name" },
127
+ title: { type: "string", required: true, description: "Issue title" },
128
+ body: { type: "string", required: false, description: "Issue body (markdown)" },
129
+ labels: { type: "array", required: false, description: "Label names" },
130
+ assignees: { type: "array", required: false, description: "Assignee usernames" },
131
+ milestone: { type: "number", required: false, description: "Milestone number" },
132
+ },
133
+ async execute(input, ctx) {
134
+ const { owner, repo, title, body: issueBody, labels, assignees, milestone } = input;
135
+ const b = { title };
136
+ if (issueBody)
137
+ b.body = issueBody;
138
+ if (labels)
139
+ b.labels = labels;
140
+ if (assignees)
141
+ b.assignees = assignees;
142
+ if (milestone)
143
+ b.milestone = milestone;
144
+ return gh(ctx, "POST", `/repos/${owner}/${repo}/issues`, b);
145
+ },
146
+ });
147
+ rl.registerAction("issue.get", {
148
+ description: "Get an issue",
149
+ inputSchema: {
150
+ owner: { type: "string", required: true, description: "Repository owner" },
151
+ repo: { type: "string", required: true, description: "Repository name" },
152
+ issueNumber: { type: "number", required: true, description: "Issue number" },
153
+ },
154
+ async execute(input, ctx) {
155
+ const { owner, repo, issueNumber } = input;
156
+ return gh(ctx, "GET", `/repos/${owner}/${repo}/issues/${issueNumber}`);
157
+ },
158
+ });
159
+ rl.registerAction("issue.update", {
160
+ description: "Update an issue",
161
+ inputSchema: {
162
+ owner: { type: "string", required: true, description: "Repository owner" },
163
+ repo: { type: "string", required: true, description: "Repository name" },
164
+ issueNumber: { type: "number", required: true, description: "Issue number" },
165
+ title: { type: "string", required: false, description: "New title" },
166
+ body: { type: "string", required: false, description: "New body" },
167
+ state: { type: "string", required: false, description: "open or closed" },
168
+ labels: { type: "array", required: false, description: "Labels" },
169
+ assignees: { type: "array", required: false, description: "Assignees" },
170
+ },
171
+ async execute(input, ctx) {
172
+ const { owner, repo, issueNumber, ...fields } = input;
173
+ return gh(ctx, "PATCH", `/repos/${owner}/${repo}/issues/${issueNumber}`, fields);
174
+ },
175
+ });
176
+ rl.registerAction("issue.createComment", {
177
+ description: "Create a comment on an issue",
178
+ inputSchema: {
179
+ owner: { type: "string", required: true, description: "Repository owner" },
180
+ repo: { type: "string", required: true, description: "Repository name" },
181
+ issueNumber: { type: "number", required: true, description: "Issue number" },
182
+ body: { type: "string", required: true, description: "Comment body (markdown)" },
183
+ },
184
+ async execute(input, ctx) {
185
+ const { owner, repo, issueNumber, body: commentBody } = input;
186
+ return gh(ctx, "POST", `/repos/${owner}/${repo}/issues/${issueNumber}/comments`, { body: commentBody });
187
+ },
188
+ });
189
+ rl.registerAction("issue.lock", {
190
+ description: "Lock an issue",
191
+ inputSchema: {
192
+ owner: { type: "string", required: true, description: "Repository owner" },
193
+ repo: { type: "string", required: true, description: "Repository name" },
194
+ issueNumber: { type: "number", required: true, description: "Issue number" },
195
+ lockReason: { type: "string", required: false, description: "Reason: off-topic, too heated, resolved, spam" },
196
+ },
197
+ async execute(input, ctx) {
198
+ const { owner, repo, issueNumber, lockReason } = input;
199
+ const body = {};
200
+ if (lockReason)
201
+ body.lock_reason = lockReason;
202
+ await gh(ctx, "PUT", `/repos/${owner}/${repo}/issues/${issueNumber}/lock`, body);
203
+ return { success: true };
204
+ },
205
+ });
206
+ // ── Release ─────────────────────────────────────────
207
+ rl.registerAction("release.create", {
208
+ description: "Create a release",
209
+ inputSchema: {
210
+ owner: { type: "string", required: true, description: "Repository owner" },
211
+ repo: { type: "string", required: true, description: "Repository name" },
212
+ tagName: { type: "string", required: true, description: "Tag name" },
213
+ name: { type: "string", required: false, description: "Release name" },
214
+ body: { type: "string", required: false, description: "Release notes (markdown)" },
215
+ draft: { type: "boolean", required: false, description: "Create as draft" },
216
+ prerelease: { type: "boolean", required: false, description: "Mark as pre-release" },
217
+ targetCommitish: { type: "string", required: false, description: "Branch or commit SHA for the tag" },
218
+ },
219
+ async execute(input, ctx) {
220
+ const { owner, repo, tagName, name, body: releaseBody, draft, prerelease, targetCommitish } = input;
221
+ const b = { tag_name: tagName };
222
+ if (name)
223
+ b.name = name;
224
+ if (releaseBody)
225
+ b.body = releaseBody;
226
+ if (draft !== undefined)
227
+ b.draft = draft;
228
+ if (prerelease !== undefined)
229
+ b.prerelease = prerelease;
230
+ if (targetCommitish)
231
+ b.target_commitish = targetCommitish;
232
+ return gh(ctx, "POST", `/repos/${owner}/${repo}/releases`, b);
233
+ },
234
+ });
235
+ rl.registerAction("release.get", {
236
+ description: "Get a release",
237
+ inputSchema: {
238
+ owner: { type: "string", required: true, description: "Repository owner" },
239
+ repo: { type: "string", required: true, description: "Repository name" },
240
+ releaseId: { type: "string", required: true, description: "Release ID" },
241
+ },
242
+ async execute(input, ctx) {
243
+ const { owner, repo, releaseId } = input;
244
+ return gh(ctx, "GET", `/repos/${owner}/${repo}/releases/${releaseId}`);
245
+ },
246
+ });
247
+ rl.registerAction("release.list", {
248
+ description: "List releases",
249
+ inputSchema: {
250
+ owner: { type: "string", required: true, description: "Repository owner" },
251
+ repo: { type: "string", required: true, description: "Repository name" },
252
+ perPage: { type: "number", required: false, description: "Results per page (max: 100)" },
253
+ page: { type: "number", required: false, description: "Page number" },
254
+ },
255
+ async execute(input, ctx) {
256
+ const { owner, repo, perPage, page } = (input ?? {});
257
+ const qs = {};
258
+ if (perPage)
259
+ qs.per_page = perPage;
260
+ if (page)
261
+ qs.page = page;
262
+ return gh(ctx, "GET", `/repos/${owner}/${repo}/releases`, undefined, qs);
263
+ },
264
+ });
265
+ rl.registerAction("release.update", {
266
+ description: "Update a release",
267
+ inputSchema: {
268
+ owner: { type: "string", required: true, description: "Repository owner" },
269
+ repo: { type: "string", required: true, description: "Repository name" },
270
+ releaseId: { type: "string", required: true, description: "Release ID" },
271
+ tagName: { type: "string", required: false, description: "New tag name" },
272
+ name: { type: "string", required: false, description: "New name" },
273
+ body: { type: "string", required: false, description: "New release notes" },
274
+ draft: { type: "boolean", required: false, description: "Draft flag" },
275
+ prerelease: { type: "boolean", required: false, description: "Pre-release flag" },
276
+ },
277
+ async execute(input, ctx) {
278
+ const { owner, repo, releaseId, tagName, name, body: releaseBody, draft, prerelease } = input;
279
+ const b = {};
280
+ if (tagName)
281
+ b.tag_name = tagName;
282
+ if (name)
283
+ b.name = name;
284
+ if (releaseBody !== undefined)
285
+ b.body = releaseBody;
286
+ if (draft !== undefined)
287
+ b.draft = draft;
288
+ if (prerelease !== undefined)
289
+ b.prerelease = prerelease;
290
+ return gh(ctx, "PATCH", `/repos/${owner}/${repo}/releases/${releaseId}`, b);
291
+ },
292
+ });
293
+ rl.registerAction("release.delete", {
294
+ description: "Delete a release",
295
+ inputSchema: {
296
+ owner: { type: "string", required: true, description: "Repository owner" },
297
+ repo: { type: "string", required: true, description: "Repository name" },
298
+ releaseId: { type: "string", required: true, description: "Release ID" },
299
+ },
300
+ async execute(input, ctx) {
301
+ const { owner, repo, releaseId } = input;
302
+ await gh(ctx, "DELETE", `/repos/${owner}/${repo}/releases/${releaseId}`);
303
+ return { success: true };
304
+ },
305
+ });
306
+ // ── Repository ──────────────────────────────────────
307
+ rl.registerAction("repository.get", {
308
+ description: "Get repository details",
309
+ inputSchema: {
310
+ owner: { type: "string", required: true, description: "Repository owner" },
311
+ repo: { type: "string", required: true, description: "Repository name" },
312
+ },
313
+ async execute(input, ctx) {
314
+ const { owner, repo } = input;
315
+ return gh(ctx, "GET", `/repos/${owner}/${repo}`);
316
+ },
317
+ });
318
+ rl.registerAction("repository.getLicense", {
319
+ description: "Get a repository's license",
320
+ inputSchema: {
321
+ owner: { type: "string", required: true, description: "Repository owner" },
322
+ repo: { type: "string", required: true, description: "Repository name" },
323
+ },
324
+ async execute(input, ctx) {
325
+ const { owner, repo } = input;
326
+ return gh(ctx, "GET", `/repos/${owner}/${repo}/license`);
327
+ },
328
+ });
329
+ rl.registerAction("repository.listIssues", {
330
+ description: "List issues for a repository",
331
+ inputSchema: {
332
+ owner: { type: "string", required: true, description: "Repository owner" },
333
+ repo: { type: "string", required: true, description: "Repository name" },
334
+ state: { type: "string", required: false, description: "open, closed, or all" },
335
+ labels: { type: "string", required: false, description: "Comma-separated label names" },
336
+ sort: { type: "string", required: false, description: "created, updated, comments" },
337
+ direction: { type: "string", required: false, description: "asc or desc" },
338
+ perPage: { type: "number", required: false, description: "Results per page" },
339
+ page: { type: "number", required: false, description: "Page number" },
340
+ },
341
+ async execute(input, ctx) {
342
+ const { owner, repo, state, labels, sort, direction, perPage, page } = (input ?? {});
343
+ const qs = {};
344
+ if (state)
345
+ qs.state = state;
346
+ if (labels)
347
+ qs.labels = labels;
348
+ if (sort)
349
+ qs.sort = sort;
350
+ if (direction)
351
+ qs.direction = direction;
352
+ if (perPage)
353
+ qs.per_page = perPage;
354
+ if (page)
355
+ qs.page = page;
356
+ return gh(ctx, "GET", `/repos/${owner}/${repo}/issues`, undefined, qs);
357
+ },
358
+ });
359
+ rl.registerAction("repository.listPullRequests", {
360
+ description: "List pull requests",
361
+ inputSchema: {
362
+ owner: { type: "string", required: true, description: "Repository owner" },
363
+ repo: { type: "string", required: true, description: "Repository name" },
364
+ state: { type: "string", required: false, description: "open, closed, or all" },
365
+ sort: { type: "string", required: false, description: "created, updated, popularity, long-running" },
366
+ direction: { type: "string", required: false, description: "asc or desc" },
367
+ perPage: { type: "number", required: false, description: "Results per page" },
368
+ page: { type: "number", required: false, description: "Page number" },
369
+ },
370
+ async execute(input, ctx) {
371
+ const { owner, repo, state, sort, direction, perPage, page } = (input ?? {});
372
+ const qs = {};
373
+ if (state)
374
+ qs.state = state;
375
+ if (sort)
376
+ qs.sort = sort;
377
+ if (direction)
378
+ qs.direction = direction;
379
+ if (perPage)
380
+ qs.per_page = perPage;
381
+ if (page)
382
+ qs.page = page;
383
+ return gh(ctx, "GET", `/repos/${owner}/${repo}/pulls`, undefined, qs);
384
+ },
385
+ });
386
+ rl.registerAction("repository.listPopularPaths", {
387
+ description: "List popular content paths (traffic)",
388
+ inputSchema: {
389
+ owner: { type: "string", required: true, description: "Repository owner" },
390
+ repo: { type: "string", required: true, description: "Repository name" },
391
+ },
392
+ async execute(input, ctx) {
393
+ const { owner, repo } = input;
394
+ return gh(ctx, "GET", `/repos/${owner}/${repo}/traffic/popular/paths`);
395
+ },
396
+ });
397
+ rl.registerAction("repository.listReferrers", {
398
+ description: "List top referral sources (traffic)",
399
+ inputSchema: {
400
+ owner: { type: "string", required: true, description: "Repository owner" },
401
+ repo: { type: "string", required: true, description: "Repository name" },
402
+ },
403
+ async execute(input, ctx) {
404
+ const { owner, repo } = input;
405
+ return gh(ctx, "GET", `/repos/${owner}/${repo}/traffic/popular/referrers`);
406
+ },
407
+ });
408
+ // ── Review ──────────────────────────────────────────
409
+ rl.registerAction("review.get", {
410
+ description: "Get a pull request review",
411
+ inputSchema: {
412
+ owner: { type: "string", required: true, description: "Repository owner" },
413
+ repo: { type: "string", required: true, description: "Repository name" },
414
+ pullNumber: { type: "number", required: true, description: "Pull request number" },
415
+ reviewId: { type: "number", required: true, description: "Review ID" },
416
+ },
417
+ async execute(input, ctx) {
418
+ const { owner, repo, pullNumber, reviewId } = input;
419
+ return gh(ctx, "GET", `/repos/${owner}/${repo}/pulls/${pullNumber}/reviews/${reviewId}`);
420
+ },
421
+ });
422
+ rl.registerAction("review.list", {
423
+ description: "List reviews on a pull request",
424
+ inputSchema: {
425
+ owner: { type: "string", required: true, description: "Repository owner" },
426
+ repo: { type: "string", required: true, description: "Repository name" },
427
+ pullNumber: { type: "number", required: true, description: "Pull request number" },
428
+ },
429
+ async execute(input, ctx) {
430
+ const { owner, repo, pullNumber } = input;
431
+ return gh(ctx, "GET", `/repos/${owner}/${repo}/pulls/${pullNumber}/reviews`);
432
+ },
433
+ });
434
+ rl.registerAction("review.create", {
435
+ description: "Create a review on a pull request",
436
+ inputSchema: {
437
+ owner: { type: "string", required: true, description: "Repository owner" },
438
+ repo: { type: "string", required: true, description: "Repository name" },
439
+ pullNumber: { type: "number", required: true, description: "Pull request number" },
440
+ event: { type: "string", required: true, description: "APPROVE, REQUEST_CHANGES, or COMMENT" },
441
+ body: { type: "string", required: false, description: "Review body" },
442
+ },
443
+ async execute(input, ctx) {
444
+ const { owner, repo, pullNumber, event, body: reviewBody } = input;
445
+ const b = { event };
446
+ if (reviewBody)
447
+ b.body = reviewBody;
448
+ return gh(ctx, "POST", `/repos/${owner}/${repo}/pulls/${pullNumber}/reviews`, b);
449
+ },
450
+ });
451
+ rl.registerAction("review.update", {
452
+ description: "Update a review",
453
+ inputSchema: {
454
+ owner: { type: "string", required: true, description: "Repository owner" },
455
+ repo: { type: "string", required: true, description: "Repository name" },
456
+ pullNumber: { type: "number", required: true, description: "Pull request number" },
457
+ reviewId: { type: "number", required: true, description: "Review ID" },
458
+ body: { type: "string", required: true, description: "Updated review body" },
459
+ },
460
+ async execute(input, ctx) {
461
+ const { owner, repo, pullNumber, reviewId, body: reviewBody } = input;
462
+ return gh(ctx, "PUT", `/repos/${owner}/${repo}/pulls/${pullNumber}/reviews/${reviewId}`, { body: reviewBody });
463
+ },
464
+ });
465
+ // ── User ────────────────────────────────────────────
466
+ rl.registerAction("user.listRepos", {
467
+ description: "List repositories for a user",
468
+ inputSchema: {
469
+ username: { type: "string", required: false, description: "Username (omit for authenticated user)" },
470
+ type: { type: "string", required: false, description: "all, owner, member" },
471
+ sort: { type: "string", required: false, description: "created, updated, pushed, full_name" },
472
+ perPage: { type: "number", required: false, description: "Results per page" },
473
+ page: { type: "number", required: false, description: "Page number" },
474
+ },
475
+ async execute(input, ctx) {
476
+ const { username, type, sort, perPage, page } = (input ?? {});
477
+ const qs = {};
478
+ if (type)
479
+ qs.type = type;
480
+ if (sort)
481
+ qs.sort = sort;
482
+ if (perPage)
483
+ qs.per_page = perPage;
484
+ if (page)
485
+ qs.page = page;
486
+ const endpoint = username ? `/users/${username}/repos` : "/user/repos";
487
+ return gh(ctx, "GET", endpoint, undefined, qs);
488
+ },
489
+ });
490
+ rl.registerAction("user.listIssues", {
491
+ description: "List issues assigned to the authenticated user",
492
+ inputSchema: {
493
+ state: { type: "string", required: false, description: "open, closed, or all" },
494
+ sort: { type: "string", required: false, description: "created, updated, comments" },
495
+ perPage: { type: "number", required: false, description: "Results per page" },
496
+ },
497
+ async execute(input, ctx) {
498
+ const { state, sort, perPage } = (input ?? {});
499
+ const qs = {};
500
+ if (state)
501
+ qs.state = state;
502
+ if (sort)
503
+ qs.sort = sort;
504
+ if (perPage)
505
+ qs.per_page = perPage;
506
+ return gh(ctx, "GET", "/user/issues", undefined, qs);
507
+ },
508
+ });
509
+ rl.registerAction("user.invite", {
510
+ description: "Invite a user to a repository",
511
+ inputSchema: {
512
+ owner: { type: "string", required: true, description: "Repository owner" },
513
+ repo: { type: "string", required: true, description: "Repository name" },
514
+ username: { type: "string", required: true, description: "Username to invite" },
515
+ permission: { type: "string", required: false, description: "pull, push, admin, maintain, triage" },
516
+ },
517
+ async execute(input, ctx) {
518
+ const { owner, repo, username, permission } = input;
519
+ const body = {};
520
+ if (permission)
521
+ body.permission = permission;
522
+ return gh(ctx, "PUT", `/repos/${owner}/${repo}/collaborators/${username}`, body);
523
+ },
524
+ });
525
+ // ── Organization ────────────────────────────────────
526
+ rl.registerAction("organization.listRepos", {
527
+ description: "List repositories for an organization",
528
+ inputSchema: {
529
+ org: { type: "string", required: true, description: "Organization name" },
530
+ type: { type: "string", required: false, description: "all, public, private, forks, sources, member" },
531
+ sort: { type: "string", required: false, description: "created, updated, pushed, full_name" },
532
+ perPage: { type: "number", required: false, description: "Results per page" },
533
+ page: { type: "number", required: false, description: "Page number" },
534
+ },
535
+ async execute(input, ctx) {
536
+ const { org, type, sort, perPage, page } = (input ?? {});
537
+ const qs = {};
538
+ if (type)
539
+ qs.type = type;
540
+ if (sort)
541
+ qs.sort = sort;
542
+ if (perPage)
543
+ qs.per_page = perPage;
544
+ if (page)
545
+ qs.page = page;
546
+ return gh(ctx, "GET", `/orgs/${org}/repos`, undefined, qs);
547
+ },
548
+ });
549
+ // ── Workflow ────────────────────────────────────────
550
+ rl.registerAction("workflow.list", {
551
+ description: "List workflows in a repository",
552
+ inputSchema: {
553
+ owner: { type: "string", required: true, description: "Repository owner" },
554
+ repo: { type: "string", required: true, description: "Repository name" },
555
+ },
556
+ async execute(input, ctx) {
557
+ const { owner, repo } = input;
558
+ const data = (await gh(ctx, "GET", `/repos/${owner}/${repo}/actions/workflows`));
559
+ return data.workflows;
560
+ },
561
+ });
562
+ rl.registerAction("workflow.get", {
563
+ description: "Get a workflow",
564
+ inputSchema: {
565
+ owner: { type: "string", required: true, description: "Repository owner" },
566
+ repo: { type: "string", required: true, description: "Repository name" },
567
+ workflowId: { type: "string", required: true, description: "Workflow ID or filename" },
568
+ },
569
+ async execute(input, ctx) {
570
+ const { owner, repo, workflowId } = input;
571
+ return gh(ctx, "GET", `/repos/${owner}/${repo}/actions/workflows/${workflowId}`);
572
+ },
573
+ });
574
+ rl.registerAction("workflow.dispatch", {
575
+ description: "Trigger a workflow dispatch event",
576
+ inputSchema: {
577
+ owner: { type: "string", required: true, description: "Repository owner" },
578
+ repo: { type: "string", required: true, description: "Repository name" },
579
+ workflowId: { type: "string", required: true, description: "Workflow ID or filename" },
580
+ ref: { type: "string", required: true, description: "Branch or tag to run on" },
581
+ inputs: { type: "object", required: false, description: "Workflow input parameters" },
582
+ },
583
+ async execute(input, ctx) {
584
+ const { owner, repo, workflowId, ref, inputs } = input;
585
+ const body = { ref };
586
+ if (inputs)
587
+ body.inputs = inputs;
588
+ await gh(ctx, "POST", `/repos/${owner}/${repo}/actions/workflows/${workflowId}/dispatches`, body);
589
+ return { success: true };
590
+ },
591
+ });
592
+ rl.registerAction("workflow.enable", {
593
+ description: "Enable a workflow",
594
+ inputSchema: {
595
+ owner: { type: "string", required: true, description: "Repository owner" },
596
+ repo: { type: "string", required: true, description: "Repository name" },
597
+ workflowId: { type: "string", required: true, description: "Workflow ID" },
598
+ },
599
+ async execute(input, ctx) {
600
+ const { owner, repo, workflowId } = input;
601
+ await gh(ctx, "PUT", `/repos/${owner}/${repo}/actions/workflows/${workflowId}/enable`);
602
+ return { success: true };
603
+ },
604
+ });
605
+ rl.registerAction("workflow.disable", {
606
+ description: "Disable a workflow",
607
+ inputSchema: {
608
+ owner: { type: "string", required: true, description: "Repository owner" },
609
+ repo: { type: "string", required: true, description: "Repository name" },
610
+ workflowId: { type: "string", required: true, description: "Workflow ID" },
611
+ },
612
+ async execute(input, ctx) {
613
+ const { owner, repo, workflowId } = input;
614
+ await gh(ctx, "PUT", `/repos/${owner}/${repo}/actions/workflows/${workflowId}/disable`);
615
+ return { success: true };
616
+ },
617
+ });
618
+ rl.registerAction("workflow.getUsage", {
619
+ description: "Get workflow usage billing",
620
+ inputSchema: {
621
+ owner: { type: "string", required: true, description: "Repository owner" },
622
+ repo: { type: "string", required: true, description: "Repository name" },
623
+ workflowId: { type: "string", required: true, description: "Workflow ID" },
624
+ },
625
+ async execute(input, ctx) {
626
+ const { owner, repo, workflowId } = input;
627
+ return gh(ctx, "GET", `/repos/${owner}/${repo}/actions/workflows/${workflowId}/timing`);
628
+ },
629
+ });
630
+ }