@deadragdoll/tellymcp 0.0.9 → 0.0.10
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/.env.example.client +2 -0
- package/.env.example.gateway +2 -0
- package/VERSION.md +26 -0
- package/config/templates/env.both.template +1 -0
- package/config/templates/env.client.template +1 -0
- package/config/templates/env.gateway.template +1 -0
- package/dist/services/features/telegram-mcp/approval.service.js +1 -1
- package/dist/services/features/telegram-mcp/browser.service.js +1 -1
- package/dist/services/features/telegram-mcp/collaboration.service.js +1 -1
- package/dist/services/features/telegram-mcp/gateway-rmq.service.js +3 -2
- package/dist/services/features/telegram-mcp/gateway-socket.service.js +8 -2
- package/dist/services/features/telegram-mcp/inbox.service.js +1 -1
- package/dist/services/features/telegram-mcp/mcp-http.service.js +1 -1
- package/dist/services/features/telegram-mcp/notify.service.js +1 -1
- package/dist/services/features/telegram-mcp/pair.service.js +1 -1
- package/dist/services/features/telegram-mcp/runtime.service.js +27 -7
- package/dist/services/features/telegram-mcp/session-context.service.js +1 -1
- package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +2 -1
- package/dist/services/features/telegram-mcp/src/app/config/env.js +4 -0
- package/dist/services/features/telegram-mcp/src/shared/i18n/index.js +46 -0
- package/dist/services/features/telegram-mcp/src/shared/i18n/resources/en.js +555 -0
- package/dist/services/features/telegram-mcp/src/shared/i18n/resources/ru.js +555 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +9 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +1148 -575
- package/dist/services/features/telegram-mcp/standalone-http.service.js +1 -1
- package/dist/services/features/telegram-mcp/tools-sync.service.js +1 -1
- package/package.json +2 -1
package/.env.example.client
CHANGED
package/.env.example.gateway
CHANGED
package/VERSION.md
CHANGED
|
@@ -4,6 +4,32 @@ Public, user-facing release notes for published versions of `@deadragdoll/tellym
|
|
|
4
4
|
|
|
5
5
|
For detailed engineering history, refactors, and internal development notes, see [CHANGELOG.md](CHANGELOG.md).
|
|
6
6
|
|
|
7
|
+
## 0.0.10
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- Telegram UI localization for the bot layer:
|
|
11
|
+
- English and Russian catalogs for user-facing bot screens
|
|
12
|
+
- locale resolution from Telegram profile with persisted user preference
|
|
13
|
+
- `DEBUG_LANGUAGE=en|ru` override for fast testing without changing the Telegram profile
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- Localization scope is now explicit:
|
|
17
|
+
- Telegram bot UI is localized
|
|
18
|
+
- MCP tools, logs, `TOOLS.md`, and the Live Mini App remain canonical English by design
|
|
19
|
+
- Telegram menus, callbacks, project/collaboration screens, startup notices, and operational bot notices now render through a shared translation layer instead of ad hoc inline strings
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- Builder startup is more robust:
|
|
23
|
+
- runtime-dependent services now wait for full runtime readiness instead of racing broker registration
|
|
24
|
+
- this avoids `telegram_mcp runtime is not initialized yet` failures during `yarn dev:builder`
|
|
25
|
+
- Locale resolution is safe for partial test mocks and startup paths
|
|
26
|
+
- Telegram UI text is now consistent across:
|
|
27
|
+
- main menus
|
|
28
|
+
- inbox/session flows
|
|
29
|
+
- project/collab flows
|
|
30
|
+
- live approval prompts
|
|
31
|
+
- tmux and operational bot notices
|
|
32
|
+
|
|
7
33
|
## 0.0.9
|
|
8
34
|
|
|
9
35
|
### Added
|
|
@@ -24,7 +24,7 @@ const TelegramMcpApprovalService = {
|
|
|
24
24
|
if (!runtimeService) {
|
|
25
25
|
throw new Error(`Local Moleculer service '${runtime_service_1.TELEGRAM_MCP_RUNTIME_SERVICE_NAME}' is unavailable`);
|
|
26
26
|
}
|
|
27
|
-
const runtime = runtimeService.
|
|
27
|
+
const runtime = await runtimeService.waitUntilReady();
|
|
28
28
|
this.logger.info("Starting telegram_mcp approval service");
|
|
29
29
|
this.approvalOrchestrator = new orchestrator_1.HumanApprovalOrchestrator(runtime.config, runtime.stateStore, runtime.stateStore, runtime.stateStore, runtime.telegramTransport, runtime.logger, runtime.projectIdentityResolver);
|
|
30
30
|
this.logger.info("telegram_mcp approval service is ready");
|
|
@@ -24,7 +24,7 @@ const TelegramMcpBrowserService = {
|
|
|
24
24
|
if (!runtimeService) {
|
|
25
25
|
throw new Error(`Local Moleculer service '${runtime_service_1.TELEGRAM_MCP_RUNTIME_SERVICE_NAME}' is unavailable`);
|
|
26
26
|
}
|
|
27
|
-
const runtime = runtimeService.
|
|
27
|
+
const runtime = await runtimeService.waitUntilReady();
|
|
28
28
|
this.logger.info("Starting telegram_mcp browser service");
|
|
29
29
|
this.browserService = new browserService_1.BrowserService(runtime.config, runtime.stateStore, runtime.stateStore, runtime.stateStore, runtime.objectStore, runtime.telegramTransport, runtime.logger, runtime.projectIdentityResolver);
|
|
30
30
|
this.logger.info("telegram_mcp browser service is ready");
|
|
@@ -34,7 +34,7 @@ const TelegramMcpCollaborationService = {
|
|
|
34
34
|
if (!runtimeService) {
|
|
35
35
|
throw new Error(`Local Moleculer service '${runtime_service_1.TELEGRAM_MCP_RUNTIME_SERVICE_NAME}' is unavailable`);
|
|
36
36
|
}
|
|
37
|
-
const runtime = runtimeService.
|
|
37
|
+
const runtime = await runtimeService.waitUntilReady();
|
|
38
38
|
this.logger.info("Starting telegram_mcp collaboration service");
|
|
39
39
|
const localBackend = new localCollaborationBackend_1.LocalCollaborationBackend(runtime.config, runtime.stateStore, runtime.stateStore, runtime.stateStore, runtime.stateStore, runtime.objectStore, runtime.telegramTransport, runtime.logger);
|
|
40
40
|
runtime.gatewayHttpService.setPartnerNoteRelayHandler(async (input) => {
|
|
@@ -276,10 +276,11 @@ const TelegramMcpGatewayRmqService = {
|
|
|
276
276
|
throw new Error(`Local Moleculer service '${runtime_service_1.TELEGRAM_MCP_RUNTIME_SERVICE_NAME}' is unavailable`);
|
|
277
277
|
}
|
|
278
278
|
this.runtimeService = runtimeService;
|
|
279
|
+
const runtime = await runtimeService.waitUntilReady();
|
|
279
280
|
if (!this.isEnabled?.()) {
|
|
280
281
|
this.logger.info("Gateway RMQ is disabled", {
|
|
281
|
-
distributedMode:
|
|
282
|
-
rmqConfigured: Boolean(
|
|
282
|
+
distributedMode: runtime.config.distributed.mode,
|
|
283
|
+
rmqConfigured: Boolean(runtime.config.distributed.rmq?.host),
|
|
283
284
|
});
|
|
284
285
|
return;
|
|
285
286
|
}
|
|
@@ -1455,8 +1455,14 @@ const TelegramMcpGatewaySocketService = {
|
|
|
1455
1455
|
},
|
|
1456
1456
|
},
|
|
1457
1457
|
async started() {
|
|
1458
|
-
|
|
1459
|
-
const
|
|
1458
|
+
await this.broker.waitForServices([runtime_service_1.TELEGRAM_MCP_RUNTIME_SERVICE_NAME]);
|
|
1459
|
+
const runtimeService = this.broker.getLocalService(runtime_service_1.TELEGRAM_MCP_RUNTIME_SERVICE_NAME);
|
|
1460
|
+
if (!runtimeService) {
|
|
1461
|
+
throw new Error(`Local Moleculer service '${runtime_service_1.TELEGRAM_MCP_RUNTIME_SERVICE_NAME}' is unavailable`);
|
|
1462
|
+
}
|
|
1463
|
+
this.runtimeService = runtimeService;
|
|
1464
|
+
const runtime = await runtimeService.waitUntilReady();
|
|
1465
|
+
const mode = runtime.config.distributed.mode;
|
|
1460
1466
|
const gatewayEnabled = mode === "gateway" || mode === "both";
|
|
1461
1467
|
const clientEnabled = mode === "client" || mode === "both";
|
|
1462
1468
|
if (gatewayEnabled) {
|
|
@@ -24,7 +24,7 @@ const TelegramMcpInboxService = {
|
|
|
24
24
|
if (!runtimeService) {
|
|
25
25
|
throw new Error(`Local Moleculer service '${runtime_service_1.TELEGRAM_MCP_RUNTIME_SERVICE_NAME}' is unavailable`);
|
|
26
26
|
}
|
|
27
|
-
const runtime = runtimeService.
|
|
27
|
+
const runtime = await runtimeService.waitUntilReady();
|
|
28
28
|
this.logger.info("Starting telegram_mcp inbox service");
|
|
29
29
|
this.inboxService = new inboxService_1.InboxService(runtime.config, runtime.stateStore, runtime.stateStore, runtime.logger, runtime.projectIdentityResolver);
|
|
30
30
|
this.logger.info("telegram_mcp inbox service is ready");
|
|
@@ -52,7 +52,7 @@ const TelegramMcpHttpService = {
|
|
|
52
52
|
if (!mcpServerService) {
|
|
53
53
|
throw new Error(`Local Moleculer service '${mcp_server_service_1.TELEGRAM_MCP_MCP_SERVER_SERVICE_NAME}' is unavailable`);
|
|
54
54
|
}
|
|
55
|
-
const runtime = runtimeService.
|
|
55
|
+
const runtime = await runtimeService.waitUntilReady();
|
|
56
56
|
this.logger.info("Starting telegram_mcp HTTP service");
|
|
57
57
|
this.httpHandler = (0, http_1.createMcpHttpHandler)(runtime, {
|
|
58
58
|
createMcpServer: () => mcpServerService.createServer(),
|
|
@@ -24,7 +24,7 @@ const TelegramMcpNotifyService = {
|
|
|
24
24
|
if (!runtimeService) {
|
|
25
25
|
throw new Error(`Local Moleculer service '${runtime_service_1.TELEGRAM_MCP_RUNTIME_SERVICE_NAME}' is unavailable`);
|
|
26
26
|
}
|
|
27
|
-
const runtime = runtimeService.
|
|
27
|
+
const runtime = await runtimeService.waitUntilReady();
|
|
28
28
|
this.logger.info("Starting telegram_mcp notify service");
|
|
29
29
|
this.notifyService = new notifyService_1.NotifyService(runtime.config, runtime.stateStore, runtime.stateStore, runtime.telegramTransport, runtime.logger, runtime.projectIdentityResolver);
|
|
30
30
|
this.logger.info("telegram_mcp notify service is ready");
|
|
@@ -24,7 +24,7 @@ const TelegramMcpPairService = {
|
|
|
24
24
|
if (!runtimeService) {
|
|
25
25
|
throw new Error(`Local Moleculer service '${runtime_service_1.TELEGRAM_MCP_RUNTIME_SERVICE_NAME}' is unavailable`);
|
|
26
26
|
}
|
|
27
|
-
const runtime = runtimeService.
|
|
27
|
+
const runtime = await runtimeService.waitUntilReady();
|
|
28
28
|
this.logger.info("Starting telegram_mcp pair service");
|
|
29
29
|
this.pairSessionService = new generatePairCode_1.PairSessionService(runtime.config, runtime.stateStore, runtime.stateStore, runtime.stateStore, runtime.logger, runtime.projectIdentityResolver);
|
|
30
30
|
this.logger.info("telegram_mcp pair service is ready");
|
|
@@ -8,6 +8,10 @@ const TelegramMcpRuntimeService = {
|
|
|
8
8
|
name: exports.TELEGRAM_MCP_RUNTIME_SERVICE_NAME,
|
|
9
9
|
created() {
|
|
10
10
|
this.runtime = null;
|
|
11
|
+
this.readyPromise = new Promise((resolve, reject) => {
|
|
12
|
+
this.resolveReady = resolve;
|
|
13
|
+
this.rejectReady = reject;
|
|
14
|
+
});
|
|
11
15
|
},
|
|
12
16
|
methods: {
|
|
13
17
|
getRuntime() {
|
|
@@ -16,19 +20,35 @@ const TelegramMcpRuntimeService = {
|
|
|
16
20
|
}
|
|
17
21
|
return this.runtime;
|
|
18
22
|
},
|
|
23
|
+
waitUntilReady() {
|
|
24
|
+
if (this.runtime) {
|
|
25
|
+
return Promise.resolve(this.runtime);
|
|
26
|
+
}
|
|
27
|
+
if (!this.readyPromise) {
|
|
28
|
+
return Promise.reject(new Error("telegram_mcp runtime readiness promise is unavailable"));
|
|
29
|
+
}
|
|
30
|
+
return this.readyPromise;
|
|
31
|
+
},
|
|
19
32
|
},
|
|
20
33
|
async started() {
|
|
21
34
|
this.logger.info("Starting telegram_mcp runtime service", {
|
|
22
35
|
packageVersion: (0, versionHandshake_1.getTellyMcpPackageVersion)(__dirname),
|
|
23
36
|
protocolVersion: versionHandshake_1.TELLYMCP_PROTOCOL_VERSION,
|
|
24
37
|
});
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
38
|
+
try {
|
|
39
|
+
this.runtime = await (0, runtime_1.createAppRuntime)({
|
|
40
|
+
callBroker: (actionName, params, options) => this.broker.call(actionName, params, options),
|
|
41
|
+
});
|
|
42
|
+
this.resolveReady?.(this.runtime);
|
|
43
|
+
this.logger.info("telegram_mcp runtime service is ready", {
|
|
44
|
+
packageVersion: (0, versionHandshake_1.getTellyMcpPackageVersion)(__dirname),
|
|
45
|
+
protocolVersion: versionHandshake_1.TELLYMCP_PROTOCOL_VERSION,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
this.rejectReady?.(error);
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
32
52
|
},
|
|
33
53
|
async stopped() {
|
|
34
54
|
if (!this.runtime) {
|
|
@@ -24,7 +24,7 @@ const TelegramMcpSessionContextService = {
|
|
|
24
24
|
if (!runtimeService) {
|
|
25
25
|
throw new Error(`Local Moleculer service '${runtime_service_1.TELEGRAM_MCP_RUNTIME_SERVICE_NAME}' is unavailable`);
|
|
26
26
|
}
|
|
27
|
-
const runtime = runtimeService.
|
|
27
|
+
const runtime = await runtimeService.waitUntilReady();
|
|
28
28
|
this.logger.info("Starting telegram_mcp session-context service");
|
|
29
29
|
this.sessionContextService = new sessionContextService_1.SessionContextService(runtime.stateStore, runtime.stateStore, runtime.logger, runtime.projectIdentityResolver);
|
|
30
30
|
this.logger.info("telegram_mcp session-context service is ready");
|
|
@@ -72,7 +72,7 @@ async function createAppRuntime(input) {
|
|
|
72
72
|
const objectStore = new minioExchangeStore_1.MinioExchangeStore(input.callBroker, stateStore, config.tmux, config.exchange.dir, config.mcp.vfsScope, logger, config.distributed.mode, config.distributed.gatewayPublicUrl, config.distributed.gatewayAuthToken);
|
|
73
73
|
await stateStore.resetRuntimeState();
|
|
74
74
|
logger.info("Runtime pending state reset");
|
|
75
|
-
const telegramTransport = new transport_1.TelegramTransport(config, stateStore, stateStore, stateStore, stateStore, stateStore, stateStore, objectStore, webAppLaunchRegistry, logger);
|
|
75
|
+
const telegramTransport = new transport_1.TelegramTransport(config, stateStore, stateStore, stateStore, stateStore, stateStore, stateStore, stateStore, objectStore, webAppLaunchRegistry, logger);
|
|
76
76
|
await telegramTransport.start();
|
|
77
77
|
logger.info("Telegram transport ready");
|
|
78
78
|
await telegramTransport.recoverPendingInboxNudges();
|
|
@@ -89,6 +89,7 @@ async function createAppRuntime(input) {
|
|
|
89
89
|
sessionStore: stateStore,
|
|
90
90
|
bindingStore: stateStore,
|
|
91
91
|
inboxStore: stateStore,
|
|
92
|
+
localeStore: stateStore,
|
|
92
93
|
xchangeFileMetaStore: stateStore,
|
|
93
94
|
maintenanceStore: stateStore,
|
|
94
95
|
objectStore,
|
|
@@ -59,6 +59,7 @@ const envSchema = z.object({
|
|
|
59
59
|
.int()
|
|
60
60
|
.positive()
|
|
61
61
|
.default(300),
|
|
62
|
+
DEBUG_LANGUAGE: z.enum(["en", "ru"]).optional(),
|
|
62
63
|
REDIS_HOST: z.string().min(1),
|
|
63
64
|
REDIS_PORT: z.coerce.number().int().positive(),
|
|
64
65
|
REDIS_DB: z.coerce.number().int().nonnegative(),
|
|
@@ -205,6 +206,9 @@ function loadConfig() {
|
|
|
205
206
|
...(parsed.TELEGRAM_BOT_USERNAME
|
|
206
207
|
? { botUsername: parsed.TELEGRAM_BOT_USERNAME }
|
|
207
208
|
: {}),
|
|
209
|
+
...(parsed.DEBUG_LANGUAGE
|
|
210
|
+
? { debugLanguage: parsed.DEBUG_LANGUAGE }
|
|
211
|
+
: {}),
|
|
208
212
|
pollIntervalMs: parsed.TELEGRAM_POLL_INTERVAL_MS,
|
|
209
213
|
defaultTimeoutSeconds: parsed.TELEGRAM_DEFAULT_TIMEOUT_SECONDS,
|
|
210
214
|
maxContextChars: parsed.TELEGRAM_MAX_CONTEXT_CHARS,
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeLocale = normalizeLocale;
|
|
4
|
+
exports.translate = translate;
|
|
5
|
+
const i18next_1 = require("i18next");
|
|
6
|
+
const en_1 = require("./resources/en");
|
|
7
|
+
const ru_1 = require("./resources/ru");
|
|
8
|
+
const instance = (0, i18next_1.createInstance)();
|
|
9
|
+
void instance.init({
|
|
10
|
+
lng: "en",
|
|
11
|
+
fallbackLng: "en",
|
|
12
|
+
ns: ["common", "menu"],
|
|
13
|
+
defaultNS: "common",
|
|
14
|
+
initAsync: false,
|
|
15
|
+
interpolation: {
|
|
16
|
+
escapeValue: false,
|
|
17
|
+
},
|
|
18
|
+
returnNull: false,
|
|
19
|
+
returnEmptyString: false,
|
|
20
|
+
resources: {
|
|
21
|
+
en: {
|
|
22
|
+
common: en_1.enCommon,
|
|
23
|
+
menu: en_1.enMenu,
|
|
24
|
+
},
|
|
25
|
+
ru: {
|
|
26
|
+
common: ru_1.ruCommon,
|
|
27
|
+
menu: ru_1.ruMenu,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
function normalizeLocale(input) {
|
|
32
|
+
const normalized = input?.trim().toLowerCase() ?? "";
|
|
33
|
+
if (normalized === "ru" || normalized.startsWith("ru-")) {
|
|
34
|
+
return "ru";
|
|
35
|
+
}
|
|
36
|
+
if (normalized === "en" || normalized.startsWith("en-")) {
|
|
37
|
+
return "en";
|
|
38
|
+
}
|
|
39
|
+
return "en";
|
|
40
|
+
}
|
|
41
|
+
function translate(locale, key, options) {
|
|
42
|
+
return instance.t(key, {
|
|
43
|
+
lng: normalizeLocale(locale),
|
|
44
|
+
...(options ?? {}),
|
|
45
|
+
});
|
|
46
|
+
}
|