teleton 0.7.0 → 0.7.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 +11 -8
- package/dist/{chunk-OGIG552S.js → chunk-3YM57ZAV.js} +312 -132
- package/dist/{chunk-TCD4NZDA.js → chunk-HZNZT4TG.js} +66 -58
- package/dist/cli/index.js +4 -4
- package/dist/index.js +4 -4
- package/dist/{memory-RD7ZSTRV.js → memory-5SS3Q5EA.js} +2 -2
- package/dist/{migrate-GO4NOBT7.js → migrate-M7SJMDOL.js} +2 -2
- package/dist/{server-OWVEZTR3.js → server-DS5OARW6.js} +94 -2
- package/dist/web/assets/index-BqwoDycr.js +72 -0
- package/dist/web/assets/index-CRDIf07k.css +1 -0
- package/dist/web/assets/{index.es-oXiZF7Hc.js → index.es-D81xLR29.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/web/assets/index-B_FcaX5D.css +0 -1
- package/dist/web/assets/index-CbeAP4_n.js +0 -67
- package/dist/{chunk-N3F7E7DR.js → chunk-RBU6JXD3.js} +3 -3
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
writePluginSecret,
|
|
43
43
|
writeRawConfig,
|
|
44
44
|
writeSummaryToDailyLog
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-HZNZT4TG.js";
|
|
46
46
|
import {
|
|
47
47
|
getKeyPair,
|
|
48
48
|
getTonPrice,
|
|
@@ -83,7 +83,7 @@ import {
|
|
|
83
83
|
closeDatabase,
|
|
84
84
|
getDatabase,
|
|
85
85
|
initializeMemory
|
|
86
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-RBU6JXD3.js";
|
|
87
87
|
import {
|
|
88
88
|
JOURNAL_SCHEMA,
|
|
89
89
|
USED_TRANSACTIONS_SCHEMA,
|
|
@@ -20984,6 +20984,7 @@ var PluginWatcher = class {
|
|
|
20984
20984
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
20985
20985
|
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
20986
20986
|
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
20987
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
20987
20988
|
var log123 = createLogger("MCP");
|
|
20988
20989
|
var MCP_CONNECT_TIMEOUT_MS = 3e4;
|
|
20989
20990
|
function parseCommand(config) {
|
|
@@ -21031,21 +21032,48 @@ async function loadMcpServers(config) {
|
|
|
21031
21032
|
stderr: "pipe"
|
|
21032
21033
|
});
|
|
21033
21034
|
} else if (serverConfig.url) {
|
|
21034
|
-
transport = new
|
|
21035
|
+
transport = new StreamableHTTPClientTransport(new URL(serverConfig.url));
|
|
21035
21036
|
} else {
|
|
21036
21037
|
throw new Error(`MCP server "${name}": needs 'command' or 'url'`);
|
|
21037
21038
|
}
|
|
21038
21039
|
const client = new Client({ name: `teleton-${name}`, version: "1.0.0" });
|
|
21039
21040
|
let timeoutHandle;
|
|
21040
|
-
|
|
21041
|
-
|
|
21042
|
-
|
|
21043
|
-
|
|
21044
|
-
|
|
21045
|
-
|
|
21046
|
-
|
|
21047
|
-
|
|
21048
|
-
|
|
21041
|
+
try {
|
|
21042
|
+
await Promise.race([
|
|
21043
|
+
client.connect(transport),
|
|
21044
|
+
new Promise((_, reject) => {
|
|
21045
|
+
timeoutHandle = setTimeout(
|
|
21046
|
+
() => reject(new Error(`Connection timed out after ${MCP_CONNECT_TIMEOUT_MS / 1e3}s`)),
|
|
21047
|
+
MCP_CONNECT_TIMEOUT_MS
|
|
21048
|
+
);
|
|
21049
|
+
})
|
|
21050
|
+
]).finally(() => clearTimeout(timeoutHandle));
|
|
21051
|
+
} catch (err) {
|
|
21052
|
+
if (serverConfig.url && transport instanceof StreamableHTTPClientTransport) {
|
|
21053
|
+
await client.close().catch(() => {
|
|
21054
|
+
});
|
|
21055
|
+
log123.info({ server: name }, "Streamable HTTP failed, falling back to SSE");
|
|
21056
|
+
transport = new SSEClientTransport(new URL(serverConfig.url));
|
|
21057
|
+
const fallbackClient = new Client({ name: `teleton-${name}`, version: "1.0.0" });
|
|
21058
|
+
await Promise.race([
|
|
21059
|
+
fallbackClient.connect(transport),
|
|
21060
|
+
new Promise((_, reject) => {
|
|
21061
|
+
timeoutHandle = setTimeout(
|
|
21062
|
+
() => reject(
|
|
21063
|
+
new Error(`SSE fallback timed out after ${MCP_CONNECT_TIMEOUT_MS / 1e3}s`)
|
|
21064
|
+
),
|
|
21065
|
+
MCP_CONNECT_TIMEOUT_MS
|
|
21066
|
+
);
|
|
21067
|
+
})
|
|
21068
|
+
]).finally(() => clearTimeout(timeoutHandle));
|
|
21069
|
+
return {
|
|
21070
|
+
serverName: name,
|
|
21071
|
+
client: fallbackClient,
|
|
21072
|
+
scope: serverConfig.scope ?? "always"
|
|
21073
|
+
};
|
|
21074
|
+
}
|
|
21075
|
+
throw err;
|
|
21076
|
+
}
|
|
21049
21077
|
return { serverName: name, client, scope: serverConfig.scope ?? "always" };
|
|
21050
21078
|
})
|
|
21051
21079
|
);
|
|
@@ -21056,9 +21084,8 @@ async function loadMcpServers(config) {
|
|
|
21056
21084
|
if (result.status === "fulfilled") {
|
|
21057
21085
|
connections.push(result.value);
|
|
21058
21086
|
} else {
|
|
21059
|
-
|
|
21060
|
-
|
|
21061
|
-
);
|
|
21087
|
+
const reason = result.reason instanceof Error ? result.reason.stack ?? result.reason.message : result.reason;
|
|
21088
|
+
log123.warn({ server: name, reason }, `MCP server "${name}" failed to connect`);
|
|
21062
21089
|
}
|
|
21063
21090
|
}
|
|
21064
21091
|
return connections;
|
|
@@ -21141,8 +21168,129 @@ async function closeMcpServers(connections) {
|
|
|
21141
21168
|
);
|
|
21142
21169
|
}
|
|
21143
21170
|
|
|
21171
|
+
// src/agent/lifecycle.ts
|
|
21172
|
+
import { EventEmitter } from "events";
|
|
21173
|
+
var log124 = createLogger("Lifecycle");
|
|
21174
|
+
var AgentLifecycle = class extends EventEmitter {
|
|
21175
|
+
state = "stopped";
|
|
21176
|
+
error;
|
|
21177
|
+
startPromise = null;
|
|
21178
|
+
stopPromise = null;
|
|
21179
|
+
runningSince = null;
|
|
21180
|
+
registeredStartFn = null;
|
|
21181
|
+
registeredStopFn = null;
|
|
21182
|
+
getState() {
|
|
21183
|
+
return this.state;
|
|
21184
|
+
}
|
|
21185
|
+
getError() {
|
|
21186
|
+
return this.error;
|
|
21187
|
+
}
|
|
21188
|
+
getUptime() {
|
|
21189
|
+
if (this.state !== "running" || this.runningSince === null) {
|
|
21190
|
+
return null;
|
|
21191
|
+
}
|
|
21192
|
+
return Math.floor((Date.now() - this.runningSince) / 1e3);
|
|
21193
|
+
}
|
|
21194
|
+
/**
|
|
21195
|
+
* Register the start/stop callbacks so start()/stop() can be called without args.
|
|
21196
|
+
*/
|
|
21197
|
+
registerCallbacks(startFn, stopFn) {
|
|
21198
|
+
this.registeredStartFn = startFn;
|
|
21199
|
+
this.registeredStopFn = stopFn;
|
|
21200
|
+
}
|
|
21201
|
+
/**
|
|
21202
|
+
* Start the agent. Uses the provided callback or falls back to registered one.
|
|
21203
|
+
* - No-op if already running
|
|
21204
|
+
* - Returns existing promise if already starting
|
|
21205
|
+
* - Throws if currently stopping
|
|
21206
|
+
*/
|
|
21207
|
+
async start(startFn) {
|
|
21208
|
+
const fn = startFn ?? this.registeredStartFn;
|
|
21209
|
+
if (!fn) {
|
|
21210
|
+
throw new Error("No start function provided or registered");
|
|
21211
|
+
}
|
|
21212
|
+
if (this.state === "running") {
|
|
21213
|
+
return;
|
|
21214
|
+
}
|
|
21215
|
+
if (this.state === "starting") {
|
|
21216
|
+
return this.startPromise;
|
|
21217
|
+
}
|
|
21218
|
+
if (this.state === "stopping") {
|
|
21219
|
+
throw new Error("Cannot start while agent is stopping");
|
|
21220
|
+
}
|
|
21221
|
+
this.transition("starting");
|
|
21222
|
+
this.startPromise = (async () => {
|
|
21223
|
+
try {
|
|
21224
|
+
await fn();
|
|
21225
|
+
this.error = void 0;
|
|
21226
|
+
this.runningSince = Date.now();
|
|
21227
|
+
this.transition("running");
|
|
21228
|
+
} catch (err) {
|
|
21229
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
21230
|
+
this.error = message;
|
|
21231
|
+
this.runningSince = null;
|
|
21232
|
+
this.transition("stopped", message);
|
|
21233
|
+
throw err;
|
|
21234
|
+
} finally {
|
|
21235
|
+
this.startPromise = null;
|
|
21236
|
+
}
|
|
21237
|
+
})();
|
|
21238
|
+
return this.startPromise;
|
|
21239
|
+
}
|
|
21240
|
+
/**
|
|
21241
|
+
* Stop the agent. Uses the provided callback or falls back to registered one.
|
|
21242
|
+
* - No-op if already stopped
|
|
21243
|
+
* - Returns existing promise if already stopping
|
|
21244
|
+
* - If starting, waits for start to complete then stops
|
|
21245
|
+
*/
|
|
21246
|
+
async stop(stopFn) {
|
|
21247
|
+
const fn = stopFn ?? this.registeredStopFn;
|
|
21248
|
+
if (!fn) {
|
|
21249
|
+
throw new Error("No stop function provided or registered");
|
|
21250
|
+
}
|
|
21251
|
+
if (this.state === "stopped") {
|
|
21252
|
+
return;
|
|
21253
|
+
}
|
|
21254
|
+
if (this.state === "stopping") {
|
|
21255
|
+
return this.stopPromise;
|
|
21256
|
+
}
|
|
21257
|
+
if (this.state === "starting" && this.startPromise) {
|
|
21258
|
+
try {
|
|
21259
|
+
await this.startPromise;
|
|
21260
|
+
} catch {
|
|
21261
|
+
return;
|
|
21262
|
+
}
|
|
21263
|
+
}
|
|
21264
|
+
this.transition("stopping");
|
|
21265
|
+
this.stopPromise = (async () => {
|
|
21266
|
+
try {
|
|
21267
|
+
await fn();
|
|
21268
|
+
} catch (err) {
|
|
21269
|
+
log124.error({ err }, "Error during agent stop");
|
|
21270
|
+
} finally {
|
|
21271
|
+
this.runningSince = null;
|
|
21272
|
+
this.transition("stopped");
|
|
21273
|
+
this.stopPromise = null;
|
|
21274
|
+
}
|
|
21275
|
+
})();
|
|
21276
|
+
return this.stopPromise;
|
|
21277
|
+
}
|
|
21278
|
+
transition(newState, error) {
|
|
21279
|
+
this.state = newState;
|
|
21280
|
+
const event = {
|
|
21281
|
+
state: newState,
|
|
21282
|
+
timestamp: Date.now()
|
|
21283
|
+
};
|
|
21284
|
+
if (error !== void 0) {
|
|
21285
|
+
event.error = error;
|
|
21286
|
+
}
|
|
21287
|
+
log124.info(`Agent state: ${newState}${error ? ` (${error})` : ""}`);
|
|
21288
|
+
this.emit("stateChange", event);
|
|
21289
|
+
}
|
|
21290
|
+
};
|
|
21291
|
+
|
|
21144
21292
|
// src/index.ts
|
|
21145
|
-
var
|
|
21293
|
+
var log125 = createLogger("App");
|
|
21146
21294
|
var TeletonApp = class {
|
|
21147
21295
|
config;
|
|
21148
21296
|
agent;
|
|
@@ -21162,6 +21310,7 @@ var TeletonApp = class {
|
|
|
21162
21310
|
pluginWatcher = null;
|
|
21163
21311
|
mcpConnections = [];
|
|
21164
21312
|
callbackHandlerRegistered = false;
|
|
21313
|
+
lifecycle = new AgentLifecycle();
|
|
21165
21314
|
configPath;
|
|
21166
21315
|
constructor(configPath) {
|
|
21167
21316
|
this.configPath = configPath ?? getDefaultConfigPath();
|
|
@@ -21220,13 +21369,19 @@ var TeletonApp = class {
|
|
|
21220
21369
|
this.toolRegistry
|
|
21221
21370
|
);
|
|
21222
21371
|
}
|
|
21372
|
+
/**
|
|
21373
|
+
* Get the lifecycle state machine for WebUI integration
|
|
21374
|
+
*/
|
|
21375
|
+
getLifecycle() {
|
|
21376
|
+
return this.lifecycle;
|
|
21377
|
+
}
|
|
21223
21378
|
/**
|
|
21224
21379
|
* Start the agent
|
|
21225
21380
|
*/
|
|
21226
21381
|
async start() {
|
|
21227
21382
|
const blue = "\x1B[34m";
|
|
21228
21383
|
const reset = "\x1B[0m";
|
|
21229
|
-
|
|
21384
|
+
log125.info(`
|
|
21230
21385
|
${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
|
|
21231
21386
|
\u2502 \u2502
|
|
21232
21387
|
\u2502 ______________ ________________ _ __ ___ _____________ ________ \u2502
|
|
@@ -21237,6 +21392,71 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
21237
21392
|
\u2502 \u2502
|
|
21238
21393
|
\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 DEV: ZKPROOF.T.ME \u2500\u2500\u2518${reset}
|
|
21239
21394
|
`);
|
|
21395
|
+
this.lifecycle.registerCallbacks(
|
|
21396
|
+
() => this.startAgent(),
|
|
21397
|
+
() => this.stopAgent()
|
|
21398
|
+
);
|
|
21399
|
+
if (this.config.webui.enabled) {
|
|
21400
|
+
try {
|
|
21401
|
+
const { WebUIServer } = await import("./server-DS5OARW6.js");
|
|
21402
|
+
const mcpServers = () => Object.entries(this.config.mcp.servers).map(([name, serverConfig]) => {
|
|
21403
|
+
const type = serverConfig.command ? "stdio" : serverConfig.url ? "streamable-http" : "sse";
|
|
21404
|
+
const target = serverConfig.command ?? serverConfig.url ?? "";
|
|
21405
|
+
const connected = this.mcpConnections.some((c2) => c2.serverName === name);
|
|
21406
|
+
const moduleName = `mcp_${name}`;
|
|
21407
|
+
const moduleTools = this.toolRegistry.getModuleTools(moduleName);
|
|
21408
|
+
return {
|
|
21409
|
+
name,
|
|
21410
|
+
type,
|
|
21411
|
+
target,
|
|
21412
|
+
scope: serverConfig.scope ?? "always",
|
|
21413
|
+
enabled: serverConfig.enabled ?? true,
|
|
21414
|
+
connected,
|
|
21415
|
+
toolCount: moduleTools.length,
|
|
21416
|
+
tools: moduleTools.map((t) => t.name),
|
|
21417
|
+
envKeys: Object.keys(serverConfig.env ?? {})
|
|
21418
|
+
};
|
|
21419
|
+
});
|
|
21420
|
+
const builtinNames = this.modules.map((m) => m.name);
|
|
21421
|
+
const pluginContext = {
|
|
21422
|
+
bridge: this.bridge,
|
|
21423
|
+
db: getDatabase().getDb(),
|
|
21424
|
+
config: this.config
|
|
21425
|
+
};
|
|
21426
|
+
this.webuiServer = new WebUIServer({
|
|
21427
|
+
agent: this.agent,
|
|
21428
|
+
bridge: this.bridge,
|
|
21429
|
+
memory: this.memory,
|
|
21430
|
+
toolRegistry: this.toolRegistry,
|
|
21431
|
+
plugins: this.modules.filter((m) => this.toolRegistry.isPluginModule(m.name)).map((m) => ({ name: m.name, version: m.version ?? "0.0.0" })),
|
|
21432
|
+
mcpServers,
|
|
21433
|
+
config: this.config.webui,
|
|
21434
|
+
configPath: this.configPath,
|
|
21435
|
+
lifecycle: this.lifecycle,
|
|
21436
|
+
marketplace: {
|
|
21437
|
+
modules: this.modules,
|
|
21438
|
+
config: this.config,
|
|
21439
|
+
sdkDeps: this.sdkDeps,
|
|
21440
|
+
pluginContext,
|
|
21441
|
+
loadedModuleNames: builtinNames,
|
|
21442
|
+
rewireHooks: () => this.wirePluginEventHooks()
|
|
21443
|
+
}
|
|
21444
|
+
});
|
|
21445
|
+
await this.webuiServer.start();
|
|
21446
|
+
} catch (error) {
|
|
21447
|
+
log125.error({ err: error }, "\u274C Failed to start WebUI server");
|
|
21448
|
+
log125.warn("\u26A0\uFE0F Continuing without WebUI...");
|
|
21449
|
+
}
|
|
21450
|
+
}
|
|
21451
|
+
await this.lifecycle.start(() => this.startAgent());
|
|
21452
|
+
await new Promise(() => {
|
|
21453
|
+
});
|
|
21454
|
+
}
|
|
21455
|
+
/**
|
|
21456
|
+
* Start agent subsystems (Telegram, plugins, MCP, modules, debouncer, handler).
|
|
21457
|
+
* Called by lifecycle.start() — do NOT call directly.
|
|
21458
|
+
*/
|
|
21459
|
+
async startAgent() {
|
|
21240
21460
|
const moduleNames = this.modules.filter((m) => m.tools(this.config).length > 0).map((m) => m.name);
|
|
21241
21461
|
const builtinNames = this.modules.map((m) => m.name);
|
|
21242
21462
|
const externalModules = await loadEnhancedPlugins(this.config, builtinNames, this.sdkDeps);
|
|
@@ -21253,7 +21473,7 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
21253
21473
|
}
|
|
21254
21474
|
this.modules.push(mod);
|
|
21255
21475
|
} catch (error) {
|
|
21256
|
-
|
|
21476
|
+
log125.error(
|
|
21257
21477
|
`\u274C Plugin "${mod.name}" failed to load: ${error instanceof Error ? error.message : error}`
|
|
21258
21478
|
);
|
|
21259
21479
|
}
|
|
@@ -21269,7 +21489,7 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
21269
21489
|
if (mcp.count > 0) {
|
|
21270
21490
|
this.toolCount = this.toolRegistry.count;
|
|
21271
21491
|
mcpServerNames.push(...mcp.names);
|
|
21272
|
-
|
|
21492
|
+
log125.info(
|
|
21273
21493
|
`\u{1F50C} MCP: ${mcp.count} tools from ${mcp.names.length} server(s) (${mcp.names.join(", ")})`
|
|
21274
21494
|
);
|
|
21275
21495
|
}
|
|
@@ -21297,15 +21517,15 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
21297
21517
|
const provider = this.config.agent.provider || "anthropic";
|
|
21298
21518
|
const providerMeta = getProviderMetadata(provider);
|
|
21299
21519
|
const allNames = [...moduleNames, ...pluginNames, ...mcpServerNames];
|
|
21300
|
-
|
|
21520
|
+
log125.info(
|
|
21301
21521
|
`\u{1F50C} ${this.toolCount} tools loaded (${allNames.join(", ")})${pluginToolCount > 0 ? ` \u2014 ${pluginToolCount} from plugins` : ""}`
|
|
21302
21522
|
);
|
|
21303
21523
|
if (providerMeta.toolLimit !== null && this.toolCount > providerMeta.toolLimit) {
|
|
21304
|
-
|
|
21524
|
+
log125.warn(
|
|
21305
21525
|
`\u26A0\uFE0F Tool count (${this.toolCount}) exceeds ${providerMeta.displayName} limit (${providerMeta.toolLimit})`
|
|
21306
21526
|
);
|
|
21307
21527
|
}
|
|
21308
|
-
const { migrateSessionsToDb } = await import("./migrate-
|
|
21528
|
+
const { migrateSessionsToDb } = await import("./migrate-M7SJMDOL.js");
|
|
21309
21529
|
migrateSessionsToDb();
|
|
21310
21530
|
const { cleanupOldTranscripts } = await import("./transcript-UDJZP6NK.js");
|
|
21311
21531
|
cleanupOldTranscripts(30);
|
|
@@ -21319,7 +21539,7 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
21319
21539
|
if (toolIndex) {
|
|
21320
21540
|
const t0 = Date.now();
|
|
21321
21541
|
const indexedCount = await toolIndex.indexAll(this.toolRegistry.getAll());
|
|
21322
|
-
|
|
21542
|
+
log125.info(`\u{1F50D} Tool RAG: ${indexedCount} tools indexed (${Date.now() - t0}ms)`);
|
|
21323
21543
|
}
|
|
21324
21544
|
this.agent.initializeContextBuilder(this.memory.embedder, db2.isVectorSearchReady());
|
|
21325
21545
|
if (this.config.agent.provider === "cocoon") {
|
|
@@ -21330,44 +21550,44 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
21330
21550
|
if (models.length === 0) {
|
|
21331
21551
|
throw new Error(`No models found on port ${port}`);
|
|
21332
21552
|
}
|
|
21333
|
-
|
|
21553
|
+
log125.info(`Cocoon Network ready \u2014 ${models.length} model(s) on port ${port}`);
|
|
21334
21554
|
} catch (err) {
|
|
21335
|
-
|
|
21555
|
+
log125.error(
|
|
21336
21556
|
`Cocoon Network unavailable on port ${this.config.cocoon?.port ?? 1e4}: ${getErrorMessage(err)}`
|
|
21337
21557
|
);
|
|
21338
|
-
|
|
21339
|
-
|
|
21558
|
+
log125.error("Start the Cocoon client first: cocoon start");
|
|
21559
|
+
throw new Error(`Cocoon Network unavailable: ${getErrorMessage(err)}`);
|
|
21340
21560
|
}
|
|
21341
21561
|
}
|
|
21342
21562
|
if (this.config.agent.provider === "local" && !this.config.agent.base_url) {
|
|
21343
|
-
|
|
21344
|
-
|
|
21563
|
+
throw new Error(
|
|
21564
|
+
"Local provider requires base_url in config (e.g. http://localhost:11434/v1)"
|
|
21565
|
+
);
|
|
21345
21566
|
}
|
|
21346
21567
|
if (this.config.agent.provider === "local" && this.config.agent.base_url) {
|
|
21347
21568
|
try {
|
|
21348
21569
|
const { registerLocalModels } = await import("./client-3VWE7NC4.js");
|
|
21349
21570
|
const models = await registerLocalModels(this.config.agent.base_url);
|
|
21350
21571
|
if (models.length > 0) {
|
|
21351
|
-
|
|
21572
|
+
log125.info(`Discovered ${models.length} local model(s): ${models.join(", ")}`);
|
|
21352
21573
|
if (!this.config.agent.model || this.config.agent.model === "auto") {
|
|
21353
21574
|
this.config.agent.model = models[0];
|
|
21354
|
-
|
|
21575
|
+
log125.info(`Using local model: ${models[0]}`);
|
|
21355
21576
|
}
|
|
21356
21577
|
} else {
|
|
21357
|
-
|
|
21578
|
+
log125.warn("No models found on local LLM server \u2014 is it running?");
|
|
21358
21579
|
}
|
|
21359
21580
|
} catch (err) {
|
|
21360
|
-
|
|
21581
|
+
log125.error(
|
|
21361
21582
|
`Local LLM server unavailable at ${this.config.agent.base_url}: ${getErrorMessage(err)}`
|
|
21362
21583
|
);
|
|
21363
|
-
|
|
21364
|
-
|
|
21584
|
+
log125.error("Start the LLM server first (e.g. ollama serve)");
|
|
21585
|
+
throw new Error(`Local LLM server unavailable: ${getErrorMessage(err)}`);
|
|
21365
21586
|
}
|
|
21366
21587
|
}
|
|
21367
21588
|
await this.bridge.connect();
|
|
21368
21589
|
if (!this.bridge.isAvailable()) {
|
|
21369
|
-
|
|
21370
|
-
process.exit(1);
|
|
21590
|
+
throw new Error("Failed to connect to Telegram");
|
|
21371
21591
|
}
|
|
21372
21592
|
await this.resolveOwnerInfo();
|
|
21373
21593
|
const ownUserId = this.bridge.getOwnUserId();
|
|
@@ -21389,12 +21609,12 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
21389
21609
|
startedModules.push(mod);
|
|
21390
21610
|
}
|
|
21391
21611
|
} catch (error) {
|
|
21392
|
-
|
|
21612
|
+
log125.error({ err: error }, "\u274C Module start failed, cleaning up started modules");
|
|
21393
21613
|
for (const mod of startedModules.reverse()) {
|
|
21394
21614
|
try {
|
|
21395
21615
|
await mod.stop?.();
|
|
21396
21616
|
} catch (e) {
|
|
21397
|
-
|
|
21617
|
+
log125.error({ err: e }, `\u26A0\uFE0F Module "${mod.name}" cleanup failed`);
|
|
21398
21618
|
}
|
|
21399
21619
|
}
|
|
21400
21620
|
throw error;
|
|
@@ -21411,67 +21631,22 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
21411
21631
|
});
|
|
21412
21632
|
this.pluginWatcher.start();
|
|
21413
21633
|
}
|
|
21414
|
-
|
|
21415
|
-
|
|
21416
|
-
|
|
21417
|
-
|
|
21634
|
+
log125.info(`\u2705 SOUL.md loaded`);
|
|
21635
|
+
log125.info(`\u2705 Knowledge: ${indexResult.indexed} files, ${ftsResult.knowledge} chunks indexed`);
|
|
21636
|
+
log125.info(`\u2705 Telegram: @${username} connected`);
|
|
21637
|
+
log125.info(`\u2705 TON Blockchain: connected`);
|
|
21418
21638
|
if (this.config.tonapi_key) {
|
|
21419
|
-
|
|
21639
|
+
log125.info(`\u{1F511} TonAPI key configured`);
|
|
21420
21640
|
}
|
|
21421
|
-
|
|
21422
|
-
|
|
21423
|
-
|
|
21424
|
-
|
|
21425
|
-
|
|
21641
|
+
log125.info(`\u2705 DEXs: STON.fi, DeDust connected`);
|
|
21642
|
+
log125.info(`\u2705 Wallet: ${walletAddress || "not configured"}`);
|
|
21643
|
+
log125.info(`\u2705 Model: ${provider}/${this.config.agent.model}`);
|
|
21644
|
+
log125.info(`\u2705 Admins: ${this.config.telegram.admin_ids.join(", ")}`);
|
|
21645
|
+
log125.info(
|
|
21426
21646
|
`\u2705 Policy: DM ${this.config.telegram.dm_policy}, Groups ${this.config.telegram.group_policy}, Debounce ${this.config.telegram.debounce_ms}ms
|
|
21427
21647
|
`
|
|
21428
21648
|
);
|
|
21429
|
-
|
|
21430
|
-
if (this.config.webui.enabled) {
|
|
21431
|
-
try {
|
|
21432
|
-
const { WebUIServer } = await import("./server-OWVEZTR3.js");
|
|
21433
|
-
const mcpServers = Object.entries(this.config.mcp.servers).map(([name, serverConfig]) => {
|
|
21434
|
-
const type = serverConfig.command ? "stdio" : "sse";
|
|
21435
|
-
const target = serverConfig.command ?? serverConfig.url ?? "";
|
|
21436
|
-
const connected = this.mcpConnections.some((c2) => c2.serverName === name);
|
|
21437
|
-
const moduleName = `mcp_${name}`;
|
|
21438
|
-
const moduleTools = this.toolRegistry.getModuleTools(moduleName);
|
|
21439
|
-
return {
|
|
21440
|
-
name,
|
|
21441
|
-
type,
|
|
21442
|
-
target,
|
|
21443
|
-
scope: serverConfig.scope ?? "always",
|
|
21444
|
-
enabled: serverConfig.enabled ?? true,
|
|
21445
|
-
connected,
|
|
21446
|
-
toolCount: moduleTools.length,
|
|
21447
|
-
tools: moduleTools.map((t) => t.name),
|
|
21448
|
-
envKeys: Object.keys(serverConfig.env ?? {})
|
|
21449
|
-
};
|
|
21450
|
-
});
|
|
21451
|
-
this.webuiServer = new WebUIServer({
|
|
21452
|
-
agent: this.agent,
|
|
21453
|
-
bridge: this.bridge,
|
|
21454
|
-
memory: this.memory,
|
|
21455
|
-
toolRegistry: this.toolRegistry,
|
|
21456
|
-
plugins: this.modules.filter((m) => this.toolRegistry.isPluginModule(m.name)).map((m) => ({ name: m.name, version: m.version ?? "0.0.0" })),
|
|
21457
|
-
mcpServers,
|
|
21458
|
-
config: this.config.webui,
|
|
21459
|
-
configPath: this.configPath,
|
|
21460
|
-
marketplace: {
|
|
21461
|
-
modules: this.modules,
|
|
21462
|
-
config: this.config,
|
|
21463
|
-
sdkDeps: this.sdkDeps,
|
|
21464
|
-
pluginContext,
|
|
21465
|
-
loadedModuleNames: builtinNames,
|
|
21466
|
-
rewireHooks: () => this.wirePluginEventHooks()
|
|
21467
|
-
}
|
|
21468
|
-
});
|
|
21469
|
-
await this.webuiServer.start();
|
|
21470
|
-
} catch (error) {
|
|
21471
|
-
log124.error({ err: error }, "\u274C Failed to start WebUI server");
|
|
21472
|
-
log124.warn("\u26A0\uFE0F Continuing without WebUI...");
|
|
21473
|
-
}
|
|
21474
|
-
}
|
|
21649
|
+
log125.info("Teleton Agent is running! Press Ctrl+C to stop.");
|
|
21475
21650
|
this.debouncer = new MessageDebouncer(
|
|
21476
21651
|
{
|
|
21477
21652
|
debounceMs: this.config.telegram.debounce_ms
|
|
@@ -21492,18 +21667,16 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
21492
21667
|
}
|
|
21493
21668
|
},
|
|
21494
21669
|
(error, messages) => {
|
|
21495
|
-
|
|
21670
|
+
log125.error({ err: error }, `Error processing batch of ${messages.length} messages`);
|
|
21496
21671
|
}
|
|
21497
21672
|
);
|
|
21498
21673
|
this.bridge.onNewMessage(async (message) => {
|
|
21499
21674
|
try {
|
|
21500
21675
|
await this.debouncer.enqueue(message);
|
|
21501
21676
|
} catch (error) {
|
|
21502
|
-
|
|
21677
|
+
log125.error({ err: error }, "Error enqueueing message");
|
|
21503
21678
|
}
|
|
21504
21679
|
});
|
|
21505
|
-
await new Promise(() => {
|
|
21506
|
-
});
|
|
21507
21680
|
}
|
|
21508
21681
|
/**
|
|
21509
21682
|
* Resolve owner name and username from Telegram API if not already configured.
|
|
@@ -21546,10 +21719,10 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
21546
21719
|
writeRawConfig(raw, this.configPath);
|
|
21547
21720
|
const displayName = this.config.telegram.owner_name || "Unknown";
|
|
21548
21721
|
const displayUsername = this.config.telegram.owner_username ? ` (@${this.config.telegram.owner_username})` : "";
|
|
21549
|
-
|
|
21722
|
+
log125.info(`\u{1F464} Owner resolved: ${displayName}${displayUsername}`);
|
|
21550
21723
|
}
|
|
21551
21724
|
} catch (error) {
|
|
21552
|
-
|
|
21725
|
+
log125.warn(
|
|
21553
21726
|
`\u26A0\uFE0F Could not resolve owner info: ${error instanceof Error ? error.message : error}`
|
|
21554
21727
|
);
|
|
21555
21728
|
}
|
|
@@ -21617,7 +21790,7 @@ Task: "${taskDescription}"`;
|
|
|
21617
21790
|
if (this.adminHandler.isPaused()) return;
|
|
21618
21791
|
await this.messageHandler.handleMessage(message);
|
|
21619
21792
|
} catch (error) {
|
|
21620
|
-
|
|
21793
|
+
log125.error({ err: error }, "Error handling message");
|
|
21621
21794
|
}
|
|
21622
21795
|
}
|
|
21623
21796
|
/**
|
|
@@ -21627,19 +21800,19 @@ Task: "${taskDescription}"`;
|
|
|
21627
21800
|
const { getTaskStore } = await import("./tasks-QSCWSMPS.js");
|
|
21628
21801
|
const { executeScheduledTask } = await import("./task-executor-PD3H4MLO.js");
|
|
21629
21802
|
const { TaskDependencyResolver } = await import("./task-dependency-resolver-WKZWJLLM.js");
|
|
21630
|
-
const { getDatabase: getDatabase2 } = await import("./memory-
|
|
21803
|
+
const { getDatabase: getDatabase2 } = await import("./memory-5SS3Q5EA.js");
|
|
21631
21804
|
const db2 = getDatabase2().getDb();
|
|
21632
21805
|
const taskStore = getTaskStore(db2);
|
|
21633
21806
|
const match = message.text.match(/^\[TASK:([^\]]+)\]/);
|
|
21634
21807
|
if (!match) {
|
|
21635
|
-
|
|
21808
|
+
log125.warn(`Invalid task format: ${message.text}`);
|
|
21636
21809
|
return;
|
|
21637
21810
|
}
|
|
21638
21811
|
const taskId = match[1];
|
|
21639
21812
|
try {
|
|
21640
21813
|
const task = taskStore.getTask(taskId);
|
|
21641
21814
|
if (!task) {
|
|
21642
|
-
|
|
21815
|
+
log125.warn(`Task ${taskId} not found in database`);
|
|
21643
21816
|
await this.bridge.sendMessage({
|
|
21644
21817
|
chatId: message.chatId,
|
|
21645
21818
|
text: `\u26A0\uFE0F Task ${taskId} not found. It may have been deleted.`,
|
|
@@ -21648,11 +21821,11 @@ Task: "${taskDescription}"`;
|
|
|
21648
21821
|
return;
|
|
21649
21822
|
}
|
|
21650
21823
|
if (task.status === "cancelled" || task.status === "done" || task.status === "failed") {
|
|
21651
|
-
|
|
21824
|
+
log125.info(`\u23ED\uFE0F Task ${taskId} already ${task.status}, skipping`);
|
|
21652
21825
|
return;
|
|
21653
21826
|
}
|
|
21654
21827
|
if (!taskStore.canExecute(taskId)) {
|
|
21655
|
-
|
|
21828
|
+
log125.warn(`Task ${taskId} cannot execute yet - dependencies not satisfied`);
|
|
21656
21829
|
await this.bridge.sendMessage({
|
|
21657
21830
|
chatId: message.chatId,
|
|
21658
21831
|
text: `\u23F3 Task "${task.description}" is waiting for parent tasks to complete.`,
|
|
@@ -21701,13 +21874,13 @@ Task: "${taskDescription}"`;
|
|
|
21701
21874
|
});
|
|
21702
21875
|
}
|
|
21703
21876
|
taskStore.completeTask(taskId, response.content);
|
|
21704
|
-
|
|
21877
|
+
log125.info(`\u2705 Executed scheduled task ${taskId}: ${task.description}`);
|
|
21705
21878
|
if (!this.dependencyResolver) {
|
|
21706
21879
|
this.dependencyResolver = new TaskDependencyResolver(taskStore, this.bridge);
|
|
21707
21880
|
}
|
|
21708
21881
|
await this.dependencyResolver.onTaskComplete(taskId);
|
|
21709
21882
|
} catch (error) {
|
|
21710
|
-
|
|
21883
|
+
log125.error({ err: error }, "Error handling scheduled task");
|
|
21711
21884
|
try {
|
|
21712
21885
|
taskStore.failTask(taskId, getErrorMessage(error));
|
|
21713
21886
|
if (!this.dependencyResolver) {
|
|
@@ -21732,7 +21905,7 @@ Task: "${taskDescription}"`;
|
|
|
21732
21905
|
try {
|
|
21733
21906
|
await withHooks.onMessage(event);
|
|
21734
21907
|
} catch (err) {
|
|
21735
|
-
|
|
21908
|
+
log125.error(
|
|
21736
21909
|
`\u274C [${mod.name}] onMessage error: ${err instanceof Error ? err.message : err}`
|
|
21737
21910
|
);
|
|
21738
21911
|
}
|
|
@@ -21742,7 +21915,7 @@ Task: "${taskDescription}"`;
|
|
|
21742
21915
|
]);
|
|
21743
21916
|
const hookCount = this.modules.filter((m) => m.onMessage).length;
|
|
21744
21917
|
if (hookCount > 0) {
|
|
21745
|
-
|
|
21918
|
+
log125.info(`\u{1F517} ${hookCount} plugin onMessage hook(s) registered`);
|
|
21746
21919
|
}
|
|
21747
21920
|
if (!this.callbackHandlerRegistered) {
|
|
21748
21921
|
this.bridge.getClient().addCallbackQueryHandler(async (update) => {
|
|
@@ -21758,7 +21931,7 @@ Task: "${taskDescription}"`;
|
|
|
21758
21931
|
try {
|
|
21759
21932
|
await this.bridge.getClient().answerCallbackQuery(queryId, { message: text, alert });
|
|
21760
21933
|
} catch (err) {
|
|
21761
|
-
|
|
21934
|
+
log125.error(
|
|
21762
21935
|
`\u274C Failed to answer callback query: ${err instanceof Error ? err.message : err}`
|
|
21763
21936
|
);
|
|
21764
21937
|
}
|
|
@@ -21778,7 +21951,7 @@ Task: "${taskDescription}"`;
|
|
|
21778
21951
|
try {
|
|
21779
21952
|
await withHooks.onCallbackQuery(event);
|
|
21780
21953
|
} catch (err) {
|
|
21781
|
-
|
|
21954
|
+
log125.error(
|
|
21782
21955
|
`\u274C [${mod.name}] onCallbackQuery error: ${err instanceof Error ? err.message : err}`
|
|
21783
21956
|
);
|
|
21784
21957
|
}
|
|
@@ -21790,7 +21963,7 @@ Task: "${taskDescription}"`;
|
|
|
21790
21963
|
(m) => m.onCallbackQuery
|
|
21791
21964
|
).length;
|
|
21792
21965
|
if (cbCount > 0) {
|
|
21793
|
-
|
|
21966
|
+
log125.info(`\u{1F517} ${cbCount} plugin onCallbackQuery hook(s) registered`);
|
|
21794
21967
|
}
|
|
21795
21968
|
}
|
|
21796
21969
|
}
|
|
@@ -21798,56 +21971,63 @@ Task: "${taskDescription}"`;
|
|
|
21798
21971
|
* Stop the agent
|
|
21799
21972
|
*/
|
|
21800
21973
|
async stop() {
|
|
21801
|
-
|
|
21974
|
+
log125.info("\u{1F44B} Stopping Teleton AI...");
|
|
21975
|
+
await this.lifecycle.stop(() => this.stopAgent());
|
|
21802
21976
|
if (this.webuiServer) {
|
|
21803
21977
|
try {
|
|
21804
21978
|
await this.webuiServer.stop();
|
|
21805
21979
|
} catch (e) {
|
|
21806
|
-
|
|
21980
|
+
log125.error({ err: e }, "\u26A0\uFE0F WebUI stop failed");
|
|
21807
21981
|
}
|
|
21808
21982
|
}
|
|
21983
|
+
try {
|
|
21984
|
+
closeDatabase();
|
|
21985
|
+
} catch (e) {
|
|
21986
|
+
log125.error({ err: e }, "\u26A0\uFE0F Database close failed");
|
|
21987
|
+
}
|
|
21988
|
+
}
|
|
21989
|
+
/**
|
|
21990
|
+
* Stop agent subsystems (watcher, MCP, debouncer, handler, modules, bridge).
|
|
21991
|
+
* Called by lifecycle.stop() — do NOT call directly.
|
|
21992
|
+
*/
|
|
21993
|
+
async stopAgent() {
|
|
21809
21994
|
if (this.pluginWatcher) {
|
|
21810
21995
|
try {
|
|
21811
21996
|
await this.pluginWatcher.stop();
|
|
21812
21997
|
} catch (e) {
|
|
21813
|
-
|
|
21998
|
+
log125.error({ err: e }, "\u26A0\uFE0F Plugin watcher stop failed");
|
|
21814
21999
|
}
|
|
21815
22000
|
}
|
|
21816
22001
|
if (this.mcpConnections.length > 0) {
|
|
21817
22002
|
try {
|
|
21818
22003
|
await closeMcpServers(this.mcpConnections);
|
|
21819
22004
|
} catch (e) {
|
|
21820
|
-
|
|
22005
|
+
log125.error({ err: e }, "\u26A0\uFE0F MCP close failed");
|
|
21821
22006
|
}
|
|
21822
22007
|
}
|
|
21823
22008
|
if (this.debouncer) {
|
|
21824
22009
|
try {
|
|
21825
22010
|
await this.debouncer.flushAll();
|
|
21826
22011
|
} catch (e) {
|
|
21827
|
-
|
|
22012
|
+
log125.error({ err: e }, "\u26A0\uFE0F Debouncer flush failed");
|
|
21828
22013
|
}
|
|
21829
22014
|
}
|
|
21830
22015
|
try {
|
|
21831
22016
|
await this.messageHandler.drain();
|
|
21832
22017
|
} catch (e) {
|
|
21833
|
-
|
|
22018
|
+
log125.error({ err: e }, "\u26A0\uFE0F Message queue drain failed");
|
|
21834
22019
|
}
|
|
21835
22020
|
for (const mod of this.modules) {
|
|
21836
22021
|
try {
|
|
21837
22022
|
await mod.stop?.();
|
|
21838
22023
|
} catch (e) {
|
|
21839
|
-
|
|
22024
|
+
log125.error({ err: e }, `\u26A0\uFE0F Module "${mod.name}" stop failed`);
|
|
21840
22025
|
}
|
|
21841
22026
|
}
|
|
21842
22027
|
try {
|
|
21843
22028
|
await this.bridge.disconnect();
|
|
21844
22029
|
} catch (e) {
|
|
21845
|
-
|
|
21846
|
-
}
|
|
21847
|
-
try {
|
|
21848
|
-
closeDatabase();
|
|
21849
|
-
} catch (e) {
|
|
21850
|
-
log124.error({ err: e }, "\u26A0\uFE0F Database close failed");
|
|
22030
|
+
log125.error({ err: e }, "\u26A0\uFE0F Bridge disconnect failed");
|
|
21851
22031
|
}
|
|
21852
22032
|
}
|
|
21853
22033
|
};
|
|
@@ -21856,14 +22036,14 @@ async function main(configPath) {
|
|
|
21856
22036
|
try {
|
|
21857
22037
|
app = new TeletonApp(configPath);
|
|
21858
22038
|
} catch (error) {
|
|
21859
|
-
|
|
22039
|
+
log125.error(`Failed to initialize: ${error instanceof Error ? error.message : error}`);
|
|
21860
22040
|
process.exit(1);
|
|
21861
22041
|
}
|
|
21862
22042
|
process.on("unhandledRejection", (reason) => {
|
|
21863
|
-
|
|
22043
|
+
log125.error({ err: reason }, "\u26A0\uFE0F Unhandled promise rejection");
|
|
21864
22044
|
});
|
|
21865
22045
|
process.on("uncaughtException", (error) => {
|
|
21866
|
-
|
|
22046
|
+
log125.error({ err: error }, "\u{1F4A5} Uncaught exception");
|
|
21867
22047
|
process.exit(1);
|
|
21868
22048
|
});
|
|
21869
22049
|
let shutdownInProgress = false;
|
|
@@ -21871,7 +22051,7 @@ async function main(configPath) {
|
|
|
21871
22051
|
if (shutdownInProgress) return;
|
|
21872
22052
|
shutdownInProgress = true;
|
|
21873
22053
|
const forceExit = setTimeout(() => {
|
|
21874
|
-
|
|
22054
|
+
log125.error("\u26A0\uFE0F Shutdown timed out, forcing exit");
|
|
21875
22055
|
process.exit(1);
|
|
21876
22056
|
}, SHUTDOWN_TIMEOUT_MS);
|
|
21877
22057
|
forceExit.unref();
|
|
@@ -21885,7 +22065,7 @@ async function main(configPath) {
|
|
|
21885
22065
|
}
|
|
21886
22066
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
21887
22067
|
main().catch((error) => {
|
|
21888
|
-
|
|
22068
|
+
log125.fatal({ err: error }, "Fatal error");
|
|
21889
22069
|
process.exit(1);
|
|
21890
22070
|
});
|
|
21891
22071
|
}
|