@gh-symphony/cli 0.0.21 → 0.1.2

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 (36) hide show
  1. package/README.md +100 -69
  2. package/dist/chunk-6I753NYO.js +18 -0
  3. package/dist/{workflow-BLJH2HC3.js → chunk-B4ZJMAZL.js} +27 -19
  4. package/dist/{chunk-SXGT7LOF.js → chunk-DLZAJXZL.js} +600 -12
  5. package/dist/chunk-GHVDABFO.js +235 -0
  6. package/dist/{chunk-QEONJ5DZ.js → chunk-GPRCOJDJ.js} +1314 -35
  7. package/dist/{chunk-A67CMOYE.js → chunk-VFHMHHZW.js} +1 -1
  8. package/dist/{chunk-JN3TQVFV.js → chunk-WM2B6BJ7.js} +16 -62
  9. package/dist/{chunk-ROGRTUFI.js → chunk-WOVNN5NW.js} +16 -6
  10. package/dist/{chunk-C67H3OUL.js → chunk-Z3NZOPLZ.js} +0 -81
  11. package/dist/{config-cmd-DNXNL26Z.js → config-cmd-2ADPUYWA.js} +1 -1
  12. package/dist/{doctor-4HBRICHP.js → doctor-EEPNFCGF.js} +464 -40
  13. package/dist/index.js +357 -244
  14. package/dist/repo-RX4OK7XH.js +6783 -0
  15. package/dist/{setup-B2SVLW2R.js → setup-XNHHRBGU.js} +57 -91
  16. package/dist/{upgrade-OJXPZRYE.js → upgrade-NS53EO2B.js} +2 -2
  17. package/dist/{version-TBDCTKDO.js → version-2RHFZ5CI.js} +1 -1
  18. package/dist/worker-entry.js +376 -15
  19. package/dist/workflow-26QNZZWH.js +22 -0
  20. package/package.json +5 -5
  21. package/dist/chunk-5NV3LSAJ.js +0 -11
  22. package/dist/chunk-C7G7RJ4G.js +0 -146
  23. package/dist/chunk-KY6WKH66.js +0 -1300
  24. package/dist/chunk-MYVJ6HK4.js +0 -3510
  25. package/dist/chunk-S6VIK4FF.js +0 -723
  26. package/dist/chunk-XN5ABWZ6.js +0 -486
  27. package/dist/chunk-Y6TYJMNT.js +0 -109
  28. package/dist/init-HZ3JEDGQ.js +0 -38
  29. package/dist/logs-6JKKYDGJ.js +0 -188
  30. package/dist/project-25NQ4J4Y.js +0 -24
  31. package/dist/recover-L3MJHHDA.js +0 -133
  32. package/dist/repo-TDCWQR6P.js +0 -379
  33. package/dist/run-XJQ6BF7U.js +0 -110
  34. package/dist/start-I2CC7BLW.js +0 -18
  35. package/dist/status-QSCFVGRQ.js +0 -11
  36. package/dist/stop-7MFCBQVW.js +0 -9
