wormclaude 1.0.140 → 1.0.142
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 +41 -9
- package/package.json +1 -1
package/dist/theme.js
CHANGED
package/dist/tui.js
CHANGED
|
@@ -28,6 +28,20 @@ function fmtDur(ms) {
|
|
|
28
28
|
const s = Math.max(0, Math.floor(ms / 1000));
|
|
29
29
|
return s >= 60 ? `${Math.floor(s / 60)}m ${s % 60}s` : `${s}s`;
|
|
30
30
|
}
|
|
31
|
+
// Kullanıcı mesajının dilini tespit et → UI etiketleri (Oluşturulacak/Create file, Yazıldı/Wrote…)
|
|
32
|
+
// konuşma diline uysun. Belirsizse null döner (mevcut dili koru).
|
|
33
|
+
const _TR_HINT = /[çğışöüÇĞİŞÖÜ]|\b(bir|bu|ve|ile|için|nasıl|nedir|var|olan|bana|beni|merhaba|selam|tamam|evet|hayır|değil|çok|yap|yapar|oluştur|kur|yaz|dosya|çalıştır|göster|aç|sil|ekle|değiştir|düzelt|kod|site|uygulama|sunucu|güvenlik|tarama|anlat|nerede|neden|hangisi)\b/i;
|
|
34
|
+
const _EN_HINT = /^(write|make|create|build|fix|add|remove|update|show|run|test|the|what|how|why|where|can you|could you|please|i want|i need|give|generate|implement|explain|tell me|help me)\b/i;
|
|
35
|
+
function _detectMsgLang(text) {
|
|
36
|
+
const s = (text || '').trim();
|
|
37
|
+
if (!s)
|
|
38
|
+
return null;
|
|
39
|
+
if (_TR_HINT.test(s))
|
|
40
|
+
return 'tr';
|
|
41
|
+
if (_EN_HINT.test(s))
|
|
42
|
+
return 'en';
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
31
45
|
// Dosya yolunu çalışma alanına göreli göster (Claude tarzı: "todo/index.html"), yoksa olduğu gibi.
|
|
32
46
|
function relWs(fp) {
|
|
33
47
|
try {
|
|
@@ -95,6 +109,7 @@ export async function runTui() {
|
|
|
95
109
|
];
|
|
96
110
|
const displayItems = [{ kind: 'banner' }];
|
|
97
111
|
let inputBuf = '', inputCur = 0, busy = false, streamChars = 0, spin = 0;
|
|
112
|
+
let turnAbort = null; // ESC ile çalışan turu durdurma
|
|
98
113
|
let taskStart = 0; // görev başlangıç zamanı (spinner'da geçen süre için)
|
|
99
114
|
// Canlı akış artık FOOTER'da DEĞİL — içerik akışına (mesajın altından aşağı) satır-satır basılır.
|
|
100
115
|
const SPIN = ['·', '✢', '✳', '✶', '✻', '✽', '✶', '✳', '✢'];
|
|
@@ -300,6 +315,11 @@ export async function runTui() {
|
|
|
300
315
|
busy = true;
|
|
301
316
|
streamChars = 0;
|
|
302
317
|
taskStart = Date.now();
|
|
318
|
+
turnAbort = new AbortController(); // ESC ile durdurulabilsin
|
|
319
|
+
// UI dili konuşma diline uysun (etiketler: Oluşturulacak/Create file, Yazıldı/Wrote…)
|
|
320
|
+
const _ml = _detectMsgLang(userText);
|
|
321
|
+
if (_ml && _ml !== getLang())
|
|
322
|
+
setLang(_ml);
|
|
303
323
|
if (displayText !== undefined)
|
|
304
324
|
printItem({ kind: 'user', text: displayText }); // skill/@mention: gösterim farklı
|
|
305
325
|
history.push({ role: 'user', content: userText });
|
|
@@ -310,6 +330,8 @@ export async function runTui() {
|
|
|
310
330
|
let reactiveRetried = false; // bağlam taşmasında bir kez compact+retry
|
|
311
331
|
try {
|
|
312
332
|
for (let iter = 0; iter < 25; iter++) {
|
|
333
|
+
if (turnAbort?.signal.aborted)
|
|
334
|
+
break; // ESC ile durduruldu
|
|
313
335
|
streamChars = 0;
|
|
314
336
|
// Oto-compact: bağlam eşiği aşılınca otomatik özetle (uzun sohbet patlamasın)
|
|
315
337
|
if (shouldAutoCompact(history)) {
|
|
@@ -358,7 +380,7 @@ export async function runTui() {
|
|
|
358
380
|
refresh(); // footer'ı dibe yeniden sabitle
|
|
359
381
|
};
|
|
360
382
|
let gotCtxErr = false;
|
|
361
|
-
for await (const ev of streamChat(history, allToolSchemas(), config)) {
|
|
383
|
+
for await (const ev of streamChat(history, allToolSchemas(), config, turnAbort?.signal)) {
|
|
362
384
|
if (ev.type === 'text') {
|
|
363
385
|
answer += ev.text;
|
|
364
386
|
streamChars = answer.length;
|
|
@@ -378,6 +400,8 @@ export async function runTui() {
|
|
|
378
400
|
}
|
|
379
401
|
}
|
|
380
402
|
flushStream(true); // kalan yarım satırı bas
|
|
403
|
+
if (turnAbort?.signal.aborted)
|
|
404
|
+
break; // ESC → araçları çalıştırma, dur
|
|
381
405
|
// Reactive compact: bağlam taştıysa bir kez özetle ve turu tekrarla → "token bitti, yazılmıyor" olmaz.
|
|
382
406
|
if (gotCtxErr && !reactiveRetried) {
|
|
383
407
|
reactiveRetried = true;
|
|
@@ -432,15 +456,16 @@ export async function runTui() {
|
|
|
432
456
|
onResult: (c, _i, res) => {
|
|
433
457
|
if ((c.name === 'WebSearch' || c.name === 'WebFetch') && res.ok)
|
|
434
458
|
usedWeb = true;
|
|
435
|
-
//
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
459
|
+
// İÇERİK İKİ KEZ BASILMASIN: Write/Edit içeriği onay anında (fileprev) tam gösterildi →
|
|
460
|
+
// burada SADECE tek-satır özet ("Yazıldı N satır → X"), token/ekran israfı yok.
|
|
461
|
+
let result = sanitizeOutput(res.output);
|
|
462
|
+
if (res.ok && (c.name === 'Write' || c.name === 'Edit')) {
|
|
463
|
+
const _c = c.name === 'Write' ? res.args?.content : res.args?.new_string;
|
|
464
|
+
const _n = _c != null ? String(_c).split('\n').length : 0;
|
|
465
|
+
const _verb = c.name === 'Write' ? (t('tui.wrote') || 'Yazıldı') : (t('tui.edited') || 'Düzenlendi');
|
|
466
|
+
result = `${_verb} ${_n} ${t('tui.linesWord') || 'satır'} → ${relWs(res.args.file_path)}`;
|
|
442
467
|
}
|
|
443
|
-
printItem({ kind: 'tool', label: toolLabel(c.name, res.args), result
|
|
468
|
+
printItem({ kind: 'tool', label: toolLabel(c.name, res.args), result, ok: res.ok });
|
|
444
469
|
},
|
|
445
470
|
});
|
|
446
471
|
for (let i = 0; i < toolCalls.length; i++)
|
|
@@ -467,6 +492,7 @@ export async function runTui() {
|
|
|
467
492
|
busy = false;
|
|
468
493
|
perm = null;
|
|
469
494
|
ask = null;
|
|
495
|
+
turnAbort = null;
|
|
470
496
|
refresh();
|
|
471
497
|
// Web-öğrenme: web'de arayıp cevap ürettiyse {soru→cevap}'ı eğitim datasına ekle
|
|
472
498
|
if (usedWeb && lastAnswer) {
|
|
@@ -813,6 +839,12 @@ export async function runTui() {
|
|
|
813
839
|
return;
|
|
814
840
|
}
|
|
815
841
|
if (key && key.name === 'escape') {
|
|
842
|
+
// Tur çalışıyorsa ESC = modeli DURDUR (akış/araç döngüsünü kes). Boştaysa input'u temizle.
|
|
843
|
+
if (busy && turnAbort) {
|
|
844
|
+
turnAbort.abort();
|
|
845
|
+
printItem({ kind: 'note', text: getLang() === 'en' ? '■ Stopped (Esc). You can type a new message.' : '■ Durduruldu (Esc). Yeni mesaj yazabilirsin.' });
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
816
848
|
inputBuf = '';
|
|
817
849
|
inputCur = 0;
|
|
818
850
|
refresh();
|