@simonfestl/husky-cli 0.5.1 → 0.6.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.
Files changed (37) hide show
  1. package/dist/commands/config.js +4 -3
  2. package/dist/commands/idea.js +9 -7
  3. package/dist/commands/interactive/changelog.d.ts +1 -0
  4. package/dist/commands/interactive/changelog.js +398 -0
  5. package/dist/commands/interactive/departments.d.ts +1 -0
  6. package/dist/commands/interactive/departments.js +242 -0
  7. package/dist/commands/interactive/ideas.d.ts +1 -0
  8. package/dist/commands/interactive/ideas.js +311 -0
  9. package/dist/commands/interactive/jules-sessions.d.ts +1 -0
  10. package/dist/commands/interactive/jules-sessions.js +460 -0
  11. package/dist/commands/interactive/processes.d.ts +1 -0
  12. package/dist/commands/interactive/processes.js +271 -0
  13. package/dist/commands/interactive/projects.d.ts +1 -0
  14. package/dist/commands/interactive/projects.js +297 -0
  15. package/dist/commands/interactive/roadmaps.d.ts +1 -0
  16. package/dist/commands/interactive/roadmaps.js +650 -0
  17. package/dist/commands/interactive/strategy.d.ts +1 -0
  18. package/dist/commands/interactive/strategy.js +790 -0
  19. package/dist/commands/interactive/tasks.d.ts +1 -0
  20. package/dist/commands/interactive/tasks.js +415 -0
  21. package/dist/commands/interactive/utils.d.ts +15 -0
  22. package/dist/commands/interactive/utils.js +54 -0
  23. package/dist/commands/interactive/vm-sessions.d.ts +1 -0
  24. package/dist/commands/interactive/vm-sessions.js +319 -0
  25. package/dist/commands/interactive/workflows.d.ts +1 -0
  26. package/dist/commands/interactive/workflows.js +442 -0
  27. package/dist/commands/interactive/worktrees.d.ts +6 -0
  28. package/dist/commands/interactive/worktrees.js +354 -0
  29. package/dist/commands/interactive.js +118 -1208
  30. package/dist/commands/worktree.d.ts +2 -0
  31. package/dist/commands/worktree.js +404 -0
  32. package/dist/index.js +3 -1
  33. package/dist/lib/merge-lock.d.ts +83 -0
  34. package/dist/lib/merge-lock.js +242 -0
  35. package/dist/lib/worktree.d.ts +133 -0
  36. package/dist/lib/worktree.js +473 -0
  37. package/package.json +1 -1
