patchwork-os 0.2.0-alpha.3 → 0.2.0-alpha.31

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 (301) hide show
  1. package/README.bridge.md +6 -0
  2. package/README.md +40 -15
  3. package/deploy/bootstrap-vps.sh +184 -0
  4. package/deploy/deploy-dashboard.sh +174 -0
  5. package/deploy/deploy-landing.sh +79 -0
  6. package/dist/activationMetrics.d.ts +67 -0
  7. package/dist/activationMetrics.js +255 -0
  8. package/dist/activationMetrics.js.map +1 -0
  9. package/dist/approvalHttp.d.ts +24 -2
  10. package/dist/approvalHttp.js +150 -10
  11. package/dist/approvalHttp.js.map +1 -1
  12. package/dist/approvalQueue.d.ts +16 -1
  13. package/dist/approvalQueue.js +44 -3
  14. package/dist/approvalQueue.js.map +1 -1
  15. package/dist/automation.d.ts +20 -0
  16. package/dist/automation.js +54 -1
  17. package/dist/automation.js.map +1 -1
  18. package/dist/bridge.d.ts +2 -0
  19. package/dist/bridge.js +55 -130
  20. package/dist/bridge.js.map +1 -1
  21. package/dist/bridgeToken.js +57 -19
  22. package/dist/bridgeToken.js.map +1 -1
  23. package/dist/ccPermissions.js +6 -4
  24. package/dist/ccPermissions.js.map +1 -1
  25. package/dist/claudeOrchestrator.d.ts +1 -1
  26. package/dist/claudeOrchestrator.js +14 -8
  27. package/dist/claudeOrchestrator.js.map +1 -1
  28. package/dist/commands/launchd.d.ts +2 -0
  29. package/dist/commands/launchd.js +94 -0
  30. package/dist/commands/launchd.js.map +1 -0
  31. package/dist/commands/recipe.d.ts +258 -0
  32. package/dist/commands/recipe.js +1130 -0
  33. package/dist/commands/recipe.js.map +1 -0
  34. package/dist/commands/recipeInstall.d.ts +72 -0
  35. package/dist/commands/recipeInstall.js +339 -0
  36. package/dist/commands/recipeInstall.js.map +1 -0
  37. package/dist/config.d.ts +14 -1
  38. package/dist/config.js +99 -8
  39. package/dist/config.js.map +1 -1
  40. package/dist/connectors/baseConnector.d.ts +117 -0
  41. package/dist/connectors/baseConnector.js +213 -0
  42. package/dist/connectors/baseConnector.js.map +1 -0
  43. package/dist/connectors/confluence.d.ts +111 -0
  44. package/dist/connectors/confluence.js +406 -0
  45. package/dist/connectors/confluence.js.map +1 -0
  46. package/dist/connectors/datadog.d.ts +116 -0
  47. package/dist/connectors/datadog.js +385 -0
  48. package/dist/connectors/datadog.js.map +1 -0
  49. package/dist/connectors/fixtureLibrary.d.ts +21 -0
  50. package/dist/connectors/fixtureLibrary.js +70 -0
  51. package/dist/connectors/fixtureLibrary.js.map +1 -0
  52. package/dist/connectors/fixtureRecorder.d.ts +1 -0
  53. package/dist/connectors/fixtureRecorder.js +35 -0
  54. package/dist/connectors/fixtureRecorder.js.map +1 -0
  55. package/dist/connectors/github.d.ts +58 -8
  56. package/dist/connectors/github.js +312 -84
  57. package/dist/connectors/github.js.map +1 -1
  58. package/dist/connectors/gmail.d.ts +4 -1
  59. package/dist/connectors/gmail.js +79 -16
  60. package/dist/connectors/gmail.js.map +1 -1
  61. package/dist/connectors/googleCalendar.d.ts +60 -0
  62. package/dist/connectors/googleCalendar.js +345 -0
  63. package/dist/connectors/googleCalendar.js.map +1 -0
  64. package/dist/connectors/hubspot.d.ts +112 -0
  65. package/dist/connectors/hubspot.js +408 -0
  66. package/dist/connectors/hubspot.js.map +1 -0
  67. package/dist/connectors/intercom.d.ts +102 -0
  68. package/dist/connectors/intercom.js +402 -0
  69. package/dist/connectors/intercom.js.map +1 -0
  70. package/dist/connectors/jira.d.ts +98 -0
  71. package/dist/connectors/jira.js +379 -0
  72. package/dist/connectors/jira.js.map +1 -0
  73. package/dist/connectors/linear.d.ts +69 -19
  74. package/dist/connectors/linear.js +170 -129
  75. package/dist/connectors/linear.js.map +1 -1
  76. package/dist/connectors/mcpClient.d.ts +56 -0
  77. package/dist/connectors/mcpClient.js +189 -0
  78. package/dist/connectors/mcpClient.js.map +1 -0
  79. package/dist/connectors/mcpOAuth.d.ts +84 -0
  80. package/dist/connectors/mcpOAuth.js +389 -0
  81. package/dist/connectors/mcpOAuth.js.map +1 -0
  82. package/dist/connectors/mockConnector.d.ts +28 -0
  83. package/dist/connectors/mockConnector.js +81 -0
  84. package/dist/connectors/mockConnector.js.map +1 -0
  85. package/dist/connectors/notion.d.ts +143 -0
  86. package/dist/connectors/notion.js +424 -0
  87. package/dist/connectors/notion.js.map +1 -0
  88. package/dist/connectors/sentry.d.ts +17 -21
  89. package/dist/connectors/sentry.js +115 -131
  90. package/dist/connectors/sentry.js.map +1 -1
  91. package/dist/connectors/slack.d.ts +50 -0
  92. package/dist/connectors/slack.js +324 -0
  93. package/dist/connectors/slack.js.map +1 -0
  94. package/dist/connectors/stripe.d.ts +116 -0
  95. package/dist/connectors/stripe.js +379 -0
  96. package/dist/connectors/stripe.js.map +1 -0
  97. package/dist/connectors/tokenStorage.d.ts +35 -0
  98. package/dist/connectors/tokenStorage.js +459 -0
  99. package/dist/connectors/tokenStorage.js.map +1 -0
  100. package/dist/connectors/zendesk.d.ts +104 -0
  101. package/dist/connectors/zendesk.js +424 -0
  102. package/dist/connectors/zendesk.js.map +1 -0
  103. package/dist/drivers/gemini/index.d.ts +5 -1
  104. package/dist/drivers/gemini/index.js +39 -5
  105. package/dist/drivers/gemini/index.js.map +1 -1
  106. package/dist/drivers/index.d.ts +5 -0
  107. package/dist/drivers/index.js +1 -1
  108. package/dist/drivers/index.js.map +1 -1
  109. package/dist/featureFlags.d.ts +73 -0
  110. package/dist/featureFlags.js +203 -0
  111. package/dist/featureFlags.js.map +1 -0
  112. package/dist/fp/automationInterpreter.js +1 -0
  113. package/dist/fp/automationInterpreter.js.map +1 -1
  114. package/dist/fp/automationProgram.d.ts +1 -1
  115. package/dist/fp/automationProgram.js.map +1 -1
  116. package/dist/fp/policyParser.js +17 -0
  117. package/dist/fp/policyParser.js.map +1 -1
  118. package/dist/index.js +621 -61
  119. package/dist/index.js.map +1 -1
  120. package/dist/installGuard.d.ts +25 -0
  121. package/dist/installGuard.js +48 -0
  122. package/dist/installGuard.js.map +1 -0
  123. package/dist/oauth.d.ts +4 -1
  124. package/dist/oauth.js +50 -14
  125. package/dist/oauth.js.map +1 -1
  126. package/dist/patchworkConfig.d.ts +9 -0
  127. package/dist/patchworkConfig.js.map +1 -1
  128. package/dist/recipeOrchestration.d.ts +53 -0
  129. package/dist/recipeOrchestration.js +272 -0
  130. package/dist/recipeOrchestration.js.map +1 -0
  131. package/dist/recipes/RecipeOrchestrator.d.ts +40 -0
  132. package/dist/recipes/RecipeOrchestrator.js +51 -0
  133. package/dist/recipes/RecipeOrchestrator.js.map +1 -0
  134. package/dist/recipes/agentExecutor.d.ts +28 -0
  135. package/dist/recipes/agentExecutor.js +42 -0
  136. package/dist/recipes/agentExecutor.js.map +1 -0
  137. package/dist/recipes/chainedRunner.d.ts +140 -0
  138. package/dist/recipes/chainedRunner.js +539 -0
  139. package/dist/recipes/chainedRunner.js.map +1 -0
  140. package/dist/recipes/dependencyGraph.d.ts +39 -0
  141. package/dist/recipes/dependencyGraph.js +199 -0
  142. package/dist/recipes/dependencyGraph.js.map +1 -0
  143. package/dist/recipes/legacyRecipeCompat.d.ts +2 -0
  144. package/dist/recipes/legacyRecipeCompat.js +112 -0
  145. package/dist/recipes/legacyRecipeCompat.js.map +1 -0
  146. package/dist/recipes/manifest.d.ts +47 -0
  147. package/dist/recipes/manifest.js +141 -0
  148. package/dist/recipes/manifest.js.map +1 -0
  149. package/dist/recipes/nestedRecipeStep.d.ts +58 -0
  150. package/dist/recipes/nestedRecipeStep.js +95 -0
  151. package/dist/recipes/nestedRecipeStep.js.map +1 -0
  152. package/dist/recipes/outputRegistry.d.ts +28 -0
  153. package/dist/recipes/outputRegistry.js +52 -0
  154. package/dist/recipes/outputRegistry.js.map +1 -0
  155. package/dist/recipes/scheduler.d.ts +23 -7
  156. package/dist/recipes/scheduler.js +131 -41
  157. package/dist/recipes/scheduler.js.map +1 -1
  158. package/dist/recipes/schema.d.ts +17 -2
  159. package/dist/recipes/schemaGenerator.d.ts +28 -0
  160. package/dist/recipes/schemaGenerator.js +565 -0
  161. package/dist/recipes/schemaGenerator.js.map +1 -0
  162. package/dist/recipes/templateEngine.d.ts +62 -0
  163. package/dist/recipes/templateEngine.js +182 -0
  164. package/dist/recipes/templateEngine.js.map +1 -0
  165. package/dist/recipes/toolRegistry.d.ts +181 -0
  166. package/dist/recipes/toolRegistry.js +300 -0
  167. package/dist/recipes/toolRegistry.js.map +1 -0
  168. package/dist/recipes/tools/calendar.d.ts +6 -0
  169. package/dist/recipes/tools/calendar.js +61 -0
  170. package/dist/recipes/tools/calendar.js.map +1 -0
  171. package/dist/recipes/tools/confluence.d.ts +6 -0
  172. package/dist/recipes/tools/confluence.js +254 -0
  173. package/dist/recipes/tools/confluence.js.map +1 -0
  174. package/dist/recipes/tools/datadog.d.ts +6 -0
  175. package/dist/recipes/tools/datadog.js +239 -0
  176. package/dist/recipes/tools/datadog.js.map +1 -0
  177. package/dist/recipes/tools/diagnostics.d.ts +6 -0
  178. package/dist/recipes/tools/diagnostics.js +36 -0
  179. package/dist/recipes/tools/diagnostics.js.map +1 -0
  180. package/dist/recipes/tools/file.d.ts +6 -0
  181. package/dist/recipes/tools/file.js +170 -0
  182. package/dist/recipes/tools/file.js.map +1 -0
  183. package/dist/recipes/tools/git.d.ts +6 -0
  184. package/dist/recipes/tools/git.js +63 -0
  185. package/dist/recipes/tools/git.js.map +1 -0
  186. package/dist/recipes/tools/github.d.ts +6 -0
  187. package/dist/recipes/tools/github.js +91 -0
  188. package/dist/recipes/tools/github.js.map +1 -0
  189. package/dist/recipes/tools/gmail.d.ts +6 -0
  190. package/dist/recipes/tools/gmail.js +210 -0
  191. package/dist/recipes/tools/gmail.js.map +1 -0
  192. package/dist/recipes/tools/hubspot.d.ts +6 -0
  193. package/dist/recipes/tools/hubspot.js +232 -0
  194. package/dist/recipes/tools/hubspot.js.map +1 -0
  195. package/dist/recipes/tools/index.d.ts +22 -0
  196. package/dist/recipes/tools/index.js +25 -0
  197. package/dist/recipes/tools/index.js.map +1 -0
  198. package/dist/recipes/tools/intercom.d.ts +6 -0
  199. package/dist/recipes/tools/intercom.js +226 -0
  200. package/dist/recipes/tools/intercom.js.map +1 -0
  201. package/dist/recipes/tools/linear.d.ts +6 -0
  202. package/dist/recipes/tools/linear.js +83 -0
  203. package/dist/recipes/tools/linear.js.map +1 -0
  204. package/dist/recipes/tools/notion.d.ts +6 -0
  205. package/dist/recipes/tools/notion.js +278 -0
  206. package/dist/recipes/tools/notion.js.map +1 -0
  207. package/dist/recipes/tools/slack.d.ts +6 -0
  208. package/dist/recipes/tools/slack.js +72 -0
  209. package/dist/recipes/tools/slack.js.map +1 -0
  210. package/dist/recipes/tools/stripe.d.ts +6 -0
  211. package/dist/recipes/tools/stripe.js +265 -0
  212. package/dist/recipes/tools/stripe.js.map +1 -0
  213. package/dist/recipes/tools/zendesk.d.ts +6 -0
  214. package/dist/recipes/tools/zendesk.js +245 -0
  215. package/dist/recipes/tools/zendesk.js.map +1 -0
  216. package/dist/recipes/validation.d.ts +13 -0
  217. package/dist/recipes/validation.js +433 -0
  218. package/dist/recipes/validation.js.map +1 -0
  219. package/dist/recipes/yamlRunner.d.ts +87 -0
  220. package/dist/recipes/yamlRunner.js +693 -409
  221. package/dist/recipes/yamlRunner.js.map +1 -1
  222. package/dist/recipesHttp.d.ts +34 -6
  223. package/dist/recipesHttp.js +285 -15
  224. package/dist/recipesHttp.js.map +1 -1
  225. package/dist/riskTier.js +1 -0
  226. package/dist/riskTier.js.map +1 -1
  227. package/dist/runLog.d.ts +23 -0
  228. package/dist/runLog.js +56 -1
  229. package/dist/runLog.js.map +1 -1
  230. package/dist/schemas/dry-run-plan.v1.json +139 -0
  231. package/dist/schemas/recipe.v1.json +684 -0
  232. package/dist/server.d.ts +32 -1
  233. package/dist/server.js +980 -97
  234. package/dist/server.js.map +1 -1
  235. package/dist/streamableHttp.js +2 -0
  236. package/dist/streamableHttp.js.map +1 -1
  237. package/dist/tools/addLinearComment.d.ts +55 -0
  238. package/dist/tools/addLinearComment.js +72 -0
  239. package/dist/tools/addLinearComment.js.map +1 -0
  240. package/dist/tools/bridgeDoctor.js +2 -2
  241. package/dist/tools/bridgeDoctor.js.map +1 -1
  242. package/dist/tools/createLinearIssue.d.ts +84 -0
  243. package/dist/tools/createLinearIssue.js +146 -0
  244. package/dist/tools/createLinearIssue.js.map +1 -0
  245. package/dist/tools/fetchCalendarEvents.d.ts +94 -0
  246. package/dist/tools/fetchCalendarEvents.js +97 -0
  247. package/dist/tools/fetchCalendarEvents.js.map +1 -0
  248. package/dist/tools/fetchGithubIssue.d.ts +80 -0
  249. package/dist/tools/fetchGithubIssue.js +84 -0
  250. package/dist/tools/fetchGithubIssue.js.map +1 -0
  251. package/dist/tools/fetchGithubPR.d.ts +89 -0
  252. package/dist/tools/fetchGithubPR.js +96 -0
  253. package/dist/tools/fetchGithubPR.js.map +1 -0
  254. package/dist/tools/fetchSlackProfile.d.ts +43 -0
  255. package/dist/tools/fetchSlackProfile.js +46 -0
  256. package/dist/tools/fetchSlackProfile.js.map +1 -0
  257. package/dist/tools/getConnectorStatus.d.ts +58 -0
  258. package/dist/tools/getConnectorStatus.js +56 -0
  259. package/dist/tools/getConnectorStatus.js.map +1 -0
  260. package/dist/tools/github/actions.js +4 -2
  261. package/dist/tools/github/actions.js.map +1 -1
  262. package/dist/tools/github/composite.d.ts +339 -0
  263. package/dist/tools/github/composite.js +343 -0
  264. package/dist/tools/github/composite.js.map +1 -0
  265. package/dist/tools/github/index.d.ts +2 -1
  266. package/dist/tools/github/index.js +2 -1
  267. package/dist/tools/github/index.js.map +1 -1
  268. package/dist/tools/github/issues.js +8 -4
  269. package/dist/tools/github/issues.js.map +1 -1
  270. package/dist/tools/github/pr.d.ts +122 -0
  271. package/dist/tools/github/pr.js +195 -5
  272. package/dist/tools/github/pr.js.map +1 -1
  273. package/dist/tools/index.js +32 -1
  274. package/dist/tools/index.js.map +1 -1
  275. package/dist/tools/searchTools.js +1 -1
  276. package/dist/tools/searchTools.js.map +1 -1
  277. package/dist/tools/slackListChannels.d.ts +65 -0
  278. package/dist/tools/slackListChannels.js +70 -0
  279. package/dist/tools/slackListChannels.js.map +1 -0
  280. package/dist/tools/slackPostMessage.d.ts +57 -0
  281. package/dist/tools/slackPostMessage.js +77 -0
  282. package/dist/tools/slackPostMessage.js.map +1 -0
  283. package/dist/tools/testTraceToSource.js +2 -2
  284. package/dist/tools/testTraceToSource.js.map +1 -1
  285. package/dist/tools/updateLinearIssue.d.ts +89 -0
  286. package/dist/tools/updateLinearIssue.js +117 -0
  287. package/dist/tools/updateLinearIssue.js.map +1 -0
  288. package/dist/transport.d.ts +7 -1
  289. package/dist/transport.js +85 -11
  290. package/dist/transport.js.map +1 -1
  291. package/package.json +5 -2
  292. package/scripts/start-all.sh +56 -19
  293. package/templates/automation-policies/recipe-authoring.json +25 -0
  294. package/templates/automation-policy.example.json +6 -0
  295. package/templates/co.patchwork-os.bridge.plist +34 -0
  296. package/templates/recipes/ctx-loop-test.yaml +75 -0
  297. package/templates/recipes/lint-on-save.yaml +1 -2
  298. package/templates/recipes/morning-brief-slack.yaml +57 -0
  299. package/templates/recipes/morning-brief.yaml +14 -6
  300. package/templates/recipes/project-health-check.yaml +50 -0
  301. package/templates/recipes/sentry-to-linear.yaml +77 -0
