@takimcizgisi/ajan 0.2.5 → 0.3.0
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.
Potentially problematic release.
This version of @takimcizgisi/ajan might be problematic. Click here for more details.
- package/LICENSE +227 -674
- package/README.md +243 -305
- package/ajan-logo.txt +2 -0
- package/dist/config/configManager.js +122 -19
- package/dist/config/types.d.ts +37 -0
- package/dist/core/agent.d.ts +1 -1
- package/dist/core/agent.js +25 -4
- package/dist/discord/presence.d.ts +65 -0
- package/dist/discord/presence.js +401 -0
- package/dist/engine/llama.d.ts +5 -0
- package/dist/engine/llama.js +19 -5
- package/dist/engine/modelManager.d.ts +0 -1
- package/dist/engine/modelManager.js +0 -8
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/service.js +0 -1
- package/dist/tools/playground.d.ts +4 -0
- package/dist/tools/playground.js +125 -0
- package/dist/tools/registry.d.ts +0 -1
- package/dist/tools/registry.js +5 -4
- package/dist/tools/taskComplete.js +16 -4
- package/dist/tools/terminal.js +12 -12
- package/dist/utils/paths.d.ts +1 -0
- package/dist/utils/paths.js +29 -11
- package/package.json +78 -106
- package/scripts/build-vscode.mjs +28 -0
- package/scripts/ensure-tgz.mjs +27 -0
- package/scripts/install-vscode.mjs +236 -0
- package/scripts/release.mjs +19 -0
- package/scripts/smoke-new-tools.ts +79 -0
- package/scripts/smoke-tools.ts +201 -0
- package/src/vscode/LICENSE +674 -0
- package/src/vscode/README.md +54 -0
- package/src/vscode/media/assets/Anton.ttf +0 -0
- package/src/vscode/media/chat.js +634 -0
- package/src/vscode/media/style.css +767 -0
- package/src/vscode/out/extension.js +598 -0
- package/src/vscode/package.json +243 -0
- package/dist/cli/index.d.ts +0 -2
- package/dist/cli/index.js +0 -741
- package/dist/cli/tui.d.ts +0 -145
- package/dist/cli/tui.js +0 -1003
- package/dist/electron/main.d.ts +0 -1
- package/dist/electron/main.js +0 -364
- package/dist/electron/preload.d.ts +0 -1
- package/dist/electron/preload.js +0 -67
- package/dist/utils/clipboard.d.ts +0 -2
- package/dist/utils/clipboard.js +0 -40
- package/dist/utils/lock.d.ts +0 -12
- package/dist/utils/lock.js +0 -68
- package/dist/utils/sacGuard.d.ts +0 -4
- package/dist/utils/sacGuard.js +0 -47
- package/dist/utils/spinner.d.ts +0 -10
- package/dist/utils/spinner.js +0 -32
- package/src/gui/assets/image/logo.svg +0 -1
- package/src/gui/assets/image/opencode.svg +0 -18
- package/src/gui/css/style.css +0 -430
- package/src/gui/html/chat.html +0 -34
- package/src/gui/html/downloads.html +0 -11
- package/src/gui/html/hakkinda.html +0 -26
- package/src/gui/html/index.html +0 -82
- package/src/gui/html/projects.html +0 -12
- package/src/gui/html/settings.html +0 -4
- package/src/gui/js/app.js +0 -197
- package/src/gui/js/chat.js +0 -434
- package/src/gui/js/downloads.js +0 -172
- package/src/gui/js/hakkinda.js +0 -16
- package/src/gui/js/projects.js +0 -113
- package/src/gui/js/settings.js +0 -177
- /package/src/{gui/assets/image → vscode/media/assets}/AJAN_LOGO.svg +0 -0
- /package/src/{gui/assets/image → vscode/media/assets}/ajan.png +0 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync, existsSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { createCoreTools } from "../src/tools/registry.js";
|
|
5
|
+
import { openPlaygroundTool, setTodosTool, getTodosTool } from "../src/tools/playground.js";
|
|
6
|
+
import { taskCompleteTool } from "../src/tools/taskComplete.js";
|
|
7
|
+
|
|
8
|
+
let failures = 0;
|
|
9
|
+
const check = (name: string, ok: boolean, detail?: string): void => {
|
|
10
|
+
if (ok) console.log(` ok ${name}`);
|
|
11
|
+
else { failures++; console.log(` FAIL ${name}${detail ? ` — ${detail}` : ""}`); }
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const tmp = mkdtempSync(join(tmpdir(), "ajan-test-"));
|
|
15
|
+
const ctx = { cwd: tmp, config: { modelId: "x", maxToolOutput: 100000 } };
|
|
16
|
+
|
|
17
|
+
const tools = createCoreTools(ctx);
|
|
18
|
+
const names = tools.map(t => t.name);
|
|
19
|
+
|
|
20
|
+
check("çekirdek araçlar korundu", tools.length >= 18, `toplam ${tools.length}`);
|
|
21
|
+
for (const need of [
|
|
22
|
+
"open_playground", "set_todos", "get_todos"
|
|
23
|
+
]) {
|
|
24
|
+
check(`araç ${need}`, names.includes(need));
|
|
25
|
+
}
|
|
26
|
+
check("GUI otomasyon araçları kaldırıldı",
|
|
27
|
+
!["screen_info", "screenshot", "mouse_move", "mouse_click", "mouse_scroll", "key_press", "type_text"].some(n => names.includes(n)),
|
|
28
|
+
names.filter(n => n.includes("screen") || n.includes("mouse") || n.includes("key_") || n.includes("type")).join(","));
|
|
29
|
+
|
|
30
|
+
const opened = await openPlaygroundTool.handler({}, ctx);
|
|
31
|
+
check("open_playground oluşturur", opened.ok && opened.output.includes(".ajan"), opened.output);
|
|
32
|
+
|
|
33
|
+
const played = await openPlaygroundTool.handler({ note: "deneme" }, ctx);
|
|
34
|
+
check("open_playground korur", played.ok && played.output.includes("0 öğe"), played.output);
|
|
35
|
+
|
|
36
|
+
const set = await setTodosTool.handler(
|
|
37
|
+
{ todos: [{ text: "adım 1" }, { text: "adım 2", done: true }] },
|
|
38
|
+
ctx
|
|
39
|
+
);
|
|
40
|
+
check("set_todos kaydeder", set.ok && set.output.includes("2 madde"), set.output);
|
|
41
|
+
|
|
42
|
+
const get = await getTodosTool.handler({}, ctx);
|
|
43
|
+
check("get_todos okur", get.ok && get.output.includes("adım 1") && get.output.includes("[x] 2."), get.output);
|
|
44
|
+
|
|
45
|
+
const reset = await openPlaygroundTool.handler({ reset: true }, ctx);
|
|
46
|
+
check("open_playground reset temizler", reset.ok && reset.output.includes("1 temizlendi"), reset.output);
|
|
47
|
+
|
|
48
|
+
const get2 = await getTodosTool.handler({}, ctx);
|
|
49
|
+
check("reset sonrası TODO boş", get2.ok && get2.output.includes("TODO yok"), get2.output);
|
|
50
|
+
|
|
51
|
+
const sigA: { taskCompleted?: boolean; continueRequested?: boolean } = {};
|
|
52
|
+
const resA = await taskCompleteTool.handler({ report: "ara rapor", continue: true }, { cwd: tmp, config: {}, signals: sigA });
|
|
53
|
+
check("task_complete continue:true tur açar", resA.ok && sigA.continueRequested === true && !sigA.taskCompleted, resA.output);
|
|
54
|
+
|
|
55
|
+
const sigB: { taskCompleted?: boolean; continueRequested?: boolean } = {};
|
|
56
|
+
const resB = await taskCompleteTool.handler({ report: "bitti", continue: false }, { cwd: tmp, config: {}, signals: sigB });
|
|
57
|
+
check("task_complete continue:false bitirir", resB.ok && sigB.taskCompleted === true && !sigB.continueRequested, resB.output);
|
|
58
|
+
|
|
59
|
+
const sigC: { taskCompleted?: boolean; continueRequested?: boolean } = {};
|
|
60
|
+
const resC = await taskCompleteTool.handler({ report: "bitti" }, { cwd: tmp, config: {}, signals: sigC });
|
|
61
|
+
check("task_complete varsayılan bitirir", resC.ok && sigC.taskCompleted === true && !sigC.continueRequested, resC.output);
|
|
62
|
+
|
|
63
|
+
const sigD: { taskCompleted?: boolean; continueRequested?: boolean } = {};
|
|
64
|
+
const resD = await taskCompleteTool.handler({ report: "bitti" }, { cwd: tmp, config: {}, signals: sigD });
|
|
65
|
+
check("task_complete report korunur", resD.ok && resD.output.includes("bitti"), resD.output);
|
|
66
|
+
|
|
67
|
+
// Geçici dizini temizle (Windows kilitleri için birkaç deneme).
|
|
68
|
+
for (let attempt = 0; attempt < 10 && existsSync(tmp); attempt++) {
|
|
69
|
+
try {
|
|
70
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
71
|
+
} catch {
|
|
72
|
+
/* kilitli: bekleyip tekrar dene */
|
|
73
|
+
}
|
|
74
|
+
if (!existsSync(tmp)) break;
|
|
75
|
+
await new Promise((r) => setTimeout(r, 400));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.log(failures === 0 ? "\nYENİ ARAÇ TESTLERİ GEÇTİ" : `\n${failures} TEST BAŞARISIZ`);
|
|
79
|
+
process.exitCode = failures === 0 ? 0 : 1;
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync, readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import { createCoreTools } from "../src/tools/registry.js";
|
|
5
|
+
import type { AjanConfig, ToolExecutionContext } from "../src/config/types.js";
|
|
6
|
+
|
|
7
|
+
let failures = 0;
|
|
8
|
+
|
|
9
|
+
function check(name: string, ok: boolean, detail?: string): void {
|
|
10
|
+
if (ok) {
|
|
11
|
+
console.log(` ok ${name}`);
|
|
12
|
+
} else {
|
|
13
|
+
failures++;
|
|
14
|
+
console.log(` FAIL ${name}${detail ? ` — ${detail}` : ""}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function main(): Promise<void> {
|
|
19
|
+
const tmp = mkdtempSync(join(os.tmpdir(), "ajan-smoke-"));
|
|
20
|
+
const config: AjanConfig = {
|
|
21
|
+
modelId: "smoke",
|
|
22
|
+
toolTimeout: 2_000,
|
|
23
|
+
maxToolOutput: 10_000
|
|
24
|
+
};
|
|
25
|
+
const ctx: ToolExecutionContext = { cwd: tmp, config };
|
|
26
|
+
const tools = new Map(createCoreTools(ctx).map((t) => [t.name, t]));
|
|
27
|
+
const run = (name: string, params: Record<string, unknown>): Promise<{ ok: boolean; output: string }> => {
|
|
28
|
+
const tool = tools.get(name);
|
|
29
|
+
if (!tool) throw new Error(`Araç yok: ${name}`);
|
|
30
|
+
return Promise.resolve(tool.handler(params, ctx));
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
console.log("Araç smoke testi");
|
|
34
|
+
console.log(`Geçici dizin: ${tmp}\n`);
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
// write_file + read_file
|
|
38
|
+
let res = await run("write_file", { path: "src/merhaba.txt", content: "ilk satır\nikinci satır" });
|
|
39
|
+
check("write_file oluşturur", res.ok && existsSync(join(tmp, "src", "merhaba.txt")), res.output);
|
|
40
|
+
|
|
41
|
+
res = await run("write_file", { path: "src/merhaba.txt", content: "\nüçüncü satır", append: true });
|
|
42
|
+
check("write_file append", res.ok, res.output);
|
|
43
|
+
|
|
44
|
+
res = await run("read_file", { path: "src/merhaba.txt" });
|
|
45
|
+
check("read_file içerik", res.ok && res.output.includes("ilk satır") && res.output.includes("üçüncü satır"), res.output);
|
|
46
|
+
|
|
47
|
+
// list_dir
|
|
48
|
+
res = await run("list_dir", { path: ".", recursive: true });
|
|
49
|
+
check("list_dir recursive", res.ok && res.output.includes("merhaba.txt"), res.output);
|
|
50
|
+
|
|
51
|
+
// search_files
|
|
52
|
+
res = await run("search_files", { pattern: "**/*.txt" });
|
|
53
|
+
check("search_files glob", res.ok && res.output.includes("merhaba.txt"), res.output);
|
|
54
|
+
|
|
55
|
+
// grep_files
|
|
56
|
+
res = await run("grep_files", { pattern: "üçüncü" });
|
|
57
|
+
check("grep_files bulur", res.ok && res.output.includes("üçüncü"), res.output);
|
|
58
|
+
|
|
59
|
+
res = await run("grep_files", { pattern: "[" });
|
|
60
|
+
check("grep_files geçersiz regex hatası", !res.ok && res.output.includes("Geçersiz"), res.output);
|
|
61
|
+
|
|
62
|
+
// apply_patch
|
|
63
|
+
const patch = [
|
|
64
|
+
"--- a/src/merhaba.txt",
|
|
65
|
+
"+++ b/src/merhaba.txt",
|
|
66
|
+
"@@ -1,2 +1,3 @@",
|
|
67
|
+
" ilk satır",
|
|
68
|
+
"-ikinci satır",
|
|
69
|
+
"+yeni satır",
|
|
70
|
+
"+üçüncü satır"
|
|
71
|
+
].join("\n");
|
|
72
|
+
res = await run("apply_patch", { patch });
|
|
73
|
+
check("apply_patch uygular", res.ok, res.output);
|
|
74
|
+
const patched = readFileSync(join(tmp, "src", "merhaba.txt"), "utf8");
|
|
75
|
+
check("apply_patch içerik", patched.includes("yeni satır") && !patched.includes("ikinci satır"), patched);
|
|
76
|
+
|
|
77
|
+
// edit_file
|
|
78
|
+
res = await run("edit_file", { path: "src/merhaba.txt", oldString: "yeni satır", newString: "düzenlenmiş satır" });
|
|
79
|
+
check("edit_file değiştirir", res.ok, res.output);
|
|
80
|
+
let edited = readFileSync(join(tmp, "src", "merhaba.txt"), "utf8");
|
|
81
|
+
check("edit_file içerik", edited.includes("düzenlenmiş satır") && !edited.includes("yeni satır"), edited);
|
|
82
|
+
|
|
83
|
+
res = await run("edit_file", { path: "src/merhaba.txt", oldString: "yok böyle bir metin", newString: "x" });
|
|
84
|
+
check("edit_file eşleşme yok hatası", !res.ok && res.output.includes("Eşleşme bulunamadı"), res.output);
|
|
85
|
+
|
|
86
|
+
res = await run("edit_file", { path: "src/merhaba.txt", oldString: "satır", newString: "X", replaceAll: false });
|
|
87
|
+
check("edit_file çoklu eşleşme hatası", !res.ok && res.output.includes("kez geçiyor"), res.output);
|
|
88
|
+
|
|
89
|
+
res = await run("edit_file", { path: "src/merhaba.txt", oldString: "satır", newString: "satır", replaceAll: true });
|
|
90
|
+
check("edit_file replaceAll", res.ok, res.output);
|
|
91
|
+
|
|
92
|
+
// run_command: tehlikeli komut engeli
|
|
93
|
+
res = await run("run_command", { command: "format c:" });
|
|
94
|
+
check("run_command tehlikeli komut engellenir", !res.ok && res.output.includes("engellendi"), res.output);
|
|
95
|
+
|
|
96
|
+
// run_command: başarılı
|
|
97
|
+
const echoCmd = process.platform === "win32" ? "echo smoke-test-ok" : "echo smoke-test-ok";
|
|
98
|
+
res = await run("run_command", { command: echoCmd });
|
|
99
|
+
check("run_command başarılı", res.ok && res.output.includes("smoke-test-ok"), res.output);
|
|
100
|
+
|
|
101
|
+
// run_command: göreli cwd ctx.cwd'ye göre çözülür
|
|
102
|
+
res = await run("run_command", { command: echoCmd, cwd: "src" });
|
|
103
|
+
check("run_command göreli cwd", res.ok, res.output);
|
|
104
|
+
|
|
105
|
+
// run_command: timeout + süreç ağacı öldürme (Windows: taskkill)
|
|
106
|
+
const sleepCmd = process.platform === "win32"
|
|
107
|
+
? "ping -n 30 127.0.0.1 >nul"
|
|
108
|
+
: "sleep 30";
|
|
109
|
+
const started = Date.now();
|
|
110
|
+
res = await run("run_command", { command: sleepCmd, timeout: 1500 });
|
|
111
|
+
const elapsed = Date.now() - started;
|
|
112
|
+
check(
|
|
113
|
+
"run_command timeout döner (askıda kalmaz)",
|
|
114
|
+
!res.ok && res.output.includes("ZAMAN AŞIMI") && elapsed < 20_000,
|
|
115
|
+
`${res.output} (${elapsed}ms)`
|
|
116
|
+
);
|
|
117
|
+
// Windows'ta süreç ağacı tutamaçlarının bırakılması biraz zaman alır;
|
|
118
|
+
// temizlik öncesi kısa bir nefes ver.
|
|
119
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
120
|
+
|
|
121
|
+
// web_search: ağ varsa dene, yoksa uyar
|
|
122
|
+
res = await run("web_search", { query: "opencode test", maxResults: 3 });
|
|
123
|
+
if (res.ok) {
|
|
124
|
+
check("web_search sonuç", !res.output.includes("bulunamadı"), res.output.slice(0, 200));
|
|
125
|
+
} else {
|
|
126
|
+
console.log(` ---- web_search atlandı (ağ yok olabilir): ${res.output.slice(0, 120)}`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// task_complete: sinyali işaretler
|
|
130
|
+
const signals = { taskCompleted: false };
|
|
131
|
+
const ctxWithSignals: ToolExecutionContext = { ...ctx, signals };
|
|
132
|
+
const completeTool = tools.get("task_complete");
|
|
133
|
+
if (!completeTool) throw new Error("Araç yok: task_complete");
|
|
134
|
+
res = await Promise.resolve(completeTool.handler({ report: "bitti" }, ctxWithSignals));
|
|
135
|
+
check("task_complete sinyal", res.ok && signals.taskCompleted === true, res.output);
|
|
136
|
+
|
|
137
|
+
// not_al / not_oku
|
|
138
|
+
res = await run("not_al", { text: "smoke-test hafıza kaydı" });
|
|
139
|
+
check("not_al kaydeder", res.ok && res.output.includes("#"), res.output);
|
|
140
|
+
res = await run("not_oku", { query: "smoke-test" });
|
|
141
|
+
check("not_oku bulur", res.ok && res.output.includes("hafıza kaydı"), res.output);
|
|
142
|
+
|
|
143
|
+
// move_file + delete_file
|
|
144
|
+
res = await run("move_file", { source: "src/merhaba.txt", destination: "yeni/taşındı.txt" });
|
|
145
|
+
check("move_file taşır", res.ok && existsSync(join(tmp, "yeni", "taşındı.txt")), res.output);
|
|
146
|
+
res = await run("delete_file", { path: "yeni/taşındı.txt" });
|
|
147
|
+
check("delete_file siler", res.ok && !existsSync(join(tmp, "yeni", "taşındı.txt")), res.output);
|
|
148
|
+
res = await run("delete_file", { path: "." , recursive: true });
|
|
149
|
+
check("delete_file cwd koruması", !res.ok && res.output.includes("silemezsin"), res.output);
|
|
150
|
+
|
|
151
|
+
// read_data: JSON ve YAML
|
|
152
|
+
writeFileSync(join(tmp, "veri.json"), JSON.stringify({ ad: "ajan", sayi: 7, liste: [1, 2, 3] }), "utf8");
|
|
153
|
+
res = await run("read_data", { path: "veri.json" });
|
|
154
|
+
check("read_data json", res.ok && res.output.includes("ajan") && res.output.includes("nesne"), res.output);
|
|
155
|
+
writeFileSync(join(tmp, "veri.yaml"), "ad: ajan\nsayi: 7\n", "utf8");
|
|
156
|
+
res = await run("read_data", { path: "veri.yaml" });
|
|
157
|
+
check("read_data yaml", res.ok && res.output.includes("ajan"), res.output);
|
|
158
|
+
|
|
159
|
+
// unzip_file
|
|
160
|
+
const zipPath = join(tmp, "arsiv.zip");
|
|
161
|
+
const AdmZipMod = await import("adm-zip");
|
|
162
|
+
const zip = new AdmZipMod.default();
|
|
163
|
+
zip.addFile("icindekiler/okubeni.txt", Buffer.from("zip içeriği smoke", "utf8"));
|
|
164
|
+
zip.writeZip(zipPath);
|
|
165
|
+
res = await run("unzip_file", { path: "arsiv.zip" });
|
|
166
|
+
check(
|
|
167
|
+
"unzip_file açar",
|
|
168
|
+
res.ok && existsSync(join(tmp, "icindekiler", "okubeni.txt")) && readFileSync(join(tmp, "icindekiler", "okubeni.txt"), "utf8").includes("smoke"),
|
|
169
|
+
res.output
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
// fetch_url: ağ varsa dene
|
|
173
|
+
res = await run("fetch_url", { url: "https://example.com", maxLength: 2000 });
|
|
174
|
+
if (res.ok) {
|
|
175
|
+
check("fetch_url içerik", res.output.includes("example"), res.output.slice(0, 160));
|
|
176
|
+
} else {
|
|
177
|
+
console.log(` ---- fetch_url atlandı (ağ yok olabilir): ${res.output.slice(0, 120)}`);
|
|
178
|
+
}
|
|
179
|
+
} finally {
|
|
180
|
+
// Windows'ta force:true hata fırlatmayıp sessizce kalıntı bırakabildiği için
|
|
181
|
+
// dizinin gerçekten silindiğini kontrol ederek döngüyle dene.
|
|
182
|
+
// (timeout testinden kalan cmd.exe cwd tutamacını bırakana kadar beklenir.)
|
|
183
|
+
for (let attempt = 0; attempt < 15 && existsSync(tmp); attempt++) {
|
|
184
|
+
try {
|
|
185
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
186
|
+
} catch {
|
|
187
|
+
/* kilitli: bekleyip tekrar dene */
|
|
188
|
+
}
|
|
189
|
+
if (!existsSync(tmp)) break;
|
|
190
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
console.log(failures === 0 ? "\nTÜM TESTLER GEÇTİ" : `\n${failures} TEST BAŞARISIZ`);
|
|
195
|
+
process.exitCode = failures === 0 ? 0 : 1;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
main().catch((err) => {
|
|
199
|
+
console.error(err);
|
|
200
|
+
process.exit(1);
|
|
201
|
+
});
|