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
@@ -0,0 +1,379 @@
1
+ /**
2
+ * Jira connector — read/write Jira issues via Atlassian REST API v3.
3
+ *
4
+ * Auth: OAuth 2.0 (cloud) or API token + email (server/data center)
5
+ * Tools: fetchIssue, searchIssues, listProjects, createIssue, updateStatus, addComment
6
+ *
7
+ * Extends BaseConnector for unified auth, retry, error handling.
8
+ */
9
+ import { existsSync, readFileSync, unlinkSync } from "node:fs";
10
+ import { homedir } from "node:os";
11
+ import path from "node:path";
12
+ import { BaseConnector, } from "./baseConnector.js";
13
+ import { getSecretJsonSync, storeSecretJsonSync } from "./tokenStorage.js";
14
+ const JIRA_CLOUD_API = "/rest/api/3";
15
+ const JIRA_SERVER_API = "/rest/api/2";
16
+ export class JiraConnector extends BaseConnector {
17
+ providerName = "jira";
18
+ tokens = null;
19
+ getOAuthConfig() {
20
+ return null;
21
+ }
22
+ async authenticate() {
23
+ // Try loading from file first
24
+ const tokens = loadTokens();
25
+ if (!tokens) {
26
+ throw new Error("Jira not connected. Run: patchwork-os connect jira or set JIRA_API_TOKEN");
27
+ }
28
+ this.tokens = tokens;
29
+ return {
30
+ token: tokens.accessToken,
31
+ scopes: ["read:jira-work", "write:jira-work"],
32
+ };
33
+ }
34
+ async healthCheck() {
35
+ try {
36
+ // Lightweight check: get my permissions
37
+ const result = await this.apiCall(async (token) => {
38
+ const api = this.getApiPath();
39
+ const url = `${this.tokens?.instanceUrl}${api}/mypermissions`;
40
+ const res = await fetch(url, {
41
+ headers: this.buildHeaders(token),
42
+ });
43
+ if (!res.ok)
44
+ throw new Error(`HTTP ${res.status}`);
45
+ return res.json();
46
+ });
47
+ if ("error" in result) {
48
+ return { ok: false, error: result.error };
49
+ }
50
+ return { ok: true };
51
+ }
52
+ catch (err) {
53
+ return {
54
+ ok: false,
55
+ error: this.normalizeError(err),
56
+ };
57
+ }
58
+ }
59
+ normalizeError(error) {
60
+ if (error instanceof Response) {
61
+ const status = error.status;
62
+ if (status === 401) {
63
+ return {
64
+ code: "auth_expired",
65
+ message: "Jira authentication expired or invalid",
66
+ retryable: false,
67
+ suggestedAction: "Reconnect Jira: patchwork-os connect jira",
68
+ };
69
+ }
70
+ if (status === 403) {
71
+ return {
72
+ code: "permission_denied",
73
+ message: "Insufficient permissions for this Jira operation",
74
+ retryable: false,
75
+ suggestedAction: "Check project permissions in Jira",
76
+ };
77
+ }
78
+ if (status === 404) {
79
+ return {
80
+ code: "not_found",
81
+ message: "Jira issue or project not found",
82
+ retryable: false,
83
+ };
84
+ }
85
+ if (status === 429) {
86
+ return {
87
+ code: "rate_limited",
88
+ message: "Jira API rate limit exceeded",
89
+ retryable: true,
90
+ suggestedAction: "Wait and retry",
91
+ };
92
+ }
93
+ return {
94
+ code: "provider_error",
95
+ message: `Jira API error: HTTP ${status}`,
96
+ retryable: status >= 500,
97
+ };
98
+ }
99
+ if (error instanceof Error) {
100
+ if (error.message.includes("ENOTFOUND") ||
101
+ error.message.includes("ECONNREFUSED")) {
102
+ return {
103
+ code: "network_error",
104
+ message: `Cannot connect to Jira: ${error.message}`,
105
+ retryable: true,
106
+ };
107
+ }
108
+ }
109
+ return {
110
+ code: "provider_error",
111
+ message: error instanceof Error ? error.message : String(error),
112
+ retryable: false,
113
+ };
114
+ }
115
+ getStatus() {
116
+ const tokens = loadTokens();
117
+ return {
118
+ id: "jira",
119
+ status: tokens ? "connected" : "disconnected",
120
+ lastSync: tokens?.connected_at,
121
+ workspace: tokens?.instanceUrl,
122
+ };
123
+ }
124
+ // ── API Methods ────────────────────────────────────────────────────────────
125
+ async fetchIssue(issueIdOrKey) {
126
+ const result = await this.apiCall(async (token) => {
127
+ const api = this.getApiPath();
128
+ const url = `${this.tokens?.instanceUrl}${api}/issue/${issueIdOrKey}`;
129
+ const res = await fetch(url, {
130
+ headers: this.buildHeaders(token),
131
+ });
132
+ this.updateRateLimitFromHeaders({
133
+ "x-ratelimit-remaining": res.headers.get("x-ratelimit-remaining") ?? undefined,
134
+ "retry-after": res.headers.get("retry-after") ?? undefined,
135
+ });
136
+ if (res.status === 404)
137
+ return null;
138
+ if (!res.ok)
139
+ throw res;
140
+ return res.json();
141
+ });
142
+ if ("error" in result) {
143
+ throw new Error(result.error.message);
144
+ }
145
+ return result.data;
146
+ }
147
+ async searchIssues(jql, maxResults = 50) {
148
+ const result = await this.apiCall(async (token) => {
149
+ const api = this.getApiPath();
150
+ const params = new URLSearchParams({
151
+ jql,
152
+ maxResults: String(maxResults),
153
+ fields: "summary,status,issuetype,priority,assignee,reporter,created,updated,labels",
154
+ });
155
+ const url = `${this.tokens?.instanceUrl}${api}/search?${params}`;
156
+ const res = await fetch(url, {
157
+ headers: this.buildHeaders(token),
158
+ });
159
+ if (!res.ok)
160
+ throw res;
161
+ return res.json();
162
+ });
163
+ if ("error" in result) {
164
+ throw new Error(result.error.message);
165
+ }
166
+ return result.data;
167
+ }
168
+ async listProjects() {
169
+ const result = await this.apiCall(async (token) => {
170
+ const api = this.getApiPath();
171
+ const url = `${this.tokens?.instanceUrl}${api}/project`;
172
+ const res = await fetch(url, {
173
+ headers: this.buildHeaders(token),
174
+ });
175
+ if (!res.ok)
176
+ throw res;
177
+ return res.json();
178
+ });
179
+ if ("error" in result) {
180
+ throw new Error(result.error.message);
181
+ }
182
+ return result.data;
183
+ }
184
+ async createIssue(params) {
185
+ const result = await this.apiCall(async (token) => {
186
+ const api = this.getApiPath();
187
+ const url = `${this.tokens?.instanceUrl}${api}/issue`;
188
+ const body = {
189
+ fields: {
190
+ project: { key: params.projectKey },
191
+ summary: params.summary,
192
+ issuetype: { name: params.issueType ?? "Bug" },
193
+ },
194
+ };
195
+ if (params.description) {
196
+ // Atlassian Document Format (ADF) for cloud, plain text for server
197
+ if (this.tokens?.isCloud) {
198
+ body.fields.description = {
199
+ type: "doc",
200
+ version: 1,
201
+ content: [
202
+ {
203
+ type: "paragraph",
204
+ content: [{ type: "text", text: params.description }],
205
+ },
206
+ ],
207
+ };
208
+ }
209
+ else {
210
+ body.fields.description =
211
+ params.description;
212
+ }
213
+ }
214
+ if (params.priority) {
215
+ body.fields.priority = {
216
+ name: params.priority,
217
+ };
218
+ }
219
+ if (params.labels) {
220
+ body.fields.labels = params.labels;
221
+ }
222
+ if (params.assignee) {
223
+ if (this.tokens?.isCloud) {
224
+ body.fields.assignee = {
225
+ accountId: params.assignee,
226
+ };
227
+ }
228
+ else {
229
+ body.fields.assignee = {
230
+ name: params.assignee,
231
+ };
232
+ }
233
+ }
234
+ const res = await fetch(url, {
235
+ method: "POST",
236
+ headers: {
237
+ ...this.buildHeaders(token),
238
+ "Content-Type": "application/json",
239
+ },
240
+ body: JSON.stringify(body),
241
+ });
242
+ if (!res.ok)
243
+ throw res;
244
+ return res.json();
245
+ });
246
+ if ("error" in result) {
247
+ throw new Error(result.error.message);
248
+ }
249
+ return result.data;
250
+ }
251
+ async updateStatus(issueIdOrKey, transitionId) {
252
+ const result = await this.apiCall(async (token) => {
253
+ const api = this.getApiPath();
254
+ const url = `${this.tokens?.instanceUrl}${api}/issue/${issueIdOrKey}/transitions`;
255
+ const res = await fetch(url, {
256
+ method: "POST",
257
+ headers: {
258
+ ...this.buildHeaders(token),
259
+ "Content-Type": "application/json",
260
+ },
261
+ body: JSON.stringify({ transition: { id: transitionId } }),
262
+ });
263
+ if (!res.ok)
264
+ throw res;
265
+ return { ok: true };
266
+ });
267
+ if ("error" in result) {
268
+ throw new Error(result.error.message);
269
+ }
270
+ }
271
+ async addComment(issueIdOrKey, body) {
272
+ const result = await this.apiCall(async (token) => {
273
+ const api = this.getApiPath();
274
+ const url = `${this.tokens?.instanceUrl}${api}/issue/${issueIdOrKey}/comment`;
275
+ let commentBody;
276
+ if (this.tokens?.isCloud) {
277
+ commentBody = {
278
+ type: "doc",
279
+ version: 1,
280
+ content: [
281
+ { type: "paragraph", content: [{ type: "text", text: body }] },
282
+ ],
283
+ };
284
+ }
285
+ else {
286
+ commentBody = body;
287
+ }
288
+ const res = await fetch(url, {
289
+ method: "POST",
290
+ headers: {
291
+ ...this.buildHeaders(token),
292
+ "Content-Type": "application/json",
293
+ },
294
+ body: JSON.stringify({ body: commentBody }),
295
+ });
296
+ if (!res.ok)
297
+ throw res;
298
+ return { ok: true };
299
+ });
300
+ if ("error" in result) {
301
+ throw new Error(result.error.message);
302
+ }
303
+ }
304
+ // ── Helpers ────────────────────────────────────────────────────────────────
305
+ getApiPath() {
306
+ return this.tokens?.isCloud ? JIRA_CLOUD_API : JIRA_SERVER_API;
307
+ }
308
+ buildHeaders(token) {
309
+ if (this.tokens?.isCloud) {
310
+ return {
311
+ Authorization: `Bearer ${token}`,
312
+ Accept: "application/json",
313
+ };
314
+ }
315
+ else {
316
+ // Server/Data Center uses Basic auth with email:token
317
+ const email = this.tokens?.email ?? "api";
318
+ const basic = Buffer.from(`${email}:${token}`).toString("base64");
319
+ return {
320
+ Authorization: `Basic ${basic}`,
321
+ Accept: "application/json",
322
+ };
323
+ }
324
+ }
325
+ }
326
+ // ── Token persistence ────────────────────────────────────────────────────────
327
+ function getLegacyTokenPath() {
328
+ const patchworkHome = process.env.PATCHWORK_HOME ?? path.join(homedir(), ".patchwork");
329
+ return path.join(patchworkHome, "tokens", "jira.json");
330
+ }
331
+ export function loadTokens() {
332
+ // Environment variable override
333
+ const envToken = process.env.JIRA_API_TOKEN;
334
+ const envUrl = process.env.JIRA_INSTANCE_URL;
335
+ if (envToken && envUrl) {
336
+ return {
337
+ accessToken: envToken,
338
+ instanceUrl: envUrl.replace(/\/$/, ""), // strip trailing slash
339
+ isCloud: envUrl.includes("atlassian.net"),
340
+ connected_at: new Date().toISOString(),
341
+ email: process.env.JIRA_EMAIL,
342
+ };
343
+ }
344
+ const secure = getSecretJsonSync("jira");
345
+ if (secure) {
346
+ return secure;
347
+ }
348
+ const legacyTokenPath = getLegacyTokenPath();
349
+ if (!existsSync(legacyTokenPath))
350
+ return null;
351
+ try {
352
+ const data = JSON.parse(readFileSync(legacyTokenPath, "utf-8"));
353
+ saveTokens(data);
354
+ return data;
355
+ }
356
+ catch {
357
+ return null;
358
+ }
359
+ }
360
+ export function saveTokens(tokens) {
361
+ storeSecretJsonSync("jira", tokens);
362
+ const legacyTokenPath = getLegacyTokenPath();
363
+ if (existsSync(legacyTokenPath)) {
364
+ try {
365
+ unlinkSync(legacyTokenPath);
366
+ }
367
+ catch { }
368
+ }
369
+ }
370
+ // ── Singleton instance ───────────────────────────────────────────────────────
371
+ let _instance = null;
372
+ export function getJiraConnector() {
373
+ if (!_instance) {
374
+ _instance = new JiraConnector();
375
+ }
376
+ return _instance;
377
+ }
378
+ export { getJiraConnector as jira };
379
+ //# sourceMappingURL=jira.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jira.js","sourceRoot":"","sources":["../../src/connectors/jira.ts"],"names":[],"mappings":"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"}
@@ -1,14 +1,17 @@
1
1
  /**
2
- * Linear connector.
2
+ * Linear connector — routes through Linear's official MCP server.
3
3
  *
4
- * Uses Linear's GraphQL API with a personal API key (no OAuth app required).
5
- * Token stored at ~/.patchwork/tokens/linear.json (mode 0600).
6
- * Env var: LINEAR_API_KEY
4
+ * Endpoint: https://mcp.linear.app/mcp
5
+ * Auth: OAuth 2.1 w/ PKCE; dynamic client registration (RFC 7591).
7
6
  *
8
- * HTTP routes registered in server.ts:
9
- * POST /connections/linear/connect store token + verify
10
- * POST /connections/linear/test verify stored token works
11
- * DELETE /connections/linear delete stored token
7
+ * HTTP routes (wired in src/server.ts):
8
+ * GET /connections/linear/authorize returns { url } for popup
9
+ * GET /connections/linear/callback — token exchange
10
+ * POST /connections/linear/test ping MCP server
11
+ * DELETE /connections/linear — revoke + delete token
12
+ *
13
+ * Back-compat: loadTokens() returns a shape compatible with legacy code
14
+ * that expected { api_key }. Set LINEAR_API_KEY to bypass OAuth for CI/headless.
12
15
  */
