@deadragdoll/tellymcp 0.0.3 → 0.0.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/README-ru.md +1 -1
- package/README.md +1 -1
- package/VERSION.md +93 -0
- package/dist/cli.js +4 -1
- package/dist/services/features/telegram-mcp/runtime.service.js +9 -2
- package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +2 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +95 -0
- package/package.json +2 -1
package/README-ru.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# TellyMCP
|
|
2
2
|
|
|
3
|
-
[English](README.md) | [Русский](README-ru.md) | [Standalone Guide](STANDALONE.md) | [Standalone RU](STANDALONE-ru.md)
|
|
3
|
+
[English](README.md) | [Русский](README-ru.md) | [Standalone Guide](STANDALONE.md) | [Standalone RU](STANDALONE-ru.md) | [Release Notes](VERSION.md)
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@deadragdoll/tellymcp)
|
|
6
6
|
[](https://www.npmjs.com/package/@deadragdoll/tellymcp)
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# TellyMCP
|
|
2
2
|
|
|
3
|
-
[English](README.md) | [Русский](README-ru.md) | [Standalone Guide](STANDALONE.md) | [Standalone RU](STANDALONE-ru.md)
|
|
3
|
+
[English](README.md) | [Русский](README-ru.md) | [Standalone Guide](STANDALONE.md) | [Standalone RU](STANDALONE-ru.md) | [Release Notes](VERSION.md)
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@deadragdoll/tellymcp)
|
|
6
6
|
[](https://www.npmjs.com/package/@deadragdoll/tellymcp)
|
package/VERSION.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# TellyMCP Release Notes
|
|
2
|
+
|
|
3
|
+
Public, user-facing release notes for published versions of `@deadragdoll/tellymcp`.
|
|
4
|
+
|
|
5
|
+
For detailed engineering history, refactors, and internal development notes, see [CHANGELOG.md](CHANGELOG.md).
|
|
6
|
+
|
|
7
|
+
## 0.0.3
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- Standalone CLI workflow:
|
|
11
|
+
- `tellymcp init <client|gateway|both>`
|
|
12
|
+
- `tellymcp run`
|
|
13
|
+
- `tellymcp doctor`
|
|
14
|
+
- `tellymcp mcp --help`
|
|
15
|
+
- Standalone and public installation guides:
|
|
16
|
+
- [STANDALONE.md](STANDALONE.md)
|
|
17
|
+
- [STANDALONE-ru.md](STANDALONE-ru.md)
|
|
18
|
+
- Browser runtime helper:
|
|
19
|
+
- `tellymcp browser install`
|
|
20
|
+
- Public README set for GitHub and npm:
|
|
21
|
+
- [README.md](README.md)
|
|
22
|
+
- [README-ru.md](README-ru.md)
|
|
23
|
+
- Human-readable release notes in this file.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- Default installation path is now npm-first:
|
|
27
|
+
- `npm install -g @deadragdoll/tellymcp`
|
|
28
|
+
- Standalone client mode is documented first, before gateway/both deployment.
|
|
29
|
+
- `tmux` is now documented as a strongly recommended prerequisite for the full experience:
|
|
30
|
+
- Live View
|
|
31
|
+
- nudges
|
|
32
|
+
- direct terminal control from Telegram
|
|
33
|
+
- Environment examples were split into dedicated client and gateway variants.
|
|
34
|
+
- Package build/publish flow now validates itself before packing/publishing.
|
|
35
|
+
|
|
36
|
+
### Collaboration
|
|
37
|
+
- Project collaboration works across local and remote sessions.
|
|
38
|
+
- `Collab` now includes:
|
|
39
|
+
- `Broadcast`
|
|
40
|
+
- `History`
|
|
41
|
+
- `Delete`
|
|
42
|
+
- `Ask` and `Share` semantics were clarified:
|
|
43
|
+
- `Ask` tells the selected session to do the work and reply back
|
|
44
|
+
- `Share` tells the current session to send something to the selected session
|
|
45
|
+
|
|
46
|
+
### Live View
|
|
47
|
+
- Telegram Mini App Live View supports:
|
|
48
|
+
- fullscreen/expand launch policy
|
|
49
|
+
- bottom toolbar layout
|
|
50
|
+
- `Esc`
|
|
51
|
+
- `Tab`
|
|
52
|
+
- `Ctrl+C`
|
|
53
|
+
- `Backspace`
|
|
54
|
+
- `Up`
|
|
55
|
+
- `Down`
|
|
56
|
+
- `Enter`
|
|
57
|
+
- Live approval flow was added for remote project sessions.
|
|
58
|
+
|
|
59
|
+
### Browser
|
|
60
|
+
- Browser tools use Playwright Chromium.
|
|
61
|
+
- Headless mode is the recommended default for remote and SSH-based environments.
|
|
62
|
+
- `doctor` now helps detect missing browser runtime and connectivity issues.
|
|
63
|
+
|
|
64
|
+
### Compatibility
|
|
65
|
+
- Gateway and clients now compare:
|
|
66
|
+
- package version
|
|
67
|
+
- protocol version
|
|
68
|
+
- capabilities
|
|
69
|
+
- `TOOLS.md` sync now detects outdated or missing local instructions and asks the session to refresh them.
|
|
70
|
+
|
|
71
|
+
### Removed
|
|
72
|
+
- Legacy Go/HTTP tmux proxy path was removed.
|
|
73
|
+
- Direct product path is now local `tmux` only.
|
|
74
|
+
|
|
75
|
+
## Next entry template
|
|
76
|
+
|
|
77
|
+
Copy this block for the next published version:
|
|
78
|
+
|
|
79
|
+
```md
|
|
80
|
+
## x.y.z
|
|
81
|
+
|
|
82
|
+
### Added
|
|
83
|
+
- ...
|
|
84
|
+
|
|
85
|
+
### Changed
|
|
86
|
+
- ...
|
|
87
|
+
|
|
88
|
+
### Fixed
|
|
89
|
+
- ...
|
|
90
|
+
|
|
91
|
+
### Removed
|
|
92
|
+
- ...
|
|
93
|
+
```
|
package/dist/cli.js
CHANGED
|
@@ -11,8 +11,10 @@ const node_net_1 = __importDefault(require("node:net"));
|
|
|
11
11
|
const dotenv_1 = require("dotenv");
|
|
12
12
|
const picocolors_1 = __importDefault(require("picocolors"));
|
|
13
13
|
const ws_1 = __importDefault(require("ws"));
|
|
14
|
+
const versionHandshake_1 = require("./services/features/telegram-mcp/src/shared/lib/version/versionHandshake");
|
|
14
15
|
const distDir = __dirname;
|
|
15
16
|
const packageRoot = node_path_1.default.resolve(distDir, "..");
|
|
17
|
+
const cliPackageVersion = (0, versionHandshake_1.getTellyMcpPackageVersion)(__dirname);
|
|
16
18
|
function getTmuxStatus() {
|
|
17
19
|
const result = (0, node_child_process_1.spawnSync)("tmux", ["-V"], {
|
|
18
20
|
encoding: "utf8",
|
|
@@ -27,7 +29,7 @@ function getTmuxStatus() {
|
|
|
27
29
|
return { found: false };
|
|
28
30
|
}
|
|
29
31
|
function printBanner(title, subtitle) {
|
|
30
|
-
process.stdout.write(`${picocolors_1.default.bold(picocolors_1.default.cyan("TellyMCP"))} ${picocolors_1.default.dim(title)}\n`);
|
|
32
|
+
process.stdout.write(`${picocolors_1.default.bold(picocolors_1.default.cyan("TellyMCP"))} ${picocolors_1.default.bold(picocolors_1.default.white(`v${cliPackageVersion}`))} ${picocolors_1.default.dim(title)}\n`);
|
|
31
33
|
if (subtitle) {
|
|
32
34
|
process.stdout.write(`${picocolors_1.default.dim(subtitle)}\n`);
|
|
33
35
|
}
|
|
@@ -666,6 +668,7 @@ function runRuntime(args) {
|
|
|
666
668
|
if (!(0, node_fs_1.existsSync)(servicesPath)) {
|
|
667
669
|
fail(`Missing compiled services: ${servicesPath}`);
|
|
668
670
|
}
|
|
671
|
+
printBanner("run", "Starting packaged runtime");
|
|
669
672
|
const tmux = getTmuxStatus();
|
|
670
673
|
if (tmux.found) {
|
|
671
674
|
process.stdout.write(`${picocolors_1.default.green("tmux detected:")} ${tmux.version}\n`);
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TELEGRAM_MCP_RUNTIME_SERVICE_NAME = void 0;
|
|
4
4
|
const runtime_1 = require("./src/app/bootstrap/runtime");
|
|
5
|
+
const versionHandshake_1 = require("./src/shared/lib/version/versionHandshake");
|
|
5
6
|
exports.TELEGRAM_MCP_RUNTIME_SERVICE_NAME = "telegramMcp.runtime";
|
|
6
7
|
const TelegramMcpRuntimeService = {
|
|
7
8
|
name: exports.TELEGRAM_MCP_RUNTIME_SERVICE_NAME,
|
|
@@ -17,11 +18,17 @@ const TelegramMcpRuntimeService = {
|
|
|
17
18
|
},
|
|
18
19
|
},
|
|
19
20
|
async started() {
|
|
20
|
-
this.logger.info("Starting telegram_mcp runtime service"
|
|
21
|
+
this.logger.info("Starting telegram_mcp runtime service", {
|
|
22
|
+
packageVersion: (0, versionHandshake_1.getTellyMcpPackageVersion)(__dirname),
|
|
23
|
+
protocolVersion: versionHandshake_1.TELLYMCP_PROTOCOL_VERSION,
|
|
24
|
+
});
|
|
21
25
|
this.runtime = await (0, runtime_1.createAppRuntime)({
|
|
22
26
|
callBroker: (actionName, params, options) => this.broker.call(actionName, params, options),
|
|
23
27
|
});
|
|
24
|
-
this.logger.info("telegram_mcp runtime service is ready"
|
|
28
|
+
this.logger.info("telegram_mcp runtime service is ready", {
|
|
29
|
+
packageVersion: (0, versionHandshake_1.getTellyMcpPackageVersion)(__dirname),
|
|
30
|
+
protocolVersion: versionHandshake_1.TELLYMCP_PROTOCOL_VERSION,
|
|
31
|
+
});
|
|
25
32
|
},
|
|
26
33
|
async stopped() {
|
|
27
34
|
if (!this.runtime) {
|
|
@@ -77,6 +77,8 @@ async function createAppRuntime(input) {
|
|
|
77
77
|
logger.info("Telegram transport ready");
|
|
78
78
|
await telegramTransport.recoverPendingInboxNudges();
|
|
79
79
|
logger.info("Startup inbox nudge recovery completed");
|
|
80
|
+
await telegramTransport.sendStartupNotifications();
|
|
81
|
+
logger.info("Startup Telegram notifications completed");
|
|
80
82
|
const gatewayHttpService = new gatewayHttpService_1.GatewayHttpService(config, input.callBroker);
|
|
81
83
|
return {
|
|
82
84
|
config,
|
|
@@ -17,6 +17,7 @@ const collabSemantics_1 = require("./collabSemantics");
|
|
|
17
17
|
const collabUi_1 = require("./collabUi");
|
|
18
18
|
const proxyFetch_1 = require("./proxyFetch");
|
|
19
19
|
const client_1 = require("../tmux/client");
|
|
20
|
+
const versionHandshake_1 = require("../../lib/version/versionHandshake");
|
|
20
21
|
const LOCAL_INDEX_FILE_NAME = "LOCAL_INDEX.md";
|
|
21
22
|
function trimTrailingSlashes(value) {
|
|
22
23
|
return value.replace(/\/+$/u, "");
|
|
@@ -25,6 +26,14 @@ function normalizeBasePath(value) {
|
|
|
25
26
|
const trimmed = trimTrailingSlashes(value.trim());
|
|
26
27
|
return trimmed.startsWith("/") ? trimmed || "/" : `/${trimmed || ""}`;
|
|
27
28
|
}
|
|
29
|
+
function joinHttpPath(prefix, suffix) {
|
|
30
|
+
const normalizedPrefix = prefix ? normalizeBasePath(prefix) : "";
|
|
31
|
+
const normalizedSuffix = normalizeBasePath(suffix);
|
|
32
|
+
if (!normalizedPrefix || normalizedPrefix === "/") {
|
|
33
|
+
return normalizedSuffix;
|
|
34
|
+
}
|
|
35
|
+
return `${normalizedPrefix}${normalizedSuffix}`.replace(/\/{2,}/gu, "/");
|
|
36
|
+
}
|
|
28
37
|
function resolveWebAppPublicBaseUrl(config) {
|
|
29
38
|
if (!config.webapp.publicUrl) {
|
|
30
39
|
return null;
|
|
@@ -755,6 +764,92 @@ class TelegramTransport {
|
|
|
755
764
|
recoveredSessions: recoveredCount,
|
|
756
765
|
});
|
|
757
766
|
}
|
|
767
|
+
async sendStartupNotifications() {
|
|
768
|
+
const packageVersion = (0, versionHandshake_1.getTellyMcpPackageVersion)(__dirname);
|
|
769
|
+
const sessions = await this.sessionStore.listSessions();
|
|
770
|
+
const groupedRecipients = new Map();
|
|
771
|
+
for (const session of sessions) {
|
|
772
|
+
const binding = await this.bindingStore.getBinding(session.sessionId);
|
|
773
|
+
if (!binding) {
|
|
774
|
+
continue;
|
|
775
|
+
}
|
|
776
|
+
const key = `${binding.telegramChatId}:${binding.telegramUserId}`;
|
|
777
|
+
const current = groupedRecipients.get(key);
|
|
778
|
+
if (current) {
|
|
779
|
+
current.sessionIds.push(session.sessionId);
|
|
780
|
+
current.sessionLabels.push(session.label ?? session.sessionId);
|
|
781
|
+
continue;
|
|
782
|
+
}
|
|
783
|
+
groupedRecipients.set(key, {
|
|
784
|
+
binding: {
|
|
785
|
+
telegramChatId: binding.telegramChatId,
|
|
786
|
+
telegramUserId: binding.telegramUserId,
|
|
787
|
+
},
|
|
788
|
+
sessionIds: [session.sessionId],
|
|
789
|
+
sessionLabels: [session.label ?? session.sessionId],
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
if (groupedRecipients.size === 0) {
|
|
793
|
+
this.logger.info("Skipping startup notifications because no Telegram sessions are paired");
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
const runtimePort = this.config.distributed.mode === "gateway" || this.config.distributed.mode === "both"
|
|
797
|
+
? Number(process.env.PORT || this.config.mcp.httpPort)
|
|
798
|
+
: this.config.mcp.httpPort;
|
|
799
|
+
const rootPrefix = this.config.distributed.mode === "gateway" || this.config.distributed.mode === "both"
|
|
800
|
+
? normalizeBasePath(process.env.ROOT_PREFIX || "/api")
|
|
801
|
+
: "";
|
|
802
|
+
const localMcpPath = this.config.distributed.mode === "gateway" || this.config.distributed.mode === "both"
|
|
803
|
+
? joinHttpPath(rootPrefix, this.config.mcp.httpPath)
|
|
804
|
+
: this.config.mcp.httpPath;
|
|
805
|
+
const localWebappPath = this.config.distributed.mode === "gateway" || this.config.distributed.mode === "both"
|
|
806
|
+
? joinHttpPath(rootPrefix, this.config.webapp.basePath)
|
|
807
|
+
: this.config.webapp.basePath;
|
|
808
|
+
const localMcpUrl = `http://${this.config.mcp.httpHost}:${runtimePort}${localMcpPath}`;
|
|
809
|
+
const localWebappUrl = `http://${this.config.mcp.httpHost}:${runtimePort}${localWebappPath}`;
|
|
810
|
+
for (const recipientGroup of groupedRecipients.values()) {
|
|
811
|
+
const primarySessionId = recipientGroup.sessionIds[0];
|
|
812
|
+
if (!primarySessionId) {
|
|
813
|
+
continue;
|
|
814
|
+
}
|
|
815
|
+
const uniqueSessionLabels = Array.from(new Set(recipientGroup.sessionLabels)).sort();
|
|
816
|
+
const startupMessage = [
|
|
817
|
+
"✅ TellyMCP запущен.",
|
|
818
|
+
`Версия: ${packageVersion}`,
|
|
819
|
+
`Протокол: ${versionHandshake_1.TELLYMCP_PROTOCOL_VERSION}`,
|
|
820
|
+
`Режим: ${this.config.distributed.mode}`,
|
|
821
|
+
...(this.config.telegram.botUsername
|
|
822
|
+
? [`Бот: @${this.config.telegram.botUsername.replace(/^@/u, "")}`]
|
|
823
|
+
: []),
|
|
824
|
+
`Сессии: ${uniqueSessionLabels.join(", ")}`,
|
|
825
|
+
`MCP: ${localMcpUrl}`,
|
|
826
|
+
...(this.config.webapp.enabled ? [`WebApp: ${localWebappUrl}`] : []),
|
|
827
|
+
...(this.config.distributed.gatewayPublicUrl
|
|
828
|
+
? [`Gateway: ${this.config.distributed.gatewayPublicUrl}`]
|
|
829
|
+
: []),
|
|
830
|
+
...(this.config.distributed.gatewayWsUrl
|
|
831
|
+
? [`Gateway WS: ${this.config.distributed.gatewayWsUrl}`]
|
|
832
|
+
: []),
|
|
833
|
+
`Browser: ${this.config.browser.enabled ? (this.config.browser.headless ? "enabled, headless" : "enabled, headed") : "disabled"}`,
|
|
834
|
+
"Напиши /menu, чтобы открыть меню сессий.",
|
|
835
|
+
].join("\n");
|
|
836
|
+
try {
|
|
837
|
+
await this.sendNotification({
|
|
838
|
+
sessionId: primarySessionId,
|
|
839
|
+
sessionLabel: "TellyMCP",
|
|
840
|
+
recipient: recipientGroup.binding,
|
|
841
|
+
message: startupMessage,
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
catch (error) {
|
|
845
|
+
this.logger.warn("Failed to deliver Telegram startup notification", {
|
|
846
|
+
telegramChatId: recipientGroup.binding.telegramChatId,
|
|
847
|
+
telegramUserId: recipientGroup.binding.telegramUserId,
|
|
848
|
+
error: error instanceof Error ? error.message : String(error),
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
}
|
|
758
853
|
async sendRequest(input) {
|
|
759
854
|
const text = (0, messageFormat_1.formatTelegramMessage)(input, {
|
|
760
855
|
maxQuestionChars: this.config.telegram.maxQuestionChars,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deadragdoll/tellymcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "TellyMCP - Telegram Human-in-the-Loop MCP Server",
|
|
5
5
|
"main": "dist/services/features/telegram-mcp/runtime.service.js",
|
|
6
6
|
"bin": {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"README-ru.md",
|
|
15
15
|
"STANDALONE.md",
|
|
16
16
|
"STANDALONE-ru.md",
|
|
17
|
+
"VERSION.md",
|
|
17
18
|
"CHANGELOG.md",
|
|
18
19
|
"TOOLS.md",
|
|
19
20
|
".env.example.client",
|