@pixelbyte-software/pixcode 1.51.2 → 1.51.4
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/CODE_OF_CONDUCT.md +41 -41
- package/CONTRIBUTING.md +155 -155
- package/LICENSE +718 -718
- package/README.de.md +169 -169
- package/README.ja.md +167 -167
- package/README.ko.md +167 -167
- package/README.md +419 -419
- package/README.ru.md +169 -169
- package/README.tr.md +298 -298
- package/README.zh-CN.md +167 -167
- package/SECURITY.md +46 -46
- package/dist/api-automation.html +110 -110
- package/dist/api-docs.html +548 -548
- package/dist/assets/index-B9N-gfOQ.css +32 -0
- package/dist/assets/{index-EN9ngyxf.js → index-HfGHXhD6.js} +175 -175
- package/dist/clear-cache.html +85 -85
- package/dist/convert-icons.md +52 -52
- package/dist/docs.html +308 -308
- package/dist/favicon.svg +8 -8
- package/dist/features.html +133 -133
- package/dist/generate-icons.js +48 -48
- package/dist/humans.txt +15 -15
- package/dist/icons/codex-white.svg +3 -3
- package/dist/icons/codex.svg +3 -3
- package/dist/icons/cursor-white.svg +11 -11
- package/dist/icons/icon-128x128.svg +9 -9
- package/dist/icons/icon-144x144.svg +9 -9
- package/dist/icons/icon-152x152.svg +9 -9
- package/dist/icons/icon-192x192.svg +9 -9
- package/dist/icons/icon-384x384.svg +9 -9
- package/dist/icons/icon-512x512.svg +9 -9
- package/dist/icons/icon-72x72.svg +9 -9
- package/dist/icons/icon-96x96.svg +9 -9
- package/dist/icons/icon-template.svg +9 -9
- package/dist/icons/qwen-logo.svg +14 -14
- package/dist/index.html +59 -59
- package/dist/landing.html +268 -268
- package/dist/llms-full.txt +119 -119
- package/dist/llms.txt +53 -53
- package/dist/logo.svg +12 -12
- package/dist/manifest.json +60 -60
- package/dist/openapi.yaml +1696 -1696
- package/dist/orchestration.html +125 -125
- package/dist/robots.txt +4 -4
- package/dist/site.css +692 -692
- package/dist/sitemap.xml +51 -51
- package/dist/sw.js +132 -132
- package/dist-server/server/cli.js +96 -96
- package/dist-server/server/daemon/manager.js +33 -33
- package/dist-server/server/daemon-manager.js +64 -64
- package/dist-server/server/database/db.js +14 -2
- package/dist-server/server/database/db.js.map +1 -1
- package/dist-server/server/index.js +191 -31
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/middleware/auth.js +16 -5
- package/dist-server/server/middleware/auth.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/json-event.adapter.js +84 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/json-event.adapter.js.map +1 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/json-event.adapter.test.js +43 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/json-event.adapter.test.js.map +1 -0
- package/dist-server/server/modules/orchestration/hermes/hermes.routes.js +55 -1
- package/dist-server/server/modules/orchestration/hermes/hermes.routes.js.map +1 -1
- package/dist-server/server/modules/orchestration/index.js +1 -0
- package/dist-server/server/modules/orchestration/index.js.map +1 -1
- package/dist-server/server/routes/auth.js +12 -5
- package/dist-server/server/routes/auth.js.map +1 -1
- package/dist-server/server/routes/commands.js +25 -25
- package/dist-server/server/routes/git.js +29 -17
- package/dist-server/server/routes/git.js.map +1 -1
- package/dist-server/server/routes/live-view.js +46 -46
- package/dist-server/server/routes/platformization.js +7 -6
- package/dist-server/server/routes/platformization.js.map +1 -1
- package/dist-server/server/services/hermes-gateway.js +310 -0
- package/dist-server/server/services/hermes-gateway.js.map +1 -1
- package/dist-server/server/services/platformization.js +58 -2
- package/dist-server/server/services/platformization.js.map +1 -1
- package/dist-server/server/services/public-api-manifest.js +59 -51
- package/dist-server/server/services/public-api-manifest.js.map +1 -1
- package/package.json +222 -222
- package/scripts/fix-node-pty.js +67 -67
- package/scripts/github/create-v1.38-issues.mjs +351 -351
- package/scripts/github/create-vscode-workbench-issues.mjs +121 -121
- package/scripts/hermes/configure-pixcode-mcp.mjs +165 -163
- package/scripts/hermes/pixcode-mcp-server.mjs +1009 -958
- package/scripts/smoke/changes-panel-layout.mjs +48 -48
- package/scripts/smoke/chat-composer-fixed-layout.mjs +55 -55
- package/scripts/smoke/chat-message-timeline-order.mjs +41 -41
- package/scripts/smoke/chat-realtime-hydration.mjs +44 -44
- package/scripts/smoke/chat-session-provider-pools.mjs +35 -35
- package/scripts/smoke/chat-session-state.mjs +19 -19
- package/scripts/smoke/code-editor-theme.mjs +55 -55
- package/scripts/smoke/code-editor-vscode-engine.mjs +91 -91
- package/scripts/smoke/command-center-agent-writes.mjs +79 -79
- package/scripts/smoke/command-center-non-git.mjs +46 -46
- package/scripts/smoke/context-packet.mjs +43 -43
- package/scripts/smoke/control-room-ux-redesign.mjs +91 -91
- package/scripts/smoke/daemon-entrypoint.mjs +20 -20
- package/scripts/smoke/default-landing-routing.mjs +33 -33
- package/scripts/smoke/desktop-native-notifications.mjs +30 -30
- package/scripts/smoke/desktop-tray-icon.mjs +33 -33
- package/scripts/smoke/discord-release-workflow.mjs +24 -24
- package/scripts/smoke/git-install-update.mjs +255 -255
- package/scripts/smoke/handoff-artifact-protocol.mjs +50 -50
- package/scripts/smoke/hermes-api-install.mjs +56 -56
- package/scripts/smoke/hermes-gateway-persistence.mjs +104 -104
- package/scripts/smoke/hermes-mcp-pixcode-roundtrip.mjs +426 -367
- package/scripts/smoke/hermes-rest-chat-api.mjs +162 -162
- package/scripts/smoke/hermes-rest-chat-live.mjs +45 -45
- package/scripts/smoke/hermes-rest-codex-launch.mjs +209 -209
- package/scripts/smoke/hermes-rest-gateway.mjs +79 -70
- package/scripts/smoke/hermes-rest-live.mjs +42 -42
- package/scripts/smoke/hermes-roundtrip.mjs +167 -167
- package/scripts/smoke/hermes-settings-commands.mjs +349 -346
- package/scripts/smoke/hermes-smoke-launcher-guard.mjs +34 -34
- package/scripts/smoke/live-view-diagnostics.mjs +53 -53
- package/scripts/smoke/live-view-environment.mjs +92 -92
- package/scripts/smoke/live-view-integration.mjs +450 -450
- package/scripts/smoke/mac-desktop-runtime.mjs +37 -37
- package/scripts/smoke/mobile-tunnel-guidance.mjs +29 -29
- package/scripts/smoke/model-registry.mjs +36 -36
- package/scripts/smoke/multi-project-ui.mjs +45 -45
- package/scripts/smoke/multi-worker-slots.mjs +42 -42
- package/scripts/smoke/notification-center.mjs +87 -87
- package/scripts/smoke/notification-inapp-preference.mjs +23 -23
- package/scripts/smoke/notification-taxonomy.mjs +58 -58
- package/scripts/smoke/orchestration-api.mjs +172 -172
- package/scripts/smoke/orchestration-execution-dashboard.mjs +33 -33
- package/scripts/smoke/orchestration-live-run.mjs +176 -176
- package/scripts/smoke/orchestration-mobile-scroll.mjs +29 -29
- package/scripts/smoke/orchestration-model-sync.mjs +30 -30
- package/scripts/smoke/orchestration-permission-fallback.mjs +34 -34
- package/scripts/smoke/orchestration-runtime-guards.mjs +48 -48
- package/scripts/smoke/orchestration-user-facing-output.mjs +25 -25
- package/scripts/smoke/permission-policy.mjs +50 -50
- package/scripts/smoke/pixcode-workbench-1-48.mjs +167 -167
- package/scripts/smoke/provider-models-opencode-live.mjs +66 -66
- package/scripts/smoke/provider-rest-api.mjs +124 -124
- package/scripts/smoke/provider-selection-status.mjs +52 -52
- package/scripts/smoke/run-state-refresh.mjs +52 -52
- package/scripts/smoke/runtime-manager.mjs +99 -99
- package/scripts/smoke/shell-manual-disconnect.mjs +30 -30
- package/scripts/smoke/side-panel-editor-layout.mjs +34 -34
- package/scripts/smoke/static-root-routing.mjs +21 -21
- package/scripts/smoke/strict-handoff-compact.mjs +60 -60
- package/scripts/smoke/taskmaster-config.mjs +24 -24
- package/scripts/smoke/taskmaster-execution-telegram.mjs +3 -3
- package/scripts/smoke/taskmaster-onboarding.mjs +3 -3
- package/scripts/smoke/taskmaster-run-graph.mjs +3 -3
- package/scripts/smoke/telegram-control.mjs +242 -242
- package/scripts/smoke/tunnel-persistence.mjs +56 -56
- package/scripts/smoke/update-issue-progress.mjs +69 -69
- package/scripts/smoke/update-ux.mjs +55 -55
- package/scripts/smoke/v138-completion.mjs +132 -132
- package/scripts/smoke/v138-desktop-release-hardening.mjs +69 -69
- package/scripts/smoke/v138-diagnostics.mjs +63 -63
- package/scripts/smoke/v138-issue-planner.mjs +33 -33
- package/scripts/smoke/v143-remote-control.mjs +76 -76
- package/scripts/smoke/v144-production-loop.mjs +47 -47
- package/scripts/smoke/v145-platformization.mjs +46 -46
- package/scripts/smoke/v146-control-room-ui.mjs +150 -150
- package/scripts/smoke/version-modal-autoshow.mjs +29 -29
- package/scripts/smoke/vscode-workbench-layout.mjs +63 -63
- package/scripts/smoke/vscode-workbench-polish.mjs +461 -436
- package/scripts/smoke/workflow-fallback-replay.mjs +56 -56
- package/scripts/smoke/workflow-templates.mjs +43 -43
- package/scripts/smoke/workflow-trace-timeline.mjs +46 -46
- package/scripts/update-git-install.mjs +293 -293
- package/server/claude-sdk.js +920 -920
- package/server/cli.js +1039 -1039
- package/server/constants/config.js +4 -4
- package/server/cursor-cli.js +344 -344
- package/server/daemon/manager.js +563 -563
- package/server/daemon-manager.js +964 -964
- package/server/database/db.js +908 -895
- package/server/database/json-store.js +197 -197
- package/server/gemini-cli.js +550 -550
- package/server/gemini-response-handler.js +79 -79
- package/server/index.js +201 -30
- package/server/load-env.js +35 -35
- package/server/middleware/auth.js +171 -156
- package/server/modules/orchestration/a2a/adapter-registry.ts +108 -108
- package/server/modules/orchestration/a2a/adapters/abstract-a2a.adapter.ts +63 -63
- package/server/modules/orchestration/a2a/adapters/claude-code.adapter.ts +286 -286
- package/server/modules/orchestration/a2a/adapters/codex.adapter.ts +244 -244
- package/server/modules/orchestration/a2a/adapters/cursor.adapter.ts +249 -249
- package/server/modules/orchestration/a2a/adapters/gemini.adapter.ts +248 -248
- package/server/modules/orchestration/a2a/adapters/json-event.adapter.test.ts +60 -0
- package/server/modules/orchestration/a2a/adapters/json-event.adapter.ts +101 -0
- package/server/modules/orchestration/a2a/adapters/opencode.adapter.ts +248 -248
- package/server/modules/orchestration/a2a/adapters/qwen.adapter.ts +248 -248
- package/server/modules/orchestration/a2a/agent-card.ts +55 -55
- package/server/modules/orchestration/a2a/routes.ts +590 -590
- package/server/modules/orchestration/a2a/task-store.ts +178 -178
- package/server/modules/orchestration/a2a/types.ts +126 -126
- package/server/modules/orchestration/a2a/validator.ts +113 -113
- package/server/modules/orchestration/hermes/hermes.routes.ts +642 -583
- package/server/modules/orchestration/index.ts +101 -100
- package/server/modules/orchestration/preview/port-watcher.ts +112 -112
- package/server/modules/orchestration/preview/preview-proxy.ts +60 -60
- package/server/modules/orchestration/preview/types.ts +19 -19
- package/server/modules/orchestration/security/permission-policy.ts +401 -401
- package/server/modules/orchestration/tasks/orchestration-task-store.ts +41 -41
- package/server/modules/orchestration/tasks/orchestration-task.routes.ts +64 -64
- package/server/modules/orchestration/tasks/orchestration-task.service.ts +209 -209
- package/server/modules/orchestration/tasks/orchestration-task.types.ts +40 -40
- package/server/modules/orchestration/tasks/task-run-graph.ts +155 -155
- package/server/modules/orchestration/workflows/approval-queue.ts +106 -106
- package/server/modules/orchestration/workflows/built-in-workflows.ts +127 -127
- package/server/modules/orchestration/workflows/context-packet.ts +186 -186
- package/server/modules/orchestration/workflows/handoff-artifact.ts +175 -175
- package/server/modules/orchestration/workflows/workflow-fallback-policy.ts +161 -161
- package/server/modules/orchestration/workflows/workflow-replay.ts +254 -254
- package/server/modules/orchestration/workflows/workflow-runner.ts +2070 -2070
- package/server/modules/orchestration/workflows/workflow-store.ts +97 -97
- package/server/modules/orchestration/workflows/workflow-templates.ts +272 -272
- package/server/modules/orchestration/workflows/workflow-trace.ts +424 -424
- package/server/modules/orchestration/workflows/workflow.routes.ts +586 -586
- package/server/modules/orchestration/workflows/workflow.types.ts +111 -111
- package/server/modules/orchestration/workflows/workspace-target.ts +122 -122
- package/server/modules/orchestration/workspace/docker-workspace.ts +136 -136
- package/server/modules/orchestration/workspace/path-safety.ts +55 -55
- package/server/modules/orchestration/workspace/types.ts +52 -52
- package/server/modules/orchestration/workspace/workspace-manager.ts +102 -102
- package/server/modules/orchestration/workspace/worktree-workspace.ts +126 -126
- package/server/modules/providers/index.ts +2 -2
- package/server/modules/providers/list/claude/claude-auth.provider.ts +146 -146
- package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -135
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +306 -306
- package/server/modules/providers/list/claude/claude.provider.ts +15 -15
- package/server/modules/providers/list/codex/codex-auth.provider.ts +117 -117
- package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -135
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +319 -319
- package/server/modules/providers/list/codex/codex.provider.ts +15 -15
- package/server/modules/providers/list/cursor/cursor-auth.provider.ts +147 -147
- package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -108
- package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +421 -421
- package/server/modules/providers/list/cursor/cursor.provider.ts +15 -15
- package/server/modules/providers/list/gemini/gemini-auth.provider.ts +173 -173
- package/server/modules/providers/list/gemini/gemini-mcp.provider.ts +110 -110
- package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +227 -227
- package/server/modules/providers/list/gemini/gemini.provider.ts +15 -15
- package/server/modules/providers/list/opencode/opencode-auth.provider.ts +131 -131
- package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +126 -126
- package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +286 -286
- package/server/modules/providers/list/opencode/opencode.provider.ts +29 -29
- package/server/modules/providers/list/qwen/qwen-auth.provider.ts +146 -146
- package/server/modules/providers/list/qwen/qwen-mcp.provider.ts +114 -114
- package/server/modules/providers/list/qwen/qwen-sessions.provider.ts +265 -265
- package/server/modules/providers/list/qwen/qwen.provider.ts +21 -21
- package/server/modules/providers/provider.registry.ts +40 -40
- package/server/modules/providers/provider.routes.ts +944 -944
- package/server/modules/providers/services/mcp.service.ts +86 -86
- package/server/modules/providers/services/provider-auth.service.ts +26 -26
- package/server/modules/providers/services/sessions.service.ts +45 -45
- package/server/modules/providers/shared/base/abstract.provider.ts +20 -20
- package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -151
- package/server/modules/providers/shared/provider-configs.ts +142 -142
- package/server/modules/providers/tests/mcp.test.ts +293 -293
- package/server/openai-codex.js +462 -462
- package/server/opencode-cli.js +491 -491
- package/server/opencode-response-handler.js +111 -111
- package/server/projects.js +3008 -3008
- package/server/qwen-code-cli.js +410 -410
- package/server/qwen-response-handler.js +73 -73
- package/server/routes/agent.js +1435 -1435
- package/server/routes/auth.js +154 -146
- package/server/routes/codex.js +20 -20
- package/server/routes/commands.js +570 -570
- package/server/routes/cursor.js +61 -61
- package/server/routes/diagnostics.js +41 -41
- package/server/routes/gemini.js +25 -25
- package/server/routes/git.js +1650 -1635
- package/server/routes/live-view.js +411 -411
- package/server/routes/mcp-utils.js +13 -13
- package/server/routes/messages.js +62 -62
- package/server/routes/network.js +125 -125
- package/server/routes/platformization.js +198 -197
- package/server/routes/plugins.js +320 -320
- package/server/routes/production-agent-loop.js +90 -90
- package/server/routes/projects.js +917 -917
- package/server/routes/public-api.js +34 -34
- package/server/routes/qwen.js +27 -27
- package/server/routes/remote.js +55 -55
- package/server/routes/settings.js +321 -321
- package/server/routes/telegram.js +140 -140
- package/server/routes/user.js +125 -125
- package/server/routes/webhooks.js +63 -63
- package/server/services/control-room.js +102 -102
- package/server/services/diagnostics.js +165 -165
- package/server/services/external-access.js +375 -375
- package/server/services/hermes-gateway.js +1562 -1247
- package/server/services/hermes-install-jobs.js +729 -729
- package/server/services/install-jobs.js +715 -715
- package/server/services/live-view.js +956 -956
- package/server/services/managed-runtimes.js +493 -493
- package/server/services/model-registry.js +144 -144
- package/server/services/notification-orchestrator.js +365 -365
- package/server/services/notification-taxonomy.js +204 -204
- package/server/services/platformization.js +844 -779
- package/server/services/production-agent-loop.js +248 -248
- package/server/services/provider-cli-versions.js +149 -149
- package/server/services/provider-credentials.js +189 -189
- package/server/services/provider-models.js +396 -396
- package/server/services/public-api-manifest.js +190 -182
- package/server/services/remote-connection.js +127 -127
- package/server/services/runtime-manager.js +323 -323
- package/server/services/startup-update.js +234 -234
- package/server/services/telegram/bot.js +331 -331
- package/server/services/telegram/control-center.js +979 -979
- package/server/services/telegram/telegram-http-client.js +151 -151
- package/server/services/telegram/translations.js +340 -340
- package/server/services/vapid-keys.js +36 -36
- package/server/services/webhooks.js +216 -216
- package/server/sessionManager.js +225 -225
- package/server/shared/interfaces.ts +54 -54
- package/server/shared/types.ts +172 -172
- package/server/shared/utils.ts +193 -193
- package/server/tsconfig.json +36 -36
- package/server/utils/colors.js +21 -21
- package/server/utils/commandParser.js +305 -305
- package/server/utils/frontmatter.js +18 -18
- package/server/utils/gitConfig.js +34 -34
- package/server/utils/plugin-loader.js +457 -457
- package/server/utils/plugin-process-manager.js +185 -185
- package/server/utils/port-access.js +209 -209
- package/server/utils/runtime-paths.js +37 -37
- package/server/utils/url-detection.js +71 -71
- package/server/vite-daemon.js +79 -79
- package/shared/modelConstants.js +161 -161
- package/shared/networkHosts.js +22 -22
- package/dist/assets/index-DMz0zv6T.css +0 -32
|
@@ -1,151 +1,151 @@
|
|
|
1
|
-
import { EventEmitter } from 'node:events';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Minimal Telegram Bot API client.
|
|
5
|
-
*
|
|
6
|
-
* Replaces `node-telegram-bot-api` which pulled in the deprecated
|
|
7
|
-
* `request` / `har-validator` / `uuid@3` chain (~30 transitive packages,
|
|
8
|
-
* npm install warnings on every fresh box). The Bot API itself is just
|
|
9
|
-
* HTTP, and we only use a few endpoints (getUpdates polling + sendMessage +
|
|
10
|
-
* callback answers + message edits),
|
|
11
|
-
* so 100 lines of fetch is all that's needed. Exposes the same surface
|
|
12
|
-
* the bot.js consumer relied on: `getMe()`, `sendMessage()`,
|
|
13
|
-
* `editMessageText()`, `answerCallbackQuery()`,
|
|
14
|
-
* `on('message'|'callback_query'|'polling_error')`, `stopPolling()`.
|
|
15
|
-
*
|
|
16
|
-
* No third-party deps — uses Node 22's built-in `fetch`.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
const API_BASE = 'https://api.telegram.org/bot';
|
|
20
|
-
|
|
21
|
-
class TelegramApiError extends Error {
|
|
22
|
-
constructor(method, body, httpStatus) {
|
|
23
|
-
const description = body?.description || `HTTP ${httpStatus}`;
|
|
24
|
-
super(`Telegram ${method} failed: ${description}`);
|
|
25
|
-
this.name = 'TelegramApiError';
|
|
26
|
-
this.method = method;
|
|
27
|
-
this.httpStatus = httpStatus;
|
|
28
|
-
// Mirror the shape node-telegram-bot-api exposed so upstream error
|
|
29
|
-
// handling (401/409 checks in bot.js) keeps working unchanged.
|
|
30
|
-
this.response = { statusCode: httpStatus, body };
|
|
31
|
-
this.code = body?.error_code || httpStatus;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Call a Bot API method by name. Returns the `result` field on success,
|
|
37
|
-
* throws a TelegramApiError otherwise.
|
|
38
|
-
*/
|
|
39
|
-
async function callApi(token, method, params, { signal } = {}) {
|
|
40
|
-
const url = `${API_BASE}${token}/${method}`;
|
|
41
|
-
const res = await fetch(url, {
|
|
42
|
-
method: 'POST',
|
|
43
|
-
headers: { 'Content-Type': 'application/json' },
|
|
44
|
-
body: JSON.stringify(params || {}),
|
|
45
|
-
signal,
|
|
46
|
-
});
|
|
47
|
-
let body;
|
|
48
|
-
try { body = await res.json(); } catch { body = null; }
|
|
49
|
-
if (!res.ok || !body?.ok) {
|
|
50
|
-
throw new TelegramApiError(method, body, res.status);
|
|
51
|
-
}
|
|
52
|
-
return body.result;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export class TelegramHttpBot extends EventEmitter {
|
|
56
|
-
constructor(token, { polling = true, pollTimeoutSec = 30 } = {}) {
|
|
57
|
-
super();
|
|
58
|
-
if (!token) throw new Error('TelegramHttpBot: token is required');
|
|
59
|
-
this._token = token;
|
|
60
|
-
this._pollTimeoutSec = pollTimeoutSec;
|
|
61
|
-
this._offset = 0;
|
|
62
|
-
this._polling = false;
|
|
63
|
-
this._abortController = null;
|
|
64
|
-
if (polling) this._startPolling();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// ---------- Public API (mirrors node-telegram-bot-api surface) ----------
|
|
68
|
-
|
|
69
|
-
async getMe() {
|
|
70
|
-
return callApi(this._token, 'getMe', {});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async sendMessage(chatId, text, extra = {}) {
|
|
74
|
-
return callApi(this._token, 'sendMessage', {
|
|
75
|
-
chat_id: chatId,
|
|
76
|
-
text,
|
|
77
|
-
...extra,
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async editMessageText(text, extra = {}) {
|
|
82
|
-
return callApi(this._token, 'editMessageText', {
|
|
83
|
-
text,
|
|
84
|
-
...extra,
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
async answerCallbackQuery(callbackQueryId, extra = {}) {
|
|
89
|
-
return callApi(this._token, 'answerCallbackQuery', {
|
|
90
|
-
callback_query_id: callbackQueryId,
|
|
91
|
-
...extra,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
async stopPolling(_opts = {}) {
|
|
96
|
-
this._polling = false;
|
|
97
|
-
try { this._abortController?.abort(); } catch { /* ignore */ }
|
|
98
|
-
this._abortController = null;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// ---------- Polling loop ----------
|
|
102
|
-
|
|
103
|
-
async _startPolling() {
|
|
104
|
-
this._polling = true;
|
|
105
|
-
// Kick off a non-awaited loop. Each iteration long-polls getUpdates for
|
|
106
|
-
// up to pollTimeoutSec, then loops immediately. We deliberately serialize
|
|
107
|
-
// (no concurrent long-polls) because Telegram rejects that with 409.
|
|
108
|
-
(async () => {
|
|
109
|
-
while (this._polling) {
|
|
110
|
-
this._abortController = new AbortController();
|
|
111
|
-
try {
|
|
112
|
-
const updates = await callApi(
|
|
113
|
-
this._token,
|
|
114
|
-
'getUpdates',
|
|
115
|
-
{
|
|
116
|
-
offset: this._offset,
|
|
117
|
-
timeout: this._pollTimeoutSec,
|
|
118
|
-
allowed_updates: ['message', 'callback_query'],
|
|
119
|
-
},
|
|
120
|
-
{ signal: this._abortController.signal },
|
|
121
|
-
);
|
|
122
|
-
for (const update of updates) {
|
|
123
|
-
if (typeof update.update_id === 'number') {
|
|
124
|
-
this._offset = Math.max(this._offset, update.update_id + 1);
|
|
125
|
-
}
|
|
126
|
-
if (update.message) {
|
|
127
|
-
try { this.emit('message', update.message); } catch (err) {
|
|
128
|
-
// Don't let a listener exception break the poll loop.
|
|
129
|
-
this.emit('polling_error', err);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
if (update.callback_query) {
|
|
133
|
-
try { this.emit('callback_query', update.callback_query); } catch (err) {
|
|
134
|
-
this.emit('polling_error', err);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
} catch (err) {
|
|
139
|
-
// AbortError is the expected path when stopPolling() is called.
|
|
140
|
-
if (err?.name === 'AbortError' || !this._polling) break;
|
|
141
|
-
this.emit('polling_error', err);
|
|
142
|
-
// Back off before retrying — rapid retries on 401/409 would
|
|
143
|
-
// otherwise spin at 100% CPU. Upstream consumer's polling_error
|
|
144
|
-
// handler may also call stopBot() on 401/409 which flips _polling
|
|
145
|
-
// off and breaks the loop on the next tick.
|
|
146
|
-
await new Promise((r) => setTimeout(r, 2000));
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
})();
|
|
150
|
-
}
|
|
151
|
-
}
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Minimal Telegram Bot API client.
|
|
5
|
+
*
|
|
6
|
+
* Replaces `node-telegram-bot-api` which pulled in the deprecated
|
|
7
|
+
* `request` / `har-validator` / `uuid@3` chain (~30 transitive packages,
|
|
8
|
+
* npm install warnings on every fresh box). The Bot API itself is just
|
|
9
|
+
* HTTP, and we only use a few endpoints (getUpdates polling + sendMessage +
|
|
10
|
+
* callback answers + message edits),
|
|
11
|
+
* so 100 lines of fetch is all that's needed. Exposes the same surface
|
|
12
|
+
* the bot.js consumer relied on: `getMe()`, `sendMessage()`,
|
|
13
|
+
* `editMessageText()`, `answerCallbackQuery()`,
|
|
14
|
+
* `on('message'|'callback_query'|'polling_error')`, `stopPolling()`.
|
|
15
|
+
*
|
|
16
|
+
* No third-party deps — uses Node 22's built-in `fetch`.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const API_BASE = 'https://api.telegram.org/bot';
|
|
20
|
+
|
|
21
|
+
class TelegramApiError extends Error {
|
|
22
|
+
constructor(method, body, httpStatus) {
|
|
23
|
+
const description = body?.description || `HTTP ${httpStatus}`;
|
|
24
|
+
super(`Telegram ${method} failed: ${description}`);
|
|
25
|
+
this.name = 'TelegramApiError';
|
|
26
|
+
this.method = method;
|
|
27
|
+
this.httpStatus = httpStatus;
|
|
28
|
+
// Mirror the shape node-telegram-bot-api exposed so upstream error
|
|
29
|
+
// handling (401/409 checks in bot.js) keeps working unchanged.
|
|
30
|
+
this.response = { statusCode: httpStatus, body };
|
|
31
|
+
this.code = body?.error_code || httpStatus;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Call a Bot API method by name. Returns the `result` field on success,
|
|
37
|
+
* throws a TelegramApiError otherwise.
|
|
38
|
+
*/
|
|
39
|
+
async function callApi(token, method, params, { signal } = {}) {
|
|
40
|
+
const url = `${API_BASE}${token}/${method}`;
|
|
41
|
+
const res = await fetch(url, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: { 'Content-Type': 'application/json' },
|
|
44
|
+
body: JSON.stringify(params || {}),
|
|
45
|
+
signal,
|
|
46
|
+
});
|
|
47
|
+
let body;
|
|
48
|
+
try { body = await res.json(); } catch { body = null; }
|
|
49
|
+
if (!res.ok || !body?.ok) {
|
|
50
|
+
throw new TelegramApiError(method, body, res.status);
|
|
51
|
+
}
|
|
52
|
+
return body.result;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export class TelegramHttpBot extends EventEmitter {
|
|
56
|
+
constructor(token, { polling = true, pollTimeoutSec = 30 } = {}) {
|
|
57
|
+
super();
|
|
58
|
+
if (!token) throw new Error('TelegramHttpBot: token is required');
|
|
59
|
+
this._token = token;
|
|
60
|
+
this._pollTimeoutSec = pollTimeoutSec;
|
|
61
|
+
this._offset = 0;
|
|
62
|
+
this._polling = false;
|
|
63
|
+
this._abortController = null;
|
|
64
|
+
if (polling) this._startPolling();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ---------- Public API (mirrors node-telegram-bot-api surface) ----------
|
|
68
|
+
|
|
69
|
+
async getMe() {
|
|
70
|
+
return callApi(this._token, 'getMe', {});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async sendMessage(chatId, text, extra = {}) {
|
|
74
|
+
return callApi(this._token, 'sendMessage', {
|
|
75
|
+
chat_id: chatId,
|
|
76
|
+
text,
|
|
77
|
+
...extra,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async editMessageText(text, extra = {}) {
|
|
82
|
+
return callApi(this._token, 'editMessageText', {
|
|
83
|
+
text,
|
|
84
|
+
...extra,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async answerCallbackQuery(callbackQueryId, extra = {}) {
|
|
89
|
+
return callApi(this._token, 'answerCallbackQuery', {
|
|
90
|
+
callback_query_id: callbackQueryId,
|
|
91
|
+
...extra,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async stopPolling(_opts = {}) {
|
|
96
|
+
this._polling = false;
|
|
97
|
+
try { this._abortController?.abort(); } catch { /* ignore */ }
|
|
98
|
+
this._abortController = null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ---------- Polling loop ----------
|
|
102
|
+
|
|
103
|
+
async _startPolling() {
|
|
104
|
+
this._polling = true;
|
|
105
|
+
// Kick off a non-awaited loop. Each iteration long-polls getUpdates for
|
|
106
|
+
// up to pollTimeoutSec, then loops immediately. We deliberately serialize
|
|
107
|
+
// (no concurrent long-polls) because Telegram rejects that with 409.
|
|
108
|
+
(async () => {
|
|
109
|
+
while (this._polling) {
|
|
110
|
+
this._abortController = new AbortController();
|
|
111
|
+
try {
|
|
112
|
+
const updates = await callApi(
|
|
113
|
+
this._token,
|
|
114
|
+
'getUpdates',
|
|
115
|
+
{
|
|
116
|
+
offset: this._offset,
|
|
117
|
+
timeout: this._pollTimeoutSec,
|
|
118
|
+
allowed_updates: ['message', 'callback_query'],
|
|
119
|
+
},
|
|
120
|
+
{ signal: this._abortController.signal },
|
|
121
|
+
);
|
|
122
|
+
for (const update of updates) {
|
|
123
|
+
if (typeof update.update_id === 'number') {
|
|
124
|
+
this._offset = Math.max(this._offset, update.update_id + 1);
|
|
125
|
+
}
|
|
126
|
+
if (update.message) {
|
|
127
|
+
try { this.emit('message', update.message); } catch (err) {
|
|
128
|
+
// Don't let a listener exception break the poll loop.
|
|
129
|
+
this.emit('polling_error', err);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (update.callback_query) {
|
|
133
|
+
try { this.emit('callback_query', update.callback_query); } catch (err) {
|
|
134
|
+
this.emit('polling_error', err);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
} catch (err) {
|
|
139
|
+
// AbortError is the expected path when stopPolling() is called.
|
|
140
|
+
if (err?.name === 'AbortError' || !this._polling) break;
|
|
141
|
+
this.emit('polling_error', err);
|
|
142
|
+
// Back off before retrying — rapid retries on 401/409 would
|
|
143
|
+
// otherwise spin at 100% CPU. Upstream consumer's polling_error
|
|
144
|
+
// handler may also call stopBot() on 401/409 which flips _polling
|
|
145
|
+
// off and breaks the loop on the next tick.
|
|
146
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
})();
|
|
150
|
+
}
|
|
151
|
+
}
|