wormclaude 1.0.22 → 1.0.23
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/dist/cli.js +183 -21
- package/dist/commands.js +1 -0
- package/dist/theme.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import React, { useState, useRef, useEffect } from 'react';
|
|
3
|
-
import { render, Box, Text,
|
|
3
|
+
import { render, Box, Text, useApp, useInput } from 'ink';
|
|
4
4
|
import TextInput from 'ink-text-input';
|
|
5
5
|
import * as path from 'node:path';
|
|
6
6
|
import { theme, VERSION } from './theme.js';
|
|
@@ -11,6 +11,7 @@ import { allToolSchemas, executeToolCalls, executeTool, toolLabel, setToolConfig
|
|
|
11
11
|
import { sanitizeError, sanitizeOutput } from './errorsan.js';
|
|
12
12
|
import { cleanModelText } from './textclean.js';
|
|
13
13
|
import { MarkdownDisplay } from './markdown.js';
|
|
14
|
+
import { highlight } from './highlight.js';
|
|
14
15
|
import { resolveAtMentions } from './atmention.js';
|
|
15
16
|
import { summarizeTools } from './toolSummary.js';
|
|
16
17
|
import { pickTipId, tipText } from './tips.js';
|
|
@@ -85,10 +86,19 @@ const _initHistory = () => {
|
|
|
85
86
|
sys.push({ role: 'system', content: _memCtx });
|
|
86
87
|
return sys;
|
|
87
88
|
};
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
//
|
|
89
|
+
// ALT-SCREEN (alternate screen) — ink normal buffer'da resize'da eski dinamik çerçeveyi
|
|
90
|
+
// silemeyip KASKAD yapıyor (scrollback reflow). Alt-screen tüm ekranı yönetir → resize'da
|
|
91
|
+
// temiz yeniden çizim, kaskad YOK. Kopyalama: alt-screen'de fare seçimi sınırlı olduğundan
|
|
92
|
+
// /kopyala komutu (OSC52 ile panoya) sağlanır. ?1049h alt-screen · ?1007h alternate-scroll.
|
|
93
|
+
try {
|
|
94
|
+
process.stdout.write('\x1b[?1049h\x1b[?1007h\x1b[2J\x1b[H');
|
|
95
|
+
}
|
|
96
|
+
catch { }
|
|
97
|
+
const _leaveAlt = () => { try {
|
|
98
|
+
process.stdout.write('\x1b[?1007l\x1b[?1049l');
|
|
99
|
+
}
|
|
100
|
+
catch { } };
|
|
101
|
+
process.on('exit', _leaveAlt);
|
|
92
102
|
function useDimensions() {
|
|
93
103
|
const [d, setD] = useState({
|
|
94
104
|
cols: process.stdout.columns || 80,
|
|
@@ -148,6 +158,91 @@ function wrapText(text, width) {
|
|
|
148
158
|
}
|
|
149
159
|
return out;
|
|
150
160
|
}
|
|
161
|
+
// Inline markdown (`code` **bold**) → segment'ler.
|
|
162
|
+
function inlineSegs(text, base) {
|
|
163
|
+
const segs = [];
|
|
164
|
+
const re = /(`[^`]+`|\*\*[^*]+\*\*)/g;
|
|
165
|
+
let last = 0;
|
|
166
|
+
let m;
|
|
167
|
+
while ((m = re.exec(text)) !== null) {
|
|
168
|
+
if (m.index > last)
|
|
169
|
+
segs.push({ text: text.slice(last, m.index), color: base });
|
|
170
|
+
const f = m[0];
|
|
171
|
+
if (f.startsWith('`'))
|
|
172
|
+
segs.push({ text: f.slice(1, -1), color: theme.green });
|
|
173
|
+
else
|
|
174
|
+
segs.push({ text: f.slice(2, -2), color: base, bold: true });
|
|
175
|
+
last = re.lastIndex;
|
|
176
|
+
}
|
|
177
|
+
if (last < text.length)
|
|
178
|
+
segs.push({ text: text.slice(last), color: base });
|
|
179
|
+
return segs.length ? segs : [{ text, color: base }];
|
|
180
|
+
}
|
|
181
|
+
// Markdown metnini segment-satırlarına çevirir; kod blokları sözdizimi-vurgulu (highlight()).
|
|
182
|
+
function mdToSegLines(text, W) {
|
|
183
|
+
const out = [];
|
|
184
|
+
const white = theme.white;
|
|
185
|
+
let inCode = false, fence = '', lang = '', code = [];
|
|
186
|
+
const fenceRe = /^ *(`{3,}|~{3,}) *(\w*)? *$/;
|
|
187
|
+
const flush = () => {
|
|
188
|
+
if (lang)
|
|
189
|
+
out.push([{ text: ' ' + lang, dim: true }]);
|
|
190
|
+
for (const toks of highlight(code.join('\n'), lang)) {
|
|
191
|
+
const segs = [{ text: '│ ', dim: true }];
|
|
192
|
+
if (toks.length)
|
|
193
|
+
for (const tk of toks)
|
|
194
|
+
segs.push({ text: tk.text, color: tk.color });
|
|
195
|
+
else
|
|
196
|
+
segs.push({ text: ' ' });
|
|
197
|
+
out.push(segs);
|
|
198
|
+
}
|
|
199
|
+
code = [];
|
|
200
|
+
lang = '';
|
|
201
|
+
fence = '';
|
|
202
|
+
};
|
|
203
|
+
for (const line of text.split('\n')) {
|
|
204
|
+
if (inCode) {
|
|
205
|
+
const fm = line.match(fenceRe);
|
|
206
|
+
if (fm && fm[1][0] === fence[0] && fm[1].length >= fence.length) {
|
|
207
|
+
inCode = false;
|
|
208
|
+
flush();
|
|
209
|
+
}
|
|
210
|
+
else
|
|
211
|
+
code.push(line);
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
const fm = line.match(fenceRe);
|
|
215
|
+
if (fm) {
|
|
216
|
+
inCode = true;
|
|
217
|
+
fence = fm[1];
|
|
218
|
+
lang = (fm[2] || '').trim();
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
const hm = line.match(/^ *(#{1,4}) +(.*)/);
|
|
222
|
+
const um = line.match(/^([ \t]*)([-*+]) +(.*)/);
|
|
223
|
+
const om = line.match(/^([ \t]*)(\d+)\. +(.*)/);
|
|
224
|
+
if (hm) {
|
|
225
|
+
const lvl = hm[1].length;
|
|
226
|
+
out.push([{ text: hm[2], color: lvl <= 2 ? theme.redBright : white, bold: lvl <= 3, italic: lvl > 3 }]);
|
|
227
|
+
}
|
|
228
|
+
else if (um || om) {
|
|
229
|
+
const [, ws, marker, itemText] = (um || om);
|
|
230
|
+
const prefix = om ? `${marker}. ` : '• ';
|
|
231
|
+
const wrapped = wrapText(itemText, Math.max(8, W - ws.length - prefix.length));
|
|
232
|
+
wrapped.forEach((w, i) => out.push([{ text: ' '.repeat(ws.length) + (i === 0 ? prefix : ' '), dim: true }, ...inlineSegs(w, white)]));
|
|
233
|
+
}
|
|
234
|
+
else if (line.trim() === '') {
|
|
235
|
+
out.push([]);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
for (const w of wrapText(line, W))
|
|
239
|
+
out.push(inlineSegs(w, white));
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (inCode)
|
|
243
|
+
flush();
|
|
244
|
+
return out;
|
|
245
|
+
}
|
|
151
246
|
// Tüm öğeleri görsel satır dizisine çevirir (kaydırma satır granülerliğinde).
|
|
152
247
|
function buildLines(items, cols) {
|
|
153
248
|
const lines = [];
|
|
@@ -171,7 +266,8 @@ function buildLines(items, cols) {
|
|
|
171
266
|
lines.push([{ text: '╰' + '─'.repeat(W - 2) + '╯', dim: true }]);
|
|
172
267
|
}
|
|
173
268
|
else if (it.kind === 'assistant') {
|
|
174
|
-
|
|
269
|
+
const seg = mdToSegLines(it.text, W - 2);
|
|
270
|
+
seg.forEach((segs, i) => lines.push(i === 0 ? [{ text: '⏺ ', color: redB, bold: true }, ...segs] : [{ text: ' ', dim: true }, ...segs]));
|
|
175
271
|
}
|
|
176
272
|
else if (it.kind === 'tool') {
|
|
177
273
|
const n = it.result.split('\n').length, chars = it.result.length;
|
|
@@ -440,9 +536,24 @@ function App() {
|
|
|
440
536
|
else if (key.downArrow)
|
|
441
537
|
setCmdSel((s) => (s + 1) % n);
|
|
442
538
|
});
|
|
443
|
-
//
|
|
444
|
-
//
|
|
445
|
-
|
|
539
|
+
// Geçmişte kaydırma: PageUp/PageDown her zaman; boş input'ta ok tuşları (fare tekerleği
|
|
540
|
+
// alternate-scroll ile ok yollar → tekerlekle kaydırma). Alt-screen olduğundan biz yönetiriz.
|
|
541
|
+
useInput((_inp, key) => {
|
|
542
|
+
if (!started || perm || ask || lang === null)
|
|
543
|
+
return;
|
|
544
|
+
if (key.pageUp)
|
|
545
|
+
setScroll((s) => s + 10);
|
|
546
|
+
else if (key.pageDown)
|
|
547
|
+
setScroll((s) => Math.max(0, s - 10));
|
|
548
|
+
else if (input === '' && !busy) {
|
|
549
|
+
if (key.upArrow)
|
|
550
|
+
setScroll((s) => s + 3);
|
|
551
|
+
else if (key.downArrow)
|
|
552
|
+
setScroll((s) => Math.max(0, s - 3));
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
// Yeni mesaj gelince en alta dön
|
|
556
|
+
useEffect(() => { setScroll(0); }, [items.length]);
|
|
446
557
|
// Başlangıçta güven seviyesini (Doğrulanmış Araştırmacı Programı) çek → StatusLine rozeti
|
|
447
558
|
useEffect(() => {
|
|
448
559
|
if (!started)
|
|
@@ -695,6 +806,31 @@ function App() {
|
|
|
695
806
|
v = filtered[Math.min(cmdSel, filtered.length - 1)].name;
|
|
696
807
|
}
|
|
697
808
|
const tok = v.split(' ')[0];
|
|
809
|
+
// /kopyala [hepsi] — son yanıtı (veya tüm sohbeti) panoya kopyalar (OSC52, fare gerekmez).
|
|
810
|
+
if (tok === '/kopyala' || tok === '/copy') {
|
|
811
|
+
const arg = v.slice(tok.length).trim().toLowerCase();
|
|
812
|
+
const en = getLang() === 'en';
|
|
813
|
+
const asst = items.filter((it) => it.kind === 'assistant').map((it) => it.text);
|
|
814
|
+
let text = '';
|
|
815
|
+
if (arg === 'all' || arg === 'hepsi') {
|
|
816
|
+
text = items.map((it) => it.kind === 'user' ? '> ' + it.text : it.kind === 'assistant' ? it.text : '').filter(Boolean).join('\n\n');
|
|
817
|
+
}
|
|
818
|
+
else
|
|
819
|
+
text = asst[asst.length - 1] || '';
|
|
820
|
+
if (!text) {
|
|
821
|
+
push({ kind: 'note', text: en ? 'Nothing to copy.' : 'Kopyalanacak içerik yok.' });
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
try {
|
|
825
|
+
const b64 = Buffer.from(text, 'utf8').toString('base64');
|
|
826
|
+
process.stdout.write(`\x1b]52;c;${b64}\x07`);
|
|
827
|
+
push({ kind: 'note', text: en ? `✓ Copied to clipboard (${text.length} chars).` : `✓ Panoya kopyalandı (${text.length} karakter).` });
|
|
828
|
+
}
|
|
829
|
+
catch {
|
|
830
|
+
push({ kind: 'note', text: en ? 'Copy failed.' : 'Kopyalama başarısız.' });
|
|
831
|
+
}
|
|
832
|
+
return;
|
|
833
|
+
}
|
|
698
834
|
// /agent ve /multi-agent — tek / çoklu alt-agent
|
|
699
835
|
if (tok === '/agent' || tok === '/multi-agent') {
|
|
700
836
|
const task = v.slice(tok.length).trim();
|
|
@@ -788,9 +924,10 @@ function App() {
|
|
|
788
924
|
runAgent(v);
|
|
789
925
|
}
|
|
790
926
|
const { cols, rows } = useDimensions();
|
|
791
|
-
// İlk açılış: dil seçimi
|
|
927
|
+
// İlk açılış: dil seçimi
|
|
792
928
|
if (lang === null) {
|
|
793
|
-
return (React.createElement(Box, { flexDirection: "column", width: cols },
|
|
929
|
+
return (React.createElement(Box, { flexDirection: "column", height: rows, width: cols },
|
|
930
|
+
React.createElement(Banner, null),
|
|
794
931
|
React.createElement(Box, { flexDirection: "column", marginTop: 1, paddingX: 1 },
|
|
795
932
|
React.createElement(Text, { color: theme.redBright, bold: true }, t('lang.title')),
|
|
796
933
|
React.createElement(Box, { flexDirection: "column", marginTop: 1 },
|
|
@@ -802,11 +939,14 @@ function App() {
|
|
|
802
939
|
t('lang.en'))),
|
|
803
940
|
React.createElement(Text, { color: theme.greyDim },
|
|
804
941
|
" ",
|
|
805
|
-
t('lang.hint')))
|
|
942
|
+
t('lang.hint'))),
|
|
943
|
+
React.createElement(Box, { flexGrow: 1 }),
|
|
944
|
+
React.createElement(StatusLine, { model: config.model, ctxTokens: 0 })));
|
|
806
945
|
}
|
|
807
|
-
// Açılış: klasöre güven sorusu (
|
|
946
|
+
// Açılış: klasöre güven sorusu (WormClaude tarzı)
|
|
808
947
|
if (!started) {
|
|
809
|
-
return (React.createElement(Box, { flexDirection: "column", width: cols },
|
|
948
|
+
return (React.createElement(Box, { flexDirection: "column", height: rows, width: cols },
|
|
949
|
+
React.createElement(Banner, null),
|
|
810
950
|
React.createElement(Box, { flexDirection: "column", marginTop: 1, paddingX: 1 },
|
|
811
951
|
React.createElement(Text, { color: theme.redBright, bold: true }, t('trust.accessing')),
|
|
812
952
|
React.createElement(Text, null, " "),
|
|
@@ -824,14 +964,36 @@ function App() {
|
|
|
824
964
|
t('trust.no'))),
|
|
825
965
|
React.createElement(Text, { color: theme.greyDim },
|
|
826
966
|
" ",
|
|
827
|
-
t('trust.hint')))
|
|
967
|
+
t('trust.hint'))),
|
|
968
|
+
React.createElement(Box, { flexGrow: 1 }),
|
|
969
|
+
React.createElement(StatusLine, { model: config.model, ctxTokens: 0 })));
|
|
828
970
|
}
|
|
829
|
-
return (React.createElement(Box, { flexDirection: "column", width: cols },
|
|
830
|
-
React.createElement(
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
971
|
+
return (React.createElement(Box, { flexDirection: "column", height: rows, width: cols },
|
|
972
|
+
React.createElement(Box, { flexDirection: "column", flexGrow: 1, overflow: "hidden" }, (() => {
|
|
973
|
+
// Alt-screen + satır-pencere pager: tüm öğeleri satıra çevir, pencere göster.
|
|
974
|
+
// (Kopyalama /kopyala komutuyla; resize'da kaskad olmaz.)
|
|
975
|
+
const all = buildLines(items, cols);
|
|
976
|
+
const reserve = busy ? 4 : 6;
|
|
977
|
+
const avail = Math.max(4, rows - reserve - (streaming ? 3 : 0) - 2);
|
|
978
|
+
const maxScroll = Math.max(0, all.length - avail);
|
|
979
|
+
const off = Math.min(scroll, maxScroll);
|
|
980
|
+
const startLine = Math.max(0, all.length - avail - off);
|
|
981
|
+
const view = all.slice(startLine, startLine + avail);
|
|
982
|
+
return (React.createElement(React.Fragment, null,
|
|
983
|
+
startLine > 0 ? React.createElement(Text, { color: theme.greyDim },
|
|
984
|
+
" \u2191 ",
|
|
985
|
+
startLine,
|
|
986
|
+
" sat\u0131r \u00B7 PageUp") : null,
|
|
987
|
+
view.map((segs, i) => (React.createElement(Text, { key: i }, segs.length === 0 ? ' ' : segs.map((s, j) => (React.createElement(Text, { key: j, color: s.dim ? theme.greyDim : s.color, bold: s.bold, italic: s.italic }, linkify(s.text))))))),
|
|
988
|
+
off > 0 ? React.createElement(Text, { color: theme.greyDim },
|
|
989
|
+
" \u2193 ",
|
|
990
|
+
off,
|
|
991
|
+
" sat\u0131r \u00B7 PageDown / Son") : null,
|
|
992
|
+
streaming && off === 0 ? (React.createElement(Box, { flexDirection: "row" },
|
|
993
|
+
React.createElement(Text, { color: theme.redBright, bold: true }, "\u23FA "),
|
|
994
|
+
React.createElement(Box, { flexDirection: "column" },
|
|
995
|
+
React.createElement(Text, { color: theme.white }, streaming)))) : null));
|
|
996
|
+
})()),
|
|
835
997
|
perm ? (React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: theme.red, paddingX: 1, marginTop: 1 },
|
|
836
998
|
React.createElement(Text, { color: theme.redBright, bold: true }, t('perm.title', perm.label)),
|
|
837
999
|
permMode === 'feedback' ? (React.createElement(React.Fragment, null,
|
package/dist/commands.js
CHANGED
|
@@ -18,6 +18,7 @@ import { programText, tier } from './program.js';
|
|
|
18
18
|
export const COMMANDS = [
|
|
19
19
|
{ name: '/help', desc: 'komutları ve ipuçlarını göster' },
|
|
20
20
|
{ name: '/clear', desc: 'sohbeti ve geçmişi temizle' },
|
|
21
|
+
{ name: '/kopyala', desc: 'son yanıtı panoya kopyala (/kopyala hepsi · tüm sohbet)' },
|
|
21
22
|
{ name: '/compact', desc: 'geçmişi modelle özetleyip bağlamı küçült' },
|
|
22
23
|
{ name: '/context', desc: 'bağlam / token kullanımını göster' },
|
|
23
24
|
{ name: '/cost', desc: 'oturum token tahminini göster' },
|
package/dist/theme.js
CHANGED