jira-pilot 2.0.2 → 2.0.3
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 +1 -1
- package/package.json +2 -2
- package/src/commands/ai-actions/plan.js +2 -2
- package/src/commands/ai-actions/review.js +2 -9
- package/src/commands/ai-actions/standup.js +2 -2
- package/src/commands/ai.js +4 -24
- package/src/commands/git.js +2 -6
- package/src/commands/issue.js +6 -66
- package/src/commands/mcp.js +9 -2
- package/src/commands/project.js +2 -2
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jira-pilot",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "AI-powered Jira CLI for humans and agents — manage issues, sprints, boards with interactive wizards, multi-provider AI (OpenAI/Gemini/Anthropic), and an 8-tool MCP server for AI assistants",
|
|
3
|
+
"version": "2.0.3",
|
|
4
|
+
"description": "AI-powered Jira CLI and MCP server for humans and agents — manage issues, sprints, boards with interactive wizards, multi-provider AI (OpenAI/Gemini/Anthropic), and an 8-tool MCP server for AI assistants",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -5,6 +5,7 @@ import { api } from '../../services/api-service.js';
|
|
|
5
5
|
import { aiService } from '../../services/ai-service.js';
|
|
6
6
|
import { validateIssueKey } from '../../utils/validators.js';
|
|
7
7
|
import { parseADF } from '../../utils/adf-parser.js';
|
|
8
|
+
import { handleCommandError } from '../../utils/error-handler.js';
|
|
8
9
|
|
|
9
10
|
export async function planAction(epicKey, options) {
|
|
10
11
|
const check = validateIssueKey(epicKey);
|
|
@@ -113,7 +114,6 @@ export async function planAction(epicKey, options) {
|
|
|
113
114
|
console.log(chalk.green(`\nDone! Created ${results.length} issues linked to ${epicKey}.`));
|
|
114
115
|
|
|
115
116
|
} catch (e) {
|
|
116
|
-
spinner
|
|
117
|
-
console.error(chalk.red(`Error: ${e.message}`));
|
|
117
|
+
handleCommandError(spinner, e, `Failed to plan ${epicKey}`);
|
|
118
118
|
}
|
|
119
119
|
}
|
|
@@ -7,6 +7,7 @@ import { aiService } from '../../services/ai-service.js';
|
|
|
7
7
|
import { validateIssueKey } from '../../utils/validators.js';
|
|
8
8
|
import { getCredentials } from '../../utils/config.js';
|
|
9
9
|
import { parseADF } from '../../utils/adf-parser.js';
|
|
10
|
+
import { handleCommandError } from '../../utils/error-handler.js';
|
|
10
11
|
|
|
11
12
|
export async function reviewAction(issueKey, options) {
|
|
12
13
|
const check = validateIssueKey(issueKey);
|
|
@@ -96,14 +97,6 @@ export async function reviewAction(issueKey, options) {
|
|
|
96
97
|
console.log(chalk.dim(`\nPR Link: ${pr.html_url}`));
|
|
97
98
|
|
|
98
99
|
} catch (e) {
|
|
99
|
-
spinner
|
|
100
|
-
if (e.response?.status === 404) {
|
|
101
|
-
console.error(chalk.red(`Resource not found (Issue or Repo). Check permissions.`));
|
|
102
|
-
} else if (e.response?.status === 401) {
|
|
103
|
-
console.error(chalk.red(`GitHub/Jira Authentication failed. Check your tokens.`));
|
|
104
|
-
} else {
|
|
105
|
-
console.error(chalk.red(`Error: ${e.message}`));
|
|
106
|
-
if (e.response?.data) console.error(chalk.dim(JSON.stringify(e.response.data)));
|
|
107
|
-
}
|
|
100
|
+
handleCommandError(spinner, e, `Failed to review ${issueKey}`);
|
|
108
101
|
}
|
|
109
102
|
}
|
|
@@ -3,6 +3,7 @@ import ora from 'ora';
|
|
|
3
3
|
import { api } from '../../services/api-service.js';
|
|
4
4
|
import { aiService } from '../../services/ai-service.js';
|
|
5
5
|
import { parseADF } from '../../utils/adf-parser.js';
|
|
6
|
+
import { handleCommandError } from '../../utils/error-handler.js';
|
|
6
7
|
|
|
7
8
|
export async function standupAction(options) {
|
|
8
9
|
const spinner = ora('Analyzing your recent activity...').start();
|
|
@@ -36,7 +37,6 @@ export async function standupAction(options) {
|
|
|
36
37
|
console.log(report);
|
|
37
38
|
|
|
38
39
|
} catch (e) {
|
|
39
|
-
spinner
|
|
40
|
-
console.error(chalk.red(`Error: ${e.message}`));
|
|
40
|
+
handleCommandError(spinner, e, 'Failed to generate standup');
|
|
41
41
|
}
|
|
42
42
|
}
|
package/src/commands/ai.js
CHANGED
|
@@ -6,6 +6,7 @@ import { api } from '../services/api-service.js';
|
|
|
6
6
|
import { aiService } from '../services/ai-service.js';
|
|
7
7
|
import { parseADF } from '../utils/adf-parser.js';
|
|
8
8
|
import { validateIssueKey } from '../utils/validators.js';
|
|
9
|
+
import { handleCommandError } from '../utils/error-handler.js';
|
|
9
10
|
import { reviewAction } from './ai-actions/review.js';
|
|
10
11
|
import { planAction } from './ai-actions/plan.js';
|
|
11
12
|
import { standupAction } from './ai-actions/standup.js';
|
|
@@ -60,17 +61,7 @@ Provide a concise summary of the current status, key discussion points, and next
|
|
|
60
61
|
console.log(aiResponse);
|
|
61
62
|
|
|
62
63
|
} catch (e) {
|
|
63
|
-
spinner
|
|
64
|
-
if (e.response && e.response.config && e.response.config.url.includes('/issue/')) {
|
|
65
|
-
console.error(chalk.red(`\nError: Issue "${issueKey}" not found.`));
|
|
66
|
-
} else {
|
|
67
|
-
console.error(chalk.red('\nFailed to generate summary:'));
|
|
68
|
-
if (e.response) {
|
|
69
|
-
console.error(chalk.red(`API Error ${e.response.status}: `), e.response.data);
|
|
70
|
-
} else {
|
|
71
|
-
console.error(chalk.red(e.message));
|
|
72
|
-
}
|
|
73
|
-
}
|
|
64
|
+
handleCommandError(spinner, e, `Failed to summarize ${issueKey}`);
|
|
74
65
|
}
|
|
75
66
|
});
|
|
76
67
|
|
|
@@ -132,12 +123,7 @@ Keep it professional and concise. Output in plain text (not markdown headers, us
|
|
|
132
123
|
console.log(chalk.grey('\nTip: Copy this into "jira issue create" or use it as a starting point.'));
|
|
133
124
|
|
|
134
125
|
} catch (e) {
|
|
135
|
-
|
|
136
|
-
console.log(chalk.yellow('\nCancelled.'));
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
console.error(chalk.red('\nFailed to generate draft:'));
|
|
140
|
-
console.error(chalk.red(e.message));
|
|
126
|
+
handleCommandError(null, e, 'Failed to generate draft');
|
|
141
127
|
}
|
|
142
128
|
});
|
|
143
129
|
|
|
@@ -198,13 +184,7 @@ Keep suggestions actionable and concise.
|
|
|
198
184
|
console.log(aiResponse);
|
|
199
185
|
|
|
200
186
|
} catch (e) {
|
|
201
|
-
spinner
|
|
202
|
-
if (e.response && e.response.status === 404) {
|
|
203
|
-
console.error(chalk.red(`\nError: Issue "${issueKey}" not found.`));
|
|
204
|
-
} else {
|
|
205
|
-
console.error(chalk.red('\nFailed to generate suggestions:'));
|
|
206
|
-
console.error(chalk.red(e.message));
|
|
207
|
-
}
|
|
187
|
+
handleCommandError(spinner, e, `Failed to suggest for ${issueKey}`);
|
|
208
188
|
}
|
|
209
189
|
});
|
|
210
190
|
|
package/src/commands/git.js
CHANGED
|
@@ -5,6 +5,7 @@ import { api } from '../services/api-service.js';
|
|
|
5
5
|
import ora from 'ora';
|
|
6
6
|
import enquirer from 'enquirer';
|
|
7
7
|
import { validateIssueKey } from '../utils/validators.js';
|
|
8
|
+
import { handleCommandError } from '../utils/error-handler.js';
|
|
8
9
|
|
|
9
10
|
export function registerGitCommand(program) {
|
|
10
11
|
const gitCmd = new Command('git')
|
|
@@ -50,12 +51,7 @@ export function registerGitCommand(program) {
|
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
} catch (e) {
|
|
53
|
-
spinner
|
|
54
|
-
if (e.response) {
|
|
55
|
-
console.error(chalk.red(`Error ${e.response.status}: `), e.response.data);
|
|
56
|
-
} else {
|
|
57
|
-
console.error(chalk.red(e.message));
|
|
58
|
-
}
|
|
54
|
+
handleCommandError(spinner, e, 'Failed to create branch');
|
|
59
55
|
}
|
|
60
56
|
});
|
|
61
57
|
|
package/src/commands/issue.js
CHANGED
|
@@ -146,12 +146,7 @@ Examples:
|
|
|
146
146
|
console.log(table(tableData));
|
|
147
147
|
|
|
148
148
|
} catch (e) {
|
|
149
|
-
spinner
|
|
150
|
-
if (e.response) {
|
|
151
|
-
console.error(chalk.red(`Error ${e.response.status}: `), e.response.data);
|
|
152
|
-
} else {
|
|
153
|
-
console.error(chalk.red(e.message));
|
|
154
|
-
}
|
|
149
|
+
handleCommandError(spinner, e, 'Failed to list issues');
|
|
155
150
|
}
|
|
156
151
|
});
|
|
157
152
|
|
|
@@ -202,16 +197,7 @@ Examples:
|
|
|
202
197
|
}
|
|
203
198
|
console.log('');
|
|
204
199
|
} catch (e) {
|
|
205
|
-
spinner
|
|
206
|
-
if (e.response) {
|
|
207
|
-
if (e.response.status === 404) {
|
|
208
|
-
console.error(chalk.red(`Issue "${issueKey}" not found.`));
|
|
209
|
-
} else {
|
|
210
|
-
console.error(chalk.red(`Error ${e.response.status}: `), e.response.data);
|
|
211
|
-
}
|
|
212
|
-
} else {
|
|
213
|
-
console.error(chalk.red(e.message));
|
|
214
|
-
}
|
|
200
|
+
handleCommandError(spinner, e, 'Failed to fetch issue');
|
|
215
201
|
}
|
|
216
202
|
});
|
|
217
203
|
|
|
@@ -481,17 +467,7 @@ Examples:
|
|
|
481
467
|
console.log(chalk.grey(`View it: jira issue view ${result.key}`));
|
|
482
468
|
|
|
483
469
|
} catch (e) {
|
|
484
|
-
|
|
485
|
-
// User cancelled prompt (Ctrl+C)
|
|
486
|
-
console.log(chalk.yellow('\nCancelled.'));
|
|
487
|
-
return;
|
|
488
|
-
}
|
|
489
|
-
console.error(chalk.red('\nFailed to create issue:'));
|
|
490
|
-
if (e.response) {
|
|
491
|
-
console.error(chalk.red(`Error ${e.response.status}: `), JSON.stringify(e.response.data, null, 2));
|
|
492
|
-
} else {
|
|
493
|
-
console.error(chalk.red(e.message));
|
|
494
|
-
}
|
|
470
|
+
handleCommandError(spinner, e, 'Failed to create issue');
|
|
495
471
|
}
|
|
496
472
|
});
|
|
497
473
|
|
|
@@ -570,21 +546,7 @@ Examples:
|
|
|
570
546
|
execSpinner.succeed(chalk.green(`${issueKey} transitioned: ${currentStatus} → ${chalk.bold(targetTransition.to.name)}`));
|
|
571
547
|
|
|
572
548
|
} catch (e) {
|
|
573
|
-
spinner
|
|
574
|
-
if (e === '' || e.message === '') {
|
|
575
|
-
console.log(chalk.yellow('\nCancelled.'));
|
|
576
|
-
return;
|
|
577
|
-
}
|
|
578
|
-
console.error(chalk.red('\nFailed to transition issue:'));
|
|
579
|
-
if (e.response) {
|
|
580
|
-
if (e.response.status === 404) {
|
|
581
|
-
console.error(chalk.red(`Issue "${issueKey}" not found.`));
|
|
582
|
-
} else {
|
|
583
|
-
console.error(chalk.red(`Error ${e.response.status}: `), e.response.data);
|
|
584
|
-
}
|
|
585
|
-
} else {
|
|
586
|
-
console.error(chalk.red(e.message));
|
|
587
|
-
}
|
|
549
|
+
handleCommandError(spinner, e, 'Failed to transition issue');
|
|
588
550
|
}
|
|
589
551
|
});
|
|
590
552
|
// ── ASSIGN ────────────────────────────────────────────────────────
|
|
@@ -672,16 +634,7 @@ Examples:
|
|
|
672
634
|
spinner.succeed(chalk.green(`${issueKey} ${assigneeId === 'none' ? 'unassigned' : 'assigned'} successfully.`));
|
|
673
635
|
|
|
674
636
|
} catch (e) {
|
|
675
|
-
|
|
676
|
-
console.log(chalk.yellow('\nCancelled.'));
|
|
677
|
-
return;
|
|
678
|
-
}
|
|
679
|
-
console.error(chalk.red('\nFailed to assign issue:'));
|
|
680
|
-
if (e.response) {
|
|
681
|
-
console.error(chalk.red(`Error ${e.response.status}: `), e.response.data);
|
|
682
|
-
} else {
|
|
683
|
-
console.error(chalk.red(e.message));
|
|
684
|
-
}
|
|
637
|
+
handleCommandError(spinner, e, 'Failed to assign issue');
|
|
685
638
|
}
|
|
686
639
|
});
|
|
687
640
|
|
|
@@ -727,20 +680,7 @@ Examples:
|
|
|
727
680
|
spinner.succeed(chalk.green(`Comment added to ${issueKey}.`));
|
|
728
681
|
|
|
729
682
|
} catch (e) {
|
|
730
|
-
|
|
731
|
-
console.log(chalk.yellow('\nCancelled.'));
|
|
732
|
-
return;
|
|
733
|
-
}
|
|
734
|
-
console.error(chalk.red('\nFailed to add comment:'));
|
|
735
|
-
if (e.response) {
|
|
736
|
-
if (e.response.status === 404) {
|
|
737
|
-
console.error(chalk.red(`Issue "${issueKey}" not found.`));
|
|
738
|
-
} else {
|
|
739
|
-
console.error(chalk.red(`Error ${e.response.status}: `), e.response.data);
|
|
740
|
-
}
|
|
741
|
-
} else {
|
|
742
|
-
console.error(chalk.red(e.message));
|
|
743
|
-
}
|
|
683
|
+
handleCommandError(spinner, e, 'Failed to add comment');
|
|
744
684
|
}
|
|
745
685
|
});
|
|
746
686
|
|
package/src/commands/mcp.js
CHANGED
|
@@ -6,8 +6,15 @@ export function registerMcpCommand(program) {
|
|
|
6
6
|
const mcpCmd = new Command('mcp')
|
|
7
7
|
.description('Start MCP Agent Server (Stdio)')
|
|
8
8
|
.action(async () => {
|
|
9
|
-
// MCP server uses stdio
|
|
10
|
-
//
|
|
9
|
+
// MCP server uses stdio for communication.
|
|
10
|
+
// If run directly in a TTY (terminal), warn the user.
|
|
11
|
+
if (process.stdin.isTTY) {
|
|
12
|
+
console.error(chalk.blue('ℹ Jira MCP Server is running...'));
|
|
13
|
+
console.error(chalk.grey(' This command is designed for AI Agents (Claude, Cursor, etc).'));
|
|
14
|
+
console.error(chalk.grey(' It communicates via JSON-RPC on stdin/stdout.'));
|
|
15
|
+
console.error(chalk.grey(' Press Ctrl+C to stop.'));
|
|
16
|
+
}
|
|
17
|
+
|
|
11
18
|
try {
|
|
12
19
|
await startServer();
|
|
13
20
|
} catch (e) {
|
package/src/commands/project.js
CHANGED
|
@@ -3,6 +3,7 @@ import chalk from 'chalk';
|
|
|
3
3
|
import { table } from 'table';
|
|
4
4
|
import { api } from '../services/api-service.js';
|
|
5
5
|
import ora from 'ora';
|
|
6
|
+
import { handleCommandError } from '../utils/error-handler.js';
|
|
6
7
|
|
|
7
8
|
export function registerProjectCommand(program) {
|
|
8
9
|
const projectCmd = new Command('project')
|
|
@@ -50,8 +51,7 @@ Common Actions:
|
|
|
50
51
|
|
|
51
52
|
console.log(table(tableData));
|
|
52
53
|
} catch (e) {
|
|
53
|
-
spinner
|
|
54
|
-
console.error(e.message);
|
|
54
|
+
handleCommandError(spinner, e, 'Failed to list projects');
|
|
55
55
|
}
|
|
56
56
|
});
|
|
57
57
|
|