ultra-dex 3.1.0 ā 3.3.0
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/README.md +79 -74
- package/assets/code-patterns/clerk-middleware.ts +138 -0
- package/assets/code-patterns/prisma-schema.prisma +224 -0
- package/assets/code-patterns/rls-policies.sql +246 -0
- package/assets/code-patterns/server-actions.ts +191 -0
- package/assets/code-patterns/trpc-router.ts +258 -0
- package/assets/cursor-rules/13-ai-integration.mdc +155 -0
- package/assets/cursor-rules/14-server-components.mdc +81 -0
- package/assets/cursor-rules/15-server-actions.mdc +102 -0
- package/assets/cursor-rules/16-edge-middleware.mdc +105 -0
- package/assets/cursor-rules/17-streaming-ssr.mdc +138 -0
- package/bin/ultra-dex.js +50 -1
- package/lib/commands/agents.js +16 -13
- package/lib/commands/banner.js +43 -21
- package/lib/commands/build.js +26 -17
- package/lib/commands/cloud.js +780 -0
- package/lib/commands/doctor.js +98 -79
- package/lib/commands/exec.js +434 -0
- package/lib/commands/generate.js +19 -16
- package/lib/commands/github.js +475 -0
- package/lib/commands/init.js +52 -56
- package/lib/commands/scaffold.js +151 -0
- package/lib/commands/search.js +477 -0
- package/lib/commands/serve.js +15 -13
- package/lib/commands/state.js +43 -70
- package/lib/commands/swarm.js +31 -9
- package/lib/config/theme.js +47 -0
- package/lib/mcp/client.js +502 -0
- package/lib/providers/agent-sdk.js +630 -0
- package/lib/providers/anthropic-agents.js +580 -0
- package/lib/templates/code/clerk-middleware.ts +138 -0
- package/lib/templates/code/prisma-schema.prisma +224 -0
- package/lib/templates/code/rls-policies.sql +246 -0
- package/lib/templates/code/server-actions.ts +191 -0
- package/lib/templates/code/trpc-router.ts +258 -0
- package/lib/themes/doomsday.js +229 -0
- package/lib/ui/index.js +5 -0
- package/lib/ui/interface.js +241 -0
- package/lib/ui/spinners.js +116 -0
- package/lib/ui/theme.js +183 -0
- package/lib/utils/agents.js +32 -0
- package/lib/utils/browser.js +373 -0
- package/lib/utils/help.js +64 -0
- package/lib/utils/messages.js +35 -0
- package/lib/utils/progress.js +24 -0
- package/lib/utils/prompts.js +47 -0
- package/lib/utils/spinners.js +46 -0
- package/lib/utils/status.js +31 -0
- package/lib/utils/tables.js +41 -0
- package/lib/utils/theme-state.js +9 -0
- package/lib/utils/version-display.js +32 -0
- package/package.json +19 -4
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ultra-dex github command
|
|
3
|
+
* GitHub App integration for issue tracking, auto-PR creation, and CI/CD
|
|
4
|
+
* This connects Ultra-Dex to the GitHub ecosystem for true automation
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import ora from 'ora';
|
|
9
|
+
import fs from 'fs/promises';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import { exec as execCallback } from 'child_process';
|
|
12
|
+
import { promisify } from 'util';
|
|
13
|
+
import inquirer from 'inquirer';
|
|
14
|
+
|
|
15
|
+
const execAsync = promisify(execCallback);
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// GITHUB CONFIGURATION
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
const GITHUB_CONFIG = {
|
|
22
|
+
// State file for tracking synced issues
|
|
23
|
+
stateFile: '.ultra-dex/github-sync.json',
|
|
24
|
+
|
|
25
|
+
// Label mappings
|
|
26
|
+
labelToAgent: {
|
|
27
|
+
'backend': '@Backend',
|
|
28
|
+
'frontend': '@Frontend',
|
|
29
|
+
'database': '@Database',
|
|
30
|
+
'auth': '@Auth',
|
|
31
|
+
'security': '@Security',
|
|
32
|
+
'testing': '@Testing',
|
|
33
|
+
'devops': '@DevOps',
|
|
34
|
+
'bug': '@Debugger',
|
|
35
|
+
'documentation': '@Documentation',
|
|
36
|
+
'performance': '@Performance',
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
// PR template
|
|
40
|
+
prTemplate: `## Summary
|
|
41
|
+
{summary}
|
|
42
|
+
|
|
43
|
+
## Changes
|
|
44
|
+
{changes}
|
|
45
|
+
|
|
46
|
+
## Testing
|
|
47
|
+
{testing}
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
š¤ Generated by [Ultra-Dex](https://github.com/Srujan0798/Ultra-Dex) Agent Swarm
|
|
51
|
+
`,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// ============================================================================
|
|
55
|
+
// GITHUB CLI UTILITIES
|
|
56
|
+
// ============================================================================
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Check if GitHub CLI is installed and authenticated
|
|
60
|
+
*/
|
|
61
|
+
async function checkGitHubCLI() {
|
|
62
|
+
try {
|
|
63
|
+
await execAsync('gh --version');
|
|
64
|
+
const { stdout } = await execAsync('gh auth status 2>&1');
|
|
65
|
+
return { installed: true, authenticated: stdout.includes('Logged in') };
|
|
66
|
+
} catch (err) {
|
|
67
|
+
if (err.message.includes('not found')) {
|
|
68
|
+
return { installed: false, authenticated: false };
|
|
69
|
+
}
|
|
70
|
+
// gh auth status returns non-zero if not authenticated
|
|
71
|
+
return { installed: true, authenticated: false };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get current repository info
|
|
77
|
+
*/
|
|
78
|
+
async function getRepoInfo() {
|
|
79
|
+
try {
|
|
80
|
+
const { stdout } = await execAsync('gh repo view --json owner,name,url');
|
|
81
|
+
return JSON.parse(stdout);
|
|
82
|
+
} catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* List open issues
|
|
89
|
+
*/
|
|
90
|
+
async function listIssues(options = {}) {
|
|
91
|
+
const { limit = 20, labels = [], state = 'open' } = options;
|
|
92
|
+
|
|
93
|
+
let cmd = `gh issue list --state ${state} --limit ${limit} --json number,title,labels,body,assignees,createdAt`;
|
|
94
|
+
|
|
95
|
+
if (labels.length > 0) {
|
|
96
|
+
cmd += ` --label "${labels.join(',')}"`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const { stdout } = await execAsync(cmd);
|
|
100
|
+
return JSON.parse(stdout);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Create a new issue
|
|
105
|
+
*/
|
|
106
|
+
async function createIssue(title, body, options = {}) {
|
|
107
|
+
const { labels = [], assignees = [] } = options;
|
|
108
|
+
|
|
109
|
+
let cmd = `gh issue create --title "${title.replace(/"/g, '\\"')}" --body "${body.replace(/"/g, '\\"')}"`;
|
|
110
|
+
|
|
111
|
+
if (labels.length > 0) {
|
|
112
|
+
cmd += ` --label "${labels.join(',')}"`;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (assignees.length > 0) {
|
|
116
|
+
cmd += ` --assignee "${assignees.join(',')}"`;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const { stdout } = await execAsync(cmd);
|
|
120
|
+
return stdout.trim();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Create a pull request
|
|
125
|
+
*/
|
|
126
|
+
async function createPullRequest(title, body, options = {}) {
|
|
127
|
+
const { base = 'main', head, draft = false } = options;
|
|
128
|
+
|
|
129
|
+
let cmd = `gh pr create --title "${title.replace(/"/g, '\\"')}" --body "${body.replace(/"/g, '\\"')}" --base ${base}`;
|
|
130
|
+
|
|
131
|
+
if (head) {
|
|
132
|
+
cmd += ` --head ${head}`;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (draft) {
|
|
136
|
+
cmd += ' --draft';
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const { stdout } = await execAsync(cmd);
|
|
140
|
+
return stdout.trim();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Get PR status
|
|
145
|
+
*/
|
|
146
|
+
async function getPRStatus(prNumber) {
|
|
147
|
+
const { stdout } = await execAsync(`gh pr view ${prNumber} --json state,mergeable,reviews,statusCheckRollup`);
|
|
148
|
+
return JSON.parse(stdout);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* List PRs
|
|
153
|
+
*/
|
|
154
|
+
async function listPRs(options = {}) {
|
|
155
|
+
const { state = 'open', limit = 10 } = options;
|
|
156
|
+
|
|
157
|
+
const { stdout } = await execAsync(`gh pr list --state ${state} --limit ${limit} --json number,title,headRefName,state,createdAt`);
|
|
158
|
+
return JSON.parse(stdout);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ============================================================================
|
|
162
|
+
// ISSUE ā TASK CONVERSION
|
|
163
|
+
// ============================================================================
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Convert GitHub issue to Ultra-Dex task format
|
|
167
|
+
*/
|
|
168
|
+
function issueToTask(issue) {
|
|
169
|
+
// Detect agent from labels
|
|
170
|
+
let agent = '@Planner'; // Default
|
|
171
|
+
for (const label of issue.labels || []) {
|
|
172
|
+
const labelName = label.name?.toLowerCase() || label.toLowerCase();
|
|
173
|
+
if (GITHUB_CONFIG.labelToAgent[labelName]) {
|
|
174
|
+
agent = GITHUB_CONFIG.labelToAgent[labelName];
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
id: `gh-${issue.number}`,
|
|
181
|
+
source: 'github',
|
|
182
|
+
issueNumber: issue.number,
|
|
183
|
+
title: issue.title,
|
|
184
|
+
description: issue.body || '',
|
|
185
|
+
agent,
|
|
186
|
+
labels: (issue.labels || []).map(l => l.name || l),
|
|
187
|
+
createdAt: issue.createdAt,
|
|
188
|
+
status: 'pending',
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Sync issues to local task file
|
|
194
|
+
*/
|
|
195
|
+
async function syncIssuesToTasks(workdir = process.cwd()) {
|
|
196
|
+
const stateFile = path.join(workdir, GITHUB_CONFIG.stateFile);
|
|
197
|
+
|
|
198
|
+
// Load existing state
|
|
199
|
+
let state = { syncedIssues: {}, lastSync: null };
|
|
200
|
+
try {
|
|
201
|
+
state = JSON.parse(await fs.readFile(stateFile, 'utf8'));
|
|
202
|
+
} catch {
|
|
203
|
+
// No existing state
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Fetch open issues
|
|
207
|
+
const issues = await listIssues({ limit: 50 });
|
|
208
|
+
|
|
209
|
+
// Convert to tasks
|
|
210
|
+
const tasks = issues.map(issueToTask);
|
|
211
|
+
|
|
212
|
+
// Track which issues we've synced
|
|
213
|
+
const newTasks = [];
|
|
214
|
+
for (const task of tasks) {
|
|
215
|
+
if (!state.syncedIssues[task.id]) {
|
|
216
|
+
newTasks.push(task);
|
|
217
|
+
state.syncedIssues[task.id] = {
|
|
218
|
+
syncedAt: new Date().toISOString(),
|
|
219
|
+
issueNumber: task.issueNumber,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Save state
|
|
225
|
+
state.lastSync = new Date().toISOString();
|
|
226
|
+
await fs.mkdir(path.dirname(stateFile), { recursive: true });
|
|
227
|
+
await fs.writeFile(stateFile, JSON.stringify(state, null, 2));
|
|
228
|
+
|
|
229
|
+
return { all: tasks, new: newTasks };
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ============================================================================
|
|
233
|
+
// AUTO-PR CREATION
|
|
234
|
+
// ============================================================================
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Create PR from swarm output
|
|
238
|
+
*/
|
|
239
|
+
async function createPRFromSwarm(swarmResult, options = {}) {
|
|
240
|
+
const { branch = null, title = null, draft = true } = options;
|
|
241
|
+
|
|
242
|
+
// Generate branch name
|
|
243
|
+
const branchName = branch || `ultra-dex/${Date.now()}`;
|
|
244
|
+
|
|
245
|
+
// Create branch
|
|
246
|
+
await execAsync(`git checkout -b ${branchName}`);
|
|
247
|
+
|
|
248
|
+
// Stage all changes
|
|
249
|
+
await execAsync('git add -A');
|
|
250
|
+
|
|
251
|
+
// Commit
|
|
252
|
+
const commitMsg = swarmResult.goal || 'Ultra-Dex agent swarm implementation';
|
|
253
|
+
await execAsync(`git commit -m "${commitMsg}"`);
|
|
254
|
+
|
|
255
|
+
// Push
|
|
256
|
+
await execAsync(`git push -u origin ${branchName}`);
|
|
257
|
+
|
|
258
|
+
// Generate PR body
|
|
259
|
+
const prBody = GITHUB_CONFIG.prTemplate
|
|
260
|
+
.replace('{summary}', swarmResult.goal || 'Automated implementation')
|
|
261
|
+
.replace('{changes}', swarmResult.artifacts?.join('\n- ') || 'See commits for details')
|
|
262
|
+
.replace('{testing}', '- [ ] Manual testing\n- [ ] Automated tests pass');
|
|
263
|
+
|
|
264
|
+
// Create PR
|
|
265
|
+
const prTitle = title || `š¤ ${commitMsg}`;
|
|
266
|
+
const prUrl = await createPullRequest(prTitle, prBody, { head: branchName, draft });
|
|
267
|
+
|
|
268
|
+
return { branch: branchName, prUrl };
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// ============================================================================
|
|
272
|
+
// WEBHOOK HANDLER (for CI integration)
|
|
273
|
+
// ============================================================================
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Parse GitHub webhook payload
|
|
277
|
+
*/
|
|
278
|
+
function parseWebhook(payload) {
|
|
279
|
+
if (payload.action === 'opened' && payload.issue) {
|
|
280
|
+
return {
|
|
281
|
+
type: 'issue_opened',
|
|
282
|
+
issue: issueToTask(payload.issue),
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (payload.action === 'completed' && payload.workflow_run) {
|
|
287
|
+
return {
|
|
288
|
+
type: 'workflow_completed',
|
|
289
|
+
workflow: payload.workflow_run,
|
|
290
|
+
success: payload.workflow_run.conclusion === 'success',
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (payload.action === 'submitted' && payload.review) {
|
|
295
|
+
return {
|
|
296
|
+
type: 'pr_review',
|
|
297
|
+
pr: payload.pull_request,
|
|
298
|
+
review: payload.review,
|
|
299
|
+
approved: payload.review.state === 'approved',
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return { type: 'unknown', payload };
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// ============================================================================
|
|
307
|
+
// CLI COMMAND
|
|
308
|
+
// ============================================================================
|
|
309
|
+
|
|
310
|
+
export function registerGitHubCommand(program) {
|
|
311
|
+
program
|
|
312
|
+
.command('github')
|
|
313
|
+
.description('GitHub integration for issues, PRs, and CI/CD')
|
|
314
|
+
.option('--sync', 'Sync GitHub issues to local tasks')
|
|
315
|
+
.option('--issues', 'List open issues')
|
|
316
|
+
.option('--prs', 'List open pull requests')
|
|
317
|
+
.option('--create-issue <title>', 'Create a new issue')
|
|
318
|
+
.option('--create-pr', 'Create PR from current changes')
|
|
319
|
+
.option('--status', 'Check GitHub CLI status')
|
|
320
|
+
.option('--labels <labels>', 'Filter by labels (comma-separated)')
|
|
321
|
+
.option('--draft', 'Create PR as draft')
|
|
322
|
+
.action(async (options) => {
|
|
323
|
+
console.log(chalk.cyan('\nš Ultra-Dex GitHub Integration\n'));
|
|
324
|
+
|
|
325
|
+
// Check GitHub CLI
|
|
326
|
+
const spinner = ora('Checking GitHub CLI...').start();
|
|
327
|
+
const ghStatus = await checkGitHubCLI();
|
|
328
|
+
|
|
329
|
+
if (!ghStatus.installed) {
|
|
330
|
+
spinner.fail('GitHub CLI (gh) not installed');
|
|
331
|
+
console.log(chalk.yellow('\nInstall: https://cli.github.com/'));
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (!ghStatus.authenticated) {
|
|
336
|
+
spinner.fail('Not authenticated with GitHub');
|
|
337
|
+
console.log(chalk.yellow('\nRun: gh auth login'));
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
spinner.succeed('GitHub CLI ready');
|
|
342
|
+
|
|
343
|
+
// Get repo info
|
|
344
|
+
const repo = await getRepoInfo();
|
|
345
|
+
if (!repo) {
|
|
346
|
+
console.log(chalk.yellow('\nā ļø Not in a GitHub repository'));
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
console.log(chalk.gray(`Repository: ${repo.owner.login}/${repo.name}\n`));
|
|
351
|
+
|
|
352
|
+
try {
|
|
353
|
+
if (options.status) {
|
|
354
|
+
// Just show status (already done above)
|
|
355
|
+
console.log(chalk.green('ā
GitHub integration active'));
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (options.issues) {
|
|
360
|
+
// List issues
|
|
361
|
+
spinner.start('Fetching issues...');
|
|
362
|
+
const labelFilter = options.labels?.split(',') || [];
|
|
363
|
+
const issues = await listIssues({ labels: labelFilter });
|
|
364
|
+
spinner.succeed(`Found ${issues.length} open issues\n`);
|
|
365
|
+
|
|
366
|
+
if (issues.length === 0) {
|
|
367
|
+
console.log(chalk.gray('No open issues found.'));
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
for (const issue of issues) {
|
|
372
|
+
const labels = (issue.labels || []).map(l => chalk.cyan(`[${l.name}]`)).join(' ');
|
|
373
|
+
console.log(`#${chalk.bold(issue.number)} ${issue.title} ${labels}`);
|
|
374
|
+
}
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (options.prs) {
|
|
379
|
+
// List PRs
|
|
380
|
+
spinner.start('Fetching pull requests...');
|
|
381
|
+
const prs = await listPRs();
|
|
382
|
+
spinner.succeed(`Found ${prs.length} open PRs\n`);
|
|
383
|
+
|
|
384
|
+
for (const pr of prs) {
|
|
385
|
+
console.log(`#${chalk.bold(pr.number)} ${pr.title} ${chalk.gray(`(${pr.headRefName})`)}`);
|
|
386
|
+
}
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (options.sync) {
|
|
391
|
+
// Sync issues to tasks
|
|
392
|
+
spinner.start('Syncing issues to tasks...');
|
|
393
|
+
const result = await syncIssuesToTasks();
|
|
394
|
+
spinner.succeed(`Synced ${result.all.length} issues (${result.new.length} new)\n`);
|
|
395
|
+
|
|
396
|
+
if (result.new.length > 0) {
|
|
397
|
+
console.log(chalk.bold('New tasks:'));
|
|
398
|
+
for (const task of result.new) {
|
|
399
|
+
console.log(` ${task.agent} #${task.issueNumber}: ${task.title}`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (options.createIssue) {
|
|
406
|
+
// Create issue
|
|
407
|
+
const { body } = await inquirer.prompt([{
|
|
408
|
+
type: 'editor',
|
|
409
|
+
name: 'body',
|
|
410
|
+
message: 'Issue description:',
|
|
411
|
+
}]);
|
|
412
|
+
|
|
413
|
+
spinner.start('Creating issue...');
|
|
414
|
+
const url = await createIssue(options.createIssue, body);
|
|
415
|
+
spinner.succeed(`Issue created: ${url}`);
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
if (options.createPr) {
|
|
420
|
+
// Create PR from current changes
|
|
421
|
+
const { title, description } = await inquirer.prompt([
|
|
422
|
+
{ type: 'input', name: 'title', message: 'PR title:' },
|
|
423
|
+
{ type: 'editor', name: 'description', message: 'PR description:' },
|
|
424
|
+
]);
|
|
425
|
+
|
|
426
|
+
spinner.start('Creating pull request...');
|
|
427
|
+
|
|
428
|
+
const prBody = GITHUB_CONFIG.prTemplate
|
|
429
|
+
.replace('{summary}', description)
|
|
430
|
+
.replace('{changes}', 'See commits for details')
|
|
431
|
+
.replace('{testing}', '- [ ] Tests pass\n- [ ] Manual testing');
|
|
432
|
+
|
|
433
|
+
const url = await createPullRequest(title, prBody, { draft: options.draft });
|
|
434
|
+
spinner.succeed(`Pull request created: ${url}`);
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Default: show menu
|
|
439
|
+
const { action } = await inquirer.prompt([{
|
|
440
|
+
type: 'list',
|
|
441
|
+
name: 'action',
|
|
442
|
+
message: 'What would you like to do?',
|
|
443
|
+
choices: [
|
|
444
|
+
{ name: 'š List open issues', value: 'issues' },
|
|
445
|
+
{ name: 'š List open PRs', value: 'prs' },
|
|
446
|
+
{ name: 'š Sync issues to tasks', value: 'sync' },
|
|
447
|
+
{ name: 'ā Create new issue', value: 'create-issue' },
|
|
448
|
+
{ name: 'š Create PR from changes', value: 'create-pr' },
|
|
449
|
+
{ name: 'ā Cancel', value: 'cancel' },
|
|
450
|
+
],
|
|
451
|
+
}]);
|
|
452
|
+
|
|
453
|
+
// Recurse with selected action
|
|
454
|
+
if (action !== 'cancel') {
|
|
455
|
+
const newOptions = { ...options, [action.replace('-', '')]: true };
|
|
456
|
+
await registerGitHubCommand(program).action(newOptions);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
} catch (err) {
|
|
460
|
+
spinner.fail(`Failed: ${err.message}`);
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
export default {
|
|
466
|
+
registerGitHubCommand,
|
|
467
|
+
checkGitHubCLI,
|
|
468
|
+
listIssues,
|
|
469
|
+
listPRs,
|
|
470
|
+
createIssue,
|
|
471
|
+
createPullRequest,
|
|
472
|
+
createPRFromSwarm,
|
|
473
|
+
syncIssuesToTasks,
|
|
474
|
+
parseWebhook,
|
|
475
|
+
};
|