@cliphijack/santaclaude 1.0.5 → 1.0.7
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 +14 -10
package/package.json
CHANGED
package/santaclaude.js
CHANGED
|
@@ -277,6 +277,15 @@ async function run(conf) {
|
|
|
277
277
|
const w = (cmd.name && windowExists(session, cmd.name)) ? (session + ':' + cmd.name) : pane;
|
|
278
278
|
execFileSync('tmux', ['send-keys', '-t', w, String(cmd.key || '')]);
|
|
279
279
|
console.log(` ⌨️ 키 → ${w}: ${cmd.key}`);
|
|
280
|
+
} else if (cmd.action === 'resize') {
|
|
281
|
+
// 웹 뷰어 폭에 맞춰 tmux 윈도우 리사이즈 — claude TUI가 그 폭으로 reflow(모바일 가로스크롤 해소)
|
|
282
|
+
// 보통 cols만 옴 = 폭만 맞추고 높이는 그대로(스크롤백으로 세로 내역 풍부하게). rows 오면 같이 적용.
|
|
283
|
+
const w = (cmd.name && windowExists(session, cmd.name)) ? (session + ':' + cmd.name) : pane;
|
|
284
|
+
const c = parseInt(cmd.cols) || 0, rr = parseInt(cmd.rows) || 0;
|
|
285
|
+
const args = ['resize-window', '-t', w];
|
|
286
|
+
if (c > 0) args.push('-x', String(Math.max(20, Math.min(400, c))));
|
|
287
|
+
if (rr > 0) args.push('-y', String(Math.max(10, Math.min(200, rr))));
|
|
288
|
+
if (args.length > 3) { try { execFileSync('tmux', args); console.log(` 📐 리사이즈 ${w} → 폭${c || '그대로'}${rr ? '×높이' + rr : ''}`); } catch (e) {} }
|
|
280
289
|
}
|
|
281
290
|
} catch (e) { console.warn(` ⚠️ 제어 실패(${cmd.action} ${cmd.name}): ${e.message}`); }
|
|
282
291
|
}
|
|
@@ -307,10 +316,8 @@ async function run(conf) {
|
|
|
307
316
|
const r = await fetch(api + '/api/skill', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ token, name, publisher, files, public: true }) });
|
|
308
317
|
const j = await r.json();
|
|
309
318
|
if (j.ok) {
|
|
310
|
-
console.log(` 🏪 스킬 "${name}" 마켓 클린등록 완료`);
|
|
319
|
+
console.log(` 🏪 스킬 "${name}" 마켓 클린등록 완료`); // 확인은 웹 마켓에 — claude 입력칸 주입 금지(사용자 메시지로 오인됨)
|
|
311
320
|
try { fs.rmSync(d, { recursive: true, force: true }); } catch (e) {}
|
|
312
|
-
execFileSync('tmux', ['send-keys', '-t', pane, '-l', '🏪 "' + name + '" 마켓에 클린 등록됐어!']);
|
|
313
|
-
setTimeout(() => { try { execFileSync('tmux', ['send-keys', '-t', pane, 'Enter']); } catch (e) {} }, 300);
|
|
314
321
|
} else { console.warn(` 스킬 등록 실패(${name}): ${j.error}`); try { fs.unlinkSync(path.join(d, 'READY')); } catch (e) {} }
|
|
315
322
|
} catch (e) { console.error('[scan fetch err]', e.message); }
|
|
316
323
|
}
|
|
@@ -330,10 +337,8 @@ async function run(conf) {
|
|
|
330
337
|
try {
|
|
331
338
|
const j = await post(api, '/api/schedule', Object.assign({}, req, { token }));
|
|
332
339
|
if (j.ok) {
|
|
333
|
-
console.log(` 🎄 세션 예약 등록 — ${req.kind || 'once'} · ${String(req.message).slice(0, 40)}`);
|
|
340
|
+
console.log(` 🎄 세션 예약 등록 — ${req.kind || 'once'} · ${String(req.message).slice(0, 40)}`); // 확인은 웹 예약내역에 — claude 주입 금지
|
|
334
341
|
try { fs.unlinkSync(fp); } catch (e) {}
|
|
335
|
-
execFileSync('tmux', ['send-keys', '-t', pane, '-l', '🎄 예약 걸렸어 — ' + String(req.message).slice(0, 40)]);
|
|
336
|
-
setTimeout(() => { try { execFileSync('tmux', ['send-keys', '-t', pane, 'Enter']); } catch (e) {} }, 300);
|
|
337
342
|
} else { console.warn(` 예약 실패: ${j.error}`); try { fs.renameSync(fp, fp + '.err'); } catch (e) {} }
|
|
338
343
|
} catch (e) { console.error('[sched fetch err]', e.message); }
|
|
339
344
|
}
|
|
@@ -343,7 +348,7 @@ async function run(conf) {
|
|
|
343
348
|
// 루돌프가 사용자에게 보내는 파일 — santa-show 스킬이 ~/.santaclaude/outbox/ 에 복사하면 릴레이
|
|
344
349
|
const OUTBOXDIR = path.join(os.homedir(), '.santaclaude', 'outbox');
|
|
345
350
|
const MAXOUT = 18 * 1024 * 1024; // 18MB (KV 릴레이 한계 — 초과는 R2 예정)
|
|
346
|
-
|
|
351
|
+
// 주의: 상태 알림을 claude pane에 send-keys 하면 사용자 메시지로 오인돼 claude가 되받아침 → 절대 금지. 확인은 웹 UI(드로어)에서.
|
|
347
352
|
async function scanOutbox() {
|
|
348
353
|
try {
|
|
349
354
|
if (!fs.existsSync(OUTBOXDIR)) return;
|
|
@@ -352,7 +357,7 @@ async function run(conf) {
|
|
|
352
357
|
const fp = path.join(OUTBOXDIR, fn);
|
|
353
358
|
let st; try { st = fs.statSync(fp); } catch (e) { continue; }
|
|
354
359
|
if (!st.isFile()) continue;
|
|
355
|
-
if (st.size > MAXOUT) { console.warn(` ⚠️ "${fn}" ${(st.size / 1048576).toFixed(1)}MB > 18MB — 못
|
|
360
|
+
if (st.size > MAXOUT) { console.warn(` ⚠️ "${fn}" ${(st.size / 1048576).toFixed(1)}MB > 18MB — 못 보냄(R2 대기)`); try { fs.renameSync(fp, fp + '.toobig'); } catch (e) {} continue; }
|
|
356
361
|
const ext = (fn.split('.').pop() || '').toLowerCase();
|
|
357
362
|
const mime = EXT_MIME[ext] || 'application/octet-stream';
|
|
358
363
|
let data; try { data = fs.readFileSync(fp).toString('base64'); } catch (e) { continue; }
|
|
@@ -360,9 +365,8 @@ async function run(conf) {
|
|
|
360
365
|
const j = await post(api, '/api/upload', { token, data, mime, name: fn });
|
|
361
366
|
if (j && j.id) {
|
|
362
367
|
await post(api, '/api/outfile', { token, id: j.id, name: fn, mime, size: st.size }).catch(() => {});
|
|
363
|
-
console.log(` 📤 "${fn}" (${(st.size / 1024).toFixed(0)}KB) → 사용자 화면으로 보냄`);
|
|
368
|
+
console.log(` 📤 "${fn}" (${(st.size / 1024).toFixed(0)}KB) → 사용자 화면으로 보냄`); // 확인은 웹 드로어 '받은파일'에 — claude 주입 금지
|
|
364
369
|
try { fs.unlinkSync(fp); } catch (e) {}
|
|
365
|
-
tmuxNote('📤 보냈어 — ' + fn);
|
|
366
370
|
} else { console.warn(` 파일 보내기 실패(${fn}): ${j && j.error}`); try { fs.renameSync(fp, fp + '.err'); } catch (e) {} }
|
|
367
371
|
} catch (e) { console.error('[outbox fetch err]', e.message); }
|
|
368
372
|
}
|