@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 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;
@@ -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: () => console.log("[nzb] Telegram bot connected"),
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
34
+ }
35
+ //# sourceMappingURL=log-channel.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iletai/nzb",
3
- "version": "1.1.8",
3
+ "version": "1.2.0",
4
4
  "description": "NZB — a personal AI assistant for developers, built on the GitHub Copilot SDK",
5
5
  "bin": {
6
6
  "nzb": "dist/cli.js"