teleton 0.8.0 → 0.8.1
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 +28 -11
- package/dist/{chunk-U56QTM46.js → chunk-3S4GGLLR.js} +28 -26
- package/dist/{chunk-NUGDTPE4.js → chunk-4L66JHQE.js} +2 -1
- package/dist/{chunk-H36RFKRI.js → chunk-5FNWBZ5K.js} +476 -143
- package/dist/{chunk-SD4NLLYG.js → chunk-7U7BOHCL.js} +80 -33
- package/dist/{chunk-QVBSUYVX.js → chunk-AYWEJCDB.js} +11 -3
- package/dist/{chunk-RQBAMUCV.js → chunk-CGOXE4WP.js} +1235 -201
- package/dist/{chunk-TVRZJIZX.js → chunk-KVXV7EF7.js} +3 -3
- package/dist/{chunk-WIKM24GZ.js → chunk-QBHRXLZS.js} +5 -0
- package/dist/{chunk-P36I6OIV.js → chunk-QV2GLOTK.js} +12 -1
- package/dist/{chunk-JHYZYFZJ.js → chunk-S6PHGKOC.js} +8 -1
- package/dist/{chunk-IJBWWQE4.js → chunk-UP55PXFH.js} +4 -0
- package/dist/cli/index.js +17 -16
- package/dist/{client-LNZTDQSA.js → client-MPHPIZB6.js} +2 -2
- package/dist/{get-my-gifts-OMGKOEPM.js → get-my-gifts-CC6HAVWB.js} +1 -1
- package/dist/index.js +11 -11
- package/dist/{memory-AS7WKGTW.js → memory-UBHM7ILG.js} +4 -4
- package/dist/{migrate-POHWYEIW.js → migrate-UBBEJ5BL.js} +4 -4
- package/dist/{server-H3QA252W.js → server-3FHI2SEB.js} +392 -51
- package/dist/{setup-server-QXED3D2L.js → setup-server-32XGDPE6.js} +157 -7
- package/dist/{store-GAFULOOX.js → store-M5IMUQCL.js} +5 -5
- package/dist/{task-dependency-resolver-3FIKQ7Z6.js → task-dependency-resolver-RR2O5S7B.js} +2 -2
- package/dist/{task-executor-RUTFG6VG.js → task-executor-6W5HRX5C.js} +2 -2
- package/dist/{tasks-BEZ4QRI2.js → tasks-WQIKXDX5.js} +1 -1
- package/dist/{tool-index-H3SHOJC3.js → tool-index-PMAOXWUA.js} +8 -5
- package/dist/{transcript-IMNE6KU3.js → transcript-NGDPSNIH.js} +1 -1
- package/dist/web/assets/index-BfYCdwLI.js +80 -0
- package/dist/web/assets/{index-BrVqauzj.css → index-DmlyQVhR.css} +1 -1
- package/dist/web/assets/{index.es-DkU1GvWU.js → index.es-DitvF-9H.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +11 -4
- package/dist/web/assets/index-DYeEkvJ6.js +0 -72
|
@@ -3,46 +3,56 @@ import {
|
|
|
3
3
|
} from "./chunk-OJCLKU5Z.js";
|
|
4
4
|
import {
|
|
5
5
|
CONFIGURABLE_KEYS,
|
|
6
|
+
TonProxyManager,
|
|
6
7
|
WorkspaceSecurityError,
|
|
7
8
|
adaptPlugin,
|
|
8
9
|
clearPromptCache,
|
|
9
10
|
deleteNestedValue,
|
|
10
11
|
deletePluginSecret,
|
|
11
12
|
ensurePluginDeps,
|
|
13
|
+
getBlocklistConfig,
|
|
12
14
|
getNestedValue,
|
|
15
|
+
getPluginPriorities,
|
|
13
16
|
getTokenUsage,
|
|
17
|
+
getTonProxyManager,
|
|
18
|
+
getTriggersConfig,
|
|
14
19
|
listPluginSecretKeys,
|
|
15
20
|
readRawConfig,
|
|
21
|
+
resetPluginPriority,
|
|
22
|
+
setBlocklistConfig,
|
|
16
23
|
setNestedValue,
|
|
24
|
+
setPluginPriority,
|
|
25
|
+
setTonProxyManager,
|
|
26
|
+
setTriggersConfig,
|
|
17
27
|
validateDirectory,
|
|
18
28
|
validatePath,
|
|
19
29
|
validateReadPath,
|
|
20
30
|
validateWritePath,
|
|
21
31
|
writePluginSecret,
|
|
22
32
|
writeRawConfig
|
|
23
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-CGOXE4WP.js";
|
|
24
34
|
import {
|
|
25
35
|
invalidateEndpointCache,
|
|
26
36
|
invalidateTonClientCache,
|
|
27
37
|
setToncenterApiKey
|
|
28
|
-
} from "./chunk-
|
|
29
|
-
import "./chunk-
|
|
38
|
+
} from "./chunk-S6PHGKOC.js";
|
|
39
|
+
import "./chunk-KVXV7EF7.js";
|
|
30
40
|
import "./chunk-7TECSLJ4.js";
|
|
31
41
|
import {
|
|
32
42
|
getErrorMessage
|
|
33
43
|
} from "./chunk-XBE4JB7C.js";
|
|
34
|
-
import "./chunk-
|
|
44
|
+
import "./chunk-AYWEJCDB.js";
|
|
35
45
|
import {
|
|
36
46
|
getProviderMetadata,
|
|
37
47
|
validateApiKeyFormat
|
|
38
48
|
} from "./chunk-PHSAHTK4.js";
|
|
39
|
-
import "./chunk-
|
|
40
|
-
import "./chunk-
|
|
41
|
-
import "./chunk-
|
|
49
|
+
import "./chunk-QV2GLOTK.js";
|
|
50
|
+
import "./chunk-7U7BOHCL.js";
|
|
51
|
+
import "./chunk-3S4GGLLR.js";
|
|
42
52
|
import {
|
|
43
53
|
setTonapiKey
|
|
44
54
|
} from "./chunk-VFA7QMCZ.js";
|
|
45
|
-
import "./chunk-
|
|
55
|
+
import "./chunk-UP55PXFH.js";
|
|
46
56
|
import "./chunk-XQUHC3JZ.js";
|
|
47
57
|
import "./chunk-R4YSJ4EY.js";
|
|
48
58
|
import {
|
|
@@ -56,11 +66,11 @@ import {
|
|
|
56
66
|
} from "./chunk-RCMD3U65.js";
|
|
57
67
|
import {
|
|
58
68
|
getTaskStore
|
|
59
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-4L66JHQE.js";
|
|
60
70
|
import "./chunk-3RG5ZIWI.js";
|
|
61
71
|
|
|
62
72
|
// src/webui/server.ts
|
|
63
|
-
import { Hono as
|
|
73
|
+
import { Hono as Hono14 } from "hono";
|
|
64
74
|
import { serve } from "@hono/node-server";
|
|
65
75
|
import { cors } from "hono/cors";
|
|
66
76
|
import { streamSSE as streamSSE2 } from "hono/streaming";
|
|
@@ -413,15 +423,14 @@ function createLogsRoutes(_deps) {
|
|
|
413
423
|
const app = new Hono3();
|
|
414
424
|
app.get("/stream", (c) => {
|
|
415
425
|
return streamSSE(c, async (stream) => {
|
|
416
|
-
let cleanup;
|
|
417
426
|
let aborted = false;
|
|
418
427
|
stream.onAbort(() => {
|
|
419
428
|
aborted = true;
|
|
420
429
|
if (cleanup) cleanup();
|
|
421
430
|
});
|
|
422
|
-
cleanup = logInterceptor.addListener((entry) => {
|
|
431
|
+
const cleanup = logInterceptor.addListener((entry) => {
|
|
423
432
|
if (!aborted) {
|
|
424
|
-
stream.writeSSE({
|
|
433
|
+
void stream.writeSSE({
|
|
425
434
|
data: JSON.stringify(entry),
|
|
426
435
|
event: "log"
|
|
427
436
|
});
|
|
@@ -717,6 +726,52 @@ function createPluginsRoutes(deps) {
|
|
|
717
726
|
const data = deps.marketplace ? deps.marketplace.modules.filter((m) => deps.toolRegistry.isPluginModule(m.name)).map((m) => ({ name: m.name, version: m.version ?? "0.0.0" })) : deps.plugins;
|
|
718
727
|
return c.json({ success: true, data });
|
|
719
728
|
});
|
|
729
|
+
app.get("/priorities", (c) => {
|
|
730
|
+
try {
|
|
731
|
+
const priorities = getPluginPriorities(deps.memory.db);
|
|
732
|
+
const data = {};
|
|
733
|
+
for (const [name, priority] of priorities) {
|
|
734
|
+
data[name] = priority;
|
|
735
|
+
}
|
|
736
|
+
return c.json({ success: true, data });
|
|
737
|
+
} catch (err) {
|
|
738
|
+
return c.json({ success: false, error: getErrorMessage(err) }, 500);
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
app.post("/priorities", async (c) => {
|
|
742
|
+
try {
|
|
743
|
+
const body = await c.req.json();
|
|
744
|
+
const { pluginName, priority } = body;
|
|
745
|
+
if (!pluginName || typeof pluginName !== "string") {
|
|
746
|
+
return c.json({ success: false, error: "pluginName is required" }, 400);
|
|
747
|
+
}
|
|
748
|
+
if (typeof priority !== "number" || !Number.isInteger(priority)) {
|
|
749
|
+
return c.json({ success: false, error: "priority must be an integer" }, 400);
|
|
750
|
+
}
|
|
751
|
+
if (priority < -1e3 || priority > 1e3) {
|
|
752
|
+
return c.json(
|
|
753
|
+
{ success: false, error: "priority must be between -1000 and 1000" },
|
|
754
|
+
400
|
|
755
|
+
);
|
|
756
|
+
}
|
|
757
|
+
setPluginPriority(deps.memory.db, pluginName, priority);
|
|
758
|
+
return c.json({
|
|
759
|
+
success: true,
|
|
760
|
+
data: { pluginName, priority }
|
|
761
|
+
});
|
|
762
|
+
} catch (err) {
|
|
763
|
+
return c.json({ success: false, error: getErrorMessage(err) }, 500);
|
|
764
|
+
}
|
|
765
|
+
});
|
|
766
|
+
app.delete("/priorities/:name", (c) => {
|
|
767
|
+
try {
|
|
768
|
+
const name = c.req.param("name");
|
|
769
|
+
resetPluginPriority(deps.memory.db, name);
|
|
770
|
+
return c.json({ success: true, data: null });
|
|
771
|
+
} catch (err) {
|
|
772
|
+
return c.json({ success: false, error: getErrorMessage(err) }, 500);
|
|
773
|
+
}
|
|
774
|
+
});
|
|
720
775
|
return app;
|
|
721
776
|
}
|
|
722
777
|
|
|
@@ -782,7 +837,7 @@ function createMcpRoutes(deps) {
|
|
|
782
837
|
entry.url = body.url;
|
|
783
838
|
} else {
|
|
784
839
|
entry.command = "npx";
|
|
785
|
-
entry.args = ["-y", body.package, ...body.args || []];
|
|
840
|
+
entry.args = ["-y", body.package ?? "", ...body.args || []];
|
|
786
841
|
}
|
|
787
842
|
if (body.scope && body.scope !== "always") entry.scope = body.scope;
|
|
788
843
|
if (body.env && Object.keys(body.env).length > 0) entry.env = body.env;
|
|
@@ -833,7 +888,7 @@ function createMcpRoutes(deps) {
|
|
|
833
888
|
return app;
|
|
834
889
|
}
|
|
835
890
|
function deriveServerName(pkg) {
|
|
836
|
-
const unscoped = pkg.includes("/") ? pkg.split("/").pop() : pkg;
|
|
891
|
+
const unscoped = pkg.includes("/") ? pkg.split("/").pop() ?? pkg : pkg;
|
|
837
892
|
return unscoped.replace(/^server-/, "").replace(/^mcp-server-/, "").replace(/^mcp-/, "");
|
|
838
893
|
}
|
|
839
894
|
|
|
@@ -850,6 +905,8 @@ import {
|
|
|
850
905
|
existsSync
|
|
851
906
|
} from "fs";
|
|
852
907
|
import { join as join2, relative } from "path";
|
|
908
|
+
var MAX_SCAN_DEPTH = 10;
|
|
909
|
+
var MAX_SCAN_ENTRIES = 5e3;
|
|
853
910
|
function errorResponse(c, error, status = 500) {
|
|
854
911
|
const message = getErrorMessage(error);
|
|
855
912
|
const code = error instanceof WorkspaceSecurityError ? 403 : status;
|
|
@@ -866,35 +923,46 @@ var IMAGE_MIME_TYPES = {
|
|
|
866
923
|
".bmp": "image/bmp",
|
|
867
924
|
".ico": "image/x-icon"
|
|
868
925
|
};
|
|
869
|
-
function getWorkspaceStats(dir) {
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
926
|
+
function getWorkspaceStats(dir, depth = 0, state = { files: 0, size: 0, truncated: false }) {
|
|
927
|
+
if (!existsSync(dir)) return state;
|
|
928
|
+
if (depth >= MAX_SCAN_DEPTH || state.files >= MAX_SCAN_ENTRIES) {
|
|
929
|
+
state.truncated = true;
|
|
930
|
+
return state;
|
|
931
|
+
}
|
|
873
932
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
933
|
+
if (state.files >= MAX_SCAN_ENTRIES) {
|
|
934
|
+
state.truncated = true;
|
|
935
|
+
return state;
|
|
936
|
+
}
|
|
874
937
|
const fullPath = join2(dir, entry.name);
|
|
875
938
|
if (entry.isDirectory()) {
|
|
876
|
-
|
|
877
|
-
files += sub.files;
|
|
878
|
-
size += sub.size;
|
|
939
|
+
getWorkspaceStats(fullPath, depth + 1, state);
|
|
879
940
|
} else if (entry.isFile()) {
|
|
880
|
-
files++;
|
|
941
|
+
state.files++;
|
|
881
942
|
try {
|
|
882
|
-
size += statSync(fullPath).size;
|
|
943
|
+
state.size += statSync(fullPath).size;
|
|
883
944
|
} catch {
|
|
884
945
|
}
|
|
885
946
|
}
|
|
886
947
|
}
|
|
887
|
-
return
|
|
948
|
+
return state;
|
|
888
949
|
}
|
|
889
|
-
function listDir(absPath, recursive) {
|
|
890
|
-
if (!existsSync(absPath)) return
|
|
891
|
-
|
|
950
|
+
function listDir(absPath, recursive, depth = 0, state = { entries: [], truncated: false }) {
|
|
951
|
+
if (!existsSync(absPath)) return state;
|
|
952
|
+
if (depth >= MAX_SCAN_DEPTH || state.entries.length >= MAX_SCAN_ENTRIES) {
|
|
953
|
+
state.truncated = true;
|
|
954
|
+
return state;
|
|
955
|
+
}
|
|
892
956
|
for (const entry of readdirSync(absPath, { withFileTypes: true })) {
|
|
957
|
+
if (state.entries.length >= MAX_SCAN_ENTRIES) {
|
|
958
|
+
state.truncated = true;
|
|
959
|
+
return state;
|
|
960
|
+
}
|
|
893
961
|
const fullPath = join2(absPath, entry.name);
|
|
894
962
|
const relPath = relative(WORKSPACE_ROOT, fullPath);
|
|
895
963
|
try {
|
|
896
964
|
const stats = statSync(fullPath);
|
|
897
|
-
entries.push({
|
|
965
|
+
state.entries.push({
|
|
898
966
|
name: entry.name,
|
|
899
967
|
path: relPath,
|
|
900
968
|
isDirectory: entry.isDirectory(),
|
|
@@ -902,12 +970,12 @@ function listDir(absPath, recursive) {
|
|
|
902
970
|
mtime: stats.mtime.toISOString()
|
|
903
971
|
});
|
|
904
972
|
if (recursive && entry.isDirectory()) {
|
|
905
|
-
|
|
973
|
+
listDir(fullPath, true, depth + 1, state);
|
|
906
974
|
}
|
|
907
975
|
} catch {
|
|
908
976
|
}
|
|
909
977
|
}
|
|
910
|
-
return
|
|
978
|
+
return state;
|
|
911
979
|
}
|
|
912
980
|
function createWorkspaceRoutes(_deps) {
|
|
913
981
|
const app = new Hono8();
|
|
@@ -927,12 +995,18 @@ function createWorkspaceRoutes(_deps) {
|
|
|
927
995
|
const response2 = { success: true, data: [] };
|
|
928
996
|
return c.json(response2);
|
|
929
997
|
}
|
|
930
|
-
const
|
|
931
|
-
entries.sort((a, b) => {
|
|
998
|
+
const result = listDir(validated.absolutePath, recursive);
|
|
999
|
+
result.entries.sort((a, b) => {
|
|
932
1000
|
if (a.isDirectory !== b.isDirectory) return a.isDirectory ? -1 : 1;
|
|
933
1001
|
return a.name.localeCompare(b.name);
|
|
934
1002
|
});
|
|
935
|
-
const response = {
|
|
1003
|
+
const response = {
|
|
1004
|
+
success: true,
|
|
1005
|
+
data: {
|
|
1006
|
+
entries: result.entries,
|
|
1007
|
+
...result.truncated && { truncated: true }
|
|
1008
|
+
}
|
|
1009
|
+
};
|
|
936
1010
|
return c.json(response);
|
|
937
1011
|
} catch (error) {
|
|
938
1012
|
return errorResponse(c, error);
|
|
@@ -1101,7 +1175,8 @@ function createWorkspaceRoutes(_deps) {
|
|
|
1101
1175
|
data: {
|
|
1102
1176
|
root: WORKSPACE_ROOT,
|
|
1103
1177
|
totalFiles: stats.files,
|
|
1104
|
-
totalSize: stats.size
|
|
1178
|
+
totalSize: stats.size,
|
|
1179
|
+
...stats.truncated && { truncated: true }
|
|
1105
1180
|
}
|
|
1106
1181
|
};
|
|
1107
1182
|
return c.json(response);
|
|
@@ -1658,7 +1733,7 @@ var MarketplaceService = class {
|
|
|
1658
1733
|
const registry = await this.getRegistry();
|
|
1659
1734
|
const entry = registry.find((e) => e.id === pluginId);
|
|
1660
1735
|
if (!entry) throw new Error(`Plugin "${pluginId}" not found in registry`);
|
|
1661
|
-
const
|
|
1736
|
+
const _manifest = await this.fetchRemoteManifest(entry);
|
|
1662
1737
|
mkdirSync2(pluginDir, { recursive: true });
|
|
1663
1738
|
await this.downloadDir(entry.path, pluginDir);
|
|
1664
1739
|
await ensurePluginDeps(pluginDir, pluginId);
|
|
@@ -1834,7 +1909,7 @@ function createMarketplaceRoutes(deps) {
|
|
|
1834
1909
|
const result = await svc.installPlugin(body.id);
|
|
1835
1910
|
deps.plugins.length = 0;
|
|
1836
1911
|
deps.plugins.push(
|
|
1837
|
-
...deps.marketplace
|
|
1912
|
+
...(deps.marketplace?.modules ?? []).filter((m) => deps.toolRegistry.isPluginModule(m.name)).map((m) => ({ name: m.name, version: m.version ?? "0.0.0" }))
|
|
1838
1913
|
);
|
|
1839
1914
|
return c.json({ success: true, data: result });
|
|
1840
1915
|
} catch (err) {
|
|
@@ -1858,7 +1933,7 @@ function createMarketplaceRoutes(deps) {
|
|
|
1858
1933
|
const result = await svc.uninstallPlugin(body.id);
|
|
1859
1934
|
deps.plugins.length = 0;
|
|
1860
1935
|
deps.plugins.push(
|
|
1861
|
-
...deps.marketplace
|
|
1936
|
+
...(deps.marketplace?.modules ?? []).filter((m) => deps.toolRegistry.isPluginModule(m.name)).map((m) => ({ name: m.name, version: m.version ?? "0.0.0" }))
|
|
1862
1937
|
);
|
|
1863
1938
|
return c.json({ success: true, data: result });
|
|
1864
1939
|
} catch (err) {
|
|
@@ -1882,7 +1957,7 @@ function createMarketplaceRoutes(deps) {
|
|
|
1882
1957
|
const result = await svc.updatePlugin(body.id);
|
|
1883
1958
|
deps.plugins.length = 0;
|
|
1884
1959
|
deps.plugins.push(
|
|
1885
|
-
...deps.marketplace
|
|
1960
|
+
...(deps.marketplace?.modules ?? []).filter((m) => deps.toolRegistry.isPluginModule(m.name)).map((m) => ({ name: m.name, version: m.version ?? "0.0.0" }))
|
|
1886
1961
|
);
|
|
1887
1962
|
return c.json({ success: true, data: result });
|
|
1888
1963
|
} catch (err) {
|
|
@@ -1972,8 +2047,271 @@ function createMarketplaceRoutes(deps) {
|
|
|
1972
2047
|
return app;
|
|
1973
2048
|
}
|
|
1974
2049
|
|
|
2050
|
+
// src/webui/routes/hooks.ts
|
|
2051
|
+
import { Hono as Hono12 } from "hono";
|
|
2052
|
+
import { randomUUID } from "crypto";
|
|
2053
|
+
function createHooksRoutes(deps) {
|
|
2054
|
+
const app = new Hono12();
|
|
2055
|
+
app.get("/blocklist", (c) => {
|
|
2056
|
+
try {
|
|
2057
|
+
const data = getBlocklistConfig(deps.memory.db);
|
|
2058
|
+
return c.json({ success: true, data });
|
|
2059
|
+
} catch (err) {
|
|
2060
|
+
return c.json({ success: false, error: getErrorMessage(err) }, 500);
|
|
2061
|
+
}
|
|
2062
|
+
});
|
|
2063
|
+
app.put("/blocklist", async (c) => {
|
|
2064
|
+
try {
|
|
2065
|
+
const body = await c.req.json();
|
|
2066
|
+
if (typeof body.enabled !== "boolean") {
|
|
2067
|
+
return c.json({ success: false, error: "enabled must be a boolean" }, 400);
|
|
2068
|
+
}
|
|
2069
|
+
if (!Array.isArray(body.keywords)) {
|
|
2070
|
+
return c.json({ success: false, error: "keywords must be an array" }, 400);
|
|
2071
|
+
}
|
|
2072
|
+
if (body.keywords.length > 200) {
|
|
2073
|
+
return c.json({ success: false, error: "Maximum 200 keywords" }, 400);
|
|
2074
|
+
}
|
|
2075
|
+
const keywords = body.keywords.map((k) => typeof k === "string" ? k.trim() : "").filter((k) => k.length >= 2);
|
|
2076
|
+
const message = typeof body.message === "string" ? body.message.slice(0, 500) : "";
|
|
2077
|
+
const config = {
|
|
2078
|
+
enabled: body.enabled,
|
|
2079
|
+
keywords,
|
|
2080
|
+
message
|
|
2081
|
+
};
|
|
2082
|
+
setBlocklistConfig(deps.memory.db, config);
|
|
2083
|
+
deps.userHookEvaluator?.reload();
|
|
2084
|
+
return c.json({ success: true, data: config });
|
|
2085
|
+
} catch (err) {
|
|
2086
|
+
return c.json({ success: false, error: getErrorMessage(err) }, 500);
|
|
2087
|
+
}
|
|
2088
|
+
});
|
|
2089
|
+
app.get("/triggers", (c) => {
|
|
2090
|
+
try {
|
|
2091
|
+
const data = getTriggersConfig(deps.memory.db);
|
|
2092
|
+
return c.json({ success: true, data });
|
|
2093
|
+
} catch (err) {
|
|
2094
|
+
return c.json({ success: false, error: getErrorMessage(err) }, 500);
|
|
2095
|
+
}
|
|
2096
|
+
});
|
|
2097
|
+
app.post("/triggers", async (c) => {
|
|
2098
|
+
try {
|
|
2099
|
+
const body = await c.req.json();
|
|
2100
|
+
const keyword = typeof body.keyword === "string" ? body.keyword.trim() : "";
|
|
2101
|
+
const context = typeof body.context === "string" ? body.context.trim() : "";
|
|
2102
|
+
if (keyword.length < 2 || keyword.length > 100) {
|
|
2103
|
+
return c.json(
|
|
2104
|
+
{ success: false, error: "keyword must be 2-100 characters" },
|
|
2105
|
+
400
|
|
2106
|
+
);
|
|
2107
|
+
}
|
|
2108
|
+
if (context.length < 1 || context.length > 2e3) {
|
|
2109
|
+
return c.json(
|
|
2110
|
+
{ success: false, error: "context must be 1-2000 characters" },
|
|
2111
|
+
400
|
|
2112
|
+
);
|
|
2113
|
+
}
|
|
2114
|
+
const triggers = getTriggersConfig(deps.memory.db);
|
|
2115
|
+
if (triggers.length >= 50) {
|
|
2116
|
+
return c.json({ success: false, error: "Maximum 50 triggers" }, 400);
|
|
2117
|
+
}
|
|
2118
|
+
const entry = {
|
|
2119
|
+
id: randomUUID(),
|
|
2120
|
+
keyword,
|
|
2121
|
+
context,
|
|
2122
|
+
enabled: body.enabled !== false
|
|
2123
|
+
};
|
|
2124
|
+
triggers.push(entry);
|
|
2125
|
+
setTriggersConfig(deps.memory.db, triggers);
|
|
2126
|
+
deps.userHookEvaluator?.reload();
|
|
2127
|
+
return c.json({ success: true, data: entry });
|
|
2128
|
+
} catch (err) {
|
|
2129
|
+
return c.json({ success: false, error: getErrorMessage(err) }, 500);
|
|
2130
|
+
}
|
|
2131
|
+
});
|
|
2132
|
+
app.put("/triggers/:id", async (c) => {
|
|
2133
|
+
try {
|
|
2134
|
+
const id = c.req.param("id");
|
|
2135
|
+
const body = await c.req.json();
|
|
2136
|
+
const triggers = getTriggersConfig(deps.memory.db);
|
|
2137
|
+
const idx = triggers.findIndex((t) => t.id === id);
|
|
2138
|
+
if (idx === -1) {
|
|
2139
|
+
return c.json({ success: false, error: "Trigger not found" }, 404);
|
|
2140
|
+
}
|
|
2141
|
+
if (typeof body.keyword === "string") {
|
|
2142
|
+
const kw = body.keyword.trim();
|
|
2143
|
+
if (kw.length < 2 || kw.length > 100) {
|
|
2144
|
+
return c.json(
|
|
2145
|
+
{ success: false, error: "keyword must be 2-100 characters" },
|
|
2146
|
+
400
|
|
2147
|
+
);
|
|
2148
|
+
}
|
|
2149
|
+
triggers[idx].keyword = kw;
|
|
2150
|
+
}
|
|
2151
|
+
if (typeof body.context === "string") {
|
|
2152
|
+
const ctx = body.context.trim();
|
|
2153
|
+
if (ctx.length < 1 || ctx.length > 2e3) {
|
|
2154
|
+
return c.json(
|
|
2155
|
+
{ success: false, error: "context must be 1-2000 characters" },
|
|
2156
|
+
400
|
|
2157
|
+
);
|
|
2158
|
+
}
|
|
2159
|
+
triggers[idx].context = ctx;
|
|
2160
|
+
}
|
|
2161
|
+
if (typeof body.enabled === "boolean") {
|
|
2162
|
+
triggers[idx].enabled = body.enabled;
|
|
2163
|
+
}
|
|
2164
|
+
setTriggersConfig(deps.memory.db, triggers);
|
|
2165
|
+
deps.userHookEvaluator?.reload();
|
|
2166
|
+
return c.json({ success: true, data: triggers[idx] });
|
|
2167
|
+
} catch (err) {
|
|
2168
|
+
return c.json({ success: false, error: getErrorMessage(err) }, 500);
|
|
2169
|
+
}
|
|
2170
|
+
});
|
|
2171
|
+
app.delete("/triggers/:id", (c) => {
|
|
2172
|
+
try {
|
|
2173
|
+
const id = c.req.param("id");
|
|
2174
|
+
const triggers = getTriggersConfig(deps.memory.db);
|
|
2175
|
+
const filtered = triggers.filter((t) => t.id !== id);
|
|
2176
|
+
setTriggersConfig(deps.memory.db, filtered);
|
|
2177
|
+
deps.userHookEvaluator?.reload();
|
|
2178
|
+
return c.json({ success: true, data: null });
|
|
2179
|
+
} catch (err) {
|
|
2180
|
+
return c.json({ success: false, error: getErrorMessage(err) }, 500);
|
|
2181
|
+
}
|
|
2182
|
+
});
|
|
2183
|
+
app.patch("/triggers/:id/toggle", async (c) => {
|
|
2184
|
+
try {
|
|
2185
|
+
const id = c.req.param("id");
|
|
2186
|
+
const body = await c.req.json();
|
|
2187
|
+
if (typeof body.enabled !== "boolean") {
|
|
2188
|
+
return c.json({ success: false, error: "enabled must be a boolean" }, 400);
|
|
2189
|
+
}
|
|
2190
|
+
const triggers = getTriggersConfig(deps.memory.db);
|
|
2191
|
+
const trigger = triggers.find((t) => t.id === id);
|
|
2192
|
+
if (!trigger) {
|
|
2193
|
+
return c.json({ success: false, error: "Trigger not found" }, 404);
|
|
2194
|
+
}
|
|
2195
|
+
trigger.enabled = body.enabled;
|
|
2196
|
+
setTriggersConfig(deps.memory.db, triggers);
|
|
2197
|
+
deps.userHookEvaluator?.reload();
|
|
2198
|
+
return c.json({
|
|
2199
|
+
success: true,
|
|
2200
|
+
data: { id, enabled: body.enabled }
|
|
2201
|
+
});
|
|
2202
|
+
} catch (err) {
|
|
2203
|
+
return c.json({ success: false, error: getErrorMessage(err) }, 500);
|
|
2204
|
+
}
|
|
2205
|
+
});
|
|
2206
|
+
return app;
|
|
2207
|
+
}
|
|
2208
|
+
|
|
2209
|
+
// src/webui/routes/ton-proxy.ts
|
|
2210
|
+
import { Hono as Hono13 } from "hono";
|
|
2211
|
+
var log2 = createLogger("TonProxyRoute");
|
|
2212
|
+
function createTonProxyRoutes(deps) {
|
|
2213
|
+
const app = new Hono13();
|
|
2214
|
+
app.get("/", (c) => {
|
|
2215
|
+
const mgr = getTonProxyManager();
|
|
2216
|
+
if (!mgr) {
|
|
2217
|
+
return c.json({
|
|
2218
|
+
success: true,
|
|
2219
|
+
data: { running: false, installed: false, port: 8080, enabled: false }
|
|
2220
|
+
});
|
|
2221
|
+
}
|
|
2222
|
+
return c.json({
|
|
2223
|
+
success: true,
|
|
2224
|
+
data: { ...mgr.getStatus(), enabled: true }
|
|
2225
|
+
});
|
|
2226
|
+
});
|
|
2227
|
+
app.post("/start", async (c) => {
|
|
2228
|
+
try {
|
|
2229
|
+
const runtimeConfig = deps.agent.getConfig();
|
|
2230
|
+
const port = runtimeConfig.ton_proxy?.port ?? 8080;
|
|
2231
|
+
const binaryPath = runtimeConfig.ton_proxy?.binary_path;
|
|
2232
|
+
const existing = getTonProxyManager();
|
|
2233
|
+
if (existing?.isRunning()) await existing.stop();
|
|
2234
|
+
const mgr = new TonProxyManager({ enabled: true, port, binary_path: binaryPath });
|
|
2235
|
+
setTonProxyManager(mgr);
|
|
2236
|
+
await mgr.start();
|
|
2237
|
+
const raw = readRawConfig(deps.configPath);
|
|
2238
|
+
setNestedValue(raw, "ton_proxy.enabled", true);
|
|
2239
|
+
writeRawConfig(raw, deps.configPath);
|
|
2240
|
+
setNestedValue(runtimeConfig, "ton_proxy.enabled", true);
|
|
2241
|
+
log2.info(`TON Proxy started on port ${port} (WebUI)`);
|
|
2242
|
+
return c.json({
|
|
2243
|
+
success: true,
|
|
2244
|
+
data: { ...mgr.getStatus(), enabled: true }
|
|
2245
|
+
});
|
|
2246
|
+
} catch (err) {
|
|
2247
|
+
log2.error({ err }, "Failed to start TON Proxy");
|
|
2248
|
+
return c.json(
|
|
2249
|
+
{ success: false, error: err instanceof Error ? err.message : String(err) },
|
|
2250
|
+
500
|
|
2251
|
+
);
|
|
2252
|
+
}
|
|
2253
|
+
});
|
|
2254
|
+
app.post("/stop", async (c) => {
|
|
2255
|
+
try {
|
|
2256
|
+
const mgr = getTonProxyManager();
|
|
2257
|
+
if (mgr) {
|
|
2258
|
+
await mgr.stop();
|
|
2259
|
+
setTonProxyManager(null);
|
|
2260
|
+
}
|
|
2261
|
+
const runtimeConfig = deps.agent.getConfig();
|
|
2262
|
+
const raw = readRawConfig(deps.configPath);
|
|
2263
|
+
setNestedValue(raw, "ton_proxy.enabled", false);
|
|
2264
|
+
writeRawConfig(raw, deps.configPath);
|
|
2265
|
+
setNestedValue(runtimeConfig, "ton_proxy.enabled", false);
|
|
2266
|
+
log2.info("TON Proxy stopped (WebUI)");
|
|
2267
|
+
return c.json({
|
|
2268
|
+
success: true,
|
|
2269
|
+
data: { running: false, installed: true, port: 8080, enabled: false }
|
|
2270
|
+
});
|
|
2271
|
+
} catch (err) {
|
|
2272
|
+
log2.error({ err }, "Failed to stop TON Proxy");
|
|
2273
|
+
return c.json(
|
|
2274
|
+
{ success: false, error: err instanceof Error ? err.message : String(err) },
|
|
2275
|
+
500
|
|
2276
|
+
);
|
|
2277
|
+
}
|
|
2278
|
+
});
|
|
2279
|
+
app.post("/uninstall", async (c) => {
|
|
2280
|
+
try {
|
|
2281
|
+
const mgr = getTonProxyManager();
|
|
2282
|
+
if (mgr) {
|
|
2283
|
+
await mgr.uninstall();
|
|
2284
|
+
setTonProxyManager(null);
|
|
2285
|
+
} else {
|
|
2286
|
+
const runtimeConfig2 = deps.agent.getConfig();
|
|
2287
|
+
const port = runtimeConfig2.ton_proxy?.port ?? 8080;
|
|
2288
|
+
const binaryPath = runtimeConfig2.ton_proxy?.binary_path;
|
|
2289
|
+
const tmp = new TonProxyManager({ enabled: false, port, binary_path: binaryPath });
|
|
2290
|
+
await tmp.uninstall();
|
|
2291
|
+
}
|
|
2292
|
+
const runtimeConfig = deps.agent.getConfig();
|
|
2293
|
+
const raw = readRawConfig(deps.configPath);
|
|
2294
|
+
setNestedValue(raw, "ton_proxy.enabled", false);
|
|
2295
|
+
writeRawConfig(raw, deps.configPath);
|
|
2296
|
+
setNestedValue(runtimeConfig, "ton_proxy.enabled", false);
|
|
2297
|
+
log2.info("TON Proxy uninstalled (WebUI)");
|
|
2298
|
+
return c.json({
|
|
2299
|
+
success: true,
|
|
2300
|
+
data: { running: false, installed: false, port: 8080, enabled: false }
|
|
2301
|
+
});
|
|
2302
|
+
} catch (err) {
|
|
2303
|
+
log2.error({ err }, "Failed to uninstall TON Proxy");
|
|
2304
|
+
return c.json(
|
|
2305
|
+
{ success: false, error: err instanceof Error ? err.message : String(err) },
|
|
2306
|
+
500
|
|
2307
|
+
);
|
|
2308
|
+
}
|
|
2309
|
+
});
|
|
2310
|
+
return app;
|
|
2311
|
+
}
|
|
2312
|
+
|
|
1975
2313
|
// src/webui/server.ts
|
|
1976
|
-
var
|
|
2314
|
+
var log3 = createLogger("WebUI");
|
|
1977
2315
|
function findWebDist() {
|
|
1978
2316
|
const candidates = [
|
|
1979
2317
|
resolve2("dist/web"),
|
|
@@ -2002,12 +2340,13 @@ var WebUIServer = class {
|
|
|
2002
2340
|
authToken;
|
|
2003
2341
|
constructor(deps) {
|
|
2004
2342
|
this.deps = deps;
|
|
2005
|
-
this.app = new
|
|
2343
|
+
this.app = new Hono14();
|
|
2006
2344
|
this.authToken = deps.config.auth_token || generateToken();
|
|
2007
2345
|
this.setupMiddleware();
|
|
2008
2346
|
this.setupRoutes();
|
|
2009
2347
|
}
|
|
2010
2348
|
/** Set an HttpOnly session cookie */
|
|
2349
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Hono context type
|
|
2011
2350
|
setSessionCookie(c) {
|
|
2012
2351
|
setCookie(c, COOKIE_NAME, this.authToken, {
|
|
2013
2352
|
path: "/",
|
|
@@ -2034,7 +2373,7 @@ var WebUIServer = class {
|
|
|
2034
2373
|
const start = Date.now();
|
|
2035
2374
|
await next();
|
|
2036
2375
|
const duration = Date.now() - start;
|
|
2037
|
-
|
|
2376
|
+
log3.info(`${c.req.method} ${c.req.path} \u2192 ${c.res.status} (${duration}ms)`);
|
|
2038
2377
|
});
|
|
2039
2378
|
}
|
|
2040
2379
|
this.app.use(
|
|
@@ -2112,6 +2451,8 @@ var WebUIServer = class {
|
|
|
2112
2451
|
this.app.route("/api/tasks", createTasksRoutes(this.deps));
|
|
2113
2452
|
this.app.route("/api/config", createConfigRoutes(this.deps));
|
|
2114
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));
|
|
2115
2456
|
this.app.post("/api/agent/start", async (c) => {
|
|
2116
2457
|
const lifecycle = this.deps.lifecycle;
|
|
2117
2458
|
if (!lifecycle) {
|
|
@@ -2125,7 +2466,7 @@ var WebUIServer = class {
|
|
|
2125
2466
|
return c.json({ error: "Agent is currently stopping, please wait" }, 409);
|
|
2126
2467
|
}
|
|
2127
2468
|
lifecycle.start().catch((err) => {
|
|
2128
|
-
|
|
2469
|
+
log3.error({ err }, "Agent start failed");
|
|
2129
2470
|
});
|
|
2130
2471
|
return c.json({ state: "starting" });
|
|
2131
2472
|
});
|
|
@@ -2142,7 +2483,7 @@ var WebUIServer = class {
|
|
|
2142
2483
|
return c.json({ error: "Agent is currently starting, please wait" }, 409);
|
|
2143
2484
|
}
|
|
2144
2485
|
lifecycle.stop().catch((err) => {
|
|
2145
|
-
|
|
2486
|
+
log3.error({ err }, "Agent stop failed");
|
|
2146
2487
|
});
|
|
2147
2488
|
return c.json({ state: "stopping" });
|
|
2148
2489
|
});
|
|
@@ -2180,7 +2521,7 @@ var WebUIServer = class {
|
|
|
2180
2521
|
});
|
|
2181
2522
|
const onStateChange = (event) => {
|
|
2182
2523
|
if (aborted) return;
|
|
2183
|
-
stream.writeSSE({
|
|
2524
|
+
void stream.writeSSE({
|
|
2184
2525
|
event: "status",
|
|
2185
2526
|
id: String(event.timestamp),
|
|
2186
2527
|
data: JSON.stringify({
|
|
@@ -2239,7 +2580,7 @@ var WebUIServer = class {
|
|
|
2239
2580
|
});
|
|
2240
2581
|
}
|
|
2241
2582
|
this.app.onError((err, c) => {
|
|
2242
|
-
|
|
2583
|
+
log3.error({ err }, "WebUI error");
|
|
2243
2584
|
return c.json(
|
|
2244
2585
|
{
|
|
2245
2586
|
success: false,
|
|
@@ -2261,9 +2602,9 @@ var WebUIServer = class {
|
|
|
2261
2602
|
},
|
|
2262
2603
|
(info) => {
|
|
2263
2604
|
const url = `http://${info.address}:${info.port}`;
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
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)`);
|
|
2267
2608
|
resolve3();
|
|
2268
2609
|
}
|
|
2269
2610
|
);
|
|
@@ -2276,9 +2617,9 @@ var WebUIServer = class {
|
|
|
2276
2617
|
async stop() {
|
|
2277
2618
|
if (this.server) {
|
|
2278
2619
|
return new Promise((resolve3) => {
|
|
2279
|
-
this.server
|
|
2620
|
+
this.server?.close(() => {
|
|
2280
2621
|
logInterceptor.uninstall();
|
|
2281
|
-
|
|
2622
|
+
log3.info("WebUI server stopped");
|
|
2282
2623
|
resolve3();
|
|
2283
2624
|
});
|
|
2284
2625
|
});
|