wormclaude 1.0.231 → 1.0.232
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/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 };
|