@takimcizgisi/ajan 0.2.5
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/LICENSE +674 -0
- package/README.md +366 -0
- package/config/models.json +54 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +741 -0
- package/dist/cli/tui.d.ts +145 -0
- package/dist/cli/tui.js +1003 -0
- package/dist/config/configManager.d.ts +18 -0
- package/dist/config/configManager.js +204 -0
- package/dist/config/types.d.ts +98 -0
- package/dist/config/types.js +2 -0
- package/dist/core/agent.d.ts +88 -0
- package/dist/core/agent.js +222 -0
- package/dist/electron/main.d.ts +1 -0
- package/dist/electron/main.js +364 -0
- package/dist/electron/preload.d.ts +1 -0
- package/dist/electron/preload.js +67 -0
- package/dist/engine/llama.d.ts +39 -0
- package/dist/engine/llama.js +146 -0
- package/dist/engine/modelManager.d.ts +18 -0
- package/dist/engine/modelManager.js +73 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +9 -0
- package/dist/service.d.ts +90 -0
- package/dist/service.js +268 -0
- package/dist/tools/data.d.ts +3 -0
- package/dist/tools/data.js +111 -0
- package/dist/tools/edit.d.ts +2 -0
- package/dist/tools/edit.js +48 -0
- package/dist/tools/file.d.ts +6 -0
- package/dist/tools/file.js +274 -0
- package/dist/tools/filesys.d.ts +3 -0
- package/dist/tools/filesys.js +74 -0
- package/dist/tools/memory.d.ts +3 -0
- package/dist/tools/memory.js +69 -0
- package/dist/tools/patch.d.ts +15 -0
- package/dist/tools/patch.js +129 -0
- package/dist/tools/registry.d.ts +10 -0
- package/dist/tools/registry.js +64 -0
- package/dist/tools/taskComplete.d.ts +2 -0
- package/dist/tools/taskComplete.js +19 -0
- package/dist/tools/terminal.d.ts +2 -0
- package/dist/tools/terminal.js +130 -0
- package/dist/tools/utils.d.ts +7 -0
- package/dist/tools/utils.js +63 -0
- package/dist/tools/web.d.ts +8 -0
- package/dist/tools/web.js +181 -0
- package/dist/utils/clipboard.d.ts +2 -0
- package/dist/utils/clipboard.js +40 -0
- package/dist/utils/lock.d.ts +12 -0
- package/dist/utils/lock.js +68 -0
- package/dist/utils/paths.d.ts +13 -0
- package/dist/utils/paths.js +58 -0
- package/dist/utils/projectContext.d.ts +2 -0
- package/dist/utils/projectContext.js +24 -0
- package/dist/utils/sacGuard.d.ts +4 -0
- package/dist/utils/sacGuard.js +47 -0
- package/dist/utils/sessions.d.ts +29 -0
- package/dist/utils/sessions.js +64 -0
- package/dist/utils/spinner.d.ts +10 -0
- package/dist/utils/spinner.js +32 -0
- package/package.json +106 -0
- package/src/gui/assets/image/AJAN_LOGO.svg +1 -0
- package/src/gui/assets/image/ajan.png +0 -0
- package/src/gui/assets/image/logo.svg +1 -0
- package/src/gui/assets/image/opencode.svg +18 -0
- package/src/gui/css/style.css +430 -0
- package/src/gui/html/chat.html +34 -0
- package/src/gui/html/downloads.html +11 -0
- package/src/gui/html/hakkinda.html +26 -0
- package/src/gui/html/index.html +82 -0
- package/src/gui/html/projects.html +12 -0
- package/src/gui/html/settings.html +4 -0
- package/src/gui/js/app.js +197 -0
- package/src/gui/js/chat.js +434 -0
- package/src/gui/js/downloads.js +172 -0
- package/src/gui/js/hakkinda.js +16 -0
- package/src/gui/js/projects.js +113 -0
- package/src/gui/js/settings.js +177 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/// <reference path="./ajan.d.ts" />
|
|
3
|
+
(function () {
|
|
4
|
+
"use strict";
|
|
5
|
+
if (!window.AjanInit)
|
|
6
|
+
window.AjanInit = {};
|
|
7
|
+
window.AjanInit.downloads = function (container) {
|
|
8
|
+
const ajan = window.ajan;
|
|
9
|
+
const modelsList = container.querySelector("#models-list");
|
|
10
|
+
const refreshBtn = container.querySelector("#btn-refresh-models");
|
|
11
|
+
let activeDownload = null;
|
|
12
|
+
function escapeHTML(str) {
|
|
13
|
+
return String(str).replace(/[&<>'"]/g, c => ({ "&": "&", "<": "<", ">": ">", "'": "'", '"': """ }[c] || c));
|
|
14
|
+
}
|
|
15
|
+
async function loadModels() {
|
|
16
|
+
if (!modelsList)
|
|
17
|
+
return;
|
|
18
|
+
if (!ajan?.listModels) {
|
|
19
|
+
modelsList.innerHTML = '<div class="empty-state"><div class="empty-state-text">Model API mevcut değil</div></div>';
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
const [models, modelInfo] = await Promise.all([
|
|
24
|
+
ajan.listModels(),
|
|
25
|
+
ajan.getModelInfo()
|
|
26
|
+
]);
|
|
27
|
+
if (!models || models.length === 0) {
|
|
28
|
+
modelsList.innerHTML = '<div class="empty-state"><div class="empty-state-icon">📦</div><div class="empty-state-text">Kayıtlı model yok</div></div>';
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
modelsList.innerHTML = "";
|
|
32
|
+
const activeId = modelInfo?.modelId;
|
|
33
|
+
for (const entry of models) {
|
|
34
|
+
const m = entry.model;
|
|
35
|
+
const card = document.createElement("div");
|
|
36
|
+
card.className = "model-card";
|
|
37
|
+
const statusClass = entry.installed ? (m.id === activeId ? "model-card-active" : "installed") : "missing";
|
|
38
|
+
const statusText = entry.installed ? (m.id === activeId ? "AKTİF" : "Kurulu") : "İndirilmemiş";
|
|
39
|
+
card.innerHTML = `
|
|
40
|
+
<div class="model-card-header">
|
|
41
|
+
<span class="model-card-name">${escapeHTML(m.name || m.id)}</span>
|
|
42
|
+
<span class="model-card-status ${statusClass}">${statusText}</span>
|
|
43
|
+
</div>
|
|
44
|
+
<div class="model-card-desc">${escapeHTML(m.description || "")}</div>
|
|
45
|
+
<div class="model-card-meta">
|
|
46
|
+
<span>${m.contextSize ? `Bağlam: ${typeof m.contextSize === 'number' ? (m.contextSize / 1024).toFixed(0) + 'K' : m.contextSize}` : ""}</span>
|
|
47
|
+
<span>${m.chatWrapper || ""}</span>
|
|
48
|
+
<span>${m.reasoning ? "Muhakeme" : ""}</span>
|
|
49
|
+
<span>${m.multimodal ? "Çoklu ortam" : ""}</span>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="model-download-progress" style="display:none"></div>
|
|
52
|
+
<div class="model-card-actions">
|
|
53
|
+
${entry.installed
|
|
54
|
+
? (m.id !== activeId
|
|
55
|
+
? `<button class="settings-btn-outline btn-use" data-id="${m.id}">Kullan</button>
|
|
56
|
+
<button class="settings-btn-danger btn-remove" data-id="${m.id}">Kaldır</button>`
|
|
57
|
+
: `<button class="settings-btn" disabled>Aktif</button>`)
|
|
58
|
+
: `<button class="settings-btn btn-install" data-id="${m.id}">İndir</button>`}
|
|
59
|
+
</div>
|
|
60
|
+
`;
|
|
61
|
+
modelsList.appendChild(card);
|
|
62
|
+
}
|
|
63
|
+
bindActions();
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
modelsList.innerHTML = `<div class="empty-state"><div class="empty-state-text">Hata: ${escapeHTML(err.message)}</div></div>`;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function bindActions() {
|
|
70
|
+
if (!modelsList)
|
|
71
|
+
return;
|
|
72
|
+
modelsList.querySelectorAll(".btn-install").forEach(btn => {
|
|
73
|
+
btn.addEventListener("click", async () => {
|
|
74
|
+
const card = btn.closest(".model-card");
|
|
75
|
+
const progressEl = card?.querySelector(".model-download-progress") ?? null;
|
|
76
|
+
activateDownload(btn, progressEl);
|
|
77
|
+
try {
|
|
78
|
+
await ajan.installModel(btn.dataset.id || "");
|
|
79
|
+
window.ajanToast?.("Model indirildi", "success");
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
window.ajanToast?.(`Hata: ${err.message}`, "error");
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
deactivateDownload(btn, progressEl);
|
|
86
|
+
loadModels();
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
modelsList.querySelectorAll(".btn-use").forEach(btn => {
|
|
91
|
+
btn.addEventListener("click", async () => {
|
|
92
|
+
try {
|
|
93
|
+
await ajan.useModel(btn.dataset.id || "");
|
|
94
|
+
window.ajanToast?.("Model seçildi", "success");
|
|
95
|
+
loadModels();
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
window.ajanToast?.(`Hata: ${err.message}`, "error");
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
modelsList.querySelectorAll(".btn-remove").forEach(btn => {
|
|
103
|
+
btn.addEventListener("click", async () => {
|
|
104
|
+
if (!confirm("Bu modeli silmek istediğinize emin misiniz?"))
|
|
105
|
+
return;
|
|
106
|
+
try {
|
|
107
|
+
await ajan.removeModel(btn.dataset.id || "");
|
|
108
|
+
window.ajanToast?.("Model silindi", "success");
|
|
109
|
+
loadModels();
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
window.ajanToast?.(`Hata: ${err.message}`, "error");
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function activateDownload(btn, progressEl) {
|
|
118
|
+
btn.disabled = true;
|
|
119
|
+
btn.textContent = "İndiriliyor...";
|
|
120
|
+
if (progressEl) {
|
|
121
|
+
progressEl.style.display = "block";
|
|
122
|
+
progressEl.innerHTML = `<div class="model-dl-bar"><div style="width:0%"></div></div><span>%0</span>`;
|
|
123
|
+
}
|
|
124
|
+
activeDownload = {
|
|
125
|
+
btn,
|
|
126
|
+
unsub: ajan.onLoadProgress ? ajan.onLoadProgress((pct) => {
|
|
127
|
+
if (activeDownload && progressEl) {
|
|
128
|
+
const bar = progressEl.querySelector(".model-dl-bar > div");
|
|
129
|
+
const label = progressEl.querySelector("span");
|
|
130
|
+
if (bar)
|
|
131
|
+
bar.style.width = `${pct}%`;
|
|
132
|
+
if (label)
|
|
133
|
+
label.textContent = `%${pct}`;
|
|
134
|
+
}
|
|
135
|
+
}) : () => { }
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function deactivateDownload(btn, progressEl) {
|
|
139
|
+
if (activeDownload?.unsub) {
|
|
140
|
+
try {
|
|
141
|
+
activeDownload.unsub();
|
|
142
|
+
}
|
|
143
|
+
catch { /* empty */ }
|
|
144
|
+
}
|
|
145
|
+
activeDownload = null;
|
|
146
|
+
if (progressEl)
|
|
147
|
+
progressEl.style.display = "none";
|
|
148
|
+
btn.disabled = false;
|
|
149
|
+
btn.textContent = "İndir";
|
|
150
|
+
}
|
|
151
|
+
refreshBtn?.addEventListener("click", async () => {
|
|
152
|
+
if (!ajan?.refreshModels)
|
|
153
|
+
return;
|
|
154
|
+
refreshBtn.disabled = true;
|
|
155
|
+
try {
|
|
156
|
+
const result = await ajan.refreshModels();
|
|
157
|
+
if (result.ok)
|
|
158
|
+
window.ajanToast?.("Model listesi güncellendi", "success");
|
|
159
|
+
else
|
|
160
|
+
window.ajanToast?.(`Hata: ${result.error}`, "error");
|
|
161
|
+
loadModels();
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
window.ajanToast?.(`Hata: ${err.message}`, "error");
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
refreshBtn.disabled = false;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
loadModels();
|
|
171
|
+
};
|
|
172
|
+
})();
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/// <reference path="./ajan.d.ts" />
|
|
3
|
+
(function () {
|
|
4
|
+
"use strict";
|
|
5
|
+
if (!window.AjanInit)
|
|
6
|
+
window.AjanInit = {};
|
|
7
|
+
window.AjanInit.hakkinda = function (container) {
|
|
8
|
+
const versionEl = container.querySelector("#about-version");
|
|
9
|
+
if (versionEl && window.ajan?.getVersion) {
|
|
10
|
+
window.ajan.getVersion().then(v => {
|
|
11
|
+
if (versionEl)
|
|
12
|
+
versionEl.textContent = `v${v}`;
|
|
13
|
+
}).catch(() => { });
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
})();
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/// <reference path="./ajan.d.ts" />
|
|
3
|
+
(function () {
|
|
4
|
+
"use strict";
|
|
5
|
+
if (!window.AjanInit)
|
|
6
|
+
window.AjanInit = {};
|
|
7
|
+
window.AjanInit.projects = function (container) {
|
|
8
|
+
const ajan = window.ajan;
|
|
9
|
+
const listEl = container.querySelector("#projects-list");
|
|
10
|
+
const addBtn = container.querySelector("#btn-add-project");
|
|
11
|
+
const refreshBtn = container.querySelector("#btn-refresh-projects");
|
|
12
|
+
function escapeHTML(str) {
|
|
13
|
+
return String(str).replace(/[&<>'"]/g, c => ({ "&": "&", "<": "<", ">": ">", "'": "'", '"': """ }[c] || c));
|
|
14
|
+
}
|
|
15
|
+
function baseName(path) {
|
|
16
|
+
const parts = String(path).split(/[\\/]/).filter(Boolean);
|
|
17
|
+
return parts[parts.length - 1] || path;
|
|
18
|
+
}
|
|
19
|
+
async function loadProjects() {
|
|
20
|
+
if (!listEl)
|
|
21
|
+
return;
|
|
22
|
+
if (!ajan?.listProjects) {
|
|
23
|
+
listEl.innerHTML = '<div class="empty-state"><div class="empty-state-text">Proje API mevcut değil</div></div>';
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const projects = await ajan.listProjects();
|
|
28
|
+
if (!projects || projects.length === 0) {
|
|
29
|
+
listEl.innerHTML = `
|
|
30
|
+
<div class="empty-state">
|
|
31
|
+
<div class="empty-state-icon">📁</div>
|
|
32
|
+
<div class="empty-state-text">Henüz proje yok<br><span style="font-size:0.85rem;color:#666">Yeni proje eklemek için butonu kullanın</span></div>
|
|
33
|
+
</div>`;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
listEl.innerHTML = "";
|
|
37
|
+
for (const p of projects) {
|
|
38
|
+
const card = document.createElement("div");
|
|
39
|
+
card.className = `project-card${p.active ? " project-card-active" : ""}`;
|
|
40
|
+
card.innerHTML = `
|
|
41
|
+
<div class="project-card-body">
|
|
42
|
+
<div class="project-card-icon">📂</div>
|
|
43
|
+
<div class="project-card-info">
|
|
44
|
+
<div class="project-card-path">${escapeHTML(p.path)}</div>
|
|
45
|
+
<div class="project-card-name">${escapeHTML(baseName(p.path))}</div>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="project-card-status">${p.active ? "AKTİF" : "Kayıtlı"}</div>
|
|
48
|
+
</div>
|
|
49
|
+
<div class="project-card-actions">
|
|
50
|
+
<button class="settings-btn btn-project-use" data-path="${escapeHTML(p.path)}" ${p.active ? "disabled" : ""}>${p.active ? "Aktif" : "Kullan"}</button>
|
|
51
|
+
<button class="settings-btn-danger btn-project-remove" data-path="${escapeHTML(p.path)}">Kaldır</button>
|
|
52
|
+
</div>`;
|
|
53
|
+
listEl.appendChild(card);
|
|
54
|
+
}
|
|
55
|
+
bindActions();
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
listEl.innerHTML = `<div class="empty-state"><div class="empty-state-text">Hata: ${escapeHTML(err.message)}</div></div>`;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function bindActions() {
|
|
62
|
+
if (!listEl)
|
|
63
|
+
return;
|
|
64
|
+
listEl.querySelectorAll(".btn-project-use").forEach(btn => {
|
|
65
|
+
btn.addEventListener("click", async () => {
|
|
66
|
+
try {
|
|
67
|
+
await ajan.setActiveProject(btn.dataset.path || "");
|
|
68
|
+
window.ajanToast?.("Aktif proje seçildi", "success");
|
|
69
|
+
loadProjects();
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
window.ajanToast?.(`Hata: ${err.message}`, "error");
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
listEl.querySelectorAll(".btn-project-remove").forEach(btn => {
|
|
77
|
+
btn.addEventListener("click", async () => {
|
|
78
|
+
if (!confirm(`Projeyi listeden kaldır: ${btn.dataset.path || ""}`))
|
|
79
|
+
return;
|
|
80
|
+
try {
|
|
81
|
+
await ajan.removeProject(btn.dataset.path || "");
|
|
82
|
+
window.ajanToast?.("Proje kaldırıldı", "success");
|
|
83
|
+
loadProjects();
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
window.ajanToast?.(`Hata: ${err.message}`, "error");
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
addBtn?.addEventListener("click", async () => {
|
|
92
|
+
if (!ajan?.pickDir)
|
|
93
|
+
return;
|
|
94
|
+
try {
|
|
95
|
+
const picked = await ajan.pickDir();
|
|
96
|
+
if (!picked)
|
|
97
|
+
return;
|
|
98
|
+
const result = await ajan.addProject(picked);
|
|
99
|
+
if (!result.ok) {
|
|
100
|
+
window.ajanToast?.(`Hata: ${result.error}`, "error");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
window.ajanToast?.("Proje eklendi", "success");
|
|
104
|
+
loadProjects();
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
window.ajanToast?.(`Hata: ${err.message}`, "error");
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
refreshBtn?.addEventListener("click", loadProjects);
|
|
111
|
+
loadProjects();
|
|
112
|
+
};
|
|
113
|
+
})();
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/// <reference path="./ajan.d.ts" />
|
|
3
|
+
(function () {
|
|
4
|
+
"use strict";
|
|
5
|
+
if (!window.AjanInit)
|
|
6
|
+
window.AjanInit = {};
|
|
7
|
+
window.AjanInit.settings = function (container) {
|
|
8
|
+
const ajan = window.ajan;
|
|
9
|
+
async function loadSettings() {
|
|
10
|
+
if (!ajan?.getConfig)
|
|
11
|
+
return;
|
|
12
|
+
try {
|
|
13
|
+
const config = await ajan.getConfig();
|
|
14
|
+
container.innerHTML = `
|
|
15
|
+
<div class="settings-page">
|
|
16
|
+
<div class="settings-title">Ayarlar</div>
|
|
17
|
+
|
|
18
|
+
<div class="settings-section">
|
|
19
|
+
<div class="settings-section-title">Model</div>
|
|
20
|
+
<div class="settings-row">
|
|
21
|
+
<div>
|
|
22
|
+
<div class="settings-label">Seçili Model</div>
|
|
23
|
+
<div class="settings-hint" id="current-model-id">${escapeHTML(String(config.modelId || ""))}</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<div class="settings-section">
|
|
29
|
+
<div class="settings-section-title">Oturum Parametreleri</div>
|
|
30
|
+
<div class="settings-row">
|
|
31
|
+
<div>
|
|
32
|
+
<div class="settings-label">Sıcaklık (Temperature)</div>
|
|
33
|
+
<div class="settings-hint">0-2 arası. Düşük = daha tutarlı, yüksek = daha yaratıcı</div>
|
|
34
|
+
</div>
|
|
35
|
+
<input type="number" class="settings-input" id="cfg-temperature"
|
|
36
|
+
value="${config.session?.temperature ?? 0.6}" min="0" max="2" step="0.1">
|
|
37
|
+
</div>
|
|
38
|
+
<div class="settings-row">
|
|
39
|
+
<div>
|
|
40
|
+
<div class="settings-label">Maksimum Token</div>
|
|
41
|
+
<div class="settings-hint">Yanıt başına maksimum token sayısı</div>
|
|
42
|
+
</div>
|
|
43
|
+
<input type="number" class="settings-input" id="cfg-maxTokens"
|
|
44
|
+
value="${config.session?.maxTokens ?? 8192}" min="256" max="131072" step="256">
|
|
45
|
+
</div>
|
|
46
|
+
<div class="settings-row">
|
|
47
|
+
<div>
|
|
48
|
+
<div class="settings-label">Maksimum Adım</div>
|
|
49
|
+
<div class="settings-hint">Otonom görev başına maks araç-adımı</div>
|
|
50
|
+
</div>
|
|
51
|
+
<input type="number" class="settings-input" id="cfg-maxSteps"
|
|
52
|
+
value="${config.maxSteps ?? 25}" min="1" max="200">
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<div class="settings-section">
|
|
57
|
+
<div class="settings-section-title">Sistem</div>
|
|
58
|
+
<div class="settings-row">
|
|
59
|
+
<div>
|
|
60
|
+
<div class="settings-label">GPU</div>
|
|
61
|
+
<div class="settings-hint">Otomatik tespit edilir</div>
|
|
62
|
+
</div>
|
|
63
|
+
<select class="settings-select" id="cfg-gpu">
|
|
64
|
+
<option value="auto" ${config.gpu === "auto" ? "selected" : ""}>Otomatik</option>
|
|
65
|
+
<option value="cuda" ${config.gpu === "cuda" ? "selected" : ""}>CUDA (NVIDIA)</option>
|
|
66
|
+
<option value="vulkan" ${config.gpu === "vulkan" ? "selected" : ""}>Vulkan</option>
|
|
67
|
+
<option value="metal" ${config.gpu === "metal" ? "selected" : ""}>Metal (Apple)</option>
|
|
68
|
+
</select>
|
|
69
|
+
</div>
|
|
70
|
+
<div class="settings-row">
|
|
71
|
+
<div>
|
|
72
|
+
<div class="settings-label">Görev Tamamlanınca Bip</div>
|
|
73
|
+
<div class="settings-hint">Otonom görev bitince sesli uyarı</div>
|
|
74
|
+
</div>
|
|
75
|
+
<select class="settings-select" id="cfg-beep">
|
|
76
|
+
<option value="true" ${config.beepOnComplete !== false ? "selected" : ""}>Açık</option>
|
|
77
|
+
<option value="false" ${config.beepOnComplete === false ? "selected" : ""}>Kapalı</option>
|
|
78
|
+
</select>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<div class="settings-section">
|
|
83
|
+
<div class="settings-section-title">Kısayol</div>
|
|
84
|
+
<div class="settings-row">
|
|
85
|
+
<div>
|
|
86
|
+
<div class="settings-label">Masaüstü ve Başlat Menüsü</div>
|
|
87
|
+
<div class="settings-hint">"AJAN AI" kısayolu oluşturur. Başlat Menüsü'ne ekleyerek Windows aramadan açabilirsiniz.</div>
|
|
88
|
+
</div>
|
|
89
|
+
<button class="settings-btn" id="btn-create-shortcut">Kısayol Oluştur</button>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<div class="settings-section">
|
|
94
|
+
<div class="settings-section-title">Sistem Bilgisi</div>
|
|
95
|
+
<div class="settings-row">
|
|
96
|
+
<div class="settings-label">Çalışma Dizini</div>
|
|
97
|
+
<div class="settings-hint" id="sys-cwd">Yükleniyor...</div>
|
|
98
|
+
</div>
|
|
99
|
+
<div class="settings-row">
|
|
100
|
+
<div class="settings-label">GPU</div>
|
|
101
|
+
<div class="settings-hint" id="sys-gpu">Yükleniyor...</div>
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
<div style="margin-top: 20px; display: flex; gap: 10px;">
|
|
106
|
+
<button class="settings-btn" id="btn-save-settings">Kaydet</button>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
`;
|
|
110
|
+
if (ajan.getCwd) {
|
|
111
|
+
ajan.getCwd().then(info => {
|
|
112
|
+
const el = document.getElementById("sys-cwd");
|
|
113
|
+
if (el)
|
|
114
|
+
el.textContent = info?.cwd || "-";
|
|
115
|
+
}).catch(() => { });
|
|
116
|
+
}
|
|
117
|
+
if (ajan.getGpuInfo) {
|
|
118
|
+
ajan.getGpuInfo().then(info => {
|
|
119
|
+
const el = document.getElementById("sys-gpu");
|
|
120
|
+
if (el)
|
|
121
|
+
el.textContent = info?.gpus?.join(", ") || "Yok (CPU)";
|
|
122
|
+
}).catch(() => { });
|
|
123
|
+
}
|
|
124
|
+
document.getElementById("btn-save-settings")?.addEventListener("click", async () => {
|
|
125
|
+
const num = (id, def) => (document.getElementById(id)?.value) || def;
|
|
126
|
+
const newConfig = {
|
|
127
|
+
maxSteps: parseInt(num("cfg-maxSteps", "25"), 10),
|
|
128
|
+
gpu: num("cfg-gpu", "auto"),
|
|
129
|
+
beepOnComplete: num("cfg-beep", "true") === "true",
|
|
130
|
+
session: {
|
|
131
|
+
temperature: parseFloat(num("cfg-temperature", "0.6")),
|
|
132
|
+
maxTokens: parseInt(num("cfg-maxTokens", "8192"), 10)
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
try {
|
|
136
|
+
await ajan.setConfig(newConfig);
|
|
137
|
+
window.ajanToast?.("Ayarlar kaydedildi", "success");
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
window.ajanToast?.(`Kaydetme hatası: ${err.message}`, "error");
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
document.getElementById("btn-create-shortcut")?.addEventListener("click", async () => {
|
|
144
|
+
const btn = document.getElementById("btn-create-shortcut");
|
|
145
|
+
if (!btn)
|
|
146
|
+
return;
|
|
147
|
+
btn.textContent = "Oluşturuluyor...";
|
|
148
|
+
btn.setAttribute("disabled", "true");
|
|
149
|
+
try {
|
|
150
|
+
const result = await ajan.createShortcut();
|
|
151
|
+
if (result?.ok) {
|
|
152
|
+
window.ajanToast?.("Kısayol oluşturuldu! Başlat Menüsü'nden 'AJAN AI' arayın.", "success");
|
|
153
|
+
btn.textContent = "Oluşturuldu";
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
window.ajanToast?.(`Hata: ${result?.error || "Bilinmeyen hata"}`, "error");
|
|
157
|
+
btn.textContent = "Kısayol Oluştur";
|
|
158
|
+
btn.removeAttribute("disabled");
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
window.ajanToast?.(`Hata: ${err.message}`, "error");
|
|
163
|
+
btn.textContent = "Kısayol Oluştur";
|
|
164
|
+
btn.removeAttribute("disabled");
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
container.innerHTML = `<div class="empty-state"><div class="empty-state-text">Ayarlar yüklenemedi: ${err.message}</div></div>`;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function escapeHTML(str) {
|
|
173
|
+
return String(str).replace(/[&<>'"]/g, c => ({ "&": "&", "<": "<", ">": ">", "'": "'", '"': """ }[c] || c));
|
|
174
|
+
}
|
|
175
|
+
loadSettings();
|
|
176
|
+
};
|
|
177
|
+
})();
|