@@ -1,379 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- GitHubRepositoryLookupError,
4
- GitHubScopeError,
5
- checkRequiredScopes,
6
- createClient,
7
- getGhToken,
8
- getProjectDetail,
9
- getRepositoryMetadata,
10
- validateToken
11
- } from "./chunk-C67H3OUL.js";
12
- import {
13
- loadActiveProjectConfig,
14
- loadGlobalConfig,
15
- saveProjectConfig
16
- } from "./chunk-ROGRTUFI.js";
17
-
18
- // src/commands/repo.ts
19
- var handler = async (args, options) => {
20
- const [subcommand, ...rest] = args;
21
- switch (subcommand) {
22
- case "list":
23
- await repoList(options);
24
- break;
25
- case "add":
26
- await repoAdd(rest, options);
27
- break;
28
- case "remove":
29
- await repoRemove(rest, options);
30
- break;
31
- case "sync":
32
- await repoSync(rest, options);
33
- break;
34
- default:
35
- process.stderr.write(
36
- "Usage: gh-symphony repo <list|add|remove|sync> [repo]\n"
37
- );
38
- process.exitCode = 2;
39
- }
40
- };
41
- var repo_default = handler;
42
- function repoKey(repo) {
43
- return `${repo.owner}/${repo.name}`.toLowerCase();
44
- }
45
- function toRepoConfigEntry(repo) {
46
- return {
47
- owner: repo.owner,
48
- name: repo.name,
49
- cloneUrl: repo.cloneUrl
50
- };
51
- }
52
- function parseRepoSyncFlags(args) {
53
- const flags = { dryRun: false, prune: false };
54
- for (const arg of args) {
55
- if (arg === "--dry-run") {
56
- flags.dryRun = true;
57
- } else if (arg === "--prune") {
58
- flags.prune = true;
59
- }
60
- }
61
- return flags;
62
- }
63
- function displayScopeError(error) {
64
- const plural = error.requiredScopes.length === 1 ? "" : "s";
65
- process.stderr.write(
66
- `Token is missing required scope${plural}: ${error.requiredScopes.join(", ")}
67
- `
68
- );
69
- const currentSet = new Set(error.currentScopes.map((scope) => scope.toLowerCase()));
70
- const scopesToAdd = ["repo", "read:org", "project"].filter(
71
- (scope) => !currentSet.has(scope)
72
- );
73
- const scopeArg = scopesToAdd.length > 0 ? scopesToAdd.join(",") : error.requiredScopes.join(",");
74
- process.stderr.write(
75
- `Run 'gh auth refresh --scopes ${scopeArg}' and try again.
76
- `
77
- );
78
- }
79
- function formatRepoSpec(repo) {
80
- return `${repo.owner}/${repo.name}`;
81
- }
82
- function fallbackCloneUrl(repo) {
83
- return `https://github.com/${repo.owner}/${repo.name}.git`;
84
- }
85
- function sortRepos(repos) {
86
- return [...repos].sort(
87
- (left, right) => formatRepoSpec(left).localeCompare(formatRepoSpec(right))
88
- );
89
- }
90
- function renderRepoGroup(label, repos) {
91
- if (repos.length === 0) {
92
- return [`${label}: none`];
93
- }
94
- return [label, ...sortRepos(repos).map((repo) => ` ${formatRepoSpec(repo)}`)];
95
- }
96
- function buildSyncedRepositories(currentRepos, linkedMap, linkedRepositories, prune) {
97
- const retained = currentRepos.filter((repo) => linkedMap.has(repoKey(repo)) || !prune).map((repo) => {
98
- const linked = linkedMap.get(repoKey(repo));
99
- return linked ? toRepoConfigEntry(linked) : { ...repo };
100
- });
101
- const currentKeys = new Set(currentRepos.map((repo) => repoKey(repo)));
102
- const additions = sortRepos(
103
- linkedRepositories.filter((repo) => !currentKeys.has(repoKey(repo))).map(toRepoConfigEntry)
104
- );
105
- return [...retained, ...additions];
106
- }
107
- function writeRepoSummary(summary, options) {
108
- if (options.json) {
109
- process.stdout.write(JSON.stringify(summary, null, 2) + "\n");
110
- return;
111
- }
112
- process.stdout.write(
113
- [
114
- `Repository sync ${summary.dryRun ? "preview" : "complete"} for ${summary.projectId}`,
115
- `Mode: ${summary.prune ? "prune" : "additive"}`,
116
- ...renderRepoGroup("Added", summary.added),
117
- ...renderRepoGroup("Removed", summary.removed),
118
- ...renderRepoGroup("Unchanged", summary.unchanged),
119
- summary.dryRun ? "No config changes written." : "Configuration updated."
120
- ].join("\n") + "\n"
121
- );
122
- }
123
- async function repoList(options) {
124
- const ws = await loadActiveProjectConfig(options.configDir);
125
- if (!ws) {
126
- process.stderr.write("No project configured.\n");
127
- process.exitCode = 1;
128
- return;
129
- }
130
- if (options.json) {
131
- process.stdout.write(JSON.stringify(ws.repositories, null, 2) + "\n");
132
- return;
133
- }
134
- process.stdout.write("Repositories:\n");
135
- for (const repo of ws.repositories) {
136
- process.stdout.write(` ${repo.owner}/${repo.name}
137
- `);
138
- }
139
- }
140
- async function repoAdd(args, options) {
141
- const [repoSpec] = args;
142
- if (!repoSpec || !repoSpec.includes("/")) {
143
- process.stderr.write("Usage: gh-symphony repo add <owner/name>\n");
144
- process.exitCode = 2;
145
- return;
146
- }
147
- const global = await loadGlobalConfig(options.configDir);
148
- if (!global?.activeProject) {
149
- process.stderr.write("No active project.\n");
150
- process.exitCode = 1;
151
- return;
152
- }
153
- const ws = await loadActiveProjectConfig(options.configDir);
154
- if (!ws) {
155
- process.stderr.write("Project config missing.\n");
156
- process.exitCode = 1;
157
- return;
158
- }
159
- const activeProjectId = global.activeProject;
160
- const [owner, name] = repoSpec.split("/");
161
- if (!owner || !name) {
162
- process.stderr.write("Invalid repo format. Use: owner/name\n");
163
- process.exitCode = 2;
164
- return;
165
- }
166
- const requestedRepo = { owner, name };
167
- const addRepository = async (repo, message, warning) => {
168
- if (ws.repositories.some((entry) => repoKey(entry) === repoKey(repo))) {
169
- process.stdout.write(
170
- `Repository ${formatRepoSpec(repo)} is already configured.
171
- `
172
- );
173
- return;
174
- }
175
- ws.repositories.push(repo);
176
- await saveProjectConfig(options.configDir, activeProjectId, ws);
177
- if (warning) {
178
- process.stderr.write(`${warning}
179
- `);
180
- }
181
- process.stdout.write(`${message}
182
- `);
183
- };
184
- let token;
185
- try {
186
- token = getGhToken();
187
- } catch {
188
- await addRepository(
189
- {
190
- ...requestedRepo,
191
- cloneUrl: fallbackCloneUrl(requestedRepo)
192
- },
193
- `Added repository without validation: ${formatRepoSpec(requestedRepo)}`,
194
- "Warning: GitHub authentication is unavailable, so the repository was saved without validation. Run 'gh auth login --scopes repo,read:org,project' or set GITHUB_GRAPHQL_TOKEN to validate access before saving."
195
- );
196
- return;
197
- }
198
- try {
199
- const repository = await getRepositoryMetadata(createClient(token), owner, name);
200
- await addRepository(
201
- {
202
- owner: repository.owner,
203
- name: repository.name,
204
- cloneUrl: repository.cloneUrl || fallbackCloneUrl(repository)
205
- },
206
- `Added repository after validation: ${formatRepoSpec(repository)}`
207
- );
208
- } catch (error) {
209
- if (error instanceof GitHubRepositoryLookupError && error.reason === "offline") {
210
- await addRepository(
211
- {
212
- ...requestedRepo,
213
- cloneUrl: fallbackCloneUrl(requestedRepo)
214
- },
215
- `Added repository without validation: ${formatRepoSpec(requestedRepo)}`,
216
- `Warning: ${error.message} Saved the repository without validation. ${error.remediation}`
217
- );
218
- return;
219
- }
220
- if (error instanceof GitHubRepositoryLookupError) {
221
- process.stderr.write(`${error.message}
222
- ${error.remediation}
223
- `);
224
- } else {
225
- process.stderr.write(
226
- `${error instanceof Error ? error.message : "Repository validation failed."}
227
- `
228
- );
229
- }
230
- process.exitCode = 1;
231
- }
232
- }
233
- async function repoRemove(args, options) {
234
- const [repoSpec] = args;
235
- if (!repoSpec || !repoSpec.includes("/")) {
236
- process.stderr.write("Usage: gh-symphony repo remove <owner/name>\n");
237
- process.exitCode = 2;
238
- return;
239
- }
240
- const global = await loadGlobalConfig(options.configDir);
241
- if (!global?.activeProject) {
242
- process.stderr.write("No active project.\n");
243
- process.exitCode = 1;
244
- return;
245
- }
246
- const ws = await loadActiveProjectConfig(options.configDir);
247
- if (!ws) {
248
- process.stderr.write("Project config missing.\n");
249
- process.exitCode = 1;
250
- return;
251
- }
252
- const [owner, name] = repoSpec.split("/");
253
- const requestedRepo = { owner, name };
254
- const idx = ws.repositories.findIndex(
255
- (r) => repoKey(r) === repoKey(requestedRepo)
256
- );
257
- if (idx === -1) {
258
- process.stderr.write(`Repository ${repoSpec} is not configured.
259
- `);
260
- process.exitCode = 1;
261
- return;
262
- }
263
- ws.repositories.splice(idx, 1);
264
- await saveProjectConfig(options.configDir, global.activeProject, ws);
265
- process.stdout.write(`Removed repository: ${formatRepoSpec(requestedRepo)}
266
- `);
267
- }
268
- async function repoSync(args, options) {
269
- const flags = parseRepoSyncFlags(args);
270
- const global = await loadGlobalConfig(options.configDir);
271
- if (!global?.activeProject) {
272
- process.stderr.write("No active project.\n");
273
- process.exitCode = 1;
274
- return;
275
- }
276
- const ws = await loadActiveProjectConfig(options.configDir);
277
- if (!ws) {
278
- process.stderr.write("Project config missing.\n");
279
- process.exitCode = 1;
280
- return;
281
- }
282
- const projectBindingId = typeof ws.tracker.settings?.projectId === "string" ? ws.tracker.settings.projectId : ws.tracker.bindingId;
283
- if (!projectBindingId) {
284
- process.stderr.write(
285
- "Active project is missing its GitHub Project binding. Re-run 'gh-symphony project add'.\n"
286
- );
287
- process.exitCode = 1;
288
- return;
289
- }
290
- let token;
291
- try {
292
- token = getGhToken();
293
- } catch {
294
- process.stderr.write(
295
- "Error: GitHub token not found. Run 'gh auth login --scopes repo,read:org,project' or set GITHUB_GRAPHQL_TOKEN.\n"
296
- );
297
- process.exitCode = 1;
298
- return;
299
- }
300
- const client = createClient(token);
301
- try {
302
- const viewer = await validateToken(client);
303
- const scopeCheck = checkRequiredScopes(viewer.scopes);
304
- if (!scopeCheck.valid) {
305
- process.stderr.write(
306
- `Error: Missing required PAT scopes: ${scopeCheck.missing.join(", ")}
307
- `
308
- );
309
- process.exitCode = 1;
310
- return;
311
- }
312
- } catch {
313
- process.stderr.write("Error: Invalid GitHub token.\n");
314
- process.exitCode = 1;
315
- return;
316
- }
317
- let projectDetail;
318
- try {
319
- projectDetail = await getProjectDetail(client, projectBindingId);
320
- } catch (error) {
321
- if (error instanceof GitHubScopeError) {
322
- displayScopeError(error);
323
- } else {
324
- process.stderr.write(
325
- `${error instanceof Error ? error.message : "Failed to load linked repositories."}
326
- `
327
- );
328
- }
329
- process.exitCode = 1;
330
- return;
331
- }
332
- const currentRepos = ws.repositories;
333
- const currentMap = new Map(
334
- currentRepos.map((repo) => [repoKey(repo), repo])
335
- );
336
- const linkedMap = new Map(
337
- projectDetail.linkedRepositories.map((repo) => [
338
- repoKey(repo),
339
- repo
340
- ])
341
- );
342
- const added = projectDetail.linkedRepositories.filter((repo) => !currentMap.has(repoKey(repo))).map(toRepoConfigEntry);
343
- const removed = flags.prune ? currentRepos.filter((repo) => !linkedMap.has(repoKey(repo))).map((repo) => ({ ...repo })) : [];
344
- const unchanged = flags.prune ? currentRepos.filter((repo) => linkedMap.has(repoKey(repo))).map((repo) => {
345
- const linked = linkedMap.get(repoKey(repo));
346
- return linked ? toRepoConfigEntry(linked) : { ...repo };
347
- }) : currentRepos.map((repo) => {
348
- const linked = linkedMap.get(repoKey(repo));
349
- return linked ? toRepoConfigEntry(linked) : { ...repo };
350
- });
351
- const nextRepositories = buildSyncedRepositories(
352
- currentRepos,
353
- linkedMap,
354
- projectDetail.linkedRepositories,
355
- flags.prune
356
- );
357
- if (!flags.dryRun) {
358
- await saveProjectConfig(options.configDir, global.activeProject, {
359
- ...ws,
360
- repositories: nextRepositories
361
- });
362
- }
363
- writeRepoSummary(
364
- {
365
- projectId: global.activeProject,
366
- githubProjectId: projectBindingId,
367
- dryRun: flags.dryRun,
368
- prune: flags.prune,
369
- added,
370
- removed,
371
- unchanged,
372
- repositories: nextRepositories
373
- },
374
- options
375
- );
376
- }
377
- export {
378
- repo_default as default
379
- };
@@ -1,110 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- runCli
4
- } from "./chunk-MYVJ6HK4.js";
5
- import "./chunk-A67CMOYE.js";
6
- import "./chunk-SXGT7LOF.js";
7
- import "./chunk-QEONJ5DZ.js";
8
- import {
9
- resolveRuntimeRoot
10
- } from "./chunk-5NV3LSAJ.js";
11
- import {
12
- handleMissingManagedProjectConfig,
13
- resolveManagedProjectConfig
14
- } from "./chunk-C7G7RJ4G.js";
15
- import "./chunk-ROGRTUFI.js";
16
-
17
- // src/commands/run.ts
18
- function parseRunArgs(args) {
19
- const parsed = {
20
- watch: false
21
- };
22
- for (let i = 0; i < args.length; i += 1) {
23
- const arg = args[i];
24
- if (arg === "--watch" || arg === "-w") {
25
- parsed.watch = true;
26
- } else if (arg === "--project" || arg === "--project-id") {
27
- const value = args[i + 1];
28
- if (!value || value.startsWith("-")) {
29
- parsed.error = `Option '${arg}' argument missing`;
30
- return parsed;
31
- }
32
- parsed.projectId = value;
33
- i += 1;
34
- } else if (arg === "--log-level") {
35
- const value = args[i + 1];
36
- if (!value || value.startsWith("-")) {
37
- parsed.error = `Option '${arg}' argument missing`;
38
- return parsed;
39
- }
40
- parsed.logLevel = value;
41
- i += 1;
42
- } else if (!arg?.startsWith("-")) {
43
- parsed.issue = arg;
44
- } else {
45
- parsed.error = `Unknown option '${arg}'`;
46
- return parsed;
47
- }
48
- }
49
- return parsed;
50
- }
51
- var handler = async (args, options) => {
52
- const parsed = parseRunArgs(args);
53
- if (parsed.error) {
54
- process.stderr.write(`${parsed.error}
55
- `);
56
- process.exitCode = 2;
57
- return;
58
- }
59
- if (!parsed.issue) {
60
- process.stderr.write("Usage: gh-symphony run <owner/repo#number>\n");
61
- process.exitCode = 2;
62
- return;
63
- }
64
- const projectConfig = await resolveManagedProjectConfig({
65
- configDir: options.configDir,
66
- requestedProjectId: parsed.projectId
67
- });
68
- if (!projectConfig) {
69
- handleMissingManagedProjectConfig();
70
- return;
71
- }
72
- const runtimeRoot = resolveRuntimeRoot(options.configDir);
73
- const projectId = projectConfig.projectId;
74
- const [repoSpec] = parsed.issue.split("#");
75
- if (repoSpec && !projectConfig.repositories.some((r) => `${r.owner}/${r.name}` === repoSpec)) {
76
- process.stderr.write(
77
- `Repository "${repoSpec}" is not configured in this project.
78
- Configured repos: ${projectConfig.repositories.map((r) => `${r.owner}/${r.name}`).join(", ")}
79
- `
80
- );
81
- process.exitCode = 1;
82
- return;
83
- }
84
- process.stdout.write(`Dispatching issue: ${parsed.issue}
85
- `);
86
- await runCli([
87
- "run-issue",
88
- "--runtime-root",
89
- runtimeRoot,
90
- "--project-id",
91
- projectId,
92
- "--issue",
93
- parsed.issue,
94
- ...parsed.logLevel ? ["--log-level", parsed.logLevel] : []
95
- ]);
96
- if (parsed.watch) {
97
- process.stdout.write("\nWatching for status changes...\n");
98
- await runCli([
99
- "status",
100
- "--runtime-root",
101
- runtimeRoot,
102
- "--project-id",
103
- projectId
104
- ]);
105
- }
106
- };
107
- var run_default = handler;
108
- export {
109
- run_default as default
110
- };
@@ -1,18 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- shutdownForegroundOrchestrator,
4
- start_default
5
- } from "./chunk-KY6WKH66.js";
6
- import "./chunk-MYVJ6HK4.js";
7
- import "./chunk-A67CMOYE.js";
8
- import "./chunk-SXGT7LOF.js";
9
- import "./chunk-C67H3OUL.js";
10
- import "./chunk-QEONJ5DZ.js";
11
- import "./chunk-MVRF7BES.js";
12
- import "./chunk-5NV3LSAJ.js";
13
- import "./chunk-C7G7RJ4G.js";
14
- import "./chunk-ROGRTUFI.js";
15
- export {
16
- start_default as default,
17
- shutdownForegroundOrchestrator
18
- };
@@ -1,11 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- status_default
4
- } from "./chunk-XN5ABWZ6.js";
5
- import "./chunk-MVRF7BES.js";
6
- import "./chunk-5NV3LSAJ.js";
7
- import "./chunk-C7G7RJ4G.js";
8
- import "./chunk-ROGRTUFI.js";
9
- export {
10
- status_default as default
11
- };
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- stop_default
4
- } from "./chunk-Y6TYJMNT.js";
5
- import "./chunk-C7G7RJ4G.js";
6
- import "./chunk-ROGRTUFI.js";
7
- export {
8
- stop_default as default
9
- };