13
16
  export interface LinearTokens {
14
17
  api_key: string;
@@ -21,9 +24,14 @@ export interface ConnectorStatus {
21
24
  lastSync?: string;
22
25
  workspace?: string;
23
26
  }
27
+ export interface ConnectorHandlerResult {
28
+ status: number;
29
+ body: string;
30
+ contentType?: string;
31
+ redirect?: string;
32
+ }
24
33
  export declare function loadTokens(): LinearTokens | null;
25
34
  export declare function getStatus(): ConnectorStatus;
26
- export declare function linearQuery<T>(query: string, variables: Record<string, unknown>, apiKey: string, signal?: AbortSignal): Promise<T>;
27
35
  export interface LinearIssue {
28
36
  id: string;
29
37
  identifier: string;
@@ -52,16 +60,58 @@ export interface LinearIssue {
52
60
  }>;
53
61
  };
54
62
  }
55
- /**
56
- * Fetch a Linear issue by ID or URL.
57
- * Accepts: "LIN-123", "abc123def456...", "https://linear.app/.../issue/LIN-123/..."
58
- */
59
63
  export declare function fetchIssue(issueIdOrUrl: string, signal?: AbortSignal): Promise<LinearIssue>;
60
- export interface ConnectorHandlerResult {
61
- status: number;
62
- body: string;
63
- contentType?: string;
64
+ export interface ListLinearIssuesOpts {
65
+ team?: string;
66
+ assigneeMe?: boolean;
67
+ states?: string[];
68
+ limit?: number;
64
69
  }
65
- export declare function handleLinearConnect(body: unknown): Promise<ConnectorHandlerResult>;
70
+ export declare function listIssues(opts?: ListLinearIssuesOpts, signal?: AbortSignal): Promise<Record<string, unknown>[]>;
71
+ export declare function handleLinearAuthorize(): Promise<ConnectorHandlerResult>;
72
+ export declare function handleLinearCallback(code: string | null, state: string | null, error: string | null): Promise<ConnectorHandlerResult>;
66
73
  export declare function handleLinearTest(): Promise<ConnectorHandlerResult>;
67
- export declare function handleLinearDisconnect(): ConnectorHandlerResult;
74
+ export declare function handleLinearDisconnect(): Promise<ConnectorHandlerResult>;
75
+ export interface LinearTeam {
76
+ id: string;
77
+ key: string;
78
+ name: string;
79
+ }
80
+ export declare function listTeams(signal?: AbortSignal): Promise<LinearTeam[]>;
81
+ export declare function listLabels(signal?: AbortSignal): Promise<Array<{
82
+ id: string;
83
+ name: string;
84
+ }>>;
85
+ export interface CreateIssueInput {
86
+ team: string;
87
+ title: string;
88
+ description?: string;
89
+ priority?: number;
90
+ labels?: string[];
91
+ }
92
+ export interface UpdateIssueInput {
93
+ id: string;
94
+ title?: string;
95
+ description?: string;
96
+ priority?: number;
97
+ state?: string;
98
+ assignee?: string;
99
+ labels?: string[];
100
+ }
101
+ type SaveIssueResult = {
102
+ id: string;
103
+ identifier: string;
104
+ title: string;
105
+ url: string;
106
+ state?: {
107
+ name: string;
108
+ };
109
+ };
110
+ export declare function createIssue(input: CreateIssueInput, signal?: AbortSignal): Promise<SaveIssueResult>;
111
+ export declare function updateIssue(input: UpdateIssueInput, signal?: AbortSignal): Promise<SaveIssueResult>;
112
+ export declare function addComment(issueId: string, body: string, signal?: AbortSignal): Promise<{
113
+ id: string;
114
+ body: string;
115
+ url?: string;
116
+ }>;
117
+ export {};