teleton 0.8.1 → 0.8.2
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/{chunk-5FNWBZ5K.js → chunk-2IZU3REP.js} +147 -82
- package/dist/chunk-3UFPFWYP.js +12 -0
- package/dist/{chunk-KVXV7EF7.js → chunk-55SKE6YH.js} +2 -2
- package/dist/{setup-server-32XGDPE6.js → chunk-57URFK6M.js} +7 -206
- package/dist/chunk-5SEMA47R.js +75 -0
- package/dist/{chunk-S6PHGKOC.js → chunk-7YKSXOQQ.js} +10 -2
- package/dist/{chunk-UP55PXFH.js → chunk-C4NKJT2Z.js} +8 -0
- package/dist/{chunk-CGOXE4WP.js → chunk-GGXJLMOH.js} +404 -730
- package/dist/{chunk-QBHRXLZS.js → chunk-H7MFXJZK.js} +2 -2
- package/dist/{chunk-3S4GGLLR.js → chunk-HEDJCLA6.js} +58 -19
- package/dist/{chunk-AYWEJCDB.js → chunk-J73TA3UM.js} +7 -7
- package/dist/{chunk-QV2GLOTK.js → chunk-LC4TV3KL.js} +1 -1
- package/dist/{chunk-RCMD3U65.js → chunk-NQ6FZKCE.js} +13 -0
- package/dist/{chunk-7U7BOHCL.js → chunk-VYKW7FMV.js} +147 -63
- package/dist/chunk-W25Z7CM6.js +487 -0
- package/dist/{chunk-OJCLKU5Z.js → chunk-WFTC3JJW.js} +16 -0
- package/dist/{server-3FHI2SEB.js → chunk-XBSCYMKM.js} +23 -369
- package/dist/{chunk-PHSAHTK4.js → chunk-YOSUPUAJ.js} +75 -7
- package/dist/cli/index.js +61 -17
- package/dist/{client-MPHPIZB6.js → client-YOOHI776.js} +4 -4
- package/dist/{get-my-gifts-CC6HAVWB.js → get-my-gifts-Y7EN7RK4.js} +3 -3
- package/dist/index.js +14 -13
- package/dist/{memory-UBHM7ILG.js → memory-Q6EWGK2S.js} +6 -4
- package/dist/memory-hook-WUXJNVT5.js +18 -0
- package/dist/{migrate-UBBEJ5BL.js → migrate-WFU6COBN.js} +4 -4
- package/dist/server-GYZXKIKU.js +787 -0
- package/dist/server-YODFBZKG.js +392 -0
- package/dist/setup-server-IZBUOJRU.js +215 -0
- package/dist/{store-M5IMUQCL.js → store-7M4XV6M5.js} +5 -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-NYH57UWP.js} +3 -3
- package/dist/{transcript-NGDPSNIH.js → transcript-IM7G25OS.js} +2 -2
- package/package.json +4 -2
- package/dist/chunk-XBE4JB7C.js +0 -8
|
@@ -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-GGXJLMOH.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-7YKSXOQQ.js";
|
|
41
39
|
import {
|
|
42
40
|
getErrorMessage
|
|
43
|
-
} from "./chunk-
|
|
44
|
-
import "./chunk-AYWEJCDB.js";
|
|
41
|
+
} from "./chunk-3UFPFWYP.js";
|
|
45
42
|
import {
|
|
46
43
|
getProviderMetadata,
|
|
47
44
|
validateApiKeyFormat
|
|
48
|
-
} from "./chunk-
|
|
49
|
-
import "./chunk-QV2GLOTK.js";
|
|
50
|
-
import "./chunk-7U7BOHCL.js";
|
|
51
|
-
import "./chunk-3S4GGLLR.js";
|
|
45
|
+
} from "./chunk-YOSUPUAJ.js";
|
|
52
46
|
import {
|
|
53
47
|
setTonapiKey
|
|
54
48
|
} from "./chunk-VFA7QMCZ.js";
|
|
55
|
-
import "./chunk-UP55PXFH.js";
|
|
56
|
-
import "./chunk-XQUHC3JZ.js";
|
|
57
|
-
import "./chunk-R4YSJ4EY.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
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createLogger
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NQ6FZKCE.js";
|
|
4
4
|
|
|
5
5
|
// src/config/providers.ts
|
|
6
6
|
var PROVIDER_REGISTRY = {
|
|
@@ -30,12 +30,12 @@ var PROVIDER_REGISTRY = {
|
|
|
30
30
|
},
|
|
31
31
|
openai: {
|
|
32
32
|
id: "openai",
|
|
33
|
-
displayName: "OpenAI (GPT-
|
|
33
|
+
displayName: "OpenAI (GPT-5.4)",
|
|
34
34
|
envVar: "OPENAI_API_KEY",
|
|
35
35
|
keyPrefix: "sk-",
|
|
36
36
|
keyHint: "sk-proj-...",
|
|
37
37
|
consoleUrl: "https://platform.openai.com/api-keys",
|
|
38
|
-
defaultModel: "gpt-
|
|
38
|
+
defaultModel: "gpt-5.4",
|
|
39
39
|
utilityModel: "gpt-4o-mini",
|
|
40
40
|
toolLimit: 128,
|
|
41
41
|
piAiProvider: "openai"
|
|
@@ -207,13 +207,17 @@ function validateApiKeyFormat(provider, key) {
|
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
// src/providers/claude-code-credentials.ts
|
|
210
|
-
import { readFileSync, existsSync } from "fs";
|
|
210
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
211
211
|
import { execSync } from "child_process";
|
|
212
212
|
import { homedir } from "os";
|
|
213
213
|
import { join } from "path";
|
|
214
214
|
var log = createLogger("ClaudeCodeCreds");
|
|
215
|
+
var OAUTH_TOKEN_URL = "https://platform.claude.com/v1/oauth/token";
|
|
216
|
+
var OAUTH_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
|
|
217
|
+
var OAUTH_SCOPES = "user:profile user:inference user:sessions:claude_code user:mcp_servers";
|
|
215
218
|
var cachedToken = null;
|
|
216
219
|
var cachedExpiresAt = 0;
|
|
220
|
+
var cachedRefreshToken = null;
|
|
217
221
|
function getClaudeConfigDir() {
|
|
218
222
|
return process.env.CLAUDE_CONFIG_DIR || join(homedir(), ".claude");
|
|
219
223
|
}
|
|
@@ -261,7 +265,8 @@ function extractToken(creds) {
|
|
|
261
265
|
}
|
|
262
266
|
return {
|
|
263
267
|
token: oauth.accessToken,
|
|
264
|
-
expiresAt: oauth.expiresAt ?? 0
|
|
268
|
+
expiresAt: oauth.expiresAt ?? 0,
|
|
269
|
+
refreshToken: oauth.refreshToken
|
|
265
270
|
};
|
|
266
271
|
}
|
|
267
272
|
function getClaudeCodeApiKey(fallbackKey) {
|
|
@@ -274,6 +279,7 @@ function getClaudeCodeApiKey(fallbackKey) {
|
|
|
274
279
|
if (extracted) {
|
|
275
280
|
cachedToken = extracted.token;
|
|
276
281
|
cachedExpiresAt = extracted.expiresAt;
|
|
282
|
+
cachedRefreshToken = extracted.refreshToken ?? null;
|
|
277
283
|
log.debug("Claude Code credentials loaded successfully");
|
|
278
284
|
return cachedToken;
|
|
279
285
|
}
|
|
@@ -284,20 +290,82 @@ function getClaudeCodeApiKey(fallbackKey) {
|
|
|
284
290
|
}
|
|
285
291
|
throw new Error("No Claude Code credentials found. Run 'claude login' or set api_key in config.");
|
|
286
292
|
}
|
|
287
|
-
function
|
|
293
|
+
async function performOAuthRefresh(refreshToken) {
|
|
294
|
+
try {
|
|
295
|
+
const res = await fetch(OAUTH_TOKEN_URL, {
|
|
296
|
+
method: "POST",
|
|
297
|
+
headers: { "Content-Type": "application/json" },
|
|
298
|
+
body: JSON.stringify({
|
|
299
|
+
grant_type: "refresh_token",
|
|
300
|
+
refresh_token: refreshToken,
|
|
301
|
+
client_id: OAUTH_CLIENT_ID,
|
|
302
|
+
scope: OAUTH_SCOPES
|
|
303
|
+
})
|
|
304
|
+
});
|
|
305
|
+
if (!res.ok) {
|
|
306
|
+
log.warn(`OAuth token refresh failed: ${res.status} ${res.statusText}`);
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
const data = await res.json();
|
|
310
|
+
if (!data.access_token || !data.expires_in) {
|
|
311
|
+
log.warn("OAuth token refresh: unexpected response shape");
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
const newExpiresAt = Date.now() + data.expires_in * 1e3;
|
|
315
|
+
const newRefreshToken = data.refresh_token ?? refreshToken;
|
|
316
|
+
const filePath = getCredentialsFilePath();
|
|
317
|
+
try {
|
|
318
|
+
const existing = existsSync(filePath) ? JSON.parse(readFileSync(filePath, "utf-8")) : {};
|
|
319
|
+
const updated = {
|
|
320
|
+
...existing,
|
|
321
|
+
claudeAiOauth: {
|
|
322
|
+
...existing.claudeAiOauth,
|
|
323
|
+
accessToken: data.access_token,
|
|
324
|
+
refreshToken: newRefreshToken,
|
|
325
|
+
expiresAt: newExpiresAt
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
writeFileSync(filePath, JSON.stringify(updated, null, 2), { mode: 384 });
|
|
329
|
+
} catch (e) {
|
|
330
|
+
log.warn({ err: e }, "Failed to persist refreshed OAuth credentials to disk");
|
|
331
|
+
}
|
|
332
|
+
cachedToken = data.access_token;
|
|
333
|
+
cachedExpiresAt = newExpiresAt;
|
|
334
|
+
cachedRefreshToken = newRefreshToken;
|
|
335
|
+
log.info("Claude Code OAuth token refreshed successfully");
|
|
336
|
+
return cachedToken;
|
|
337
|
+
} catch (e) {
|
|
338
|
+
log.warn({ err: e }, "OAuth token refresh request failed");
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
async function refreshClaudeCodeApiKey() {
|
|
288
343
|
cachedToken = null;
|
|
289
344
|
cachedExpiresAt = 0;
|
|
345
|
+
if (!cachedRefreshToken) {
|
|
346
|
+
const creds2 = readCredentials();
|
|
347
|
+
if (creds2) {
|
|
348
|
+
const extracted = extractToken(creds2);
|
|
349
|
+
cachedRefreshToken = extracted?.refreshToken ?? null;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
if (cachedRefreshToken) {
|
|
353
|
+
const refreshed = await performOAuthRefresh(cachedRefreshToken);
|
|
354
|
+
if (refreshed) return refreshed;
|
|
355
|
+
log.warn("OAuth refresh failed, falling back to disk read");
|
|
356
|
+
}
|
|
290
357
|
const creds = readCredentials();
|
|
291
358
|
if (creds) {
|
|
292
359
|
const extracted = extractToken(creds);
|
|
293
360
|
if (extracted) {
|
|
294
361
|
cachedToken = extracted.token;
|
|
295
362
|
cachedExpiresAt = extracted.expiresAt;
|
|
363
|
+
cachedRefreshToken = extracted.refreshToken ?? null;
|
|
296
364
|
log.info("Claude Code credentials refreshed from disk");
|
|
297
365
|
return cachedToken;
|
|
298
366
|
}
|
|
299
367
|
}
|
|
300
|
-
log.warn("Failed to refresh Claude Code credentials
|
|
368
|
+
log.warn("Failed to refresh Claude Code credentials");
|
|
301
369
|
return null;
|
|
302
370
|
}
|
|
303
371
|
function isClaudeCodeTokenValid() {
|