@cliphijack/santaclaude 1.0.10 → 1.0.11
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 +22 -11
package/package.json
CHANGED
package/santaclaude.js
CHANGED
|
@@ -106,30 +106,41 @@ function findTranscript(cwd) {
|
|
|
106
106
|
return files[0]; // 가장 최근 수정 = 활성 세션
|
|
107
107
|
} catch (e) { return null; }
|
|
108
108
|
}
|
|
109
|
-
// JSONL
|
|
109
|
+
// 파일 꼬리(최근 maxBytes)만 읽음 — 수MB JSONL 통째로 안 열고 끝부분만(첫 잘린 줄 버림)
|
|
110
|
+
function readTail(file, maxBytes) {
|
|
111
|
+
try {
|
|
112
|
+
const size = fs.statSync(file).size; const start = Math.max(0, size - maxBytes); const len = size - start;
|
|
113
|
+
const fd = fs.openSync(file, 'r'); const buf = Buffer.alloc(len); fs.readSync(fd, buf, 0, len, start); fs.closeSync(fd);
|
|
114
|
+
let s = buf.toString('utf8'); if (start > 0) { const nl = s.indexOf('\n'); if (nl >= 0) s = s.slice(nl + 1); } // 중간부터 읽었으면 깨진 첫 줄 버림
|
|
115
|
+
return s.split('\n');
|
|
116
|
+
} catch (e) { return []; }
|
|
117
|
+
}
|
|
118
|
+
// JSONL → user/assistant 턴 (툴콜=칩, 첨부이미지=data URL). 파일 꼬리만 읽고 최근 maxTurns개.
|
|
110
119
|
function parseTurns(file, maxTurns) {
|
|
111
|
-
const out = [];
|
|
112
|
-
|
|
120
|
+
const out = []; let imgBudget = 8 * 1024 * 1024; // 전체 이미지 base64 합계 상한(모바일 보호)
|
|
121
|
+
const lines = readTail(file, 2 * 1024 * 1024); // 최근 ~2MB만 (통째로 X) — 형 지적: "꼭 다 열어야되나"
|
|
122
|
+
function grabImgs(c) { const out2 = []; if (!Array.isArray(c)) return out2; for (const b of c) { if (b && b.type === 'image' && b.source) { const s = b.source; if (s.type === 'base64' && s.data && imgBudget > s.data.length) { imgBudget -= s.data.length; out2.push('data:' + (s.media_type || 'image/png') + ';base64,' + s.data); } else if (s.type === 'url' && s.url) out2.push(String(s.url)); } } return out2; }
|
|
113
123
|
for (const line of lines) {
|
|
114
124
|
if (!line) continue; let o; try { o = JSON.parse(line); } catch (e) { continue; }
|
|
115
125
|
if (o.type !== 'user' && o.type !== 'assistant') continue;
|
|
116
126
|
const m = o.message; if (!m) continue; const c = m.content;
|
|
117
127
|
if (o.type === 'user') {
|
|
118
|
-
let text = '';
|
|
128
|
+
let text = ''; const imgs = grabImgs(c);
|
|
119
129
|
if (typeof c === 'string') text = c;
|
|
120
|
-
else if (Array.isArray(c)) { const t = c.filter((b) => b && b.type === 'text').map((b) => b.text); if (!t.length) continue; text = t.join('\n'); } //
|
|
121
|
-
text = String(text || '').trim();
|
|
122
|
-
if (/^<(command-name|local-command|command-message|command-args)/.test(text)) continue; // 슬래시명령 메타 스킵
|
|
123
|
-
|
|
130
|
+
else if (Array.isArray(c)) { const t = c.filter((b) => b && b.type === 'text').map((b) => b.text); if (!t.length && !imgs.length) continue; text = t.join('\n'); } // 텍스트도 이미지도 없으면(tool_result만) 스킵
|
|
131
|
+
text = String(text || '').trim();
|
|
132
|
+
if (text && /^<(command-name|local-command|command-message|command-args)/.test(text)) continue; // 슬래시명령 메타 스킵
|
|
133
|
+
if (!text && !imgs.length) continue;
|
|
134
|
+
out.push({ role: 'user', text: text.slice(0, 8000), imgs });
|
|
124
135
|
} else {
|
|
125
|
-
let text = '', tools = [];
|
|
136
|
+
let text = '', tools = []; const imgs = grabImgs(c);
|
|
126
137
|
if (typeof c === 'string') text = c;
|
|
127
138
|
else if (Array.isArray(c)) for (const b of c) {
|
|
128
139
|
if (b && b.type === 'text' && b.text) text += (text ? '\n' : '') + b.text;
|
|
129
140
|
else if (b && b.type === 'tool_use') { const inp = b.input || {}; const hint = inp.command ? String(inp.command) : (inp.file_path ? String(inp.file_path).split('/').pop() : (inp.path ? String(inp.path) : '')); tools.push((b.name || 'tool') + (hint ? ': ' + hint.slice(0, 70) : '')); }
|
|
130
141
|
}
|
|
131
|
-
text = String(text || '').trim(); if (!text && !tools.length) continue;
|
|
132
|
-
out.push({ role: 'assistant', text: text.slice(0, 8000), tools });
|
|
142
|
+
text = String(text || '').trim(); if (!text && !tools.length && !imgs.length) continue;
|
|
143
|
+
out.push({ role: 'assistant', text: text.slice(0, 8000), tools, imgs });
|
|
133
144
|
}
|
|
134
145
|
}
|
|
135
146
|
return out.slice(-Math.max(10, Math.min(200, maxTurns || 60)));
|