@shepai/cli 1.154.0 → 1.155.0-pr482.ac79b36
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/apis/json-schema/Settings.yaml +3 -0
- package/apis/json-schema/TelegramCommandType.yaml +11 -0
- package/apis/json-schema/TelegramConfig.yaml +21 -0
- package/apis/json-schema/TelegramNotifyEvents.yaml +61 -0
- package/dist/packages/core/src/application/ports/output/services/telegram-service.interface.d.ts +92 -0
- package/dist/packages/core/src/application/ports/output/services/telegram-service.interface.d.ts.map +1 -0
- package/dist/packages/core/src/application/ports/output/services/telegram-service.interface.js +37 -0
- package/dist/packages/core/src/application/use-cases/telegram/configure-telegram.use-case.d.ts +42 -0
- package/dist/packages/core/src/application/use-cases/telegram/configure-telegram.use-case.d.ts.map +1 -0
- package/dist/packages/core/src/application/use-cases/telegram/configure-telegram.use-case.js +108 -0
- package/dist/packages/core/src/domain/generated/output.d.ts +82 -0
- package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
- package/dist/packages/core/src/domain/generated/output.js +9 -0
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +12 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts +14 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.js +34 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/049-add-telegram-settings.d.ts +17 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/049-add-telegram-settings.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/049-add-telegram-settings.js +40 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.js +4 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/pr-branding.d.ts +5 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/pr-branding.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/pr-branding.js +4 -0
- package/dist/packages/core/src/infrastructure/services/deployment/deployment.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/deployment/deployment.service.js +6 -5
- package/dist/packages/core/src/infrastructure/services/deployment/detect-dev-script.d.ts +2 -0
- package/dist/packages/core/src/infrastructure/services/deployment/detect-dev-script.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/deployment/detect-dev-script.js +52 -3
- package/dist/packages/core/src/infrastructure/services/git/git-fork.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/git/git-fork.service.js +3 -1
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.js +2 -1
- package/dist/packages/core/src/infrastructure/services/git/pr-branding.d.ts +17 -0
- package/dist/packages/core/src/infrastructure/services/git/pr-branding.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/git/pr-branding.js +31 -0
- package/dist/packages/core/src/infrastructure/services/notifications/notification.service.d.ts +9 -1
- package/dist/packages/core/src/infrastructure/services/notifications/notification.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/notifications/notification.service.js +40 -1
- package/dist/packages/core/src/infrastructure/services/telegram/telegram.service.d.ts +22 -0
- package/dist/packages/core/src/infrastructure/services/telegram/telegram.service.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/telegram/telegram.service.js +128 -0
- package/dist/src/presentation/cli/commands/settings/index.d.ts +1 -0
- package/dist/src/presentation/cli/commands/settings/index.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/settings/index.js +4 -1
- package/dist/src/presentation/cli/commands/settings/telegram.command.d.ts +18 -0
- package/dist/src/presentation/cli/commands/settings/telegram.command.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/settings/telegram.command.js +158 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +3 -3
- package/web/.next/required-server-files.json +3 -3
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +28 -28
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/chat/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/@drawer/chat/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/chat/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +29 -29
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +36 -36
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +36 -36
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/chat/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +29 -29
- package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +36 -36
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +36 -36
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page/server-reference-manifest.json +5 -5
- package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/settings/page/server-reference-manifest.json +8 -8
- package/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/skills/page/server-reference-manifest.json +10 -10
- package/web/.next/server/app/skills/page.js.nft.json +1 -1
- package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/tools/page/server-reference-manifest.json +10 -10
- package/web/.next/server/app/tools/page.js.nft.json +1 -1
- package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page/server-reference-manifest.json +5 -5
- package/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__beda892a._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__beda892a._.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js +2 -2
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__0b150ddf._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__17ed7ed1._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__17ed7ed1._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__28d0d265._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__28d0d265._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__42bf1807._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__42bf1807._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__56b70465._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__56b70465._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__88f7e8e6._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__88f7e8e6._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8b0aac03._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c30f1f82._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c30f1f82._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f80bfc75._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f80bfc75._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f8dd4422._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f8dd4422._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_4af8a3cb._.js → _002d7e8d._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_4af8a3cb._.js.map → _002d7e8d._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_05c23ad9._.js +1 -1
- package/web/.next/server/chunks/ssr/_05c23ad9._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_16eb4fec._.js +1 -1
- package/web/.next/server/chunks/ssr/_16eb4fec._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_3a0b989f._.js +2 -2
- package/web/.next/server/chunks/ssr/_3a0b989f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_56b9d60f._.js +1 -1
- package/web/.next/server/chunks/ssr/_56b9d60f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_5f69c13f._.js +1 -1
- package/web/.next/server/chunks/ssr/_5f69c13f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_7c5b97c6._.js +1 -1
- package/web/.next/server/chunks/ssr/_7c5b97c6._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_82c57f10._.js +1 -1
- package/web/.next/server/chunks/ssr/_82c57f10._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_a0e4c32f._.js → _912552dd._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_a0e4c32f._.js.map → _912552dd._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_9495d50b._.js +1 -1
- package/web/.next/server/chunks/ssr/_9495d50b._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_27154347._.js → _97486b47._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_27154347._.js.map → _97486b47._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_a0e3f7e4._.js +1 -1
- package/web/.next/server/chunks/ssr/_a0e3f7e4._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_ac4a3873._.js +1 -1
- package/web/.next/server/chunks/ssr/_ca0aa7f0._.js +1 -1
- package/web/.next/server/chunks/ssr/_ca0aa7f0._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_cb5a021e._.js +1 -1
- package/web/.next/server/chunks/ssr/_cb5a021e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_d4b20e29._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_d86175ae._.js +1 -1
- package/web/.next/server/chunks/ssr/_d86175ae._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_d8bedf13._.js +1 -1
- package/web/.next/server/chunks/ssr/_d8bedf13._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_fa7efce3._.js +2 -2
- package/web/.next/server/chunks/ssr/_fa7efce3._.js.map +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_cdc632e3.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_cdc632e3.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_39ca0924.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_39ca0924.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_357e3eb0._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_357e3eb0._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +45 -45
- package/web/.next/static/chunks/13d4e516b0ecf5f0.js +1 -0
- package/web/.next/static/chunks/{f10c138c3fae4680.js → 6c5e7b36525b3532.js} +1 -1
- package/web/.next/static/chunks/{e0104cdb4b857e49.js → 818689ed2c41772b.js} +1 -1
- package/web/.next/static/chunks/{be495f0642b9f423.js → 8208e717057eedd0.js} +1 -1
- package/web/.next/static/chunks/{2eb2e32a6181e9ed.js → a07d5cbafca0277c.js} +1 -1
- package/web/.next/static/chunks/{9545412c334d71c5.js → ad67307f6b0c1490.js} +1 -1
- package/web/.next/static/chunks/{a18fcdf7dd4055a5.js → b4e5c56e14e63cb0.js} +2 -2
- package/web/.next/static/chunks/{ae61d24b1bcc8cf7.js → b6fc216cfa8fa52a.js} +2 -2
- package/web/.next/static/chunks/{0e258f8cce588570.js → d1c58b0747b10ae5.js} +1 -1
- package/web/.next/static/chunks/{e9cce6c925c64f10.js → d5cbc603b8bb904d.js} +1 -1
- package/web/.next/static/chunks/{e333a91862ff2423.js → deef7f0b5f7981e8.js} +1 -1
- package/web/.next/static/chunks/{b5bf0ff0a2bc910a.js → e664cd5c9c0f4fd4.js} +1 -1
- package/web/.next/static/chunks/502fd2cb6c8beb89.js +0 -1
- /package/web/.next/static/{9ZnNgGSTMM2ACNp4ImvQo → fX8_4OoVzGj6K0VH9X7nb}/_buildManifest.js +0 -0
- /package/web/.next/static/{9ZnNgGSTMM2ACNp4ImvQo → fX8_4OoVzGj6K0VH9X7nb}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{9ZnNgGSTMM2ACNp4ImvQo → fX8_4OoVzGj6K0VH9X7nb}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telegram Service Implementation
|
|
3
|
+
*
|
|
4
|
+
* Implements the ITelegramService port using the Telegram Bot HTTP API.
|
|
5
|
+
* Uses native `fetch` (available in Node 18+) — no external SDK required.
|
|
6
|
+
*
|
|
7
|
+
* All methods are stateless; bot token and chat ID are passed as parameters
|
|
8
|
+
* so the service can be used for validation before persisting config.
|
|
9
|
+
*/
|
|
10
|
+
import type { NotificationEvent } from '../../../domain/generated/output.js';
|
|
11
|
+
import type { ITelegramService, TelegramBotInfo, TelegramChatResolution } from '../../../application/ports/output/services/telegram-service.interface.js';
|
|
12
|
+
export declare class TelegramService implements ITelegramService {
|
|
13
|
+
validateBotToken(botToken: string): Promise<TelegramBotInfo>;
|
|
14
|
+
resolveChatId(botToken: string): Promise<TelegramChatResolution>;
|
|
15
|
+
sendMessage(botToken: string, chatId: string, text: string): Promise<void>;
|
|
16
|
+
sendNotification(botToken: string, chatId: string, event: NotificationEvent): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Escape HTML special characters for Telegram's HTML parse mode.
|
|
19
|
+
*/
|
|
20
|
+
private escapeHtml;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=telegram.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telegram.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/telegram/telegram.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAE7E,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,sBAAsB,EACvB,MAAM,0EAA0E,CAAC;AA2ClF,qBAAa,eAAgB,YAAW,gBAAgB;IAChD,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IA6B5D,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IA0ChE,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B1E,gBAAgB,CACpB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,IAAI,CAAC;IAgBhB;;OAEG;IACH,OAAO,CAAC,UAAU;CAGnB"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telegram Service Implementation
|
|
3
|
+
*
|
|
4
|
+
* Implements the ITelegramService port using the Telegram Bot HTTP API.
|
|
5
|
+
* Uses native `fetch` (available in Node 18+) — no external SDK required.
|
|
6
|
+
*
|
|
7
|
+
* All methods are stateless; bot token and chat ID are passed as parameters
|
|
8
|
+
* so the service can be used for validation before persisting config.
|
|
9
|
+
*/
|
|
10
|
+
import { NotificationEventType } from '../../../domain/generated/output.js';
|
|
11
|
+
import { TelegramAuthError, TelegramNoChatError, TelegramSendError, } from '../../../application/ports/output/services/telegram-service.interface.js';
|
|
12
|
+
const TELEGRAM_API_BASE = 'https://api.telegram.org/bot';
|
|
13
|
+
/**
|
|
14
|
+
* Human-readable labels for notification event types.
|
|
15
|
+
*/
|
|
16
|
+
const EVENT_LABELS = {
|
|
17
|
+
[NotificationEventType.AgentStarted]: 'Agent Started',
|
|
18
|
+
[NotificationEventType.PhaseCompleted]: 'Phase Completed',
|
|
19
|
+
[NotificationEventType.WaitingApproval]: 'Waiting for Approval',
|
|
20
|
+
[NotificationEventType.AgentCompleted]: 'Agent Completed',
|
|
21
|
+
[NotificationEventType.AgentFailed]: 'Agent Failed',
|
|
22
|
+
[NotificationEventType.PrMerged]: 'PR Merged',
|
|
23
|
+
[NotificationEventType.PrClosed]: 'PR Closed',
|
|
24
|
+
[NotificationEventType.PrChecksPassed]: 'PR Checks Passed',
|
|
25
|
+
[NotificationEventType.PrChecksFailed]: 'PR Checks Failed',
|
|
26
|
+
[NotificationEventType.PrBlocked]: 'PR Blocked',
|
|
27
|
+
[NotificationEventType.MergeReviewReady]: 'Merge Review Ready',
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Emoji indicators for notification event types.
|
|
31
|
+
*/
|
|
32
|
+
const EVENT_EMOJI = {
|
|
33
|
+
[NotificationEventType.AgentStarted]: '\u{1F680}',
|
|
34
|
+
[NotificationEventType.PhaseCompleted]: '\u2705',
|
|
35
|
+
[NotificationEventType.WaitingApproval]: '\u23F3',
|
|
36
|
+
[NotificationEventType.AgentCompleted]: '\u{1F389}',
|
|
37
|
+
[NotificationEventType.AgentFailed]: '\u274C',
|
|
38
|
+
[NotificationEventType.PrMerged]: '\u{1F7E2}',
|
|
39
|
+
[NotificationEventType.PrClosed]: '\u{1F534}',
|
|
40
|
+
[NotificationEventType.PrChecksPassed]: '\u2705',
|
|
41
|
+
[NotificationEventType.PrChecksFailed]: '\u274C',
|
|
42
|
+
[NotificationEventType.PrBlocked]: '\u26A0\uFE0F',
|
|
43
|
+
[NotificationEventType.MergeReviewReady]: '\u{1F4CB}',
|
|
44
|
+
};
|
|
45
|
+
export class TelegramService {
|
|
46
|
+
async validateBotToken(botToken) {
|
|
47
|
+
const url = `${TELEGRAM_API_BASE}${botToken}/getMe`;
|
|
48
|
+
let response;
|
|
49
|
+
try {
|
|
50
|
+
response = await fetch(url);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
throw new TelegramAuthError(`Failed to connect to Telegram API: ${error instanceof Error ? error.message : String(error)}`);
|
|
54
|
+
}
|
|
55
|
+
const body = (await response.json());
|
|
56
|
+
if (!body.ok || !body.result) {
|
|
57
|
+
throw new TelegramAuthError(body.description ?? 'Invalid bot token');
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
id: body.result.id,
|
|
61
|
+
firstName: body.result.first_name,
|
|
62
|
+
username: body.result.username,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
async resolveChatId(botToken) {
|
|
66
|
+
const url = `${TELEGRAM_API_BASE}${botToken}/getUpdates?limit=10&allowed_updates=["message"]`;
|
|
67
|
+
let response;
|
|
68
|
+
try {
|
|
69
|
+
response = await fetch(url);
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
throw new TelegramNoChatError(`Failed to connect to Telegram API: ${error instanceof Error ? error.message : String(error)}`);
|
|
73
|
+
}
|
|
74
|
+
const body = (await response.json());
|
|
75
|
+
if (!body.ok || !body.result) {
|
|
76
|
+
throw new TelegramNoChatError('Failed to fetch bot updates');
|
|
77
|
+
}
|
|
78
|
+
// Look for a /start message
|
|
79
|
+
const startUpdate = body.result.find((update) => update.message?.text === '/start');
|
|
80
|
+
if (!startUpdate?.message) {
|
|
81
|
+
throw new TelegramNoChatError('No /start message found. Please send /start to your bot on Telegram first, then retry.');
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
chatId: String(startUpdate.message.chat.id),
|
|
85
|
+
firstName: startUpdate.message.from?.first_name ?? 'Unknown',
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
async sendMessage(botToken, chatId, text) {
|
|
89
|
+
const url = `${TELEGRAM_API_BASE}${botToken}/sendMessage`;
|
|
90
|
+
let response;
|
|
91
|
+
try {
|
|
92
|
+
response = await fetch(url, {
|
|
93
|
+
method: 'POST',
|
|
94
|
+
headers: { 'Content-Type': 'application/json' },
|
|
95
|
+
body: JSON.stringify({
|
|
96
|
+
chat_id: chatId,
|
|
97
|
+
text,
|
|
98
|
+
parse_mode: 'HTML',
|
|
99
|
+
}),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
throw new TelegramSendError(`Failed to send Telegram message: ${error instanceof Error ? error.message : String(error)}`);
|
|
104
|
+
}
|
|
105
|
+
const body = (await response.json());
|
|
106
|
+
if (!body.ok) {
|
|
107
|
+
throw new TelegramSendError(`Telegram API error: ${body.description ?? 'Unknown error'}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async sendNotification(botToken, chatId, event) {
|
|
111
|
+
const emoji = EVENT_EMOJI[event.eventType] ?? '';
|
|
112
|
+
const label = EVENT_LABELS[event.eventType] ?? event.eventType;
|
|
113
|
+
const lines = [
|
|
114
|
+
`${emoji} <b>${label}</b>`,
|
|
115
|
+
`Feature: ${this.escapeHtml(event.featureName)}`,
|
|
116
|
+
];
|
|
117
|
+
if (event.message) {
|
|
118
|
+
lines.push(`\n${this.escapeHtml(event.message)}`);
|
|
119
|
+
}
|
|
120
|
+
await this.sendMessage(botToken, chatId, lines.join('\n'));
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Escape HTML special characters for Telegram's HTML parse mode.
|
|
124
|
+
*/
|
|
125
|
+
escapeHtml(text) {
|
|
126
|
+
return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* shep settings ide # Configure preferred IDE
|
|
13
13
|
* shep settings workflow # Configure workflow defaults
|
|
14
14
|
* shep settings model # Configure default LLM model
|
|
15
|
+
* shep settings telegram # Configure Telegram remote control
|
|
15
16
|
*/
|
|
16
17
|
import { Command } from 'commander';
|
|
17
18
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/settings/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/settings/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAuB/C"}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* shep settings ide # Configure preferred IDE
|
|
13
13
|
* shep settings workflow # Configure workflow defaults
|
|
14
14
|
* shep settings model # Configure default LLM model
|
|
15
|
+
* shep settings telegram # Configure Telegram remote control
|
|
15
16
|
*/
|
|
16
17
|
import { Command } from 'commander';
|
|
17
18
|
import { createShowCommand } from './show.command.js';
|
|
@@ -20,6 +21,7 @@ import { createAgentCommand } from './agent.command.js';
|
|
|
20
21
|
import { createIdeCommand } from './ide.command.js';
|
|
21
22
|
import { createWorkflowCommand } from './workflow.command.js';
|
|
22
23
|
import { createModelCommand } from './model.command.js';
|
|
24
|
+
import { createTelegramCommand } from './telegram.command.js';
|
|
23
25
|
import { onboardingWizard } from '../../../tui/wizards/onboarding/onboarding.wizard.js';
|
|
24
26
|
import { messages } from '../../ui/index.js';
|
|
25
27
|
/**
|
|
@@ -33,7 +35,8 @@ export function createSettingsCommand() {
|
|
|
33
35
|
.addCommand(createAgentCommand())
|
|
34
36
|
.addCommand(createIdeCommand())
|
|
35
37
|
.addCommand(createWorkflowCommand())
|
|
36
|
-
.addCommand(createModelCommand())
|
|
38
|
+
.addCommand(createModelCommand())
|
|
39
|
+
.addCommand(createTelegramCommand());
|
|
37
40
|
// Default action: launch the full setup wizard when no subcommand is given
|
|
38
41
|
cmd.action(async () => {
|
|
39
42
|
try {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telegram Configuration Command
|
|
3
|
+
*
|
|
4
|
+
* Configures the Telegram Bot integration for remote control and notifications.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* shep settings telegram # Interactive setup
|
|
8
|
+
* shep settings telegram --bot-token <token> # Set token + auto-pair
|
|
9
|
+
* shep settings telegram --bot-token <token> --chat-id 123 # Set token + explicit chat
|
|
10
|
+
* shep settings telegram --disable # Disable Telegram
|
|
11
|
+
* shep settings telegram --status # Show current status
|
|
12
|
+
*/
|
|
13
|
+
import { Command } from 'commander';
|
|
14
|
+
/**
|
|
15
|
+
* Create the Telegram configuration command.
|
|
16
|
+
*/
|
|
17
|
+
export declare function createTelegramCommand(): Command;
|
|
18
|
+
//# sourceMappingURL=telegram.command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telegram.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/settings/telegram.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBpC;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAsD/C"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telegram Configuration Command
|
|
3
|
+
*
|
|
4
|
+
* Configures the Telegram Bot integration for remote control and notifications.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* shep settings telegram # Interactive setup
|
|
8
|
+
* shep settings telegram --bot-token <token> # Set token + auto-pair
|
|
9
|
+
* shep settings telegram --bot-token <token> --chat-id 123 # Set token + explicit chat
|
|
10
|
+
* shep settings telegram --disable # Disable Telegram
|
|
11
|
+
* shep settings telegram --status # Show current status
|
|
12
|
+
*/
|
|
13
|
+
import { Command } from 'commander';
|
|
14
|
+
import { input, confirm } from '@inquirer/prompts';
|
|
15
|
+
import { container } from '../../../../../packages/core/src/infrastructure/di/container.js';
|
|
16
|
+
import { ConfigureTelegramUseCase } from '../../../../../packages/core/src/application/use-cases/telegram/configure-telegram.use-case.js';
|
|
17
|
+
import { getSettings, resetSettings, initializeSettings, } from '../../../../../packages/core/src/infrastructure/services/settings.service.js';
|
|
18
|
+
import { messages, colors, fmt, symbols } from '../../ui/index.js';
|
|
19
|
+
/**
|
|
20
|
+
* Create the Telegram configuration command.
|
|
21
|
+
*/
|
|
22
|
+
export function createTelegramCommand() {
|
|
23
|
+
return new Command('telegram')
|
|
24
|
+
.description('Configure Telegram remote control and notifications')
|
|
25
|
+
.option('--bot-token <token>', 'Bot API token from @BotFather')
|
|
26
|
+
.option('--chat-id <id>', 'Telegram chat ID (auto-resolved if omitted)')
|
|
27
|
+
.option('--disable', 'Disable Telegram integration')
|
|
28
|
+
.option('--status', 'Show current Telegram configuration status')
|
|
29
|
+
.addHelpText('after', `
|
|
30
|
+
Examples:
|
|
31
|
+
$ shep settings telegram Interactive setup wizard
|
|
32
|
+
$ shep settings telegram --bot-token 123456:ABC-DEF... Set token and auto-pair
|
|
33
|
+
$ shep settings telegram --disable Disable Telegram
|
|
34
|
+
$ shep settings telegram --status Show current status
|
|
35
|
+
|
|
36
|
+
Setup guide:
|
|
37
|
+
1. Open Telegram and search for @BotFather
|
|
38
|
+
2. Send /newbot and follow the prompts to create a bot
|
|
39
|
+
3. Copy the bot token (looks like 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11)
|
|
40
|
+
4. Start a chat with your new bot and send /start
|
|
41
|
+
5. Run: shep settings telegram --bot-token <your-token>`)
|
|
42
|
+
.action(async (options) => {
|
|
43
|
+
try {
|
|
44
|
+
if (options.status) {
|
|
45
|
+
showTelegramStatus();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (options.disable) {
|
|
49
|
+
await disableTelegram();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const hasFlags = options.botToken !== undefined;
|
|
53
|
+
if (hasFlags) {
|
|
54
|
+
await enableTelegramNonInteractive(options);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
await enableTelegramInteractive();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
62
|
+
if (err.message.includes('force closed') || err.message.includes('User force closed')) {
|
|
63
|
+
messages.info('Configuration cancelled.');
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
messages.error('Failed to configure Telegram', err);
|
|
67
|
+
process.exitCode = 1;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function showTelegramStatus() {
|
|
72
|
+
const settings = getSettings();
|
|
73
|
+
const telegram = settings.telegram;
|
|
74
|
+
if (!telegram?.enabled) {
|
|
75
|
+
messages.info('Telegram integration is disabled.');
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
console.log(`\n${symbols.success} Telegram integration is ${colors.success('enabled')}`);
|
|
79
|
+
console.log(` Bot token: ${colors.muted(telegram.botToken ? `****${telegram.botToken.slice(-8)}` : 'not set')}`);
|
|
80
|
+
console.log(` Chat ID: ${colors.muted(telegram.chatId ?? 'not set')}`);
|
|
81
|
+
const enabledEvents = Object.entries(telegram.notifyEvents)
|
|
82
|
+
.filter(([, enabled]) => enabled)
|
|
83
|
+
.map(([key]) => key);
|
|
84
|
+
console.log(` Events: ${colors.muted(enabledEvents.length > 0 ? enabledEvents.join(', ') : 'none')}\n`);
|
|
85
|
+
}
|
|
86
|
+
async function disableTelegram() {
|
|
87
|
+
const useCase = container.resolve(ConfigureTelegramUseCase);
|
|
88
|
+
const result = await useCase.execute({ enabled: false });
|
|
89
|
+
resetSettings();
|
|
90
|
+
initializeSettings(result.settings);
|
|
91
|
+
messages.success('Telegram integration disabled.');
|
|
92
|
+
}
|
|
93
|
+
async function enableTelegramNonInteractive(options) {
|
|
94
|
+
if (!options.botToken) {
|
|
95
|
+
messages.error('--bot-token is required when enabling Telegram.');
|
|
96
|
+
process.exitCode = 1;
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const useCase = container.resolve(ConfigureTelegramUseCase);
|
|
100
|
+
messages.info('Validating bot token...');
|
|
101
|
+
const result = await useCase.execute({
|
|
102
|
+
enabled: true,
|
|
103
|
+
botToken: options.botToken,
|
|
104
|
+
chatId: options.chatId,
|
|
105
|
+
});
|
|
106
|
+
resetSettings();
|
|
107
|
+
initializeSettings(result.settings);
|
|
108
|
+
if (result.botInfo) {
|
|
109
|
+
messages.success(`Connected to @${result.botInfo.username}`);
|
|
110
|
+
}
|
|
111
|
+
if (result.chatResolution) {
|
|
112
|
+
messages.success(`Paired with ${result.chatResolution.firstName} (chat ID: ${result.chatResolution.chatId})`);
|
|
113
|
+
}
|
|
114
|
+
messages.success('Telegram integration enabled. Check your Telegram for a confirmation message.');
|
|
115
|
+
}
|
|
116
|
+
async function enableTelegramInteractive() {
|
|
117
|
+
console.log(`\n${fmt.heading('Telegram Remote Control Setup')}\n`);
|
|
118
|
+
console.log(`${colors.muted('This wizard will connect Shep to your personal Telegram bot.')}`);
|
|
119
|
+
console.log(`${colors.muted('You will receive notifications and can send commands via Telegram.\n')}`);
|
|
120
|
+
console.log(`${colors.muted('Prerequisites:')}`);
|
|
121
|
+
console.log(`${colors.muted(' 1. Create a bot via @BotFather on Telegram')}`);
|
|
122
|
+
console.log(`${colors.muted(' 2. Send /start to your new bot')}\n`);
|
|
123
|
+
const botToken = await input({
|
|
124
|
+
message: 'Enter your bot token from @BotFather:',
|
|
125
|
+
validate: (value) => {
|
|
126
|
+
if (!value.trim())
|
|
127
|
+
return 'Bot token is required';
|
|
128
|
+
if (!value.includes(':'))
|
|
129
|
+
return 'Invalid bot token format (should contain ":")';
|
|
130
|
+
return true;
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
const useCase = container.resolve(ConfigureTelegramUseCase);
|
|
134
|
+
messages.info('Validating bot token...');
|
|
135
|
+
const result = await useCase.execute({
|
|
136
|
+
enabled: true,
|
|
137
|
+
botToken: botToken.trim(),
|
|
138
|
+
});
|
|
139
|
+
resetSettings();
|
|
140
|
+
initializeSettings(result.settings);
|
|
141
|
+
if (result.botInfo) {
|
|
142
|
+
messages.success(`Connected to @${result.botInfo.username}`);
|
|
143
|
+
}
|
|
144
|
+
if (result.chatResolution) {
|
|
145
|
+
messages.success(`Paired with ${result.chatResolution.firstName} (chat ID: ${result.chatResolution.chatId})`);
|
|
146
|
+
}
|
|
147
|
+
messages.success('Telegram integration enabled! Check your Telegram for a confirmation message.');
|
|
148
|
+
const wantTest = await confirm({
|
|
149
|
+
message: 'Send a test notification?',
|
|
150
|
+
default: false,
|
|
151
|
+
});
|
|
152
|
+
if (wantTest) {
|
|
153
|
+
const telegramSvc = container.resolve('ITelegramService');
|
|
154
|
+
const telegram = result.settings.telegram;
|
|
155
|
+
await telegramSvc.sendMessage(telegram.botToken, telegram.chatId, '\u{1F6CE}\uFE0F <b>Test notification from Shep!</b>\nIf you see this, everything is working.');
|
|
156
|
+
messages.success('Test notification sent!');
|
|
157
|
+
}
|
|
158
|
+
}
|