wormclaude 1.0.122 → 1.0.124

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/cli.js CHANGED
@@ -60,6 +60,17 @@ import { shouldAutoCompact, runCompact, isContextError } from './compact.js';
60
60
  import { shouldExtract, triggerMemory, loadMemoryContext } from './memory.js';
61
61
  // --- WORMCLAUDE SUBCOMMANDS (TUI oncesi) ---
62
62
  const _arg = (process.argv[2] || '').toLowerCase();
63
+ // Headless mod: wormclaude -p "<görev>" → TUI'siz çalıştır, stdout'a yaz, çık (scriptlenebilir + test).
64
+ if (_arg === '-p' || _arg === '--print') {
65
+ const _prompt = process.argv.slice(3).join(' ').trim();
66
+ if (!_prompt) {
67
+ console.error('Kullanım: wormclaude -p "<görev>"');
68
+ process.exit(1);
69
+ }
70
+ const { runHeadless } = await import('./headless.js');
71
+ await runHeadless(_prompt);
72
+ process.exit(0);
73
+ }
63
74
  if (_arg === 'login' || _arg === 'logout' || _arg === 'whoami' || _arg === '--version' || _arg === '-v' || _arg === 'update') {
64
75
  const auth = await import('./auth.js');
65
76
  if (_arg === 'login')
@@ -0,0 +1,76 @@
1
+ // Headless (non-interactive) mod: `wormclaude -p "<görev>"` → ajan döngüsünü bir kez çalıştırır,
2
+ // sonucu stdout'a yazar, çıkar. TUI yok. Scriptlenebilir + otomatik test için. Araçlar OTO-onaylı
3
+ // (kullanıcı -p ile bilerek başlattı). Davranış TUI ile aynı: aynı streamChat + executeToolCalls
4
+ // + strip/capOut/devre-kesici.
5
+ import { loadConfig, streamChat } from './api.js';
6
+ import { allToolSchemas, executeToolCalls, toolLabel, setToolConfig } from './tools.js';
7
+ import { stripInlineToolCalls, stripEchoBlocks } from './inlinetools.js';
8
+ import { cleanModelText } from './textclean.js';
9
+ function cap(name, out) {
10
+ const s = out || '';
11
+ const isCmd = name === 'Bash' || name === 'PowerShell';
12
+ const CAP = isCmd ? 2200 : 8000;
13
+ if (s.length <= CAP)
14
+ return s;
15
+ if (isCmd)
16
+ return s.slice(0, 1400) + `\n… [kısaltıldı] …\n` + s.slice(-600);
17
+ return s.slice(0, CAP) + `\n… [kısaltıldı]`;
18
+ }
19
+ export async function runHeadless(prompt) {
20
+ const config = loadConfig();
21
+ if (!config.apiKey) {
22
+ console.error('Giriş gerekli: wormclaude login');
23
+ process.exit(1);
24
+ }
25
+ setToolConfig(config);
26
+ const plat = process.platform === 'win32' ? 'Windows' : process.platform === 'darwin' ? 'macOS' : 'Linux';
27
+ const history = [
28
+ { role: 'system', content: `ENVIRONMENT: User machine = ${plat}. Bash runs via ${plat === 'Windows' ? 'cmd.exe' : 'sh'}. CWD: ${process.cwd()}.` },
29
+ { role: 'user', content: prompt },
30
+ ];
31
+ let consecFail = 0, totalFails = 0;
32
+ for (let iter = 0; iter < 30; iter++) {
33
+ let answer = '';
34
+ let toolCalls = [];
35
+ try {
36
+ for await (const ev of streamChat(history, allToolSchemas(), config)) {
37
+ if (ev.type === 'text') {
38
+ process.stdout.write(ev.text);
39
+ answer += ev.text;
40
+ }
41
+ else if (ev.type === 'done') {
42
+ toolCalls = ev.toolCalls || [];
43
+ }
44
+ else if (ev.type === 'error') {
45
+ process.stderr.write(`\n[hata: ${ev.error}]\n`);
46
+ }
47
+ }
48
+ }
49
+ catch (e) {
50
+ process.stderr.write(`\n[bağlantı hatası: ${e?.message || e}]\n`);
51
+ process.exit(1);
52
+ }
53
+ answer = stripEchoBlocks(stripInlineToolCalls(cleanModelText(answer))).trim();
54
+ const am = { role: 'assistant', content: answer || '' };
55
+ if (toolCalls.length)
56
+ am.tool_calls = toolCalls.map((t) => ({ id: t.id, type: 'function', function: { name: t.name, arguments: t.args || '{}' } }));
57
+ history.push(am);
58
+ if (!toolCalls.length)
59
+ break;
60
+ const results = await executeToolCalls(toolCalls, {
61
+ confirm: () => Promise.resolve('allow'), // headless → oto-onay
62
+ onResult: (c, _i, res) => { process.stdout.write(`\n ⎿ ${toolLabel(c.name, res.args)} → ${res.ok ? 'OK' : '✗ ' + (res.output || '').slice(0, 120)} (${(res.output || '').length} kar)\n`); },
63
+ });
64
+ for (let i = 0; i < toolCalls.length; i++)
65
+ history.push({ role: 'tool', tool_call_id: toolCalls[i].id, content: cap(toolCalls[i].name, results[i].output || '') });
66
+ const _failed = results.filter((r) => !r.ok).length;
67
+ totalFails += _failed;
68
+ consecFail = (results.length > 0 && _failed === results.length) ? consecFail + 1 : 0;
69
+ if (consecFail >= 2 || totalFails >= 4) {
70
+ process.stdout.write('\n[devre-kesici: komutlar başarısız oldu, durduruldu]\n');
71
+ break;
72
+ }
73
+ }
74
+ process.stdout.write('\n');
75
+ process.exit(0);
76
+ }
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.122';
19
+ export const VERSION = '1.0.124';
package/dist/tools.js CHANGED
@@ -605,8 +605,10 @@ const computerToolSchemas = [
605
605
  // çağırıp işi yapar, planı ekrana basmaz. (Gerekirse buraya yeni araç eklenir.)
606
606
  const CORE_TOOLS = new Set([
607
607
  'Bash', 'PowerShell', 'Read', 'Write', 'Edit', 'Glob', 'Grep',
608
- 'WebFetch', 'WebSearch', 'AskUserQuestion', 'Sleep',
608
+ 'WebFetch', 'WebSearch', 'Sleep',
609
609
  '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.
610
612
  ]);
611
613
  export function allToolSchemas() {
612
614
  const sk = skillToolSchema();
package/dist/tui.js CHANGED
@@ -6,7 +6,9 @@
6
6
  import readline from 'node:readline';
7
7
  import stringWidth from 'string-width';
8
8
  import { loadConfig, streamChat, fetchAccount } from './api.js';
9
- import { allToolSchemas, executeToolCalls, executeTool, toolLabel, setToolConfig } from './tools.js';
9
+ import { allToolSchemas, executeToolCalls, executeTool, toolLabel, setToolConfig, setBashCwd } from './tools.js';
10
+ import * as path from 'node:path';
11
+ import * as fs from 'node:fs';
10
12
  import { sanitizeOutput } from './errorsan.js';
11
13
  import { itemAnsi, markdownAnsi } from './ansi.js';
12
14
  import { theme, VERSION } from './theme.js';
@@ -83,6 +85,7 @@ export async function runTui() {
83
85
  const displayItems = [{ kind: 'banner' }];
84
86
  let inputBuf = '', inputCur = 0, busy = false, streamChars = 0, spin = 0;
85
87
  let taskStart = 0; // görev başlangıç zamanı (spinner'da geçen süre için)
88
+ let awaitingWorkspace = true; // açılışta çalışma klasörü sorulur (ilk submit = klasör)
86
89
  // 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.
87
90
  const SPIN = ['·', '✢', '✳', '✶', '✻', '✽', '✶', '✳', '✢'];
88
91
  // Canlı bağlam ölçer: son isteğin prompt_tokens'ı = o anki kullanılan bağlam (footer'da gösterilir).
@@ -448,6 +451,10 @@ export async function runTui() {
448
451
  catch { }
449
452
  process.stdout.write('\x1b[?25l'); // gerçek imleci gizle (kendi ▌ bloğumuzu çiziyoruz)
450
453
  redrawAll();
454
+ // Açılış: çalışma klasörünü sor (ilk submit = klasör). Dosyalar buraya yazılır.
455
+ printItem({ kind: 'note', text: getLang() === 'en'
456
+ ? `📁 Working folder? Type a path (a new folder is created if missing), or press Enter to use:\n ${process.cwd()}`
457
+ : `📁 Hangi klasörde çalışayım? Bir yol yaz (yoksa oluşturulur) ya da Enter ile şunu kullan:\n ${process.cwd()}` });
451
458
  fetchAccount(config).then((a) => { if (a) {
452
459
  account = a;
453
460
  redrawAll();
@@ -616,6 +623,25 @@ export async function runTui() {
616
623
  inputBuf = '';
617
624
  inputCur = 0;
618
625
  histIdx = -1;
626
+ // Açılış klasör sorusu: ilk submit = çalışma klasörü (Enter = mevcut, ya da yol yaz/oluştur)
627
+ if (awaitingWorkspace) {
628
+ awaitingWorkspace = false;
629
+ const tgt = v.replace(/^["']|["']$/g, '');
630
+ if (tgt) {
631
+ try {
632
+ const abs = path.isAbsolute(tgt) ? tgt : path.resolve(process.cwd(), tgt);
633
+ fs.mkdirSync(abs, { recursive: true });
634
+ process.chdir(abs);
635
+ setBashCwd(abs);
636
+ }
637
+ catch (e) {
638
+ printItem({ kind: 'note', text: (getLang() === 'en' ? 'Folder error: ' : 'Klasör hatası: ') + (e?.message || e) });
639
+ }
640
+ }
641
+ printItem({ kind: 'note', text: (getLang() === 'en' ? '✓ Working folder: ' : '✓ Çalışma klasörü: ') + process.cwd() });
642
+ refresh();
643
+ return;
644
+ }
619
645
  if (!v) {
620
646
  refresh();
621
647
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wormclaude",
3
- "version": "1.0.122",
3
+ "version": "1.0.124",
4
4
  "description": "WormClaude CLI - uncensored security+code assistant (ink TUI, Claude-style)",
5
5
  "type": "module",
6
6
  "bin": {