@@ -0,0 +1,319 @@
1
+ import { select, input, confirm } from "@inquirer/prompts";
2
+ import { ensureConfig, pressEnterToContinue, truncate } from "./utils.js";
3
+ export async function vmSessionsMenu() {
4
+ const config = ensureConfig();
5
+ const menuItems = [
6
+ { name: "List all VM sessions", value: "list" },
7
+ { name: "View session details", value: "view" },
8
+ { name: "Create new session", value: "create" },
9
+ { name: "Start VM", value: "start" },
10
+ { name: "Stop VM", value: "stop" },
11
+ { name: "View logs", value: "logs" },
12
+ { name: "Approve plan", value: "approve" },
13
+ { name: "Delete session", value: "delete" },
14
+ { name: "Back to main menu", value: "back" },
15
+ ];
16
+ const choice = await select({
17
+ message: "VM Sessions:",
18
+ choices: menuItems,
19
+ });
20
+ switch (choice) {
21
+ case "list":
22
+ await listVMSessions(config);
23
+ break;
24
+ case "view":
25
+ await viewVMSession(config);
26
+ break;
27
+ case "create":
28
+ await createVMSession(config);
29
+ break;
30
+ case "start":
31
+ await startVM(config);
32
+ break;
33
+ case "stop":
34
+ await stopVM(config);
35
+ break;
36
+ case "logs":
37
+ await viewLogs(config);
38
+ break;
39
+ case "approve":
40
+ await approvePlan(config);
41
+ break;
42
+ case "delete":
43
+ await deleteVMSession(config);
44
+ break;
45
+ case "back":
46
+ return;
47
+ }
48
+ }
49
+ async function fetchVMSessions(config) {
50
+ const res = await fetch(`${config.apiUrl}/api/vm-sessions`, {
51
+ headers: config.apiKey ? { "x-api-key": config.apiKey } : {},
52
+ });
53
+ if (!res.ok)
54
+ throw new Error(`API returned ${res.status}`);
55
+ const data = await res.json();
56
+ return data.sessions || [];
57
+ }
58
+ async function selectVMSession(config, message) {
59
+ const sessions = await fetchVMSessions(config);
60
+ if (sessions.length === 0) {
61
+ console.log("\n No VM sessions found.\n");
62
+ await pressEnterToContinue();
63
+ return null;
64
+ }
65
+ const choices = sessions.map((s) => ({
66
+ name: `[${s.vmStatus}] ${truncate(s.name, 35)} (${s.agentType})`,
67
+ value: s.id,
68
+ }));
69
+ choices.push({ name: "Cancel", value: "__cancel__" });
70
+ const sessionId = await select({ message, choices });
71
+ if (sessionId === "__cancel__")
72
+ return null;
73
+ return sessions.find((s) => s.id === sessionId) || null;
74
+ }
75
+ async function listVMSessions(config) {
76
+ try {
77
+ const sessions = await fetchVMSessions(config);
78
+ console.log("\n VM SESSIONS");
79
+ console.log(" " + "-".repeat(70));
80
+ if (sessions.length === 0) {
81
+ console.log(" No VM sessions found.");
82
+ }
83
+ else {
84
+ for (const session of sessions) {
85
+ const statusLabel = session.vmStatus.replace(/_/g, " ").toUpperCase();
86
+ console.log(` [${statusLabel}] ${truncate(session.name, 40)} (${session.agentType})`);
87
+ console.log(` ID: ${session.id}`);
88
+ }
89
+ }
90
+ console.log("");
91
+ await pressEnterToContinue();
92
+ }
93
+ catch (error) {
94
+ console.error("\n Error fetching VM sessions:", error);
95
+ await pressEnterToContinue();
96
+ }
97
+ }
98
+ async function viewVMSession(config) {
99
+ try {
100
+ const session = await selectVMSession(config, "Select session to view:");
101
+ if (!session)
102
+ return;
103
+ const res = await fetch(`${config.apiUrl}/api/vm-sessions/${session.id}`, {
104
+ headers: config.apiKey ? { "x-api-key": config.apiKey } : {},
105
+ });
106
+ if (!res.ok) {
107
+ console.error(`\n Error: API returned ${res.status}\n`);
108
+ await pressEnterToContinue();
109
+ return;
110
+ }
111
+ const full = await res.json();
112
+ console.log(`\n VM Session: ${full.name}`);
113
+ console.log(" " + "-".repeat(50));
114
+ console.log(` ID: ${full.id}`);
115
+ console.log(` Status: ${full.vmStatus}`);
116
+ console.log(` Agent: ${full.agentType}`);
117
+ if (full.prompt) {
118
+ console.log(` Prompt: ${truncate(full.prompt, 50)}`);
119
+ }
120
+ console.log("");
121
+ await pressEnterToContinue();
122
+ }
123
+ catch (error) {
124
+ console.error("\n Error viewing session:", error);
125
+ await pressEnterToContinue();
126
+ }
127
+ }
128
+ async function createVMSession(config) {
129
+ try {
130
+ const name = await input({
131
+ message: "Session name:",
132
+ validate: (v) => (v.length > 0 ? true : "Name required"),
133
+ });
134
+ const prompt = await input({
135
+ message: "Prompt (task description):",
136
+ validate: (v) => (v.length > 0 ? true : "Prompt required"),
137
+ });
138
+ const agentType = await select({
139
+ message: "Agent type:",
140
+ choices: [
141
+ { name: "Claude Code", value: "claude-code" },
142
+ { name: "Gemini CLI", value: "gemini-cli" },
143
+ { name: "Aider", value: "aider" },
144
+ { name: "Custom", value: "custom" },
145
+ ],
146
+ default: "claude-code",
147
+ });
148
+ const res = await fetch(`${config.apiUrl}/api/vm-sessions`, {
149
+ method: "POST",
150
+ headers: {
151
+ "Content-Type": "application/json",
152
+ ...(config.apiKey ? { "x-api-key": config.apiKey } : {}),
153
+ },
154
+ body: JSON.stringify({
155
+ name,
156
+ prompt,
157
+ agentType,
158
+ machineType: "e2-medium",
159
+ zone: "us-central1-a",
160
+ startTrigger: "manual",
161
+ }),
162
+ });
163
+ if (!res.ok) {
164
+ const error = await res.json().catch(() => ({}));
165
+ console.error(`\n Error: ${error.error || `API returned ${res.status}`}\n`);
166
+ await pressEnterToContinue();
167
+ return;
168
+ }
169
+ const session = await res.json();
170
+ console.log(`\n ✓ VM session created!`);
171
+ console.log(` ID: ${session.id}`);
172
+ console.log(` Name: ${session.name}\n`);
173
+ await pressEnterToContinue();
174
+ }
175
+ catch (error) {
176
+ console.error("\n Error creating session:", error);
177
+ await pressEnterToContinue();
178
+ }
179
+ }
180
+ async function startVM(config) {
181
+ try {
182
+ const session = await selectVMSession(config, "Select session to start:");
183
+ if (!session)
184
+ return;
185
+ console.log("\n Starting VM... This may take a moment.\n");
186
+ const res = await fetch(`${config.apiUrl}/api/vm-sessions/${session.id}/start`, {
187
+ method: "POST",
188
+ headers: config.apiKey ? { "x-api-key": config.apiKey } : {},
189
+ });
190
+ if (!res.ok) {
191
+ console.error(`\n Error: API returned ${res.status}\n`);
192
+ await pressEnterToContinue();
193
+ return;
194
+ }
195
+ console.log(` ✓ VM started: ${session.name}\n`);
196
+ await pressEnterToContinue();
197
+ }
198
+ catch (error) {
199
+ console.error("\n Error starting VM:", error);
200
+ await pressEnterToContinue();
201
+ }
202
+ }
203
+ async function stopVM(config) {
204
+ try {
205
+ const session = await selectVMSession(config, "Select session to stop:");
206
+ if (!session)
207
+ return;
208
+ const res = await fetch(`${config.apiUrl}/api/vm-sessions/${session.id}/stop`, {
209
+ method: "POST",
210
+ headers: config.apiKey ? { "x-api-key": config.apiKey } : {},
211
+ });
212
+ if (!res.ok) {
213
+ console.error(`\n Error: API returned ${res.status}\n`);
214
+ await pressEnterToContinue();
215
+ return;
216
+ }
217
+ console.log(`\n ✓ VM stopped: ${session.name}\n`);
218
+ await pressEnterToContinue();
219
+ }
220
+ catch (error) {
221
+ console.error("\n Error stopping VM:", error);
222
+ await pressEnterToContinue();
223
+ }
224
+ }
225
+ async function viewLogs(config) {
226
+ try {
227
+ const session = await selectVMSession(config, "Select session to view logs:");
228
+ if (!session)
229
+ return;
230
+ const res = await fetch(`${config.apiUrl}/api/vm-sessions/${session.id}/logs?tail=30`, {
231
+ headers: config.apiKey ? { "x-api-key": config.apiKey } : {},
232
+ });
233
+ if (!res.ok) {
234
+ console.error(`\n Error: API returned ${res.status}\n`);
235
+ await pressEnterToContinue();
236
+ return;
237
+ }
238
+ const data = await res.json();
239
+ const logs = data.logs || [];
240
+ console.log(`\n Logs for: ${session.name}`);
241
+ console.log(" " + "-".repeat(50));
242
+ if (logs.length === 0) {
243
+ console.log(" No logs available.");
244
+ }
245
+ else {
246
+ for (const log of logs) {
247
+ console.log(` ${log.timestamp || ""} ${log.message || log}`);
248
+ }
249
+ }
250
+ console.log("");
251
+ await pressEnterToContinue();
252
+ }
253
+ catch (error) {
254
+ console.error("\n Error fetching logs:", error);
255
+ await pressEnterToContinue();
256
+ }
257
+ }
258
+ async function approvePlan(config) {
259
+ try {
260
+ const session = await selectVMSession(config, "Select session to approve:");
261
+ if (!session)
262
+ return;
263
+ const confirmed = await confirm({
264
+ message: `Approve plan for "${session.name}"?`,
265
+ default: true,
266
+ });
267
+ if (!confirmed) {
268
+ console.log("\n Cancelled.\n");
269
+ await pressEnterToContinue();
270
+ return;
271
+ }
272
+ const res = await fetch(`${config.apiUrl}/api/vm-sessions/${session.id}/approve`, {
273
+ method: "POST",
274
+ headers: config.apiKey ? { "x-api-key": config.apiKey } : {},
275
+ });
276
+ if (!res.ok) {
277
+ console.error(`\n Error: API returned ${res.status}\n`);
278
+ await pressEnterToContinue();
279
+ return;
280
+ }
281
+ console.log(`\n ✓ Plan approved!\n`);
282
+ await pressEnterToContinue();
283
+ }
284
+ catch (error) {
285
+ console.error("\n Error approving plan:", error);
286
+ await pressEnterToContinue();
287
+ }
288
+ }
289
+ async function deleteVMSession(config) {
290
+ try {
291
+ const session = await selectVMSession(config, "Select session to delete:");
292
+ if (!session)
293
+ return;
294
+ const confirmed = await confirm({
295
+ message: `Delete "${session.name}"? This cannot be undone.`,
296
+ default: false,
297
+ });
298
+ if (!confirmed) {
299
+ console.log("\n Cancelled.\n");
300
+ await pressEnterToContinue();
301
+ return;
302
+ }
303
+ const res = await fetch(`${config.apiUrl}/api/vm-sessions/${session.id}`, {
304
+ method: "DELETE",
305
+ headers: config.apiKey ? { "x-api-key": config.apiKey } : {},
306
+ });
307
+ if (!res.ok) {
308
+ console.error(`\n Error: API returned ${res.status}\n`);
309
+ await pressEnterToContinue();
310
+ return;
311
+ }
312
+ console.log(`\n ✓ Session deleted.\n`);
313
+ await pressEnterToContinue();
314
+ }
315
+ catch (error) {
316
+ console.error("\n Error deleting session:", error);
317
+ await pressEnterToContinue();
318
+ }
319
+ }
@@ -0,0 +1 @@
1
+ export declare function workflowsMenu(): Promise<void>;