wormclaude 1.0.46 → 1.0.47
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/theme.js +1 -1
- package/dist/tui.js +54 -35
- package/package.json +1 -1
package/dist/theme.js
CHANGED
package/dist/tui.js
CHANGED
|
@@ -12,6 +12,7 @@ import { itemAnsi } from './ansi.js';
|
|
|
12
12
|
import { theme, VERSION } from './theme.js';
|
|
13
13
|
import { cleanModelText } from './textclean.js';
|
|
14
14
|
import { COMMANDS, runSlashCommand } from './commands.js';
|
|
15
|
+
import { cmdDesc } from './i18n.js';
|
|
15
16
|
const RESET = '\x1b[0m';
|
|
16
17
|
const hex = (h) => { const m = /^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(h); return m ? `\x1b[38;2;${parseInt(m[1], 16)};${parseInt(m[2], 16)};${parseInt(m[3], 16)}m` : ''; };
|
|
17
18
|
const paint = (s, c, bold = false) => `${bold ? '\x1b[1m' : ''}${c ? hex(c) : ''}${s}${RESET}`;
|
|
@@ -54,7 +55,21 @@ export async function runTui() {
|
|
|
54
55
|
const displayItems = [{ kind: 'banner' }];
|
|
55
56
|
let inputBuf = '', busy = false, streamChars = 0, spin = 0;
|
|
56
57
|
const SPIN = ['·', '✢', '✳', '✶', '✻', '✽', '✶', '✳', '✢'];
|
|
57
|
-
|
|
58
|
+
// Footer yüksekliği DİNAMİK: izin=4, slash menü=N+3 (menü satırları + çizgi/giriş/çizgi), normal=4.
|
|
59
|
+
let prevFH = 4;
|
|
60
|
+
const footerHeight = () => {
|
|
61
|
+
if (perm)
|
|
62
|
+
return 4;
|
|
63
|
+
const m = cmdMatches();
|
|
64
|
+
if (m.length)
|
|
65
|
+
return Math.min(8, m.length) + 3;
|
|
66
|
+
return 4;
|
|
67
|
+
};
|
|
68
|
+
// Yükseklik değiştiyse scroll-region'ı + içeriği yeniden bas; değişmediyse sadece footer'ı çiz.
|
|
69
|
+
const refresh = () => { const fh = footerHeight(); if (fh !== prevFH)
|
|
70
|
+
redrawAll();
|
|
71
|
+
else
|
|
72
|
+
drawFooter(); };
|
|
58
73
|
setToolConfig(config); // araçlar (Write/Bash/Edit…) aynı config'i kullansın
|
|
59
74
|
// İzin (araç onayı) durumu
|
|
60
75
|
let perm = null;
|
|
@@ -81,9 +96,9 @@ export async function runTui() {
|
|
|
81
96
|
};
|
|
82
97
|
async function runCommand(v) {
|
|
83
98
|
busy = true;
|
|
84
|
-
|
|
99
|
+
refresh();
|
|
85
100
|
const timer = setInterval(() => { spin++; if (busy && !perm)
|
|
86
|
-
|
|
101
|
+
refresh(); }, 120);
|
|
87
102
|
try {
|
|
88
103
|
await runSlashCommand(v, cmdCtx);
|
|
89
104
|
}
|
|
@@ -92,7 +107,7 @@ export async function runTui() {
|
|
|
92
107
|
}
|
|
93
108
|
clearInterval(timer);
|
|
94
109
|
busy = false;
|
|
95
|
-
|
|
110
|
+
refresh();
|
|
96
111
|
}
|
|
97
112
|
// ── İkonlu, 2-sütunlu bilgi başlığı (3 sol / 3 sağ) — responsive ──
|
|
98
113
|
function headerLines(W) {
|
|
@@ -115,15 +130,16 @@ export async function runTui() {
|
|
|
115
130
|
return [...L, ...R].map((r) => fit(cell(r), W)); // dar ekran → alt alta
|
|
116
131
|
return [0, 1, 2].map((i) => fit(padVis(cell(L[i]), colW) + cell(R[i]), W)); // geniş → 2 sütun
|
|
117
132
|
}
|
|
118
|
-
// ── Scroll region: üst = içerik (kayar), alt = sabit footer ──
|
|
133
|
+
// ── Scroll region: üst = içerik (kayar), alt = sabit footer (dinamik yükseklik) ──
|
|
119
134
|
function setRegion() {
|
|
120
|
-
const bottom = Math.max(1, rows() -
|
|
135
|
+
const bottom = Math.max(1, rows() - footerHeight() - 1); // footer üstünde 1 boş satır
|
|
121
136
|
process.stdout.write(`\x1b[1;${bottom}r`);
|
|
122
137
|
}
|
|
123
138
|
// ── Sabit footer'ı en alta mutlak konumla çiz (imleci kaydet/geri yükle → içerik bozulmaz) ──
|
|
124
139
|
function drawFooter() {
|
|
125
140
|
const W = Math.max(8, cols());
|
|
126
|
-
const
|
|
141
|
+
const fh = footerHeight();
|
|
142
|
+
const start = rows() - fh + 1;
|
|
127
143
|
const line = paint('─'.repeat(W), theme.red);
|
|
128
144
|
let body;
|
|
129
145
|
if (perm) {
|
|
@@ -139,21 +155,23 @@ export async function runTui() {
|
|
|
139
155
|
if (vis(shown) > avail)
|
|
140
156
|
shown = '…' + shown.slice(-(avail - 1));
|
|
141
157
|
const inputLine = paint('✶ ', theme.redBright, true) + paint(shown, theme.white) + paint('▌', theme.greyDim);
|
|
142
|
-
// Durum satırı KUTUNUN ÜSTÜNDE: slash menü > spinner > ipucu.
|
|
143
158
|
const m = cmdMatches();
|
|
144
|
-
let status;
|
|
145
159
|
if (m.length) {
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
160
|
+
// DİKEY slash menü (alt alta), seçili kırmızı — kutunun üstünde.
|
|
161
|
+
const items = m.slice(0, 8);
|
|
162
|
+
const sel = Math.min(cmdSel, items.length - 1);
|
|
163
|
+
const menu = items.map((c, i) => {
|
|
164
|
+
const on = i === sel;
|
|
165
|
+
return ' ' + paint((on ? '✶ ' : ' ') + c.name.padEnd(13), on ? theme.redBright : theme.grey) + paint(cmdDesc(c.name) || c.desc || '', theme.greyDim);
|
|
166
|
+
});
|
|
167
|
+
body = [...menu, line, inputLine, line];
|
|
152
168
|
}
|
|
153
169
|
else {
|
|
154
|
-
status =
|
|
170
|
+
const status = busy
|
|
171
|
+
? paint(` ${SPIN[spin % SPIN.length]} çalışıyor…${streamChars ? ' ' + streamChars + ' karakter' : ''}`, theme.grey)
|
|
172
|
+
: paint(' / komutlar · ↑↓ geçmiş · /kopyala · Ctrl+C çıkış', theme.greyDim);
|
|
173
|
+
body = [status, line, inputLine, line];
|
|
155
174
|
}
|
|
156
|
-
body = [status, line, inputLine, line];
|
|
157
175
|
}
|
|
158
176
|
let out = '\x1b7'; // imleci kaydet
|
|
159
177
|
body.forEach((l, i) => { out += `\x1b[${start + i};1H\x1b[2K` + fit(l, W); });
|
|
@@ -162,6 +180,7 @@ export async function runTui() {
|
|
|
162
180
|
}
|
|
163
181
|
// ── Her şeyi yeni boyutta yeniden bas (banner/kod responsive); içerik bölgesine ──
|
|
164
182
|
function redrawAll() {
|
|
183
|
+
prevFH = footerHeight(); // mevcut footer yüksekliğini kaydet (refresh karşılaştırması için)
|
|
165
184
|
setRegion();
|
|
166
185
|
process.stdout.write('\x1b[2J\x1b[3J\x1b[H');
|
|
167
186
|
const W = cols();
|
|
@@ -173,7 +192,7 @@ export async function runTui() {
|
|
|
173
192
|
drawFooter();
|
|
174
193
|
}
|
|
175
194
|
// İçerik öğesini ekle + içerik alanına bas (taşarsa scrollback'e → kopyalanır). Footer sabit kalır.
|
|
176
|
-
const printItem = (it) => { displayItems.push(it); process.stdout.write(itemAnsi(it, cols()) + '\n');
|
|
195
|
+
const printItem = (it) => { displayItems.push(it); process.stdout.write(itemAnsi(it, cols()) + '\n'); refresh(); };
|
|
177
196
|
// ── Agent döngüsü (M2: araçlar + izin). Model tool çağırırsa izin sorulup çalıştırılır,
|
|
178
197
|
// sonuç geçmişe eklenip döngü devam eder; tool yoksa biter. ──
|
|
179
198
|
async function runTurn(userText) {
|
|
@@ -181,7 +200,7 @@ export async function runTui() {
|
|
|
181
200
|
streamChars = 0;
|
|
182
201
|
history.push({ role: 'user', content: userText });
|
|
183
202
|
const timer = setInterval(() => { spin++; if (busy && !perm)
|
|
184
|
-
|
|
203
|
+
refresh(); }, 120);
|
|
185
204
|
let lastSig = '', sameCount = 0;
|
|
186
205
|
try {
|
|
187
206
|
for (let iter = 0; iter < 25; iter++) {
|
|
@@ -226,7 +245,7 @@ export async function runTui() {
|
|
|
226
245
|
if (allowAll.has(c.name))
|
|
227
246
|
return resolve('allow');
|
|
228
247
|
perm = { label: toolLabel(c.name, args), name: c.name, resolve };
|
|
229
|
-
|
|
248
|
+
refresh();
|
|
230
249
|
}),
|
|
231
250
|
onResult: (c, _i, res) => printItem({ kind: 'tool', label: toolLabel(c.name, res.args), result: sanitizeOutput(res.output), ok: res.ok }),
|
|
232
251
|
});
|
|
@@ -240,7 +259,7 @@ export async function runTui() {
|
|
|
240
259
|
clearInterval(timer);
|
|
241
260
|
busy = false;
|
|
242
261
|
perm = null;
|
|
243
|
-
|
|
262
|
+
refresh();
|
|
244
263
|
}
|
|
245
264
|
// ── Kurulum ──
|
|
246
265
|
readline.emitKeypressEvents(process.stdin);
|
|
@@ -270,31 +289,31 @@ export async function runTui() {
|
|
|
270
289
|
if (key && key.ctrl && key.name === 'c') {
|
|
271
290
|
perm = null;
|
|
272
291
|
r({ deny: 'kullanıcı iptal etti' });
|
|
273
|
-
|
|
292
|
+
refresh();
|
|
274
293
|
return;
|
|
275
294
|
}
|
|
276
295
|
if (k === 'e' || k === '1' || (key && key.name === 'return')) {
|
|
277
296
|
perm = null;
|
|
278
297
|
r('allow');
|
|
279
|
-
|
|
298
|
+
refresh();
|
|
280
299
|
}
|
|
281
300
|
else if (k === 't' || k === '2') {
|
|
282
301
|
allowAll.add(nm);
|
|
283
302
|
perm = null;
|
|
284
303
|
r('allow');
|
|
285
|
-
|
|
304
|
+
refresh();
|
|
286
305
|
}
|
|
287
306
|
else if (k === 'h' || k === '3' || (key && key.name === 'escape')) {
|
|
288
307
|
perm = null;
|
|
289
308
|
r({ deny: '' });
|
|
290
|
-
|
|
309
|
+
refresh();
|
|
291
310
|
}
|
|
292
311
|
return;
|
|
293
312
|
}
|
|
294
313
|
if (key && key.ctrl && key.name === 'c') {
|
|
295
314
|
if (inputBuf) {
|
|
296
315
|
inputBuf = '';
|
|
297
|
-
|
|
316
|
+
refresh();
|
|
298
317
|
return;
|
|
299
318
|
}
|
|
300
319
|
const now = Date.now();
|
|
@@ -313,13 +332,13 @@ export async function runTui() {
|
|
|
313
332
|
const m = cmdMatches();
|
|
314
333
|
if (m.length) {
|
|
315
334
|
cmdSel = (cmdSel - 1 + m.length) % m.length;
|
|
316
|
-
|
|
335
|
+
refresh();
|
|
317
336
|
return;
|
|
318
337
|
}
|
|
319
338
|
if (inputHistory.length) {
|
|
320
339
|
histIdx = histIdx < 0 ? inputHistory.length - 1 : Math.max(0, histIdx - 1);
|
|
321
340
|
inputBuf = inputHistory[histIdx];
|
|
322
|
-
|
|
341
|
+
refresh();
|
|
323
342
|
}
|
|
324
343
|
return;
|
|
325
344
|
}
|
|
@@ -327,7 +346,7 @@ export async function runTui() {
|
|
|
327
346
|
const m = cmdMatches();
|
|
328
347
|
if (m.length) {
|
|
329
348
|
cmdSel = (cmdSel + 1) % m.length;
|
|
330
|
-
|
|
349
|
+
refresh();
|
|
331
350
|
return;
|
|
332
351
|
}
|
|
333
352
|
if (histIdx >= 0) {
|
|
@@ -338,7 +357,7 @@ export async function runTui() {
|
|
|
338
357
|
}
|
|
339
358
|
else
|
|
340
359
|
inputBuf = inputHistory[histIdx];
|
|
341
|
-
|
|
360
|
+
refresh();
|
|
342
361
|
}
|
|
343
362
|
return;
|
|
344
363
|
}
|
|
@@ -348,7 +367,7 @@ export async function runTui() {
|
|
|
348
367
|
if (m.length) {
|
|
349
368
|
inputBuf = m[Math.min(cmdSel, m.length - 1)].name + ' ';
|
|
350
369
|
cmdSel = 0;
|
|
351
|
-
|
|
370
|
+
refresh();
|
|
352
371
|
}
|
|
353
372
|
return;
|
|
354
373
|
}
|
|
@@ -359,7 +378,7 @@ export async function runTui() {
|
|
|
359
378
|
inputBuf = '';
|
|
360
379
|
histIdx = -1;
|
|
361
380
|
if (!v) {
|
|
362
|
-
|
|
381
|
+
refresh();
|
|
363
382
|
return;
|
|
364
383
|
}
|
|
365
384
|
// Slash komutu: tam eşleşme yoksa menüde SEÇİLİ olanı kullan
|
|
@@ -395,19 +414,19 @@ export async function runTui() {
|
|
|
395
414
|
if (key && key.name === 'backspace') {
|
|
396
415
|
inputBuf = inputBuf.slice(0, -1);
|
|
397
416
|
cmdSel = 0;
|
|
398
|
-
|
|
417
|
+
refresh();
|
|
399
418
|
return;
|
|
400
419
|
}
|
|
401
420
|
if (key && key.name === 'escape') {
|
|
402
421
|
inputBuf = '';
|
|
403
|
-
|
|
422
|
+
refresh();
|
|
404
423
|
return;
|
|
405
424
|
}
|
|
406
425
|
// sadece gerçek yazdırılabilir karakter (her zaman → cevap üretilirken bile type-ahead)
|
|
407
426
|
if (str && !key?.ctrl && !key?.meta && !str.startsWith('\x1b') && !/[\x00-\x1f]/.test(str)) {
|
|
408
427
|
inputBuf += str;
|
|
409
428
|
cmdSel = 0;
|
|
410
|
-
|
|
429
|
+
refresh();
|
|
411
430
|
}
|
|
412
431
|
});
|
|
413
432
|
// resize → settle sonrası her şeyi yeni boyutta yeniden bas (region + banner + footer)
|