@jonit-dev/night-watch-cli 1.2.0 → 1.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/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/dashboard/tab-actions.d.ts +10 -0
- package/dist/commands/dashboard/tab-actions.d.ts.map +1 -0
- package/dist/commands/dashboard/tab-actions.js +245 -0
- package/dist/commands/dashboard/tab-actions.js.map +1 -0
- package/dist/commands/dashboard/tab-config.d.ts +21 -0
- package/dist/commands/dashboard/tab-config.d.ts.map +1 -0
- package/dist/commands/dashboard/tab-config.js +821 -0
- package/dist/commands/dashboard/tab-config.js.map +1 -0
- package/dist/commands/dashboard/tab-logs.d.ts +10 -0
- package/dist/commands/dashboard/tab-logs.d.ts.map +1 -0
- package/dist/commands/dashboard/tab-logs.js +178 -0
- package/dist/commands/dashboard/tab-logs.js.map +1 -0
- package/dist/commands/dashboard/tab-schedules.d.ts +21 -0
- package/dist/commands/dashboard/tab-schedules.d.ts.map +1 -0
- package/dist/commands/dashboard/tab-schedules.js +304 -0
- package/dist/commands/dashboard/tab-schedules.js.map +1 -0
- package/dist/commands/dashboard/tab-status.d.ts +32 -0
- package/dist/commands/dashboard/tab-status.d.ts.map +1 -0
- package/dist/commands/dashboard/tab-status.js +416 -0
- package/dist/commands/dashboard/tab-status.js.map +1 -0
- package/dist/commands/dashboard/types.d.ts +43 -0
- package/dist/commands/dashboard/types.d.ts.map +1 -0
- package/dist/commands/dashboard/types.js +5 -0
- package/dist/commands/dashboard/types.js.map +1 -0
- package/dist/commands/dashboard.d.ts +2 -20
- package/dist/commands/dashboard.d.ts.map +1 -1
- package/dist/commands/dashboard.js +166 -224
- package/dist/commands/dashboard.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +21 -10
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install.d.ts +16 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +54 -0
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +4 -0
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/serve.d.ts +7 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +27 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/uninstall.d.ts +12 -0
- package/dist/commands/uninstall.d.ts.map +1 -1
- package/dist/commands/uninstall.js +44 -0
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +5 -0
- package/dist/constants.js.map +1 -1
- package/dist/server/index.d.ts +23 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +470 -0
- package/dist/server/index.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/checks.d.ts +55 -0
- package/dist/utils/checks.d.ts.map +1 -0
- package/dist/utils/checks.js +246 -0
- package/dist/utils/checks.js.map +1 -0
- package/dist/utils/config-writer.d.ts +16 -0
- package/dist/utils/config-writer.d.ts.map +1 -0
- package/dist/utils/config-writer.js +45 -0
- package/dist/utils/config-writer.js.map +1 -0
- package/dist/utils/registry.d.ts +39 -0
- package/dist/utils/registry.d.ts.map +1 -0
- package/dist/utils/registry.js +97 -0
- package/dist/utils/registry.js.map +1 -0
- package/package.json +13 -3
- package/scripts/night-watch-helpers.sh +20 -0
|
@@ -1,120 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dashboard command for Night Watch CLI
|
|
3
|
-
*
|
|
3
|
+
* Tabbed TUI with Status, Config, Schedules, Actions, and Logs tabs
|
|
4
4
|
*/
|
|
5
5
|
import blessed from "blessed";
|
|
6
6
|
import { loadConfig } from "../config.js";
|
|
7
|
-
import { fetchStatusSnapshot
|
|
8
|
-
import
|
|
7
|
+
import { fetchStatusSnapshot } from "../utils/status-data.js";
|
|
8
|
+
import { createStatusTab } from "./dashboard/tab-status.js";
|
|
9
|
+
import { createConfigTab } from "./dashboard/tab-config.js";
|
|
10
|
+
import { createSchedulesTab } from "./dashboard/tab-schedules.js";
|
|
11
|
+
import { createActionsTab } from "./dashboard/tab-actions.js";
|
|
12
|
+
import { createLogsTab } from "./dashboard/tab-logs.js";
|
|
13
|
+
// Re-export render functions for backward compatibility (used by tests)
|
|
14
|
+
export { renderPrdPane, renderProcessPane, renderPrPane, renderLogPane, } from "./dashboard/tab-status.js";
|
|
9
15
|
/**
|
|
10
|
-
*
|
|
11
|
-
* Each PRD gets a colored status indicator and optional dependency list.
|
|
16
|
+
* Show a temporary flash message overlay
|
|
12
17
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
indicator = "{#888888-fg}\u25cf{/#888888-fg}";
|
|
32
|
-
break;
|
|
33
|
-
}
|
|
34
|
-
let line = `${indicator} ${prd.name}`;
|
|
35
|
-
if (prd.dependencies.length > 0) {
|
|
36
|
-
line += ` (deps: ${prd.dependencies.join(", ")})`;
|
|
37
|
-
}
|
|
38
|
-
lines.push(line);
|
|
39
|
-
}
|
|
40
|
-
return lines.join("\n");
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Render the Process Status pane content from snapshot data.
|
|
44
|
-
*/
|
|
45
|
-
export function renderProcessPane(processes) {
|
|
46
|
-
const lines = [];
|
|
47
|
-
for (const proc of processes) {
|
|
48
|
-
if (proc.running) {
|
|
49
|
-
lines.push(`{green-fg}\u25cf{/green-fg} ${proc.name}: Running (PID: ${proc.pid})`);
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
lines.push(`{white-fg}\u25cb{/white-fg} ${proc.name}: Not running`);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return lines.join("\n");
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Render the PR Status pane content from snapshot data.
|
|
59
|
-
*/
|
|
60
|
-
export function renderPrPane(prs) {
|
|
61
|
-
if (prs.length === 0) {
|
|
62
|
-
return "No matching pull requests";
|
|
63
|
-
}
|
|
64
|
-
const lines = [];
|
|
65
|
-
for (const pr of prs) {
|
|
66
|
-
let ciIndicator;
|
|
67
|
-
switch (pr.ciStatus) {
|
|
68
|
-
case "pass":
|
|
69
|
-
ciIndicator = "{green-fg}\u25cf{/green-fg}";
|
|
70
|
-
break;
|
|
71
|
-
case "fail":
|
|
72
|
-
ciIndicator = "{red-fg}\u25cf{/red-fg}";
|
|
73
|
-
break;
|
|
74
|
-
case "pending":
|
|
75
|
-
ciIndicator = "{yellow-fg}\u25cf{/yellow-fg}";
|
|
76
|
-
break;
|
|
77
|
-
default:
|
|
78
|
-
ciIndicator = "{white-fg}\u25cf{/white-fg}";
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
const reviewLabel = pr.reviewScore !== null ? ` [Review: ${pr.reviewScore}%]` : "";
|
|
82
|
-
lines.push(`${ciIndicator} #${pr.number} ${pr.title}${reviewLabel}`);
|
|
83
|
-
lines.push(` ${pr.branch}`);
|
|
84
|
-
}
|
|
85
|
-
return lines.join("\n");
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Render the Log Tail pane content from snapshot data.
|
|
89
|
-
* Shows the last 20 lines from the most recent log file.
|
|
90
|
-
*/
|
|
91
|
-
export function renderLogPane(projectDir, logs) {
|
|
92
|
-
// Find the most recent log file that exists
|
|
93
|
-
const existingLogs = logs.filter((l) => l.exists);
|
|
94
|
-
if (existingLogs.length === 0) {
|
|
95
|
-
return "No log files found";
|
|
96
|
-
}
|
|
97
|
-
// Pick the log with the most recent modification time
|
|
98
|
-
let newestLog = existingLogs[0];
|
|
99
|
-
let newestMtime = 0;
|
|
100
|
-
for (const log of existingLogs) {
|
|
101
|
-
try {
|
|
102
|
-
const stat = fs.statSync(log.path);
|
|
103
|
-
if (stat.mtimeMs > newestMtime) {
|
|
104
|
-
newestMtime = stat.mtimeMs;
|
|
105
|
-
newestLog = log;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
// Ignore stat errors
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
// Read the last 20 lines directly for the dashboard
|
|
113
|
-
const lines = getLastLogLines(newestLog.path, 20);
|
|
114
|
-
if (lines.length === 0) {
|
|
115
|
-
return `${newestLog.name}.log: (empty)`;
|
|
116
|
-
}
|
|
117
|
-
return `--- ${newestLog.name}.log ---\n${lines.join("\n")}`;
|
|
18
|
+
function showMessage(screen, text, type, durationMs = 2000) {
|
|
19
|
+
const colors = { success: "green", error: "red", info: "cyan" };
|
|
20
|
+
const msgBox = blessed.box({
|
|
21
|
+
top: "center",
|
|
22
|
+
left: "center",
|
|
23
|
+
width: Math.min(60, text.length + 6),
|
|
24
|
+
height: 3,
|
|
25
|
+
content: `{center}${text}{/center}`,
|
|
26
|
+
tags: true,
|
|
27
|
+
border: { type: "line" },
|
|
28
|
+
style: { border: { fg: colors[type] }, fg: "white", bg: "black" },
|
|
29
|
+
});
|
|
30
|
+
screen.append(msgBox);
|
|
31
|
+
screen.render();
|
|
32
|
+
setTimeout(() => {
|
|
33
|
+
msgBox.destroy();
|
|
34
|
+
screen.render();
|
|
35
|
+
}, durationMs);
|
|
118
36
|
}
|
|
119
37
|
export function dashboardCommand(program) {
|
|
120
38
|
program
|
|
@@ -123,139 +41,144 @@ export function dashboardCommand(program) {
|
|
|
123
41
|
.option("--interval <seconds>", "Refresh interval in seconds", "10")
|
|
124
42
|
.action(async (options) => {
|
|
125
43
|
const projectDir = process.cwd();
|
|
126
|
-
|
|
44
|
+
let config = loadConfig(projectDir);
|
|
127
45
|
// Create blessed screen
|
|
128
46
|
const screen = blessed.screen({
|
|
129
47
|
smartCSR: true,
|
|
130
48
|
title: "Night Watch Dashboard",
|
|
131
49
|
fullUnicode: true,
|
|
132
50
|
});
|
|
133
|
-
//
|
|
51
|
+
// --- Layout ---
|
|
52
|
+
// Header: row 0, height 1
|
|
134
53
|
const headerBox = blessed.box({
|
|
135
54
|
top: 0,
|
|
136
55
|
left: 0,
|
|
137
56
|
width: "100%",
|
|
138
|
-
height:
|
|
57
|
+
height: 1,
|
|
139
58
|
content: "{center}Night Watch Dashboard{/center}",
|
|
140
59
|
tags: true,
|
|
141
60
|
style: { fg: "cyan", bold: true },
|
|
142
61
|
});
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
top: 3,
|
|
62
|
+
// Tab bar: row 1, height 1
|
|
63
|
+
const tabBar = blessed.box({
|
|
64
|
+
top: 1,
|
|
147
65
|
left: 0,
|
|
148
|
-
width: "
|
|
149
|
-
height:
|
|
150
|
-
label: "[ PRD Queue ]",
|
|
151
|
-
border: { type: "line" },
|
|
152
|
-
scrollable: true,
|
|
153
|
-
alwaysScroll: true,
|
|
154
|
-
scrollbar: { style: { bg: "blue" } },
|
|
155
|
-
style: { border: { fg: "white" } },
|
|
156
|
-
tags: true,
|
|
157
|
-
content: "Loading...",
|
|
158
|
-
});
|
|
159
|
-
// Top-right: Process Status (50% width, 40% height)
|
|
160
|
-
const processPane = blessed.box({
|
|
161
|
-
top: 3,
|
|
162
|
-
left: "50%",
|
|
163
|
-
width: "50%",
|
|
164
|
-
height: "40%",
|
|
165
|
-
label: "[ Processes ]",
|
|
166
|
-
border: { type: "line" },
|
|
167
|
-
scrollable: true,
|
|
168
|
-
alwaysScroll: true,
|
|
169
|
-
scrollbar: { style: { bg: "blue" } },
|
|
170
|
-
style: { border: { fg: "white" } },
|
|
66
|
+
width: "100%",
|
|
67
|
+
height: 1,
|
|
171
68
|
tags: true,
|
|
172
|
-
|
|
69
|
+
style: { fg: "white", bg: "black" },
|
|
70
|
+
content: "",
|
|
173
71
|
});
|
|
174
|
-
//
|
|
175
|
-
const
|
|
176
|
-
top:
|
|
72
|
+
// Content area: rows 2..n-2
|
|
73
|
+
const contentArea = blessed.box({
|
|
74
|
+
top: 2,
|
|
177
75
|
left: 0,
|
|
178
|
-
width: "
|
|
179
|
-
height: "
|
|
180
|
-
label: "[ Pull Requests ]",
|
|
181
|
-
border: { type: "line" },
|
|
182
|
-
scrollable: true,
|
|
183
|
-
alwaysScroll: true,
|
|
184
|
-
scrollbar: { style: { bg: "blue" } },
|
|
185
|
-
style: { border: { fg: "white" } },
|
|
186
|
-
tags: true,
|
|
187
|
-
content: "Loading...",
|
|
188
|
-
});
|
|
189
|
-
// Bottom-right: Log Tail (50% width, 30% height)
|
|
190
|
-
const logPane = blessed.box({
|
|
191
|
-
top: "43%",
|
|
192
|
-
left: "50%",
|
|
193
|
-
width: "50%",
|
|
194
|
-
height: "30%",
|
|
195
|
-
label: "[ Logs ]",
|
|
196
|
-
border: { type: "line" },
|
|
197
|
-
scrollable: true,
|
|
198
|
-
alwaysScroll: true,
|
|
199
|
-
scrollbar: { style: { bg: "blue" } },
|
|
200
|
-
style: { border: { fg: "white" } },
|
|
201
|
-
tags: true,
|
|
202
|
-
content: "Loading...",
|
|
76
|
+
width: "100%",
|
|
77
|
+
height: "100%-4",
|
|
203
78
|
});
|
|
204
|
-
// Footer
|
|
79
|
+
// Footer: bottom row
|
|
205
80
|
const footerBox = blessed.box({
|
|
206
81
|
bottom: 0,
|
|
207
82
|
left: 0,
|
|
208
83
|
width: "100%",
|
|
209
84
|
height: 1,
|
|
210
|
-
content: "
|
|
85
|
+
content: "",
|
|
86
|
+
tags: true,
|
|
211
87
|
style: { fg: "white", bg: "blue" },
|
|
212
88
|
});
|
|
213
|
-
// Append all elements
|
|
214
89
|
screen.append(headerBox);
|
|
215
|
-
screen.append(
|
|
216
|
-
screen.append(
|
|
217
|
-
screen.append(prPane);
|
|
218
|
-
screen.append(logPane);
|
|
90
|
+
screen.append(tabBar);
|
|
91
|
+
screen.append(contentArea);
|
|
219
92
|
screen.append(footerBox);
|
|
220
|
-
//
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
93
|
+
// --- Create tabs ---
|
|
94
|
+
const tabs = [
|
|
95
|
+
createStatusTab(),
|
|
96
|
+
createConfigTab(),
|
|
97
|
+
createSchedulesTab(),
|
|
98
|
+
createActionsTab(),
|
|
99
|
+
createLogsTab(),
|
|
100
|
+
];
|
|
101
|
+
// Append all tab containers to content area
|
|
102
|
+
for (const tab of tabs) {
|
|
103
|
+
contentArea.append(tab.container);
|
|
104
|
+
}
|
|
105
|
+
// --- State ---
|
|
106
|
+
let activeTabIndex = 0;
|
|
107
|
+
let isEditing = false;
|
|
108
|
+
let snapshot = fetchStatusSnapshot(projectDir, config);
|
|
109
|
+
// --- Tab context ---
|
|
110
|
+
const ctx = {
|
|
111
|
+
screen,
|
|
112
|
+
projectDir,
|
|
113
|
+
config,
|
|
114
|
+
snapshot,
|
|
115
|
+
reloadConfig: () => {
|
|
116
|
+
config = loadConfig(projectDir);
|
|
117
|
+
ctx.config = config;
|
|
118
|
+
return config;
|
|
119
|
+
},
|
|
120
|
+
refreshSnapshot: () => {
|
|
121
|
+
snapshot = fetchStatusSnapshot(projectDir, config);
|
|
122
|
+
ctx.snapshot = snapshot;
|
|
123
|
+
return snapshot;
|
|
124
|
+
},
|
|
125
|
+
setFooter: (text) => {
|
|
126
|
+
footerBox.setContent(text);
|
|
127
|
+
},
|
|
128
|
+
showMessage: (text, type, durationMs) => {
|
|
129
|
+
showMessage(screen, text, type, durationMs);
|
|
130
|
+
},
|
|
131
|
+
setEditing: (editing) => {
|
|
132
|
+
isEditing = editing;
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
// --- Tab bar rendering ---
|
|
136
|
+
function renderTabBar() {
|
|
137
|
+
const parts = tabs.map((tab, idx) => {
|
|
138
|
+
const num = idx + 1;
|
|
139
|
+
if (idx === activeTabIndex) {
|
|
140
|
+
return `{white-bg}{black-fg} ${num}:${tab.name} {/black-fg}{/white-bg}`;
|
|
231
141
|
}
|
|
142
|
+
return ` {blue-fg}${num}:${tab.name}{/blue-fg} `;
|
|
232
143
|
});
|
|
144
|
+
tabBar.setContent(parts.join(""));
|
|
145
|
+
}
|
|
146
|
+
// --- Tab switching ---
|
|
147
|
+
function switchTab(newIndex) {
|
|
148
|
+
if (newIndex === activeTabIndex)
|
|
149
|
+
return;
|
|
150
|
+
if (newIndex < 0 || newIndex >= tabs.length)
|
|
151
|
+
return;
|
|
152
|
+
if (isEditing)
|
|
153
|
+
return; // Don't switch while editing
|
|
154
|
+
// Deactivate current tab
|
|
155
|
+
tabs[activeTabIndex].deactivate();
|
|
156
|
+
tabs[activeTabIndex].container.hide();
|
|
157
|
+
// Activate new tab
|
|
158
|
+
activeTabIndex = newIndex;
|
|
159
|
+
tabs[activeTabIndex].container.show();
|
|
160
|
+
renderTabBar();
|
|
161
|
+
tabs[activeTabIndex].activate(ctx);
|
|
233
162
|
screen.render();
|
|
234
|
-
}
|
|
235
|
-
//
|
|
236
|
-
let snapshot = fetchStatusSnapshot(projectDir, config);
|
|
237
|
-
// Render all panes from snapshot data
|
|
238
|
-
const renderPanes = (snap) => {
|
|
239
|
-
prdPane.setContent(renderPrdPane(snap.prds));
|
|
240
|
-
processPane.setContent(renderProcessPane(snap.processes));
|
|
241
|
-
prPane.setContent(renderPrPane(snap.prs));
|
|
242
|
-
logPane.setContent(renderLogPane(snap.projectDir, snap.logs));
|
|
243
|
-
// Auto-scroll log pane to bottom
|
|
244
|
-
logPane.setScrollPerc(100);
|
|
245
|
-
};
|
|
246
|
-
// Auto-refresh setup
|
|
163
|
+
}
|
|
164
|
+
// --- Header ---
|
|
247
165
|
const intervalSeconds = parseInt(options.interval, 10) || 10;
|
|
248
166
|
let countdown = intervalSeconds;
|
|
249
|
-
|
|
250
|
-
headerBox.setContent(`{center}Night Watch: ${snapshot.projectName} | Provider: ${config.provider} | Last
|
|
251
|
-
}
|
|
252
|
-
|
|
167
|
+
function updateHeader() {
|
|
168
|
+
headerBox.setContent(`{center}Night Watch: ${snapshot.projectName} | Provider: ${config.provider} | Last: ${snapshot.timestamp.toLocaleTimeString()} | Next: ${countdown}s{/center}`);
|
|
169
|
+
}
|
|
170
|
+
// --- Refresh ---
|
|
171
|
+
function refreshData() {
|
|
172
|
+
config = loadConfig(projectDir);
|
|
173
|
+
ctx.config = config;
|
|
253
174
|
snapshot = fetchStatusSnapshot(projectDir, config);
|
|
254
|
-
|
|
175
|
+
ctx.snapshot = snapshot;
|
|
255
176
|
countdown = intervalSeconds;
|
|
256
177
|
updateHeader();
|
|
178
|
+
tabs[activeTabIndex].refresh(ctx);
|
|
257
179
|
screen.render();
|
|
258
|
-
}
|
|
180
|
+
}
|
|
181
|
+
// --- Timer ---
|
|
259
182
|
const timer = setInterval(() => {
|
|
260
183
|
countdown--;
|
|
261
184
|
updateHeader();
|
|
@@ -264,33 +187,52 @@ export function dashboardCommand(program) {
|
|
|
264
187
|
refreshData();
|
|
265
188
|
}
|
|
266
189
|
}, 1000);
|
|
267
|
-
//
|
|
268
|
-
renderPanes(snapshot);
|
|
269
|
-
updateHeader();
|
|
270
|
-
// Wire keyboard handlers
|
|
190
|
+
// --- Global keyboard handlers ---
|
|
271
191
|
screen.key(["q", "escape"], () => {
|
|
192
|
+
if (isEditing)
|
|
193
|
+
return;
|
|
272
194
|
clearInterval(timer);
|
|
195
|
+
for (const tab of tabs) {
|
|
196
|
+
tab.destroy();
|
|
197
|
+
}
|
|
273
198
|
screen.destroy();
|
|
274
199
|
process.exit(0);
|
|
275
200
|
});
|
|
276
201
|
screen.key(["r"], () => {
|
|
202
|
+
if (isEditing)
|
|
203
|
+
return;
|
|
277
204
|
refreshData();
|
|
278
205
|
});
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
206
|
+
// Tab switching via number keys
|
|
207
|
+
for (let i = 0; i < tabs.length; i++) {
|
|
208
|
+
const idx = i;
|
|
209
|
+
screen.key([String(i + 1)], () => {
|
|
210
|
+
if (isEditing)
|
|
211
|
+
return;
|
|
212
|
+
switchTab(idx);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
// Tab cycling is handled per-tab (Status tab uses Tab for pane focus)
|
|
216
|
+
// Shift+Tab always cycles tabs
|
|
217
|
+
screen.key(["S-tab"], () => {
|
|
218
|
+
if (isEditing)
|
|
219
|
+
return;
|
|
220
|
+
const newIndex = (activeTabIndex - 1 + tabs.length) % tabs.length;
|
|
221
|
+
switchTab(newIndex);
|
|
290
222
|
});
|
|
291
|
-
// Initial
|
|
292
|
-
|
|
293
|
-
|
|
223
|
+
// --- Initial render ---
|
|
224
|
+
// Show only the first tab's container
|
|
225
|
+
for (let i = 0; i < tabs.length; i++) {
|
|
226
|
+
if (i === 0) {
|
|
227
|
+
tabs[i].container.show();
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
tabs[i].container.hide();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
renderTabBar();
|
|
234
|
+
updateHeader();
|
|
235
|
+
tabs[activeTabIndex].activate(ctx);
|
|
294
236
|
screen.render();
|
|
295
237
|
});
|
|
296
238
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/commands/dashboard.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,
|
|
1
|
+
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/commands/dashboard.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoCpC;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiEpD;AAgMD;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoCpC;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiEpD;AAgMD;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgOlD;AAED,eAAe,WAAW,CAAC"}
|
package/dist/commands/init.js
CHANGED
|
@@ -257,7 +257,7 @@ export function initCommand(program) {
|
|
|
257
257
|
console.log();
|
|
258
258
|
header('Night Watch CLI - Initializing');
|
|
259
259
|
// Step 1: Verify git repository
|
|
260
|
-
step(1,
|
|
260
|
+
step(1, 10, 'Checking git repository...');
|
|
261
261
|
if (!isGitRepo(cwd)) {
|
|
262
262
|
uiError('Current directory is not a git repository.');
|
|
263
263
|
console.log('Please run this command from the root of a git repository.');
|
|
@@ -265,7 +265,7 @@ export function initCommand(program) {
|
|
|
265
265
|
}
|
|
266
266
|
success('Git repository found');
|
|
267
267
|
// Step 2: Verify gh CLI
|
|
268
|
-
step(2,
|
|
268
|
+
step(2, 10, 'Checking GitHub CLI (gh)...');
|
|
269
269
|
if (!isGhAuthenticated()) {
|
|
270
270
|
uiError('GitHub CLI (gh) is not authenticated.');
|
|
271
271
|
console.log('Please run: gh auth login');
|
|
@@ -273,7 +273,7 @@ export function initCommand(program) {
|
|
|
273
273
|
}
|
|
274
274
|
success('GitHub CLI is authenticated');
|
|
275
275
|
// Step 3: Detect AI providers
|
|
276
|
-
step(3,
|
|
276
|
+
step(3, 10, 'Detecting AI providers...');
|
|
277
277
|
let selectedProvider;
|
|
278
278
|
if (options.provider) {
|
|
279
279
|
// Validate provider flag
|
|
@@ -330,25 +330,25 @@ export function initCommand(program) {
|
|
|
330
330
|
'${DEFAULT_BRANCH}': defaultBranch,
|
|
331
331
|
};
|
|
332
332
|
// Step 4: Create PRD directory structure
|
|
333
|
-
step(4,
|
|
333
|
+
step(4, 10, 'Creating PRD directory structure...');
|
|
334
334
|
const prdDirPath = path.join(cwd, prdDir);
|
|
335
335
|
const doneDirPath = path.join(prdDirPath, 'done');
|
|
336
336
|
ensureDir(doneDirPath);
|
|
337
337
|
success(`Created ${prdDirPath}/`);
|
|
338
338
|
success(`Created ${doneDirPath}/`);
|
|
339
339
|
// Step 5: Create NIGHT-WATCH-SUMMARY.md
|
|
340
|
-
step(5,
|
|
340
|
+
step(5, 10, 'Creating NIGHT-WATCH-SUMMARY.md...');
|
|
341
341
|
const summaryPath = path.join(prdDirPath, 'NIGHT-WATCH-SUMMARY.md');
|
|
342
342
|
createSummaryFile(summaryPath, force);
|
|
343
343
|
// Step 6: Create logs directory
|
|
344
|
-
step(6,
|
|
344
|
+
step(6, 10, 'Creating logs directory...');
|
|
345
345
|
const logsPath = path.join(cwd, LOG_DIR);
|
|
346
346
|
ensureDir(logsPath);
|
|
347
347
|
success(`Created ${logsPath}/`);
|
|
348
348
|
// Add /logs/ to .gitignore
|
|
349
349
|
addToGitignore(cwd);
|
|
350
350
|
// Step 7: Create .claude/commands directory and copy templates
|
|
351
|
-
step(7,
|
|
351
|
+
step(7, 10, 'Creating Claude slash commands...');
|
|
352
352
|
const commandsDir = path.join(cwd, '.claude', 'commands');
|
|
353
353
|
ensureDir(commandsDir);
|
|
354
354
|
success(`Created ${commandsDir}/`);
|
|
@@ -359,7 +359,7 @@ export function initCommand(program) {
|
|
|
359
359
|
// Copy night-watch-pr-reviewer.md template
|
|
360
360
|
processTemplate('night-watch-pr-reviewer.md', path.join(commandsDir, 'night-watch-pr-reviewer.md'), replacements, force);
|
|
361
361
|
// Step 8: Create config file
|
|
362
|
-
step(8,
|
|
362
|
+
step(8, 10, 'Creating configuration file...');
|
|
363
363
|
const configPath = path.join(cwd, CONFIG_FILE_NAME);
|
|
364
364
|
if (fs.existsSync(configPath) && !force) {
|
|
365
365
|
console.log(` Skipped (exists): ${configPath}`);
|
|
@@ -377,8 +377,18 @@ export function initCommand(program) {
|
|
|
377
377
|
fs.writeFileSync(configPath, configContent);
|
|
378
378
|
success(`Created ${configPath}`);
|
|
379
379
|
}
|
|
380
|
-
// Step 9:
|
|
381
|
-
step(9,
|
|
380
|
+
// Step 9: Register in global registry
|
|
381
|
+
step(9, 10, 'Registering project in global registry...');
|
|
382
|
+
try {
|
|
383
|
+
const { registerProject } = await import('../utils/registry.js');
|
|
384
|
+
const entry = registerProject(cwd);
|
|
385
|
+
success(`Registered as "${entry.name}" in global registry`);
|
|
386
|
+
}
|
|
387
|
+
catch (regErr) {
|
|
388
|
+
console.warn(` Warning: Could not register in global registry: ${regErr instanceof Error ? regErr.message : String(regErr)}`);
|
|
389
|
+
}
|
|
390
|
+
// Step 10: Print summary
|
|
391
|
+
step(10, 10, 'Initialization complete!');
|
|
382
392
|
// Summary with table
|
|
383
393
|
header('Initialization Complete');
|
|
384
394
|
const filesTable = createTable({ head: ['Created Files', ''] });
|
|
@@ -389,6 +399,7 @@ export function initCommand(program) {
|
|
|
389
399
|
filesTable.push(['', '.claude/commands/prd-executor.md']);
|
|
390
400
|
filesTable.push(['', '.claude/commands/night-watch-pr-reviewer.md']);
|
|
391
401
|
filesTable.push(['Config File', CONFIG_FILE_NAME]);
|
|
402
|
+
filesTable.push(['Global Registry', '~/.night-watch/projects.json']);
|
|
392
403
|
console.log(filesTable.toString());
|
|
393
404
|
// Configuration summary
|
|
394
405
|
header('Configuration');
|