@cliphijack/santaclaude 1.0.2 → 1.0.4

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 (2) hide show
  1. package/package.json +1 -1
  2. package/santaclaude.js +12 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cliphijack/santaclaude",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "publishConfig": { "access": "public" },
5
5
  "description": "SantaClaude 커넥터 — 클라우드 예약을 내 로컬 Claude(tmux)에 발사",
6
6
  "bin": { "santaclaude": "./santaclaude.js" },
package/santaclaude.js CHANGED
@@ -31,9 +31,16 @@ function saveConf(c) { fs.writeFileSync(CONF, JSON.stringify(c, null, 2)); }
31
31
  function paneExists(pane) { try { execFileSync('tmux', ['has-session', '-t', pane.split(':')[0]], { stdio: 'ignore' }); return true; } catch { return false; } }
32
32
 
33
33
  function inject(pane, message) {
34
- const oneLine = String(message).replace(/[\r\n]+/g, ' ');
35
- execFileSync('tmux', ['send-keys', '-t', pane, '-l', oneLine]);
36
- setTimeout(() => { try { execFileSync('tmux', ['send-keys', '-t', pane, 'Enter']); } catch (e) {} }, 350);
34
+ const msg = String(message);
35
+ if (/[\r\n]/.test(msg)) {
36
+ // 멀티라인 tmux paste-buffer로 줄바꿈 보존 주입 (claude code가 bracketed paste로 입력 인식)
37
+ execFileSync('tmux', ['set-buffer', '-b', 'sc-inj', msg]);
38
+ execFileSync('tmux', ['paste-buffer', '-b', 'sc-inj', '-p', '-d', '-t', pane]); // -p bracketed, -d 버퍼삭제
39
+ setTimeout(() => { try { execFileSync('tmux', ['send-keys', '-t', pane, 'Enter']); } catch (e) {} }, 400);
40
+ } else {
41
+ execFileSync('tmux', ['send-keys', '-t', pane, '-l', msg]);
42
+ setTimeout(() => { try { execFileSync('tmux', ['send-keys', '-t', pane, 'Enter']); } catch (e) {} }, 350);
43
+ }
37
44
  }
38
45
  // tmux 세션 새로 만들고 그 안에 claude 자동 실행 (cwd 지정 시 그 폴더에서 = 프로젝트별 분리)
39
46
  function spawnClaude(session, cmd, cwd) {
@@ -270,7 +277,7 @@ async function run(conf) {
270
277
  process.on('SIGINT', () => { clearInterval(hbIv); clearInterval(scrIv); clearInterval(scanIv); try { ws && ws.close(); } catch (e) {} console.log('\n🛷 커넥터 종료. 너의 루돌프들은 자러 간다.'); process.exit(0); });
271
278
  } else {
272
279
  console.log(` ℹ️ 이 node는 WebSocket(21+) 미지원 — 폴링 모드로 동작 (DO 백엔드라 KV write 0 동일, 발사 ±${Math.round(every / 1000)}초). node 21+ 쓰면 자동 WebSocket.`);
273
- await pollTick(); const pollIv = setInterval(pollTick, every);
280
+ await pollTick(); const pollIv = setInterval(pollTick, Math.max(every, 60000)); // 폴백은 최소 60초(서버 부담↓, 비실시간 유저라 OK)
274
281
  process.on('SIGINT', () => { clearInterval(pollIv); clearInterval(scanIv); console.log('\n🛷 커넥터 종료. 너의 루돌프들은 자러 간다.'); process.exit(0); });
275
282
  }
276
283
  }
@@ -285,6 +292,7 @@ async function main() {
285
292
  const conf = { token, pane, api: a.api || DEFAULT_API, every: a.every ? Number(a.every) : 20 };
286
293
  if (a['no-spawn']) conf.spawn = false;
287
294
  if (a['claude-cmd']) conf.claudeCmd = a['claude-cmd'];
295
+ if (a.publisher) conf.publisher = String(a.publisher).replace(/[^a-zA-Z0-9-]/g, '').toLowerCase(); // 마켓 publisher
288
296
  saveConf(conf);
289
297
  console.log(`✅ 페어링 저장 → ${CONF}`);
290
298
  return run(conf);