fix(telegram): harden polling release path

This commit is contained in:
ilya-bov
2026-04-30 18:26:54 +03:00
parent a78c41c75e
commit 376d67cac9
11 changed files with 100 additions and 15 deletions

View File

@@ -22,8 +22,8 @@ The app runs as a Next.js service and stores runtime state on disk (`./data`).
## Releases
- Latest release snapshot: [0.1.5 - Web Fetch for Direct Links](./docs/releases/0.1.5-web-fetch-direct-links.md)
- GitHub release body : [v0.1.5](./docs/releases/github-v0.1.5.md)
- Latest release snapshot: [0.1.6 - Telegram Long Polling](./docs/releases/0.1.6-telegram-long-polling.md)
- GitHub release body : [v0.1.6](./docs/releases/github-v0.1.6.md)
- Release archive: [docs/releases/README.md](./docs/releases/README.md)
## Contributing and Support

View File

@@ -0,0 +1,46 @@
# Eggent 0.1.6 - Telegram Long Polling
Date: 2026-04-30
Type: Patch release snapshot
## Release Name
`Telegram Long Polling`
This release adds Telegram long polling alongside the existing webhook path, so Telegram integration can run without a public domain or HTTPS endpoint.
## What Is Included
### 1) Telegram Long Polling
- Added a polling service that reads Telegram updates with `getUpdates`.
- Added API controls for polling status, start, and stop.
- Automatically removes an existing webhook before polling starts.
### 2) Shared Telegram Message Handling
- Moved Telegram update processing into a shared message handler.
- Kept webhook and polling modes on the same message/session/access-control behavior.
- Preserved file upload handling and Telegram reply support.
### 3) Connection Mode Settings
- Added `auto`, `webhook`, and `polling` modes for Telegram configuration.
- Auto mode uses polling for local, private, or non-HTTPS URLs, and webhook for public HTTPS URLs.
- Added UI controls for choosing mode and controlling polling.
### 4) Runtime Reliability
- Starts Telegram lifecycle from server instrumentation instead of page layout rendering.
- Stops polling when Telegram is disconnected.
- Keeps webhook secret generation and mode detection consistent across runtime paths.
### 5) Installation Docs
- Reworked installation docs around Docker, local Node.js, development, and PM2 deployment paths.
## New in 0.1.6
- Telegram long polling mode for installs without public HTTPS.
- Telegram lifecycle startup via Next.js instrumentation.
- Package/app health version bumped to `0.1.6`.
## Upgrade Notes
- No migration is required.
- Existing webhook setups continue to work.
- For local or VPS installs without HTTPS, set Telegram mode to `Auto` or `Long Polling`.

View File

@@ -4,6 +4,7 @@ This directory contains release summaries and publish-ready notes.
| Version | Name | Date | Notes |
| --- | --- | --- | --- |
| `0.1.6` | Telegram Long Polling | 2026-04-30 | [Full snapshot](./0.1.6-telegram-long-polling.md), [GitHub body](./github-v0.1.6.md) |
| `0.1.5` | Web Fetch for Direct Links | 2026-03-23 | [Full snapshot](./0.1.5-web-fetch-direct-links.md), [GitHub body](./github-v0.1.5.md) |
| `0.1.4` | Web Search Autostart | 2026-03-23 | [Full snapshot](./0.1.4-web-search-autostart.md), [GitHub body](./github-v0.1.4.md) |
| `0.1.3` | OAuth Native CLI Providers | 2026-03-06 | [Full snapshot](./0.1.3-oauth-native-cli-providers.md), [GitHub body](./github-v0.1.3.md) |

View File

@@ -0,0 +1,25 @@
## Eggent v0.1.6 - Telegram Long Polling
Patch release focused on making Telegram integration usable without a public HTTPS webhook.
### Highlights
- Added Telegram long polling support with status/start/stop API controls.
- Shared Telegram update handling between webhook and polling modes.
- Added Telegram connection modes: `auto`, `webhook`, and `polling`.
- Auto mode now chooses polling for local, private, or non-HTTPS URLs.
- Moved Telegram lifecycle startup into Next.js instrumentation so polling can resume on server startup.
- Stopped polling during Telegram disconnect.
- Updated installation documentation for Docker, local Node.js, development, and PM2 setups.
- Version bump to `0.1.6` across package metadata and `GET /api/health`.
### Upgrade Notes
- No migration required.
- Existing webhook configurations continue to work.
- Use `Auto` or `Long Polling` for installs without a public HTTPS URL.
### Links
- Full release snapshot: `docs/releases/0.1.6-telegram-long-polling.md`
- Installation and update guide: `README.md`

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "design-vibe",
"version": "0.1.5",
"version": "0.1.6",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "design-vibe",
"version": "0.1.5",
"version": "0.1.6",
"dependencies": {
"@ai-sdk/anthropic": "^3.0.37",
"@ai-sdk/google": "^3.0.21",

View File

@@ -1,6 +1,6 @@
{
"name": "design-vibe",
"version": "0.1.5",
"version": "0.1.6",
"private": true,
"scripts": {
"dev": "next dev",

View File

@@ -2,6 +2,6 @@ export async function GET() {
return Response.json({
status: "ok",
timestamp: new Date().toISOString(),
version: "0.1.5",
version: "0.1.6",
});
}

View File

@@ -4,6 +4,7 @@ import {
getTelegramIntegrationStoredSettings,
saveTelegramIntegrationStoredSettings,
} from "@/lib/storage/telegram-integration-store";
import { telegramPollingService } from "@/lib/telegram/polling-service";
interface TelegramApiResponse {
ok?: boolean;
@@ -58,6 +59,10 @@ export async function POST() {
}
}
if (telegramPollingService.status.isRunning) {
telegramPollingService.stop();
}
await saveTelegramIntegrationStoredSettings({
botToken: "",
webhookSecret: "",

View File

@@ -2,7 +2,6 @@ import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import { unstable_noStore as noStore } from "next/cache";
import { getSettings } from "@/lib/storage/settings-store";
import { initTelegramLifecycle } from "@/lib/telegram/polling-lifecycle";
import "./globals.css";
const geistSans = Geist({
@@ -20,13 +19,6 @@ export const metadata: Metadata = {
description: "AI Agent Terminal - Execute code, manage memory, search the web",
};
// Initialize Telegram lifecycle (polling or webhook) on server startup
if (typeof window === "undefined") {
initTelegramLifecycle().catch((error) => {
console.error("Failed to initialize Telegram lifecycle:", error);
});
}
export default async function RootLayout({
children,
}: Readonly<{

12
src/instrumentation.ts Normal file
View File

@@ -0,0 +1,12 @@
export async function register() {
if (process.env.NEXT_RUNTIME === "edge") {
return;
}
try {
const { initTelegramLifecycle } = await import("@/lib/telegram/polling-lifecycle");
await initTelegramLifecycle();
} catch (error) {
console.error("Failed to initialize Telegram lifecycle:", error);
}
}

View File

@@ -259,7 +259,11 @@ function isLocalhostUrl(url: string): boolean {
if (!url) return true;
try {
const parsed = new URL(url);
const hostname = parsed.hostname.toLowerCase();
if (parsed.protocol !== "https:") {
return true;
}
const hostname = parsed.hostname.toLowerCase().replace(/^\[|\]$/g, "");
if (hostname === "localhost" || hostname === "::1" || hostname.endsWith(".local")) {
return true;
}