wormclaude 1.0.79 → 1.0.81

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 CHANGED
@@ -120,6 +120,30 @@ export async function* streamChat(messages, tools, config, signal) {
120
120
  };
121
121
  if (tools && tools.length)
122
122
  body.tools = tools;
123
+ // ── Zaman aşımı koruması ──────────────────────────────────────────────────
124
+ // Node fetch (undici) varsayılan olarak header ve chunk'lar için SONSUZA kadar
125
+ // bekler. Bayat keep-alive soketi / ağ takılmasında akış ebediyen asılı kalır
126
+ // ("mesaj gönderdim, yanıt gelmiyor"). Header ve chunk'lar-arası (idle) zaman
127
+ // aşımı ekliyoruz; kullanıcının abort sinyaliyle BİRLEŞİR.
128
+ const HEADERS_MS = Number(process.env.WORMCLAUDE_HEADERS_TIMEOUT_MS) || 45_000;
129
+ const IDLE_MS = Number(process.env.WORMCLAUDE_IDLE_TIMEOUT_MS) || 60_000;
130
+ const ac = new AbortController();
131
+ let timedOut = false;
132
+ const onUserAbort = () => ac.abort();
133
+ if (signal) {
134
+ if (signal.aborted)
135
+ ac.abort();
136
+ else
137
+ signal.addEventListener('abort', onUserAbort, { once: true });
138
+ }
139
+ let timer = setTimeout(() => { timedOut = true; ac.abort(); }, HEADERS_MS);
140
+ const armIdle = () => { if (timer)
141
+ clearTimeout(timer); timer = setTimeout(() => { timedOut = true; ac.abort(); }, IDLE_MS); };
142
+ const clearTimer = () => { if (timer) {
143
+ clearTimeout(timer);
144
+ timer = null;
145
+ } if (signal)
146
+ signal.removeEventListener('abort', onUserAbort); };
123
147
  let res;
124
148
  try {
125
149
  res = await fetchWithRetry(`${config.baseUrl}/chat/completions`, {
@@ -130,10 +154,15 @@ export async function* streamChat(messages, tools, config, signal) {
130
154
  ...(getTrace() ? { 'X-WC-Trace': getTrace(), 'X-WC-Session': getSession() } : {}),
131
155
  },
132
156
  body: JSON.stringify(body),
133
- signal,
157
+ signal: ac.signal,
134
158
  });
135
159
  }
136
160
  catch (e) {
161
+ clearTimer();
162
+ if (timedOut) {
163
+ yield { type: 'error', error: `Yanıt zaman aşımı — ${Math.round(HEADERS_MS / 1000)}sn içinde sunucudan yanıt gelmedi. Tekrar dene.` };
164
+ return;
165
+ }
137
166
  if (signal?.aborted || e?.name === 'AbortError') {
138
167
  yield { type: 'done', toolCalls: [] };
139
168
  return;
@@ -142,6 +171,7 @@ export async function* streamChat(messages, tools, config, signal) {
142
171
  return;
143
172
  }
144
173
  if (!res.ok || !res.body) {
174
+ clearTimer();
145
175
  let detail = '';
146
176
  try {
147
177
  detail = await res.text();
@@ -150,13 +180,14 @@ export async function* streamChat(messages, tools, config, signal) {
150
180
  yield { type: 'error', error: `HTTP ${res.status}: ${detail.slice(0, 300)}` };
151
181
  return;
152
182
  }
183
+ armIdle(); // header geldi → chunk'lar-arası idle zaman aşımına geç
153
184
  const reader = res.body.getReader();
154
185
  const decoder = new TextDecoder();
155
186
  let buf = '';
156
187
  const toolParser = new StreamingToolCallParser();
157
188
  let usage;
158
189
  while (true) {
159
- if (signal?.aborted) {
190
+ if (ac.signal.aborted && !timedOut) {
160
191
  try {
161
192
  await reader.cancel();
162
193
  }
@@ -168,10 +199,16 @@ export async function* streamChat(messages, tools, config, signal) {
168
199
  chunk = await reader.read();
169
200
  }
170
201
  catch (e) {
202
+ clearTimer();
203
+ if (timedOut) {
204
+ yield { type: 'error', error: `Bağlantı durdu — ${Math.round(IDLE_MS / 1000)}sn yeni veri gelmedi. Tekrar dene.` };
205
+ return;
206
+ }
171
207
  if (signal?.aborted || e?.name === 'AbortError')
172
208
  break;
173
209
  throw e;
174
210
  }
211
+ armIdle(); // her chunk → idle sayacını sıfırla
175
212
  const { done, value } = chunk;
176
213
  if (done)
177
214
  break;
@@ -212,6 +249,7 @@ export async function* streamChat(messages, tools, config, signal) {
212
249
  }
213
250
  }
214
251
  }
252
+ clearTimer(); // akış normal bitti → zamanlayıcı + dinleyici temizle
215
253
  // Tamamlanan çağrıları sağlam biçimde topla; args'ı GEÇERLİ JSON string olarak emit et
216
254
  // (tools.ts tarafındaki JSON.parse artık asla patlamaz — onarım burada yapıldı).
217
255
  const toolCalls = toolParser.getCompleted().map((c) => ({
package/dist/compact.js CHANGED
@@ -2,8 +2,11 @@
2
2
  // Manuel /compact ve otomatik (eşik aşılınca) tetikleme aynı çekirdeği kullanır.
3
3
  import { completeText } from './agent.js';
4
4
  import { approxTokens } from './usage.js';
5
- // Bağlam penceresi (Qwen 2.5 7B = 32768). Env ile override edilebilir.
6
- const CONTEXT_WINDOW = Number(process.env.WORMCLAUDE_CONTEXT_WINDOW) || 32768;
5
+ // Bağlam penceresi vLLM'de servis edilen modelin GERÇEK tavanıyla hizalı olmalı.
6
+ // Sunucu (Qwen2.5-32B-AWQ) max-model-len = 16384. 32768 verilirse özetleme geç
7
+ // tetiklenir, model 16K'da "bağlam taştı" hatası döndürür → tepkisel/geç toparlama.
8
+ // Daha büyük bağlam istenirse: önce vLLM max-model-len artırılmalı (KV-cache VRAM gerektirir).
9
+ const CONTEXT_WINDOW = Number(process.env.WORMCLAUDE_CONTEXT_WINDOW) || 16384;
7
10
  const SUMMARY_RESERVE = 4000; // özet çıktısı için rezerv (CC: ~20K büyük modellerde)
8
11
  const AUTOCOMPACT_BUFFER = 2000;
9
12
  export function autoCompactThreshold() {
package/dist/theme.js CHANGED
@@ -16,4 +16,4 @@ export const theme = {
16
16
  synType: '#a78bfa', // tip/sınıf adları, sabitler
17
17
  synProp: '#e0e0e0', // özellik/anahtar adları
18
18
  };
19
- export const VERSION = '1.0.79';
19
+ export const VERSION = '1.0.81';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wormclaude",
3
- "version": "1.0.79",
3
+ "version": "1.0.81",
4
4
  "description": "WormClaude CLI - uncensored security+code assistant (ink TUI, Claude-style)",
5
5
  "type": "module",
6
6
  "bin": {