wormclaude 1.0.128 → 1.0.130

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 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.128';
19
+ export const VERSION = '1.0.130';
package/dist/tools.js CHANGED
@@ -27,6 +27,9 @@ let todosStore = []; // TodoWrite durumu
27
27
  export function getTodos() { return todosStore; }
28
28
  const MAX_LINES_TO_READ = 2000;
29
29
  const DEFAULT_BASH_TIMEOUT_MS = 120000;
30
+ // Sunucu/never-exits komutları: ön planda çalışırsa CLI'ı bloklar (timeout'a kadar "donma").
31
+ // Bunları run_in_background istenmese bile OTOMATİK arka plana alıyoruz → CLI asla donmaz.
32
+ const _DEV_SERVER_RE = /\b(?:npm|pnpm|yarn)\s+(?:run\s+)?(?:dev|start|serve|preview)\b|\b(?:next|nuxt|vite|gatsby)\s+(?:dev|develop|start)\b|\bng\s+serve\b|\breact-scripts\s+start\b|\bnodemon\b|\bhttp-server\b|(?:^|\s)serve(?:\s|$)|\bpython3?\s+-m\s+http\.server\b|\bflask\s+run\b|\buvicorn\b|\bgunicorn\b|\bphp\s+-S\b|\brails\s+s(?:erver)?\b|\bwebpack(?:-dev-server)?\s+serve\b/i;
30
33
  const MAX_BASH_TIMEOUT_MS = 600000;
31
34
  // Bash çalışma dizini — oturum boyunca kalıcı. execSync her çağrıda taze shell açtığı için
32
35
  // `cd` normalde kaybolur; burada cwd'yi takip edip her komuta geçiriyoruz.
@@ -43,6 +46,9 @@ export function resolveWs(fp) {
43
46
  return fp;
44
47
  }
45
48
  }
49
+ // WebFetch önbelleği: model aynı URL'i bir cevap içinde defalarca (7×) çekiyordu (farklı prompt'larla
50
+ // ama sayfa aynı) → israf + kafa karışıklığı. Aynı URL 2 dk içinde tekrar istenirse cache'den döner.
51
+ const _webFetchCache = new Map();
46
52
  // Komutu çalıştırır ve sonrasında cwd değişikliğini (cd) yakalayıp bashCwd'yi günceller.
47
53
  // POSIX: pwd'yi temp dosyaya yazan, çıkış kodunu KORUYAN sarmalayıcı (hata propagasyonu bozulmaz).
48
54
  // Windows: komutu olduğu gibi çalıştır, sonra baştaki `cd <hedef>`'i regex ile yakala (best-effort).
