@vibedx/vibekit 0.3.1 → 0.4.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/assets/default.md +2 -0
- package/package.json +1 -1
- package/src/commands/list/index.js +68 -31
- package/src/commands/new/index.js +29 -14
package/assets/default.md
CHANGED
package/package.json
CHANGED
|
@@ -10,10 +10,13 @@ import { getTicketsDir } from '../../utils/index.js';
|
|
|
10
10
|
function listCommand(args) {
|
|
11
11
|
// Parse arguments for filtering
|
|
12
12
|
let statusFilter = null;
|
|
13
|
-
|
|
13
|
+
let assigneeFilter = null;
|
|
14
|
+
|
|
14
15
|
for (let i = 0; i < args.length; i++) {
|
|
15
16
|
if (args[i].startsWith("--status=")) {
|
|
16
17
|
statusFilter = args[i].split("=")[1];
|
|
18
|
+
} else if (args[i].startsWith("--assignee=") || args[i].startsWith("--owner=")) {
|
|
19
|
+
assigneeFilter = args[i].split("=")[1];
|
|
17
20
|
}
|
|
18
21
|
}
|
|
19
22
|
|
|
@@ -49,6 +52,8 @@ function listCommand(args) {
|
|
|
49
52
|
title: frontmatter.title || "Untitled",
|
|
50
53
|
status: frontmatter.status || "unknown",
|
|
51
54
|
priority: frontmatter.priority || "medium",
|
|
55
|
+
assignee: frontmatter.assignee || frontmatter.owner || "",
|
|
56
|
+
author: frontmatter.author || "",
|
|
52
57
|
file
|
|
53
58
|
});
|
|
54
59
|
}
|
|
@@ -57,10 +62,16 @@ function listCommand(args) {
|
|
|
57
62
|
}
|
|
58
63
|
}
|
|
59
64
|
|
|
60
|
-
// Filter tickets
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
// Filter tickets
|
|
66
|
+
let filteredTickets = tickets;
|
|
67
|
+
if (statusFilter) {
|
|
68
|
+
filteredTickets = filteredTickets.filter(ticket => ticket.status === statusFilter);
|
|
69
|
+
}
|
|
70
|
+
if (assigneeFilter) {
|
|
71
|
+
filteredTickets = filteredTickets.filter(ticket =>
|
|
72
|
+
ticket.assignee.toLowerCase() === assigneeFilter.toLowerCase()
|
|
73
|
+
);
|
|
74
|
+
}
|
|
64
75
|
|
|
65
76
|
// Sort tickets by ID
|
|
66
77
|
filteredTickets.sort((a, b) => {
|
|
@@ -79,20 +90,27 @@ function listCommand(args) {
|
|
|
79
90
|
// Display tickets in a formatted table
|
|
80
91
|
console.log("\n✨ VibeKit Tickets ✨\n");
|
|
81
92
|
|
|
82
|
-
// Calculate column widths
|
|
83
|
-
const idWidth = 10;
|
|
84
|
-
const statusWidth = 15;
|
|
85
|
-
const
|
|
86
|
-
|
|
93
|
+
// Calculate column widths
|
|
94
|
+
const idWidth = 10;
|
|
95
|
+
const statusWidth = 15;
|
|
96
|
+
const assigneeWidth = 14;
|
|
97
|
+
const titleWidth = 40;
|
|
98
|
+
|
|
99
|
+
// Check if any tickets have assignees
|
|
100
|
+
const hasAssignees = filteredTickets.some(t => t.assignee);
|
|
101
|
+
|
|
87
102
|
// Print header
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
"STATUS".padEnd(statusWidth)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
103
|
+
if (hasAssignees) {
|
|
104
|
+
console.log(
|
|
105
|
+
`${"ID".padEnd(idWidth)}${"|"} ${"STATUS".padEnd(statusWidth)}${"|"} ${"ASSIGNEE".padEnd(assigneeWidth)}${"|"} TITLE`
|
|
106
|
+
);
|
|
107
|
+
console.log(`${'-'.repeat(idWidth)}+${'-'.repeat(statusWidth + 2)}+${'-'.repeat(assigneeWidth + 2)}+${'-'.repeat(titleWidth)}`);
|
|
108
|
+
} else {
|
|
109
|
+
console.log(
|
|
110
|
+
`${"ID".padEnd(idWidth)}${"|"} ${"STATUS".padEnd(statusWidth)}${"|"} TITLE`
|
|
111
|
+
);
|
|
112
|
+
console.log(`${'-'.repeat(idWidth)}+${'-'.repeat(statusWidth + 2)}+${'-'.repeat(titleWidth)}`);
|
|
113
|
+
}
|
|
96
114
|
|
|
97
115
|
for (const ticket of filteredTickets) {
|
|
98
116
|
let statusColor = "";
|
|
@@ -112,20 +130,39 @@ function listCommand(args) {
|
|
|
112
130
|
statusColor = "\x1b[0m"; // Default
|
|
113
131
|
}
|
|
114
132
|
|
|
115
|
-
// Format each row
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
133
|
+
// Format each row
|
|
134
|
+
const truncatedTitle = ticket.title.length > titleWidth - 3
|
|
135
|
+
? ticket.title.substring(0, titleWidth - 3) + "..."
|
|
136
|
+
: ticket.title;
|
|
137
|
+
|
|
138
|
+
if (hasAssignees) {
|
|
139
|
+
console.log(
|
|
140
|
+
`${ticket.id.padEnd(idWidth)}${"|"} ${
|
|
141
|
+
statusColor + ticket.status.padEnd(statusWidth - 1) + "\x1b[0m"
|
|
142
|
+
}${"|"} ${
|
|
143
|
+
(ticket.assignee || "").padEnd(assigneeWidth - 1)
|
|
144
|
+
}${"|"} ${truncatedTitle}`
|
|
145
|
+
);
|
|
146
|
+
} else {
|
|
147
|
+
console.log(
|
|
148
|
+
`${ticket.id.padEnd(idWidth)}${"|"} ${
|
|
149
|
+
statusColor + ticket.status.padEnd(statusWidth - 1) + "\x1b[0m"
|
|
150
|
+
}${"|"} ${truncatedTitle}`
|
|
151
|
+
);
|
|
152
|
+
}
|
|
125
153
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
154
|
+
|
|
155
|
+
if (hasAssignees) {
|
|
156
|
+
console.log(`${'-'.repeat(idWidth)}+${'-'.repeat(statusWidth + 2)}+${'-'.repeat(assigneeWidth + 2)}+${'-'.repeat(titleWidth)}`);
|
|
157
|
+
} else {
|
|
158
|
+
console.log(`${'-'.repeat(idWidth)}+${'-'.repeat(statusWidth + 2)}+${'-'.repeat(titleWidth)}`);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const filters = [
|
|
162
|
+
statusFilter ? `status: ${statusFilter}` : '',
|
|
163
|
+
assigneeFilter ? `assignee: ${assigneeFilter}` : '',
|
|
164
|
+
].filter(Boolean).join(', ');
|
|
165
|
+
console.log(`Found ${filteredTickets.length} ticket(s)${filters ? ` (${filters})` : ''}.\n`);
|
|
129
166
|
}
|
|
130
167
|
|
|
131
168
|
export default listCommand;
|
|
@@ -32,28 +32,39 @@ function parseArguments(args) {
|
|
|
32
32
|
let titleParts = [];
|
|
33
33
|
let priority = DEFAULT_PRIORITY;
|
|
34
34
|
let status = DEFAULT_STATUS;
|
|
35
|
-
|
|
35
|
+
let assignee = '';
|
|
36
|
+
let author = '';
|
|
37
|
+
let noInteractive = false;
|
|
38
|
+
|
|
36
39
|
for (let i = 0; i < args.length; i++) {
|
|
37
40
|
const arg = args[i];
|
|
38
|
-
|
|
41
|
+
|
|
39
42
|
if (arg === '--priority' && i + 1 < args.length) {
|
|
40
43
|
priority = args[i + 1];
|
|
41
|
-
i++;
|
|
44
|
+
i++;
|
|
42
45
|
} else if (arg === '--status' && i + 1 < args.length) {
|
|
43
46
|
status = args[i + 1];
|
|
44
|
-
i++;
|
|
47
|
+
i++;
|
|
48
|
+
} else if ((arg === '--assignee' || arg === '--owner') && i + 1 < args.length) {
|
|
49
|
+
assignee = args[i + 1];
|
|
50
|
+
i++;
|
|
51
|
+
} else if (arg === '--author' && i + 1 < args.length) {
|
|
52
|
+
author = args[i + 1];
|
|
53
|
+
i++;
|
|
54
|
+
} else if (arg === '--no-interactive' || arg === '-n') {
|
|
55
|
+
noInteractive = true;
|
|
45
56
|
} else if (!arg.startsWith('--')) {
|
|
46
57
|
titleParts.push(arg);
|
|
47
58
|
}
|
|
48
59
|
}
|
|
49
|
-
|
|
60
|
+
|
|
50
61
|
const title = titleParts.join(' ').trim();
|
|
51
|
-
|
|
62
|
+
|
|
52
63
|
if (!title) {
|
|
53
64
|
throw new Error('Please provide a title for the new ticket.');
|
|
54
65
|
}
|
|
55
|
-
|
|
56
|
-
return { title, priority, status };
|
|
66
|
+
|
|
67
|
+
return { title, priority, status, assignee, author, noInteractive };
|
|
57
68
|
}
|
|
58
69
|
|
|
59
70
|
/**
|
|
@@ -93,16 +104,18 @@ function createTicketContent(template, ticketData) {
|
|
|
93
104
|
throw new Error('Template must be a string');
|
|
94
105
|
}
|
|
95
106
|
|
|
96
|
-
const { ticketId, title, slug, priority, status, timestamp } = ticketData;
|
|
107
|
+
const { ticketId, title, slug, priority, status, assignee, author, timestamp } = ticketData;
|
|
97
108
|
const paddedId = ticketId.replace('TKT-', '');
|
|
98
|
-
|
|
109
|
+
|
|
99
110
|
return template
|
|
100
111
|
.replace(/{id}/g, paddedId)
|
|
101
112
|
.replace(/{title}/g, title)
|
|
102
113
|
.replace(/{slug}/g, slug)
|
|
103
114
|
.replace(/{date}/g, timestamp)
|
|
104
115
|
.replace(/^priority: .*$/m, `priority: ${priority}`)
|
|
105
|
-
.replace(/^status: .*$/m, `status: ${status}`)
|
|
116
|
+
.replace(/^status: .*$/m, `status: ${status}`)
|
|
117
|
+
.replace(/^assignee: .*$/m, `assignee: "${assignee || ''}"`)
|
|
118
|
+
.replace(/^author: .*$/m, `author: "${author || ''}"`);
|
|
106
119
|
}
|
|
107
120
|
|
|
108
121
|
/**
|
|
@@ -193,7 +206,7 @@ async function handleFileRename(originalPath, ticketDir) {
|
|
|
193
206
|
async function newCommand(args) {
|
|
194
207
|
try {
|
|
195
208
|
// Parse and validate arguments
|
|
196
|
-
const { title, priority, status } = parseArguments(args);
|
|
209
|
+
const { title, priority, status, assignee, author, noInteractive } = parseArguments(args);
|
|
197
210
|
|
|
198
211
|
// Check required files and paths
|
|
199
212
|
const configPath = path.join(process.cwd(), '.vibe', 'config.yml');
|
|
@@ -236,6 +249,8 @@ async function newCommand(args) {
|
|
|
236
249
|
slug: ticketSlug,
|
|
237
250
|
priority: validatedOptions.priority,
|
|
238
251
|
status: validatedOptions.status,
|
|
252
|
+
assignee,
|
|
253
|
+
author,
|
|
239
254
|
timestamp
|
|
240
255
|
};
|
|
241
256
|
|
|
@@ -254,8 +269,8 @@ async function newCommand(args) {
|
|
|
254
269
|
|
|
255
270
|
logger.success(`Created ticket: ${filename} (priority: ${ticketData.priority}, status: ${ticketData.status})`);
|
|
256
271
|
|
|
257
|
-
// Offer AI enhancement if available
|
|
258
|
-
if (checkAiEnabled(config)) {
|
|
272
|
+
// Offer AI enhancement if available (skip in non-interactive mode)
|
|
273
|
+
if (checkAiEnabled(config) && !noInteractive) {
|
|
259
274
|
await offerAiEnhancement(ticketId, outputPath, ticketDir);
|
|
260
275
|
}
|
|
261
276
|
|