jira-pilot 2.1.2 → 2.2.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 +54 -0
- package/bin/jira.ts +2 -0
- package/dist/bin/jira.js +2 -0
- package/dist/bin/jira.js.map +1 -1
- package/dist/src/commands/ai-actions/plan.js +1 -1
- package/dist/src/commands/ai-actions/plan.js.map +1 -1
- package/dist/src/commands/ai-actions/review.js +5 -4
- package/dist/src/commands/ai-actions/review.js.map +1 -1
- package/dist/src/commands/ai-actions/standup.js +1 -1
- package/dist/src/commands/ai-actions/standup.js.map +1 -1
- package/dist/src/commands/ai.js +1 -1
- package/dist/src/commands/ai.js.map +1 -1
- package/dist/src/commands/board.js +10 -5
- package/dist/src/commands/board.js.map +1 -1
- package/dist/src/commands/bulk.js +11 -10
- package/dist/src/commands/bulk.js.map +1 -1
- package/dist/src/commands/config.js +1 -1
- package/dist/src/commands/config.js.map +1 -1
- package/dist/src/commands/dashboard.js +19 -12
- package/dist/src/commands/dashboard.js.map +1 -1
- package/dist/src/commands/filter.js +7 -4
- package/dist/src/commands/filter.js.map +1 -1
- package/dist/src/commands/git.js +1 -1
- package/dist/src/commands/git.js.map +1 -1
- package/dist/src/commands/issue-attach.js +1 -1
- package/dist/src/commands/issue-attach.js.map +1 -1
- package/dist/src/commands/issue-pr.js +1 -1
- package/dist/src/commands/issue-pr.js.map +1 -1
- package/dist/src/commands/issue-worklog.js +10 -5
- package/dist/src/commands/issue-worklog.js.map +1 -1
- package/dist/src/commands/issue.js +173 -122
- package/dist/src/commands/issue.js.map +1 -1
- package/dist/src/commands/project.js +10 -5
- package/dist/src/commands/project.js.map +1 -1
- package/dist/src/commands/sprint.js +19 -8
- package/dist/src/commands/sprint.js.map +1 -1
- package/dist/src/commands/tui.d.ts +2 -0
- package/dist/src/commands/tui.js +10 -0
- package/dist/src/commands/tui.js.map +1 -0
- package/dist/src/server/mcp-server.js +209 -27
- package/dist/src/server/mcp-server.js.map +1 -1
- package/dist/src/services/ai-service.js +7 -4
- package/dist/src/services/ai-service.js.map +1 -1
- package/dist/src/services/api-service.d.ts +2 -0
- package/dist/src/services/api-service.js +32 -20
- package/dist/src/services/api-service.js.map +1 -1
- package/dist/src/tui/App.d.ts +1 -0
- package/dist/src/tui/App.js +26 -0
- package/dist/src/tui/App.js.map +1 -0
- package/dist/src/tui/index.d.ts +1 -0
- package/dist/src/tui/index.js +8 -0
- package/dist/src/tui/index.js.map +1 -0
- package/dist/src/tui/screens/BoardList.d.ts +1 -0
- package/dist/src/tui/screens/BoardList.js +71 -0
- package/dist/src/tui/screens/BoardList.js.map +1 -0
- package/dist/src/tui/screens/Dashboard.d.ts +1 -0
- package/dist/src/tui/screens/Dashboard.js +41 -0
- package/dist/src/tui/screens/Dashboard.js.map +1 -0
- package/dist/src/tui/screens/IssueDetail.d.ts +6 -0
- package/dist/src/tui/screens/IssueDetail.js +40 -0
- package/dist/src/tui/screens/IssueDetail.js.map +1 -0
- package/dist/src/tui/screens/IssueList.d.ts +1 -0
- package/dist/src/tui/screens/IssueList.js +72 -0
- package/dist/src/tui/screens/IssueList.js.map +1 -0
- package/dist/src/tui/screens/KanbanBoard.d.ts +6 -0
- package/dist/src/tui/screens/KanbanBoard.js +86 -0
- package/dist/src/tui/screens/KanbanBoard.js.map +1 -0
- package/dist/src/tui/utils/adf-render.d.ts +1 -0
- package/dist/src/tui/utils/adf-render.js +29 -0
- package/dist/src/tui/utils/adf-render.js.map +1 -0
- package/dist/src/utils/api-paths.d.ts +31 -0
- package/dist/src/utils/api-paths.js +32 -0
- package/dist/src/utils/api-paths.js.map +1 -0
- package/dist/src/utils/error-handler.d.ts +2 -2
- package/dist/src/utils/error-handler.js.map +1 -1
- package/dist/src/utils/http.d.ts +27 -0
- package/dist/src/utils/http.js +95 -0
- package/dist/src/utils/http.js.map +1 -0
- package/dist/src/utils/spinner.d.ts +21 -0
- package/dist/src/utils/spinner.js +79 -0
- package/dist/src/utils/spinner.js.map +1 -0
- package/package.json +10 -5
- package/src/commands/ai-actions/plan.ts +1 -1
- package/src/commands/ai-actions/review.ts +5 -4
- package/src/commands/ai-actions/standup.ts +1 -1
- package/src/commands/ai.ts +1 -1
- package/src/commands/board.ts +10 -5
- package/src/commands/bulk.ts +11 -10
- package/src/commands/config.ts +1 -1
- package/src/commands/dashboard.ts +20 -12
- package/src/commands/filter.ts +8 -5
- package/src/commands/git.ts +1 -1
- package/src/commands/issue-attach.ts +1 -1
- package/src/commands/issue-pr.ts +1 -1
- package/src/commands/issue-worklog.ts +10 -5
- package/src/commands/issue.ts +181 -124
- package/src/commands/project.ts +10 -5
- package/src/commands/sprint.ts +19 -8
- package/src/commands/tui.ts +11 -0
- package/src/server/mcp-server.ts +234 -27
- package/src/services/ai-service.ts +7 -4
- package/src/services/api-service.ts +34 -21
- package/src/tui/App.tsx +61 -0
- package/src/tui/index.tsx +8 -0
- package/src/tui/screens/BoardList.tsx +102 -0
- package/src/tui/screens/Dashboard.tsx +75 -0
- package/src/tui/screens/IssueDetail.tsx +93 -0
- package/src/tui/screens/IssueList.tsx +116 -0
- package/src/tui/screens/KanbanBoard.tsx +133 -0
- package/src/tui/utils/adf-render.ts +30 -0
- package/src/utils/api-paths.ts +32 -0
- package/src/utils/error-handler.ts +2 -2
- package/src/utils/http.ts +128 -0
- package/src/utils/spinner.ts +87 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export declare const API: {
|
|
2
|
+
SEARCH: {
|
|
3
|
+
JQL: string;
|
|
4
|
+
};
|
|
5
|
+
ISSUE: {
|
|
6
|
+
BASE: string;
|
|
7
|
+
GET: (key: string) => string;
|
|
8
|
+
TRANSITIONS: (key: string) => string;
|
|
9
|
+
COMMENT: (key: string) => string;
|
|
10
|
+
ASSIGNEE: (key: string) => string;
|
|
11
|
+
WORKLOG: (key: string) => string;
|
|
12
|
+
ATTACHMENTS: (key: string) => string;
|
|
13
|
+
CREATEMETA: (projectKey: string) => string;
|
|
14
|
+
};
|
|
15
|
+
PROJECT: {
|
|
16
|
+
SEARCH: string;
|
|
17
|
+
GET: (key: string) => string;
|
|
18
|
+
COMPONENTS: (key: string) => string;
|
|
19
|
+
VERSIONS: (key: string) => string;
|
|
20
|
+
};
|
|
21
|
+
USER: {
|
|
22
|
+
MYSELF: string;
|
|
23
|
+
SEARCH: string;
|
|
24
|
+
};
|
|
25
|
+
PRIORITY: {
|
|
26
|
+
ALL: string;
|
|
27
|
+
};
|
|
28
|
+
SERVER: {
|
|
29
|
+
INFO: string;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export const API = {
|
|
2
|
+
SEARCH: {
|
|
3
|
+
JQL: '/search/jql',
|
|
4
|
+
},
|
|
5
|
+
ISSUE: {
|
|
6
|
+
BASE: '/issue',
|
|
7
|
+
GET: (key) => `/issue/${key}`,
|
|
8
|
+
TRANSITIONS: (key) => `/issue/${key}/transitions`,
|
|
9
|
+
COMMENT: (key) => `/issue/${key}/comment`,
|
|
10
|
+
ASSIGNEE: (key) => `/issue/${key}/assignee`,
|
|
11
|
+
WORKLOG: (key) => `/issue/${key}/worklog`,
|
|
12
|
+
ATTACHMENTS: (key) => `/issue/${key}/attachments`,
|
|
13
|
+
CREATEMETA: (projectKey) => `/issue/createmeta/${projectKey}/issuetypes`,
|
|
14
|
+
},
|
|
15
|
+
PROJECT: {
|
|
16
|
+
SEARCH: '/project/search',
|
|
17
|
+
GET: (key) => `/project/${key}`,
|
|
18
|
+
COMPONENTS: (key) => `/project/${key}/components`,
|
|
19
|
+
VERSIONS: (key) => `/project/${key}/versions`,
|
|
20
|
+
},
|
|
21
|
+
USER: {
|
|
22
|
+
MYSELF: '/myself',
|
|
23
|
+
SEARCH: '/user/search',
|
|
24
|
+
},
|
|
25
|
+
PRIORITY: {
|
|
26
|
+
ALL: '/priority',
|
|
27
|
+
},
|
|
28
|
+
SERVER: {
|
|
29
|
+
INFO: '/serverInfo',
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=api-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-paths.js","sourceRoot":"","sources":["../../../src/utils/api-paths.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,GAAG,GAAG;IACf,MAAM,EAAE;QACJ,GAAG,EAAE,aAAa;KACrB;IACD,KAAK,EAAE;QACH,IAAI,EAAE,QAAQ;QACd,GAAG,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,UAAU,GAAG,EAAE;QACrC,WAAW,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,UAAU,GAAG,cAAc;QACzD,OAAO,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,UAAU,GAAG,UAAU;QACjD,QAAQ,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,UAAU,GAAG,WAAW;QACnD,OAAO,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,UAAU,GAAG,UAAU;QACjD,WAAW,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,UAAU,GAAG,cAAc;QACzD,UAAU,EAAE,CAAC,UAAkB,EAAE,EAAE,CAAC,qBAAqB,UAAU,aAAa;KACnF;IACD,OAAO,EAAE;QACL,MAAM,EAAE,iBAAiB;QACzB,GAAG,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,YAAY,GAAG,EAAE;QACvC,UAAU,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,YAAY,GAAG,aAAa;QACzD,QAAQ,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,YAAY,GAAG,WAAW;KACxD;IACD,IAAI,EAAE;QACF,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,cAAc;KACzB;IACD,QAAQ,EAAE;QACN,GAAG,EAAE,WAAW;KACnB;IACD,MAAM,EAAE;QACJ,IAAI,EAAE,aAAa;KACtB;CACJ,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Spinner } from './spinner.js';
|
|
2
2
|
/**
|
|
3
3
|
* Standardized error handler for CLI commands.
|
|
4
4
|
* Stops the spinner and prints a formatted error message.
|
|
@@ -7,4 +7,4 @@ import { Ora } from 'ora';
|
|
|
7
7
|
* @param {Error} error - The error object
|
|
8
8
|
* @param {string} [context] - Optional context (e.g., "Failed to list issues")
|
|
9
9
|
*/
|
|
10
|
-
export declare function handleCommandError(spinner:
|
|
10
|
+
export declare function handleCommandError(spinner: Spinner | null, error: any, context?: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../../src/utils/error-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../../src/utils/error-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAuB,EAAE,KAAU,EAAE,OAAO,GAAG,kBAAkB;IAChG,gDAAgD;IAChD,IAAI,KAAK,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,EAAE,CAAC,EAAE,CAAC;QAClD,IAAI,OAAO;YAAE,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;QAC1C,OAAO;IACX,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACV,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;SAAM,CAAC;QACJ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,OAAO,GAAG,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;QACrC,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC,CAAC;QACzE,CAAC;aAAM,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;YACjC,MAAM,QAAQ,GAAG,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM;gBAC7D,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBACtE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,gBAAgB,QAAQ,EAAE,CAAC,CAAC,CAAC;QACzD,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,MAAM,IAAI,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACvE,CAAC;IACL,CAAC;SAAM,CAAC;QACJ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5C,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import https from 'https';
|
|
2
|
+
interface HelperConfig {
|
|
3
|
+
baseURL?: string;
|
|
4
|
+
headers?: Record<string, string>;
|
|
5
|
+
validateStatus?: (status: number) => boolean;
|
|
6
|
+
httpsAgent?: https.Agent;
|
|
7
|
+
}
|
|
8
|
+
interface RequestConfig extends HelperConfig {
|
|
9
|
+
params?: Record<string, any>;
|
|
10
|
+
}
|
|
11
|
+
interface Response<T = any> {
|
|
12
|
+
data: T;
|
|
13
|
+
status: number;
|
|
14
|
+
statusText: string;
|
|
15
|
+
headers: Record<string, string>;
|
|
16
|
+
}
|
|
17
|
+
export declare class HttpClient {
|
|
18
|
+
private defaults;
|
|
19
|
+
constructor(defaults?: HelperConfig);
|
|
20
|
+
static create(config?: HelperConfig): HttpClient;
|
|
21
|
+
request<T = any>(url: string, options?: RequestInit & RequestConfig): Promise<Response<T>>;
|
|
22
|
+
get<T = any>(url: string, config?: RequestConfig): Promise<Response<T>>;
|
|
23
|
+
post<T = any>(url: string, data?: any, config?: RequestConfig): Promise<Response<T>>;
|
|
24
|
+
put<T = any>(url: string, data?: any, config?: RequestConfig): Promise<Response<T>>;
|
|
25
|
+
delete<T = any>(url: string, config?: RequestConfig): Promise<Response<T>>;
|
|
26
|
+
}
|
|
27
|
+
export default HttpClient;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
export class HttpClient {
|
|
2
|
+
defaults;
|
|
3
|
+
constructor(defaults = {}) {
|
|
4
|
+
this.defaults = defaults;
|
|
5
|
+
}
|
|
6
|
+
static create(config = {}) {
|
|
7
|
+
return new HttpClient(config);
|
|
8
|
+
}
|
|
9
|
+
async request(url, options = {}) {
|
|
10
|
+
const baseURL = options.baseURL || this.defaults.baseURL || '';
|
|
11
|
+
const fullUrl = new URL(url.startsWith('http') ? url : `${baseURL}${url}`);
|
|
12
|
+
if (options.params) {
|
|
13
|
+
Object.entries(options.params).forEach(([key, value]) => {
|
|
14
|
+
if (value !== undefined)
|
|
15
|
+
fullUrl.searchParams.append(key, String(value));
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
const headers = {
|
|
19
|
+
...this.defaults.headers,
|
|
20
|
+
...options.headers
|
|
21
|
+
};
|
|
22
|
+
// Handle body for JSON
|
|
23
|
+
let body = options.body;
|
|
24
|
+
if (body && typeof body === 'object') {
|
|
25
|
+
const explicitContentType = headers['Content-Type'];
|
|
26
|
+
if (!explicitContentType || explicitContentType.includes('application/json')) {
|
|
27
|
+
if (!explicitContentType) {
|
|
28
|
+
headers['Content-Type'] = 'application/json';
|
|
29
|
+
}
|
|
30
|
+
body = JSON.stringify(body);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const fetchOptions = {
|
|
34
|
+
method: options.method || 'GET',
|
|
35
|
+
headers,
|
|
36
|
+
body: body,
|
|
37
|
+
// Node native fetch doesn't support 'agent' directly in standard RequestInit
|
|
38
|
+
// but we can pass it via 'dispatcher' in undici, or ignore if using global fetch.
|
|
39
|
+
// For simple usage we usually ignore httpsAgent unless strictly needed.
|
|
40
|
+
};
|
|
41
|
+
const response = await fetch(fullUrl.toString(), fetchOptions);
|
|
42
|
+
let data;
|
|
43
|
+
const contentType = response.headers.get('content-type');
|
|
44
|
+
const contentLength = response.headers.get('content-length');
|
|
45
|
+
if (response.status === 204 || (contentLength && parseInt(contentLength) === 0)) {
|
|
46
|
+
data = null;
|
|
47
|
+
}
|
|
48
|
+
else if (contentType && contentType.includes('application/json')) {
|
|
49
|
+
try {
|
|
50
|
+
data = await response.json();
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
// If JSON parsing fails (e.g. empty body despite content-type), fallback to text or null
|
|
54
|
+
const text = await response.text();
|
|
55
|
+
try {
|
|
56
|
+
data = JSON.parse(text);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
data = text || null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
data = await response.text();
|
|
65
|
+
}
|
|
66
|
+
const res = {
|
|
67
|
+
data,
|
|
68
|
+
status: response.status,
|
|
69
|
+
statusText: response.statusText,
|
|
70
|
+
headers: Object.fromEntries(response.headers.entries())
|
|
71
|
+
};
|
|
72
|
+
const validateStatus = options.validateStatus || this.defaults.validateStatus || ((s) => s >= 200 && s < 300);
|
|
73
|
+
if (!validateStatus(res.status)) {
|
|
74
|
+
const error = new Error(`Request failed with status ${res.status}`);
|
|
75
|
+
error.response = res;
|
|
76
|
+
error.status = res.status;
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
return res;
|
|
80
|
+
}
|
|
81
|
+
async get(url, config = {}) {
|
|
82
|
+
return this.request(url, { ...config, method: 'GET' });
|
|
83
|
+
}
|
|
84
|
+
async post(url, data, config = {}) {
|
|
85
|
+
return this.request(url, { ...config, method: 'POST', body: data });
|
|
86
|
+
}
|
|
87
|
+
async put(url, data, config = {}) {
|
|
88
|
+
return this.request(url, { ...config, method: 'PUT', body: data });
|
|
89
|
+
}
|
|
90
|
+
async delete(url, config = {}) {
|
|
91
|
+
return this.request(url, { ...config, method: 'DELETE' });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export default HttpClient;
|
|
95
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/utils/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare class Spinner {
|
|
2
|
+
private timer;
|
|
3
|
+
private frameIndex;
|
|
4
|
+
private frames;
|
|
5
|
+
text: string;
|
|
6
|
+
constructor(text: string | {
|
|
7
|
+
text: string;
|
|
8
|
+
});
|
|
9
|
+
start(text?: string): Spinner;
|
|
10
|
+
stop(): Spinner;
|
|
11
|
+
succeed(text?: string): Spinner;
|
|
12
|
+
fail(text?: string): Spinner;
|
|
13
|
+
info(text?: string): Spinner;
|
|
14
|
+
warn(text?: string): Spinner;
|
|
15
|
+
private clearLine;
|
|
16
|
+
private write;
|
|
17
|
+
private color;
|
|
18
|
+
}
|
|
19
|
+
export default function ora(options?: string | {
|
|
20
|
+
text: string;
|
|
21
|
+
}): Spinner;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export class Spinner {
|
|
2
|
+
timer = null;
|
|
3
|
+
frameIndex = 0;
|
|
4
|
+
frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
5
|
+
text;
|
|
6
|
+
constructor(text) {
|
|
7
|
+
this.text = typeof text === 'string' ? text : (text?.text || '');
|
|
8
|
+
}
|
|
9
|
+
start(text) {
|
|
10
|
+
if (text)
|
|
11
|
+
this.text = text;
|
|
12
|
+
this.frameIndex = 0;
|
|
13
|
+
// Only start animation if TTY and not CI (basic check)
|
|
14
|
+
if (process.stdout.isTTY) {
|
|
15
|
+
this.timer = setInterval(() => {
|
|
16
|
+
const frame = this.frames[this.frameIndex];
|
|
17
|
+
this.frameIndex = (this.frameIndex + 1) % this.frames.length;
|
|
18
|
+
this.write(`\r${frame} ${this.text}`);
|
|
19
|
+
}, 80);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
console.log(this.text);
|
|
23
|
+
}
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
stop() {
|
|
27
|
+
if (this.timer) {
|
|
28
|
+
clearInterval(this.timer);
|
|
29
|
+
this.timer = null;
|
|
30
|
+
this.clearLine();
|
|
31
|
+
}
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
succeed(text) {
|
|
35
|
+
this.stop();
|
|
36
|
+
const msg = text || this.text;
|
|
37
|
+
console.log(`${this.color('green', '✔')} ${msg}`);
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
fail(text) {
|
|
41
|
+
this.stop();
|
|
42
|
+
const msg = text || this.text;
|
|
43
|
+
console.log(`${this.color('red', '✖')} ${msg}`);
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
info(text) {
|
|
47
|
+
this.stop();
|
|
48
|
+
console.log(`${this.color('blue', 'ℹ')} ${text || this.text}`);
|
|
49
|
+
return this;
|
|
50
|
+
}
|
|
51
|
+
warn(text) {
|
|
52
|
+
this.stop();
|
|
53
|
+
console.log(`${this.color('yellow', '⚠')} ${text || this.text}`);
|
|
54
|
+
return this;
|
|
55
|
+
}
|
|
56
|
+
clearLine() {
|
|
57
|
+
if (process.stdout.isTTY) {
|
|
58
|
+
process.stdout.clearLine(0);
|
|
59
|
+
process.stdout.cursorTo(0);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
write(str) {
|
|
63
|
+
process.stdout.write(str);
|
|
64
|
+
}
|
|
65
|
+
color(color, str) {
|
|
66
|
+
const colors = {
|
|
67
|
+
green: '\x1b[32m',
|
|
68
|
+
red: '\x1b[31m',
|
|
69
|
+
blue: '\x1b[34m',
|
|
70
|
+
yellow: '\x1b[33m',
|
|
71
|
+
reset: '\x1b[0m'
|
|
72
|
+
};
|
|
73
|
+
return `${colors[color] || ''}${str}${colors.reset}`;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
export default function ora(options = '') {
|
|
77
|
+
return new Spinner(options);
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=spinner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../../src/utils/spinner.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jira-pilot",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
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 14-tool MCP server for AI assistants",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -82,16 +82,21 @@
|
|
|
82
82
|
"license": "ISC",
|
|
83
83
|
"dependencies": {
|
|
84
84
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
85
|
-
"axios": "^1.13.5",
|
|
86
85
|
"chalk": "^5.3.0",
|
|
87
|
-
"
|
|
86
|
+
"cmd-table": "^0.1.0",
|
|
88
87
|
"commander": "^14.0.3",
|
|
89
88
|
"enquirer": "^2.4.1",
|
|
90
|
-
"
|
|
91
|
-
"
|
|
89
|
+
"ink": "^6.7.0",
|
|
90
|
+
"ink-select-input": "^6.2.0",
|
|
91
|
+
"ink-spinner": "^5.0.0",
|
|
92
|
+
"ink-table": "^3.1.0",
|
|
93
|
+
"ink-text-input": "^6.0.0",
|
|
94
|
+
"react": "^19.2.4"
|
|
92
95
|
},
|
|
93
96
|
"devDependencies": {
|
|
97
|
+
"@types/ink": "^0.5.2",
|
|
94
98
|
"@types/node": "^25.2.3",
|
|
99
|
+
"@types/react": "^19.2.14",
|
|
95
100
|
"@vitest/coverage-v8": "^4.0.18",
|
|
96
101
|
"rimraf": "^6.1.2",
|
|
97
102
|
"tsx": "^4.21.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import ora from '
|
|
3
|
-
import
|
|
2
|
+
import ora from '../../utils/spinner.js';
|
|
3
|
+
import { HttpClient } from '../../utils/http.js';
|
|
4
4
|
import { execSync } from 'child_process';
|
|
5
5
|
import { api } from '../../services/api-service.js';
|
|
6
6
|
import { aiService } from '../../services/ai-service.js';
|
|
@@ -52,7 +52,8 @@ export async function reviewAction(issueKey: string, options: any) {
|
|
|
52
52
|
|
|
53
53
|
// 3. Search GitHub PRs
|
|
54
54
|
// We search for PRs that mention the issue key in title or branch name
|
|
55
|
-
const
|
|
55
|
+
const http = new HttpClient();
|
|
56
|
+
const searchRes = await http.get(`https://api.github.com/search/issues`, {
|
|
56
57
|
params: {
|
|
57
58
|
q: `repo:${repoOwner}/${repoName} is:pr ${issueKey}`
|
|
58
59
|
},
|
|
@@ -73,7 +74,7 @@ export async function reviewAction(issueKey: string, options: any) {
|
|
|
73
74
|
spinner.text = `Analyzing PR #${pr.number}: ${pr.title}...`;
|
|
74
75
|
|
|
75
76
|
// 4. Fetch Diff
|
|
76
|
-
const diffRes = await
|
|
77
|
+
const diffRes = await http.get(pr.pull_request.url, {
|
|
77
78
|
headers: {
|
|
78
79
|
'Authorization': `token ${githubToken}`,
|
|
79
80
|
'Accept': 'application/vnd.github.v3.diff'
|
package/src/commands/ai.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import ora from '
|
|
3
|
+
import ora from '../utils/spinner.js';
|
|
4
4
|
import enquirer from 'enquirer';
|
|
5
5
|
import { api } from '../services/api-service.js';
|
|
6
6
|
import { aiService } from '../services/ai-service.js';
|
package/src/commands/board.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import Table from '
|
|
3
|
+
import { Table } from 'cmd-table';
|
|
4
4
|
import { api } from '../services/api-service.js';
|
|
5
|
-
import ora from '
|
|
5
|
+
import ora from '../utils/spinner.js';
|
|
6
6
|
import { handleCommandError } from '../utils/error-handler.js';
|
|
7
7
|
|
|
8
8
|
export function registerBoardCommand(program: Command) {
|
|
@@ -51,11 +51,16 @@ Common Actions:
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
const table = new Table({
|
|
54
|
-
|
|
54
|
+
columns: [
|
|
55
|
+
{ name: chalk.bold('ID') },
|
|
56
|
+
{ name: chalk.bold('Name') },
|
|
57
|
+
{ name: chalk.bold('Type') },
|
|
58
|
+
{ name: chalk.bold('Project') }
|
|
59
|
+
]
|
|
55
60
|
});
|
|
56
61
|
|
|
57
62
|
data.values.forEach((b: any) => {
|
|
58
|
-
table.
|
|
63
|
+
table.addRow([
|
|
59
64
|
b.id,
|
|
60
65
|
b.name,
|
|
61
66
|
b.type,
|
|
@@ -63,7 +68,7 @@ Common Actions:
|
|
|
63
68
|
]);
|
|
64
69
|
});
|
|
65
70
|
|
|
66
|
-
console.log(table.
|
|
71
|
+
console.log(table.render());
|
|
67
72
|
console.log(chalk.grey(`Showing ${data.values.length} board(s)`));
|
|
68
73
|
|
|
69
74
|
} catch (e: any) {
|
package/src/commands/bulk.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import ora from '
|
|
3
|
+
import ora from '../utils/spinner.js';
|
|
4
4
|
import enquirer from 'enquirer';
|
|
5
5
|
import { api } from '../services/api-service.js';
|
|
6
6
|
import { handleCommandError } from '../utils/error-handler.js';
|
|
7
|
+
import { API } from '../utils/api-paths.js';
|
|
7
8
|
|
|
8
9
|
export function registerBulkCommand(program: Command) {
|
|
9
10
|
const bulkCmd = new Command('bulk')
|
|
@@ -29,7 +30,7 @@ Examples:
|
|
|
29
30
|
.action(async (options: any) => {
|
|
30
31
|
const spinner = ora('Finding matching issues...').start();
|
|
31
32
|
try {
|
|
32
|
-
const data = await api.post(
|
|
33
|
+
const data = await api.post(API.SEARCH.JQL, {
|
|
33
34
|
jql: options.jql,
|
|
34
35
|
maxResults: parseInt(options.limit),
|
|
35
36
|
fields: ['summary', 'status']
|
|
@@ -50,7 +51,7 @@ Examples:
|
|
|
50
51
|
|
|
51
52
|
if (!targetStatus) {
|
|
52
53
|
// Get transitions from the first issue to show available statuses
|
|
53
|
-
const transData = await api.get(
|
|
54
|
+
const transData = await api.get(API.ISSUE.TRANSITIONS(data.issues[0].key));
|
|
54
55
|
const { Select } = enquirer as any;
|
|
55
56
|
const statusSelect = new Select({
|
|
56
57
|
name: 'status',
|
|
@@ -78,13 +79,13 @@ Examples:
|
|
|
78
79
|
|
|
79
80
|
for (const issue of data.issues) {
|
|
80
81
|
try {
|
|
81
|
-
const transData = await api.get(
|
|
82
|
+
const transData = await api.get(API.ISSUE.TRANSITIONS(issue.key));
|
|
82
83
|
const transition = transData.transitions.find(
|
|
83
84
|
(t: any) => t.name.toLowerCase() === targetStatus.toLowerCase()
|
|
84
85
|
);
|
|
85
86
|
|
|
86
87
|
if (transition) {
|
|
87
|
-
await api.post(
|
|
88
|
+
await api.post(API.ISSUE.TRANSITIONS(issue.key), {
|
|
88
89
|
transition: { id: transition.id }
|
|
89
90
|
});
|
|
90
91
|
success++;
|
|
@@ -114,7 +115,7 @@ Examples:
|
|
|
114
115
|
.action(async (options: any) => {
|
|
115
116
|
const spinner = ora('Finding issues...').start();
|
|
116
117
|
try {
|
|
117
|
-
const data = await api.post(
|
|
118
|
+
const data = await api.post(API.SEARCH.JQL, {
|
|
118
119
|
jql: options.jql,
|
|
119
120
|
maxResults: 50,
|
|
120
121
|
fields: ['summary', 'assignee']
|
|
@@ -141,7 +142,7 @@ Examples:
|
|
|
141
142
|
}
|
|
142
143
|
|
|
143
144
|
if (assigneeId === 'me') {
|
|
144
|
-
const me = await api.get(
|
|
145
|
+
const me = await api.get(API.USER.MYSELF);
|
|
145
146
|
assigneeId = me.accountId;
|
|
146
147
|
}
|
|
147
148
|
|
|
@@ -156,7 +157,7 @@ Examples:
|
|
|
156
157
|
|
|
157
158
|
const processSpinner = ora('Assigning...').start();
|
|
158
159
|
for (const issue of data.issues) {
|
|
159
|
-
await api.put(
|
|
160
|
+
await api.put(API.ISSUE.ASSIGNEE(issue.key), { accountId: assigneeId });
|
|
160
161
|
}
|
|
161
162
|
processSpinner.succeed('Bulk assign complete.');
|
|
162
163
|
|
|
@@ -181,7 +182,7 @@ Examples:
|
|
|
181
182
|
|
|
182
183
|
const spinner = ora('Finding issues...').start();
|
|
183
184
|
try {
|
|
184
|
-
const data = await api.post(
|
|
185
|
+
const data = await api.post(API.SEARCH.JQL, {
|
|
185
186
|
jql: options.jql,
|
|
186
187
|
maxResults: 50,
|
|
187
188
|
fields: ['summary', 'labels']
|
|
@@ -215,7 +216,7 @@ Examples:
|
|
|
215
216
|
addList.forEach((l: string) => newLabels.add(l));
|
|
216
217
|
removeList.forEach((l: string) => newLabels.delete(l));
|
|
217
218
|
|
|
218
|
-
await api.put(
|
|
219
|
+
await api.put(API.ISSUE.GET(issue.key), {
|
|
219
220
|
fields: { labels: Array.from(newLabels) }
|
|
220
221
|
});
|
|
221
222
|
}
|
package/src/commands/config.ts
CHANGED
|
@@ -3,7 +3,7 @@ import chalk from 'chalk';
|
|
|
3
3
|
import enquirer from 'enquirer';
|
|
4
4
|
import { setCredentials, getCredentials, clearCredentials, saveProfile, loadProfile, deleteProfile, listProfiles, getActiveProfile } from '../utils/config.js';
|
|
5
5
|
import ConfigStore from '../utils/config-store.js';
|
|
6
|
-
import ora from '
|
|
6
|
+
import ora from '../utils/spinner.js';
|
|
7
7
|
import { api } from '../services/api-service.js';
|
|
8
8
|
|
|
9
9
|
export function registerConfigCommand(program: Command) {
|