wormclaude 1.0.231 → 1.0.233
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/api.js +22 -1
- package/dist/streamparser.js +54 -2
- package/dist/theme.js +1 -1
- package/dist/tools.js +1 -1
- package/dist/tui.js +20 -3
- package/package.json +1 -1
package/dist/api.js
CHANGED
|
@@ -80,18 +80,39 @@ function backoff(attempt) {
|
|
|
80
80
|
const base = Math.min(BASE_DELAY_MS * 2 ** attempt, MAX_DELAY_MS);
|
|
81
81
|
return base + Math.random() * 0.25 * base; // jitter %25
|
|
82
82
|
}
|
|
83
|
+
// Retry-After header'ı ms'ye çevir (saniye VEYA HTTP-date). Sunucu "şu kadar bekle" derse
|
|
84
|
+
// kör backoff yerine onu onurla → 429/503'te ne erken hammer'la ne fazla bekle. Yoksa null.
|
|
85
|
+
function retryAfterMs(res) {
|
|
86
|
+
try {
|
|
87
|
+
const h = res.headers?.get?.('retry-after');
|
|
88
|
+
if (!h)
|
|
89
|
+
return null;
|
|
90
|
+
const secs = Number(h);
|
|
91
|
+
if (Number.isFinite(secs))
|
|
92
|
+
return Math.min(Math.max(0, secs * 1000), 60000);
|
|
93
|
+
const when = Date.parse(h);
|
|
94
|
+
if (!Number.isNaN(when))
|
|
95
|
+
return Math.min(Math.max(0, when - Date.now()), 60000);
|
|
96
|
+
}
|
|
97
|
+
catch { }
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
83
100
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
84
101
|
// Sadece BAĞLANTI kurulurken retry edilir (stream başladıktan sonra retry edilmez
|
|
85
102
|
// — aksi halde kısmi metin tekrar gelir). HTTP başlamadan önceki hatalar güvenli.
|
|
86
103
|
async function fetchWithRetry(url, init) {
|
|
87
104
|
let lastErr;
|
|
88
105
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
106
|
+
let waitMs = backoff(attempt);
|
|
89
107
|
try {
|
|
90
108
|
const res = await fetch(url, init);
|
|
91
109
|
if (res.ok)
|
|
92
110
|
return res;
|
|
93
111
|
if (!RETRYABLE_STATUS.has(res.status) || attempt === MAX_RETRIES)
|
|
94
112
|
return res;
|
|
113
|
+
const ra = retryAfterMs(res); // sunucu bekleme süresi verdiyse onu onurla
|
|
114
|
+
if (ra != null)
|
|
115
|
+
waitMs = ra;
|
|
95
116
|
try {
|
|
96
117
|
await res.body?.cancel();
|
|
97
118
|
}
|
|
@@ -107,7 +128,7 @@ async function fetchWithRetry(url, init) {
|
|
|
107
128
|
if (attempt === MAX_RETRIES)
|
|
108
129
|
throw e;
|
|
109
130
|
}
|
|
110
|
-
await sleep(
|
|
131
|
+
await sleep(waitMs);
|
|
111
132
|
}
|
|
112
133
|
throw lastErr ?? new Error('retry exhausted');
|
|
113
134
|
}
|
package/dist/streamparser.js
CHANGED
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
// Qwen-14B + vLLM(hermes) parçalı JSON arg, index çakışması, ID'siz devam chunk'ı üretebilir.
|
|
3
3
|
// Gemini streamingToolCallParser'dan uyarlandı; bizim {index, id?, name?, argChunk} delta'mıza göre sade.
|
|
4
4
|
import { safeJsonParse } from './safejson.js';
|
|
5
|
+
// Yarım kalmış JSON'u onar: açık string'i kapat + string-dışı açık {/[ 'ları doğru sırada kapat.
|
|
6
|
+
// Stream son string arg'ı (ör. uzun file_path) yarıda keserse argümanlar {} olarak kaybolmasın.
|
|
7
|
+
function repairJson(buf) {
|
|
8
|
+
let s = buf, inStr = false, esc = false;
|
|
9
|
+
const stack = [];
|
|
10
|
+
for (const ch of s) {
|
|
11
|
+
if (inStr) {
|
|
12
|
+
if (esc)
|
|
13
|
+
esc = false;
|
|
14
|
+
else if (ch === '\\')
|
|
15
|
+
esc = true;
|
|
16
|
+
else if (ch === '"')
|
|
17
|
+
inStr = false;
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (ch === '"')
|
|
21
|
+
inStr = true;
|
|
22
|
+
else if (ch === '{')
|
|
23
|
+
stack.push('}');
|
|
24
|
+
else if (ch === '[')
|
|
25
|
+
stack.push(']');
|
|
26
|
+
else if (ch === '}' || ch === ']')
|
|
27
|
+
stack.pop();
|
|
28
|
+
}
|
|
29
|
+
if (inStr)
|
|
30
|
+
s += '"';
|
|
31
|
+
while (stack.length)
|
|
32
|
+
s += stack.pop();
|
|
33
|
+
return s;
|
|
34
|
+
}
|
|
5
35
|
export class StreamingToolCallParser {
|
|
6
36
|
buffers = new Map();
|
|
7
37
|
depths = new Map();
|
|
@@ -88,6 +118,13 @@ export class StreamingToolCallParser {
|
|
|
88
118
|
return { complete: true, value: JSON.parse(newBuffer) };
|
|
89
119
|
}
|
|
90
120
|
catch {
|
|
121
|
+
// Kapanmamış string onarımı: kapanış tırnağı stream'de düştüyse (inString) ekle + tekrar dene.
|
|
122
|
+
if (inString) {
|
|
123
|
+
try {
|
|
124
|
+
return { complete: true, value: JSON.parse(newBuffer + '"') };
|
|
125
|
+
}
|
|
126
|
+
catch { }
|
|
127
|
+
}
|
|
91
128
|
return { complete: false };
|
|
92
129
|
}
|
|
93
130
|
}
|
|
@@ -100,8 +137,23 @@ export class StreamingToolCallParser {
|
|
|
100
137
|
const m = this.meta.get(index);
|
|
101
138
|
if (!m?.name)
|
|
102
139
|
continue; // isimsiz parça → çağrı değil
|
|
103
|
-
// Boş buffer = argümansız tool (ör. {}).
|
|
104
|
-
|
|
140
|
+
// Boş buffer = argümansız tool (ör. {}). Dolu ise: JSON.parse → (kapanmamış string ise
|
|
141
|
+
// kapatma-tırnağı ekle+dene) → safeJsonParse fallback. Böylece stream son string arg'ı
|
|
142
|
+
// yarıda kesse bile argümanlar {} olarak kaybolmaz.
|
|
143
|
+
let args = {};
|
|
144
|
+
if (buffer.trim()) {
|
|
145
|
+
try {
|
|
146
|
+
args = JSON.parse(buffer);
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
try {
|
|
150
|
+
args = JSON.parse(repairJson(buffer));
|
|
151
|
+
} // string + açık brace'leri kapat
|
|
152
|
+
catch {
|
|
153
|
+
args = safeJsonParse(buffer, {});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
105
157
|
out.push({ id: m.id || `call_${index}`, name: m.name, args, index });
|
|
106
158
|
}
|
|
107
159
|
return out;
|
package/dist/theme.js
CHANGED
package/dist/tools.js
CHANGED
|
@@ -874,7 +874,7 @@ async function execOne(call, hooks) {
|
|
|
874
874
|
// 1) Girdi doğrulama
|
|
875
875
|
const verr = validateToolInput(call.name, args);
|
|
876
876
|
if (verr)
|
|
877
|
-
return { ok: false, output: `
|
|
877
|
+
return { ok: false, output: `INVALID_PARAMS for ${call.name}: ${verr}. Fix the arguments and call ${call.name} again with the correct parameters.`, args };
|
|
878
878
|
// İNCELEME KİLİDİ: incele görevinde "nasıl kullanayım?" diye SORMA — açıklamayı üret.
|
|
879
879
|
if (inspectLock && call.name === 'AskUserQuestion') {
|
|
880
880
|
return { ok: false, output: 'This is an INSPECT/UNDERSTAND task — do NOT ask the user what to do with the files or how they want to use them. Just explain, in text, what the folder contains: the key files and their purpose, and what the project/collection is overall. Deliver that written explanation now.', args };
|
package/dist/tui.js
CHANGED
|
@@ -437,6 +437,7 @@ export async function runTui() {
|
|
|
437
437
|
let lastSig = '', sameCount = 0, usedWeb = false, lastAnswer = '';
|
|
438
438
|
const sigWindow = []; // dönüşümlü/döngüsel loop tespiti (A,B,A,B) için son imzalar
|
|
439
439
|
let consecFail = 0, totalFails = 0; // devre-kesici: olmayan araç/sözdizimi döngüsünü kır
|
|
440
|
+
let fruitless = 0; // boş-arama loop koruması: art arda Glob/Grep "(no matches)" → dur, yol iste
|
|
440
441
|
let reactiveRetried = false; // bağlam taşmasında bir kez compact+retry
|
|
441
442
|
let secrecyRetried = false; // inceleme görevinde yanlış gizlilik-reddinde bir kez zorla-okut
|
|
442
443
|
try {
|
|
@@ -629,7 +630,15 @@ export async function runTui() {
|
|
|
629
630
|
const _failed = results.filter((r) => !r.ok).length;
|
|
630
631
|
totalFails += _failed;
|
|
631
632
|
consecFail = (results.length > 0 && _failed === results.length) ? consecFail + 1 : 0;
|
|
632
|
-
|
|
633
|
+
// Boş-arama loop: Glob/Grep "(no matches)" ok:true döner → fail-breaker'ı tripe etmez.
|
|
634
|
+
// Bu tur SADECE arama yaptıysa ve HEPSİ boşsa fruitless++ ; bir yararlı sonuç gelince sıfırla.
|
|
635
|
+
const _searchCalls = toolCalls.filter((tc) => /^(Glob|Grep)$/.test(tc.name)).length;
|
|
636
|
+
const _emptySearch = results.filter((r, i) => r.ok && /^(Glob|Grep)$/.test(toolCalls[i].name) && /^\(no matches\)|no matches/i.test((r.output || '').trim())).length;
|
|
637
|
+
if (_searchCalls > 0 && _emptySearch === _searchCalls && _emptySearch === toolCalls.length)
|
|
638
|
+
fruitless += _emptySearch;
|
|
639
|
+
else if (results.some((r) => r.ok && !/^\(no matches\)/i.test((r.output || '').trim())))
|
|
640
|
+
fruitless = 0;
|
|
641
|
+
const _willStop = consecFail >= 2 || totalFails >= 4 || fruitless >= 5;
|
|
633
642
|
// REFLECT-AFTER: bir araç başarısızsa (ve henüz sert-dur eşiğine gelmediysek) modele
|
|
634
643
|
// teşhis+adapte dayat — körlemesine tekrar/pes etmesin, benim gibi "neden + başka yol" düşünsün.
|
|
635
644
|
for (let i = 0; i < toolCalls.length; i++) {
|
|
@@ -644,10 +653,18 @@ export async function runTui() {
|
|
|
644
653
|
if (_willStop) {
|
|
645
654
|
// Model-yönlü direktif İNGİLİZCE (Türkçe direktif instruction-following'i bozar);
|
|
646
655
|
// model yine kullanıcının diliyle özetler. (Kullanıcı-yönlü not aşağıda TR kalır.)
|
|
647
|
-
|
|
648
|
-
|
|
656
|
+
const _searchLoop = fruitless >= 5 && consecFail < 2 && totalFails < 4;
|
|
657
|
+
if (_searchLoop) {
|
|
658
|
+
history.push({ role: 'user', content: 'Your repeated Glob/Grep searches keep returning no matches — the files are not where you are looking. STOP searching now. Ask the user for the exact folder path or file name (in their language), or plainly say you could not find them. Do NOT run more searches.' });
|
|
659
|
+
printItem({ kind: 'note', text: getLang() === 'en' ? 'Searches came up empty — asking for the path.' : 'Aramalar boş döndü — yolu soruyorum.' });
|
|
660
|
+
}
|
|
661
|
+
else {
|
|
662
|
+
history.push({ role: 'user', content: 'Several commands failed — required tools/syntax are not available here (e.g. grep/openssl/hydra on Windows). STOP running commands now and give a SHORT summary of what you found so far, in the user\'s language. Do NOT call more tools, do NOT use grep/sed/awk.' });
|
|
663
|
+
printItem({ kind: 'note', text: getLang() === 'en' ? 'Commands kept failing — wrapping up.' : 'Komutlar başarısız oldu — özetle bitiriliyor.' });
|
|
664
|
+
}
|
|
649
665
|
consecFail = 0;
|
|
650
666
|
totalFails = 0;
|
|
667
|
+
fruitless = 0;
|
|
651
668
|
}
|
|
652
669
|
}
|
|
653
670
|
}
|