@@ -1,173 +1,156 @@
1
1
  /**
2
- * Sentry connector.
2
+ * Sentry connector — routes through Sentry's official MCP server.
3
3
  *
4
- * Uses Sentry's REST API with an auth token (no OAuth app required).
5
- * Token stored at ~/.patchwork/tokens/sentry.json (mode 0600).
6
- * Env vars: SENTRY_AUTH_TOKEN, SENTRY_ORG (optional default org slug).
4
+ * Endpoint: https://mcp.sentry.dev/mcp
5
+ * Auth: OAuth 2.1 w/ PKCE; dynamic client registration (RFC 7591).
7
6
  *
8
- * HTTP routes registered in bridge.ts:
9
- * POST /connections/sentry/connect store token + verify
10
- * POST /connections/sentry/test verify stored token works
11
- * DELETE /connections/sentry delete stored token
7
+ * HTTP routes (wired in src/server.ts):
8
+ * GET /connections/sentry/authorize returns { url } for popup
9
+ * GET /connections/sentry/callback — token exchange
10
+ * POST /connections/sentry/test ping MCP server
11
+ * DELETE /connections/sentry — revoke + delete token
12
12
  *
13
13
  * MCP tool: fetchSentryIssue — fetches a Sentry issue/event and returns
14
14
  * the stack trace string, ready to pass into enrichStackTrace.
15
15
  */
