patchwork-os 0.2.0-beta.10.canary.97 → 0.2.0-beta.10.canary.99
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/commands/connect.d.ts +47 -0
- package/dist/commands/connect.js +419 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/recipe.d.ts +45 -4
- package/dist/commands/recipe.js +141 -4
- package/dist/commands/recipe.js.map +1 -1
- package/dist/index.js +60 -1
- package/dist/index.js.map +1 -1
- package/dist/telemetry.js +20 -9
- package/dist/telemetry.js.map +1 -1
- package/dist/tools/searchTools.d.ts +26 -0
- package/dist/tools/searchTools.js +42 -2
- package/dist/tools/searchTools.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `patchwork connect` — the connector front-door.
|
|
3
|
+
*
|
|
4
|
+
* A thin CLI→HTTP shim over the bridge's already-built `/connections/*`
|
|
5
|
+
* routes (see src/connectorRoutes.ts). 23 connector error messages already
|
|
6
|
+
* tell users to "Run: patchwork connect <vendor>"; this is that command.
|
|
7
|
+
*
|
|
8
|
+
* NO new bridge or connector logic lives here — every verb maps to one
|
|
9
|
+
* existing HTTP route:
|
|
10
|
+
* - list → GET /connections (Bearer)
|
|
11
|
+
* - <vendor> → GET /connections/<id>/auth (OAuth, 302 Location)
|
|
12
|
+
* or POST /connections/<id>/connect (PAT, {token})
|
|
13
|
+
* - test → POST /connections/<id>/test (health probe)
|
|
14
|
+
* - disconnect → DELETE /connections/<id> (revoke)
|
|
15
|
+
*
|
|
16
|
+
* Bridge discovery + Bearer auth mirror src/commands/task.ts. All side
|
|
17
|
+
* effects (lock discovery, fetch, stdout/stderr, exit) are injectable so
|
|
18
|
+
* the command is unit-testable without a live bridge.
|
|
19
|
+
*/
|
|
20
|
+
import { type ConnectorDescriptor } from "../connectors/connectorRegistry.js";
|
|
21
|
+
interface LockInfo {
|
|
22
|
+
port: number;
|
|
23
|
+
authToken: string;
|
|
24
|
+
}
|
|
25
|
+
export interface ConnectDeps {
|
|
26
|
+
/** Resolve a running bridge. `port` selects a specific lock. */
|
|
27
|
+
findBridgeLock: (port?: number) => LockInfo | null;
|
|
28
|
+
/** HTTP transport (defaults to global fetch). */
|
|
29
|
+
fetchFn: typeof fetch;
|
|
30
|
+
/** Connector roster (defaults to the shared registry). */
|
|
31
|
+
connectors: readonly ConnectorDescriptor[];
|
|
32
|
+
/** stdout sink. */
|
|
33
|
+
write: (s: string) => void;
|
|
34
|
+
/** stderr sink. */
|
|
35
|
+
writeErr: (s: string) => void;
|
|
36
|
+
/** Process exit (capture-only in tests). */
|
|
37
|
+
exit: (code: number) => void;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* `patchwork connect ...` dispatcher.
|
|
41
|
+
*
|
|
42
|
+
* `deps` is fully injectable for tests. In production, callers pass
|
|
43
|
+
* `findBridgeLock` (from src/commands/task.ts's lock helper) plus any
|
|
44
|
+
* overrides; everything else defaults to real process I/O.
|
|
45
|
+
*/
|
|
46
|
+
export declare function runConnect(argv: string[], deps: Partial<ConnectDeps> & Pick<ConnectDeps, "findBridgeLock">): Promise<void>;
|
|
47
|
+
export {};
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `patchwork connect` — the connector front-door.
|
|
3
|
+
*
|
|
4
|
+
* A thin CLI→HTTP shim over the bridge's already-built `/connections/*`
|
|
5
|
+
* routes (see src/connectorRoutes.ts). 23 connector error messages already
|
|
6
|
+
* tell users to "Run: patchwork connect <vendor>"; this is that command.
|
|
7
|
+
*
|
|
8
|
+
* NO new bridge or connector logic lives here — every verb maps to one
|
|
9
|
+
* existing HTTP route:
|
|
10
|
+
* - list → GET /connections (Bearer)
|
|
11
|
+
* - <vendor> → GET /connections/<id>/auth (OAuth, 302 Location)
|
|
12
|
+
* or POST /connections/<id>/connect (PAT, {token})
|
|
13
|
+
* - test → POST /connections/<id>/test (health probe)
|
|
14
|
+
* - disconnect → DELETE /connections/<id> (revoke)
|
|
15
|
+
*
|
|
16
|
+
* Bridge discovery + Bearer auth mirror src/commands/task.ts. All side
|
|
17
|
+
* effects (lock discovery, fetch, stdout/stderr, exit) are injectable so
|
|
18
|
+
* the command is unit-testable without a live bridge.
|
|
19
|
+
*/
|
|
20
|
+
import { CONNECTORS, } from "../connectors/connectorRegistry.js";
|
|
21
|
+
const TIMEOUT_MS = 10_000;
|
|
22
|
+
function parseArgs(argv) {
|
|
23
|
+
const out = {
|
|
24
|
+
positional: [],
|
|
25
|
+
json: false,
|
|
26
|
+
urlOnly: false,
|
|
27
|
+
help: false,
|
|
28
|
+
};
|
|
29
|
+
for (let i = 0; i < argv.length; i++) {
|
|
30
|
+
const a = argv[i];
|
|
31
|
+
if (a === undefined)
|
|
32
|
+
continue;
|
|
33
|
+
if (a === "--json")
|
|
34
|
+
out.json = true;
|
|
35
|
+
else if (a === "--url-only")
|
|
36
|
+
out.urlOnly = true;
|
|
37
|
+
else if (a === "--help" || a === "-h")
|
|
38
|
+
out.help = true;
|
|
39
|
+
else if (a === "--token") {
|
|
40
|
+
const next = argv[++i];
|
|
41
|
+
if (next !== undefined)
|
|
42
|
+
out.token = next;
|
|
43
|
+
}
|
|
44
|
+
else if (a === "--port") {
|
|
45
|
+
const next = argv[++i];
|
|
46
|
+
if (next !== undefined)
|
|
47
|
+
out.port = Number(next);
|
|
48
|
+
}
|
|
49
|
+
else if (!a.startsWith("-")) {
|
|
50
|
+
out.positional.push(a);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
// ── helpers ──────────────────────────────────────────────────────────────────
|
|
56
|
+
function bearer(lock) {
|
|
57
|
+
return { Authorization: `Bearer ${lock.authToken}` };
|
|
58
|
+
}
|
|
59
|
+
function statusGlyph(status) {
|
|
60
|
+
if (status === "connected")
|
|
61
|
+
return "✓ connected";
|
|
62
|
+
if (status === "needs_reauth")
|
|
63
|
+
return "⚠ needs reauth";
|
|
64
|
+
return "✗ not connected";
|
|
65
|
+
}
|
|
66
|
+
function normalizeStatus(raw) {
|
|
67
|
+
if (raw === "connected" || raw === "needs_reauth")
|
|
68
|
+
return raw;
|
|
69
|
+
return "disconnected";
|
|
70
|
+
}
|
|
71
|
+
/** Levenshtein distance for "did you mean" suggestions. */
|
|
72
|
+
function editDistance(a, b) {
|
|
73
|
+
const m = a.length;
|
|
74
|
+
const n = b.length;
|
|
75
|
+
const prev = Array.from({ length: n + 1 }, (_, j) => j);
|
|
76
|
+
const curr = new Array(n + 1).fill(0);
|
|
77
|
+
for (let i = 1; i <= m; i++) {
|
|
78
|
+
curr[0] = i;
|
|
79
|
+
for (let j = 1; j <= n; j++) {
|
|
80
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
81
|
+
const del = (prev[j] ?? 0) + 1;
|
|
82
|
+
const ins = (curr[j - 1] ?? 0) + 1;
|
|
83
|
+
const sub = (prev[j - 1] ?? 0) + cost;
|
|
84
|
+
curr[j] = Math.min(del, ins, sub);
|
|
85
|
+
}
|
|
86
|
+
for (let j = 0; j <= n; j++)
|
|
87
|
+
prev[j] = curr[j] ?? 0;
|
|
88
|
+
}
|
|
89
|
+
return prev[n] ?? 0;
|
|
90
|
+
}
|
|
91
|
+
function suggestVendor(input, connectors) {
|
|
92
|
+
let best;
|
|
93
|
+
for (const c of connectors) {
|
|
94
|
+
const dist = editDistance(input, c.id);
|
|
95
|
+
if (!best || dist < best.dist)
|
|
96
|
+
best = { id: c.id, dist };
|
|
97
|
+
}
|
|
98
|
+
// Only suggest when reasonably close.
|
|
99
|
+
return best && best.dist <= 3 ? best.id : undefined;
|
|
100
|
+
}
|
|
101
|
+
function resolveLock(deps, port) {
|
|
102
|
+
const lock = deps.findBridgeLock(port);
|
|
103
|
+
if (!lock) {
|
|
104
|
+
deps.writeErr("No running bridge — start it with: patchwork start\n" +
|
|
105
|
+
(port !== undefined
|
|
106
|
+
? `(checked port ${port}; lock missing, IDE-owned, or dead)\n`
|
|
107
|
+
: ""));
|
|
108
|
+
deps.exit(1);
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
return lock;
|
|
112
|
+
}
|
|
113
|
+
async function readJson(res) {
|
|
114
|
+
const text = await res.text();
|
|
115
|
+
if (!text)
|
|
116
|
+
return null;
|
|
117
|
+
try {
|
|
118
|
+
return JSON.parse(text);
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function networkError(deps, err, json) {
|
|
125
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
126
|
+
if (json) {
|
|
127
|
+
deps.write(`${JSON.stringify({ ok: false, error: msg })}\n`);
|
|
128
|
+
}
|
|
129
|
+
deps.writeErr(`Error contacting bridge: ${msg}\n`);
|
|
130
|
+
deps.exit(1);
|
|
131
|
+
}
|
|
132
|
+
// ── verbs ────────────────────────────────────────────────────────────────────
|
|
133
|
+
async function runList(deps, args) {
|
|
134
|
+
const lock = resolveLock(deps, args.port);
|
|
135
|
+
if (!lock)
|
|
136
|
+
return;
|
|
137
|
+
let live;
|
|
138
|
+
try {
|
|
139
|
+
const res = await deps.fetchFn(`http://127.0.0.1:${lock.port}/connections`, {
|
|
140
|
+
method: "GET",
|
|
141
|
+
headers: bearer(lock),
|
|
142
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
143
|
+
});
|
|
144
|
+
live = await readJson(res);
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
networkError(deps, err, args.json);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// Join live status onto the full registry roster so connectors absent
|
|
151
|
+
// from the response render as not-connected rather than vanishing.
|
|
152
|
+
const statusById = new Map();
|
|
153
|
+
for (const c of live?.connectors ?? []) {
|
|
154
|
+
if (c.id)
|
|
155
|
+
statusById.set(c.id, normalizeStatus(c.status));
|
|
156
|
+
}
|
|
157
|
+
const rows = deps.connectors.map((c) => ({
|
|
158
|
+
id: c.id,
|
|
159
|
+
label: c.label,
|
|
160
|
+
authKind: c.authKind,
|
|
161
|
+
status: statusById.get(c.id) ?? "disconnected",
|
|
162
|
+
}));
|
|
163
|
+
if (args.json) {
|
|
164
|
+
deps.write(`${JSON.stringify({ connectors: rows })}\n`);
|
|
165
|
+
deps.exit(0);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
// Connected first, then needs_reauth, then disconnected; stable by label.
|
|
169
|
+
const rank = {
|
|
170
|
+
connected: 0,
|
|
171
|
+
needs_reauth: 1,
|
|
172
|
+
disconnected: 2,
|
|
173
|
+
};
|
|
174
|
+
rows.sort((a, b) => rank[a.status] - rank[b.status] || a.label.localeCompare(b.label));
|
|
175
|
+
const idWidth = Math.max(...rows.map((r) => r.id.length), 2);
|
|
176
|
+
deps.write("Connectors:\n");
|
|
177
|
+
for (const r of rows) {
|
|
178
|
+
deps.write(` ${r.id.padEnd(idWidth)} ${statusGlyph(r.status).padEnd(16)}` +
|
|
179
|
+
`${r.label} (${r.authKind})\n`);
|
|
180
|
+
}
|
|
181
|
+
deps.exit(0);
|
|
182
|
+
}
|
|
183
|
+
async function runOauth(deps, descriptor, args) {
|
|
184
|
+
const lock = resolveLock(deps, args.port);
|
|
185
|
+
if (!lock)
|
|
186
|
+
return;
|
|
187
|
+
let res;
|
|
188
|
+
try {
|
|
189
|
+
res = await deps.fetchFn(`http://127.0.0.1:${lock.port}/connections/${descriptor.id}/auth`, {
|
|
190
|
+
method: "GET",
|
|
191
|
+
headers: bearer(lock),
|
|
192
|
+
redirect: "manual",
|
|
193
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
catch (err) {
|
|
197
|
+
networkError(deps, err, args.json);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const location = res.headers.get("location");
|
|
201
|
+
if (res.status === 302 && location) {
|
|
202
|
+
if (args.json) {
|
|
203
|
+
deps.write(`${JSON.stringify({ ok: true, url: location })}\n`);
|
|
204
|
+
}
|
|
205
|
+
else if (args.urlOnly) {
|
|
206
|
+
deps.write(`${location}\n`);
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
deps.write(`Open this URL in your browser to authorize ${descriptor.label}:\n` +
|
|
210
|
+
` ${location}\n`);
|
|
211
|
+
}
|
|
212
|
+
deps.exit(0);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
// No redirect — surface the bridge's error body if present.
|
|
216
|
+
const body = await readJson(res);
|
|
217
|
+
const detail = body?.error ?? `HTTP ${res.status}`;
|
|
218
|
+
if (args.json) {
|
|
219
|
+
deps.write(`${JSON.stringify({ ok: false, error: detail })}\n`);
|
|
220
|
+
}
|
|
221
|
+
deps.writeErr(`Could not start ${descriptor.label} authorization: ${detail}\n`);
|
|
222
|
+
deps.exit(1);
|
|
223
|
+
}
|
|
224
|
+
async function runPatConnect(deps, descriptor, args) {
|
|
225
|
+
if (!args.token) {
|
|
226
|
+
// No token supplied — print honest instructions rather than guessing.
|
|
227
|
+
deps.write(`${descriptor.label} is a token (PAT) connector.\n` +
|
|
228
|
+
` Pass a token directly:\n` +
|
|
229
|
+
` patchwork connect ${descriptor.id} --token <TOKEN>\n` +
|
|
230
|
+
` Some connectors need more than one field (e.g. Jira/Confluence/` +
|
|
231
|
+
`Zendesk/Datadog need a URL + email + token).\n` +
|
|
232
|
+
` For those, use the dashboard /connections page to connect.\n`);
|
|
233
|
+
deps.exit(0);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const lock = resolveLock(deps, args.port);
|
|
237
|
+
if (!lock)
|
|
238
|
+
return;
|
|
239
|
+
let res;
|
|
240
|
+
try {
|
|
241
|
+
res = await deps.fetchFn(`http://127.0.0.1:${lock.port}/connections/${descriptor.id}/connect`, {
|
|
242
|
+
method: "POST",
|
|
243
|
+
headers: { ...bearer(lock), "Content-Type": "application/json" },
|
|
244
|
+
body: JSON.stringify({ token: args.token }),
|
|
245
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
catch (err) {
|
|
249
|
+
networkError(deps, err, args.json);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
const body = await readJson(res);
|
|
253
|
+
const ok = res.status >= 200 && res.status < 300 && body?.ok !== false;
|
|
254
|
+
if (args.json) {
|
|
255
|
+
deps.write(`${JSON.stringify({ ok, ...(body ?? {}) })}\n`);
|
|
256
|
+
}
|
|
257
|
+
else if (ok) {
|
|
258
|
+
const where = body?.workspace ? ` (workspace: ${body.workspace})` : "";
|
|
259
|
+
deps.write(`✓ Connected ${descriptor.label}${where}\n`);
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
deps.writeErr(`✗ Failed to connect ${descriptor.label}: ${body?.error ?? `HTTP ${res.status}`}\n`);
|
|
263
|
+
}
|
|
264
|
+
deps.exit(ok ? 0 : 1);
|
|
265
|
+
}
|
|
266
|
+
async function runTest(deps, vendor, args) {
|
|
267
|
+
const descriptor = resolveVendor(deps, vendor);
|
|
268
|
+
if (!descriptor)
|
|
269
|
+
return;
|
|
270
|
+
const lock = resolveLock(deps, args.port);
|
|
271
|
+
if (!lock)
|
|
272
|
+
return;
|
|
273
|
+
let res;
|
|
274
|
+
try {
|
|
275
|
+
res = await deps.fetchFn(`http://127.0.0.1:${lock.port}/connections/${descriptor.id}/test`, {
|
|
276
|
+
method: "POST",
|
|
277
|
+
headers: bearer(lock),
|
|
278
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
catch (err) {
|
|
282
|
+
networkError(deps, err, args.json);
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
const body = await readJson(res);
|
|
286
|
+
const ok = res.status >= 200 && res.status < 300 && body?.ok !== false;
|
|
287
|
+
if (args.json) {
|
|
288
|
+
deps.write(`${JSON.stringify({ ok, ...(body ?? {}) })}\n`);
|
|
289
|
+
}
|
|
290
|
+
else if (ok) {
|
|
291
|
+
deps.write(`✓ ${descriptor.label} is healthy\n`);
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
deps.writeErr(`✗ ${descriptor.label} test failed: ${body?.error ?? `HTTP ${res.status}`}\n`);
|
|
295
|
+
}
|
|
296
|
+
deps.exit(ok ? 0 : 1);
|
|
297
|
+
}
|
|
298
|
+
async function runDisconnect(deps, vendor, args) {
|
|
299
|
+
const descriptor = resolveVendor(deps, vendor);
|
|
300
|
+
if (!descriptor)
|
|
301
|
+
return;
|
|
302
|
+
const lock = resolveLock(deps, args.port);
|
|
303
|
+
if (!lock)
|
|
304
|
+
return;
|
|
305
|
+
let res;
|
|
306
|
+
try {
|
|
307
|
+
res = await deps.fetchFn(`http://127.0.0.1:${lock.port}/connections/${descriptor.id}`, {
|
|
308
|
+
method: "DELETE",
|
|
309
|
+
headers: bearer(lock),
|
|
310
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
catch (err) {
|
|
314
|
+
networkError(deps, err, args.json);
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
const body = await readJson(res);
|
|
318
|
+
const ok = res.status >= 200 && res.status < 300 && body?.ok !== false;
|
|
319
|
+
if (args.json) {
|
|
320
|
+
deps.write(`${JSON.stringify({ ok, ...(body ?? {}) })}\n`);
|
|
321
|
+
}
|
|
322
|
+
else if (ok) {
|
|
323
|
+
deps.write(`✓ Disconnected ${descriptor.label}\n`);
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
deps.writeErr(`✗ Failed to disconnect ${descriptor.label}: ${body?.error ?? `HTTP ${res.status}`}\n`);
|
|
327
|
+
}
|
|
328
|
+
deps.exit(ok ? 0 : 1);
|
|
329
|
+
}
|
|
330
|
+
/** Resolve a vendor id to its descriptor, or emit an error + exit(1). */
|
|
331
|
+
function resolveVendor(deps, vendor) {
|
|
332
|
+
if (!vendor) {
|
|
333
|
+
deps.writeErr("Missing connector id.\n");
|
|
334
|
+
deps.exit(1);
|
|
335
|
+
return undefined;
|
|
336
|
+
}
|
|
337
|
+
const descriptor = deps.connectors.find((c) => c.id === vendor);
|
|
338
|
+
if (!descriptor) {
|
|
339
|
+
const hint = suggestVendor(vendor, deps.connectors);
|
|
340
|
+
const validIds = deps.connectors.map((c) => c.id).join(", ");
|
|
341
|
+
deps.writeErr(`Unknown connector "${vendor}".\n` +
|
|
342
|
+
(hint ? `Did you mean "${hint}"?\n` : "") +
|
|
343
|
+
`Valid ids: ${validIds}\n`);
|
|
344
|
+
deps.exit(1);
|
|
345
|
+
return undefined;
|
|
346
|
+
}
|
|
347
|
+
return descriptor;
|
|
348
|
+
}
|
|
349
|
+
function printHelp(deps) {
|
|
350
|
+
deps.write("Usage: patchwork connect [<vendor>|list|test <vendor>|disconnect <vendor>]\n" +
|
|
351
|
+
"\n" +
|
|
352
|
+
" connect [list] [--json] List connectors + connection status\n" +
|
|
353
|
+
" connect <vendor> [--url-only] OAuth: print the authorize URL to open\n" +
|
|
354
|
+
" connect <vendor> --token <TOKEN> PAT: paste a token to connect\n" +
|
|
355
|
+
" connect test <vendor> [--json] Health-probe a connector\n" +
|
|
356
|
+
" connect disconnect <vendor> Revoke a connector\n" +
|
|
357
|
+
"\n" +
|
|
358
|
+
" --port <n> Target a specific bridge lock\n" +
|
|
359
|
+
" --url-only Print only the OAuth URL (headless/CI)\n" +
|
|
360
|
+
" --json Machine-readable output\n");
|
|
361
|
+
deps.exit(0);
|
|
362
|
+
}
|
|
363
|
+
// ── entrypoint ───────────────────────────────────────────────────────────────
|
|
364
|
+
const DEFAULT_DEPS = {
|
|
365
|
+
fetchFn: globalThis.fetch,
|
|
366
|
+
connectors: CONNECTORS,
|
|
367
|
+
write: (s) => process.stdout.write(s),
|
|
368
|
+
writeErr: (s) => process.stderr.write(s),
|
|
369
|
+
exit: (c) => process.exit(c),
|
|
370
|
+
};
|
|
371
|
+
/**
|
|
372
|
+
* `patchwork connect ...` dispatcher.
|
|
373
|
+
*
|
|
374
|
+
* `deps` is fully injectable for tests. In production, callers pass
|
|
375
|
+
* `findBridgeLock` (from src/commands/task.ts's lock helper) plus any
|
|
376
|
+
* overrides; everything else defaults to real process I/O.
|
|
377
|
+
*/
|
|
378
|
+
export async function runConnect(argv, deps) {
|
|
379
|
+
const resolved = { ...DEFAULT_DEPS, ...deps };
|
|
380
|
+
const args = parseArgs(argv);
|
|
381
|
+
if (args.help) {
|
|
382
|
+
printHelp(resolved);
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
const verb = args.positional[0];
|
|
386
|
+
// Bare `connect` or `connect list` → list.
|
|
387
|
+
if (verb === undefined || verb === "list") {
|
|
388
|
+
await runList(resolved, args);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
if (verb === "test") {
|
|
392
|
+
await runTest(resolved, args.positional[1], args);
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
if (verb === "disconnect") {
|
|
396
|
+
await runDisconnect(resolved, args.positional[1], args);
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
// Otherwise `verb` is a vendor id: OAuth (auth) or PAT (connect).
|
|
400
|
+
const descriptor = resolveVendor(resolved, verb);
|
|
401
|
+
if (!descriptor)
|
|
402
|
+
return;
|
|
403
|
+
if (descriptor.authKind === "oauth" && descriptor.supports.auth) {
|
|
404
|
+
await runOauth(resolved, descriptor, args);
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
if (descriptor.supports.connect) {
|
|
408
|
+
await runPatConnect(resolved, descriptor, args);
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
// OAuth-capable PAT connectors (auth:true but pat): prefer the token path.
|
|
412
|
+
if (descriptor.supports.auth) {
|
|
413
|
+
await runOauth(resolved, descriptor, args);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
resolved.writeErr(`Connector "${descriptor.id}" does not support an interactive connect flow.\n`);
|
|
417
|
+
resolved.exit(1);
|
|
418
|
+
}
|
|
419
|
+
//# sourceMappingURL=connect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"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"}
|
|
@@ -289,6 +289,11 @@ export interface DoctorRuntimeHalts {
|
|
|
289
289
|
runSeq: number;
|
|
290
290
|
}>;
|
|
291
291
|
}
|
|
292
|
+
/** One connection-status entry as reported by the bridge `/connections` list. */
|
|
293
|
+
export interface DoctorConnectionEntry {
|
|
294
|
+
id?: string;
|
|
295
|
+
status?: string;
|
|
296
|
+
}
|
|
292
297
|
export interface RecipeDoctorOptions extends PreflightOptions {
|
|
293
298
|
/**
|
|
294
299
|
* Fetches recent runtime halts for the recipe by name. Returns null when
|
|
@@ -296,6 +301,21 @@ export interface RecipeDoctorOptions extends PreflightOptions {
|
|
|
296
301
|
* the bridge walk lives in the CLI layer and the command stays testable.
|
|
297
302
|
*/
|
|
298
303
|
fetchHalts?: (recipeName: string) => Promise<DoctorRuntimeHalts | null>;
|
|
304
|
+
/**
|
|
305
|
+
* Fetches the current connector statuses (`/connections` payload — the
|
|
306
|
+
* same `handleConnectionsList` source the dashboard install preflight
|
|
307
|
+
* uses). Returns null when no bridge is reachable, in which case doctor
|
|
308
|
+
* reports the *required* connectors statically but skips the
|
|
309
|
+
* authorized/missing classification. Injected for the same reason as
|
|
310
|
+
* `fetchHalts`: the bridge walk stays in the CLI layer and the command
|
|
311
|
+
* stays testable.
|
|
312
|
+
*
|
|
313
|
+
* "Connector not authorized" is the #1 runtime-halt class — surfacing the
|
|
314
|
+
* unauthenticated connectors a recipe needs (with the one-command fix)
|
|
315
|
+
* turns the most common silent first-run failure into an up-front
|
|
316
|
+
* diagnosis.
|
|
317
|
+
*/
|
|
318
|
+
fetchConnections?: () => Promise<DoctorConnectionEntry[] | null>;
|
|
299
319
|
}
|
|
300
320
|
/**
|
|
301
321
|
* Static half of the doctor report. A lighter projection of
|
|
@@ -311,24 +331,45 @@ export interface DoctorStaticResult {
|
|
|
311
331
|
/** True when the recipe couldn't be planned (load threw) — lint-only. */
|
|
312
332
|
planSkipped?: boolean;
|
|
313
333
|
}
|
|
334
|
+
/**
|
|
335
|
+
* Connector authorization diagnosis. `required` is always populated (static
|
|
336
|
+
* detection over the recipe's steps — no bridge needed). `missing` /
|
|
337
|
+
* `authorized` are only meaningful when `connectionsChecked` is true; when no
|
|
338
|
+
* bridge was reachable we still tell the user which connectors the recipe
|
|
339
|
+
* needs but can't say which are authorized.
|
|
340
|
+
*/
|
|
341
|
+
export interface DoctorConnectorsResult {
|
|
342
|
+
/** Connector ids the recipe requires (static detection). Sorted. */
|
|
343
|
+
required: string[];
|
|
344
|
+
/** Required connectors that are NOT in a "connected" state. */
|
|
345
|
+
missing: string[];
|
|
346
|
+
/** Required connectors that ARE connected. */
|
|
347
|
+
authorized: string[];
|
|
348
|
+
/** True when live connection statuses were fetched and classified. */
|
|
349
|
+
connectionsChecked: boolean;
|
|
350
|
+
/** Why the auth check was skipped (no bridge / not requested), if applicable. */
|
|
351
|
+
note?: string;
|
|
352
|
+
}
|
|
314
353
|
export interface RecipeDoctorResult {
|
|
315
354
|
recipe: string;
|
|
316
355
|
recipePath: string;
|
|
317
356
|
/** Static analysis: lint + write-policy + dry-plan (lint-only on load failure). */
|
|
318
357
|
static: DoctorStaticResult;
|
|
358
|
+
/** Required connectors + (when a bridge was reachable) their auth state. */
|
|
359
|
+
connectors: DoctorConnectorsResult;
|
|
319
360
|
/** Recent runtime halts, or null when no bridge was reachable. */
|
|
320
361
|
runtime: DoctorRuntimeHalts | null;
|
|
321
362
|
/** Why runtime is null (e.g. "no running bridge"), when applicable. */
|
|
322
363
|
runtimeNote?: string;
|
|
323
|
-
/** True when static passed AND no runtime halts were seen. */
|
|
364
|
+
/** True when static passed, no required connectors are missing, AND no runtime halts were seen. */
|
|
324
365
|
ok: boolean;
|
|
325
366
|
}
|
|
326
367
|
/**
|
|
327
368
|
* `recipe doctor` — one-screen "why is this recipe unhealthy + how do I
|
|
328
369
|
* fix it" diagnosis. Composes the static `preflight` check (lint + policy
|
|
329
|
-
* + plan) with the recipe-scoped runtime
|
|
330
|
-
* finding to an actionable hint. Fail-soft: a
|
|
331
|
-
* static-only rather than erroring.
|
|
370
|
+
* + plan) and static connector detection with the recipe-scoped runtime
|
|
371
|
+
* halt summary, mapping every finding to an actionable hint. Fail-soft: a
|
|
372
|
+
* missing bridge degrades to static-only rather than erroring.
|
|
332
373
|
*/
|
|
333
374
|
export declare function runRecipeDoctor(recipeRef: string, options?: RecipeDoctorOptions): Promise<RecipeDoctorResult>;
|
|
334
375
|
/**
|