kanon-cli 0.1.2 → 0.1.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/bin/kanon.js +1 -1
- package/package.json +1 -1
- package/src/dashboard/server/index.js +94 -0
package/bin/kanon.js
CHANGED
package/package.json
CHANGED
|
@@ -116,5 +116,99 @@ export function createDashboardServer(port = 3737) {
|
|
|
116
116
|
console.log(`Dashboard server running on http://localhost:${port}`);
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
+
// --- Nightly auto-update (4:00 AM) ---
|
|
120
|
+
// Checks every 15 min; when hour=4, checks for update, waits for idle workers, then updates & restarts.
|
|
121
|
+
let autoUpdateDone = null; // date string of last auto-update to avoid repeating same night
|
|
122
|
+
|
|
123
|
+
const autoUpdateTimer = setInterval(async () => {
|
|
124
|
+
try {
|
|
125
|
+
const now = new Date();
|
|
126
|
+
// Use local date string to match local getHours() check
|
|
127
|
+
const today = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
|
|
128
|
+
if (now.getHours() !== 4 || autoUpdateDone === today) return;
|
|
129
|
+
|
|
130
|
+
// Check for update
|
|
131
|
+
const pkgPath = path.resolve(__dirname, '../../../package.json');
|
|
132
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
133
|
+
const current = pkg.version;
|
|
134
|
+
|
|
135
|
+
const resp = await fetch('https://registry.npmjs.org/kanon-cli/latest', {
|
|
136
|
+
headers: { 'Accept': 'application/json' },
|
|
137
|
+
signal: AbortSignal.timeout(5000),
|
|
138
|
+
});
|
|
139
|
+
if (!resp.ok) return;
|
|
140
|
+
const { version: latest } = await resp.json();
|
|
141
|
+
if (!latest || latest === current) {
|
|
142
|
+
autoUpdateDone = today;
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Check if workers are idle (active or queued)
|
|
147
|
+
let busy = false;
|
|
148
|
+
try {
|
|
149
|
+
const lockPath = getAgentLockPath();
|
|
150
|
+
if (fs.existsSync(lockPath)) {
|
|
151
|
+
const lock = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
|
|
152
|
+
// Only query daemon if its process is alive
|
|
153
|
+
let alive = false;
|
|
154
|
+
try { process.kill(lock.pid, 0); alive = true; } catch {}
|
|
155
|
+
if (alive) {
|
|
156
|
+
const statusRes = await fetch(`http://127.0.0.1:${lock.port}/status`, {
|
|
157
|
+
signal: AbortSignal.timeout(3000),
|
|
158
|
+
});
|
|
159
|
+
if (statusRes.ok) {
|
|
160
|
+
const status = await statusRes.json();
|
|
161
|
+
busy = (status.activeWorkers || 0) > 0 || (status.queueLength || 0) > 0;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
} catch {}
|
|
166
|
+
|
|
167
|
+
if (busy) {
|
|
168
|
+
// Workers or queued tasks — try again next interval
|
|
169
|
+
console.log(`[auto-update] Update ${current} → ${latest} available, but workers/queue active. Retrying later.`);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// All clear — install update
|
|
174
|
+
console.log(`[auto-update] Updating kanon-cli ${current} → ${latest}...`);
|
|
175
|
+
autoUpdateDone = today;
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
execSync('npm install -g kanon-cli@latest', { stdio: 'pipe', timeout: 60000 });
|
|
179
|
+
console.log(`[auto-update] Updated to ${latest}. Restarting...`);
|
|
180
|
+
} catch (err) {
|
|
181
|
+
console.error('[auto-update] npm install failed:', err.message);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Stop watch daemon before restart
|
|
186
|
+
try {
|
|
187
|
+
const lockPath = getAgentLockPath();
|
|
188
|
+
if (fs.existsSync(lockPath)) {
|
|
189
|
+
const lock = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
|
|
190
|
+
process.kill(lock.pid, 'SIGTERM');
|
|
191
|
+
}
|
|
192
|
+
} catch {}
|
|
193
|
+
|
|
194
|
+
// Restart dashboard
|
|
195
|
+
setTimeout(() => {
|
|
196
|
+
const binPath = path.resolve(__dirname, '../../../bin/kanon.js');
|
|
197
|
+
const child = spawn(process.execPath, [binPath, 'dashboard', '--no-browser', '-p', String(port)], {
|
|
198
|
+
stdio: 'ignore',
|
|
199
|
+
detached: true,
|
|
200
|
+
cwd: process.cwd(),
|
|
201
|
+
});
|
|
202
|
+
child.unref();
|
|
203
|
+
process.exit(0);
|
|
204
|
+
}, 1000);
|
|
205
|
+
} catch (err) {
|
|
206
|
+
console.error('[auto-update] Error:', err.message);
|
|
207
|
+
}
|
|
208
|
+
}, 15 * 60 * 1000); // check every 15 minutes
|
|
209
|
+
|
|
210
|
+
// Cleanup on server close
|
|
211
|
+
server.on('close', () => clearInterval(autoUpdateTimer));
|
|
212
|
+
|
|
119
213
|
return server;
|
|
120
214
|
}
|