easyoref 1.12.0 → 1.13.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/dist/agent/clarify.d.ts +43 -0
- package/dist/agent/clarify.d.ts.map +1 -0
- package/dist/agent/clarify.js +263 -0
- package/dist/agent/clarify.js.map +1 -0
- package/dist/agent/gramjs-monitor.d.ts +13 -0
- package/dist/agent/gramjs-monitor.d.ts.map +1 -1
- package/dist/agent/gramjs-monitor.js +140 -13
- package/dist/agent/gramjs-monitor.js.map +1 -1
- package/dist/agent/graph.d.ts +17 -11
- package/dist/agent/graph.d.ts.map +1 -1
- package/dist/agent/graph.js +109 -15
- package/dist/agent/graph.js.map +1 -1
- package/dist/agent/tools.d.ts +159 -0
- package/dist/agent/tools.d.ts.map +1 -0
- package/dist/agent/tools.js +439 -0
- package/dist/agent/tools.js.map +1 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clarify Node — optional ReAct tool calling for low-confidence enrichment.
|
|
3
|
+
*
|
|
4
|
+
* When the voting pipeline produces a result below the confidence threshold,
|
|
5
|
+
* the clarify node gives the LLM access to 4 tools and lets it decide:
|
|
6
|
+
*
|
|
7
|
+
* - LLM sees the voted result, contradictions, and existing extractions
|
|
8
|
+
* - LLM MAY call tools if it thinks more data would help
|
|
9
|
+
* - LLM MAY respond immediately without tools if data is sufficient
|
|
10
|
+
* - Max 3 tool call iterations, then returns either way
|
|
11
|
+
*
|
|
12
|
+
* Tools:
|
|
13
|
+
* 1. read_telegram_sources — fetch N posts from a Telegram channel
|
|
14
|
+
* 2. alert_history — recent Oref alert history (was there really an alert?)
|
|
15
|
+
* 3. resolve_area — is a mentioned location relevant to user's areas?
|
|
16
|
+
* 4. betterstack_log — query recent EasyOref logs from Better Stack
|
|
17
|
+
*
|
|
18
|
+
* The LLM decides — not a deterministic threshold.
|
|
19
|
+
* Interview answer: "tools are available, agent is autonomous."
|
|
20
|
+
*/
|
|
21
|
+
import { type ChannelPost } from "./store.js";
|
|
22
|
+
import type { ValidatedExtraction, VotedResult } from "./types.js";
|
|
23
|
+
export interface ClarifyInput {
|
|
24
|
+
alertId: string;
|
|
25
|
+
alertAreas: string[];
|
|
26
|
+
alertType: string;
|
|
27
|
+
messageId: number;
|
|
28
|
+
currentText: string;
|
|
29
|
+
extractions: ValidatedExtraction[];
|
|
30
|
+
votedResult: VotedResult;
|
|
31
|
+
}
|
|
32
|
+
export interface ClarifyOutput {
|
|
33
|
+
/** New posts discovered by tool calls (to merge into session) */
|
|
34
|
+
newPosts: ChannelPost[];
|
|
35
|
+
/** New extractions from tool-fetched posts (to add to existing) */
|
|
36
|
+
newExtractions: ValidatedExtraction[];
|
|
37
|
+
/** Number of tool calls made */
|
|
38
|
+
toolCallCount: number;
|
|
39
|
+
/** Whether clarification gathered useful new data */
|
|
40
|
+
clarified: boolean;
|
|
41
|
+
}
|
|
42
|
+
export declare function runClarify(input: ClarifyInput): Promise<ClarifyOutput>;
|
|
43
|
+
//# sourceMappingURL=clarify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clarify.d.ts","sourceRoot":"","sources":["../../src/agent/clarify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAaH,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAE/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAInE,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,mEAAmE;IACnE,cAAc,EAAE,mBAAmB,EAAE,CAAC;IACtC,gCAAgC;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,SAAS,EAAE,OAAO,CAAC;CACpB;AA6GD,wBAAsB,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CA2M5E"}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clarify Node — optional ReAct tool calling for low-confidence enrichment.
|
|
3
|
+
*
|
|
4
|
+
* When the voting pipeline produces a result below the confidence threshold,
|
|
5
|
+
* the clarify node gives the LLM access to 4 tools and lets it decide:
|
|
6
|
+
*
|
|
7
|
+
* - LLM sees the voted result, contradictions, and existing extractions
|
|
8
|
+
* - LLM MAY call tools if it thinks more data would help
|
|
9
|
+
* - LLM MAY respond immediately without tools if data is sufficient
|
|
10
|
+
* - Max 3 tool call iterations, then returns either way
|
|
11
|
+
*
|
|
12
|
+
* Tools:
|
|
13
|
+
* 1. read_telegram_sources — fetch N posts from a Telegram channel
|
|
14
|
+
* 2. alert_history — recent Oref alert history (was there really an alert?)
|
|
15
|
+
* 3. resolve_area — is a mentioned location relevant to user's areas?
|
|
16
|
+
* 4. betterstack_log — query recent EasyOref logs from Better Stack
|
|
17
|
+
*
|
|
18
|
+
* The LLM decides — not a deterministic threshold.
|
|
19
|
+
* Interview answer: "tools are available, agent is autonomous."
|
|
20
|
+
*/
|
|
21
|
+
import { AIMessage as AIMessageClass, HumanMessage, SystemMessage, ToolMessage, } from "@langchain/core/messages";
|
|
22
|
+
import { ChatOpenAI } from "@langchain/openai";
|
|
23
|
+
import { config } from "../config.js";
|
|
24
|
+
import * as logger from "../logger.js";
|
|
25
|
+
import { pushSessionPost } from "./store.js";
|
|
26
|
+
import { clarifyTools } from "./tools.js";
|
|
27
|
+
// ── Constants ──────────────────────────────────────────
|
|
28
|
+
const MAX_REACT_ITERATIONS = 3;
|
|
29
|
+
const CLARIFY_SYSTEM_PROMPT = `You are the clarification agent for EasyOref — an Israeli missile alert enrichment system.
|
|
30
|
+
|
|
31
|
+
The voting pipeline analyzed Telegram channel posts and produced a result with
|
|
32
|
+
low confidence or contradictions. You have access to 4 tools:
|
|
33
|
+
|
|
34
|
+
1. read_telegram_sources — fetch last N posts from a Telegram news channel
|
|
35
|
+
(IDF, N12, etc). Returns actual message texts.
|
|
36
|
+
2. alert_history — get recent alert history from Pikud HaOref.
|
|
37
|
+
Answers: "was there really an alert in area X in the last N minutes?"
|
|
38
|
+
3. resolve_area — check if a location mentioned in news is relevant to the
|
|
39
|
+
user's monitored areas. Uses defense-zone proximity mapping.
|
|
40
|
+
4. betterstack_log — query recent EasyOref logs from Better Stack.
|
|
41
|
+
See what the enrichment pipeline did recently (extractions, confidence, errors).
|
|
42
|
+
|
|
43
|
+
You decide whether tools would help:
|
|
44
|
+
- If contradictions can be resolved with existing data → respond immediately, no tools.
|
|
45
|
+
- If an authoritative source (IDF, N12) could settle a disagreement → fetch 1-4 posts.
|
|
46
|
+
- If you need to verify whether an alert occurred → check alert_history.
|
|
47
|
+
- If news mentions a city/region and you're unsure if it's relevant → use resolve_area.
|
|
48
|
+
- You can call 0, 1, 2, or 3+ tools. Your choice.
|
|
49
|
+
|
|
50
|
+
When done (with or without tools), respond with ONLY valid JSON (no markdown):
|
|
51
|
+
{
|
|
52
|
+
"clarified": true/false,
|
|
53
|
+
"new_data": {
|
|
54
|
+
"country_origin": string|null,
|
|
55
|
+
"rocket_count": int|null,
|
|
56
|
+
"intercepted": int|null,
|
|
57
|
+
"hits_confirmed": int|null,
|
|
58
|
+
"is_cassette": bool|null
|
|
59
|
+
},
|
|
60
|
+
"confidence_boost": float, // 0-0.3 (0 if no new info)
|
|
61
|
+
"reasoning": "brief explanation of decision"
|
|
62
|
+
}`;
|
|
63
|
+
// ── LLM ───────────────────────────────────────────────
|
|
64
|
+
function getClarifyLLM() {
|
|
65
|
+
return new ChatOpenAI({
|
|
66
|
+
model: config.agent.model,
|
|
67
|
+
configuration: {
|
|
68
|
+
baseURL: "https://openrouter.ai/api/v1",
|
|
69
|
+
defaultHeaders: {
|
|
70
|
+
"HTTP-Referer": "https://github.com/mikhailkogan17/EasyOref",
|
|
71
|
+
"X-Title": "EasyOref-Clarify",
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
apiKey: config.agent.apiKey,
|
|
75
|
+
temperature: 0,
|
|
76
|
+
maxTokens: 600,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
// ── Contradiction detection ───────────────────────────
|
|
80
|
+
function describeContradictions(extractions, voted) {
|
|
81
|
+
const issues = [];
|
|
82
|
+
// Country origin disagreement
|
|
83
|
+
if (voted.country_origins && voted.country_origins.length > 1) {
|
|
84
|
+
const names = voted.country_origins.map((c) => c.name).join(", ");
|
|
85
|
+
issues.push(`Multiple origin countries reported: ${names}`);
|
|
86
|
+
}
|
|
87
|
+
// Rocket count spread
|
|
88
|
+
if (voted.rocket_count_min !== null &&
|
|
89
|
+
voted.rocket_count_max !== null &&
|
|
90
|
+
voted.rocket_count_max - voted.rocket_count_min > 3) {
|
|
91
|
+
issues.push(`Wide rocket count range: ${voted.rocket_count_min}–${voted.rocket_count_max}`);
|
|
92
|
+
}
|
|
93
|
+
// Low sub-field confidence
|
|
94
|
+
if (voted.intercepted_confidence < 0.5 && voted.intercepted !== null) {
|
|
95
|
+
issues.push(`Intercepted count (${voted.intercepted}) has low confidence: ${voted.intercepted_confidence.toFixed(2)}`);
|
|
96
|
+
}
|
|
97
|
+
if (voted.hits_confidence < 0.5 && voted.hits_confirmed !== null) {
|
|
98
|
+
issues.push(`Hits confirmed (${voted.hits_confirmed}) has low confidence: ${voted.hits_confidence.toFixed(2)}`);
|
|
99
|
+
}
|
|
100
|
+
// Overall
|
|
101
|
+
issues.push(`Overall confidence: ${voted.confidence}`);
|
|
102
|
+
issues.push(`Sources count: ${voted.sources_count}`);
|
|
103
|
+
return issues.join("\n");
|
|
104
|
+
}
|
|
105
|
+
// ── ReAct loop ────────────────────────────────────────
|
|
106
|
+
export async function runClarify(input) {
|
|
107
|
+
const llm = getClarifyLLM();
|
|
108
|
+
const llmWithTools = llm.bindTools(clarifyTools);
|
|
109
|
+
const toolMap = new Map(clarifyTools.map((t) => [t.name, t]));
|
|
110
|
+
const contradictions = describeContradictions(input.extractions, input.votedResult);
|
|
111
|
+
const userPrompt = `Alert region: ${input.alertAreas.join(", ")}\n` +
|
|
112
|
+
`Alert type: ${input.alertType}\n` +
|
|
113
|
+
`Message ID: ${input.messageId}\n\n` +
|
|
114
|
+
`Current voted result:\n` +
|
|
115
|
+
JSON.stringify(input.votedResult, null, 2) +
|
|
116
|
+
`\n\nContradictions & issues:\n${contradictions}\n\n` +
|
|
117
|
+
`Existing extractions (${input.extractions.filter((e) => e.valid).length} valid):\n` +
|
|
118
|
+
input.extractions
|
|
119
|
+
.filter((e) => e.valid)
|
|
120
|
+
.map((e) => ` [${e.channel}] country=${e.country_origin}, rockets=${e.rocket_count}, ` +
|
|
121
|
+
`intercepted=${e.intercepted}, hits=${e.hits_confirmed}, conf=${e.confidence}`)
|
|
122
|
+
.join("\n") +
|
|
123
|
+
`\n\nDecide: would fetching more data from authoritative channels or ` +
|
|
124
|
+
`the official API resolve these issues? If not, respond directly.`;
|
|
125
|
+
// Message history for the ReAct loop
|
|
126
|
+
const messages = [new SystemMessage(CLARIFY_SYSTEM_PROMPT), new HumanMessage(userPrompt)];
|
|
127
|
+
const newPosts = [];
|
|
128
|
+
let toolCallCount = 0;
|
|
129
|
+
for (let iter = 0; iter < MAX_REACT_ITERATIONS; iter++) {
|
|
130
|
+
const response = (await llmWithTools.invoke(messages));
|
|
131
|
+
messages.push(new AIMessageClass({
|
|
132
|
+
content: typeof response.content === "string"
|
|
133
|
+
? response.content
|
|
134
|
+
: JSON.stringify(response.content),
|
|
135
|
+
tool_calls: response.tool_calls,
|
|
136
|
+
}));
|
|
137
|
+
// No tool calls → LLM is done
|
|
138
|
+
if (!response.tool_calls || response.tool_calls.length === 0) {
|
|
139
|
+
logger.info("Clarify: LLM finished without tool calls", {
|
|
140
|
+
iteration: iter,
|
|
141
|
+
alertId: input.alertId,
|
|
142
|
+
});
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
// Execute each tool call
|
|
146
|
+
for (const tc of response.tool_calls) {
|
|
147
|
+
toolCallCount++;
|
|
148
|
+
const foundTool = toolMap.get(tc.name);
|
|
149
|
+
if (!foundTool) {
|
|
150
|
+
logger.warn("Clarify: unknown tool requested", { tool: tc.name });
|
|
151
|
+
messages.push(new ToolMessage({
|
|
152
|
+
content: JSON.stringify({ error: `Unknown tool: ${tc.name}` }),
|
|
153
|
+
tool_call_id: tc.id ?? `call_${toolCallCount}`,
|
|
154
|
+
}));
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
try {
|
|
158
|
+
logger.info("Clarify: calling tool", {
|
|
159
|
+
tool: tc.name,
|
|
160
|
+
args: tc.args,
|
|
161
|
+
alertId: input.alertId,
|
|
162
|
+
});
|
|
163
|
+
const result = await foundTool.invoke(tc.args);
|
|
164
|
+
const resultStr = typeof result === "string" ? result : JSON.stringify(result);
|
|
165
|
+
messages.push(new ToolMessage({
|
|
166
|
+
content: resultStr,
|
|
167
|
+
tool_call_id: tc.id ?? `call_${toolCallCount}`,
|
|
168
|
+
}));
|
|
169
|
+
// If read_sources returned posts, store them for the session
|
|
170
|
+
if (tc.name === "read_telegram_sources" &&
|
|
171
|
+
resultStr.includes('"posts"')) {
|
|
172
|
+
try {
|
|
173
|
+
const parsed = JSON.parse(resultStr);
|
|
174
|
+
if (Array.isArray(parsed.posts)) {
|
|
175
|
+
for (const p of parsed.posts) {
|
|
176
|
+
const post = {
|
|
177
|
+
channel: parsed.channel ?? tc.args.channel,
|
|
178
|
+
text: p.text ?? "",
|
|
179
|
+
ts: p.ts ?? Date.now(),
|
|
180
|
+
messageUrl: p.messageUrl,
|
|
181
|
+
};
|
|
182
|
+
newPosts.push(post);
|
|
183
|
+
await pushSessionPost(post);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// JSON parse failed — ignore
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
logger.warn("Clarify: tool execution failed", {
|
|
194
|
+
tool: tc.name,
|
|
195
|
+
error: String(err),
|
|
196
|
+
});
|
|
197
|
+
messages.push(new ToolMessage({
|
|
198
|
+
content: JSON.stringify({
|
|
199
|
+
error: `Tool execution failed: ${String(err)}`,
|
|
200
|
+
retry: false,
|
|
201
|
+
}),
|
|
202
|
+
tool_call_id: tc.id ?? `call_${toolCallCount}`,
|
|
203
|
+
}));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// Parse the final LLM response for structured findings
|
|
208
|
+
const lastMsg = messages[messages.length - 1];
|
|
209
|
+
const lastContent = lastMsg && "content" in lastMsg && typeof lastMsg.content === "string"
|
|
210
|
+
? lastMsg.content
|
|
211
|
+
: "";
|
|
212
|
+
let clarified = false;
|
|
213
|
+
let newExtractions = [];
|
|
214
|
+
try {
|
|
215
|
+
const cleaned = lastContent
|
|
216
|
+
.replace(/^```(?:json)?\s*\n?/i, "")
|
|
217
|
+
.replace(/\n?```\s*$/i, "");
|
|
218
|
+
const findings = JSON.parse(cleaned.trim());
|
|
219
|
+
clarified = findings.clarified === true;
|
|
220
|
+
// Convert new_data into a synthetic validated extraction
|
|
221
|
+
if (findings.new_data && clarified) {
|
|
222
|
+
const syntheticExtraction = {
|
|
223
|
+
channel: "mcp_clarify",
|
|
224
|
+
region_relevance: 1.0,
|
|
225
|
+
source_trust: 0.85,
|
|
226
|
+
tone: "calm",
|
|
227
|
+
country_origin: findings.new_data.country_origin ?? null,
|
|
228
|
+
rocket_count: findings.new_data.rocket_count ?? null,
|
|
229
|
+
is_cassette: findings.new_data.is_cassette ?? null,
|
|
230
|
+
intercepted: findings.new_data.intercepted ?? null,
|
|
231
|
+
intercepted_qual: null,
|
|
232
|
+
intercepted_qual_num: null,
|
|
233
|
+
sea_impact: null,
|
|
234
|
+
sea_impact_qual: null,
|
|
235
|
+
sea_impact_qual_num: null,
|
|
236
|
+
open_area_impact: null,
|
|
237
|
+
open_area_impact_qual: null,
|
|
238
|
+
open_area_impact_qual_num: null,
|
|
239
|
+
hits_confirmed: findings.new_data.hits_confirmed ?? null,
|
|
240
|
+
eta_refined_minutes: null,
|
|
241
|
+
confidence: Math.min(0.9, (input.votedResult.confidence ?? 0.5) +
|
|
242
|
+
(findings.confidence_boost ?? 0.15)),
|
|
243
|
+
valid: true,
|
|
244
|
+
messageUrl: undefined,
|
|
245
|
+
};
|
|
246
|
+
newExtractions = [syntheticExtraction];
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
logger.info("Clarify: could not parse final LLM response as JSON", {
|
|
251
|
+
alertId: input.alertId,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
logger.info("Clarify: completed", {
|
|
255
|
+
alertId: input.alertId,
|
|
256
|
+
toolCallCount,
|
|
257
|
+
clarified,
|
|
258
|
+
newPosts: newPosts.length,
|
|
259
|
+
newExtractions: newExtractions.length,
|
|
260
|
+
});
|
|
261
|
+
return { newPosts, newExtractions, toolCallCount, clarified };
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=clarify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clarify.js","sourceRoot":"","sources":["../../src/agent/clarify.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,4 +10,17 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export declare function startMonitor(): Promise<void>;
|
|
12
12
|
export declare function stopMonitor(): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Fetch recent messages from a public Telegram channel via MTProto.
|
|
15
|
+
* Used by the telegram_mtproto_mcp_read_sources MCP tool.
|
|
16
|
+
*
|
|
17
|
+
* @param channel - Channel username with @ prefix (e.g. "@idf_telegram")
|
|
18
|
+
* @param limit - Number of messages to fetch (1-20)
|
|
19
|
+
* @returns Array of ChannelPost objects (newest first)
|
|
20
|
+
*/
|
|
21
|
+
export declare function fetchRecentChannelPosts(channel: string, limit?: number): Promise<Array<{
|
|
22
|
+
text: string;
|
|
23
|
+
ts: number;
|
|
24
|
+
messageUrl?: string;
|
|
25
|
+
}>>;
|
|
13
26
|
//# sourceMappingURL=gramjs-monitor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gramjs-monitor.d.ts","sourceRoot":"","sources":["../../src/agent/gramjs-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"gramjs-monitor.d.ts","sourceRoot":"","sources":["../../src/agent/gramjs-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA+DH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAgKlD;AA8FD,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAMjD;AAID;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,MAAU,GAChB,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CA+BnE"}
|
|
@@ -33,7 +33,13 @@ const MONITORED_CHANNELS = [
|
|
|
33
33
|
"@yaronyanir1299",
|
|
34
34
|
"@ynetalerts",
|
|
35
35
|
"@idf_telegram",
|
|
36
|
-
|
|
36
|
+
];
|
|
37
|
+
const PRIVATE_CHANNELS = [
|
|
38
|
+
{
|
|
39
|
+
inviteHash: "AmLhsj0A5YJbpv0XtJQENg",
|
|
40
|
+
channelId: "1023468930",
|
|
41
|
+
title: "Private Intel Group",
|
|
42
|
+
},
|
|
37
43
|
];
|
|
38
44
|
// ── Helpers ────────────────────────────────────────────
|
|
39
45
|
function sleep(ms) {
|
|
@@ -94,19 +100,48 @@ export async function startMonitor() {
|
|
|
94
100
|
logger.error("GramJS: connection failed", { error: String(err) });
|
|
95
101
|
return;
|
|
96
102
|
}
|
|
103
|
+
// Get all dialogs to check existing memberships
|
|
104
|
+
let existingChannels = new Set();
|
|
105
|
+
let existingPrivateIds = new Set();
|
|
106
|
+
try {
|
|
107
|
+
const dialogs = await _client.getDialogs({ limit: 200 });
|
|
108
|
+
for (const dialog of dialogs) {
|
|
109
|
+
const entity = dialog.entity;
|
|
110
|
+
// Public channel username
|
|
111
|
+
if (entity && "username" in entity && entity.username) {
|
|
112
|
+
existingChannels.add(String(entity.username).toLowerCase());
|
|
113
|
+
}
|
|
114
|
+
// Private channel ID
|
|
115
|
+
if (entity && "id" in entity) {
|
|
116
|
+
existingPrivateIds.add(String(entity.id));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
logger.info("GramJS: fetched existing dialogs", {
|
|
120
|
+
total: dialogs.length,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
logger.warn("GramJS: failed to fetch dialogs, will try joining anyway", {
|
|
125
|
+
error: String(err),
|
|
126
|
+
});
|
|
127
|
+
}
|
|
97
128
|
// Auto-join all monitored public channels (required for NewMessage events)
|
|
98
129
|
for (const ch of MONITORED_CHANNELS) {
|
|
99
130
|
const username = ch.replace("@", "");
|
|
131
|
+
const normalizedUsername = username.toLowerCase();
|
|
132
|
+
// Check if already a member
|
|
133
|
+
if (existingChannels.has(normalizedUsername)) {
|
|
134
|
+
logger.debug("GramJS: already in channel", { channel: ch });
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
100
137
|
try {
|
|
101
138
|
await _client.invoke(new Api.channels.JoinChannel({ channel: username }));
|
|
102
139
|
logger.info("GramJS: joined channel", { channel: ch });
|
|
103
140
|
}
|
|
104
141
|
catch (err) {
|
|
105
142
|
const errStr = String(err);
|
|
106
|
-
// CHANNELS_TOO_MUCH = account in too many channels
|
|
107
|
-
// USER_ALREADY_PARTICIPANT = already joined
|
|
108
143
|
if (errStr.includes("USER_ALREADY_PARTICIPANT")) {
|
|
109
|
-
logger.debug("GramJS: already in channel", { channel: ch });
|
|
144
|
+
logger.debug("GramJS: already in channel (via API)", { channel: ch });
|
|
110
145
|
}
|
|
111
146
|
else {
|
|
112
147
|
logger.warn("GramJS: failed to join channel", {
|
|
@@ -118,6 +153,35 @@ export async function startMonitor() {
|
|
|
118
153
|
// Rate limit: 1-2s between joins
|
|
119
154
|
await sleep(jitter(1500));
|
|
120
155
|
}
|
|
156
|
+
// Auto-join private channels via invite hash
|
|
157
|
+
for (const priv of PRIVATE_CHANNELS) {
|
|
158
|
+
// Check if already a member by channel ID
|
|
159
|
+
if (existingPrivateIds.has(priv.channelId)) {
|
|
160
|
+
logger.debug("GramJS: already in private channel", { title: priv.title });
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
await _client.invoke(new Api.messages.ImportChatInvite({ hash: priv.inviteHash }));
|
|
165
|
+
logger.info("GramJS: joined private channel", { title: priv.title });
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
const errStr = String(err);
|
|
169
|
+
if (errStr.includes("USER_ALREADY_PARTICIPANT") ||
|
|
170
|
+
errStr.includes("INVITE_HASH_EXPIRED")) {
|
|
171
|
+
logger.debug("GramJS: already in private channel or hash expired", {
|
|
172
|
+
title: priv.title,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
logger.warn("GramJS: failed to join private channel", {
|
|
177
|
+
title: priv.title,
|
|
178
|
+
error: errStr,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Rate limit: 1-2s between joins
|
|
183
|
+
await sleep(jitter(1500));
|
|
184
|
+
}
|
|
121
185
|
// Subscribe to new messages across all monitored channels
|
|
122
186
|
_client.addEventHandler(async (event) => {
|
|
123
187
|
await handleNewMessage(event).catch((err) => {
|
|
@@ -125,7 +189,8 @@ export async function startMonitor() {
|
|
|
125
189
|
});
|
|
126
190
|
}, new NewMessage({}));
|
|
127
191
|
logger.info("GramJS: monitoring channels", {
|
|
128
|
-
|
|
192
|
+
public: MONITORED_CHANNELS.length,
|
|
193
|
+
private: PRIVATE_CHANNELS.length,
|
|
129
194
|
});
|
|
130
195
|
}
|
|
131
196
|
async function handleNewMessage(event) {
|
|
@@ -134,11 +199,25 @@ async function handleNewMessage(event) {
|
|
|
134
199
|
logger.debug("GramJS: skipped message (no text or peerId)");
|
|
135
200
|
return;
|
|
136
201
|
}
|
|
137
|
-
// Get channel username
|
|
202
|
+
// Get channel identifier (username or title)
|
|
138
203
|
let channel = "";
|
|
204
|
+
let channelId = ""; // for private channels
|
|
205
|
+
let isPrivate = false;
|
|
139
206
|
try {
|
|
140
207
|
const chat = await event.message.getChat();
|
|
141
|
-
|
|
208
|
+
// Try to extract channel ID from peerId (for private channels)
|
|
209
|
+
if (msg.peerId && "channelId" in msg.peerId) {
|
|
210
|
+
// channelId is stored as bigint, convert to string
|
|
211
|
+
const rawId = String(msg.peerId.channelId);
|
|
212
|
+
channelId = rawId;
|
|
213
|
+
}
|
|
214
|
+
// Check if it's a monitored private channel
|
|
215
|
+
const privateMatch = PRIVATE_CHANNELS.find((p) => p.channelId === channelId);
|
|
216
|
+
if (privateMatch) {
|
|
217
|
+
channel = privateMatch.title;
|
|
218
|
+
isPrivate = true;
|
|
219
|
+
}
|
|
220
|
+
else if (chat && "username" in chat && chat.username) {
|
|
142
221
|
channel = `@${chat.username}`;
|
|
143
222
|
}
|
|
144
223
|
else if (chat && "title" in chat && chat.title) {
|
|
@@ -152,10 +231,11 @@ async function handleNewMessage(event) {
|
|
|
152
231
|
catch {
|
|
153
232
|
return;
|
|
154
233
|
}
|
|
155
|
-
// Only care about configured channels
|
|
234
|
+
// Only care about configured channels (public or private)
|
|
156
235
|
const normalizedChannel = channel.toLowerCase();
|
|
157
|
-
const isMonitored =
|
|
158
|
-
|
|
236
|
+
const isMonitored = isPrivate ||
|
|
237
|
+
MONITORED_CHANNELS.some((c) => c.toLowerCase() === normalizedChannel ||
|
|
238
|
+
c.toLowerCase().replace("@", "") === normalizedChannel.replace("@", ""));
|
|
159
239
|
if (!isMonitored) {
|
|
160
240
|
logger.debug("GramJS: skipped message (not monitored)", { channel });
|
|
161
241
|
return;
|
|
@@ -168,9 +248,17 @@ async function handleNewMessage(event) {
|
|
|
168
248
|
}
|
|
169
249
|
// Anti-flood: jittered delay
|
|
170
250
|
await sleep(jitter(1000));
|
|
171
|
-
// Build direct message URL
|
|
172
|
-
|
|
173
|
-
|
|
251
|
+
// Build direct message URL
|
|
252
|
+
let messageUrl;
|
|
253
|
+
if (isPrivate) {
|
|
254
|
+
// Private channel: https://t.me/c/1023468930/123
|
|
255
|
+
messageUrl = `https://t.me/c/${channelId}/${msg.id}`;
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
// Public channel: https://t.me/username/123
|
|
259
|
+
const username = channel.replace("@", "");
|
|
260
|
+
messageUrl = `https://t.me/${username}/${msg.id}`;
|
|
261
|
+
}
|
|
174
262
|
await pushChannelPost(active.alertId, {
|
|
175
263
|
channel,
|
|
176
264
|
text: msg.text,
|
|
@@ -181,6 +269,7 @@ async function handleNewMessage(event) {
|
|
|
181
269
|
channel,
|
|
182
270
|
alertId: active.alertId,
|
|
183
271
|
text_len: msg.text.length,
|
|
272
|
+
private: isPrivate,
|
|
184
273
|
});
|
|
185
274
|
}
|
|
186
275
|
export async function stopMonitor() {
|
|
@@ -190,4 +279,42 @@ export async function stopMonitor() {
|
|
|
190
279
|
logger.info("GramJS: disconnected");
|
|
191
280
|
}
|
|
192
281
|
}
|
|
282
|
+
// ── Fetch recent posts (used by MCP tools) ─────────────
|
|
283
|
+
/**
|
|
284
|
+
* Fetch recent messages from a public Telegram channel via MTProto.
|
|
285
|
+
* Used by the telegram_mtproto_mcp_read_sources MCP tool.
|
|
286
|
+
*
|
|
287
|
+
* @param channel - Channel username with @ prefix (e.g. "@idf_telegram")
|
|
288
|
+
* @param limit - Number of messages to fetch (1-20)
|
|
289
|
+
* @returns Array of ChannelPost objects (newest first)
|
|
290
|
+
*/
|
|
291
|
+
export async function fetchRecentChannelPosts(channel, limit = 5) {
|
|
292
|
+
if (!_client?.connected) {
|
|
293
|
+
logger.warn("GramJS: fetchRecentChannelPosts — client not connected");
|
|
294
|
+
return [];
|
|
295
|
+
}
|
|
296
|
+
const username = channel.replace("@", "");
|
|
297
|
+
const safeLimit = Math.min(Math.max(limit, 1), 20);
|
|
298
|
+
try {
|
|
299
|
+
// Rate limit: jittered delay before fetching
|
|
300
|
+
await sleep(jitter(1000));
|
|
301
|
+
const messages = await _client.getMessages(username, {
|
|
302
|
+
limit: safeLimit,
|
|
303
|
+
});
|
|
304
|
+
return messages
|
|
305
|
+
.filter((msg) => msg.text)
|
|
306
|
+
.map((msg) => ({
|
|
307
|
+
text: msg.text ?? "",
|
|
308
|
+
ts: msg.date ? msg.date * 1000 : Date.now(),
|
|
309
|
+
messageUrl: `https://t.me/${username}/${msg.id}`,
|
|
310
|
+
}));
|
|
311
|
+
}
|
|
312
|
+
catch (err) {
|
|
313
|
+
logger.warn("GramJS: fetchRecentChannelPosts failed", {
|
|
314
|
+
channel,
|
|
315
|
+
error: String(err),
|
|
316
|
+
});
|
|
317
|
+
return [];
|
|
318
|
+
}
|
|
319
|
+
}
|
|
193
320
|
//# sourceMappingURL=gramjs-monitor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gramjs-monitor.js","sourceRoot":"","sources":["../../src/agent/gramjs-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAK7D,IAAI,OAAO,GAA0B,IAAI,CAAC;AAE1C,yDAAyD;AAEzD,MAAM,kBAAkB,GAAG;IACzB,sBAAsB;IACtB,eAAe;IACf,eAAe;IACf,aAAa;IACb,iBAAiB;IACjB,UAAU;IACV,gCAAgC;IAChC,cAAc;IACd,cAAc;IACd,wBAAwB;IACxB,QAAQ;IACR,aAAa;IACb,oBAAoB;IACpB,iBAAiB;IACjB,aAAa;IACb,eAAe;
|
|
1
|
+
{"version":3,"file":"gramjs-monitor.js","sourceRoot":"","sources":["../../src/agent/gramjs-monitor.ts"],"names":[],"mappings":"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"}
|