@@ -529,15 +535,15 @@ export const toolSchemas = [
529
535
  type: 'function',
530
536
  function: {
531
537
  name: 'AskUserQuestion',
532
- description: 'Ask the user a multiple-choice question and get their answer (renders as an interactive picker). Use when a request is AMBIGUOUS and you need a decision only the user can make BEFORE acting — e.g. they ask you to build a website/app/project but did not specify the type, tech stack, or style. Prefer asking ONE concise question with 2-4 clear options (each with a short description) over guessing. Do NOT use it for things you can reasonably decide yourself.',
538
+ description: 'Ask the user a multiple-choice question and get their answer (renders as an interactive numbered picker). Use when a request is AMBIGUOUS and you need a decision only the user can make BEFORE acting — e.g. they ask you to build a website/app/project but did not specify the type, tech stack, or style. Ask ONE concise question with 2-4 SHORT option strings. Do NOT use it for things you can reasonably decide yourself. IMPORTANT: emit it as a single tool call ONLY — never also write the question as prose.',
533
539
  parameters: {
534
540
  type: 'object',
535
541
  properties: {
536
542
  question: { type: 'string', description: 'The question to ask' },
537
543
  options: {
538
544
  type: 'array',
539
- description: '2-4 options',
540
- items: { type: 'object', properties: { label: { type: 'string' }, description: { type: 'string' } }, required: ['label'] },
545
+ description: '2-4 short option strings, e.g. ["React.js", "Vue.js", "Angular"]',
546
+ items: { type: 'string' },
541
547
  },
542
548
  },
543
549
  required: ['question', 'options'],
@@ -607,8 +613,9 @@ const CORE_TOOLS = new Set([
607
613
  'Bash', 'PowerShell', 'Read', 'Write', 'Edit', 'Glob', 'Grep',
608
614
  'WebFetch', 'WebSearch', 'Sleep',
609
615
  'TaskOutput', // uzun komutları arka planda çalıştırıp bitişini yoklamak için (run_in_background)
610
- // AskUserQuestion KALDIRILDI: 32B nested options array'ini sağlıklı üretemiyor degenere
611
- // oluyor ({"name":"","arguments":""} tekrarı). Model artık makul varsayımla direkt kurar.
616
+ 'AskUserQuestion', // GERİ EKLENDİ: FLAT şema (options: string[]) ile 32B temiz çağrı üretiyor
617
+ // (test edildi). Eski degenere NESTED şemadandı ([{label,description}]). Handler string→{label}
618
+ // normalize ediyor; bare-JSON inline recovery temiz çağrıyı yakalıyor → numaralı menü.
612
619
  ]);
613
620
  export function allToolSchemas() {
614
621
  const sk = skillToolSchema();
@@ -671,8 +678,15 @@ async function execOne(call, hooks) {
671
678
  return { ok: false, output: `Geçersiz girdi: ${verr}`, args };
672
679
  // 2) İnteraktif/plan araçları
673
680
  if (call.name === 'AskUserQuestion') {
674
- const opts = Array.isArray(args.options) ? args.options : [];
675
- if (hooks?.ask) {
681
+ // Seçenekleri normalize et: model FLAT string[] verir ("React.js"), ama eski/karışık çağrı
682
+ // {label,description} objesi de olabilir. Hepsini {label, description?} biçimine indir.
683
+ const raw = Array.isArray(args.options) ? args.options : [];
684
+ const opts = raw
685
+ .map((o) => typeof o === 'string' ? { label: o.trim() }
686
+ : (o && (o.label || o.value || o.text)) ? { label: String(o.label || o.value || o.text).trim(), description: o.description ? String(o.description) : undefined }
687
+ : null)
688
+ .filter((o) => o && o.label);
689
+ if (hooks?.ask && opts.length) {
676
690
  const ch = await hooks.ask({ question: String(args.question), options: opts });
677
691
  return { ok: true, output: ch, args };
678
692
  }
@@ -962,9 +976,12 @@ export async function executeTool(name, args) {
962
976
  return { ok: true, output: `Kaydirildi: ${args.direction}` };
963
977
  }
964
978
  if (name === 'Bash') {
965
- if (args.run_in_background) {
966
- const task = tasks.create('shell', String(args.command).slice(0, 60));
967
- const child = spawn(String(args.command), { shell: true, windowsHide: true, cwd: getBashCwd() });
979
+ const _cmd = String(args.command);
980
+ // Sunucu/never-exits komutu → run_in_background istenmese bile otomatik arka plana al (donma yok).
981
+ const _autoBg = !args.run_in_background && _DEV_SERVER_RE.test(_cmd);
982
+ if (args.run_in_background || _autoBg) {
983
+ const task = tasks.create('shell', _cmd.slice(0, 60));
984
+ const child = spawn(_cmd, { shell: true, windowsHide: true, cwd: getBashCwd() });
968
985
  task.child = child;
969
986
  child.stdout?.on('data', (d) => tasks.append(task.id, d.toString()));
970
987
  child.stderr?.on('data', (d) => tasks.append(task.id, d.toString()));
@@ -973,7 +990,10 @@ export async function executeTool(name, args) {
973
990
  tasks.finish(task.id, code === 0 ? 'done' : 'error');
974
991
  });
975
992
  child.on('error', (e) => { tasks.append(task.id, `\n[spawn error: ${e.message}]`); tasks.finish(task.id, 'error'); });
976
- return { ok: true, output: `Background task started: ${task.id}. Read output later with TaskOutput("${task.id}").` };
993
+ const _note = _autoBg
994
+ ? ` (This is a long-running/server command — it was auto-started in the BACKGROUND so it cannot freeze the CLI. The server is now running. Do NOT run it again in the foreground; just tell the user it is running and on which command/port.)`
995
+ : '';
996
+ return { ok: true, output: `Background task started: ${task.id}.${_note} Read output later with TaskOutput("${task.id}").` };
977
997
  }
978
998
  let timeout = Number(args.timeout) || DEFAULT_BASH_TIMEOUT_MS;
979
999
  if (timeout > MAX_BASH_TIMEOUT_MS)
@@ -1225,6 +1245,12 @@ export async function executeTool(name, args) {
1225
1245
  let url = String(args.url);
1226
1246
  if (url.startsWith('http://'))
1227
1247
  url = 'https://' + url.slice(7);
1248
+ const header = args.prompt ? `[prompt: ${String(args.prompt).slice(0, 200)}]\n\n` : '';
1249
+ // Aynı URL bu oturumda 2 dk içinde çekildiyse → önbellekten (model 7× aynı sayfayı çekmesin).
1250
+ const _c = _webFetchCache.get(url);
1251
+ if (_c && Date.now() - _c.t < 120000) {
1252
+ return { ok: true, output: header + '[bu URL bu cevapta ZATEN çekildi — aşağıdaki içerikten OKU, tekrar çekme]\n\n' + _c.text };
1253
+ }
1228
1254
  const res = await fetch(url, { signal: AbortSignal.timeout(20000) });
1229
1255
  let txt = await res.text();
1230
1256
  txt = txt
@@ -1232,9 +1258,10 @@ export async function executeTool(name, args) {
1232
1258
  .replace(/<style[\s\S]*?<\/style>/gi, '')
1233
1259
  .replace(/<[^>]+>/g, ' ')
1234
1260
  .replace(/\s+/g, ' ')
1235
- .trim();
1236
- const header = args.prompt ? `[prompt: ${String(args.prompt).slice(0, 200)}]\n\n` : '';
1237
- return { ok: true, output: header + (txt || '(empty)').slice(0, 15000) };
1261
+ .trim()
1262
+ .slice(0, 15000);
1263
+ _webFetchCache.set(url, { text: txt, t: Date.now() });
1264
+ return { ok: true, output: header + (txt || '(empty)') };
1238
1265
  }
1239
1266
  if (name === 'WebSearch') {
1240
1267
  // Once gateway arama proxy'sini dene (Tavily anahtari sunucuda ayarliysa onu kullanir; anahtar istemciye gelmez)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wormclaude",
3
- "version": "1.0.128",
3
+ "version": "1.0.130",
4
4
  "description": "WormClaude CLI - uncensored security+code assistant (ink TUI, Claude-style)",
5
5
  "type": "module",
6
6
  "bin": {