@cliphijack/santaclaude 1.0.17 → 1.0.19
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 +6 -8
package/package.json
CHANGED
package/santaclaude.js
CHANGED
|
@@ -308,7 +308,7 @@ description: 산타 Gbrain — 내 노트·문서·지식 폴더에서 답을
|
|
|
308
308
|
}
|
|
309
309
|
};
|
|
310
310
|
// 확장자 → MIME (보낼 파일 타입 판별)
|
|
311
|
-
const EXT_MIME = { png: 'image/png', jpg: 'image/jpeg', jpeg: 'image/jpeg', gif: 'image/gif', webp: 'image/webp', svg: 'image/svg+xml', bmp: 'image/bmp', pdf: 'application/pdf', txt: 'text/plain', md: 'text/markdown', csv: 'text/csv', json: 'application/json', log: 'text/plain', html: 'text/html', xml: 'text/xml', mp3: 'audio/mpeg', wav: 'audio/wav', ogg: 'audio/ogg', m4a: 'audio/mp4', flac: 'audio/flac', mp4: 'video/mp4', webm: 'video/webm', mov: 'video/quicktime', mkv: 'video/x-matroska', zip: 'application/zip', gz: 'application/gzip', tar: 'application/x-tar' };
|
|
311
|
+
const EXT_MIME = { png: 'image/png', jpg: 'image/jpeg', jpeg: 'image/jpeg', gif: 'image/gif', webp: 'image/webp', svg: 'image/svg+xml', bmp: 'image/bmp', pdf: 'application/pdf', txt: 'text/plain', md: 'text/markdown', csv: 'text/csv', json: 'application/json', log: 'text/plain', html: 'text/html', xml: 'text/xml', mp3: 'audio/mpeg', wav: 'audio/wav', ogg: 'audio/ogg', m4a: 'audio/mp4', flac: 'audio/flac', mp4: 'video/mp4', webm: 'video/webm', mov: 'video/quicktime', mkv: 'video/x-matroska', zip: 'application/zip', gz: 'application/gzip', tar: 'application/x-tar', xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', xls: 'application/vnd.ms-excel', docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', doc: 'application/msword', pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation', ppt: 'application/vnd.ms-powerpoint', rtf: 'application/rtf', yaml: 'text/yaml', yml: 'text/yaml' };
|
|
312
312
|
function installDefaultSkills(cwd) {
|
|
313
313
|
const base = cwd && fs.existsSync(cwd) ? cwd : os.homedir();
|
|
314
314
|
for (const [name, files] of Object.entries(DEFAULT_SKILLS)) {
|
|
@@ -370,13 +370,11 @@ async function run(conf) {
|
|
|
370
370
|
let r; try { r = await fetch(api + '/api/skill/get?token=' + encodeURIComponent(token) + '&id=' + encodeURIComponent(cmd.skillId || '')); } catch (e) { console.warn(' 스킬 받기 실패'); return; }
|
|
371
371
|
if (!r.ok) { console.warn(' 스킬 없음'); return; }
|
|
372
372
|
const sk = await r.json();
|
|
373
|
-
//
|
|
374
|
-
let cwd = os.homedir();
|
|
375
|
-
try { const pc = execFileSync('tmux', ['display-message', '-t', w, '-p', '#{pane_current_path}'], { encoding: 'utf8' }).trim(); if (pc) cwd = pc; } catch (e) {}
|
|
373
|
+
// 전역 스킬 박스 — 받은 스킬은 ~/.claude/skills/ 에 둬서 모든 루돌프·폴더에서 바로 쓰게 (형 확정: 전역 기본)
|
|
376
374
|
// 폴더 네임스페이스 — santa-{퍼블리셔}-{스킬}: 충돌 방지 + 마켓 출처 식별. SKILL.md 파일명은 표준 고정
|
|
377
375
|
const pub = String(sk.publisher || 'me').replace(/[^a-zA-Z0-9-]/g, '').toLowerCase() || 'me';
|
|
378
376
|
const folder = ('santa-' + pub + '-' + sk.name).replace(/[^a-zA-Z0-9._-]/g, '-').slice(0, 80);
|
|
379
|
-
const sdir = path.join(
|
|
377
|
+
const sdir = path.join(os.homedir(), '.claude', 'skills', folder);
|
|
380
378
|
let cnt = 0;
|
|
381
379
|
for (const f of (sk.files || [])) {
|
|
382
380
|
const safe = String(f.path || '').replace(/\\/g, '/').replace(/(^|\/)\.\.(\/|$)/g, '/').replace(/^\/+/, '');
|
|
@@ -385,8 +383,8 @@ async function run(conf) {
|
|
|
385
383
|
if (!fp.startsWith(sdir)) continue; // 경로 탈출 방지
|
|
386
384
|
try { fs.mkdirSync(path.dirname(fp), { recursive: true }); fs.writeFileSync(fp, String(f.content || '')); cnt++; } catch (e) {}
|
|
387
385
|
}
|
|
388
|
-
console.log(` 🧩 스킬 "${sk.name}" ${cnt}개 파일
|
|
389
|
-
const msg = (sk.prompt && sk.prompt.trim() ? sk.prompt.trim() + ' ' : '') + '(스킬 "' + sk.name + '"이
|
|
386
|
+
console.log(` 🧩 스킬 "${sk.name}" ${cnt}개 파일 → ${sdir} (전역)`);
|
|
387
|
+
const msg = (sk.prompt && sk.prompt.trim() ? sk.prompt.trim() + ' ' : '') + '(스킬 "' + sk.name + '"이 ~/.claude/skills/' + folder + '/ 에 이식됨 — 전역이라 모든 세션에서 사용 가능. SKILL.md 읽고 적용)';
|
|
390
388
|
execFileSync('tmux', ['send-keys', '-t', w, '-l', msg]);
|
|
391
389
|
setTimeout(() => { try { execFileSync('tmux', ['send-keys', '-t', w, 'Enter']); } catch (e) {} }, 300);
|
|
392
390
|
return;
|
|
@@ -404,7 +402,7 @@ async function run(conf) {
|
|
|
404
402
|
const j = await r.json();
|
|
405
403
|
const mime = String(j.mime || '');
|
|
406
404
|
if (!mime.startsWith('image/')) allImg = false;
|
|
407
|
-
const safe = String(im.name || j.name || '').replace(/[
|
|
405
|
+
const safe = String(im.name || j.name || '').replace(/[\/\\\x00-\x1f]/g, '').replace(/\s+/g, '_').slice(0, 80); // 한글 등 유니코드 보존, 경로·제어문자만 제거(execFileSync 무쉘이라 안전)
|
|
408
406
|
let fname;
|
|
409
407
|
if (safe && /\.[A-Za-z0-9]+$/.test(safe)) fname = Date.now() + '_' + paths.length + '_' + safe; // 원본 파일명·확장자 보존
|
|
410
408
|
else { const ext = MIME_EXT[mime] || (mime.includes('png') ? 'png' : mime.includes('webp') ? 'webp' : mime.startsWith('image/') ? 'jpg' : 'bin'); fname = Date.now() + '_' + paths.length + '.' + ext; }
|