@cliphijack/santaclaude 1.0.22 → 1.0.24
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/package.json +1 -1
- package/santaclaude.js +48 -1
package/package.json
CHANGED
package/santaclaude.js
CHANGED
|
@@ -16,6 +16,51 @@ const fs = require('fs');
|
|
|
16
16
|
const os = require('os');
|
|
17
17
|
const path = require('path');
|
|
18
18
|
|
|
19
|
+
const VER = (() => { try { return require('./package.json').version; } catch (e) { return '0'; } })();
|
|
20
|
+
const VIA_NPX = __dirname.includes('_npx') || __dirname.includes('npm-cache') || process.env.SC_AUTOUP === '1';
|
|
21
|
+
|
|
22
|
+
function verGt(a, b) { const pa = String(a).split('.').map(Number), pb = String(b).split('.').map(Number); for (let i = 0; i < 3; i++) { if ((pa[i] || 0) > (pb[i] || 0)) return true; if ((pa[i] || 0) < (pb[i] || 0)) return false; } return false; }
|
|
23
|
+
const _TGT = path.join(os.homedir(), '.santaclaude-target'); // 워커가 지정한 목표 버전
|
|
24
|
+
const _GOOD = path.join(os.homedir(), '.santaclaude-good'); // 60초+ 산 마지막 안정버전(롤백용)
|
|
25
|
+
const _rd = (f) => { try { return fs.readFileSync(f, 'utf8').trim(); } catch (e) { return ''; } };
|
|
26
|
+
|
|
27
|
+
// ── 🔄 자동 업데이트 슈퍼바이저 (안전가드 포함) ──
|
|
28
|
+
// npx로 띄운 경우만: 실제 워커를 자식(@목표버전)으로 돌린다. 워커가 새 버전 감지하면 75로 종료 → 여기서 재시작.
|
|
29
|
+
// 안전판: ①새 버전이 계속 빨리 죽으면(크래시루프) 안정버전으로 자동 롤백 ②5연속 실패면 자동재시작 중단.
|
|
30
|
+
if (VIA_NPX && process.env.SC_SUP !== '1' && !process.argv.slice(2).some((a) => a === 'status' || a === 'connect')) {
|
|
31
|
+
const { spawnSync } = require('child_process');
|
|
32
|
+
console.log('🛷 SantaClaude — 자동 업데이트 켜짐 (크래시 롤백·서버 킬스위치 안전가드 포함)');
|
|
33
|
+
let quickFails = 0;
|
|
34
|
+
while (true) {
|
|
35
|
+
let spec = _rd(_TGT) || 'latest';
|
|
36
|
+
if (quickFails >= 3) { const g = _rd(_GOOD); if (g) { spec = g; console.log(` 🛟 새 버전이 반복해서 죽음 → 안정버전 ${g} 으로 고정`); } }
|
|
37
|
+
const t0 = Date.now();
|
|
38
|
+
const r = spawnSync('npx', ['-y', '@cliphijack/santaclaude@' + spec], { stdio: 'inherit', env: { ...process.env, SC_SUP: '1' } });
|
|
39
|
+
const lived = Date.now() - t0;
|
|
40
|
+
if (r.signal === 'SIGINT' || r.signal === 'SIGTERM') process.exit(0); // 사람이 Ctrl+C
|
|
41
|
+
if (lived > 60000) quickFails = 0; else quickFails++; // 60초+ 살았으면 정상
|
|
42
|
+
if (r.status === 75) { console.log(' ⬆️ 업데이트 적용 — 재시작'); continue; }
|
|
43
|
+
if (quickFails >= 5) { console.log(' ⛔ 반복 실패 — 자동 재시작 중단(수동 확인 필요). 마지막 코드 ' + r.status); process.exit(r.status == null ? 1 : r.status); }
|
|
44
|
+
console.log(` ⚠️ 커넥터 종료(코드 ${r.status}) — 6초 후 재시작`); spawnSync('sleep', ['6']);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// 워커(SC_SUP=1): 서버 버전 게이트 확인 → 새 목표면 목표버전 기록하고 75로 종료(슈퍼바이저가 재시작)
|
|
48
|
+
function checkUpdate() {
|
|
49
|
+
fetch(DEFAULT_API + '/api/cli-version', { headers: { accept: 'application/json' } })
|
|
50
|
+
.then((r) => r.json()).then((j) => {
|
|
51
|
+
if (!j || j.paused) return; // 🔴 킬스위치: paused면 업데이트 중단
|
|
52
|
+
const target = String(j.target || '');
|
|
53
|
+
if (!target || target === VER) return; // 목표=현재면 그대로 (target≠VER이면 업/다운 둘다 = 롤백 가능)
|
|
54
|
+
if (process.env.SC_SUP === '1') {
|
|
55
|
+
console.log(` ⬆️ 새 버전 ${target} (현재 ${VER}) — 미리 받는 중(무중단 교체)…`);
|
|
56
|
+
try { fs.writeFileSync(_TGT, target); } catch (e) {}
|
|
57
|
+
// 🔄 프리페치: 교체 전에 새 버전을 npx 캐시에 미리 받아둔다(status는 ping 한 번 하고 종료=데몬 안 띄움) → 재시작 순간 빠름
|
|
58
|
+
try { require('child_process').spawn('npx', ['-y', '@cliphijack/santaclaude@' + target, 'status'], { stdio: 'ignore', detached: true }).unref(); } catch (e) {}
|
|
59
|
+
setTimeout(() => { console.log(' 🔄 교체 — 1~2초 끊겼다 복귀(루돌프·예약은 계속, 빠진 잡은 서버가 보관)'); process.exit(75); }, 5000);
|
|
60
|
+
} else console.log(` ⬆️ 새 버전 ${target} 나옴 (현재 ${VER}) — 재시작 권장: npx -y @cliphijack/santaclaude@latest`);
|
|
61
|
+
}).catch(() => {});
|
|
62
|
+
}
|
|
63
|
+
|
|
19
64
|
const CONF = path.join(os.homedir(), '.santaclaude.json');
|
|
20
65
|
const DEFAULT_API = 'https://santaclaude.app';
|
|
21
66
|
|
|
@@ -334,7 +379,9 @@ async function run(conf) {
|
|
|
334
379
|
|
|
335
380
|
cleanOldImages();
|
|
336
381
|
try { execFileSync('tmux', ['set-option', '-g', 'history-limit', '50000'], { stdio: 'ignore' }); } catch (e) {} // 새로 띄우는 루돌프 pane은 스크롤백 5만줄(기존 pane은 유지)
|
|
337
|
-
|
|
382
|
+
setTimeout(() => { try { fs.writeFileSync(_GOOD, VER); } catch (e) {} }, 60000); // 60초+ 살면 이 버전을 안정버전으로 기록(롤백 기준)
|
|
383
|
+
setTimeout(checkUpdate, 90000); setInterval(checkUpdate, 3 * 3600 * 1000); // 자동 업데이트 체크: 시작 90초 후 + 3시간마다
|
|
384
|
+
console.log(`🛷 SantaClaude 커넥터 가동 v${VER} — pane=${pane} · ${every / 1000}s 폴링 · ${api}`);
|
|
338
385
|
if (paneExists(pane)) {
|
|
339
386
|
// 기존(고객) 세션엔 사람이 안 붙어있을 때만 리사이즈 — 직접 쓰고 있으면 화면 절대 안 건드림
|
|
340
387
|
if (!clientsAttached(session)) { try { execFileSync('tmux', ['resize-window', '-t', session, '-x', '220', '-y', '50']); } catch (e) {} }
|