@iletai/nzb 1.1.8 → 1.2.0
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/config.js +3 -0
- package/dist/telegram/bot.js +12 -1
- package/dist/telegram/log-channel.js +35 -0
- package/package.json +1 -1
package/dist/config.js
CHANGED
|
@@ -12,6 +12,7 @@ const configSchema = z.object({
|
|
|
12
12
|
COPILOT_MODEL: z.string().optional(),
|
|
13
13
|
WORKER_TIMEOUT: z.string().optional(),
|
|
14
14
|
SHOW_REASONING: z.string().optional(),
|
|
15
|
+
LOG_CHANNEL_ID: z.string().optional(),
|
|
15
16
|
NODE_EXTRA_CA_CERTS: z.string().optional(),
|
|
16
17
|
});
|
|
17
18
|
const raw = configSchema.parse(process.env);
|
|
@@ -33,12 +34,14 @@ const parsedWorkerTimeout = raw.WORKER_TIMEOUT ? Number(raw.WORKER_TIMEOUT) : DE
|
|
|
33
34
|
if (!Number.isInteger(parsedWorkerTimeout) || parsedWorkerTimeout <= 0) {
|
|
34
35
|
throw new Error(`WORKER_TIMEOUT must be a positive integer (ms), got: "${raw.WORKER_TIMEOUT}"`);
|
|
35
36
|
}
|
|
37
|
+
const parsedLogChannelId = raw.LOG_CHANNEL_ID ? raw.LOG_CHANNEL_ID.trim() : undefined;
|
|
36
38
|
export const DEFAULT_MODEL = "claude-sonnet-4.6";
|
|
37
39
|
let _copilotModel = raw.COPILOT_MODEL || DEFAULT_MODEL;
|
|
38
40
|
export const config = {
|
|
39
41
|
telegramBotToken: raw.TELEGRAM_BOT_TOKEN,
|
|
40
42
|
authorizedUserId: parsedUserId,
|
|
41
43
|
apiPort: parsedPort,
|
|
44
|
+
logChannelId: parsedLogChannelId,
|
|
42
45
|
workerTimeoutMs: parsedWorkerTimeout,
|
|
43
46
|
get copilotModel() {
|
|
44
47
|
return _copilotModel;
|
package/dist/telegram/bot.js
CHANGED
|
@@ -6,6 +6,7 @@ import { listSkills } from "../copilot/skills.js";
|
|
|
6
6
|
import { restartDaemon } from "../daemon.js";
|
|
7
7
|
import { searchMemories } from "../store/db.js";
|
|
8
8
|
import { chunkMessage, formatToolSummaryExpandable, toTelegramMarkdown } from "./formatter.js";
|
|
9
|
+
import { initLogChannel, logDebug, logError, logInfo } from "./log-channel.js";
|
|
9
10
|
let bot;
|
|
10
11
|
const startedAt = Date.now();
|
|
11
12
|
// Inline keyboard menu for quick actions
|
|
@@ -40,6 +41,7 @@ export function createBot() {
|
|
|
40
41
|
},
|
|
41
42
|
});
|
|
42
43
|
console.log("[nzb] Telegram bot using direct HTTPS agent (proxy bypass)");
|
|
44
|
+
initLogChannel(bot);
|
|
43
45
|
// Auth middleware — only allow the authorized user
|
|
44
46
|
bot.use(async (ctx, next) => {
|
|
45
47
|
if (config.authorizedUserId !== undefined && ctx.from?.id !== config.authorizedUserId) {
|
|
@@ -243,6 +245,8 @@ export function createBot() {
|
|
|
243
245
|
const chatId = ctx.chat.id;
|
|
244
246
|
const userMessageId = ctx.message.message_id;
|
|
245
247
|
const replyParams = { message_id: userMessageId };
|
|
248
|
+
const msgPreview = ctx.message.text.length > 80 ? ctx.message.text.slice(0, 80) + "…" : ctx.message.text;
|
|
249
|
+
void logInfo(`📩 Message: ${msgPreview}`);
|
|
246
250
|
// Typing indicator — keeps sending "typing" action every 4s until the final
|
|
247
251
|
// response is delivered. We use bot.api directly for reliability, and await the
|
|
248
252
|
// first call so the user sees typing immediately before any async work begins.
|
|
@@ -326,6 +330,7 @@ export function createBot() {
|
|
|
326
330
|
const onToolEvent = (event) => {
|
|
327
331
|
console.log(`[nzb] Bot received tool event: ${event.type} ${event.toolName}`);
|
|
328
332
|
if (event.type === "tool_start") {
|
|
333
|
+
void logDebug(`🔧 Tool start: ${event.toolName}`);
|
|
329
334
|
currentToolName = event.toolName;
|
|
330
335
|
toolHistory.push({ name: event.toolName, startTime: Date.now() });
|
|
331
336
|
const existingText = lastEditedText.replace(/^🔧 .*\n\n/, "");
|
|
@@ -369,11 +374,14 @@ export function createBot() {
|
|
|
369
374
|
if (done) {
|
|
370
375
|
finalized = true;
|
|
371
376
|
stopTyping();
|
|
377
|
+
const elapsed = ((Date.now() - handlerStartTime) / 1000).toFixed(1);
|
|
378
|
+
void logInfo(`✅ Response done (${elapsed}s, ${toolHistory.length} tools, ${text.length} chars)`);
|
|
372
379
|
// Wait for in-flight edits to finish before sending the final response
|
|
373
380
|
void editChain.then(async () => {
|
|
374
381
|
// Format error messages with a distinct visual
|
|
375
382
|
const isError = text.startsWith("Error:");
|
|
376
383
|
if (isError) {
|
|
384
|
+
void logError(`Response error: ${text.slice(0, 200)}`);
|
|
377
385
|
const errorText = `⚠️ ${text}`;
|
|
378
386
|
if (placeholderMsgId) {
|
|
379
387
|
try {
|
|
@@ -523,7 +531,10 @@ export async function startBot() {
|
|
|
523
531
|
}
|
|
524
532
|
bot
|
|
525
533
|
.start({
|
|
526
|
-
onStart: () =>
|
|
534
|
+
onStart: () => {
|
|
535
|
+
console.log("[nzb] Telegram bot connected");
|
|
536
|
+
void logInfo(`🚀 NZB v${process.env.npm_package_version || "?"} started (model: ${config.copilotModel})`);
|
|
537
|
+
},
|
|
527
538
|
})
|
|
528
539
|
.catch((err) => {
|
|
529
540
|
if (err?.error_code === 401) {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { config } from "../config.js";
|
|
2
|
+
let botRef;
|
|
3
|
+
/** Initialize the log channel with a bot reference */
|
|
4
|
+
export function initLogChannel(bot) {
|
|
5
|
+
botRef = bot;
|
|
6
|
+
}
|
|
7
|
+
const ICONS = {
|
|
8
|
+
info: "ℹ️",
|
|
9
|
+
warn: "⚠️",
|
|
10
|
+
error: "🔴",
|
|
11
|
+
debug: "🔍",
|
|
12
|
+
};
|
|
13
|
+
/** Send a log message to the configured Telegram channel */
|
|
14
|
+
export async function sendLog(level, message) {
|
|
15
|
+
if (!botRef || !config.logChannelId)
|
|
16
|
+
return;
|
|
17
|
+
const icon = ICONS[level];
|
|
18
|
+
const timestamp = new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
19
|
+
const text = `${icon} <b>[${level.toUpperCase()}]</b> <code>${timestamp}</code>\n${escapeHtml(message)}`;
|
|
20
|
+
try {
|
|
21
|
+
await botRef.api.sendMessage(config.logChannelId, text, { parse_mode: "HTML" });
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// best-effort — don't crash if log channel is unreachable
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** Convenience wrappers */
|
|
28
|
+
export const logInfo = (msg) => sendLog("info", msg);
|
|
29
|
+
export const logWarn = (msg) => sendLog("warn", msg);
|
|
30
|
+
export const logError = (msg) => sendLog("error", msg);
|
|
31
|
+
export const logDebug = (msg) => sendLog("debug", msg);
|
|
32
|
+
function escapeHtml(text) {
|
|
33
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=log-channel.js.map
|