atabey-mcp 0.0.19 → 0.0.21
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/README.md +2 -2
- package/dist/atabey/src/cli/platforms/core.d.ts +4 -0
- package/dist/atabey/src/cli/platforms/core.js +12 -8
- package/dist/atabey/src/cli/platforms/core.js.map +1 -1
- package/dist/atabey/src/cli/platforms/index.d.ts +1 -1
- package/dist/atabey/src/cli/platforms/index.js +1 -1
- package/dist/atabey/src/cli/platforms/index.js.map +1 -1
- package/dist/atabey/src/cli/utils/memory.d.ts +13 -7
- package/dist/atabey/src/cli/utils/memory.js +48 -16
- package/dist/atabey/src/cli/utils/memory.js.map +1 -1
- package/dist/atabey/src/modules/engines/agent-loop.d.ts +34 -0
- package/dist/atabey/src/modules/engines/agent-loop.js +102 -0
- package/dist/atabey/src/modules/engines/agent-loop.js.map +1 -0
- package/dist/atabey-mcp/src/mcp/constants.d.ts +3 -45
- package/dist/atabey-mcp/src/mcp/constants.js +3 -62
- package/dist/atabey-mcp/src/mcp/constants.js.map +1 -1
- package/dist/atabey-mcp/src/mcp/index.js +19 -35
- package/dist/atabey-mcp/src/mcp/index.js.map +1 -1
- package/dist/atabey-mcp/src/mcp/routes/api-agents.d.ts +3 -0
- package/dist/atabey-mcp/src/mcp/routes/api-agents.js +97 -0
- package/dist/atabey-mcp/src/mcp/routes/api-agents.js.map +1 -0
- package/dist/atabey-mcp/src/mcp/routes/api-common.d.ts +3 -0
- package/dist/atabey-mcp/src/mcp/routes/api-common.js +63 -0
- package/dist/atabey-mcp/src/mcp/routes/api-common.js.map +1 -0
- package/dist/atabey-mcp/src/mcp/routes/api-config.d.ts +3 -0
- package/dist/atabey-mcp/src/mcp/routes/api-config.js +639 -0
- package/dist/atabey-mcp/src/mcp/routes/api-config.js.map +1 -0
- package/dist/atabey-mcp/src/mcp/routes/api-governance.d.ts +3 -0
- package/dist/atabey-mcp/src/mcp/routes/api-governance.js +271 -0
- package/dist/atabey-mcp/src/mcp/routes/api-governance.js.map +1 -0
- package/dist/atabey-mcp/src/mcp/routes/api-orchestrator.d.ts +3 -0
- package/dist/atabey-mcp/src/mcp/routes/api-orchestrator.js +145 -0
- package/dist/atabey-mcp/src/mcp/routes/api-orchestrator.js.map +1 -0
- package/dist/atabey-mcp/src/mcp/routes/api-workspace.d.ts +3 -0
- package/dist/atabey-mcp/src/mcp/routes/api-workspace.js +274 -0
- package/dist/atabey-mcp/src/mcp/routes/api-workspace.js.map +1 -0
- package/dist/atabey-mcp/src/mcp/routes/index.d.ts +2 -0
- package/dist/atabey-mcp/src/mcp/routes/index.js +18 -1436
- package/dist/atabey-mcp/src/mcp/routes/index.js.map +1 -1
- package/dist/atabey-mcp/src/mcp/routes/types.d.ts +18 -0
- package/dist/atabey-mcp/src/mcp/routes/types.js +23 -0
- package/dist/atabey-mcp/src/mcp/routes/types.js.map +1 -0
- package/dist/atabey-mcp/src/mcp/tools/framework/orchestrate.d.ts +1 -1
- package/dist/atabey-mcp/src/mcp/tools/framework/orchestrate.js +11 -4
- package/dist/atabey-mcp/src/mcp/tools/framework/orchestrate.js.map +1 -1
- package/dist/atabey-mcp/src/mcp/utils/client-config.js +1 -1
- package/dist/atabey-mcp/src/mcp/utils/client-config.js.map +1 -1
- package/dist/atabey-mcp/src/mcp/utils/compliance-bootstrap.d.ts +8 -0
- package/dist/atabey-mcp/src/mcp/utils/compliance-bootstrap.js +46 -0
- package/dist/atabey-mcp/src/mcp/utils/compliance-bootstrap.js.map +1 -0
- package/dist/atabey-mcp/src/mcp/utils/consent.d.ts +25 -0
- package/dist/atabey-mcp/src/mcp/utils/consent.js +60 -0
- package/dist/atabey-mcp/src/mcp/utils/consent.js.map +1 -0
- package/dist/atabey-mcp/src/mcp/utils/finops.d.ts +7 -11
- package/dist/atabey-mcp/src/mcp/utils/finops.js +24 -26
- package/dist/atabey-mcp/src/mcp/utils/finops.js.map +1 -1
- package/dist/atabey-mcp/src/mcp/utils/framework-config.d.ts +27 -0
- package/dist/atabey-mcp/src/mcp/utils/framework-config.js +81 -0
- package/dist/atabey-mcp/src/mcp/utils/framework-config.js.map +1 -0
- package/dist/atabey-mcp/src/mcp/utils/orchestrator-bootstrap.d.ts +14 -0
- package/dist/atabey-mcp/src/mcp/utils/orchestrator-bootstrap.js +98 -0
- package/dist/atabey-mcp/src/mcp/utils/orchestrator-bootstrap.js.map +1 -0
- package/dist/atabey-mcp/src/mcp/utils/web-config.js +17 -35
- package/dist/atabey-mcp/src/mcp/utils/web-config.js.map +1 -1
- package/dist/dashboard/assets/{index-DHuA2rua.js → index-BUUxi_j8.js} +75 -75
- package/dist/dashboard/index.html +1 -1
- package/dist/shared/src/constants.d.ts +30 -1
- package/dist/shared/src/constants.js +25 -2
- package/dist/shared/src/constants.js.map +1 -1
- package/package.json +13 -2
|
@@ -0,0 +1,639 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { serveJson } from "./types.js";
|
|
3
|
+
import { Storage } from "../../shared/storage.js";
|
|
4
|
+
import { logger } from "../../shared/logger.js";
|
|
5
|
+
export async function handleConfigRoutes(pathname, params, method, req, res, context) {
|
|
6
|
+
// Knowledge Base List
|
|
7
|
+
if (pathname === "/api/knowledge" && req.method === "GET") {
|
|
8
|
+
try {
|
|
9
|
+
const list = Storage.getKnowledgeList();
|
|
10
|
+
serveJson(res, 200, { success: true, data: list });
|
|
11
|
+
}
|
|
12
|
+
catch (e) {
|
|
13
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
14
|
+
}
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
// Knowledge View
|
|
18
|
+
if (pathname === "/api/knowledge/view" && req.method === "GET") {
|
|
19
|
+
try {
|
|
20
|
+
const file = params.file;
|
|
21
|
+
if (!file) {
|
|
22
|
+
serveJson(res, 400, { success: false, error: "Missing 'file' parameter" });
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
const doc = Storage.getKnowledgeFile(file);
|
|
26
|
+
if (!doc) {
|
|
27
|
+
serveJson(res, 404, { success: false, error: "File not found" });
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
serveJson(res, 200, { success: true, data: doc });
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
// Knowledge Update
|
|
38
|
+
if (pathname === "/api/knowledge/update" && req.method === "POST") {
|
|
39
|
+
try {
|
|
40
|
+
let body = "";
|
|
41
|
+
req.on("data", chunk => { body += chunk.toString(); });
|
|
42
|
+
req.on("end", async () => {
|
|
43
|
+
try {
|
|
44
|
+
const parsed = JSON.parse(body);
|
|
45
|
+
const file = parsed.file;
|
|
46
|
+
const content = parsed.content;
|
|
47
|
+
if (!file || content === undefined) {
|
|
48
|
+
serveJson(res, 400, { success: false, error: "Missing 'file' or 'content' in request body" });
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
let safeFile = path.basename(file);
|
|
52
|
+
if (!safeFile.endsWith(".md")) {
|
|
53
|
+
safeFile += ".md";
|
|
54
|
+
}
|
|
55
|
+
Storage.saveKnowledgeFile(safeFile, content);
|
|
56
|
+
serveJson(res, 200, { success: true, message: `Knowledge document '${safeFile}' updated successfully.` });
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
serveJson(res, 400, { success: false, error: err.message });
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
// Knowledge Delete
|
|
69
|
+
if (pathname === "/api/knowledge/delete" && req.method === "POST") {
|
|
70
|
+
try {
|
|
71
|
+
let body = "";
|
|
72
|
+
req.on("data", chunk => { body += chunk.toString(); });
|
|
73
|
+
req.on("end", async () => {
|
|
74
|
+
try {
|
|
75
|
+
const parsed = JSON.parse(body);
|
|
76
|
+
const file = parsed.file;
|
|
77
|
+
if (!file) {
|
|
78
|
+
serveJson(res, 400, { success: false, error: "Missing 'file' in request body" });
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const safeFile = path.basename(file);
|
|
82
|
+
Storage.deleteKnowledgeFile(safeFile);
|
|
83
|
+
serveJson(res, 200, { success: true, message: `Knowledge document '${safeFile}' deleted.` });
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
serveJson(res, 400, { success: false, error: err.message });
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
catch (e) {
|
|
91
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
92
|
+
}
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
// Constitution List
|
|
96
|
+
if (pathname === "/api/constitution" && req.method === "GET") {
|
|
97
|
+
try {
|
|
98
|
+
const db = Storage.getDB();
|
|
99
|
+
const sections = db.prepare("SELECT * FROM constitution ORDER BY priority DESC").all();
|
|
100
|
+
serveJson(res, 200, { success: true, data: sections });
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
104
|
+
}
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
// Constitution Update
|
|
108
|
+
if (pathname === "/api/constitution/update" && req.method === "POST") {
|
|
109
|
+
try {
|
|
110
|
+
let body = "";
|
|
111
|
+
req.on("data", chunk => { body += chunk.toString(); });
|
|
112
|
+
req.on("end", async () => {
|
|
113
|
+
try {
|
|
114
|
+
const parsed = JSON.parse(body);
|
|
115
|
+
const { section, title, content } = parsed;
|
|
116
|
+
if (!section || !content) {
|
|
117
|
+
serveJson(res, 400, { success: false, error: "Missing 'section' or 'content'" });
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const db = Storage.getDB();
|
|
121
|
+
db.prepare(`
|
|
122
|
+
INSERT INTO constitution (section, title, content, updated_at)
|
|
123
|
+
VALUES (?, ?, ?, ?)
|
|
124
|
+
ON CONFLICT(section) DO UPDATE SET
|
|
125
|
+
title = excluded.title,
|
|
126
|
+
content = excluded.content,
|
|
127
|
+
updated_at = excluded.updated_at
|
|
128
|
+
`).run(section, title || "", content, new Date().toISOString());
|
|
129
|
+
serveJson(res, 200, { success: true, message: `Section '${section}' updated.` });
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
serveJson(res, 400, { success: false, error: err.message });
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
138
|
+
}
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
// CLI Commands
|
|
142
|
+
if (pathname === "/api/cli-commands" && req.method === "GET") {
|
|
143
|
+
try {
|
|
144
|
+
const db = Storage.getDB();
|
|
145
|
+
const commands = db.prepare("SELECT * FROM cli_commands ORDER BY command").all();
|
|
146
|
+
serveJson(res, 200, { success: true, data: commands });
|
|
147
|
+
}
|
|
148
|
+
catch (e) {
|
|
149
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
150
|
+
}
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
// Prompts List
|
|
154
|
+
if (pathname === "/api/prompts" && req.method === "GET") {
|
|
155
|
+
try {
|
|
156
|
+
const db = Storage.getDB();
|
|
157
|
+
const prompts = db.prepare("SELECT * FROM prompts ORDER BY category, name").all();
|
|
158
|
+
serveJson(res, 200, { success: true, data: prompts });
|
|
159
|
+
}
|
|
160
|
+
catch (e) {
|
|
161
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
162
|
+
}
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
// Prompts Update
|
|
166
|
+
if (pathname === "/api/prompts/update" && req.method === "POST") {
|
|
167
|
+
try {
|
|
168
|
+
let body = "";
|
|
169
|
+
req.on("data", chunk => { body += chunk.toString(); });
|
|
170
|
+
req.on("end", async () => {
|
|
171
|
+
try {
|
|
172
|
+
const parsed = JSON.parse(body);
|
|
173
|
+
const { name, category, content } = parsed;
|
|
174
|
+
if (!name || !content) {
|
|
175
|
+
serveJson(res, 400, { success: false, error: "Missing 'name' or 'content'" });
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const db = Storage.getDB();
|
|
179
|
+
db.prepare(`
|
|
180
|
+
INSERT INTO prompts (name, category, content, updated_at)
|
|
181
|
+
VALUES (?, ?, ?, ?)
|
|
182
|
+
ON CONFLICT(name) DO UPDATE SET
|
|
183
|
+
category = excluded.category,
|
|
184
|
+
content = excluded.content,
|
|
185
|
+
updated_at = excluded.updated_at
|
|
186
|
+
`).run(name, category || "general", content, new Date().toISOString());
|
|
187
|
+
serveJson(res, 200, { success: true, message: `Prompt '${name}' updated.` });
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
serveJson(res, 400, { success: false, error: err.message });
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
catch (e) {
|
|
195
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
196
|
+
}
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
// Rules List
|
|
200
|
+
if (pathname === "/api/rules" && req.method === "GET") {
|
|
201
|
+
try {
|
|
202
|
+
const db = Storage.getDB();
|
|
203
|
+
const rules = db.prepare("SELECT * FROM rules ORDER BY name").all();
|
|
204
|
+
serveJson(res, 200, { success: true, data: rules });
|
|
205
|
+
}
|
|
206
|
+
catch (e) {
|
|
207
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
208
|
+
}
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
// Rules Update
|
|
212
|
+
if (pathname === "/api/rules/update" && req.method === "POST") {
|
|
213
|
+
try {
|
|
214
|
+
let body = "";
|
|
215
|
+
req.on("data", chunk => { body += chunk.toString(); });
|
|
216
|
+
req.on("end", async () => {
|
|
217
|
+
try {
|
|
218
|
+
const parsed = JSON.parse(body);
|
|
219
|
+
const { name, content, enabled } = parsed;
|
|
220
|
+
if (!name) {
|
|
221
|
+
serveJson(res, 400, { success: false, error: "Missing 'name'" });
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const db = Storage.getDB();
|
|
225
|
+
db.prepare(`
|
|
226
|
+
INSERT INTO rules (name, content, enabled, updated_at)
|
|
227
|
+
VALUES (?, ?, ?, ?)
|
|
228
|
+
ON CONFLICT(name) DO UPDATE SET
|
|
229
|
+
content = excluded.content,
|
|
230
|
+
enabled = excluded.enabled,
|
|
231
|
+
updated_at = excluded.updated_at
|
|
232
|
+
`).run(name, content || "", enabled !== undefined ? (enabled ? 1 : 0) : 1, new Date().toISOString());
|
|
233
|
+
serveJson(res, 200, { success: true, message: `Rule '${name}' updated.` });
|
|
234
|
+
}
|
|
235
|
+
catch (err) {
|
|
236
|
+
serveJson(res, 400, { success: false, error: err.message });
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
catch (e) {
|
|
241
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
242
|
+
}
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
// Registry List
|
|
246
|
+
if (pathname === "/api/registry" && req.method === "GET") {
|
|
247
|
+
try {
|
|
248
|
+
const db = Storage.getDB();
|
|
249
|
+
const items = db.prepare("SELECT * FROM registry ORDER BY type, name").all();
|
|
250
|
+
serveJson(res, 200, { success: true, data: items });
|
|
251
|
+
}
|
|
252
|
+
catch (e) {
|
|
253
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
254
|
+
}
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
257
|
+
// Registry Update
|
|
258
|
+
if (pathname === "/api/registry/update" && req.method === "POST") {
|
|
259
|
+
try {
|
|
260
|
+
let body = "";
|
|
261
|
+
req.on("data", chunk => { body += chunk.toString(); });
|
|
262
|
+
req.on("end", async () => {
|
|
263
|
+
try {
|
|
264
|
+
const parsed = JSON.parse(body);
|
|
265
|
+
const { name, type, data } = parsed;
|
|
266
|
+
if (!name) {
|
|
267
|
+
serveJson(res, 400, { success: false, error: "Missing 'name'" });
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const db = Storage.getDB();
|
|
271
|
+
db.prepare(`
|
|
272
|
+
INSERT INTO registry (name, type, data, updated_at)
|
|
273
|
+
VALUES (?, ?, ?, ?)
|
|
274
|
+
ON CONFLICT(name) DO UPDATE SET
|
|
275
|
+
type = excluded.type,
|
|
276
|
+
data = excluded.data,
|
|
277
|
+
updated_at = excluded.updated_at
|
|
278
|
+
`).run(name, type || "agent", data || "{}", new Date().toISOString());
|
|
279
|
+
serveJson(res, 200, { success: true, message: `Registry '${name}' updated.` });
|
|
280
|
+
}
|
|
281
|
+
catch (err) {
|
|
282
|
+
serveJson(res, 400, { success: false, error: err.message });
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
catch (e) {
|
|
287
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
288
|
+
}
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
// Settings (Config settings - legacy)
|
|
292
|
+
if (pathname === "/api/settings" && req.method === "GET" && !params.legacy_check) {
|
|
293
|
+
// Wait, index.ts has two distinct "/api/settings" GET/POST blocks.
|
|
294
|
+
// One is in lines 728-751 (projectPath & activeProvider from Storage)
|
|
295
|
+
// One is in lines 1061-1100 (loadWebConfig from web-config.js)
|
|
296
|
+
// Let's check which one matches what.
|
|
297
|
+
// The one in lines 1061 loads safe config with keys. Let's merge them!
|
|
298
|
+
// Actually, let's keep both, but we can differentiate them by headers/body, or just keep them as they were.
|
|
299
|
+
// Let's implement the first one if it doesn't match the second one.
|
|
300
|
+
// Actually, the second one uses `loadWebConfig` which is preferred for dashboard UI configuration.
|
|
301
|
+
// Let's merge them: if it's GET, we return the settings loaded from webConfig and from metadata.
|
|
302
|
+
}
|
|
303
|
+
// Let's check settings routes specifically:
|
|
304
|
+
// GET Settings (Combined load)
|
|
305
|
+
if (pathname === "/api/settings" && req.method === "GET") {
|
|
306
|
+
try {
|
|
307
|
+
const { loadWebConfig } = await import("../utils/web-config.js");
|
|
308
|
+
const config = loadWebConfig();
|
|
309
|
+
const projectPath = config.projectPath || Storage.getMetadata("projectPath") || "";
|
|
310
|
+
const activeProvider = config.activeProvider || Storage.getMetadata("activeProvider") || "gemini";
|
|
311
|
+
const safeConfig = {
|
|
312
|
+
projectPath,
|
|
313
|
+
activeProvider,
|
|
314
|
+
geminiApiKey: config.geminiApiKey ? "********" : "",
|
|
315
|
+
anthropicApiKey: config.anthropicApiKey ? "********" : "",
|
|
316
|
+
openaiApiKey: config.openaiApiKey ? "********" : "",
|
|
317
|
+
};
|
|
318
|
+
serveJson(res, 200, { success: true, data: safeConfig });
|
|
319
|
+
}
|
|
320
|
+
catch (e) {
|
|
321
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
322
|
+
}
|
|
323
|
+
return true;
|
|
324
|
+
}
|
|
325
|
+
// POST Settings (Save)
|
|
326
|
+
if (pathname === "/api/settings" && req.method === "POST") {
|
|
327
|
+
try {
|
|
328
|
+
let body = "";
|
|
329
|
+
req.on("data", chunk => { body += chunk.toString(); });
|
|
330
|
+
req.on("end", async () => {
|
|
331
|
+
try {
|
|
332
|
+
const parsed = JSON.parse(body);
|
|
333
|
+
// Metadata storage
|
|
334
|
+
if (parsed.projectPath !== undefined)
|
|
335
|
+
Storage.setMetadata("projectPath", parsed.projectPath);
|
|
336
|
+
if (parsed.activeProvider !== undefined)
|
|
337
|
+
Storage.setMetadata("activeProvider", parsed.activeProvider);
|
|
338
|
+
// Config file storage
|
|
339
|
+
const { saveWebConfig } = await import("../utils/web-config.js");
|
|
340
|
+
const configToSave = {};
|
|
341
|
+
if (parsed.projectPath)
|
|
342
|
+
configToSave.projectPath = parsed.projectPath;
|
|
343
|
+
if (parsed.activeProvider)
|
|
344
|
+
configToSave.activeProvider = parsed.activeProvider;
|
|
345
|
+
if (parsed.geminiApiKey && parsed.geminiApiKey !== "********")
|
|
346
|
+
configToSave.geminiApiKey = parsed.geminiApiKey;
|
|
347
|
+
if (parsed.anthropicApiKey && parsed.anthropicApiKey !== "********")
|
|
348
|
+
configToSave.anthropicApiKey = parsed.anthropicApiKey;
|
|
349
|
+
if (parsed.openaiApiKey && parsed.openaiApiKey !== "********")
|
|
350
|
+
configToSave.openaiApiKey = parsed.openaiApiKey;
|
|
351
|
+
const saved = saveWebConfig(configToSave);
|
|
352
|
+
serveJson(res, 200, { success: true, message: "Settings saved successfully", projectPath: saved.projectPath });
|
|
353
|
+
}
|
|
354
|
+
catch (err) {
|
|
355
|
+
serveJson(res, 400, { success: false, error: err.message });
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
catch (e) {
|
|
360
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
361
|
+
}
|
|
362
|
+
return true;
|
|
363
|
+
}
|
|
364
|
+
// Config metadata GET
|
|
365
|
+
if (pathname === "/api/config" && req.method === "GET") {
|
|
366
|
+
try {
|
|
367
|
+
const db = Storage.getDB();
|
|
368
|
+
const configs = db.prepare("SELECT * FROM metadata WHERE key LIKE 'config.%'").all();
|
|
369
|
+
const config = {};
|
|
370
|
+
for (const c of configs) {
|
|
371
|
+
config[c.key.replace("config.", "")] = c.value;
|
|
372
|
+
}
|
|
373
|
+
serveJson(res, 200, { success: true, data: config });
|
|
374
|
+
}
|
|
375
|
+
catch (e) {
|
|
376
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
377
|
+
}
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
380
|
+
// Adapter Skills summary
|
|
381
|
+
if (pathname === "/api/adapters/skills") {
|
|
382
|
+
try {
|
|
383
|
+
const { ADAPTER_SKILLS } = await import("atabey/src/modules/skills/adapter-skills.js");
|
|
384
|
+
const summary = Object.entries(ADAPTER_SKILLS).map(([id, config]) => ({
|
|
385
|
+
id, skillCount: Object.keys(config.enabledSkills).length,
|
|
386
|
+
toolsCount: config.toolMapping ? Object.keys(config.toolMapping).length : 0,
|
|
387
|
+
skills: Object.entries(config.enabledSkills).map(([skId, skVal]) => ({
|
|
388
|
+
id: skId,
|
|
389
|
+
name: skVal.name,
|
|
390
|
+
disabled: !!skVal.disabled
|
|
391
|
+
})),
|
|
392
|
+
}));
|
|
393
|
+
serveJson(res, 200, { success: true, data: summary });
|
|
394
|
+
}
|
|
395
|
+
catch (e) {
|
|
396
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
397
|
+
}
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
// Adapter Skill Toggle
|
|
401
|
+
if (pathname === "/api/adapters/skills/toggle" && method === "POST") {
|
|
402
|
+
try {
|
|
403
|
+
let body = "";
|
|
404
|
+
req.on("data", chunk => { body += chunk.toString(); });
|
|
405
|
+
req.on("end", async () => {
|
|
406
|
+
try {
|
|
407
|
+
const parsed = JSON.parse(body);
|
|
408
|
+
const { adapterId, skillId } = parsed;
|
|
409
|
+
if (!adapterId || !skillId) {
|
|
410
|
+
serveJson(res, 400, { success: false, error: "Missing adapterId or skillId" });
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
const { ADAPTER_SKILLS } = await import("atabey/src/modules/skills/adapter-skills.js");
|
|
414
|
+
const adapter = ADAPTER_SKILLS[adapterId];
|
|
415
|
+
if (!adapter || !adapter.enabledSkills[skillId]) {
|
|
416
|
+
serveJson(res, 404, { success: false, error: "Adapter or skill not found" });
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
const skill = adapter.enabledSkills[skillId];
|
|
420
|
+
skill.disabled = !skill.disabled;
|
|
421
|
+
serveJson(res, 200, { success: true, disabled: !!skill.disabled });
|
|
422
|
+
}
|
|
423
|
+
catch (err) {
|
|
424
|
+
serveJson(res, 400, { success: false, error: err.message });
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
catch (e) {
|
|
429
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
430
|
+
}
|
|
431
|
+
return true;
|
|
432
|
+
}
|
|
433
|
+
// Auth Login
|
|
434
|
+
if (pathname === "/api/auth/login" && req.method === "POST") {
|
|
435
|
+
try {
|
|
436
|
+
let body = "";
|
|
437
|
+
req.on("data", chunk => { body += chunk.toString(); });
|
|
438
|
+
req.on("end", async () => {
|
|
439
|
+
try {
|
|
440
|
+
const parsed = JSON.parse(body);
|
|
441
|
+
const { username, token } = parsed;
|
|
442
|
+
if (!username || !token) {
|
|
443
|
+
serveJson(res, 400, { success: false, error: "Username and token are required" });
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
const maskedToken = token.length > 8 ? `${token.slice(0, 4)}...${token.slice(-4)}` : "***";
|
|
447
|
+
logger.info(`[LOGIN ATTEMPT] username="${username}", token="${maskedToken}"`);
|
|
448
|
+
const { authenticateToken } = await import("../utils/auth.js");
|
|
449
|
+
const result = authenticateToken(token);
|
|
450
|
+
logger.info(`[LOGIN RESULT] authenticated=${result.authenticated}, user="${result.user}"`);
|
|
451
|
+
if (result.authenticated && (result.user === username || (result.user === "admin" && username === "admin"))) {
|
|
452
|
+
serveJson(res, 200, { success: true, user: { name: username, role: result.user === "admin" ? "admin" : "user" } });
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
serveJson(res, 401, { success: false, error: "Invalid username or token" });
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
catch (err) {
|
|
459
|
+
logger.error(`[LOGIN ERROR] ${err.message}`);
|
|
460
|
+
serveJson(res, 400, { success: false, error: err.message });
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
catch (e) {
|
|
465
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
466
|
+
}
|
|
467
|
+
return true;
|
|
468
|
+
}
|
|
469
|
+
// GET Admin Users
|
|
470
|
+
if (pathname === "/api/admin/users" && req.method === "GET") {
|
|
471
|
+
try {
|
|
472
|
+
const users = Storage.getUsers();
|
|
473
|
+
serveJson(res, 200, { success: true, data: users });
|
|
474
|
+
}
|
|
475
|
+
catch (e) {
|
|
476
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
477
|
+
}
|
|
478
|
+
return true;
|
|
479
|
+
}
|
|
480
|
+
// POST Create/Update Admin User
|
|
481
|
+
if (pathname === "/api/admin/users/create" && req.method === "POST") {
|
|
482
|
+
try {
|
|
483
|
+
let body = "";
|
|
484
|
+
req.on("data", chunk => { body += chunk.toString(); });
|
|
485
|
+
req.on("end", async () => {
|
|
486
|
+
try {
|
|
487
|
+
const parsed = JSON.parse(body);
|
|
488
|
+
const { name, token, role } = parsed;
|
|
489
|
+
if (!name || !token) {
|
|
490
|
+
serveJson(res, 400, { success: false, error: "Username and token are required" });
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
Storage.createUser(name.trim(), token.trim(), role || "user");
|
|
494
|
+
serveJson(res, 200, { success: true, message: `User ${name} created/updated successfully.` });
|
|
495
|
+
}
|
|
496
|
+
catch (err) {
|
|
497
|
+
serveJson(res, 400, { success: false, error: err.message });
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
catch (e) {
|
|
502
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
503
|
+
}
|
|
504
|
+
return true;
|
|
505
|
+
}
|
|
506
|
+
// POST Delete Admin User
|
|
507
|
+
if (pathname === "/api/admin/users/delete" && req.method === "POST") {
|
|
508
|
+
try {
|
|
509
|
+
let body = "";
|
|
510
|
+
req.on("data", chunk => { body += chunk.toString(); });
|
|
511
|
+
req.on("end", async () => {
|
|
512
|
+
try {
|
|
513
|
+
const parsed = JSON.parse(body);
|
|
514
|
+
const { name } = parsed;
|
|
515
|
+
if (!name) {
|
|
516
|
+
serveJson(res, 400, { success: false, error: "Username is required" });
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
Storage.deleteUser(name);
|
|
520
|
+
serveJson(res, 200, { success: true, message: `User ${name} deleted.` });
|
|
521
|
+
}
|
|
522
|
+
catch (err) {
|
|
523
|
+
serveJson(res, 400, { success: false, error: err.message });
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
catch (e) {
|
|
528
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
529
|
+
}
|
|
530
|
+
return true;
|
|
531
|
+
}
|
|
532
|
+
// Orchestrator Status
|
|
533
|
+
if (pathname === "/api/orchestrator/status" && method === "GET") {
|
|
534
|
+
try {
|
|
535
|
+
const { getOrchestratorState } = await import("../utils/web-config.js");
|
|
536
|
+
serveJson(res, 200, { success: true, data: getOrchestratorState() });
|
|
537
|
+
}
|
|
538
|
+
catch (e) {
|
|
539
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
540
|
+
}
|
|
541
|
+
return true;
|
|
542
|
+
}
|
|
543
|
+
// Orchestrator Start
|
|
544
|
+
if (pathname === "/api/orchestrator/start" && method === "POST") {
|
|
545
|
+
try {
|
|
546
|
+
const { startOrchestratorLoop } = await import("../utils/web-config.js");
|
|
547
|
+
const result = startOrchestratorLoop();
|
|
548
|
+
if (result.success) {
|
|
549
|
+
context.broadcastWS("orchestrator_state", { running: true });
|
|
550
|
+
serveJson(res, 200, { success: true, message: result.message });
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
serveJson(res, 400, { success: false, error: result.message });
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
catch (e) {
|
|
557
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
558
|
+
}
|
|
559
|
+
return true;
|
|
560
|
+
}
|
|
561
|
+
// Orchestrator Stop
|
|
562
|
+
if (pathname === "/api/orchestrator/stop" && method === "POST") {
|
|
563
|
+
try {
|
|
564
|
+
const { stopOrchestratorLoop } = await import("../utils/web-config.js");
|
|
565
|
+
const result = stopOrchestratorLoop();
|
|
566
|
+
if (result.success) {
|
|
567
|
+
context.broadcastWS("orchestrator_state", { running: false });
|
|
568
|
+
serveJson(res, 200, { success: true, message: result.message });
|
|
569
|
+
}
|
|
570
|
+
else {
|
|
571
|
+
serveJson(res, 400, { success: false, error: result.message });
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
catch (e) {
|
|
575
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
576
|
+
}
|
|
577
|
+
return true;
|
|
578
|
+
}
|
|
579
|
+
// GET Token Budget Config
|
|
580
|
+
if (pathname === "/api/token-budget/config" && method === "GET") {
|
|
581
|
+
try {
|
|
582
|
+
const { getTokenBudgetConfig } = await import("../utils/context-optimizer.js");
|
|
583
|
+
const config = getTokenBudgetConfig();
|
|
584
|
+
serveJson(res, 200, { success: true, data: config });
|
|
585
|
+
}
|
|
586
|
+
catch (e) {
|
|
587
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
588
|
+
}
|
|
589
|
+
return true;
|
|
590
|
+
}
|
|
591
|
+
// UPDATE Token Budget Config
|
|
592
|
+
if (pathname === "/api/token-budget/config/update" && method === "POST") {
|
|
593
|
+
try {
|
|
594
|
+
let body = "";
|
|
595
|
+
req.on("data", chunk => { body += chunk.toString(); });
|
|
596
|
+
req.on("end", async () => {
|
|
597
|
+
try {
|
|
598
|
+
const parsed = JSON.parse(body);
|
|
599
|
+
const { updateTokenBudgetConfig } = await import("../utils/context-optimizer.js");
|
|
600
|
+
updateTokenBudgetConfig(parsed);
|
|
601
|
+
serveJson(res, 200, { success: true, message: "Token budget configuration updated successfully." });
|
|
602
|
+
}
|
|
603
|
+
catch (err) {
|
|
604
|
+
serveJson(res, 400, { success: false, error: err.message });
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
catch (e) {
|
|
609
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
610
|
+
}
|
|
611
|
+
return true;
|
|
612
|
+
}
|
|
613
|
+
// RESET Agent Token Budgets
|
|
614
|
+
if (pathname === "/api/token-budget/reset" && method === "POST") {
|
|
615
|
+
try {
|
|
616
|
+
const { resetTokenBudgets } = await import("../utils/context-optimizer.js");
|
|
617
|
+
resetTokenBudgets();
|
|
618
|
+
serveJson(res, 200, { success: true, message: "All agent token budgets reset successfully." });
|
|
619
|
+
}
|
|
620
|
+
catch (e) {
|
|
621
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
622
|
+
}
|
|
623
|
+
return true;
|
|
624
|
+
}
|
|
625
|
+
// Telemetry Status
|
|
626
|
+
if (pathname === "/api/telemetry") {
|
|
627
|
+
try {
|
|
628
|
+
const { telemetryStreamer, TelemetryConfig } = await import("../utils/telemetry-streamer.js");
|
|
629
|
+
const status = telemetryStreamer.getStatus();
|
|
630
|
+
serveJson(res, 200, { success: true, data: { ...status, config: { ...TelemetryConfig, AUTH_TOKEN: TelemetryConfig.AUTH_TOKEN ? "***" : "" } } });
|
|
631
|
+
}
|
|
632
|
+
catch (e) {
|
|
633
|
+
serveJson(res, 500, { success: false, error: e.message });
|
|
634
|
+
}
|
|
635
|
+
return true;
|
|
636
|
+
}
|
|
637
|
+
return false;
|
|
638
|
+
}
|
|
639
|
+
//# sourceMappingURL=api-config.js.map
|