16
- import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync, } from "node:fs";
17
- import { homedir } from "node:os";
18
- import path from "node:path";
19
- const SENTRY_API = "https://sentry.io/api/0";
20
- const TOKEN_PATH = path.join(homedir(), ".patchwork", "tokens", "sentry.json");
21
- // ── Token storage ─────────────────────────────────────────────────────────────
22
- export function loadTokens() {
23
- if (!existsSync(TOKEN_PATH))
24
- return null;
25
- try {
26
- return JSON.parse(readFileSync(TOKEN_PATH, "utf-8"));
16
+ import { McpClient } from "./mcpClient.js";
17
+ import { completeAuthorize, getAccessToken, loadTokenFile, revoke, startAuthorize, updateTokenProfile, vendorConfig, } from "./mcpOAuth.js";
18
+ const SENTRY_MCP_ENDPOINT = "https://mcp.sentry.dev/mcp";
19
+ // ── MCP client ───────────────────────────────────────────────────────────────
20
+ let _client = null;
21
+ function client() {
22
+ if (!_client) {
23
+ _client = new McpClient(SENTRY_MCP_ENDPOINT, () => getAccessToken("sentry"));
27
24
  }
28
- catch {
29
- return null;
30
- }
31
- }
32
- function saveTokens(tokens) {
33
- mkdirSync(path.dirname(TOKEN_PATH), { recursive: true, mode: 0o700 });
34
- writeFileSync(TOKEN_PATH, JSON.stringify(tokens, null, 2), { mode: 0o600 });
25
+ return _client;
35
26
  }
36
- function deleteTokens() {
37
- if (existsSync(TOKEN_PATH))
38
- unlinkSync(TOKEN_PATH);
27
+ // ── Back-compat ──────────────────────────────────────────────────────────────
28
+ export function loadTokens() {
29
+ const file = loadTokenFile("sentry");
30
+ if (!file)
31
+ return null;
32
+ return {
33
+ auth_token: file.access_token,
34
+ org: file.profile?.org,
35
+ connected_at: file.connected_at,
36
+ };
39
37
  }
40
38
  export function getStatus() {
41
- const tokens = loadTokens();
39
+ const file = loadTokenFile("sentry");
42
40
  return {
43
41
  id: "sentry",
44
- status: tokens ? "connected" : "disconnected",
45
- lastSync: tokens?.connected_at,
46
- org: tokens?.org,
42
+ status: file ? "connected" : "disconnected",
43
+ lastSync: file?.connected_at,
44
+ org: file?.profile?.org,
47
45
  };
48
46
  }
49
- // ── API helpers ───────────────────────────────────────────────────────────────
50
- async function sentryGet(path, token, signal) {
51
- const res = await fetch(`${SENTRY_API}${path}`, {
52
- headers: { Authorization: `Bearer ${token}` },
53
- signal,
54
- });
55
- if (!res.ok) {
56
- const body = await res.text();
57
- throw new Error(`Sentry API error ${res.status}: ${body.slice(0, 200)}`);
58
- }
59
- return res.json();
60
- }
61
- /** Verify the token and return the authenticated user's identity. */
62
- async function verifyToken(token, signal) {
63
- const data = (await sentryGet("/", token, signal));
64
- return { username: data.user?.username ?? "unknown" };
65
- }
66
- /**
67
- * Fetch the latest event for a Sentry issue and extract the stack trace text.
68
- * issueIdOrUrl accepts:
69
- * - A numeric issue ID: "12345"
70
- * - A Sentry issue URL: "https://sentry.io/organizations/my-org/issues/12345/"
71
- */
72
- export async function fetchIssueStackTrace(issueIdOrUrl, signal) {
73
- const tokens = loadTokens();
74
- if (!tokens)
75
- throw new Error("Sentry not connected. POST /connections/sentry/connect first.");
76
- const issueId = extractIssueId(issueIdOrUrl);
77
- // Org-scoped endpoint required for self-hosted / team orgs.
78
- // Fall back to legacy path if no org stored.
79
- const issuePath = tokens.org
80
- ? `/organizations/${tokens.org}/issues/${issueId}/`
81
- : `/issues/${issueId}/`;
82
- const eventPath = tokens.org
83
- ? `/organizations/${tokens.org}/issues/${issueId}/events/latest/`
84
- : `/issues/${issueId}/events/latest/`;
85
- // Fetch issue metadata first to get the title
86
- const issue = (await sentryGet(issuePath, tokens.auth_token, signal));
87
- const event = (await sentryGet(eventPath, tokens.auth_token, signal));
88
- event.title = event.title ?? issue.title;
89
- const stackTrace = eventToStackTrace(event);
90
- return { stackTrace, title: event.title ?? issueId, issueId };
91
- }
47
+ // ── Issue fetch ──────────────────────────────────────────────────────────────
92
48
  function extractIssueId(issueIdOrUrl) {
93
- // URL form: https://sentry.io/organizations/.../issues/12345/
94
49
  const urlMatch = issueIdOrUrl.match(/\/issues\/(\d+)/);
95
50
  if (urlMatch)
96
51
  return urlMatch[1];
97
- // Plain numeric or alphanumeric ID
98
52
  const trimmed = issueIdOrUrl.trim();
99
53
  if (/^\d+$/.test(trimmed))
100
54
  return trimmed;
101
55
  throw new Error(`Cannot parse Sentry issue ID from: ${issueIdOrUrl}`);
102
56
  }
103
- /**
104
- * Convert a Sentry event JSON into a stack trace string that parseStackTrace
105
- * (used by enrichStackTrace) can parse. Uses Node.js-style format.
106
- */
107
- function eventToStackTrace(event) {
108
- const exceptions = [];
109
- for (const entry of event.entries ?? []) {
110
- if (entry.type === "exception" && Array.isArray(entry.data?.values)) {
111
- exceptions.push(...(entry.data?.values ?? []));
112
- }
57
+ function extractOrgSlug(issueIdOrUrl) {
58
+ const m = issueIdOrUrl.match(/https?:\/\/([^.]+)\.sentry\.io/);
59
+ return m ? m[1] : null;
60
+ }
61
+ function buildSentryIssueUrl(issueId, orgSlug) {
62
+ return `https://${orgSlug}.sentry.io/issues/${issueId}/`;
63
+ }
64
+ export async function fetchIssueStackTrace(issueIdOrUrl, signal) {
65
+ if (!loadTokens())
66
+ throw new Error("Sentry not connected. GET /connections/sentry/authorize first.");
67
+ const issueId = extractIssueId(issueIdOrUrl);
68
+ const orgSlug = extractOrgSlug(issueIdOrUrl) ?? loadTokenFile("sentry")?.profile?.org;
69
+ if (!orgSlug)
70
+ throw new Error("Cannot determine Sentry org slug. Pass full sentry.io issue URL.");
71
+ const issueUrl = buildSentryIssueUrl(issueId, orgSlug);
72
+ const res = await client().callTool("get_sentry_resource", { url: issueUrl }, { signal });
73
+ // get_sentry_resource returns markdown text — extract title and stacktrace
74
+ const text = res.content?.[0]?.text ?? "";
75
+ const titleMatch = text.match(/\*\*Description\*\*:\s*(.+)/);
76
+ const title = titleMatch
77
+ ? titleMatch[1].trim()
78
+ : `Sentry issue ${issueId}`;
79
+ // Extract stacktrace block
80
+ const stMatch = text.match(/```(?:\w+)?\n([\s\S]*?)\n```/);
81
+ if (!stMatch) {
82
+ throw new Error(`Sentry returned no stack trace for issue ${issueId}`);
113
83
  }
114
- if (exceptions.length === 0) {
115
- return `Error: ${event.title ?? "Unknown error"}\n (no stack frames in Sentry event)`;
84
+ const stackTrace = stMatch[1].trim();
85
+ return { stackTrace, title, issueId };
86
+ }
87
+ // ── HTTP handlers ────────────────────────────────────────────────────────────
88
+ export async function handleSentryAuthorize() {
89
+ try {
90
+ const { url } = await startAuthorize(vendorConfig("sentry"));
91
+ return { status: 302, body: "", redirect: url };
116
92
  }
117
- const lines = [];
118
- for (const exc of exceptions.reverse()) {
119
- lines.push(`${exc.type ?? "Error"}: ${exc.value ?? ""}`);
120
- const frames = exc.stacktrace?.frames ?? [];
121
- // Sentry stores frames innermost-last; reverse for top-of-stack-first output
122
- for (const frame of [...frames].reverse()) {
123
- const file = frame.absPath ?? frame.filename ?? frame.module ?? "<unknown>";
124
- const line = frame.lineNo ?? 0;
125
- const col = frame.colNo !== undefined ? `:${frame.colNo}` : "";
126
- const fn = frame.function ? ` (${frame.function})` : "";
127
- lines.push(` at ${fn.trim() || "<anonymous>"} (${file}:${line}${col})`);
128
- }
93
+ catch (err) {
94
+ return {
95
+ status: 400,
96
+ contentType: "application/json",
97
+ body: JSON.stringify({
98
+ ok: false,
99
+ error: err instanceof Error ? err.message : String(err),
100
+ }),
101
+ };
129
102
  }
130
- return lines.join("\n");
131
103
  }
132
- export async function handleSentryConnect(body) {
133
- const signal = undefined;
134
- const { auth_token, org } = (body ?? {});
135
- if (!auth_token || typeof auth_token !== "string") {
104
+ export async function handleSentryCallback(code, state, error) {
105
+ if (error) {
136
106
  return {
137
107
  status: 400,
138
- contentType: "application/json",
139
- body: JSON.stringify({ ok: false, error: "auth_token required" }),
108
+ contentType: "text/html",
109
+ body: `<html><body><h2>Sentry connect failed</h2><pre>${error}</pre></body></html>`,
140
110
  };
141
111
  }
142
- try {
143
- const { username } = await verifyToken(auth_token, signal);
144
- const tokens = {
145
- auth_token,
146
- org: org ?? undefined,
147
- connected_at: new Date().toISOString(),
112
+ if (!code || !state) {
113
+ return {
114
+ status: 400,
115
+ contentType: "text/html",
116
+ body: `<html><body><h2>Sentry connect failed</h2><pre>missing code/state</pre></body></html>`,
148
117
  };
149
- saveTokens(tokens);
118
+ }
119
+ try {
120
+ await completeAuthorize(vendorConfig("sentry"), code, state);
121
+ // Best-effort org capture
122
+ try {
123
+ const res = await client().callTool("find_organizations", {}, {
124
+ timeoutMs: 10_000,
125
+ });
126
+ const orgs = McpClient.extractJson(res);
127
+ const first = Array.isArray(orgs)
128
+ ? orgs[0]
129
+ : (orgs.organizations ?? [])[0];
130
+ const org = first?.slug;
131
+ if (org) {
132
+ updateTokenProfile("sentry", { org });
133
+ }
134
+ }
135
+ catch {
136
+ // Profile fetch is best-effort
137
+ }
150
138
  return {
151
139
  status: 200,
152
- contentType: "application/json",
153
- body: JSON.stringify({ ok: true, username, org: org ?? null }),
140
+ contentType: "text/html",
141
+ body: `<html><body><h2>Sentry connected</h2><script>window.close();</script></body></html>`,
154
142
  };
155
143
  }
156
144
  catch (err) {
157
145
  return {
158
146
  status: 400,
159
- contentType: "application/json",
160
- body: JSON.stringify({
161
- ok: false,
162
- error: err instanceof Error ? err.message : String(err),
163
- }),
147
+ contentType: "text/html",
148
+ body: `<html><body><h2>Sentry connect failed</h2><pre>${err instanceof Error ? err.message : String(err)}</pre></body></html>`,
164
149
  };
165
150
  }
166
151
  }
167
152
  export async function handleSentryTest() {
168
- const signal = undefined;
169
- const tokens = loadTokens();
170
- if (!tokens) {
153
+ if (!loadTokens()) {
171
154
  return {
172
155
  status: 400,
173
156
  contentType: "application/json",
@@ -175,11 +158,11 @@ export async function handleSentryTest() {
175
158
  };
176
159
  }
177
160
  try {
178
- const { username } = await verifyToken(tokens.auth_token, signal);
161
+ const ok = await client().ping({ timeoutMs: 10_000 });
179
162
  return {
180
- status: 200,
163
+ status: ok ? 200 : 400,
181
164
  contentType: "application/json",
182
- body: JSON.stringify({ ok: true, username }),
165
+ body: JSON.stringify({ ok, message: ok ? "connected" : "ping failed" }),
183
166
  };
184
167
  }
185
168
  catch (err) {
@@ -193,8 +176,9 @@ export async function handleSentryTest() {
193
176
  };
194
177
  }
195
178
  }
196
- export function handleSentryDisconnect() {
197
- deleteTokens();
179
+ export async function handleSentryDisconnect() {
180
+ await revoke("sentry");
181
+ _client = null;
198
182
  return {
199
183
  status: 200,
200
184
  contentType: "application/json",
@@ -1 +1 @@
1
- {"version":3,"file":"sentry.js","sourceRoot":"","sources":["../../src/connectors/sentry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sentry.js","sourceRoot":"","sources":["../../src/connectors/sentry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Slack connector — calls Slack Web API directly with bot token.
3
+ *
4
+ * OAuth 2.0 (not PKCE) — Slack uses its own flow with bot token in response.
5
+ * Tokens stored at ~/.patchwork/tokens/slack.json (mode 0600).
6
+ * Client credentials: PATCHWORK_SLACK_CLIENT_ID / PATCHWORK_SLACK_CLIENT_SECRET
7
+ *
8
+ * HTTP routes (wired in src/server.ts):
9
+ * GET /connections/slack/authorize — redirect to Slack consent
10
+ * GET /connections/slack/callback — exchange code for bot token
11
+ * POST /connections/slack/test — ping Slack API
12
+ * DELETE /connections/slack — delete stored token
13
+ */
14
+ export interface SlackTokenFile {
15
+ access_token: string;
16
+ team_id: string;
17
+ team_name: string;
18
+ bot_user_id: string;
19
+ connected_at: string;
20
+ }
21
+ export interface ConnectorHandlerResult {
22
+ status: number;
23
+ body: string;
24
+ contentType?: string;
25
+ redirect?: string;
26
+ }
27
+ export declare function loadTokens(): SlackTokenFile | null;
28
+ export declare function isConnected(): boolean;
29
+ export declare function postMessage(channel: string, text: string, threadTs?: string, signal?: AbortSignal): Promise<{
30
+ ts: string;
31
+ channel: string;
32
+ }>;
33
+ export interface SlackChannel {
34
+ id: string;
35
+ name: string;
36
+ isMember: boolean;
37
+ isPrivate: boolean;
38
+ numMembers?: number;
39
+ }
40
+ export declare function listChannels(limit?: number, signal?: AbortSignal): Promise<SlackChannel[]>;
41
+ export interface SlackProfile {
42
+ teamId: string;
43
+ teamName: string;
44
+ botUserId: string;
45
+ }
46
+ export declare function getProfile(): SlackProfile | null;
47
+ export declare function handleSlackAuthorize(): ConnectorHandlerResult;
48
+ export declare function handleSlackCallback(code: string | null, state: string | null, error: string | null): Promise<ConnectorHandlerResult>;
49
+ export declare function handleSlackTest(): Promise<ConnectorHandlerResult>;
50
+ export declare function handleSlackDisconnect(): ConnectorHandlerResult;