patchwork-os 0.2.0-alpha.3 → 0.2.0-alpha.4
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.
- package/dist/bridge.js +23 -10
- package/dist/bridge.js.map +1 -1
- package/dist/connectors/github.d.ts +58 -8
- package/dist/connectors/github.js +321 -84
- package/dist/connectors/github.js.map +1 -1
- package/dist/connectors/gmail.js +7 -0
- package/dist/connectors/gmail.js.map +1 -1
- package/dist/connectors/googleCalendar.d.ts +57 -0
- package/dist/connectors/googleCalendar.js +308 -0
- package/dist/connectors/googleCalendar.js.map +1 -0
- package/dist/connectors/linear.d.ts +52 -19
- package/dist/connectors/linear.js +167 -129
- package/dist/connectors/linear.js.map +1 -1
- package/dist/connectors/mcpClient.d.ts +56 -0
- package/dist/connectors/mcpClient.js +189 -0
- package/dist/connectors/mcpClient.js.map +1 -0
- package/dist/connectors/mcpOAuth.d.ts +73 -0
- package/dist/connectors/mcpOAuth.js +338 -0
- package/dist/connectors/mcpOAuth.js.map +1 -0
- package/dist/connectors/sentry.d.ts +17 -21
- package/dist/connectors/sentry.js +124 -131
- package/dist/connectors/sentry.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/recipes/yamlRunner.js +32 -42
- package/dist/recipes/yamlRunner.js.map +1 -1
- package/dist/recipesHttp.d.ts +13 -1
- package/dist/recipesHttp.js +9 -1
- package/dist/recipesHttp.js.map +1 -1
- package/dist/server.d.ts +3 -1
- package/dist/server.js +220 -49
- package/dist/server.js.map +1 -1
- package/dist/tools/createLinearIssue.d.ts +84 -0
- package/dist/tools/createLinearIssue.js +146 -0
- package/dist/tools/createLinearIssue.js.map +1 -0
- package/dist/tools/fetchCalendarEvents.d.ts +94 -0
- package/dist/tools/fetchCalendarEvents.js +97 -0
- package/dist/tools/fetchCalendarEvents.js.map +1 -0
- package/dist/tools/fetchGithubIssue.d.ts +80 -0
- package/dist/tools/fetchGithubIssue.js +84 -0
- package/dist/tools/fetchGithubIssue.js.map +1 -0
- package/dist/tools/fetchGithubPR.d.ts +89 -0
- package/dist/tools/fetchGithubPR.js +96 -0
- package/dist/tools/fetchGithubPR.js.map +1 -0
- package/dist/tools/index.js +8 -0
- package/dist/tools/index.js.map +1 -1
- package/package.json +1 -1
- package/scripts/start-all.sh +56 -19
- package/templates/recipes/ctx-loop-test.yaml +75 -0
- package/templates/recipes/morning-brief.yaml +12 -4
- package/templates/recipes/sentry-to-linear.yaml +77 -0
|
@@ -1,173 +1,165 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Sentry connector.
|
|
2
|
+
* Sentry connector — routes through Sentry's official MCP server.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
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
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
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 {
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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, 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
|
-
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
|
39
|
+
const file = loadTokenFile("sentry");
|
|
42
40
|
return {
|
|
43
41
|
id: "sentry",
|
|
44
|
-
status:
|
|
45
|
-
lastSync:
|
|
46
|
-
org:
|
|
42
|
+
status: file ? "connected" : "disconnected",
|
|
43
|
+
lastSync: file?.connected_at,
|
|
44
|
+
org: file?.profile?.org,
|
|
47
45
|
};
|
|
48
46
|
}
|
|
49
|
-
// ──
|
|
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
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
function
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
|
|
115
|
-
|
|
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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
|
133
|
-
|
|
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: "
|
|
139
|
-
body:
|
|
108
|
+
contentType: "text/html",
|
|
109
|
+
body: `<html><body><h2>Sentry connect failed</h2><pre>${error}</pre></body></html>`,
|
|
140
110
|
};
|
|
141
111
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
-
|
|
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
|
+
const file = loadTokenFile("sentry");
|
|
133
|
+
if (file) {
|
|
134
|
+
const { writeFileSync, mkdirSync } = await import("node:fs");
|
|
135
|
+
const { homedir } = await import("node:os");
|
|
136
|
+
const path = await import("node:path");
|
|
137
|
+
const p = path.join(homedir(), ".patchwork", "tokens", "sentry-mcp.json");
|
|
138
|
+
mkdirSync(path.dirname(p), { recursive: true, mode: 0o700 });
|
|
139
|
+
file.profile = { ...(file.profile ?? {}), org };
|
|
140
|
+
writeFileSync(p, JSON.stringify(file, null, 2), { mode: 0o600 });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// Profile fetch is best-effort
|
|
146
|
+
}
|
|
150
147
|
return {
|
|
151
148
|
status: 200,
|
|
152
|
-
contentType: "
|
|
153
|
-
body:
|
|
149
|
+
contentType: "text/html",
|
|
150
|
+
body: `<html><body><h2>Sentry connected</h2><script>window.close();</script></body></html>`,
|
|
154
151
|
};
|
|
155
152
|
}
|
|
156
153
|
catch (err) {
|
|
157
154
|
return {
|
|
158
155
|
status: 400,
|
|
159
|
-
contentType: "
|
|
160
|
-
body:
|
|
161
|
-
ok: false,
|
|
162
|
-
error: err instanceof Error ? err.message : String(err),
|
|
163
|
-
}),
|
|
156
|
+
contentType: "text/html",
|
|
157
|
+
body: `<html><body><h2>Sentry connect failed</h2><pre>${err instanceof Error ? err.message : String(err)}</pre></body></html>`,
|
|
164
158
|
};
|
|
165
159
|
}
|
|
166
160
|
}
|
|
167
161
|
export async function handleSentryTest() {
|
|
168
|
-
|
|
169
|
-
const tokens = loadTokens();
|
|
170
|
-
if (!tokens) {
|
|
162
|
+
if (!loadTokens()) {
|
|
171
163
|
return {
|
|
172
164
|
status: 400,
|
|
173
165
|
contentType: "application/json",
|
|
@@ -175,11 +167,11 @@ export async function handleSentryTest() {
|
|
|
175
167
|
};
|
|
176
168
|
}
|
|
177
169
|
try {
|
|
178
|
-
const
|
|
170
|
+
const ok = await client().ping({ timeoutMs: 10_000 });
|
|
179
171
|
return {
|
|
180
|
-
status: 200,
|
|
172
|
+
status: ok ? 200 : 400,
|
|
181
173
|
contentType: "application/json",
|
|
182
|
-
body: JSON.stringify({ ok:
|
|
174
|
+
body: JSON.stringify({ ok, message: ok ? "connected" : "ping failed" }),
|
|
183
175
|
};
|
|
184
176
|
}
|
|
185
177
|
catch (err) {
|
|
@@ -193,8 +185,9 @@ export async function handleSentryTest() {
|
|
|
193
185
|
};
|
|
194
186
|
}
|
|
195
187
|
}
|
|
196
|
-
export function handleSentryDisconnect() {
|
|
197
|
-
|
|
188
|
+
export async function handleSentryDisconnect() {
|
|
189
|
+
await revoke("sentry");
|
|
190
|
+
_client = null;
|
|
198
191
|
return {
|
|
199
192
|
status: 200,
|
|
200
193
|
contentType: "application/json",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sentry.js","sourceRoot":"","sources":["../../src/connectors/sentry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"sentry.js","sourceRoot":"","sources":["../../src/connectors/sentry.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Uses Node 20.6+ native dotenv loader; falls back to manual parse for older Node.
|
|
4
4
|
{
|
|
5
5
|
const { fileURLToPath: _fileURLToPath } = await import("node:url");
|
|
6
|
-
const envPath = _fileURLToPath(new URL("
|
|
6
|
+
const envPath = _fileURLToPath(new URL("../.env", import.meta.url));
|
|
7
7
|
try {
|
|
8
8
|
const { readFileSync, existsSync } = await import("node:fs");
|
|
9
9
|
if (existsSync(envPath)) {
|