@deadragdoll/tellymcp 0.0.1
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 +93 -0
- package/.env.example.gateway +120 -0
- package/CHANGELOG.md +155 -0
- package/LICENSE +21 -0
- package/README-ru.md +338 -0
- package/README.md +1262 -0
- package/STANDALONE-ru.md +266 -0
- package/STANDALONE.md +266 -0
- package/TOOLS.md +1296 -0
- package/config/templates/env.both.template +83 -0
- package/config/templates/env.client.template +60 -0
- package/config/templates/env.gateway.template +82 -0
- package/dist/cli.js +636 -0
- package/dist/index.js +17 -0
- package/dist/lib/logfeed/store.js +52 -0
- package/dist/lib/middlewares/tracer.js +172 -0
- package/dist/lib/mixins/db.js +267 -0
- package/dist/lib/mixins/logfeed.js +34 -0
- package/dist/lib/mixins/session.errors.js +142 -0
- package/dist/lib/moleculer.js +2 -0
- package/dist/lib/trace.js +147 -0
- package/dist/lib/traceContext.js +116 -0
- package/dist/moleculer.config.js +274 -0
- package/dist/services/features/telegram-mcp/approval.service.js +33 -0
- package/dist/services/features/telegram-mcp/browser.service.js +42 -0
- package/dist/services/features/telegram-mcp/collaboration.service.js +53 -0
- package/dist/services/features/telegram-mcp/ensuredb.service.js +337 -0
- package/dist/services/features/telegram-mcp/gateway-delivery.service.js +378 -0
- package/dist/services/features/telegram-mcp/gateway-loopback.js +10 -0
- package/dist/services/features/telegram-mcp/gateway-rmq.service.js +294 -0
- package/dist/services/features/telegram-mcp/gateway-socket.service.js +1463 -0
- package/dist/services/features/telegram-mcp/gateway.service.js +1141 -0
- package/dist/services/features/telegram-mcp/inbox.service.js +33 -0
- package/dist/services/features/telegram-mcp/mcp-http.service.js +76 -0
- package/dist/services/features/telegram-mcp/mcp-server.service.js +127 -0
- package/dist/services/features/telegram-mcp/notify.service.js +33 -0
- package/dist/services/features/telegram-mcp/pair.service.js +33 -0
- package/dist/services/features/telegram-mcp/runtime.service.js +36 -0
- package/dist/services/features/telegram-mcp/session-context.service.js +33 -0
- package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +103 -0
- package/dist/services/features/telegram-mcp/src/app/config/env.js +317 -0
- package/dist/services/features/telegram-mcp/src/app/http.js +774 -0
- package/dist/services/features/telegram-mcp/src/app/index.js +2 -0
- package/dist/services/features/telegram-mcp/src/app/providers/mcp/server.js +13 -0
- package/dist/services/features/telegram-mcp/src/app/providers/redis/client.js +18 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +740 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/auth.js +267 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/relay.js +69 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/tmux.js +9 -0
- package/dist/services/features/telegram-mcp/src/entities/auth/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/browser/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/collaboration/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/inbox/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +545 -0
- package/dist/services/features/telegram-mcp/src/entities/request/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/session/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/features/ask-user/model/askUserTelegram.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserClearLogsTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserClickTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserCloseTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserComputedStyleTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserConsoleTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserDomTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserErrorsTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserFillTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserNetworkFailuresTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserOpenTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserPressTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserReloadTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserScreenshotTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +689 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserWaitForTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserWaitForUrlTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/backend.js +2 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/collaborationService.js +26 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/localCollaborationBackend.js +390 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +102 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerNoteTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayCollaborationBackend.js +69 -0
- package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +657 -0
- package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayReplyResolution.js +17 -0
- package/dist/services/features/telegram-mcp/src/features/inbox/model/deleteTelegramInboxMessageTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxCountTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/inbox/model/inboxService.js +77 -0
- package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +93 -0
- package/dist/services/features/telegram-mcp/src/features/notify/model/notifyTelegramTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/clearSessionPairingTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/createSessionPairCodeTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/generatePairCode.js +202 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/clearSessionContextTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/getSessionContextTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/getTmuxTargetTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/renameSessionTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/sessionContextService.js +409 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/setSessionContextTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/setTmuxTargetTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownService.js +123 -0
- package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/processes/human-approval/model/orchestrator.js +243 -0
- package/dist/services/features/telegram-mcp/src/shared/api/storage/contract.js +2 -0
- package/dist/services/features/telegram-mcp/src/shared/api/tool-registry/registry.js +8 -0
- package/dist/services/features/telegram-mcp/src/shared/api/tool-registry/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/shared/api/transport/contract.js +2 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/object-storage/minioExchangeStore.js +86 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +436 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/collabSemantics.js +21 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/collabUi.js +87 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/messageFormat.js +60 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/proxyFetch.js +46 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +6534 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/tmux/client.js +280 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/ids/ids.js +34 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/logger/logger.js +68 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/project-identity/projectIdentity.js +223 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/redact-secrets/redactSecrets.js +22 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/truncate/truncate.js +12 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/version/versionHandshake.js +124 -0
- package/dist/services/features/telegram-mcp/src/shared/types/common.js +2 -0
- package/dist/services/features/telegram-mcp/standalone-http.service.js +113 -0
- package/dist/services/features/telegram-mcp/tools-sync.service.js +33 -0
- package/package.json +110 -0
- package/scripts/postinstall.js +60 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,636 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const node_fs_1 = require("node:fs");
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const node_child_process_1 = require("node:child_process");
|
|
10
|
+
const node_net_1 = __importDefault(require("node:net"));
|
|
11
|
+
const dotenv_1 = require("dotenv");
|
|
12
|
+
const picocolors_1 = __importDefault(require("picocolors"));
|
|
13
|
+
const ws_1 = __importDefault(require("ws"));
|
|
14
|
+
const distDir = __dirname;
|
|
15
|
+
const packageRoot = node_path_1.default.resolve(distDir, "..");
|
|
16
|
+
function getTmuxStatus() {
|
|
17
|
+
const result = (0, node_child_process_1.spawnSync)("tmux", ["-V"], {
|
|
18
|
+
encoding: "utf8",
|
|
19
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
20
|
+
});
|
|
21
|
+
if (result.status === 0) {
|
|
22
|
+
return {
|
|
23
|
+
found: true,
|
|
24
|
+
version: (result.stdout || "tmux").trim(),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return { found: false };
|
|
28
|
+
}
|
|
29
|
+
function printBanner(title, subtitle) {
|
|
30
|
+
process.stdout.write(`${picocolors_1.default.bold(picocolors_1.default.cyan("TellyMCP"))} ${picocolors_1.default.dim(title)}\n`);
|
|
31
|
+
if (subtitle) {
|
|
32
|
+
process.stdout.write(`${picocolors_1.default.dim(subtitle)}\n`);
|
|
33
|
+
}
|
|
34
|
+
process.stdout.write("\n");
|
|
35
|
+
}
|
|
36
|
+
function printSection(title, lines) {
|
|
37
|
+
process.stdout.write(`${picocolors_1.default.bold(title)}\n`);
|
|
38
|
+
for (const line of lines) {
|
|
39
|
+
process.stdout.write(`${line}\n`);
|
|
40
|
+
}
|
|
41
|
+
process.stdout.write("\n");
|
|
42
|
+
}
|
|
43
|
+
function getTmuxInstallHints() {
|
|
44
|
+
if (process.platform === "darwin") {
|
|
45
|
+
return ["brew install tmux"];
|
|
46
|
+
}
|
|
47
|
+
return [
|
|
48
|
+
"Ubuntu/Debian: sudo apt install tmux",
|
|
49
|
+
"Fedora/RHEL: sudo dnf install tmux",
|
|
50
|
+
"Arch: sudo pacman -S tmux",
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
function printHelp() {
|
|
54
|
+
const tmux = getTmuxStatus();
|
|
55
|
+
printBanner("CLI", "Telegram Human-in-the-Loop MCP server");
|
|
56
|
+
printSection("Usage", [
|
|
57
|
+
" tellymcp init <client|gateway|both> [directory]",
|
|
58
|
+
" tellymcp run [--env <file>]",
|
|
59
|
+
" tellymcp run --env=<file>",
|
|
60
|
+
" tellymcp doctor [--env <file>]",
|
|
61
|
+
" tellymcp mcp [--url <url>] [--bearer <token>] [--format claude|legacy]",
|
|
62
|
+
" tellymcp help",
|
|
63
|
+
]);
|
|
64
|
+
printSection("Examples", [
|
|
65
|
+
" tellymcp init client",
|
|
66
|
+
" tellymcp init gateway ./gateway-node",
|
|
67
|
+
" tellymcp run",
|
|
68
|
+
" tellymcp run --env .env.client",
|
|
69
|
+
" tellymcp doctor --env .env.client",
|
|
70
|
+
" tellymcp mcp --help",
|
|
71
|
+
]);
|
|
72
|
+
if (tmux.found) {
|
|
73
|
+
printSection("tmux", [
|
|
74
|
+
`${picocolors_1.default.green(" OK")} ${tmux.version}`,
|
|
75
|
+
" Live view and session nudges are available.",
|
|
76
|
+
]);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
printSection("tmux", [
|
|
80
|
+
`${picocolors_1.default.yellow(" WARN")} tmux was not found on this system.`,
|
|
81
|
+
" TellyMCP will still run, but Live view and nudges will be limited.",
|
|
82
|
+
" Install examples:",
|
|
83
|
+
...getTmuxInstallHints().map((line) => ` ${line}`),
|
|
84
|
+
]);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function printMcpHelp() {
|
|
88
|
+
printBanner("MCP helper", "Prints JSON snippets for Claude, Codex, and other MCP clients");
|
|
89
|
+
printSection("Usage", [
|
|
90
|
+
" tellymcp mcp --help",
|
|
91
|
+
" tellymcp mcp --url <url>",
|
|
92
|
+
" tellymcp mcp --url <url> --bearer <token>",
|
|
93
|
+
" tellymcp mcp --url <url> --format legacy",
|
|
94
|
+
]);
|
|
95
|
+
printSection("What this command does", [
|
|
96
|
+
" It prints a config snippet.",
|
|
97
|
+
" It does not register MCP in your agent automatically.",
|
|
98
|
+
" Copy the printed JSON into your agent's MCP config.",
|
|
99
|
+
]);
|
|
100
|
+
printSection("What you need", [
|
|
101
|
+
" 1. tmux must be installed on the machine where tellymcp runs.",
|
|
102
|
+
" 2. Your MCP endpoint depends on mode:",
|
|
103
|
+
" - client/local: http://127.0.0.1:8787/mcp",
|
|
104
|
+
" - gateway/both behind nginx: https://your-host.example/api/mcp",
|
|
105
|
+
]);
|
|
106
|
+
printSection("Claude / modern streamable-http example", [
|
|
107
|
+
"{",
|
|
108
|
+
' "mcpServers": {',
|
|
109
|
+
' "telegramHuman": {',
|
|
110
|
+
' "transport": {',
|
|
111
|
+
' "type": "streamable-http",',
|
|
112
|
+
' "url": "https://builder.undoo.ru/api/mcp"',
|
|
113
|
+
" }",
|
|
114
|
+
" }",
|
|
115
|
+
" }",
|
|
116
|
+
"}",
|
|
117
|
+
]);
|
|
118
|
+
printSection("Legacy example", [
|
|
119
|
+
"{",
|
|
120
|
+
' "mcpServers": {',
|
|
121
|
+
' "telegramHuman": {',
|
|
122
|
+
' "type": "streamable-http",',
|
|
123
|
+
' "url": "https://builder.undoo.ru/api/mcp"',
|
|
124
|
+
" }",
|
|
125
|
+
" }",
|
|
126
|
+
"}",
|
|
127
|
+
]);
|
|
128
|
+
printSection("With bearer token", [
|
|
129
|
+
"{",
|
|
130
|
+
' "mcpServers": {',
|
|
131
|
+
' "telegramHuman": {',
|
|
132
|
+
' "transport": {',
|
|
133
|
+
' "type": "streamable-http",',
|
|
134
|
+
' "url": "https://builder.undoo.ru/api/mcp",',
|
|
135
|
+
' "headers": {',
|
|
136
|
+
' "Authorization": "Bearer YOUR_TOKEN"',
|
|
137
|
+
" }",
|
|
138
|
+
" }",
|
|
139
|
+
" }",
|
|
140
|
+
" }",
|
|
141
|
+
"}",
|
|
142
|
+
]);
|
|
143
|
+
printSection("Examples", [
|
|
144
|
+
" tellymcp mcp --url https://builder.undoo.ru/api/mcp",
|
|
145
|
+
" tellymcp mcp --url https://builder.undoo.ru/api/mcp --bearer YOUR_TOKEN",
|
|
146
|
+
" tellymcp mcp --url https://builder.undoo.ru/api/mcp --format legacy",
|
|
147
|
+
]);
|
|
148
|
+
}
|
|
149
|
+
function fail(message) {
|
|
150
|
+
process.stderr.write(`${message}\n`);
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
function ensureMode(value) {
|
|
154
|
+
if (value === "client" || value === "gateway" || value === "both") {
|
|
155
|
+
return value;
|
|
156
|
+
}
|
|
157
|
+
fail("Mode must be one of: client, gateway, both.");
|
|
158
|
+
}
|
|
159
|
+
function loadTemplate(mode) {
|
|
160
|
+
const templateName = mode === "client"
|
|
161
|
+
? "env.client.template"
|
|
162
|
+
: mode === "gateway"
|
|
163
|
+
? "env.gateway.template"
|
|
164
|
+
: "env.both.template";
|
|
165
|
+
const templatePath = node_path_1.default.join(packageRoot, templateName);
|
|
166
|
+
const nestedTemplatePath = node_path_1.default.join(packageRoot, "config", "templates", templateName);
|
|
167
|
+
const resolvedTemplatePath = (0, node_fs_1.existsSync)(templatePath) ? templatePath : nestedTemplatePath;
|
|
168
|
+
if (!(0, node_fs_1.existsSync)(resolvedTemplatePath)) {
|
|
169
|
+
fail(`Missing packaged template: ${templateName}`);
|
|
170
|
+
}
|
|
171
|
+
return (0, node_fs_1.readFileSync)(resolvedTemplatePath, "utf8");
|
|
172
|
+
}
|
|
173
|
+
function initWorkspace(mode, directoryArg) {
|
|
174
|
+
const targetDir = node_path_1.default.resolve(directoryArg ?? process.cwd());
|
|
175
|
+
(0, node_fs_1.mkdirSync)(targetDir, { recursive: true });
|
|
176
|
+
const envPath = node_path_1.default.join(targetDir, ".env");
|
|
177
|
+
if ((0, node_fs_1.existsSync)(envPath)) {
|
|
178
|
+
fail(`Refusing to overwrite existing ${envPath}`);
|
|
179
|
+
}
|
|
180
|
+
const template = loadTemplate(mode);
|
|
181
|
+
(0, node_fs_1.writeFileSync)(envPath, template, "utf8");
|
|
182
|
+
for (const subdir of ["logs", "data", "artifacts"]) {
|
|
183
|
+
(0, node_fs_1.mkdirSync)(node_path_1.default.join(targetDir, subdir), { recursive: true });
|
|
184
|
+
}
|
|
185
|
+
printBanner("workspace initialized");
|
|
186
|
+
printSection("Created", [
|
|
187
|
+
` ${envPath}`,
|
|
188
|
+
` ${node_path_1.default.join(targetDir, "logs")}`,
|
|
189
|
+
` ${node_path_1.default.join(targetDir, "data")}`,
|
|
190
|
+
` ${node_path_1.default.join(targetDir, "artifacts")}`,
|
|
191
|
+
]);
|
|
192
|
+
printSection("Next", [
|
|
193
|
+
" 1. Edit .env",
|
|
194
|
+
` 2. cd ${targetDir}`,
|
|
195
|
+
" 3. tellymcp run",
|
|
196
|
+
]);
|
|
197
|
+
}
|
|
198
|
+
function resolveRunEnvPath(args) {
|
|
199
|
+
const [firstArg, secondArg] = args;
|
|
200
|
+
if (firstArg?.startsWith("--env=")) {
|
|
201
|
+
const value = firstArg.slice("--env=".length).trim();
|
|
202
|
+
if (!value) {
|
|
203
|
+
fail("Expected a file path after --env=");
|
|
204
|
+
}
|
|
205
|
+
return node_path_1.default.resolve(process.cwd(), value);
|
|
206
|
+
}
|
|
207
|
+
if (firstArg === "--env") {
|
|
208
|
+
if (!secondArg?.trim()) {
|
|
209
|
+
fail("Expected a file path after --env");
|
|
210
|
+
}
|
|
211
|
+
return node_path_1.default.resolve(process.cwd(), secondArg);
|
|
212
|
+
}
|
|
213
|
+
return node_path_1.default.resolve(process.cwd(), ".env");
|
|
214
|
+
}
|
|
215
|
+
function joinUrlPath(left, right) {
|
|
216
|
+
const normalizedLeft = left.endsWith("/") ? left.slice(0, -1) : left;
|
|
217
|
+
const normalizedRight = right.startsWith("/") ? right : `/${right}`;
|
|
218
|
+
return `${normalizedLeft}${normalizedRight}`.replace(/\/{2,}/gu, "/");
|
|
219
|
+
}
|
|
220
|
+
function deriveGatewayHealthUrlFromPublicUrl(rawUrl) {
|
|
221
|
+
try {
|
|
222
|
+
const url = new URL(rawUrl);
|
|
223
|
+
const pathname = url.pathname.replace(/\/+$/u, "");
|
|
224
|
+
if (pathname.endsWith("/gateway")) {
|
|
225
|
+
url.pathname = `${pathname.slice(0, -"/gateway".length) || ""}/healthz`;
|
|
226
|
+
return url.toString();
|
|
227
|
+
}
|
|
228
|
+
if (pathname.endsWith("/webapp")) {
|
|
229
|
+
url.pathname = `${pathname.slice(0, -"/webapp".length) || ""}/healthz`;
|
|
230
|
+
return url.toString();
|
|
231
|
+
}
|
|
232
|
+
if (pathname.endsWith("/mcp")) {
|
|
233
|
+
url.pathname = `${pathname.slice(0, -"/mcp".length) || ""}/healthz`;
|
|
234
|
+
return url.toString();
|
|
235
|
+
}
|
|
236
|
+
url.pathname = joinUrlPath(pathname || "/", "/healthz");
|
|
237
|
+
return url.toString();
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
function readFlagValue(args, flagName) {
|
|
244
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
245
|
+
const value = args[index];
|
|
246
|
+
if (value === flagName) {
|
|
247
|
+
const next = args[index + 1]?.trim();
|
|
248
|
+
if (!next) {
|
|
249
|
+
fail(`Expected a value after ${flagName}`);
|
|
250
|
+
}
|
|
251
|
+
return next;
|
|
252
|
+
}
|
|
253
|
+
if (value?.startsWith(`${flagName}=`)) {
|
|
254
|
+
const inlineValue = value.slice(flagName.length + 1).trim();
|
|
255
|
+
if (!inlineValue) {
|
|
256
|
+
fail(`Expected a value after ${flagName}=`);
|
|
257
|
+
}
|
|
258
|
+
return inlineValue;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
function printMcpConfig(args) {
|
|
264
|
+
if (args.length === 0 ||
|
|
265
|
+
args.includes("--help") ||
|
|
266
|
+
args.includes("-h")) {
|
|
267
|
+
printMcpHelp();
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const url = readFlagValue(args, "--url");
|
|
271
|
+
if (!url) {
|
|
272
|
+
fail("Missing --url <mcp-endpoint>. Run 'tellymcp mcp --help' for examples.");
|
|
273
|
+
}
|
|
274
|
+
const bearer = readFlagValue(args, "--bearer");
|
|
275
|
+
const format = (readFlagValue(args, "--format") ?? "claude").toLowerCase();
|
|
276
|
+
if (format !== "claude" && format !== "legacy") {
|
|
277
|
+
fail("Supported --format values: claude, legacy.");
|
|
278
|
+
}
|
|
279
|
+
const config = format === "legacy"
|
|
280
|
+
? {
|
|
281
|
+
mcpServers: {
|
|
282
|
+
telegramHuman: {
|
|
283
|
+
type: "streamable-http",
|
|
284
|
+
url,
|
|
285
|
+
...(bearer
|
|
286
|
+
? {
|
|
287
|
+
headers: {
|
|
288
|
+
Authorization: `Bearer ${bearer}`,
|
|
289
|
+
},
|
|
290
|
+
}
|
|
291
|
+
: {}),
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
}
|
|
295
|
+
: {
|
|
296
|
+
mcpServers: {
|
|
297
|
+
telegramHuman: {
|
|
298
|
+
transport: {
|
|
299
|
+
type: "streamable-http",
|
|
300
|
+
url,
|
|
301
|
+
...(bearer
|
|
302
|
+
? {
|
|
303
|
+
headers: {
|
|
304
|
+
Authorization: `Bearer ${bearer}`,
|
|
305
|
+
},
|
|
306
|
+
}
|
|
307
|
+
: {}),
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
};
|
|
312
|
+
process.stdout.write(`${JSON.stringify(config, null, 2)}\n`);
|
|
313
|
+
}
|
|
314
|
+
async function checkTcpPort(host, port, timeoutMs = 2000) {
|
|
315
|
+
return await new Promise((resolve) => {
|
|
316
|
+
const socket = node_net_1.default.connect({ host, port });
|
|
317
|
+
const finish = (ok, message) => {
|
|
318
|
+
socket.removeAllListeners();
|
|
319
|
+
socket.destroy();
|
|
320
|
+
resolve({ ok, message });
|
|
321
|
+
};
|
|
322
|
+
socket.setTimeout(timeoutMs);
|
|
323
|
+
socket.once("connect", () => finish(true, `${host}:${port} is reachable`));
|
|
324
|
+
socket.once("timeout", () => finish(false, `${host}:${port} timed out`));
|
|
325
|
+
socket.once("error", (error) => {
|
|
326
|
+
finish(false, `${host}:${port} failed: ${error.code ?? error.message}`);
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
async function checkHttpHealth(url, timeoutMs = 3000) {
|
|
331
|
+
const controller = new AbortController();
|
|
332
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
333
|
+
try {
|
|
334
|
+
const response = await fetch(url, {
|
|
335
|
+
method: "GET",
|
|
336
|
+
signal: controller.signal,
|
|
337
|
+
});
|
|
338
|
+
clearTimeout(timer);
|
|
339
|
+
return {
|
|
340
|
+
ok: response.ok,
|
|
341
|
+
message: `${url} returned ${response.status}`,
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
clearTimeout(timer);
|
|
346
|
+
return {
|
|
347
|
+
ok: false,
|
|
348
|
+
message: `${url} failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
async function checkWebSocketUrl(url, timeoutMs = 3000) {
|
|
353
|
+
return await new Promise((resolve) => {
|
|
354
|
+
let settled = false;
|
|
355
|
+
let opened = false;
|
|
356
|
+
const finish = (ok, message) => {
|
|
357
|
+
if (settled) {
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
settled = true;
|
|
361
|
+
clearTimeout(timer);
|
|
362
|
+
socket.removeAllListeners();
|
|
363
|
+
try {
|
|
364
|
+
socket.close();
|
|
365
|
+
}
|
|
366
|
+
catch {
|
|
367
|
+
// ignore
|
|
368
|
+
}
|
|
369
|
+
resolve({ ok, message });
|
|
370
|
+
};
|
|
371
|
+
const socket = new ws_1.default(url);
|
|
372
|
+
const timer = setTimeout(() => {
|
|
373
|
+
finish(false, `${url} timed out`);
|
|
374
|
+
}, timeoutMs);
|
|
375
|
+
socket.once("open", () => {
|
|
376
|
+
opened = true;
|
|
377
|
+
finish(true, `${url} accepted a WebSocket connection`);
|
|
378
|
+
});
|
|
379
|
+
socket.once("unexpected-response", (_req, response) => {
|
|
380
|
+
finish(false, `${url} returned HTTP ${response.statusCode ?? "unknown"} during WebSocket upgrade`);
|
|
381
|
+
});
|
|
382
|
+
socket.once("error", (error) => {
|
|
383
|
+
finish(false, `${url} failed: ${error.message}`);
|
|
384
|
+
});
|
|
385
|
+
socket.once("close", (code) => {
|
|
386
|
+
if (!opened) {
|
|
387
|
+
finish(false, `${url} closed before open (code ${code})`);
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
async function runDoctor(args) {
|
|
393
|
+
const envPath = resolveRunEnvPath(args);
|
|
394
|
+
const tmux = getTmuxStatus();
|
|
395
|
+
printBanner("doctor", "Local installation diagnostics");
|
|
396
|
+
if (tmux.found) {
|
|
397
|
+
printSection("tmux", [
|
|
398
|
+
`${picocolors_1.default.green(" OK")} ${tmux.version}`,
|
|
399
|
+
" Live view and session nudges should work.",
|
|
400
|
+
]);
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
printSection("tmux", [
|
|
404
|
+
`${picocolors_1.default.yellow(" WARN")} tmux was not found.`,
|
|
405
|
+
" TellyMCP will still run, but Live view and nudges will be limited.",
|
|
406
|
+
" Install examples:",
|
|
407
|
+
...getTmuxInstallHints().map((line) => ` ${line}`),
|
|
408
|
+
]);
|
|
409
|
+
}
|
|
410
|
+
if (!(0, node_fs_1.existsSync)(envPath)) {
|
|
411
|
+
printSection("env", [
|
|
412
|
+
`${picocolors_1.default.red(" ERROR")} Missing env file: ${envPath}`,
|
|
413
|
+
" Run 'tellymcp init client' or pass --env <file>.",
|
|
414
|
+
]);
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
const envContent = (0, node_fs_1.readFileSync)(envPath, "utf8");
|
|
418
|
+
const parsed = (0, dotenv_1.parse)(envContent);
|
|
419
|
+
const mode = (parsed.DISTRIBUTED_MODE || "client").trim();
|
|
420
|
+
const httpHost = (parsed.MCP_HTTP_HOST || "0.0.0.0").trim();
|
|
421
|
+
const httpPort = mode === "gateway" || mode === "both"
|
|
422
|
+
? (parsed.PORT || parsed.MCP_HTTP_PORT || "8080").trim()
|
|
423
|
+
: (parsed.MCP_HTTP_PORT || "8787").trim();
|
|
424
|
+
const rootPrefix = mode === "gateway" || mode === "both"
|
|
425
|
+
? (parsed.ROOT_PREFIX || "/api").trim()
|
|
426
|
+
: "";
|
|
427
|
+
const mcpPath = (parsed.MCP_HTTP_PATH || "/mcp").trim();
|
|
428
|
+
const webappPath = (parsed.WEBAPP_BASE_PATH || "/webapp").trim();
|
|
429
|
+
const mcpUrlPath = mode === "gateway" || mode === "both"
|
|
430
|
+
? joinUrlPath(rootPrefix, mcpPath)
|
|
431
|
+
: mcpPath;
|
|
432
|
+
const webappUrlPath = mode === "gateway" || mode === "both"
|
|
433
|
+
? joinUrlPath(rootPrefix, webappPath)
|
|
434
|
+
: webappPath;
|
|
435
|
+
const healthUrlPath = mode === "gateway" || mode === "both"
|
|
436
|
+
? joinUrlPath(rootPrefix, "/healthz")
|
|
437
|
+
: "/healthz";
|
|
438
|
+
const publicGatewayUrl = parsed.GATEWAY_PUBLIC_URL?.trim();
|
|
439
|
+
const gatewayWsUrl = parsed.GATEWAY_WS_URL?.trim();
|
|
440
|
+
const publicWebappUrl = parsed.WEBAPP_PUBLIC_URL?.trim();
|
|
441
|
+
const mcpBearerToken = parsed.MCP_HTTP_BEARER_TOKEN?.trim();
|
|
442
|
+
const externalHealthUrl = deriveGatewayHealthUrlFromPublicUrl(publicGatewayUrl || "") ??
|
|
443
|
+
deriveGatewayHealthUrlFromPublicUrl(publicWebappUrl || "");
|
|
444
|
+
printSection("env", [
|
|
445
|
+
`${picocolors_1.default.green(" OK")} ${envPath}`,
|
|
446
|
+
` mode: ${mode}`,
|
|
447
|
+
` bind: http://${httpHost}:${httpPort}`,
|
|
448
|
+
` mcp: http://${httpHost}:${httpPort}${mcpUrlPath}`,
|
|
449
|
+
` web: http://${httpHost}:${httpPort}${webappUrlPath}`,
|
|
450
|
+
` mcp auth: ${mcpBearerToken ? "bearer token required" : "disabled"}`,
|
|
451
|
+
...(publicGatewayUrl ? [` public gateway: ${publicGatewayUrl}`] : []),
|
|
452
|
+
...(gatewayWsUrl ? [` public ws: ${gatewayWsUrl}`] : []),
|
|
453
|
+
...(publicWebappUrl ? [` public web: ${publicWebappUrl}`] : []),
|
|
454
|
+
...(externalHealthUrl ? [` public health: ${externalHealthUrl}`] : []),
|
|
455
|
+
]);
|
|
456
|
+
const checks = [];
|
|
457
|
+
const capabilities = [];
|
|
458
|
+
const redisHost = (parsed.REDIS_HOST || "127.0.0.1").trim();
|
|
459
|
+
const redisPort = Number(parsed.REDIS_PORT || 6379);
|
|
460
|
+
const redisCheck = await checkTcpPort(redisHost, redisPort);
|
|
461
|
+
checks.push(`${redisCheck.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.red(" ERROR")} redis: ${redisCheck.message}`);
|
|
462
|
+
if (mode === "client") {
|
|
463
|
+
const gatewayPublicUrl = parsed.GATEWAY_PUBLIC_URL?.trim();
|
|
464
|
+
if (gatewayPublicUrl) {
|
|
465
|
+
const gatewayHealth = await checkHttpHealth(`${gatewayPublicUrl.replace(/\/+$/u, "")}/healthz`);
|
|
466
|
+
checks.push(`${gatewayHealth.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.red(" ERROR")} gateway: ${gatewayHealth.message}`);
|
|
467
|
+
capabilities.push(`${gatewayHealth.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.red(" ERROR")} remote collaboration API: ${gatewayHealth.ok ? "available" : "unavailable"}`);
|
|
468
|
+
}
|
|
469
|
+
else {
|
|
470
|
+
checks.push(`${picocolors_1.default.yellow(" WARN")} gateway: GATEWAY_PUBLIC_URL is empty`);
|
|
471
|
+
capabilities.push(`${picocolors_1.default.yellow(" WARN")} remote collaboration API: not configured`);
|
|
472
|
+
}
|
|
473
|
+
if (gatewayWsUrl) {
|
|
474
|
+
const gatewayWs = await checkWebSocketUrl(gatewayWsUrl);
|
|
475
|
+
checks.push(`${gatewayWs.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.red(" ERROR")} gateway ws: ${gatewayWs.message}`);
|
|
476
|
+
capabilities.push(`${gatewayWs.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.red(" ERROR")} remote live relay: ${gatewayWs.ok ? "available" : "unavailable"}`);
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
checks.push(`${picocolors_1.default.yellow(" WARN")} gateway ws: GATEWAY_WS_URL is empty`);
|
|
480
|
+
capabilities.push(`${picocolors_1.default.yellow(" WARN")} remote live relay: not configured`);
|
|
481
|
+
}
|
|
482
|
+
if (publicWebappUrl) {
|
|
483
|
+
const publicWebapp = await checkHttpHealth(publicWebappUrl);
|
|
484
|
+
checks.push(`${publicWebapp.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.red(" ERROR")} public webapp: ${publicWebapp.message}`);
|
|
485
|
+
capabilities.push(`${publicWebapp.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.red(" ERROR")} remote webapp launcher: ${publicWebapp.ok ? "available" : "unavailable"}`);
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
checks.push(`${picocolors_1.default.yellow(" WARN")} public webapp: WEBAPP_PUBLIC_URL is empty`);
|
|
489
|
+
capabilities.push(`${picocolors_1.default.yellow(" WARN")} remote webapp launcher: not configured`);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
if (mode === "gateway" || mode === "both") {
|
|
493
|
+
const localHealth = await checkHttpHealth(`http://${httpHost}:${httpPort}${healthUrlPath}`);
|
|
494
|
+
checks.push(`${localHealth.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.yellow(" WARN")} local healthz: ${localHealth.message}`);
|
|
495
|
+
capabilities.push(`${localHealth.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.red(" ERROR")} local gateway api: ${localHealth.ok ? "available" : "unavailable"}`);
|
|
496
|
+
if (externalHealthUrl) {
|
|
497
|
+
const externalHealth = await checkHttpHealth(externalHealthUrl);
|
|
498
|
+
checks.push(`${externalHealth.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.red(" ERROR")} public healthz: ${externalHealth.message}`);
|
|
499
|
+
capabilities.push(`${externalHealth.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.red(" ERROR")} public gateway api: ${externalHealth.ok ? "available" : "unavailable"}`);
|
|
500
|
+
}
|
|
501
|
+
else {
|
|
502
|
+
checks.push(`${picocolors_1.default.yellow(" WARN")} public healthz: no public gateway/webapp URL is configured`);
|
|
503
|
+
capabilities.push(`${picocolors_1.default.yellow(" WARN")} public gateway api: not configured`);
|
|
504
|
+
}
|
|
505
|
+
if (gatewayWsUrl) {
|
|
506
|
+
const gatewayWs = await checkWebSocketUrl(gatewayWsUrl);
|
|
507
|
+
checks.push(`${gatewayWs.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.red(" ERROR")} public ws: ${gatewayWs.message}`);
|
|
508
|
+
capabilities.push(`${gatewayWs.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.red(" ERROR")} public live relay: ${gatewayWs.ok ? "available" : "unavailable"}`);
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
checks.push(`${picocolors_1.default.yellow(" WARN")} public ws: GATEWAY_WS_URL is empty`);
|
|
512
|
+
capabilities.push(`${picocolors_1.default.yellow(" WARN")} public live relay: not configured`);
|
|
513
|
+
}
|
|
514
|
+
if (publicWebappUrl) {
|
|
515
|
+
const publicWebapp = await checkHttpHealth(publicWebappUrl);
|
|
516
|
+
checks.push(`${publicWebapp.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.red(" ERROR")} public webapp: ${publicWebapp.message}`);
|
|
517
|
+
capabilities.push(`${publicWebapp.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.red(" ERROR")} public webapp launcher: ${publicWebapp.ok ? "available" : "unavailable"}`);
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
checks.push(`${picocolors_1.default.yellow(" WARN")} public webapp: WEBAPP_PUBLIC_URL is empty`);
|
|
521
|
+
capabilities.push(`${picocolors_1.default.yellow(" WARN")} public webapp launcher: not configured`);
|
|
522
|
+
}
|
|
523
|
+
const dbHost = parsed.DB_HOST?.trim();
|
|
524
|
+
if (dbHost) {
|
|
525
|
+
const dbPort = Number(parsed.DB_PORT || 5432);
|
|
526
|
+
const dbCheck = await checkTcpPort(dbHost, dbPort);
|
|
527
|
+
checks.push(`${dbCheck.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.red(" ERROR")} postgres: ${dbCheck.message}`);
|
|
528
|
+
}
|
|
529
|
+
else {
|
|
530
|
+
checks.push(`${picocolors_1.default.yellow(" WARN")} postgres: DB_HOST is empty`);
|
|
531
|
+
}
|
|
532
|
+
const rmqHost = parsed.RMQ_HOST?.trim();
|
|
533
|
+
if (rmqHost) {
|
|
534
|
+
const rmqPort = Number(parsed.RMQ_PORT || 5672);
|
|
535
|
+
const rmqCheck = await checkTcpPort(rmqHost, rmqPort);
|
|
536
|
+
checks.push(`${rmqCheck.ok ? picocolors_1.default.green(" OK") : picocolors_1.default.red(" ERROR")} rmq: ${rmqCheck.message}`);
|
|
537
|
+
}
|
|
538
|
+
else {
|
|
539
|
+
checks.push(`${picocolors_1.default.dim(" SKIP")} rmq: RMQ_HOST is not configured`);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
printSection("capabilities", capabilities);
|
|
543
|
+
printSection("checks", checks);
|
|
544
|
+
const notes = [];
|
|
545
|
+
if (!parsed.TELEGRAM_BOT_TOKEN?.trim()) {
|
|
546
|
+
notes.push(`${picocolors_1.default.yellow(" WARN")} TELEGRAM_BOT_TOKEN is empty`);
|
|
547
|
+
}
|
|
548
|
+
if (mcpBearerToken) {
|
|
549
|
+
notes.push(`${picocolors_1.default.yellow(" WARN")} MCP_HTTP_BEARER_TOKEN is set. MCP clients must send Authorization: Bearer <token>.`);
|
|
550
|
+
}
|
|
551
|
+
if ((mode === "gateway" || mode === "both") && !parsed.ROOT_PREFIX?.trim()) {
|
|
552
|
+
notes.push(`${picocolors_1.default.yellow(" WARN")} ROOT_PREFIX is not set, default /api will be used`);
|
|
553
|
+
}
|
|
554
|
+
if ((mode === "gateway" || mode === "both") && !parsed.PORT?.trim()) {
|
|
555
|
+
notes.push(`${picocolors_1.default.yellow(" WARN")} PORT is not set, default bind port will be used`);
|
|
556
|
+
}
|
|
557
|
+
if (notes.length > 0) {
|
|
558
|
+
printSection("notes", notes);
|
|
559
|
+
}
|
|
560
|
+
else {
|
|
561
|
+
printSection("notes", [`${picocolors_1.default.green(" OK")} No obvious local config issues detected.`]);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
function runRuntime(args) {
|
|
565
|
+
const envPath = resolveRunEnvPath(args);
|
|
566
|
+
if (!(0, node_fs_1.existsSync)(envPath)) {
|
|
567
|
+
fail(`Missing ${envPath}. Run 'tellymcp init <client|gateway|both>' first or pass --env <file>.`);
|
|
568
|
+
}
|
|
569
|
+
const runnerPath = node_path_1.default.join(packageRoot, "node_modules", "moleculer", "bin", "moleculer-runner.js");
|
|
570
|
+
const configPath = node_path_1.default.join(packageRoot, "dist", "moleculer.config.js");
|
|
571
|
+
const servicesPath = node_path_1.default.join(packageRoot, "dist", "services");
|
|
572
|
+
if (!(0, node_fs_1.existsSync)(runnerPath)) {
|
|
573
|
+
fail(`Missing bundled runner: ${runnerPath}`);
|
|
574
|
+
}
|
|
575
|
+
if (!(0, node_fs_1.existsSync)(configPath)) {
|
|
576
|
+
fail(`Missing compiled config: ${configPath}`);
|
|
577
|
+
}
|
|
578
|
+
if (!(0, node_fs_1.existsSync)(servicesPath)) {
|
|
579
|
+
fail(`Missing compiled services: ${servicesPath}`);
|
|
580
|
+
}
|
|
581
|
+
const tmux = getTmuxStatus();
|
|
582
|
+
if (tmux.found) {
|
|
583
|
+
process.stdout.write(`${picocolors_1.default.green("tmux detected:")} ${tmux.version}\n`);
|
|
584
|
+
}
|
|
585
|
+
else {
|
|
586
|
+
process.stdout.write(`${picocolors_1.default.yellow("tmux not found.")} Live view and nudges may be limited.\n`);
|
|
587
|
+
}
|
|
588
|
+
process.stdout.write(`${picocolors_1.default.cyan("Using env:")} ${envPath}\n\n`);
|
|
589
|
+
const child = (0, node_child_process_1.spawn)(process.execPath, [
|
|
590
|
+
runnerPath,
|
|
591
|
+
servicesPath,
|
|
592
|
+
"--config",
|
|
593
|
+
configPath,
|
|
594
|
+
"--mask",
|
|
595
|
+
"**/*.service.js",
|
|
596
|
+
], {
|
|
597
|
+
cwd: process.cwd(),
|
|
598
|
+
stdio: "inherit",
|
|
599
|
+
env: {
|
|
600
|
+
...process.env,
|
|
601
|
+
ENV_FILE: envPath,
|
|
602
|
+
TELLYMCP_STANDALONE_HTTP: "true",
|
|
603
|
+
},
|
|
604
|
+
});
|
|
605
|
+
child.on("exit", (code, signal) => {
|
|
606
|
+
if (signal) {
|
|
607
|
+
process.kill(process.pid, signal);
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
process.exit(code ?? 0);
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
async function main(argv) {
|
|
614
|
+
const [rawCommand, firstArg, secondArg] = argv;
|
|
615
|
+
const command = rawCommand === "init" || rawCommand === "run" || rawCommand === "help" || rawCommand === "mcp" || rawCommand === "doctor"
|
|
616
|
+
? rawCommand
|
|
617
|
+
: "help";
|
|
618
|
+
if (command === "help" || !rawCommand || rawCommand === "--help" || rawCommand === "-h") {
|
|
619
|
+
printHelp();
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
if (command === "init") {
|
|
623
|
+
initWorkspace(ensureMode(firstArg), secondArg);
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
if (command === "mcp") {
|
|
627
|
+
printMcpConfig(argv.slice(1));
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
if (command === "doctor") {
|
|
631
|
+
await runDoctor(argv.slice(1));
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
runRuntime(argv.slice(1));
|
|
635
|
+
}
|
|
636
|
+
void main(process.argv.slice(2));
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./lib/moleculer"), exports);
|