teleton 0.8.1 → 0.8.3
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/bootstrap-DDFVEMYI.js +128 -0
- package/dist/{server-3FHI2SEB.js → chunk-2ERTYRHA.js} +26 -372
- package/dist/{chunk-5FNWBZ5K.js → chunk-33Z47EXI.js} +264 -274
- package/dist/{chunk-3S4GGLLR.js → chunk-35MX4ZUI.js} +23 -104
- package/dist/chunk-3UFPFWYP.js +12 -0
- package/dist/chunk-5SEMA47R.js +75 -0
- package/dist/{chunk-PHSAHTK4.js → chunk-6OOHHJ4N.js} +3 -108
- package/dist/{chunk-CGOXE4WP.js → chunk-7MWKT67G.js} +467 -914
- package/dist/chunk-AEHTQI3H.js +142 -0
- package/dist/{chunk-S6PHGKOC.js → chunk-AERHOXGC.js} +88 -322
- package/dist/chunk-ALKAAG4O.js +487 -0
- package/dist/{chunk-UP55PXFH.js → chunk-C4NKJT2Z.js} +8 -0
- package/dist/chunk-CUE4UZXR.js +129 -0
- package/dist/chunk-FUNF6H4W.js +251 -0
- package/dist/{chunk-7U7BOHCL.js → chunk-GHMXWAXI.js} +147 -63
- package/dist/{chunk-QBHRXLZS.js → chunk-H7MFXJZK.js} +2 -2
- package/dist/{chunk-QV2GLOTK.js → chunk-LC4TV3KL.js} +1 -1
- package/dist/{chunk-AYWEJCDB.js → chunk-LVTKJQ7O.js} +12 -10
- package/dist/{chunk-RCMD3U65.js → chunk-NQ6FZKCE.js} +13 -0
- package/dist/chunk-NVKBBTI6.js +128 -0
- package/dist/{setup-server-32XGDPE6.js → chunk-OIMAE24Q.js} +55 -216
- package/dist/{chunk-OJCLKU5Z.js → chunk-WFTC3JJW.js} +16 -0
- package/dist/chunk-WTDAICGT.js +175 -0
- package/dist/{chunk-KVXV7EF7.js → chunk-XDZDOKIF.js} +2 -2
- package/dist/cli/index.js +91 -27
- package/dist/{client-MPHPIZB6.js → client-5KD25NOP.js} +5 -4
- package/dist/{get-my-gifts-CC6HAVWB.js → get-my-gifts-Y7EN7RK4.js} +3 -3
- package/dist/index.js +19 -13
- package/dist/local-IHKJFQJS.js +9 -0
- package/dist/{memory-UBHM7ILG.js → memory-QMJRM3XJ.js} +9 -5
- package/dist/memory-hook-VUNWZ3NY.js +19 -0
- package/dist/{migrate-UBBEJ5BL.js → migrate-5VBAP52B.js} +5 -4
- package/dist/server-JF6FX772.js +813 -0
- package/dist/server-N4T7E25M.js +396 -0
- package/dist/setup-server-IX3BFPPH.js +217 -0
- package/dist/{store-M5IMUQCL.js → store-BY7S6IFN.js} +6 -5
- package/dist/{task-dependency-resolver-RR2O5S7B.js → task-dependency-resolver-L6UUMTHK.js} +2 -2
- package/dist/{task-executor-6W5HRX5C.js → task-executor-XBNJLUCS.js} +2 -2
- package/dist/{tool-adapter-IH5VGBOO.js → tool-adapter-IVX2XQJE.js} +1 -1
- package/dist/{tool-index-PMAOXWUA.js → tool-index-FTERJSZK.js} +4 -3
- package/dist/{transcript-NGDPSNIH.js → transcript-IM7G25OS.js} +2 -2
- package/package.json +4 -2
- package/dist/chunk-XBE4JB7C.js +0 -8
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentLifecycle
|
|
3
|
+
} from "./chunk-NVKBBTI6.js";
|
|
4
|
+
import {
|
|
5
|
+
configExists,
|
|
6
|
+
getDefaultConfigPath
|
|
7
|
+
} from "./chunk-AEHTQI3H.js";
|
|
8
|
+
import {
|
|
9
|
+
ensureWorkspace
|
|
10
|
+
} from "./chunk-AERHOXGC.js";
|
|
11
|
+
import "./chunk-C4NKJT2Z.js";
|
|
12
|
+
import "./chunk-6OOHHJ4N.js";
|
|
13
|
+
import {
|
|
14
|
+
SHUTDOWN_TIMEOUT_MS
|
|
15
|
+
} from "./chunk-R4YSJ4EY.js";
|
|
16
|
+
import "./chunk-EYWNOHMJ.js";
|
|
17
|
+
import {
|
|
18
|
+
createLogger
|
|
19
|
+
} from "./chunk-NQ6FZKCE.js";
|
|
20
|
+
import "./chunk-3RG5ZIWI.js";
|
|
21
|
+
|
|
22
|
+
// src/api/bootstrap.ts
|
|
23
|
+
var log = createLogger("Bootstrap");
|
|
24
|
+
async function startApiOnly(options) {
|
|
25
|
+
await ensureWorkspace({ ensureTemplates: false, silent: false });
|
|
26
|
+
const configPath = options.config ?? getDefaultConfigPath();
|
|
27
|
+
const lifecycle = new AgentLifecycle();
|
|
28
|
+
const deps = {
|
|
29
|
+
agent: null,
|
|
30
|
+
bridge: null,
|
|
31
|
+
memory: null,
|
|
32
|
+
toolRegistry: null,
|
|
33
|
+
plugins: null,
|
|
34
|
+
mcpServers: null,
|
|
35
|
+
config: {
|
|
36
|
+
enabled: false,
|
|
37
|
+
port: 7777,
|
|
38
|
+
host: "127.0.0.1",
|
|
39
|
+
cors_origins: [],
|
|
40
|
+
log_requests: false
|
|
41
|
+
},
|
|
42
|
+
configPath,
|
|
43
|
+
lifecycle,
|
|
44
|
+
marketplace: null,
|
|
45
|
+
userHookEvaluator: null
|
|
46
|
+
};
|
|
47
|
+
const { ApiServer } = await import("./server-JF6FX772.js");
|
|
48
|
+
const apiConfig = {
|
|
49
|
+
enabled: true,
|
|
50
|
+
port: parseInt(options.apiPort || process.env.TELETON_API_PORT || "7778"),
|
|
51
|
+
key_hash: "",
|
|
52
|
+
allowed_ips: []
|
|
53
|
+
};
|
|
54
|
+
const server = new ApiServer(deps, apiConfig);
|
|
55
|
+
let appInstance = null;
|
|
56
|
+
lifecycle.registerCallbacks(
|
|
57
|
+
// startFn — called when POST /v1/agent/start fires
|
|
58
|
+
async () => {
|
|
59
|
+
if (!configExists(configPath)) {
|
|
60
|
+
throw new Error("Configuration not found. Complete setup via /v1/setup endpoints first.");
|
|
61
|
+
}
|
|
62
|
+
const { TeletonApp } = await import("./index.js");
|
|
63
|
+
appInstance = new TeletonApp(configPath);
|
|
64
|
+
await appInstance.startAgentSubsystems();
|
|
65
|
+
server.updateDeps({
|
|
66
|
+
agent: appInstance.getAgent(),
|
|
67
|
+
bridge: appInstance.getBridge(),
|
|
68
|
+
memory: appInstance.getMemory(),
|
|
69
|
+
toolRegistry: appInstance.getToolRegistry(),
|
|
70
|
+
plugins: appInstance.getPlugins(),
|
|
71
|
+
config: appInstance.getWebuiConfig()
|
|
72
|
+
});
|
|
73
|
+
},
|
|
74
|
+
// stopFn — called when POST /v1/agent/stop fires
|
|
75
|
+
async () => {
|
|
76
|
+
if (appInstance) {
|
|
77
|
+
await appInstance.stopAgentSubsystems();
|
|
78
|
+
appInstance = null;
|
|
79
|
+
server.updateDeps({
|
|
80
|
+
agent: null,
|
|
81
|
+
bridge: null,
|
|
82
|
+
memory: null,
|
|
83
|
+
toolRegistry: null,
|
|
84
|
+
plugins: null
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
await server.start();
|
|
90
|
+
if (process.env.TELETON_JSON_CREDENTIALS === "true") {
|
|
91
|
+
const creds = server.getCredentials();
|
|
92
|
+
process.stdout.write(JSON.stringify(creds) + "\n");
|
|
93
|
+
}
|
|
94
|
+
log.info("API-only mode: complete setup via /v1/setup endpoints, then POST /v1/agent/start");
|
|
95
|
+
let shutdownInProgress = false;
|
|
96
|
+
const gracefulShutdown = async () => {
|
|
97
|
+
if (shutdownInProgress) return;
|
|
98
|
+
shutdownInProgress = true;
|
|
99
|
+
const forceExit = setTimeout(() => {
|
|
100
|
+
log.error("Shutdown timed out, forcing exit");
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}, SHUTDOWN_TIMEOUT_MS);
|
|
103
|
+
forceExit.unref();
|
|
104
|
+
try {
|
|
105
|
+
if (lifecycle.getState() === "running") {
|
|
106
|
+
await lifecycle.stop();
|
|
107
|
+
}
|
|
108
|
+
await server.stop();
|
|
109
|
+
} finally {
|
|
110
|
+
clearTimeout(forceExit);
|
|
111
|
+
process.exit(0);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
process.on("SIGINT", gracefulShutdown);
|
|
115
|
+
process.on("SIGTERM", gracefulShutdown);
|
|
116
|
+
process.on("unhandledRejection", (reason) => {
|
|
117
|
+
log.error({ err: reason }, "Unhandled rejection");
|
|
118
|
+
});
|
|
119
|
+
process.on("uncaughtException", (error) => {
|
|
120
|
+
log.error({ err: error }, "Uncaught exception");
|
|
121
|
+
process.exit(1);
|
|
122
|
+
});
|
|
123
|
+
await new Promise(() => {
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
export {
|
|
127
|
+
startApiOnly
|
|
128
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getModelsForProvider
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-WFTC3JJW.js";
|
|
4
4
|
import {
|
|
5
5
|
CONFIGURABLE_KEYS,
|
|
6
6
|
TonProxyManager,
|
|
@@ -30,31 +30,22 @@ import {
|
|
|
30
30
|
validateWritePath,
|
|
31
31
|
writePluginSecret,
|
|
32
32
|
writeRawConfig
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-7MWKT67G.js";
|
|
34
34
|
import {
|
|
35
35
|
invalidateEndpointCache,
|
|
36
36
|
invalidateTonClientCache,
|
|
37
37
|
setToncenterApiKey
|
|
38
|
-
} from "./chunk-
|
|
39
|
-
import "./chunk-KVXV7EF7.js";
|
|
40
|
-
import "./chunk-7TECSLJ4.js";
|
|
38
|
+
} from "./chunk-FUNF6H4W.js";
|
|
41
39
|
import {
|
|
42
40
|
getErrorMessage
|
|
43
|
-
} from "./chunk-
|
|
44
|
-
import "./chunk-AYWEJCDB.js";
|
|
45
|
-
import {
|
|
46
|
-
getProviderMetadata,
|
|
47
|
-
validateApiKeyFormat
|
|
48
|
-
} from "./chunk-PHSAHTK4.js";
|
|
49
|
-
import "./chunk-QV2GLOTK.js";
|
|
50
|
-
import "./chunk-7U7BOHCL.js";
|
|
51
|
-
import "./chunk-3S4GGLLR.js";
|
|
41
|
+
} from "./chunk-3UFPFWYP.js";
|
|
52
42
|
import {
|
|
53
43
|
setTonapiKey
|
|
54
44
|
} from "./chunk-VFA7QMCZ.js";
|
|
55
|
-
import
|
|
56
|
-
|
|
57
|
-
|
|
45
|
+
import {
|
|
46
|
+
getProviderMetadata,
|
|
47
|
+
validateApiKeyFormat
|
|
48
|
+
} from "./chunk-6OOHHJ4N.js";
|
|
58
49
|
import {
|
|
59
50
|
WORKSPACE_PATHS,
|
|
60
51
|
WORKSPACE_ROOT
|
|
@@ -63,41 +54,10 @@ import {
|
|
|
63
54
|
addLogListener,
|
|
64
55
|
clearLogListeners,
|
|
65
56
|
createLogger
|
|
66
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-NQ6FZKCE.js";
|
|
67
58
|
import {
|
|
68
59
|
getTaskStore
|
|
69
60
|
} from "./chunk-4L66JHQE.js";
|
|
70
|
-
import "./chunk-3RG5ZIWI.js";
|
|
71
|
-
|
|
72
|
-
// src/webui/server.ts
|
|
73
|
-
import { Hono as Hono14 } from "hono";
|
|
74
|
-
import { serve } from "@hono/node-server";
|
|
75
|
-
import { cors } from "hono/cors";
|
|
76
|
-
import { streamSSE as streamSSE2 } from "hono/streaming";
|
|
77
|
-
import { bodyLimit } from "hono/body-limit";
|
|
78
|
-
import { setCookie, getCookie, deleteCookie } from "hono/cookie";
|
|
79
|
-
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
80
|
-
import { join as join4, dirname, resolve as resolve2, relative as relative2 } from "path";
|
|
81
|
-
import { fileURLToPath } from "url";
|
|
82
|
-
|
|
83
|
-
// src/webui/middleware/auth.ts
|
|
84
|
-
import { randomBytes, timingSafeEqual } from "crypto";
|
|
85
|
-
var COOKIE_NAME = "teleton_session";
|
|
86
|
-
var COOKIE_MAX_AGE = 7 * 24 * 60 * 60;
|
|
87
|
-
function generateToken() {
|
|
88
|
-
return randomBytes(32).toString("base64url");
|
|
89
|
-
}
|
|
90
|
-
function maskToken(token) {
|
|
91
|
-
if (token.length < 12) return "****";
|
|
92
|
-
return `${token.slice(0, 4)}...${token.slice(-4)}`;
|
|
93
|
-
}
|
|
94
|
-
function safeCompare(a, b) {
|
|
95
|
-
if (!a || !b) return false;
|
|
96
|
-
const bufA = Buffer.from(a);
|
|
97
|
-
const bufB = Buffer.from(b);
|
|
98
|
-
if (bufA.length !== bufB.length) return false;
|
|
99
|
-
return timingSafeEqual(bufA, bufB);
|
|
100
|
-
}
|
|
101
61
|
|
|
102
62
|
// src/webui/log-interceptor.ts
|
|
103
63
|
var LogInterceptor = class {
|
|
@@ -444,9 +404,9 @@ function createLogsRoutes(_deps) {
|
|
|
444
404
|
}),
|
|
445
405
|
event: "log"
|
|
446
406
|
});
|
|
447
|
-
await new Promise((
|
|
448
|
-
if (aborted) return
|
|
449
|
-
stream.onAbort(() =>
|
|
407
|
+
await new Promise((resolve2) => {
|
|
408
|
+
if (aborted) return resolve2();
|
|
409
|
+
stream.onAbort(() => resolve2());
|
|
450
410
|
});
|
|
451
411
|
if (cleanup) cleanup();
|
|
452
412
|
});
|
|
@@ -2310,325 +2270,19 @@ function createTonProxyRoutes(deps) {
|
|
|
2310
2270
|
return app;
|
|
2311
2271
|
}
|
|
2312
2272
|
|
|
2313
|
-
// src/webui/server.ts
|
|
2314
|
-
var log3 = createLogger("WebUI");
|
|
2315
|
-
function findWebDist() {
|
|
2316
|
-
const candidates = [
|
|
2317
|
-
resolve2("dist/web"),
|
|
2318
|
-
// npm start / teleton start (from project root)
|
|
2319
|
-
resolve2("web")
|
|
2320
|
-
// fallback
|
|
2321
|
-
];
|
|
2322
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
2323
|
-
candidates.push(
|
|
2324
|
-
resolve2(__dirname, "web"),
|
|
2325
|
-
// dist/web when __dirname = dist/
|
|
2326
|
-
resolve2(__dirname, "../dist/web")
|
|
2327
|
-
// when running with tsx from src/
|
|
2328
|
-
);
|
|
2329
|
-
for (const candidate of candidates) {
|
|
2330
|
-
if (existsSync3(join4(candidate, "index.html"))) {
|
|
2331
|
-
return candidate;
|
|
2332
|
-
}
|
|
2333
|
-
}
|
|
2334
|
-
return null;
|
|
2335
|
-
}
|
|
2336
|
-
var WebUIServer = class {
|
|
2337
|
-
app;
|
|
2338
|
-
server = null;
|
|
2339
|
-
deps;
|
|
2340
|
-
authToken;
|
|
2341
|
-
constructor(deps) {
|
|
2342
|
-
this.deps = deps;
|
|
2343
|
-
this.app = new Hono14();
|
|
2344
|
-
this.authToken = deps.config.auth_token || generateToken();
|
|
2345
|
-
this.setupMiddleware();
|
|
2346
|
-
this.setupRoutes();
|
|
2347
|
-
}
|
|
2348
|
-
/** Set an HttpOnly session cookie */
|
|
2349
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Hono context type
|
|
2350
|
-
setSessionCookie(c) {
|
|
2351
|
-
setCookie(c, COOKIE_NAME, this.authToken, {
|
|
2352
|
-
path: "/",
|
|
2353
|
-
httpOnly: true,
|
|
2354
|
-
sameSite: "Strict",
|
|
2355
|
-
secure: false,
|
|
2356
|
-
// localhost is HTTP
|
|
2357
|
-
maxAge: COOKIE_MAX_AGE
|
|
2358
|
-
});
|
|
2359
|
-
}
|
|
2360
|
-
setupMiddleware() {
|
|
2361
|
-
this.app.use(
|
|
2362
|
-
"*",
|
|
2363
|
-
cors({
|
|
2364
|
-
origin: this.deps.config.cors_origins,
|
|
2365
|
-
credentials: true,
|
|
2366
|
-
allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH"],
|
|
2367
|
-
allowHeaders: ["Content-Type", "Authorization"],
|
|
2368
|
-
maxAge: 3600
|
|
2369
|
-
})
|
|
2370
|
-
);
|
|
2371
|
-
if (this.deps.config.log_requests) {
|
|
2372
|
-
this.app.use("*", async (c, next) => {
|
|
2373
|
-
const start = Date.now();
|
|
2374
|
-
await next();
|
|
2375
|
-
const duration = Date.now() - start;
|
|
2376
|
-
log3.info(`${c.req.method} ${c.req.path} \u2192 ${c.res.status} (${duration}ms)`);
|
|
2377
|
-
});
|
|
2378
|
-
}
|
|
2379
|
-
this.app.use(
|
|
2380
|
-
"*",
|
|
2381
|
-
bodyLimit({
|
|
2382
|
-
maxSize: 2 * 1024 * 1024,
|
|
2383
|
-
// 2MB
|
|
2384
|
-
onError: (c) => c.json({ success: false, error: "Request body too large (max 2MB)" }, 413)
|
|
2385
|
-
})
|
|
2386
|
-
);
|
|
2387
|
-
this.app.use("*", async (c, next) => {
|
|
2388
|
-
await next();
|
|
2389
|
-
c.res.headers.set("X-Content-Type-Options", "nosniff");
|
|
2390
|
-
c.res.headers.set("X-Frame-Options", "DENY");
|
|
2391
|
-
c.res.headers.set("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
2392
|
-
});
|
|
2393
|
-
this.app.use("/api/*", async (c, next) => {
|
|
2394
|
-
const cookieToken = getCookie(c, COOKIE_NAME);
|
|
2395
|
-
if (cookieToken && safeCompare(cookieToken, this.authToken)) {
|
|
2396
|
-
return next();
|
|
2397
|
-
}
|
|
2398
|
-
const authHeader = c.req.header("Authorization");
|
|
2399
|
-
if (authHeader) {
|
|
2400
|
-
const match = authHeader.match(/^Bearer\s+(.+)$/i);
|
|
2401
|
-
if (match && safeCompare(match[1], this.authToken)) {
|
|
2402
|
-
return next();
|
|
2403
|
-
}
|
|
2404
|
-
}
|
|
2405
|
-
const queryToken = c.req.query("token");
|
|
2406
|
-
if (queryToken && safeCompare(queryToken, this.authToken)) {
|
|
2407
|
-
return next();
|
|
2408
|
-
}
|
|
2409
|
-
return c.json({ success: false, error: "Unauthorized" }, 401);
|
|
2410
|
-
});
|
|
2411
|
-
}
|
|
2412
|
-
setupRoutes() {
|
|
2413
|
-
this.app.get("/health", (c) => c.json({ status: "ok" }));
|
|
2414
|
-
this.app.get("/auth/exchange", (c) => {
|
|
2415
|
-
const token = c.req.query("token");
|
|
2416
|
-
if (!token || !safeCompare(token, this.authToken)) {
|
|
2417
|
-
return c.json({ success: false, error: "Invalid token" }, 401);
|
|
2418
|
-
}
|
|
2419
|
-
this.setSessionCookie(c);
|
|
2420
|
-
return c.redirect("/");
|
|
2421
|
-
});
|
|
2422
|
-
this.app.post("/auth/login", async (c) => {
|
|
2423
|
-
try {
|
|
2424
|
-
const body = await c.req.json();
|
|
2425
|
-
if (!body.token || !safeCompare(body.token, this.authToken)) {
|
|
2426
|
-
return c.json({ success: false, error: "Invalid token" }, 401);
|
|
2427
|
-
}
|
|
2428
|
-
this.setSessionCookie(c);
|
|
2429
|
-
return c.json({ success: true });
|
|
2430
|
-
} catch {
|
|
2431
|
-
return c.json({ success: false, error: "Invalid request body" }, 400);
|
|
2432
|
-
}
|
|
2433
|
-
});
|
|
2434
|
-
this.app.post("/auth/logout", (c) => {
|
|
2435
|
-
deleteCookie(c, COOKIE_NAME, { path: "/" });
|
|
2436
|
-
return c.json({ success: true });
|
|
2437
|
-
});
|
|
2438
|
-
this.app.get("/auth/check", (c) => {
|
|
2439
|
-
const cookieToken = getCookie(c, COOKIE_NAME);
|
|
2440
|
-
const authenticated = !!(cookieToken && safeCompare(cookieToken, this.authToken));
|
|
2441
|
-
return c.json({ success: true, data: { authenticated } });
|
|
2442
|
-
});
|
|
2443
|
-
this.app.route("/api/status", createStatusRoutes(this.deps));
|
|
2444
|
-
this.app.route("/api/tools", createToolsRoutes(this.deps));
|
|
2445
|
-
this.app.route("/api/logs", createLogsRoutes(this.deps));
|
|
2446
|
-
this.app.route("/api/memory", createMemoryRoutes(this.deps));
|
|
2447
|
-
this.app.route("/api/soul", createSoulRoutes(this.deps));
|
|
2448
|
-
this.app.route("/api/plugins", createPluginsRoutes(this.deps));
|
|
2449
|
-
this.app.route("/api/mcp", createMcpRoutes(this.deps));
|
|
2450
|
-
this.app.route("/api/workspace", createWorkspaceRoutes(this.deps));
|
|
2451
|
-
this.app.route("/api/tasks", createTasksRoutes(this.deps));
|
|
2452
|
-
this.app.route("/api/config", createConfigRoutes(this.deps));
|
|
2453
|
-
this.app.route("/api/marketplace", createMarketplaceRoutes(this.deps));
|
|
2454
|
-
this.app.route("/api/hooks", createHooksRoutes(this.deps));
|
|
2455
|
-
this.app.route("/api/ton-proxy", createTonProxyRoutes(this.deps));
|
|
2456
|
-
this.app.post("/api/agent/start", async (c) => {
|
|
2457
|
-
const lifecycle = this.deps.lifecycle;
|
|
2458
|
-
if (!lifecycle) {
|
|
2459
|
-
return c.json({ error: "Agent lifecycle not available" }, 503);
|
|
2460
|
-
}
|
|
2461
|
-
const state = lifecycle.getState();
|
|
2462
|
-
if (state === "running") {
|
|
2463
|
-
return c.json({ state: "running" }, 409);
|
|
2464
|
-
}
|
|
2465
|
-
if (state === "stopping") {
|
|
2466
|
-
return c.json({ error: "Agent is currently stopping, please wait" }, 409);
|
|
2467
|
-
}
|
|
2468
|
-
lifecycle.start().catch((err) => {
|
|
2469
|
-
log3.error({ err }, "Agent start failed");
|
|
2470
|
-
});
|
|
2471
|
-
return c.json({ state: "starting" });
|
|
2472
|
-
});
|
|
2473
|
-
this.app.post("/api/agent/stop", async (c) => {
|
|
2474
|
-
const lifecycle = this.deps.lifecycle;
|
|
2475
|
-
if (!lifecycle) {
|
|
2476
|
-
return c.json({ error: "Agent lifecycle not available" }, 503);
|
|
2477
|
-
}
|
|
2478
|
-
const state = lifecycle.getState();
|
|
2479
|
-
if (state === "stopped") {
|
|
2480
|
-
return c.json({ state: "stopped" }, 409);
|
|
2481
|
-
}
|
|
2482
|
-
if (state === "starting") {
|
|
2483
|
-
return c.json({ error: "Agent is currently starting, please wait" }, 409);
|
|
2484
|
-
}
|
|
2485
|
-
lifecycle.stop().catch((err) => {
|
|
2486
|
-
log3.error({ err }, "Agent stop failed");
|
|
2487
|
-
});
|
|
2488
|
-
return c.json({ state: "stopping" });
|
|
2489
|
-
});
|
|
2490
|
-
this.app.get("/api/agent/status", (c) => {
|
|
2491
|
-
const lifecycle = this.deps.lifecycle;
|
|
2492
|
-
if (!lifecycle) {
|
|
2493
|
-
return c.json({ error: "Agent lifecycle not available" }, 503);
|
|
2494
|
-
}
|
|
2495
|
-
return c.json({
|
|
2496
|
-
state: lifecycle.getState(),
|
|
2497
|
-
uptime: lifecycle.getUptime(),
|
|
2498
|
-
error: lifecycle.getError() ?? null
|
|
2499
|
-
});
|
|
2500
|
-
});
|
|
2501
|
-
this.app.get("/api/agent/events", (c) => {
|
|
2502
|
-
const lifecycle = this.deps.lifecycle;
|
|
2503
|
-
if (!lifecycle) {
|
|
2504
|
-
return c.json({ error: "Agent lifecycle not available" }, 503);
|
|
2505
|
-
}
|
|
2506
|
-
return streamSSE2(c, async (stream) => {
|
|
2507
|
-
let aborted = false;
|
|
2508
|
-
stream.onAbort(() => {
|
|
2509
|
-
aborted = true;
|
|
2510
|
-
});
|
|
2511
|
-
const now = Date.now();
|
|
2512
|
-
await stream.writeSSE({
|
|
2513
|
-
event: "status",
|
|
2514
|
-
id: String(now),
|
|
2515
|
-
data: JSON.stringify({
|
|
2516
|
-
state: lifecycle.getState(),
|
|
2517
|
-
error: lifecycle.getError() ?? null,
|
|
2518
|
-
timestamp: now
|
|
2519
|
-
}),
|
|
2520
|
-
retry: 3e3
|
|
2521
|
-
});
|
|
2522
|
-
const onStateChange = (event) => {
|
|
2523
|
-
if (aborted) return;
|
|
2524
|
-
void stream.writeSSE({
|
|
2525
|
-
event: "status",
|
|
2526
|
-
id: String(event.timestamp),
|
|
2527
|
-
data: JSON.stringify({
|
|
2528
|
-
state: event.state,
|
|
2529
|
-
error: event.error ?? null,
|
|
2530
|
-
timestamp: event.timestamp
|
|
2531
|
-
})
|
|
2532
|
-
});
|
|
2533
|
-
};
|
|
2534
|
-
lifecycle.on("stateChange", onStateChange);
|
|
2535
|
-
while (!aborted) {
|
|
2536
|
-
await stream.sleep(3e4);
|
|
2537
|
-
if (aborted) break;
|
|
2538
|
-
await stream.writeSSE({
|
|
2539
|
-
event: "ping",
|
|
2540
|
-
data: ""
|
|
2541
|
-
});
|
|
2542
|
-
}
|
|
2543
|
-
lifecycle.off("stateChange", onStateChange);
|
|
2544
|
-
});
|
|
2545
|
-
});
|
|
2546
|
-
const webDist = findWebDist();
|
|
2547
|
-
if (webDist) {
|
|
2548
|
-
const indexHtml = readFileSync3(join4(webDist, "index.html"), "utf-8");
|
|
2549
|
-
const mimeTypes = {
|
|
2550
|
-
js: "application/javascript",
|
|
2551
|
-
css: "text/css",
|
|
2552
|
-
svg: "image/svg+xml",
|
|
2553
|
-
png: "image/png",
|
|
2554
|
-
jpg: "image/jpeg",
|
|
2555
|
-
jpeg: "image/jpeg",
|
|
2556
|
-
ico: "image/x-icon",
|
|
2557
|
-
json: "application/json",
|
|
2558
|
-
woff2: "font/woff2",
|
|
2559
|
-
woff: "font/woff"
|
|
2560
|
-
};
|
|
2561
|
-
this.app.get("*", (c) => {
|
|
2562
|
-
const filePath = resolve2(join4(webDist, c.req.path));
|
|
2563
|
-
const rel = relative2(webDist, filePath);
|
|
2564
|
-
if (rel.startsWith("..") || resolve2(filePath) !== filePath) {
|
|
2565
|
-
return c.html(indexHtml);
|
|
2566
|
-
}
|
|
2567
|
-
try {
|
|
2568
|
-
const content = readFileSync3(filePath);
|
|
2569
|
-
const ext = filePath.split(".").pop() || "";
|
|
2570
|
-
if (mimeTypes[ext]) {
|
|
2571
|
-
const immutable = c.req.path.startsWith("/assets/");
|
|
2572
|
-
return c.body(content, 200, {
|
|
2573
|
-
"Content-Type": mimeTypes[ext],
|
|
2574
|
-
"Cache-Control": immutable ? "public, max-age=31536000, immutable" : "public, max-age=3600"
|
|
2575
|
-
});
|
|
2576
|
-
}
|
|
2577
|
-
} catch {
|
|
2578
|
-
}
|
|
2579
|
-
return c.html(indexHtml);
|
|
2580
|
-
});
|
|
2581
|
-
}
|
|
2582
|
-
this.app.onError((err, c) => {
|
|
2583
|
-
log3.error({ err }, "WebUI error");
|
|
2584
|
-
return c.json(
|
|
2585
|
-
{
|
|
2586
|
-
success: false,
|
|
2587
|
-
error: err.message || "Internal server error"
|
|
2588
|
-
},
|
|
2589
|
-
500
|
|
2590
|
-
);
|
|
2591
|
-
});
|
|
2592
|
-
}
|
|
2593
|
-
async start() {
|
|
2594
|
-
return new Promise((resolve3, reject) => {
|
|
2595
|
-
try {
|
|
2596
|
-
logInterceptor.install();
|
|
2597
|
-
this.server = serve(
|
|
2598
|
-
{
|
|
2599
|
-
fetch: this.app.fetch,
|
|
2600
|
-
hostname: this.deps.config.host,
|
|
2601
|
-
port: this.deps.config.port
|
|
2602
|
-
},
|
|
2603
|
-
(info) => {
|
|
2604
|
-
const url = `http://${info.address}:${info.port}`;
|
|
2605
|
-
log3.info(`WebUI server running`);
|
|
2606
|
-
log3.info(`URL: ${url}/auth/exchange?token=${this.authToken}`);
|
|
2607
|
-
log3.info(`Token: ${maskToken(this.authToken)} (use Bearer header for API access)`);
|
|
2608
|
-
resolve3();
|
|
2609
|
-
}
|
|
2610
|
-
);
|
|
2611
|
-
} catch (error) {
|
|
2612
|
-
logInterceptor.uninstall();
|
|
2613
|
-
reject(error);
|
|
2614
|
-
}
|
|
2615
|
-
});
|
|
2616
|
-
}
|
|
2617
|
-
async stop() {
|
|
2618
|
-
if (this.server) {
|
|
2619
|
-
return new Promise((resolve3) => {
|
|
2620
|
-
this.server?.close(() => {
|
|
2621
|
-
logInterceptor.uninstall();
|
|
2622
|
-
log3.info("WebUI server stopped");
|
|
2623
|
-
resolve3();
|
|
2624
|
-
});
|
|
2625
|
-
});
|
|
2626
|
-
}
|
|
2627
|
-
}
|
|
2628
|
-
getToken() {
|
|
2629
|
-
return this.authToken;
|
|
2630
|
-
}
|
|
2631
|
-
};
|
|
2632
2273
|
export {
|
|
2633
|
-
|
|
2274
|
+
logInterceptor,
|
|
2275
|
+
createStatusRoutes,
|
|
2276
|
+
createToolsRoutes,
|
|
2277
|
+
createLogsRoutes,
|
|
2278
|
+
createMemoryRoutes,
|
|
2279
|
+
createSoulRoutes,
|
|
2280
|
+
createPluginsRoutes,
|
|
2281
|
+
createMcpRoutes,
|
|
2282
|
+
createWorkspaceRoutes,
|
|
2283
|
+
createTasksRoutes,
|
|
2284
|
+
createConfigRoutes,
|
|
2285
|
+
createMarketplaceRoutes,
|
|
2286
|
+
createHooksRoutes,
|
|
2287
|
+
createTonProxyRoutes
|
|
2634
2288
|
};
|