wormclaude 1.0.6 → 1.0.8
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 +35 -6
- package/dist/computer.js +186 -0
- package/dist/theme.js +1 -1
- package/dist/tools.js +44 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -57,7 +57,7 @@ import('./auth.js').then((a) => a.checkForUpdate(VERSION)).then((v) => { _update
|
|
|
57
57
|
process.on('exit', () => { if (_updateLatest)
|
|
58
58
|
process.stdout.write('\n Yeni surum var: ' + VERSION + ' -> ' + _updateLatest + '. Guncelle: wormclaude update\n'); });
|
|
59
59
|
setToolConfig(config); // Agent/alt-agent araçları aynı config'i kullanır
|
|
60
|
-
const MAX_TURNS = Number(process.env.WORMCLAUDE_MAX_TURNS) ||
|
|
60
|
+
const MAX_TURNS = Number(process.env.WORMCLAUDE_MAX_TURNS) || 50; // tur limiti
|
|
61
61
|
setLang(loadLang() ?? 'tr'); // kayıtlı dili yükle (yoksa tr)
|
|
62
62
|
loadSkills(); // .wormclaude/skills/*.md yükle
|
|
63
63
|
// FULLSCREEN (alternate screen) — WormClaude'un yöntemi: tüm ekranı ink yönetir,
|
|
@@ -245,16 +245,29 @@ function WormSpinner({ label, tokens }) {
|
|
|
245
245
|
" tokens") : null));
|
|
246
246
|
}
|
|
247
247
|
function StatusLine({ model, ctxTokens }) {
|
|
248
|
-
const
|
|
248
|
+
const max = Number(process.env.WORMCLAUDE_CTX) || 12288;
|
|
249
|
+
const pct = Math.min(100, Math.round((ctxTokens / max) * 100));
|
|
250
|
+
const filled = Math.round(pct / 10);
|
|
251
|
+
const bar = '█'.repeat(filled) + '░'.repeat(10 - filled);
|
|
252
|
+
const barColor = pct > 85 ? theme.errorRed : pct > 60 ? theme.redBright : theme.grey;
|
|
249
253
|
return (React.createElement(Box, null,
|
|
250
254
|
React.createElement(Text, { color: theme.greyDim },
|
|
251
255
|
' ',
|
|
256
|
+
"WormClaude "),
|
|
257
|
+
React.createElement(Text, { color: theme.red, bold: true },
|
|
258
|
+
"v",
|
|
259
|
+
VERSION),
|
|
260
|
+
React.createElement(Text, { color: theme.greyDim },
|
|
261
|
+
" \u00B7 ",
|
|
252
262
|
model,
|
|
253
|
-
" \u00B7
|
|
254
|
-
|
|
255
|
-
|
|
263
|
+
" \u00B7 "),
|
|
264
|
+
React.createElement(Text, { color: barColor }, bar),
|
|
265
|
+
React.createElement(Text, { color: theme.greyDim },
|
|
266
|
+
" ",
|
|
256
267
|
pct,
|
|
257
|
-
"%
|
|
268
|
+
"% \u00B7 ",
|
|
269
|
+
ctxTokens.toLocaleString(),
|
|
270
|
+
" tok")));
|
|
258
271
|
}
|
|
259
272
|
function App() {
|
|
260
273
|
const { exit } = useApp();
|
|
@@ -470,6 +483,8 @@ function App() {
|
|
|
470
483
|
let done = false;
|
|
471
484
|
let usedWeb = false; // bu turda web aracı kullanıldı mı (öğrenme için)
|
|
472
485
|
let lastAnswer = ''; // modelin son (sentez) cevabı
|
|
486
|
+
let lastToolSig = '';
|
|
487
|
+
let sameToolCount = 0;
|
|
473
488
|
while (iter < MAX_TURNS) {
|
|
474
489
|
if (ac.signal.aborted) {
|
|
475
490
|
push({ kind: 'note', text: t('note.interrupted') });
|
|
@@ -554,6 +569,20 @@ function App() {
|
|
|
554
569
|
done = true;
|
|
555
570
|
break;
|
|
556
571
|
}
|
|
572
|
+
// Takilma korumasi: ayni arac cagrisi 3 kez ust uste gelirse dur
|
|
573
|
+
const _sig = JSON.stringify(toolCalls.map((tc) => tc.name + ':' + (tc.args || '')));
|
|
574
|
+
if (_sig === lastToolSig) {
|
|
575
|
+
sameToolCount++;
|
|
576
|
+
}
|
|
577
|
+
else {
|
|
578
|
+
sameToolCount = 0;
|
|
579
|
+
lastToolSig = _sig;
|
|
580
|
+
}
|
|
581
|
+
if (sameToolCount >= 2) {
|
|
582
|
+
push({ kind: 'note', text: getLang() === 'en' ? 'Same step repeated 3x, stopping to avoid a loop.' : 'Ayni adim 3 kez tekrarlandi, dongu onlemek icin durduruldu.' });
|
|
583
|
+
done = true;
|
|
584
|
+
break;
|
|
585
|
+
}
|
|
557
586
|
// Paralel araç çalıştırma + izin onayı (yazanlar sıralı)
|
|
558
587
|
setThinking(false);
|
|
559
588
|
setPhase(toolCalls.length > 1 ? t('phase.toolsMulti', toolCalls.length) : t('phase.toolRun', toolCalls[0].name));
|
package/dist/computer.js
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// Computer-use: çapraz-platform ekran görüntüsü + fare/klavye.
|
|
2
|
+
// Yöntem: işletim sistemi araçları (native bağımlılık YOK).
|
|
3
|
+
// Windows → PowerShell + .NET (yerleşik)
|
|
4
|
+
// macOS → screencapture + osascript (yerleşik) · fare için cliclick gerekir
|
|
5
|
+
// Linux → scrot/import/grim + xdotool (paket gerekebilir)
|
|
6
|
+
import { execFileSync } from 'node:child_process';
|
|
7
|
+
import * as fs from 'node:fs';
|
|
8
|
+
import * as os from 'node:os';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
const PLAT = process.platform;
|
|
11
|
+
const tmpFile = (ext) => path.join(os.tmpdir(), `wc_${Date.now()}_${Math.floor(Math.random() * 1e9)}.${ext}`);
|
|
12
|
+
// PowerShell tek-tırnak string literali ('' ile kaçış)
|
|
13
|
+
function psStr(s) {
|
|
14
|
+
return "'" + String(s).replace(/'/g, "''") + "'";
|
|
15
|
+
}
|
|
16
|
+
function runPS(script) {
|
|
17
|
+
return execFileSync('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', script], { encoding: 'utf8', windowsHide: true, timeout: 30000, maxBuffer: 64 * 1024 * 1024 });
|
|
18
|
+
}
|
|
19
|
+
// ── Ekran görüntüsü → base64 PNG ────────────────────────────────────────────
|
|
20
|
+
export function screenshot() {
|
|
21
|
+
const out = tmpFile('png');
|
|
22
|
+
try {
|
|
23
|
+
if (PLAT === 'win32') {
|
|
24
|
+
const p = out.replace(/\\/g, '\\\\');
|
|
25
|
+
runPS(`Add-Type -AssemblyName System.Windows.Forms,System.Drawing; ` +
|
|
26
|
+
`$b=[System.Windows.Forms.SystemInformation]::VirtualScreen; ` +
|
|
27
|
+
`$bmp=New-Object System.Drawing.Bitmap $b.Width,$b.Height; ` +
|
|
28
|
+
`$g=[System.Drawing.Graphics]::FromImage($bmp); ` +
|
|
29
|
+
`$g.CopyFromScreen($b.X,$b.Y,0,0,$bmp.Size); ` +
|
|
30
|
+
`$bmp.Save('${p}',[System.Drawing.Imaging.ImageFormat]::Png); ` +
|
|
31
|
+
`$g.Dispose();$bmp.Dispose()`);
|
|
32
|
+
}
|
|
33
|
+
else if (PLAT === 'darwin') {
|
|
34
|
+
execFileSync('screencapture', ['-x', out], { timeout: 20000 });
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const tries = [
|
|
38
|
+
['scrot', ['-o', out]],
|
|
39
|
+
['import', ['-window', 'root', out]],
|
|
40
|
+
['grim', [out]],
|
|
41
|
+
];
|
|
42
|
+
let ok = false;
|
|
43
|
+
for (const [cmd, a] of tries) {
|
|
44
|
+
try {
|
|
45
|
+
execFileSync(cmd, a, { timeout: 20000 });
|
|
46
|
+
ok = true;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
catch { }
|
|
50
|
+
}
|
|
51
|
+
if (!ok)
|
|
52
|
+
throw new Error('Linux ekran görüntüsü aracı yok (scrot / imagemagick / grim kurun)');
|
|
53
|
+
}
|
|
54
|
+
return fs.readFileSync(out).toString('base64');
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
try {
|
|
58
|
+
fs.unlinkSync(out);
|
|
59
|
+
}
|
|
60
|
+
catch { }
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// ── Fare ────────────────────────────────────────────────────────────────────
|
|
64
|
+
export function click(x, y, button = 'left') {
|
|
65
|
+
const X = Math.round(x), Y = Math.round(y);
|
|
66
|
+
if (PLAT === 'win32') {
|
|
67
|
+
const down = button === 'right' ? '0x08' : '0x02';
|
|
68
|
+
const up = button === 'right' ? '0x10' : '0x04';
|
|
69
|
+
runPS(`Add-Type @'
|
|
70
|
+
using System;using System.Runtime.InteropServices;
|
|
71
|
+
public class WCm{[DllImport("user32.dll")]public static extern bool SetCursorPos(int x,int y);[DllImport("user32.dll")]public static extern void mouse_event(uint f,uint x,uint y,uint d,int e);}
|
|
72
|
+
'@; [WCm]::SetCursorPos(${X},${Y}); Start-Sleep -Milliseconds 60; [WCm]::mouse_event(${down},0,0,0,0); [WCm]::mouse_event(${up},0,0,0,0)`);
|
|
73
|
+
}
|
|
74
|
+
else if (PLAT === 'darwin') {
|
|
75
|
+
execFileSync('cliclick', [`${button === 'right' ? 'rc' : 'c'}:${X},${Y}`], { timeout: 10000 });
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
execFileSync('xdotool', ['mousemove', String(X), String(Y), 'click', button === 'right' ? '3' : '1'], { timeout: 10000 });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// ── Klavye: düz metin yazma ──────────────────────────────────────────────────
|
|
82
|
+
export function typeText(text) {
|
|
83
|
+
if (PLAT === 'win32') {
|
|
84
|
+
const esc = String(text).replace(/([+^%~(){}\[\]])/g, '{$1}');
|
|
85
|
+
runPS(`Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.SendKeys]::SendWait(${psStr(esc)})`);
|
|
86
|
+
}
|
|
87
|
+
else if (PLAT === 'darwin') {
|
|
88
|
+
execFileSync('osascript', ['-e', `tell application "System Events" to keystroke ${osaStr(text)}`], { timeout: 15000 });
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
execFileSync('xdotool', ['type', '--clearmodifiers', String(text)], { timeout: 15000 });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function osaStr(s) {
|
|
95
|
+
return '"' + String(s).replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
|
|
96
|
+
}
|
|
97
|
+
// ── Klavye: özel tuş / kombinasyon (Enter, Tab, Ctrl+C ...) ──────────────────
|
|
98
|
+
export function key(combo) {
|
|
99
|
+
const parts = String(combo).split('+').map((p) => p.trim()).filter(Boolean);
|
|
100
|
+
if (PLAT === 'win32') {
|
|
101
|
+
runPS(`Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.SendKeys]::SendWait(${psStr(toSendKeys(parts))})`);
|
|
102
|
+
}
|
|
103
|
+
else if (PLAT === 'darwin') {
|
|
104
|
+
const mods = parts.slice(0, -1).map(macMod).filter(Boolean);
|
|
105
|
+
const k = parts[parts.length - 1];
|
|
106
|
+
const code = macKeyCode(k);
|
|
107
|
+
const using = mods.length ? ` using {${mods.join(', ')}}` : '';
|
|
108
|
+
if (code != null)
|
|
109
|
+
execFileSync('osascript', ['-e', `tell application "System Events" to key code ${code}${using}`], { timeout: 10000 });
|
|
110
|
+
else
|
|
111
|
+
execFileSync('osascript', ['-e', `tell application "System Events" to keystroke ${osaStr(k.toLowerCase())}${using}`], { timeout: 10000 });
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
execFileSync('xdotool', ['key', parts.map(xMod).join('+')], { timeout: 10000 });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// ── Kaydırma ─────────────────────────────────────────────────────────────────
|
|
118
|
+
export function scroll(direction, amount = 3) {
|
|
119
|
+
const n = Math.max(1, Math.min(20, Math.round(amount)));
|
|
120
|
+
if (PLAT === 'win32') {
|
|
121
|
+
const delta = direction === 'up' ? 120 : -120;
|
|
122
|
+
runPS(`Add-Type @'
|
|
123
|
+
using System;using System.Runtime.InteropServices;
|
|
124
|
+
public class WCs{[DllImport("user32.dll")]public static extern void mouse_event(uint f,uint x,uint y,int d,int e);}
|
|
125
|
+
'@; for($i=0;$i -lt ${n};$i++){[WCs]::mouse_event(0x0800,0,0,${delta},0);Start-Sleep -Milliseconds 30}`);
|
|
126
|
+
}
|
|
127
|
+
else if (PLAT === 'darwin') {
|
|
128
|
+
const dir = direction === 'up' ? n : -n;
|
|
129
|
+
execFileSync('osascript', ['-e', `tell application "System Events" to scroll {0, ${dir}}`], { timeout: 10000 });
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
execFileSync('xdotool', ['click', '--repeat', String(n), direction === 'up' ? '4' : '5'], { timeout: 10000 });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// ── Yardımcı eşlemeler ───────────────────────────────────────────────────────
|
|
136
|
+
function toSendKeys(parts) {
|
|
137
|
+
const mod = { ctrl: '^', control: '^', alt: '%', shift: '+', win: '^{ESC}' };
|
|
138
|
+
const special = {
|
|
139
|
+
enter: '{ENTER}', return: '{ENTER}', tab: '{TAB}', esc: '{ESC}', escape: '{ESC}',
|
|
140
|
+
backspace: '{BACKSPACE}', delete: '{DELETE}', del: '{DELETE}', up: '{UP}', down: '{DOWN}',
|
|
141
|
+
left: '{LEFT}', right: '{RIGHT}', home: '{HOME}', end: '{END}', pageup: '{PGUP}', pagedown: '{PGDN}',
|
|
142
|
+
space: ' ', f1: '{F1}', f2: '{F2}', f3: '{F3}', f4: '{F4}', f5: '{F5}',
|
|
143
|
+
};
|
|
144
|
+
const k = parts[parts.length - 1].toLowerCase();
|
|
145
|
+
const pre = parts.slice(0, -1).map((p) => mod[p.toLowerCase()] || '').join('');
|
|
146
|
+
const main = special[k] || (k.length === 1 ? k : `{${k.toUpperCase()}}`);
|
|
147
|
+
return pre + main;
|
|
148
|
+
}
|
|
149
|
+
function macMod(m) {
|
|
150
|
+
const map = { ctrl: 'control down', control: 'control down', alt: 'option down', option: 'option down', shift: 'shift down', cmd: 'command down', win: 'command down' };
|
|
151
|
+
return map[m.toLowerCase()] || '';
|
|
152
|
+
}
|
|
153
|
+
function macKeyCode(k) {
|
|
154
|
+
const map = { enter: 36, return: 36, tab: 48, space: 49, esc: 53, escape: 53, delete: 51, backspace: 51, up: 126, down: 125, left: 123, right: 124, home: 115, end: 119 };
|
|
155
|
+
return map[k.toLowerCase()] ?? null;
|
|
156
|
+
}
|
|
157
|
+
function xMod(m) {
|
|
158
|
+
const map = { ctrl: 'ctrl', control: 'ctrl', alt: 'alt', shift: 'shift', win: 'super', cmd: 'super', enter: 'Return', return: 'Return', esc: 'Escape', escape: 'Escape', del: 'Delete', pageup: 'Prior', pagedown: 'Next' };
|
|
159
|
+
return map[m.toLowerCase()] || m;
|
|
160
|
+
}
|
|
161
|
+
// ── "Gör": ekran görüntüsü al → VL modeline sor → metin döndür ────────────────
|
|
162
|
+
export async function see(question, config) {
|
|
163
|
+
const b64 = screenshot();
|
|
164
|
+
const base = (config.baseUrl || 'https://api.wormclaude.ai/v1').replace(/\/$/, '');
|
|
165
|
+
const body = {
|
|
166
|
+
model: 'wormclaude-vision',
|
|
167
|
+
messages: [{
|
|
168
|
+
role: 'user',
|
|
169
|
+
content: [
|
|
170
|
+
{ type: 'text', text: question || 'Ekranda ne görüyorsun? Önemli öğeleri ve konumlarını (yaklaşık koordinat) söyle.' },
|
|
171
|
+
{ type: 'image_url', image_url: { url: 'data:image/png;base64,' + b64 } },
|
|
172
|
+
],
|
|
173
|
+
}],
|
|
174
|
+
max_tokens: 400,
|
|
175
|
+
temperature: 0.2,
|
|
176
|
+
};
|
|
177
|
+
const res = await fetch(`${base}/chat/completions`, {
|
|
178
|
+
method: 'POST',
|
|
179
|
+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${config.apiKey}` },
|
|
180
|
+
body: JSON.stringify(body),
|
|
181
|
+
});
|
|
182
|
+
if (!res.ok)
|
|
183
|
+
throw new Error(`vision HTTP ${res.status}: ${(await res.text()).slice(0, 200)}`);
|
|
184
|
+
const data = await res.json();
|
|
185
|
+
return data?.choices?.[0]?.message?.content || '(boş yanıt)';
|
|
186
|
+
}
|
package/dist/theme.js
CHANGED
package/dist/tools.js
CHANGED
|
@@ -11,6 +11,7 @@ import { runAgentLoop } from './agent.js';
|
|
|
11
11
|
import { tasks } from './tasks.js';
|
|
12
12
|
import { getMcpToolSchemas, callMcpTool } from './mcp.js';
|
|
13
13
|
import { getAutoSkills, getSkill, buildSkillPrompt } from './skills.js';
|
|
14
|
+
import * as computer from './computer.js';
|
|
14
15
|
// Agent/alt-agent araçlarının backend'e ulaşması için config. cli.tsx başlangıçta
|
|
15
16
|
// setToolConfig ile aynı (mutable) config nesnesini verir → /config değişiklikleri görülür.
|
|
16
17
|
let toolConfig = null;
|
|
@@ -503,9 +504,16 @@ function skillToolSchema() {
|
|
|
503
504
|
};
|
|
504
505
|
}
|
|
505
506
|
// Yerleşik + MCP + autoInvoke-skill araçlarının tümü. Ana döngü ve alt-agent'lar kullanır.
|
|
507
|
+
const computerToolSchemas = [
|
|
508
|
+
{ type: 'function', function: { name: 'See', description: 'Ekran goruntusu alir ve gorsel modele sorar. Bilgisayari kontrol etmeden ONCE ekranda ne oldugunu gormek icin kullan. Donen metin ekranin aciklamasidir (ogeler, metinler, yaklasik koordinatlar).', parameters: { type: 'object', properties: { question: { type: 'string', description: 'Ekranda ne ariyorsun? Orn: "Kaydet butonu nerede, koordinati ne?"' } }, required: ['question'] } } },
|
|
509
|
+
{ type: 'function', function: { name: 'Click', description: 'Ekranda (x,y) piksel koordinatina fare tiklamasi yapar. Koordinati once See ile ogren.', parameters: { type: 'object', properties: { x: { type: 'number' }, y: { type: 'number' }, button: { type: 'string', enum: ['left', 'right'], description: 'Varsayilan left' } }, required: ['x', 'y'] } } },
|
|
510
|
+
{ type: 'function', function: { name: 'Type', description: 'Klavyeden duz metin yazar (aktif pencereye).', parameters: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] } } },
|
|
511
|
+
{ type: 'function', function: { name: 'Key', description: 'Ozel tus / kombinasyon gonderir. Orn: "Enter", "Tab", "Ctrl+C", "Alt+F4".', parameters: { type: 'object', properties: { keys: { type: 'string' } }, required: ['keys'] } } },
|
|
512
|
+
{ type: 'function', function: { name: 'Scroll', description: 'Fare tekerlegiyle kaydirir.', parameters: { type: 'object', properties: { direction: { type: 'string', enum: ['up', 'down'] }, amount: { type: 'number', description: 'Varsayilan 3' } }, required: ['direction'] } } },
|
|
513
|
+
];
|
|
506
514
|
export function allToolSchemas() {
|
|
507
515
|
const sk = skillToolSchema();
|
|
508
|
-
return [...toolSchemas, ...getMcpToolSchemas(), ...(sk ? [sk] : [])];
|
|
516
|
+
return [...toolSchemas, ...computerToolSchemas, ...getMcpToolSchemas(), ...(sk ? [sk] : [])];
|
|
509
517
|
}
|
|
510
518
|
const TOOL_META = {
|
|
511
519
|
Read: { readOnly: true, concurrencySafe: true },
|
|
@@ -517,6 +525,11 @@ const TOOL_META = {
|
|
|
517
525
|
Write: { needsPermission: true, validate: (a) => (a && a.file_path ? null : 'file_path gerekli') },
|
|
518
526
|
Edit: { needsPermission: true, validate: (a) => (a && a.file_path && a.old_string != null ? null : 'file_path ve old_string gerekli') },
|
|
519
527
|
Agent: { validate: (a) => (a && a.prompt ? null : 'prompt gerekli') },
|
|
528
|
+
See: { readOnly: true, needsPermission: true, validate: (a) => (a && a.question ? null : 'question gerekli') },
|
|
529
|
+
Click: { needsPermission: true, validate: (a) => (a && a.x != null && a.y != null ? null : 'x ve y gerekli') },
|
|
530
|
+
Type: { needsPermission: true, validate: (a) => (a && a.text != null ? null : 'text gerekli') },
|
|
531
|
+
Key: { needsPermission: true, validate: (a) => (a && a.keys ? null : 'keys gerekli') },
|
|
532
|
+
Scroll: { needsPermission: true, validate: (a) => (a && a.direction ? null : 'direction gerekli') },
|
|
520
533
|
WebSearch: { readOnly: true, needsPermission: true, validate: (a) => (a && a.query ? null : 'query gerekli') },
|
|
521
534
|
TodoWrite: { readOnly: true, validate: (a) => (a && Array.isArray(a.todos) ? null : 'todos dizisi gerekli') },
|
|
522
535
|
PowerShell: { needsPermission: true, validate: (a) => (a && a.command ? null : 'command gerekli') },
|
|
@@ -681,6 +694,16 @@ export function toolLabel(name, args) {
|
|
|
681
694
|
return 'EnterPlanMode()';
|
|
682
695
|
if (name === 'ExitPlanMode')
|
|
683
696
|
return 'ExitPlanMode()';
|
|
697
|
+
if (name === 'See')
|
|
698
|
+
return `See(${String(args.question || '').slice(0, 40)})`;
|
|
699
|
+
if (name === 'Click')
|
|
700
|
+
return `Click(${Math.round(args.x)}, ${Math.round(args.y)})`;
|
|
701
|
+
if (name === 'Type')
|
|
702
|
+
return `Type(${String(args.text || '').slice(0, 30)})`;
|
|
703
|
+
if (name === 'Key')
|
|
704
|
+
return `Key(${args.keys})`;
|
|
705
|
+
if (name === 'Scroll')
|
|
706
|
+
return `Scroll(${args.direction})`;
|
|
684
707
|
if (name.startsWith('mcp__')) {
|
|
685
708
|
const parts = name.split('__');
|
|
686
709
|
return `MCP·${parts[1]}(${parts.slice(2).join('__')})`;
|
|
@@ -737,6 +760,26 @@ const TYPE_EXT = {
|
|
|
737
760
|
// ── Executor ──────────────────────────────────────────────────────────────────
|
|
738
761
|
export async function executeTool(name, args) {
|
|
739
762
|
try {
|
|
763
|
+
if (name === 'See') {
|
|
764
|
+
const ans = await computer.see(String(args.question || ''), cfg());
|
|
765
|
+
return { ok: true, output: ans };
|
|
766
|
+
}
|
|
767
|
+
if (name === 'Click') {
|
|
768
|
+
computer.click(Number(args.x), Number(args.y), args.button === 'right' ? 'right' : 'left');
|
|
769
|
+
return { ok: true, output: `Tiklandi (${Math.round(args.x)}, ${Math.round(args.y)})` };
|
|
770
|
+
}
|
|
771
|
+
if (name === 'Type') {
|
|
772
|
+
computer.typeText(String(args.text ?? ''));
|
|
773
|
+
return { ok: true, output: `Yazildi (${String(args.text ?? '').length} karakter)` };
|
|
774
|
+
}
|
|
775
|
+
if (name === 'Key') {
|
|
776
|
+
computer.key(String(args.keys || ''));
|
|
777
|
+
return { ok: true, output: `Tus: ${args.keys}` };
|
|
778
|
+
}
|
|
779
|
+
if (name === 'Scroll') {
|
|
780
|
+
computer.scroll(args.direction === 'up' ? 'up' : 'down', Number(args.amount) || 3);
|
|
781
|
+
return { ok: true, output: `Kaydirildi: ${args.direction}` };
|
|
782
|
+
}
|
|
740
783
|
if (name === 'Bash') {
|
|
741
784
|
if (args.run_in_background) {
|
|
742
785
|
const task = tasks.create('shell', String(args.command).slice(0, 60));
|