@sulala/agent-os 0.1.32 → 0.1.34
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/dashboard-dist/assets/index-DLAqOiRu.css +1 -0
- package/dashboard-dist/assets/index-Dy8Huc2-.js +128 -0
- package/dashboard-dist/index.html +2 -2
- package/dist/cli.js +152 -19
- package/dist/index.js +146 -19
- package/package.json +1 -1
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<link rel="icon" type="image/png" href="/logo_dark.png" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>Sulala Agent Dashboard</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-Dy8Huc2-.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DLAqOiRu.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
package/dist/cli.js
CHANGED
|
@@ -154,6 +154,7 @@ async function readConfig() {
|
|
|
154
154
|
const openrouter_api_key = o.openrouter_api_key;
|
|
155
155
|
const telegram_bot_token = o.telegram_bot_token;
|
|
156
156
|
const telegram_default_agent_id = o.telegram_default_agent_id;
|
|
157
|
+
const telegram_report_chat_id = o.telegram_report_chat_id;
|
|
157
158
|
const slack_bot_token = o.slack_bot_token;
|
|
158
159
|
const slack_signing_secret = o.slack_signing_secret;
|
|
159
160
|
const slack_default_agent_id = o.slack_default_agent_id;
|
|
@@ -176,6 +177,7 @@ async function readConfig() {
|
|
|
176
177
|
openrouter_api_key: typeof openrouter_api_key === "string" ? openrouter_api_key : undefined,
|
|
177
178
|
telegram_bot_token: typeof telegram_bot_token === "string" ? telegram_bot_token : undefined,
|
|
178
179
|
telegram_default_agent_id: typeof telegram_default_agent_id === "string" ? telegram_default_agent_id : undefined,
|
|
180
|
+
telegram_report_chat_id: typeof telegram_report_chat_id === "string" ? telegram_report_chat_id.trim() || undefined : undefined,
|
|
179
181
|
slack_bot_token: typeof slack_bot_token === "string" ? slack_bot_token : undefined,
|
|
180
182
|
slack_signing_secret: typeof slack_signing_secret === "string" ? slack_signing_secret : undefined,
|
|
181
183
|
slack_default_agent_id: typeof slack_default_agent_id === "string" ? slack_default_agent_id : undefined,
|
|
@@ -225,6 +227,7 @@ async function writeConfig(updates) {
|
|
|
225
227
|
openrouter_api_key: updates.openrouter_api_key !== undefined ? updates.openrouter_api_key : current.openrouter_api_key,
|
|
226
228
|
telegram_bot_token: updates.telegram_bot_token !== undefined ? updates.telegram_bot_token : current.telegram_bot_token,
|
|
227
229
|
telegram_default_agent_id: updates.telegram_default_agent_id !== undefined ? updates.telegram_default_agent_id : current.telegram_default_agent_id,
|
|
230
|
+
telegram_report_chat_id: updates.telegram_report_chat_id !== undefined ? updates.telegram_report_chat_id : current.telegram_report_chat_id,
|
|
228
231
|
slack_bot_token: updates.slack_bot_token !== undefined ? updates.slack_bot_token : current.slack_bot_token,
|
|
229
232
|
slack_signing_secret: updates.slack_signing_secret !== undefined ? updates.slack_signing_secret : current.slack_signing_secret,
|
|
230
233
|
slack_default_agent_id: updates.slack_default_agent_id !== undefined ? updates.slack_default_agent_id : current.slack_default_agent_id,
|
|
@@ -251,6 +254,7 @@ async function writeConfig(updates) {
|
|
|
251
254
|
openrouter_api_key: merged.openrouter_api_key ?? null,
|
|
252
255
|
telegram_bot_token: merged.telegram_bot_token ?? null,
|
|
253
256
|
telegram_default_agent_id: merged.telegram_default_agent_id ?? null,
|
|
257
|
+
telegram_report_chat_id: merged.telegram_report_chat_id ?? null,
|
|
254
258
|
slack_bot_token: merged.slack_bot_token ?? null,
|
|
255
259
|
slack_signing_secret: merged.slack_signing_secret ?? null,
|
|
256
260
|
slack_default_agent_id: merged.slack_default_agent_id ?? null,
|
|
@@ -434,6 +438,7 @@ class MemoryStore {
|
|
|
434
438
|
this.migrateMemoriesEmbedding();
|
|
435
439
|
this.migrateAgentsScheduleEnabled();
|
|
436
440
|
this.migrateConversationsGraphId();
|
|
441
|
+
this.migrateAgentsScheduleReportTargets();
|
|
437
442
|
}
|
|
438
443
|
migrateMemoriesEmbedding() {
|
|
439
444
|
try {
|
|
@@ -450,6 +455,11 @@ class MemoryStore {
|
|
|
450
455
|
this.db.exec("ALTER TABLE conversations ADD COLUMN graph_id TEXT");
|
|
451
456
|
} catch {}
|
|
452
457
|
}
|
|
458
|
+
migrateAgentsScheduleReportTargets() {
|
|
459
|
+
try {
|
|
460
|
+
this.db.exec("ALTER TABLE agents ADD COLUMN schedule_report_targets TEXT");
|
|
461
|
+
} catch {}
|
|
462
|
+
}
|
|
453
463
|
insertMemory(args) {
|
|
454
464
|
const embeddingJson = args.embedding && args.embedding.length > 0 ? JSON.stringify(args.embedding) : null;
|
|
455
465
|
const stmt = this.db.prepare("INSERT INTO memories (user_id, agent_id, scope, text, tags, embedding) VALUES (?, ?, 'personal', ?, ?, ?)");
|
|
@@ -571,6 +581,7 @@ class MemoryStore {
|
|
|
571
581
|
schedule: row.schedule ?? undefined,
|
|
572
582
|
schedule_input: row.schedule_input ?? undefined,
|
|
573
583
|
schedule_enabled: row.schedule_enabled !== undefined ? Number(row.schedule_enabled) === 1 : true,
|
|
584
|
+
schedule_report_targets: row.schedule_report_targets ? JSON.parse(String(row.schedule_report_targets)) : undefined,
|
|
574
585
|
avatar: row.avatar ?? undefined,
|
|
575
586
|
user_created: Number(row.user_created) === 1,
|
|
576
587
|
limits: row.limits ? JSON.parse(String(row.limits)) : undefined
|
|
@@ -597,12 +608,13 @@ class MemoryStore {
|
|
|
597
608
|
const schedule = config.schedule != null ? String(config.schedule) : null;
|
|
598
609
|
const schedule_input = config.schedule_input != null ? String(config.schedule_input) : null;
|
|
599
610
|
const schedule_enabled = config.schedule_enabled === false ? 0 : 1;
|
|
611
|
+
const schedule_report_targets = config.schedule_report_targets != null ? JSON.stringify(config.schedule_report_targets) : null;
|
|
600
612
|
const avatar = config.avatar != null ? String(config.avatar) : null;
|
|
601
613
|
const user_created = config.user_created === true ? 1 : 0;
|
|
602
614
|
const limits = config.limits != null ? JSON.stringify(config.limits) : null;
|
|
603
|
-
const stmt = this.db.prepare(`INSERT INTO agents (id, name, model, description, personality, skills, tools, schedule, schedule_input, schedule_enabled, avatar, user_created, limits)
|
|
604
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
605
|
-
stmt.run(id, name, model, description, personality, skills, tools, schedule, schedule_input, schedule_enabled, avatar, user_created, limits);
|
|
615
|
+
const stmt = this.db.prepare(`INSERT INTO agents (id, name, model, description, personality, skills, tools, schedule, schedule_input, schedule_enabled, schedule_report_targets, avatar, user_created, limits)
|
|
616
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
617
|
+
stmt.run(id, name, model, description, personality, skills, tools, schedule, schedule_input, schedule_enabled, schedule_report_targets, avatar, user_created, limits);
|
|
606
618
|
}
|
|
607
619
|
updateAgent(id, updates) {
|
|
608
620
|
const agent = this.getAgentById(id);
|
|
@@ -619,8 +631,9 @@ class MemoryStore {
|
|
|
619
631
|
const schedule_input = updates.schedule_input !== undefined ? updates.schedule_input && String(updates.schedule_input).trim() ? String(updates.schedule_input).trim() : null : agent.schedule_input;
|
|
620
632
|
const avatar = updates.avatar !== undefined ? updates.avatar && String(updates.avatar).trim() ? String(updates.avatar).trim() : null : agent.avatar;
|
|
621
633
|
const schedule_enabled = updates.schedule_enabled !== undefined && updates.schedule_enabled !== null ? updates.schedule_enabled ? 1 : 0 : agent.schedule_enabled === true || agent.schedule_enabled === 1 ? 1 : 0;
|
|
622
|
-
const
|
|
623
|
-
stmt.
|
|
634
|
+
const schedule_report_targets = updates.schedule_report_targets !== undefined ? updates.schedule_report_targets?.length ? JSON.stringify(updates.schedule_report_targets) : null : agent.schedule_report_targets != null ? typeof agent.schedule_report_targets === "string" ? agent.schedule_report_targets : JSON.stringify(agent.schedule_report_targets) : null;
|
|
635
|
+
const stmt = this.db.prepare("UPDATE agents SET name = ?, model = ?, description = ?, personality = ?, skills = ?, tools = ?, limits = ?, schedule = ?, schedule_input = ?, avatar = ?, schedule_enabled = ?, schedule_report_targets = ?, updated_at = datetime('now') WHERE id = ?");
|
|
636
|
+
stmt.run(name, model, description, personality, skills, tools, limits, schedule, schedule_input, avatar, schedule_enabled, schedule_report_targets, id);
|
|
624
637
|
}
|
|
625
638
|
deleteAgent(id) {
|
|
626
639
|
const agent = this.getAgentById(id);
|
|
@@ -682,6 +695,9 @@ function validateAgentConfig(raw) {
|
|
|
682
695
|
} else if (obj.schedule_enabled === true) {
|
|
683
696
|
config.schedule_enabled = true;
|
|
684
697
|
}
|
|
698
|
+
if (Array.isArray(obj.schedule_report_targets)) {
|
|
699
|
+
config.schedule_report_targets = obj.schedule_report_targets.filter((t) => t && typeof t === "object" && t.channel === "telegram" && typeof t.address === "string" && String(t.address).trim() !== "").map((t) => ({ channel: "telegram", address: String(t.address).trim() }));
|
|
700
|
+
}
|
|
685
701
|
if (obj.avatar != null && typeof obj.avatar === "string" && obj.avatar.trim()) {
|
|
686
702
|
config.avatar = obj.avatar.trim();
|
|
687
703
|
}
|
|
@@ -932,6 +948,9 @@ async function updateAgent(id, updates) {
|
|
|
932
948
|
if (updates.schedule_enabled !== undefined && updates.schedule_enabled !== null) {
|
|
933
949
|
parsed.schedule_enabled = updates.schedule_enabled;
|
|
934
950
|
}
|
|
951
|
+
if (updates.schedule_report_targets !== undefined) {
|
|
952
|
+
parsed.schedule_report_targets = updates.schedule_report_targets ?? undefined;
|
|
953
|
+
}
|
|
935
954
|
const agent = parseAgentConfig(parsed);
|
|
936
955
|
await writeFile2(path, JSON.stringify(parsed, null, 2), "utf-8");
|
|
937
956
|
return agent;
|
|
@@ -23739,21 +23758,25 @@ function buildSystemPrompt(agent, hasTools, skillDocContext, workspaceContext, d
|
|
|
23739
23758
|
parts.push("Answer the user's task concisely.");
|
|
23740
23759
|
const skillList = agent.skills?.length ? agent.skills.join(", ") : "none (built-in tools only)";
|
|
23741
23760
|
parts.push(`Your skills: ${skillList}.`);
|
|
23742
|
-
parts.push("If
|
|
23761
|
+
parts.push("If a skill in your list above can fulfill the user's request, you MUST use it (via the exec tool or the skill's request tool as described in the skill documentation below). Do not claim you lack that capability.");
|
|
23762
|
+
parts.push("Only when no skill in your list can provide the requested capability: reply briefly that you don't have that skill and that they can install it from the addon store (Dashboard \u2192 Skills \u2192 install from store) and add it to this agent. Do not suggest installing when you already have a skill that can do it.");
|
|
23743
23763
|
if (delegateableAgents?.length) {
|
|
23744
|
-
parts.push(
|
|
23764
|
+
parts.push("You have the run_agent tool. When the user asks for something another agent can do, tell the user in natural language that you are delegating to another agent, then use run_agent with that agent's id and the task. After they finish, reply with a short, friendly summary of what was done and the outcome.");
|
|
23745
23765
|
parts.push("Available agents to delegate to (use run_agent with agent_id and task): " + delegateableAgents.map((a) => `${a.id} (${a.name})`).join(", ") + ".");
|
|
23746
23766
|
const memoryAgentIds = delegateableAgents.filter((a) => a.skills?.includes("memory")).map((a) => a.id);
|
|
23747
23767
|
if (memoryAgentIds.length) {
|
|
23748
|
-
parts.push(`Agents with long-term memory (use for remember/save requests): ${memoryAgentIds.join(", ")}. When the user asks to remember something
|
|
23768
|
+
parts.push(`Agents with long-term memory (use for remember/save requests): ${memoryAgentIds.join(", ")}. When the user asks to remember something or save a fact, use run_agent with one of these agents and a task like "Remember that [fact]" or "Save: [fact]". Do not say you cannot save\u2014delegate to an agent that has memory.`);
|
|
23749
23769
|
}
|
|
23750
23770
|
}
|
|
23751
23771
|
if (hasTools) {
|
|
23752
23772
|
parts.push("You have access to tools. Use them when helpful to answer the user.");
|
|
23753
|
-
parts.push(`Your agent id is "${agent.id}". When a skill requires agent_id
|
|
23773
|
+
parts.push(`Your agent id is "${agent.id}". When a skill requires agent_id in the request body, use this value.`);
|
|
23754
23774
|
parts.push("After using tools, always reply with a brief summary for the user; never end with only tool calls.");
|
|
23755
23775
|
if (skillDocContext?.includes("_request")) {
|
|
23756
|
-
parts.push("When the user asks for something a skill handles
|
|
23776
|
+
parts.push("When the user asks for something a skill handles, use that skill's request tool (the one whose id ends with _request) with method, path, and body from the skill documentation below. Do not use echo, memory_search, or memory_write for skill-specific actions\u2014use the skill's request tool as described in the documentation.");
|
|
23777
|
+
}
|
|
23778
|
+
if (skillDocContext?.includes("exec") && skillDocContext?.includes("skill_id")) {
|
|
23779
|
+
parts.push("When the skill documentation below shows commands to run (e.g. scripts), use the exec tool with skill_id set to that skill and command set to the exact command from the doc.");
|
|
23757
23780
|
}
|
|
23758
23781
|
}
|
|
23759
23782
|
if (skillDocContext) {
|
|
@@ -23761,7 +23784,7 @@ function buildSystemPrompt(agent, hasTools, skillDocContext, workspaceContext, d
|
|
|
23761
23784
|
|
|
23762
23785
|
# Skill documentation
|
|
23763
23786
|
|
|
23764
|
-
Use the
|
|
23787
|
+
Use the documentation below to call skill APIs: for request-style tools use method, path, query, and body; for script-style skills use exec with skill_id and the command.
|
|
23765
23788
|
|
|
23766
23789
|
` + skillDocContext);
|
|
23767
23790
|
}
|
|
@@ -26231,7 +26254,7 @@ async function getTaskById(id) {
|
|
|
26231
26254
|
const task = await memoryTaskStore.getById(id);
|
|
26232
26255
|
return task ?? undefined;
|
|
26233
26256
|
}
|
|
26234
|
-
async function enqueueTask(agent_id, input) {
|
|
26257
|
+
async function enqueueTask(agent_id, input, scheduled_run = false) {
|
|
26235
26258
|
const id = randomUUID();
|
|
26236
26259
|
const t = {
|
|
26237
26260
|
id,
|
|
@@ -26239,12 +26262,13 @@ async function enqueueTask(agent_id, input) {
|
|
|
26239
26262
|
input,
|
|
26240
26263
|
status: "queued",
|
|
26241
26264
|
created_at: nowIso(),
|
|
26242
|
-
updated_at: nowIso()
|
|
26265
|
+
updated_at: nowIso(),
|
|
26266
|
+
...scheduled_run && { scheduled_run: true }
|
|
26243
26267
|
};
|
|
26244
26268
|
await memoryTaskStore.enqueue(t);
|
|
26245
26269
|
return t;
|
|
26246
26270
|
}
|
|
26247
|
-
async function enqueueGraphTask(graph_id, input) {
|
|
26271
|
+
async function enqueueGraphTask(graph_id, input, scheduled_run = false) {
|
|
26248
26272
|
const id = randomUUID();
|
|
26249
26273
|
const t = {
|
|
26250
26274
|
id,
|
|
@@ -26252,7 +26276,8 @@ async function enqueueGraphTask(graph_id, input) {
|
|
|
26252
26276
|
input,
|
|
26253
26277
|
status: "queued",
|
|
26254
26278
|
created_at: nowIso(),
|
|
26255
|
-
updated_at: nowIso()
|
|
26279
|
+
updated_at: nowIso(),
|
|
26280
|
+
...scheduled_run && { scheduled_run: true }
|
|
26256
26281
|
};
|
|
26257
26282
|
await memoryTaskStore.enqueue(t);
|
|
26258
26283
|
return t;
|
|
@@ -26272,7 +26297,7 @@ function startScheduler(store = memoryTaskStore) {
|
|
|
26272
26297
|
const current = await loadAgents();
|
|
26273
26298
|
const a = current.find((x) => x.id === agentId);
|
|
26274
26299
|
const input = a?.schedule_input?.trim() || "Scheduled run";
|
|
26275
|
-
await enqueueTask(agentId, input);
|
|
26300
|
+
await enqueueTask(agentId, input, true);
|
|
26276
26301
|
});
|
|
26277
26302
|
}
|
|
26278
26303
|
const graphSummaries = await listGraphs();
|
|
@@ -26284,7 +26309,7 @@ function startScheduler(store = memoryTaskStore) {
|
|
|
26284
26309
|
import_node_cron.default.schedule(graph.schedule, async () => {
|
|
26285
26310
|
const g = await loadGraph(gid);
|
|
26286
26311
|
const input = g?.schedule_input?.trim() || "Scheduled run";
|
|
26287
|
-
await enqueueGraphTask(gid, input);
|
|
26312
|
+
await enqueueGraphTask(gid, input, true);
|
|
26288
26313
|
});
|
|
26289
26314
|
}
|
|
26290
26315
|
} catch (err) {
|
|
@@ -26770,6 +26795,7 @@ async function handleSettings(req) {
|
|
|
26770
26795
|
has_openrouter_key: Boolean(config2.openrouter_api_key?.trim()),
|
|
26771
26796
|
telegram_configured: Boolean(config2.telegram_bot_token?.trim()),
|
|
26772
26797
|
telegram_default_agent_id: config2.telegram_default_agent_id ?? null,
|
|
26798
|
+
telegram_report_chat_id: config2.telegram_report_chat_id ?? null,
|
|
26773
26799
|
slack_configured: Boolean(config2.slack_bot_token?.trim()),
|
|
26774
26800
|
slack_default_agent_id: config2.slack_default_agent_id ?? null,
|
|
26775
26801
|
discord_configured: Boolean(config2.discord_bot_token?.trim()),
|
|
@@ -26798,6 +26824,7 @@ async function handleSettings(req) {
|
|
|
26798
26824
|
const openrouter_api_key = body.openrouter_api_key !== undefined ? typeof body.openrouter_api_key === "string" ? body.openrouter_api_key.trim() || undefined : undefined : current.openrouter_api_key;
|
|
26799
26825
|
const telegram_bot_token = body.telegram_bot_token !== undefined ? typeof body.telegram_bot_token === "string" ? body.telegram_bot_token.trim() : undefined : current.telegram_bot_token;
|
|
26800
26826
|
const telegram_default_agent_id = body.telegram_default_agent_id !== undefined ? typeof body.telegram_default_agent_id === "string" ? body.telegram_default_agent_id.trim() || undefined : undefined : current.telegram_default_agent_id;
|
|
26827
|
+
const telegram_report_chat_id = body.telegram_report_chat_id !== undefined ? typeof body.telegram_report_chat_id === "string" ? body.telegram_report_chat_id.trim() || undefined : undefined : current.telegram_report_chat_id;
|
|
26801
26828
|
const slack_bot_token = body.slack_bot_token !== undefined ? typeof body.slack_bot_token === "string" ? body.slack_bot_token.trim() : undefined : current.slack_bot_token;
|
|
26802
26829
|
const slack_signing_secret = body.slack_signing_secret !== undefined ? typeof body.slack_signing_secret === "string" ? body.slack_signing_secret.trim() : undefined : current.slack_signing_secret;
|
|
26803
26830
|
const slack_default_agent_id = body.slack_default_agent_id !== undefined ? typeof body.slack_default_agent_id === "string" ? body.slack_default_agent_id.trim() || undefined : undefined : current.slack_default_agent_id;
|
|
@@ -26818,6 +26845,7 @@ async function handleSettings(req) {
|
|
|
26818
26845
|
openrouter_api_key: openrouter_api_key ?? undefined,
|
|
26819
26846
|
telegram_bot_token: telegram_bot_token || undefined,
|
|
26820
26847
|
telegram_default_agent_id: telegram_default_agent_id || undefined,
|
|
26848
|
+
telegram_report_chat_id: telegram_report_chat_id ?? undefined,
|
|
26821
26849
|
slack_bot_token: slack_bot_token || undefined,
|
|
26822
26850
|
slack_signing_secret: slack_signing_secret ?? undefined,
|
|
26823
26851
|
slack_default_agent_id: slack_default_agent_id || undefined,
|
|
@@ -27416,6 +27444,11 @@ async function processTelegramUpdate(memoryStore, body) {
|
|
|
27416
27444
|
const botToken = config2.telegram_bot_token?.trim();
|
|
27417
27445
|
if (!botToken)
|
|
27418
27446
|
return;
|
|
27447
|
+
if (text === "/set_report_chat" || text === "/setreportchat") {
|
|
27448
|
+
await writeConfig({ telegram_report_chat_id: String(chatId) });
|
|
27449
|
+
await sendTelegramMessage(botToken, chatId, "\u2713 This chat will receive schedule reports. You can change it anytime by sending /set_report_chat from another chat.");
|
|
27450
|
+
return;
|
|
27451
|
+
}
|
|
27419
27452
|
const agent = await getDefaultAgent(config2, "telegram_default_agent_id");
|
|
27420
27453
|
if (!agent) {
|
|
27421
27454
|
await sendTelegramMessage(botToken, chatId, "No agent configured. Set default agent in Settings.");
|
|
@@ -30291,6 +30324,100 @@ var init_viber = __esm(() => {
|
|
|
30291
30324
|
init_channel_run();
|
|
30292
30325
|
});
|
|
30293
30326
|
|
|
30327
|
+
// src/core/schedule-reports.ts
|
|
30328
|
+
function buildReportMessage(task, label) {
|
|
30329
|
+
const status = task.status === "completed" ? "\u2705 Completed" : "\u274C Failed";
|
|
30330
|
+
const output = task.result?.output?.trim() ?? "";
|
|
30331
|
+
const error2 = task.result?.error?.trim() ?? "";
|
|
30332
|
+
const body = task.status === "completed" ? output : error2 || output;
|
|
30333
|
+
const truncated = body.length > MAX_REPORT_LENGTH ? body.slice(0, MAX_REPORT_LENGTH) + "\u2026" : body;
|
|
30334
|
+
return [
|
|
30335
|
+
`[Schedule report] ${label}`,
|
|
30336
|
+
`Status: ${status}`,
|
|
30337
|
+
truncated ? `
|
|
30338
|
+
${truncated}` : ""
|
|
30339
|
+
].join(`
|
|
30340
|
+
`).trim();
|
|
30341
|
+
}
|
|
30342
|
+
async function sendTelegramReport(botToken, chatId, text) {
|
|
30343
|
+
console.log("[schedule-reports] Sending to Telegram chat_id:", chatId, "message length:", text.length);
|
|
30344
|
+
const url = `https://api.telegram.org/bot${botToken}/sendMessage`;
|
|
30345
|
+
const res = await fetch(url, {
|
|
30346
|
+
method: "POST",
|
|
30347
|
+
headers: { "Content-Type": "application/json" },
|
|
30348
|
+
body: JSON.stringify({
|
|
30349
|
+
chat_id: chatId,
|
|
30350
|
+
text: text.slice(0, 4096)
|
|
30351
|
+
})
|
|
30352
|
+
});
|
|
30353
|
+
if (res.ok) {
|
|
30354
|
+
console.log("[schedule-reports] Telegram sendMessage OK for chat_id:", chatId);
|
|
30355
|
+
} else {
|
|
30356
|
+
const err = await res.text();
|
|
30357
|
+
console.error("[schedule-reports] Telegram sendMessage failed:", res.status, "chat_id:", chatId, "error:", err);
|
|
30358
|
+
}
|
|
30359
|
+
}
|
|
30360
|
+
async function handleTaskFinished(event) {
|
|
30361
|
+
const task = event.data.task;
|
|
30362
|
+
console.log("[schedule-reports] handleTaskFinished task_id:", task.id, "status:", task.status, "scheduled_run:", task.scheduled_run, "agent_id:", task.agent_id, "graph_id:", task.graph_id);
|
|
30363
|
+
const targets = [];
|
|
30364
|
+
let label;
|
|
30365
|
+
if (task.agent_id) {
|
|
30366
|
+
const agent = await getAgent(task.agent_id);
|
|
30367
|
+
if (!agent?.schedule_report_targets?.length) {
|
|
30368
|
+
console.log("[schedule-reports] Agent", task.agent_id, "has no schedule_report_targets; skipping.");
|
|
30369
|
+
return;
|
|
30370
|
+
}
|
|
30371
|
+
targets.push(...agent.schedule_report_targets.filter((t) => t.channel === "telegram"));
|
|
30372
|
+
label = `Agent "${agent.name}" (${task.agent_id})`;
|
|
30373
|
+
} else if (task.graph_id) {
|
|
30374
|
+
const graph = await loadGraph(task.graph_id);
|
|
30375
|
+
if (!graph?.schedule_report_targets?.length) {
|
|
30376
|
+
console.log("[schedule-reports] Graph", task.graph_id, "has no schedule_report_targets; skipping.");
|
|
30377
|
+
return;
|
|
30378
|
+
}
|
|
30379
|
+
targets.push(...graph.schedule_report_targets.filter((t) => t.channel === "telegram"));
|
|
30380
|
+
label = `Graph "${task.graph_id}"`;
|
|
30381
|
+
} else {
|
|
30382
|
+
return;
|
|
30383
|
+
}
|
|
30384
|
+
if (targets.length === 0)
|
|
30385
|
+
return;
|
|
30386
|
+
const config2 = await readConfig();
|
|
30387
|
+
const botToken = config2.telegram_bot_token?.trim();
|
|
30388
|
+
if (!botToken) {
|
|
30389
|
+
console.warn("[schedule-reports] Telegram bot token not configured; skipping report.");
|
|
30390
|
+
return;
|
|
30391
|
+
}
|
|
30392
|
+
const defaultChatId = config2.telegram_report_chat_id?.trim();
|
|
30393
|
+
console.log("[schedule-reports] Sending report for", label, "targets:", targets.length, "defaultChatId from config:", defaultChatId ?? "(not set)");
|
|
30394
|
+
const message = buildReportMessage(task, label);
|
|
30395
|
+
for (const t of targets) {
|
|
30396
|
+
const address = t.address.trim();
|
|
30397
|
+
if (!address)
|
|
30398
|
+
continue;
|
|
30399
|
+
const chatId = address === "__default__" ? defaultChatId : address;
|
|
30400
|
+
if (!chatId) {
|
|
30401
|
+
if (address === "__default__") {
|
|
30402
|
+
console.warn("[schedule-reports] Schedule report target is 'from Settings' but no Telegram report chat is set. Send /set_report_chat to your bot in Telegram, then set it in Settings > Telegram.");
|
|
30403
|
+
}
|
|
30404
|
+
continue;
|
|
30405
|
+
}
|
|
30406
|
+
await sendTelegramReport(botToken, chatId, message);
|
|
30407
|
+
}
|
|
30408
|
+
}
|
|
30409
|
+
function initScheduleReports() {
|
|
30410
|
+
subscribe("task.completed", (event) => handleTaskFinished(event));
|
|
30411
|
+
subscribe("task.failed", (event) => handleTaskFinished(event));
|
|
30412
|
+
}
|
|
30413
|
+
var MAX_REPORT_LENGTH = 4000;
|
|
30414
|
+
var init_schedule_reports = __esm(() => {
|
|
30415
|
+
init_events();
|
|
30416
|
+
init_config();
|
|
30417
|
+
init_agent_registry();
|
|
30418
|
+
init_graphs();
|
|
30419
|
+
});
|
|
30420
|
+
|
|
30294
30421
|
// src/core/plugins.ts
|
|
30295
30422
|
import { readdir as readdir5, stat as stat2 } from "fs/promises";
|
|
30296
30423
|
import { join as join12 } from "path";
|
|
@@ -30497,6 +30624,7 @@ function createRoutes() {
|
|
|
30497
30624
|
schedule: a.schedule ?? null,
|
|
30498
30625
|
schedule_input: a.schedule_input ?? null,
|
|
30499
30626
|
schedule_enabled: a.schedule_enabled ?? true,
|
|
30627
|
+
schedule_report_targets: a.schedule_report_targets ?? null,
|
|
30500
30628
|
skills: a.skills ?? [],
|
|
30501
30629
|
tools: a.tools ?? [],
|
|
30502
30630
|
avatar: a.avatar ?? null,
|
|
@@ -30558,7 +30686,8 @@ function createRoutes() {
|
|
|
30558
30686
|
schedule: body.schedule,
|
|
30559
30687
|
schedule_input: body.schedule_input,
|
|
30560
30688
|
avatar: body.avatar,
|
|
30561
|
-
schedule_enabled: body.schedule_enabled
|
|
30689
|
+
schedule_enabled: body.schedule_enabled,
|
|
30690
|
+
schedule_report_targets: Array.isArray(body.schedule_report_targets) ? body.schedule_report_targets : undefined
|
|
30562
30691
|
});
|
|
30563
30692
|
return jsonResponse({
|
|
30564
30693
|
ok: true,
|
|
@@ -30573,6 +30702,7 @@ function createRoutes() {
|
|
|
30573
30702
|
schedule: agent.schedule ?? null,
|
|
30574
30703
|
schedule_input: agent.schedule_input ?? null,
|
|
30575
30704
|
schedule_enabled: agent.schedule_enabled ?? true,
|
|
30705
|
+
schedule_report_targets: agent.schedule_report_targets ?? null,
|
|
30576
30706
|
avatar: agent.avatar ?? null,
|
|
30577
30707
|
limits: agent.limits ?? null
|
|
30578
30708
|
}
|
|
@@ -30664,7 +30794,8 @@ function createRoutes() {
|
|
|
30664
30794
|
edges: Array.isArray(body.edges) ? body.edges : existing?.edges ?? [],
|
|
30665
30795
|
schedule: body.schedule !== undefined ? body.schedule && String(body.schedule).trim() ? String(body.schedule).trim() : undefined : existing?.schedule,
|
|
30666
30796
|
schedule_input: body.schedule_input !== undefined ? body.schedule_input && String(body.schedule_input).trim() ? String(body.schedule_input).trim() : undefined : existing?.schedule_input,
|
|
30667
|
-
schedule_enabled: body.schedule_enabled !== undefined ? body.schedule_enabled : existing?.schedule_enabled !== false
|
|
30797
|
+
schedule_enabled: body.schedule_enabled !== undefined ? body.schedule_enabled : existing?.schedule_enabled !== false,
|
|
30798
|
+
schedule_report_targets: body.schedule_report_targets !== undefined ? Array.isArray(body.schedule_report_targets) ? body.schedule_report_targets.filter((t) => t?.channel === "telegram" && typeof t?.address === "string").map((t) => ({ channel: "telegram", address: String(t.address).trim() })).filter((t) => t.address.length > 0) : undefined : existing?.schedule_report_targets
|
|
30668
30799
|
};
|
|
30669
30800
|
if (!graph.nodes.length) {
|
|
30670
30801
|
return jsonResponse({ error: "Graph must have at least one node" }, 400);
|
|
@@ -30989,6 +31120,7 @@ var init_server = __esm(() => {
|
|
|
30989
31120
|
init_config();
|
|
30990
31121
|
init_tasks();
|
|
30991
31122
|
init_events();
|
|
31123
|
+
init_schedule_reports();
|
|
30992
31124
|
init_graphs();
|
|
30993
31125
|
init_plugins();
|
|
30994
31126
|
init_loader();
|
|
@@ -31021,6 +31153,7 @@ var init_server = __esm(() => {
|
|
|
31021
31153
|
for (const type of EVENT_TYPES) {
|
|
31022
31154
|
subscribe(type, broadcastEvent);
|
|
31023
31155
|
}
|
|
31156
|
+
initScheduleReports();
|
|
31024
31157
|
});
|
|
31025
31158
|
|
|
31026
31159
|
// src/cli.ts
|