@cliphijack/santaclaude 1.0.12 → 1.0.13
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 -14
package/package.json
CHANGED
package/santaclaude.js
CHANGED
|
@@ -125,38 +125,38 @@ function readDelta(file, from) {
|
|
|
125
125
|
return { lines: complete.split('\n'), off: from + Buffer.byteLength(complete, 'utf8') + 1 };
|
|
126
126
|
} catch (e) { return { lines: [], off: from }; }
|
|
127
127
|
}
|
|
128
|
-
// JSONL 줄들 → user/assistant 턴 (툴콜=칩,
|
|
129
|
-
function linesToTurns(lines) {
|
|
130
|
-
const out = []; let imgBudget =
|
|
131
|
-
function grabImgs(c) {
|
|
128
|
+
// JSONL 줄들 → user/assistant 턴 (툴콜=칩, 이미지). withImgs=false면 이미지 데이터 빼고 개수만(imgn) → seed 초경량·즉시
|
|
129
|
+
function linesToTurns(lines, withImgs) {
|
|
130
|
+
const out = []; let imgBudget = 6 * 1024 * 1024; // 이미지 base64 합계 상한(모바일 보호)
|
|
131
|
+
function grabImgs(c) { let urls = [], n = 0; if (!Array.isArray(c)) return { urls, n }; for (const b of c) { if (b && b.type === 'image' && b.source) { n++; if (withImgs) { const s = b.source; if (s.type === 'base64' && s.data && imgBudget > s.data.length) { imgBudget -= s.data.length; urls.push('data:' + (s.media_type || 'image/png') + ';base64,' + s.data); } else if (s.type === 'url' && s.url) urls.push(String(s.url)); } } } return { urls, n }; }
|
|
132
132
|
for (const line of lines) {
|
|
133
133
|
if (!line) continue; let o; try { o = JSON.parse(line); } catch (e) { continue; }
|
|
134
134
|
if (o.type !== 'user' && o.type !== 'assistant') continue;
|
|
135
135
|
const m = o.message; if (!m) continue; const c = m.content;
|
|
136
136
|
if (o.type === 'user') {
|
|
137
|
-
let text = ''; const
|
|
137
|
+
let text = ''; const gi = grabImgs(c);
|
|
138
138
|
if (typeof c === 'string') text = c;
|
|
139
|
-
else if (Array.isArray(c)) { const t = c.filter((b) => b && b.type === 'text').map((b) => b.text); if (!t.length && !
|
|
139
|
+
else if (Array.isArray(c)) { const t = c.filter((b) => b && b.type === 'text').map((b) => b.text); if (!t.length && !gi.n) continue; text = t.join('\n'); } // 텍스트도 이미지도 없으면(tool_result만) 스킵
|
|
140
140
|
text = String(text || '').trim();
|
|
141
141
|
if (text && /^<(command-name|local-command|command-message|command-args)/.test(text)) continue; // 슬래시명령 메타 스킵
|
|
142
|
-
if (!text && !
|
|
143
|
-
out.push({ role: 'user', text: text.slice(0, 8000), imgs });
|
|
142
|
+
if (!text && !gi.n) continue;
|
|
143
|
+
out.push({ role: 'user', text: text.slice(0, 8000), imgs: gi.urls, imgn: gi.n });
|
|
144
144
|
} else {
|
|
145
|
-
let text = '', tools = []; const
|
|
145
|
+
let text = '', tools = []; const gi = grabImgs(c);
|
|
146
146
|
if (typeof c === 'string') text = c;
|
|
147
147
|
else if (Array.isArray(c)) for (const b of c) {
|
|
148
148
|
if (b && b.type === 'text' && b.text) text += (text ? '\n' : '') + b.text;
|
|
149
149
|
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) : '')); }
|
|
150
150
|
}
|
|
151
|
-
text = String(text || '').trim(); if (!text && !tools.length && !
|
|
152
|
-
out.push({ role: 'assistant', text: text.slice(0, 8000), tools, imgs });
|
|
151
|
+
text = String(text || '').trim(); if (!text && !tools.length && !gi.n) continue;
|
|
152
|
+
out.push({ role: 'assistant', text: text.slice(0, 8000), tools, imgs: gi.urls, imgn: gi.n });
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
return out;
|
|
156
156
|
}
|
|
157
|
-
// 파일 꼬리(최근 2MB)만 읽어 최근 maxTurns개 (seed
|
|
157
|
+
// 파일 꼬리(최근 2MB)만 읽어 최근 maxTurns개 (seed=텍스트만, 이미지 데이터 X → 초경량 즉시표시)
|
|
158
158
|
function parseTurns(file, maxTurns) {
|
|
159
|
-
return linesToTurns(readTail(file, 2 * 1024 * 1024)).slice(-Math.max(10, Math.min(200, maxTurns || 60)));
|
|
159
|
+
return linesToTurns(readTail(file, 2 * 1024 * 1024), false).slice(-Math.max(10, Math.min(200, maxTurns || 60)));
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
async function post(api, p, body) {
|
|
@@ -502,7 +502,7 @@ async function run(conf) {
|
|
|
502
502
|
if (!ws || ws.readyState !== 1) return; if (Date.now() > txState.until || !txState.file) return;
|
|
503
503
|
let d; try { d = readDelta(txState.file, txState.off); } catch (e) { return; }
|
|
504
504
|
if (!d.lines.length) return; txState.off = d.off;
|
|
505
|
-
const turns = linesToTurns(d.lines); if (!turns.length) return;
|
|
505
|
+
const turns = linesToTurns(d.lines, true); if (!turns.length) return; // 델타는 새 턴 1~2개라 이미지 포함 OK(가벼움)
|
|
506
506
|
try { ws.send(JSON.stringify({ type: 'txdelta', window: txState.win, turns })); console.log(` 💬+ 라이브 델타 ${turns.length}턴`); } catch (e) {}
|
|
507
507
|
}
|
|
508
508
|
|