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 +11 -0
- package/dist/headless.js +76 -0
- package/dist/theme.js +1 -1
- package/dist/tools.js +3 -1
- package/dist/tui.js +27 -1
- package/package.json +1 -1
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')
|
package/dist/headless.js
ADDED
|
@@ -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
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', '
|
|
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;
|