0agent 1.0.43 → 1.0.44
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/bin/chat.js +31 -3
- package/dist/daemon.mjs +277 -7
- package/package.json +1 -1
package/bin/chat.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* /model to switch. /key to add provider keys. Never forgets previous keys.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { createInterface, emitKeypressEvents, moveCursor, clearLine } from 'node:readline';
|
|
10
|
+
import { createInterface, emitKeypressEvents, moveCursor, clearLine as rlClearLine } from 'node:readline';
|
|
11
11
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
12
12
|
import { resolve } from 'node:path';
|
|
13
13
|
import { homedir } from 'node:os';
|
|
@@ -31,6 +31,7 @@ const SLASH_COMMANDS = [
|
|
|
31
31
|
{ cmd: '/security-audit',desc: 'Security audit — find vulnerabilities' },
|
|
32
32
|
{ cmd: '/design-review', desc: 'Design review — architecture and patterns' },
|
|
33
33
|
// Built-ins
|
|
34
|
+
{ cmd: '/telegram', desc: 'Connect Telegram bot — forward messages to 0agent'},
|
|
34
35
|
{ cmd: '/model', desc: 'Show or switch the LLM model' },
|
|
35
36
|
{ cmd: '/key', desc: 'Update a stored API key' },
|
|
36
37
|
{ cmd: '/status', desc: 'Daemon health, graph stats, active sessions' },
|
|
@@ -754,6 +755,33 @@ async function handleCommand(input) {
|
|
|
754
755
|
break;
|
|
755
756
|
}
|
|
756
757
|
|
|
758
|
+
// /telegram — configure Telegram bot token
|
|
759
|
+
case '/telegram': {
|
|
760
|
+
if (!cfg) { console.log(fmt(C.red, ' No config found. Run: 0agent init')); break; }
|
|
761
|
+
const existingToken = cfg?.telegram?.token;
|
|
762
|
+
if (existingToken) {
|
|
763
|
+
console.log(`\n Telegram bot: ${fmt(C.green, '✓ configured')}`);
|
|
764
|
+
console.log(` Token: ${existingToken.slice(0, 10)}••••`);
|
|
765
|
+
console.log(` ${fmt(C.dim, 'To update: /telegram <new-token>\n')}`);
|
|
766
|
+
}
|
|
767
|
+
const token = parts[1];
|
|
768
|
+
if (!token) {
|
|
769
|
+
if (!existingToken) {
|
|
770
|
+
console.log('\n Connect your Telegram bot to 0agent:\n');
|
|
771
|
+
console.log(` 1. Create a bot: ${fmt(C.cyan, 'https://t.me/BotFather')} → /newbot`);
|
|
772
|
+
console.log(` 2. Copy the token and run: ${fmt(C.cyan, '/telegram <token>')}`);
|
|
773
|
+
console.log(` 3. Restart daemon: ${fmt(C.dim, '0agent stop && 0agent start')}\n`);
|
|
774
|
+
}
|
|
775
|
+
break;
|
|
776
|
+
}
|
|
777
|
+
if (!cfg.telegram) cfg.telegram = {};
|
|
778
|
+
cfg.telegram.token = token;
|
|
779
|
+
saveConfig(cfg);
|
|
780
|
+
console.log(` ${fmt(C.green, '✓')} Telegram token saved`);
|
|
781
|
+
console.log(` ${fmt(C.dim, 'Restart daemon for changes to take effect: 0agent stop && 0agent start\n')}`);
|
|
782
|
+
break;
|
|
783
|
+
}
|
|
784
|
+
|
|
757
785
|
case '/skills': {
|
|
758
786
|
try {
|
|
759
787
|
const skills = await fetch(`${BASE_URL}/api/skills`).then(r => r.json());
|
|
@@ -831,7 +859,7 @@ function _drawMenu(filter) {
|
|
|
831
859
|
if (existingLines > 0) {
|
|
832
860
|
moveCursor(process.stdout, 0, existingLines);
|
|
833
861
|
for (let i = 0; i < existingLines; i++) {
|
|
834
|
-
|
|
862
|
+
rlClearLine(process.stdout, 0);
|
|
835
863
|
if (i < existingLines - 1) moveCursor(process.stdout, 0, -1);
|
|
836
864
|
}
|
|
837
865
|
moveCursor(process.stdout, 0, -(existingLines - 1));
|
|
@@ -859,7 +887,7 @@ function _clearMenu() {
|
|
|
859
887
|
_menuLines = 0;
|
|
860
888
|
moveCursor(process.stdout, 0, n);
|
|
861
889
|
for (let i = 0; i < n; i++) {
|
|
862
|
-
|
|
890
|
+
rlClearLine(process.stdout, 0);
|
|
863
891
|
moveCursor(process.stdout, 0, -1);
|
|
864
892
|
}
|
|
865
893
|
moveCursor(process.stdout, 0, 1); // back to prompt line
|
package/dist/daemon.mjs
CHANGED
|
@@ -3027,13 +3027,19 @@ content = element.text if element else page.get_all_text()` : `content = page.ge
|
|
|
3027
3027
|
`- Be concise in your final response: state what was done and where to find it`,
|
|
3028
3028
|
...hasMemory ? [
|
|
3029
3029
|
``,
|
|
3030
|
-
`Memory (
|
|
3031
|
-
`-
|
|
3032
|
-
` \xB7
|
|
3030
|
+
`Memory (CRITICAL \u2014 write EVERYTHING you learn):`,
|
|
3031
|
+
`- Call memory_write for ANY fact you discover \u2014 conversational OR from tools:`,
|
|
3032
|
+
` \xB7 User's name/identity: memory_write({label:"user_name", content:"Sahil", type:"identity"})`,
|
|
3033
|
+
` \xB7 Projects they mention: memory_write({label:"project_telegram_bot", content:"user has a Telegram bot", type:"project"})`,
|
|
3034
|
+
` \xB7 Tech stack / tools: memory_write({label:"tech_stack", content:"Node.js, Telegram", type:"tech"})`,
|
|
3035
|
+
` \xB7 Preferences and decisions they express`,
|
|
3036
|
+
` \xB7 Live URLs (ngrok, deployed apps): memory_write({label:"ngrok_url", content:"https://...", type:"url"})`,
|
|
3033
3037
|
` \xB7 Server ports: memory_write({label:"dev_server_port", content:"3000", type:"config"})`,
|
|
3034
3038
|
` \xB7 File paths of created projects: memory_write({label:"project_path", content:"/path/to/project", type:"path"})`,
|
|
3035
|
-
` \xB7 Task outcomes: memory_write({label:"
|
|
3036
|
-
`-
|
|
3039
|
+
` \xB7 Task outcomes: memory_write({label:"last_outcome", content:"...", type:"outcome"})`,
|
|
3040
|
+
`- Write to memory FIRST when the user tells you something about themselves or their work`,
|
|
3041
|
+
`- If the user says "my name is X" \u2192 memory_write immediately, before anything else`,
|
|
3042
|
+
`- If they say "we have a Y" or "our Y" \u2192 memory_write it as a project fact`
|
|
3037
3043
|
] : []
|
|
3038
3044
|
];
|
|
3039
3045
|
if (isSelfMod && this.agentRoot) {
|
|
@@ -4516,6 +4522,7 @@ var SessionManager = class {
|
|
|
4516
4522
|
weightUpdater;
|
|
4517
4523
|
anthropicFetcher = new AnthropicSkillFetcher();
|
|
4518
4524
|
agentRoot;
|
|
4525
|
+
onMemoryWritten;
|
|
4519
4526
|
constructor(deps = {}) {
|
|
4520
4527
|
this.inferenceEngine = deps.inferenceEngine;
|
|
4521
4528
|
this.eventBus = deps.eventBus;
|
|
@@ -4525,6 +4532,7 @@ var SessionManager = class {
|
|
|
4525
4532
|
this.identity = deps.identity;
|
|
4526
4533
|
this.projectContext = deps.projectContext;
|
|
4527
4534
|
this.agentRoot = deps.agentRoot;
|
|
4535
|
+
this.onMemoryWritten = deps.onMemoryWritten;
|
|
4528
4536
|
if (deps.adapter) {
|
|
4529
4537
|
this.conversationStore = new ConversationStore(deps.adapter);
|
|
4530
4538
|
this.conversationStore.init();
|
|
@@ -4816,6 +4824,8 @@ Current task:`;
|
|
|
4816
4824
|
this.addStep(sessionId, `Commands run: ${agentResult.commands_run.length}`);
|
|
4817
4825
|
}
|
|
4818
4826
|
this.addStep(sessionId, `Done (${agentResult.tokens_used} tokens, ${agentResult.iterations} LLM turns)`);
|
|
4827
|
+
this._extractAndPersistFacts(enrichedReq.task, agentResult.output, activeLLM).catch(() => {
|
|
4828
|
+
});
|
|
4819
4829
|
this.completeSession(sessionId, {
|
|
4820
4830
|
output: agentResult.output,
|
|
4821
4831
|
files_written: agentResult.files_written,
|
|
@@ -4884,6 +4894,68 @@ Current task:`;
|
|
|
4884
4894
|
}
|
|
4885
4895
|
return this.llm;
|
|
4886
4896
|
}
|
|
4897
|
+
/**
|
|
4898
|
+
* After every session, run a lightweight LLM pass to extract factual entities
|
|
4899
|
+
* (name, projects, tech, preferences, URLs) and persist them to the graph.
|
|
4900
|
+
* This catches everything the agent didn't explicitly memory_write during execution.
|
|
4901
|
+
*/
|
|
4902
|
+
async _extractAndPersistFacts(task, output, llm) {
|
|
4903
|
+
if (!this.graph || !llm.isConfigured) return;
|
|
4904
|
+
const prompt = `Extract factual entities from this conversation that should be remembered long-term.
|
|
4905
|
+
Return ONLY a JSON array, no other text, max 12 items.
|
|
4906
|
+
|
|
4907
|
+
Types: identity (name/role), project (apps/products), tech (stack/tools), preference, url, path, config, outcome
|
|
4908
|
+
|
|
4909
|
+
Format: [{"label":"snake_case_key","content":"value to remember","type":"type"}]
|
|
4910
|
+
|
|
4911
|
+
Examples:
|
|
4912
|
+
- User says "my name is Sahil" \u2192 {"label":"user_name","content":"Sahil","type":"identity"}
|
|
4913
|
+
- User says "we have a telegram bot" \u2192 {"label":"project_telegram_bot","content":"user has a Telegram bot project","type":"project"}
|
|
4914
|
+
- User says "I use React and Next.js" \u2192 {"label":"tech_stack","content":"React, Next.js","type":"tech"}
|
|
4915
|
+
|
|
4916
|
+
Conversation:
|
|
4917
|
+
User: ${task.slice(0, 600)}
|
|
4918
|
+
Agent: ${output.slice(0, 400)}`;
|
|
4919
|
+
try {
|
|
4920
|
+
const resp = await llm.complete(
|
|
4921
|
+
[{ role: "user", content: prompt }],
|
|
4922
|
+
"You are a concise memory extraction system. Extract only factual, durable information. Skip generic statements."
|
|
4923
|
+
);
|
|
4924
|
+
const jsonMatch = resp.content.match(/\[[\s\S]*?\]/);
|
|
4925
|
+
if (!jsonMatch) return;
|
|
4926
|
+
const entities = JSON.parse(jsonMatch[0]);
|
|
4927
|
+
if (!Array.isArray(entities) || entities.length === 0) return;
|
|
4928
|
+
let wrote = 0;
|
|
4929
|
+
for (const e of entities.slice(0, 12)) {
|
|
4930
|
+
if (!e.label?.trim() || !e.content?.trim()) continue;
|
|
4931
|
+
const nodeId = `memory:${e.label.toLowerCase().replace(/[^a-z0-9_]/g, "_")}`;
|
|
4932
|
+
try {
|
|
4933
|
+
const existing = this.graph.getNode(nodeId);
|
|
4934
|
+
if (existing) {
|
|
4935
|
+
this.graph.updateNode(nodeId, {
|
|
4936
|
+
label: e.label,
|
|
4937
|
+
metadata: { ...existing.metadata, content: e.content, type: e.type ?? "note", updated_at: (/* @__PURE__ */ new Date()).toISOString() }
|
|
4938
|
+
});
|
|
4939
|
+
} else {
|
|
4940
|
+
this.graph.addNode(createNode({
|
|
4941
|
+
id: nodeId,
|
|
4942
|
+
graph_id: "root",
|
|
4943
|
+
label: e.label,
|
|
4944
|
+
type: "context" /* CONTEXT */,
|
|
4945
|
+
metadata: { content: e.content, type: e.type ?? "note", saved_at: (/* @__PURE__ */ new Date()).toISOString() }
|
|
4946
|
+
}));
|
|
4947
|
+
}
|
|
4948
|
+
wrote++;
|
|
4949
|
+
} catch {
|
|
4950
|
+
}
|
|
4951
|
+
}
|
|
4952
|
+
if (wrote > 0) {
|
|
4953
|
+
console.log(`[0agent] Memory: extracted ${wrote} facts from session`);
|
|
4954
|
+
this.onMemoryWritten?.();
|
|
4955
|
+
}
|
|
4956
|
+
} catch {
|
|
4957
|
+
}
|
|
4958
|
+
}
|
|
4887
4959
|
/**
|
|
4888
4960
|
* Convert a task result into a weight signal for the knowledge graph.
|
|
4889
4961
|
*
|
|
@@ -6930,6 +7002,192 @@ var CodespaceManager = class {
|
|
|
6930
7002
|
|
|
6931
7003
|
// packages/daemon/src/ZeroAgentDaemon.ts
|
|
6932
7004
|
init_RuntimeSelfHeal();
|
|
7005
|
+
|
|
7006
|
+
// packages/daemon/src/TelegramBridge.ts
|
|
7007
|
+
var TelegramBridge = class {
|
|
7008
|
+
constructor(config, sessions, eventBus) {
|
|
7009
|
+
this.config = config;
|
|
7010
|
+
this.sessions = sessions;
|
|
7011
|
+
this.eventBus = eventBus;
|
|
7012
|
+
this.token = config.token;
|
|
7013
|
+
this.allowedUsers = new Set(config.allowed_users ?? []);
|
|
7014
|
+
}
|
|
7015
|
+
token;
|
|
7016
|
+
allowedUsers;
|
|
7017
|
+
offset = 0;
|
|
7018
|
+
pollTimer = null;
|
|
7019
|
+
running = false;
|
|
7020
|
+
// session_id per chat for streaming
|
|
7021
|
+
pendingSessions = /* @__PURE__ */ new Map();
|
|
7022
|
+
start() {
|
|
7023
|
+
if (this.running) return;
|
|
7024
|
+
this.running = true;
|
|
7025
|
+
console.log("[0agent] Telegram: bot polling started");
|
|
7026
|
+
this._poll();
|
|
7027
|
+
this.eventBus.onEvent((event) => {
|
|
7028
|
+
const chatId = this._getChatIdForSession(String(event.session_id ?? ""));
|
|
7029
|
+
if (!chatId) return;
|
|
7030
|
+
if (event.type === "session.completed") {
|
|
7031
|
+
const result = event.result;
|
|
7032
|
+
const output = String(result?.output ?? "").trim();
|
|
7033
|
+
if (output && output !== "(no output)") {
|
|
7034
|
+
this._send(chatId, output).catch(() => {
|
|
7035
|
+
});
|
|
7036
|
+
}
|
|
7037
|
+
this.pendingSessions.delete(chatId);
|
|
7038
|
+
} else if (event.type === "session.failed") {
|
|
7039
|
+
const err = String(event.error ?? "Task failed");
|
|
7040
|
+
this._send(chatId, `\u26A0\uFE0F ${err}`).catch(() => {
|
|
7041
|
+
});
|
|
7042
|
+
this.pendingSessions.delete(chatId);
|
|
7043
|
+
}
|
|
7044
|
+
});
|
|
7045
|
+
}
|
|
7046
|
+
stop() {
|
|
7047
|
+
this.running = false;
|
|
7048
|
+
if (this.pollTimer) {
|
|
7049
|
+
clearTimeout(this.pollTimer);
|
|
7050
|
+
this.pollTimer = null;
|
|
7051
|
+
}
|
|
7052
|
+
}
|
|
7053
|
+
_getChatIdForSession(sessionId) {
|
|
7054
|
+
for (const [chatId, sid] of this.pendingSessions) {
|
|
7055
|
+
if (sid === sessionId) return chatId;
|
|
7056
|
+
}
|
|
7057
|
+
return null;
|
|
7058
|
+
}
|
|
7059
|
+
async _poll() {
|
|
7060
|
+
if (!this.running) return;
|
|
7061
|
+
try {
|
|
7062
|
+
const updates = await this._getUpdates();
|
|
7063
|
+
for (const u of updates) {
|
|
7064
|
+
await this._handleUpdate(u);
|
|
7065
|
+
}
|
|
7066
|
+
} catch {
|
|
7067
|
+
}
|
|
7068
|
+
if (this.running) {
|
|
7069
|
+
this.pollTimer = setTimeout(() => this._poll(), 1e3);
|
|
7070
|
+
}
|
|
7071
|
+
}
|
|
7072
|
+
async _getUpdates() {
|
|
7073
|
+
const res = await fetch(
|
|
7074
|
+
`https://api.telegram.org/bot${this.token}/getUpdates?offset=${this.offset}&timeout=10&limit=20`,
|
|
7075
|
+
{ signal: AbortSignal.timeout(15e3) }
|
|
7076
|
+
);
|
|
7077
|
+
if (!res.ok) return [];
|
|
7078
|
+
const data = await res.json();
|
|
7079
|
+
if (!data.ok || !data.result.length) return [];
|
|
7080
|
+
this.offset = data.result[data.result.length - 1].update_id + 1;
|
|
7081
|
+
return data.result;
|
|
7082
|
+
}
|
|
7083
|
+
async _handleUpdate(u) {
|
|
7084
|
+
const msg = u.message;
|
|
7085
|
+
if (!msg?.text || !msg.from) return;
|
|
7086
|
+
const chatId = msg.chat.id;
|
|
7087
|
+
const userId = msg.from.id;
|
|
7088
|
+
const text = msg.text.trim();
|
|
7089
|
+
const userName = msg.from.first_name ?? msg.from.username ?? "User";
|
|
7090
|
+
if (this.allowedUsers.size > 0 && !this.allowedUsers.has(userId)) {
|
|
7091
|
+
await this._send(chatId, "\u26D4 You are not authorised to use this agent.");
|
|
7092
|
+
return;
|
|
7093
|
+
}
|
|
7094
|
+
if (text === "/start" || text === "/help") {
|
|
7095
|
+
await this._send(
|
|
7096
|
+
chatId,
|
|
7097
|
+
`\u{1F44B} Hi ${userName}! I'm 0agent \u2014 your AI that runs on your machine.
|
|
7098
|
+
|
|
7099
|
+
Send me any task and I'll get it done:
|
|
7100
|
+
\u2022 "make a website for my coffee shop"
|
|
7101
|
+
\u2022 "research my competitor's pricing"
|
|
7102
|
+
\u2022 "fix the bug in auth.ts"
|
|
7103
|
+
|
|
7104
|
+
I remember everything across sessions.`
|
|
7105
|
+
);
|
|
7106
|
+
return;
|
|
7107
|
+
}
|
|
7108
|
+
if (text === "/status") {
|
|
7109
|
+
try {
|
|
7110
|
+
const r = await fetch("http://localhost:4200/api/health", { signal: AbortSignal.timeout(2e3) });
|
|
7111
|
+
const h = await r.json();
|
|
7112
|
+
await this._send(
|
|
7113
|
+
chatId,
|
|
7114
|
+
`\u2705 Daemon running
|
|
7115
|
+
Graph: ${h.graph_nodes} nodes \xB7 ${h.graph_edges} edges
|
|
7116
|
+
Sessions: ${h.active_sessions} active`
|
|
7117
|
+
);
|
|
7118
|
+
} catch {
|
|
7119
|
+
await this._send(chatId, "\u26A0\uFE0F Daemon not reachable");
|
|
7120
|
+
}
|
|
7121
|
+
return;
|
|
7122
|
+
}
|
|
7123
|
+
await this._sendAction(chatId, "typing");
|
|
7124
|
+
await this._send(chatId, `\u23F3 Working on it\u2026`);
|
|
7125
|
+
try {
|
|
7126
|
+
const res = await fetch("http://localhost:4200/api/sessions", {
|
|
7127
|
+
method: "POST",
|
|
7128
|
+
headers: { "Content-Type": "application/json" },
|
|
7129
|
+
body: JSON.stringify({
|
|
7130
|
+
task: text,
|
|
7131
|
+
context: { system_context: `User's name: ${userName}. Message from Telegram.` }
|
|
7132
|
+
}),
|
|
7133
|
+
signal: AbortSignal.timeout(5e3)
|
|
7134
|
+
});
|
|
7135
|
+
const session = await res.json();
|
|
7136
|
+
const sessionId = session.session_id ?? session.id;
|
|
7137
|
+
if (sessionId) {
|
|
7138
|
+
this.pendingSessions.set(chatId, sessionId);
|
|
7139
|
+
} else {
|
|
7140
|
+
await this._send(chatId, "\u26A0\uFE0F Could not start session");
|
|
7141
|
+
}
|
|
7142
|
+
} catch (e) {
|
|
7143
|
+
await this._send(chatId, `\u26A0\uFE0F Error: ${e instanceof Error ? e.message : String(e)}`);
|
|
7144
|
+
}
|
|
7145
|
+
}
|
|
7146
|
+
async _send(chatId, text) {
|
|
7147
|
+
const chunks = this._splitMessage(text);
|
|
7148
|
+
for (const chunk of chunks) {
|
|
7149
|
+
await fetch(`https://api.telegram.org/bot${this.token}/sendMessage`, {
|
|
7150
|
+
method: "POST",
|
|
7151
|
+
headers: { "Content-Type": "application/json" },
|
|
7152
|
+
body: JSON.stringify({ chat_id: chatId, text: chunk, parse_mode: "Markdown" }),
|
|
7153
|
+
signal: AbortSignal.timeout(1e4)
|
|
7154
|
+
}).catch(() => {
|
|
7155
|
+
return fetch(`https://api.telegram.org/bot${this.token}/sendMessage`, {
|
|
7156
|
+
method: "POST",
|
|
7157
|
+
headers: { "Content-Type": "application/json" },
|
|
7158
|
+
body: JSON.stringify({ chat_id: chatId, text: chunk }),
|
|
7159
|
+
signal: AbortSignal.timeout(1e4)
|
|
7160
|
+
}).catch(() => {
|
|
7161
|
+
});
|
|
7162
|
+
});
|
|
7163
|
+
}
|
|
7164
|
+
}
|
|
7165
|
+
async _sendAction(chatId, action) {
|
|
7166
|
+
await fetch(`https://api.telegram.org/bot${this.token}/sendChatAction`, {
|
|
7167
|
+
method: "POST",
|
|
7168
|
+
headers: { "Content-Type": "application/json" },
|
|
7169
|
+
body: JSON.stringify({ chat_id: chatId, action }),
|
|
7170
|
+
signal: AbortSignal.timeout(5e3)
|
|
7171
|
+
}).catch(() => {
|
|
7172
|
+
});
|
|
7173
|
+
}
|
|
7174
|
+
_splitMessage(text) {
|
|
7175
|
+
if (text.length <= 4e3) return [text];
|
|
7176
|
+
const chunks = [];
|
|
7177
|
+
let i = 0;
|
|
7178
|
+
while (i < text.length) {
|
|
7179
|
+
chunks.push(text.slice(i, i + 4e3));
|
|
7180
|
+
i += 4e3;
|
|
7181
|
+
}
|
|
7182
|
+
return chunks;
|
|
7183
|
+
}
|
|
7184
|
+
static isConfigured(config) {
|
|
7185
|
+
const c = config;
|
|
7186
|
+
return !!(c?.token && typeof c.token === "string" && c.token.length > 10);
|
|
7187
|
+
}
|
|
7188
|
+
};
|
|
7189
|
+
|
|
7190
|
+
// packages/daemon/src/ZeroAgentDaemon.ts
|
|
6933
7191
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
6934
7192
|
import { dirname as dirname6 } from "node:path";
|
|
6935
7193
|
var ZeroAgentDaemon = class {
|
|
@@ -6949,6 +7207,7 @@ var ZeroAgentDaemon = class {
|
|
|
6949
7207
|
codespaceManager = null;
|
|
6950
7208
|
schedulerManager = null;
|
|
6951
7209
|
runtimeHealer = null;
|
|
7210
|
+
telegramBridge = null;
|
|
6952
7211
|
startedAt = 0;
|
|
6953
7212
|
pidFilePath;
|
|
6954
7213
|
constructor() {
|
|
@@ -7042,8 +7301,12 @@ var ZeroAgentDaemon = class {
|
|
|
7042
7301
|
identity: identity ?? void 0,
|
|
7043
7302
|
projectContext: projectContext ?? void 0,
|
|
7044
7303
|
adapter: this.adapter,
|
|
7045
|
-
agentRoot
|
|
7304
|
+
agentRoot,
|
|
7046
7305
|
// agent source path — self-improvement tasks read the right files
|
|
7306
|
+
// Mark GitHub memory dirty immediately when facts are extracted — pushes within 2min
|
|
7307
|
+
onMemoryWritten: () => {
|
|
7308
|
+
this.githubMemorySync?.markDirty();
|
|
7309
|
+
}
|
|
7047
7310
|
});
|
|
7048
7311
|
const teamSync = identity && teams.length > 0 ? new TeamSync(teamManager, this.adapter, identity.entity_node_id) : null;
|
|
7049
7312
|
if (this.githubMemorySync) {
|
|
@@ -7055,7 +7318,7 @@ var ZeroAgentDaemon = class {
|
|
|
7055
7318
|
console.log(`[0agent] Memory auto-synced: ${result.nodes_synced} nodes`);
|
|
7056
7319
|
}
|
|
7057
7320
|
}
|
|
7058
|
-
},
|
|
7321
|
+
}, 2 * 60 * 1e3);
|
|
7059
7322
|
if (typeof this.memorySyncTimer === "object") this.memorySyncTimer.unref?.();
|
|
7060
7323
|
}
|
|
7061
7324
|
let proactiveSurface = null;
|
|
@@ -7085,6 +7348,11 @@ var ZeroAgentDaemon = class {
|
|
|
7085
7348
|
}
|
|
7086
7349
|
this.schedulerManager = new SchedulerManager(this.adapter, this.sessionManager, this.eventBus);
|
|
7087
7350
|
this.schedulerManager.start();
|
|
7351
|
+
const tgCfg = this.config["telegram"];
|
|
7352
|
+
if (TelegramBridge.isConfigured(tgCfg) && this.sessionManager && this.eventBus) {
|
|
7353
|
+
this.telegramBridge = new TelegramBridge(tgCfg, this.sessionManager, this.eventBus);
|
|
7354
|
+
this.telegramBridge.start();
|
|
7355
|
+
}
|
|
7088
7356
|
this.backgroundWorkers = new BackgroundWorkers({
|
|
7089
7357
|
graph: this.graph,
|
|
7090
7358
|
traceStore: this.traceStore,
|
|
@@ -7156,6 +7424,8 @@ var ZeroAgentDaemon = class {
|
|
|
7156
7424
|
this.memorySyncTimer = null;
|
|
7157
7425
|
}
|
|
7158
7426
|
this.githubMemorySync = null;
|
|
7427
|
+
this.telegramBridge?.stop();
|
|
7428
|
+
this.telegramBridge = null;
|
|
7159
7429
|
this.schedulerManager?.stop();
|
|
7160
7430
|
this.schedulerManager = null;
|
|
7161
7431
|
this.codespaceManager?.closeTunnel();
|