@deadragdoll/tellymcp 0.0.9 → 0.0.11
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 +42 -50
- package/.env.example.gateway +49 -61
- package/CHANGELOG.md +3 -3
- package/README-ru.md +205 -384
- package/README.md +195 -1194
- package/TOOLS.md +294 -377
- package/VERSION.md +36 -10
- package/config/codex/plugins/telly-workflows/.codex-plugin/plugin.json +18 -0
- package/config/codex/plugins/telly-workflows/references/invariants.md +10 -0
- package/config/codex/plugins/telly-workflows/skills/telly-browser-screenshot/SKILL.md +27 -0
- package/config/codex/plugins/telly-workflows/skills/telly-collab-artifact/SKILL.md +22 -0
- package/config/codex/plugins/telly-workflows/skills/telly-human-telegram/SKILL.md +31 -0
- package/config/codex/plugins/telly-workflows/skills/telly-partner-note/SKILL.md +36 -0
- package/config/templates/env.both.template +40 -20
- package/config/templates/env.client.template +34 -18
- package/config/templates/env.gateway.template +38 -22
- package/dist/cli.js +322 -75
- package/dist/codexPluginInstaller.js +215 -0
- package/dist/lib/mixins/session.errors.js +34 -1
- package/dist/lib/pinoTargets.js +2 -2
- package/dist/moleculer.config.js +7 -5
- package/dist/services/features/telegram-mcp/approval.service.js +1 -1
- package/dist/services/features/telegram-mcp/browser.service.js +95 -2
- package/dist/services/features/telegram-mcp/collaboration.service.js +41 -4
- package/dist/services/features/telegram-mcp/ensuredb.service.js +145 -26
- package/dist/services/features/telegram-mcp/gateway-delivery.service.js +285 -103
- package/dist/services/features/telegram-mcp/gateway-rmq.service.js +3 -2
- package/dist/services/features/telegram-mcp/gateway-socket.service.js +905 -87
- package/dist/services/features/telegram-mcp/gateway.service.js +876 -81
- package/dist/services/features/telegram-mcp/mcp-http.service.js +9 -1
- package/dist/services/features/telegram-mcp/mcp-server.service.js +17 -26
- package/dist/services/features/telegram-mcp/notify.service.js +128 -2
- package/dist/services/features/telegram-mcp/runtime.service.js +27 -7
- package/dist/services/features/telegram-mcp/session-context.service.js +29 -2
- package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +133 -10
- package/dist/services/features/telegram-mcp/src/app/config/env.js +161 -51
- package/dist/services/features/telegram-mcp/src/app/http.js +375 -42
- package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +386 -58
- package/dist/services/features/telegram-mcp/src/app/webapp/auth.js +3 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/terminal.js +12 -0
- package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +116 -104
- package/dist/services/features/telegram-mcp/src/entities/xchange/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/features/ask-user/model/askUserTelegram.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserScreenshotTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +249 -19
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/gatewaySessionsService.js +71 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/listGatewaySessionsTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/localCollaborationBackend.js +93 -82
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +47 -5
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerNoteTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayClientAccess.js +82 -0
- package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayCollaborationBackend.js +22 -14
- package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +649 -75
- package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/remoteConsoleActionClient.js +76 -0
- package/dist/services/features/telegram-mcp/src/features/embedded-runtime/model/embeddedRuntimeBroker.js +92 -0
- package/dist/services/features/telegram-mcp/src/features/foreground-terminal/model/foregroundTerminalRuntime.js +192 -0
- package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +382 -3
- package/dist/services/features/telegram-mcp/src/features/notify/model/notifyTelegramTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/notify/model/sendFileToTelegramTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/clearSessionContextTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/session-context/model/getSessionContextTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/session-context/model/renameSessionTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/session-context/model/sessionContextService.js +42 -200
- package/dist/services/features/telegram-mcp/src/features/session-context/model/setSessionContextTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/terminal-buffer/model/terminalBufferService.js +96 -0
- package/dist/services/features/telegram-mcp/src/features/terminal-input/model/terminalInputService.js +97 -0
- package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownService.js +107 -58
- package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/xchange/model/getXchangeRecordTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/xchange/model/listXchangeRecordsTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/xchange/model/markXchangeRecordReadTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/xchange/model/xchangeService.js +169 -0
- package/dist/services/features/telegram-mcp/src/processes/human-approval/model/orchestrator.js +5 -4
- 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 +652 -0
- package/dist/services/features/telegram-mcp/src/shared/i18n/resources/ru.js +652 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/memory/processLocalSessionStore.js +27 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/object-storage/minioExchangeStore.js +11 -8
- package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +51 -71
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/proxyFetch.js +21 -22
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +411 -6524
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportAttachmentStore.js +93 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportBroadcastActions.js +385 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConsoleRegistry.js +143 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConstructorWiring.js +633 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContent.js +84 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContext.js +78 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportDocumentActions.js +36 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportEventActions.js +292 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFileHandoffActions.js +352 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFormatting.js +75 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportGatewayActions.js +44 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLifecycleActions.js +161 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLive.js +56 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLiveActions.js +77 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuCallbacks.js +254 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFactories.js +538 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFingerprints.js +93 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFlow.js +344 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuShell.js +62 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuState.js +408 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuText.js +216 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMessageFlow.js +452 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportOutputActions.js +189 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPartnerActions.js +286 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPayloadState.js +101 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectActions.js +463 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEntryActions.js +202 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEvents.js +99 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectMenus.js +138 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectState.js +308 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectView.js +426 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportRequestFlow.js +278 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportSessionActions.js +143 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalActions.js +468 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalRuntime.js +171 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTypes.js +2 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportUtils.js +330 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportXchangeState.js +107 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/client.js +255 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/ptyRegistry.js +543 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/xchange/sqliteRecordStore.js +223 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/gatewayScope.js +24 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/logger/logger.js +6 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/project-identity/projectIdentity.js +147 -76
- package/dist/services/features/telegram-mcp/src/shared/lib/telegramXchangeRecords.js +72 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/terminalPromptDetection.js +237 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/version/versionHandshake.js +129 -1
- package/dist/services/features/telegram-mcp/src/shared/lib/xchangeRecordHints.js +98 -0
- package/dist/services/features/telegram-mcp/standalone-http.service.js +13 -1
- package/dist/services/features/telegram-mcp/terminal-buffer.service.js +42 -0
- package/dist/services/features/telegram-mcp/terminal-input.service.js +41 -0
- package/dist/services/features/telegram-mcp/tools-sync.service.js +16 -2
- package/dist/services/features/telegram-mcp/xchange.service.js +123 -0
- package/docs/STANDALONE-ru.md +172 -0
- package/docs/STANDALONE.md +172 -0
- package/package.json +11 -5
- package/scripts/build-package-artifact.sh +27 -0
- package/scripts/deploy-gateway.sh +64 -0
- package/scripts/deploy-onebot-branch.sh +27 -0
- package/scripts/postinstall.js +11 -36
- package/STANDALONE-ru.md +0 -274
- package/STANDALONE.md +0 -274
- package/dist/services/features/telegram-mcp/inbox.service.js +0 -33
- package/dist/services/features/telegram-mcp/pair.service.js +0 -33
- package/dist/services/features/telegram-mcp/src/app/webapp/tmux.js +0 -10
- package/dist/services/features/telegram-mcp/src/features/inbox/model/deleteTelegramInboxMessageTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxCountTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/inbox/model/inboxService.js +0 -77
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/clearSessionPairingTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/createSessionPairCodeTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/generatePairCode.js +0 -202
- package/dist/services/features/telegram-mcp/src/features/session-context/model/getTmuxTargetTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/session-context/model/setTmuxTargetTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/shared/integrations/tmux/client.js +0 -363
package/dist/cli.js
CHANGED
|
@@ -9,25 +9,16 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
9
9
|
const node_child_process_1 = require("node:child_process");
|
|
10
10
|
const node_net_1 = __importDefault(require("node:net"));
|
|
11
11
|
const dotenv_1 = require("dotenv");
|
|
12
|
+
const ioredis_1 = __importDefault(require("ioredis"));
|
|
12
13
|
const picocolors_1 = __importDefault(require("picocolors"));
|
|
13
14
|
const ws_1 = __importDefault(require("ws"));
|
|
15
|
+
const codexPluginInstaller_1 = require("./codexPluginInstaller");
|
|
14
16
|
const versionHandshake_1 = require("./services/features/telegram-mcp/src/shared/lib/version/versionHandshake");
|
|
17
|
+
const projectIdentity_1 = require("./services/features/telegram-mcp/src/shared/lib/project-identity/projectIdentity");
|
|
18
|
+
const foregroundTerminalRuntime_1 = require("./services/features/telegram-mcp/src/features/foreground-terminal/model/foregroundTerminalRuntime");
|
|
15
19
|
const distDir = __dirname;
|
|
16
20
|
const packageRoot = node_path_1.default.resolve(distDir, "..");
|
|
17
21
|
const cliPackageVersion = (0, versionHandshake_1.getTellyMcpPackageVersion)(__dirname);
|
|
18
|
-
function getTmuxStatus() {
|
|
19
|
-
const result = (0, node_child_process_1.spawnSync)("tmux", ["-V"], {
|
|
20
|
-
encoding: "utf8",
|
|
21
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
22
|
-
});
|
|
23
|
-
if (result.status === 0) {
|
|
24
|
-
return {
|
|
25
|
-
found: true,
|
|
26
|
-
version: (result.stdout || "tmux").trim(),
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
return { found: false };
|
|
30
|
-
}
|
|
31
22
|
function printBanner(title, subtitle) {
|
|
32
23
|
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`);
|
|
33
24
|
if (subtitle) {
|
|
@@ -42,16 +33,6 @@ function printSection(title, lines) {
|
|
|
42
33
|
}
|
|
43
34
|
process.stdout.write("\n");
|
|
44
35
|
}
|
|
45
|
-
function getTmuxInstallHints() {
|
|
46
|
-
if (process.platform === "darwin") {
|
|
47
|
-
return ["brew install tmux"];
|
|
48
|
-
}
|
|
49
|
-
return [
|
|
50
|
-
"Ubuntu/Debian: sudo apt install tmux",
|
|
51
|
-
"Fedora/RHEL: sudo dnf install tmux",
|
|
52
|
-
"Arch: sudo pacman -S tmux",
|
|
53
|
-
];
|
|
54
|
-
}
|
|
55
36
|
async function getPlaywrightBrowserStatus(browserEnabled) {
|
|
56
37
|
if (!browserEnabled) {
|
|
57
38
|
return { enabled: false };
|
|
@@ -81,14 +62,18 @@ async function getPlaywrightBrowserStatus(browserEnabled) {
|
|
|
81
62
|
}
|
|
82
63
|
}
|
|
83
64
|
function printHelp() {
|
|
84
|
-
const tmux = getTmuxStatus();
|
|
85
65
|
printBanner("CLI", "Telegram control plane for MCP-connected coding agents");
|
|
86
66
|
printSection("Usage", [
|
|
87
67
|
" tellymcp init <client|gateway|both> [directory]",
|
|
88
68
|
" tellymcp run [--env <file>]",
|
|
89
69
|
" tellymcp run --env=<file>",
|
|
70
|
+
" tellymcp run --env .env-client -s backendDev",
|
|
71
|
+
" tellymcp run # if .mcpsession.json already stores env_file + local_session_id",
|
|
90
72
|
" tellymcp doctor [--env <file>]",
|
|
73
|
+
" tellymcp system-prune [--env <file>] --yes",
|
|
91
74
|
" tellymcp browser install",
|
|
75
|
+
" tellymcp codex-plugin install",
|
|
76
|
+
" tellymcp codex-plugin status",
|
|
92
77
|
" tellymcp mcp [--url <url>] [--bearer <token>] [--format claude|legacy]",
|
|
93
78
|
" tellymcp help",
|
|
94
79
|
]);
|
|
@@ -97,24 +82,94 @@ function printHelp() {
|
|
|
97
82
|
" tellymcp init gateway ./gateway-node",
|
|
98
83
|
" tellymcp run",
|
|
99
84
|
" tellymcp run --env .env.client",
|
|
85
|
+
" tellymcp run --env .env-client -s backendDev",
|
|
86
|
+
" tellymcp run # reuses .mcpsession.json in the current workspace",
|
|
100
87
|
" tellymcp doctor --env .env.client",
|
|
88
|
+
" tellymcp system-prune --env .env.gateway --yes",
|
|
101
89
|
" tellymcp browser install",
|
|
90
|
+
" tellymcp codex-plugin install",
|
|
91
|
+
" tellymcp codex-plugin status",
|
|
102
92
|
" tellymcp mcp --help",
|
|
103
93
|
]);
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
94
|
+
printSection("terminal", [
|
|
95
|
+
`${picocolors_1.default.green(" OK")} built-in PTY runtime`,
|
|
96
|
+
" Live view, session nudges and browser flows use the built-in terminal runtime.",
|
|
97
|
+
]);
|
|
98
|
+
}
|
|
99
|
+
function resolveMarkerEnvPath(rawPath, cwd) {
|
|
100
|
+
return node_path_1.default.isAbsolute(rawPath) ? rawPath : node_path_1.default.resolve(cwd, rawPath);
|
|
101
|
+
}
|
|
102
|
+
function formatMarkerEnvPath(envPath, cwd) {
|
|
103
|
+
const resolvedCwd = node_path_1.default.resolve(cwd);
|
|
104
|
+
const resolvedEnvPath = node_path_1.default.resolve(envPath);
|
|
105
|
+
const relativePath = node_path_1.default.relative(resolvedCwd, resolvedEnvPath);
|
|
106
|
+
return relativePath && !relativePath.startsWith("..") && !node_path_1.default.isAbsolute(relativePath)
|
|
107
|
+
? relativePath
|
|
108
|
+
: resolvedEnvPath;
|
|
109
|
+
}
|
|
110
|
+
function getSessionMarkerForCwd(cwd) {
|
|
111
|
+
return (0, projectIdentity_1.readSessionMarkerState)(cwd);
|
|
112
|
+
}
|
|
113
|
+
function resolveCliSessionDefaults(input) {
|
|
114
|
+
return (0, projectIdentity_1.resolveSessionDefaultsForCwd)({
|
|
115
|
+
cwd: process.cwd(),
|
|
116
|
+
...(input.sessionId?.trim() ? { session_id: input.sessionId.trim() } : {}),
|
|
117
|
+
...(input.sessionLabel?.trim()
|
|
118
|
+
? { session_label: input.sessionLabel.trim() }
|
|
119
|
+
: {}),
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
function persistCliSessionMarker(input) {
|
|
123
|
+
const current = getSessionMarkerForCwd(input.cwd);
|
|
124
|
+
const resolved = resolveCliSessionDefaults({
|
|
125
|
+
envPath: input.envPath,
|
|
126
|
+
sessionId: input.sessionId,
|
|
127
|
+
sessionLabel: input.sessionLabel,
|
|
128
|
+
}) ?? null;
|
|
129
|
+
const localSessionId = input.sessionId?.trim() || current?.localSessionId || resolved?.sessionId;
|
|
130
|
+
if (!localSessionId) {
|
|
131
|
+
return;
|
|
109
132
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
133
|
+
(0, projectIdentity_1.writeSessionMarkerState)({
|
|
134
|
+
cwd: input.cwd,
|
|
135
|
+
localSessionId,
|
|
136
|
+
...(input.sessionLabel?.trim()
|
|
137
|
+
? { sessionLabel: input.sessionLabel.trim() }
|
|
138
|
+
: current?.sessionLabel
|
|
139
|
+
? { sessionLabel: current.sessionLabel }
|
|
140
|
+
: resolved?.sessionLabel
|
|
141
|
+
? { sessionLabel: resolved.sessionLabel }
|
|
142
|
+
: {}),
|
|
143
|
+
envFile: formatMarkerEnvPath(input.envPath, input.cwd),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
function loadCliEnv(args) {
|
|
147
|
+
const envPath = resolveRunEnvPath(args);
|
|
148
|
+
const marker = getSessionMarkerForCwd(process.cwd());
|
|
149
|
+
const explicitSessionOverride = readFlagValue(args, "-s") ?? readFlagValue(args, "--session");
|
|
150
|
+
const sessionOverride = explicitSessionOverride ?? marker?.localSessionId ?? null;
|
|
151
|
+
const sessionLabelOverride = explicitSessionOverride
|
|
152
|
+
? explicitSessionOverride
|
|
153
|
+
: marker?.sessionLabel ?? sessionOverride ?? null;
|
|
154
|
+
if (!(0, node_fs_1.existsSync)(envPath)) {
|
|
155
|
+
fail(`Missing env file: ${envPath}`);
|
|
117
156
|
}
|
|
157
|
+
const envContent = (0, node_fs_1.readFileSync)(envPath, "utf8");
|
|
158
|
+
const fileEnv = (0, dotenv_1.parse)(envContent);
|
|
159
|
+
const runtimeEnvOverrides = Object.fromEntries(Object.entries(process.env).filter(([, value]) => typeof value === "string"));
|
|
160
|
+
return {
|
|
161
|
+
envPath,
|
|
162
|
+
parsed: {
|
|
163
|
+
...fileEnv,
|
|
164
|
+
...runtimeEnvOverrides,
|
|
165
|
+
...(sessionOverride
|
|
166
|
+
? {
|
|
167
|
+
TELLYMCP_SESSION_ID: sessionOverride,
|
|
168
|
+
TELLYMCP_SESSION_LABEL: sessionLabelOverride || sessionOverride,
|
|
169
|
+
}
|
|
170
|
+
: {}),
|
|
171
|
+
},
|
|
172
|
+
};
|
|
118
173
|
}
|
|
119
174
|
function printMcpHelp() {
|
|
120
175
|
printBanner("MCP helper", "Prints JSON snippets for Claude, Codex, and other MCP clients");
|
|
@@ -130,10 +185,11 @@ function printMcpHelp() {
|
|
|
130
185
|
" Copy the printed JSON into your agent's MCP config.",
|
|
131
186
|
]);
|
|
132
187
|
printSection("What you need", [
|
|
133
|
-
" 1.
|
|
188
|
+
" 1. Terminal live view and nudges use the built-in PTY runtime.",
|
|
134
189
|
" 2. Your MCP endpoint depends on mode:",
|
|
135
190
|
" - client/local: http://127.0.0.1:8787/mcp",
|
|
136
191
|
" - gateway/both behind nginx: https://your-host.example/api/mcp",
|
|
192
|
+
" 3. For local and remote agents, use the MCP HTTP endpoint exposed by tellymcp run.",
|
|
137
193
|
]);
|
|
138
194
|
printSection("Claude / modern streamable-http example", [
|
|
139
195
|
"{",
|
|
@@ -189,6 +245,18 @@ function printBrowserHelp() {
|
|
|
189
245
|
" Avoids generic npx warnings about missing local project dependencies.",
|
|
190
246
|
]);
|
|
191
247
|
}
|
|
248
|
+
function printCodexPluginHelp() {
|
|
249
|
+
printBanner("codex plugin", "Install or inspect the bundled Codex workflow plugin");
|
|
250
|
+
printSection("Usage", [
|
|
251
|
+
" tellymcp codex-plugin install",
|
|
252
|
+
" tellymcp codex-plugin status",
|
|
253
|
+
]);
|
|
254
|
+
printSection("What this command does", [
|
|
255
|
+
" Copies the bundled telly-workflows plugin from the package into a managed local Codex plugin directory.",
|
|
256
|
+
" Ensures the local personal marketplace entry points at that managed plugin source.",
|
|
257
|
+
" If the Codex CLI is installed, checks whether the installed plugin version matches the bundled package version and installs or updates it when needed.",
|
|
258
|
+
]);
|
|
259
|
+
}
|
|
192
260
|
function fail(message) {
|
|
193
261
|
process.stderr.write(`${message}\n`);
|
|
194
262
|
process.exit(1);
|
|
@@ -240,6 +308,7 @@ function initWorkspace(mode, directoryArg) {
|
|
|
240
308
|
}
|
|
241
309
|
function resolveRunEnvPath(args) {
|
|
242
310
|
const [firstArg, secondArg] = args;
|
|
311
|
+
const marker = getSessionMarkerForCwd(process.cwd());
|
|
243
312
|
if (firstArg?.startsWith("--env=")) {
|
|
244
313
|
const value = firstArg.slice("--env=".length).trim();
|
|
245
314
|
if (!value) {
|
|
@@ -253,6 +322,9 @@ function resolveRunEnvPath(args) {
|
|
|
253
322
|
}
|
|
254
323
|
return node_path_1.default.resolve(process.cwd(), secondArg);
|
|
255
324
|
}
|
|
325
|
+
if (marker?.envFile?.trim()) {
|
|
326
|
+
return resolveMarkerEnvPath(marker.envFile.trim(), process.cwd());
|
|
327
|
+
}
|
|
256
328
|
return node_path_1.default.resolve(process.cwd(), ".env");
|
|
257
329
|
}
|
|
258
330
|
function joinUrlPath(left, right) {
|
|
@@ -433,32 +505,13 @@ async function checkWebSocketUrl(url, timeoutMs = 3000) {
|
|
|
433
505
|
});
|
|
434
506
|
}
|
|
435
507
|
async function runDoctor(args) {
|
|
436
|
-
const envPath =
|
|
437
|
-
const tmux = getTmuxStatus();
|
|
508
|
+
const { envPath, parsed } = loadCliEnv(args);
|
|
438
509
|
printBanner("doctor", "Local installation diagnostics");
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
}
|
|
445
|
-
else {
|
|
446
|
-
printSection("tmux", [
|
|
447
|
-
`${picocolors_1.default.yellow(" WARN")} tmux was not found.`,
|
|
448
|
-
" TellyMCP will still run, but Live view and nudges will be limited.",
|
|
449
|
-
" Install examples:",
|
|
450
|
-
...getTmuxInstallHints().map((line) => ` ${line}`),
|
|
451
|
-
]);
|
|
452
|
-
}
|
|
453
|
-
if (!(0, node_fs_1.existsSync)(envPath)) {
|
|
454
|
-
printSection("env", [
|
|
455
|
-
`${picocolors_1.default.red(" ERROR")} Missing env file: ${envPath}`,
|
|
456
|
-
" Run 'tellymcp init client' or pass --env <file>.",
|
|
457
|
-
]);
|
|
458
|
-
return;
|
|
459
|
-
}
|
|
460
|
-
const envContent = (0, node_fs_1.readFileSync)(envPath, "utf8");
|
|
461
|
-
const parsed = (0, dotenv_1.parse)(envContent);
|
|
510
|
+
printSection("terminal", [
|
|
511
|
+
`${picocolors_1.default.green(" OK")} built-in PTY runtime`,
|
|
512
|
+
` shell: ${parsed.TERMINAL_SHELL?.trim() || process.env.SHELL || "bash"}`,
|
|
513
|
+
` size: ${parsed.TERMINAL_COLS?.trim() || "120"}x${parsed.TERMINAL_ROWS?.trim() || "40"}`,
|
|
514
|
+
]);
|
|
462
515
|
const mode = (parsed.DISTRIBUTED_MODE || "client").trim();
|
|
463
516
|
const httpHost = (parsed.MCP_HTTP_HOST || "0.0.0.0").trim();
|
|
464
517
|
const httpPort = mode === "gateway" || mode === "both"
|
|
@@ -488,6 +541,10 @@ async function runDoctor(args) {
|
|
|
488
541
|
printSection("env", [
|
|
489
542
|
`${picocolors_1.default.green(" OK")} ${envPath}`,
|
|
490
543
|
` mode: ${mode}`,
|
|
544
|
+
" terminal transport: built-in PTY",
|
|
545
|
+
...(parsed.TELLYMCP_SESSION_ID
|
|
546
|
+
? [` session override: ${parsed.TELLYMCP_SESSION_ID}`]
|
|
547
|
+
: []),
|
|
491
548
|
` bind: http://${httpHost}:${httpPort}`,
|
|
492
549
|
` mcp: http://${httpHost}:${httpPort}${mcpUrlPath}`,
|
|
493
550
|
` web: http://${httpHost}:${httpPort}${webappUrlPath}`,
|
|
@@ -624,6 +681,119 @@ async function runDoctor(args) {
|
|
|
624
681
|
]);
|
|
625
682
|
}
|
|
626
683
|
}
|
|
684
|
+
function hasFlag(args, flagName) {
|
|
685
|
+
return args.includes(flagName);
|
|
686
|
+
}
|
|
687
|
+
async function runSystemPrune(args) {
|
|
688
|
+
const confirmed = hasFlag(args, "--yes");
|
|
689
|
+
if (!confirmed) {
|
|
690
|
+
fail("system-prune is destructive. Re-run with --yes.");
|
|
691
|
+
}
|
|
692
|
+
const filteredArgs = args.filter((arg) => arg !== "--yes");
|
|
693
|
+
const { envPath, parsed } = loadCliEnv(filteredArgs);
|
|
694
|
+
const mode = (parsed.DISTRIBUTED_MODE || "client").trim();
|
|
695
|
+
const redisHost = (parsed.REDIS_HOST || "127.0.0.1").trim();
|
|
696
|
+
const redisPort = Number(parsed.REDIS_PORT || 6379);
|
|
697
|
+
const redisDb = Number(parsed.REDIS_DB || 1);
|
|
698
|
+
const redisUsername = parsed.REDIS_USERNAME?.trim();
|
|
699
|
+
const redisPassword = parsed.REDIS_PASSWORD?.trim();
|
|
700
|
+
const dbHost = parsed.DB_HOST?.trim();
|
|
701
|
+
const dbPort = Number(parsed.DB_PORT || 5432);
|
|
702
|
+
const dbUser = parsed.DB_USER?.trim();
|
|
703
|
+
const dbPassword = parsed.DB_PASSWORD?.trim();
|
|
704
|
+
const dbName = parsed.DB_NAME?.trim();
|
|
705
|
+
const dbSchema = (parsed.DB_SCHEME || "mcp").trim();
|
|
706
|
+
const xchangeDir = node_path_1.default.resolve(process.cwd(), parsed.MCP_XCHANGE_DIR || ".mcp-xchange");
|
|
707
|
+
const sessionMarkerPath = node_path_1.default.resolve(process.cwd(), ".mcpsession.json");
|
|
708
|
+
const sqliteDbPath = node_path_1.default.join(xchangeDir, "xchange.sqlite3");
|
|
709
|
+
printBanner("system-prune", "Destroying local and gateway state");
|
|
710
|
+
printSection("Target", [
|
|
711
|
+
` env: ${envPath}`,
|
|
712
|
+
` mode: ${mode}`,
|
|
713
|
+
` redis: ${redisHost}:${redisPort}/${redisDb}`,
|
|
714
|
+
...(dbHost && dbUser && dbName
|
|
715
|
+
? [` postgres: ${dbHost}:${dbPort}/${dbName} schema ${dbSchema}`]
|
|
716
|
+
: [` postgres: ${picocolors_1.default.dim("skipped (not configured)")}`]),
|
|
717
|
+
` xchange dir: ${xchangeDir}`,
|
|
718
|
+
` session marker: ${sessionMarkerPath}`,
|
|
719
|
+
]);
|
|
720
|
+
const redis = new ioredis_1.default({
|
|
721
|
+
host: redisHost,
|
|
722
|
+
port: redisPort,
|
|
723
|
+
db: redisDb,
|
|
724
|
+
...(redisUsername ? { username: redisUsername } : {}),
|
|
725
|
+
...(redisPassword ? { password: redisPassword } : {}),
|
|
726
|
+
maxRetriesPerRequest: 1,
|
|
727
|
+
enableReadyCheck: true,
|
|
728
|
+
});
|
|
729
|
+
let deletedRedisKeys = 0;
|
|
730
|
+
try {
|
|
731
|
+
let cursor = "0";
|
|
732
|
+
do {
|
|
733
|
+
const [nextCursor, keys] = await redis.scan(cursor, "MATCH", "telegram-mcp:*", "COUNT", 500);
|
|
734
|
+
cursor = nextCursor;
|
|
735
|
+
if (keys.length > 0) {
|
|
736
|
+
deletedRedisKeys += await redis.del(...keys);
|
|
737
|
+
}
|
|
738
|
+
} while (cursor !== "0");
|
|
739
|
+
}
|
|
740
|
+
finally {
|
|
741
|
+
redis.disconnect();
|
|
742
|
+
}
|
|
743
|
+
let truncatedTables = [];
|
|
744
|
+
if (dbHost && dbUser && dbName) {
|
|
745
|
+
const pgModule = (await import("pg"));
|
|
746
|
+
const { Client: PgClient } = pgModule;
|
|
747
|
+
const pg = new PgClient({
|
|
748
|
+
host: dbHost,
|
|
749
|
+
port: dbPort,
|
|
750
|
+
user: dbUser,
|
|
751
|
+
password: dbPassword,
|
|
752
|
+
database: dbName,
|
|
753
|
+
});
|
|
754
|
+
try {
|
|
755
|
+
await pg.connect();
|
|
756
|
+
truncatedTables = [
|
|
757
|
+
"gateway_deliveries",
|
|
758
|
+
"gateway_message_artifacts",
|
|
759
|
+
"gateway_messages",
|
|
760
|
+
"gateway_session_links",
|
|
761
|
+
"gateway_sessions",
|
|
762
|
+
"gateway_project_members",
|
|
763
|
+
"gateway_projects",
|
|
764
|
+
"gateway_clients",
|
|
765
|
+
];
|
|
766
|
+
await pg.query(`TRUNCATE TABLE ${truncatedTables
|
|
767
|
+
.map((table) => `"${dbSchema}"."${table}"`)
|
|
768
|
+
.join(", ")} RESTART IDENTITY CASCADE`);
|
|
769
|
+
}
|
|
770
|
+
finally {
|
|
771
|
+
await pg.end();
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
let deletedLocalArtifacts = 0;
|
|
775
|
+
if ((0, node_fs_1.existsSync)(sqliteDbPath)) {
|
|
776
|
+
(0, node_fs_1.rmSync)(sqliteDbPath, { force: true });
|
|
777
|
+
deletedLocalArtifacts += 1;
|
|
778
|
+
}
|
|
779
|
+
if ((0, node_fs_1.existsSync)(xchangeDir)) {
|
|
780
|
+
(0, node_fs_1.rmSync)(xchangeDir, { recursive: true, force: true });
|
|
781
|
+
deletedLocalArtifacts += 1;
|
|
782
|
+
}
|
|
783
|
+
if ((0, node_fs_1.existsSync)(sessionMarkerPath)) {
|
|
784
|
+
(0, node_fs_1.rmSync)(sessionMarkerPath, { force: true });
|
|
785
|
+
deletedLocalArtifacts += 1;
|
|
786
|
+
}
|
|
787
|
+
printSection("Result", [
|
|
788
|
+
`${picocolors_1.default.green(" OK")} redis keys deleted: ${deletedRedisKeys}`,
|
|
789
|
+
...(truncatedTables.length > 0
|
|
790
|
+
? [
|
|
791
|
+
`${picocolors_1.default.green(" OK")} postgres tables truncated: ${truncatedTables.join(", ")}`,
|
|
792
|
+
]
|
|
793
|
+
: [`${picocolors_1.default.dim(" SKIP")} postgres tables: not configured`]),
|
|
794
|
+
`${picocolors_1.default.green(" OK")} local artifacts removed: ${deletedLocalArtifacts}`,
|
|
795
|
+
]);
|
|
796
|
+
}
|
|
627
797
|
function runBrowserCommand(args) {
|
|
628
798
|
const [subcommand] = args;
|
|
629
799
|
if (!subcommand || subcommand === "--help" || subcommand === "-h") {
|
|
@@ -651,10 +821,78 @@ function runBrowserCommand(args) {
|
|
|
651
821
|
process.exit(code ?? 0);
|
|
652
822
|
});
|
|
653
823
|
}
|
|
654
|
-
function
|
|
655
|
-
const
|
|
656
|
-
if (!
|
|
657
|
-
|
|
824
|
+
function runCodexPluginCommand(args) {
|
|
825
|
+
const [subcommand] = args;
|
|
826
|
+
if (!subcommand || subcommand === "--help" || subcommand === "-h") {
|
|
827
|
+
printCodexPluginHelp();
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
if (subcommand !== "install" && subcommand !== "status") {
|
|
831
|
+
fail("Supported codex-plugin subcommands: install, status");
|
|
832
|
+
}
|
|
833
|
+
if (subcommand === "status") {
|
|
834
|
+
const status = (0, codexPluginInstaller_1.getCodexPluginStatus)(packageRoot);
|
|
835
|
+
printBanner("codex plugin status", "Bundled telly-workflows plugin");
|
|
836
|
+
printSection("plugin", [
|
|
837
|
+
` name: ${status.pluginName}`,
|
|
838
|
+
` bundled version: ${status.bundledVersion}`,
|
|
839
|
+
` source version: ${status.sourceVersion ?? "not synced yet"}`,
|
|
840
|
+
` installed version: ${status.installedVersion ?? "not installed"}`,
|
|
841
|
+
` codex cli: ${status.codexAvailable ? "detected" : "not detected"}`,
|
|
842
|
+
` marketplace registered: ${status.marketplaceRegistered ? "yes" : "no"}`,
|
|
843
|
+
` up to date: ${status.upToDate ? "yes" : "no"}`,
|
|
844
|
+
]);
|
|
845
|
+
printSection("paths", [
|
|
846
|
+
` bundled: ${status.bundledPluginDir}`,
|
|
847
|
+
` managed: ${status.managedPluginDir}`,
|
|
848
|
+
` marketplace root: ${status.marketplaceRoot}`,
|
|
849
|
+
` marketplace file: ${status.marketplaceFile}`,
|
|
850
|
+
]);
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
const status = (0, codexPluginInstaller_1.installCodexPlugin)(packageRoot);
|
|
854
|
+
printBanner("codex plugin install", "Bundled telly-workflows plugin");
|
|
855
|
+
printSection("result", [
|
|
856
|
+
` plugin: ${status.pluginName}@${status.marketplaceName}`,
|
|
857
|
+
` bundled version: ${status.bundledVersion}`,
|
|
858
|
+
` source version: ${status.sourceVersion ?? "unknown"}`,
|
|
859
|
+
` installed version: ${status.installedVersion ?? "not installed"}`,
|
|
860
|
+
` marketplace registered: ${status.marketplaceRegistered ? "yes" : "no"}`,
|
|
861
|
+
` up to date: ${status.upToDate ? "yes" : "no"}`,
|
|
862
|
+
]);
|
|
863
|
+
printSection("paths", [
|
|
864
|
+
` managed plugin dir: ${status.managedPluginDir}`,
|
|
865
|
+
` marketplace file: ${status.marketplaceFile}`,
|
|
866
|
+
]);
|
|
867
|
+
if (!status.codexAvailable) {
|
|
868
|
+
printSection("next", [
|
|
869
|
+
" Codex CLI was not detected on this machine.",
|
|
870
|
+
" The plugin source and marketplace manifest were synced locally.",
|
|
871
|
+
" Install Codex, then rerun: tellymcp codex-plugin install",
|
|
872
|
+
]);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
async function runRuntime(args) {
|
|
876
|
+
const { envPath, parsed } = loadCliEnv(args);
|
|
877
|
+
if (parsed.TELLYMCP_SESSION_ID) {
|
|
878
|
+
process.env.TELLYMCP_SESSION_ID = parsed.TELLYMCP_SESSION_ID;
|
|
879
|
+
}
|
|
880
|
+
if (parsed.TELLYMCP_SESSION_LABEL) {
|
|
881
|
+
process.env.TELLYMCP_SESSION_LABEL = parsed.TELLYMCP_SESSION_LABEL;
|
|
882
|
+
}
|
|
883
|
+
persistCliSessionMarker({
|
|
884
|
+
cwd: process.cwd(),
|
|
885
|
+
envPath,
|
|
886
|
+
sessionId: parsed.TELLYMCP_SESSION_ID,
|
|
887
|
+
sessionLabel: parsed.TELLYMCP_SESSION_LABEL,
|
|
888
|
+
});
|
|
889
|
+
if ((0, foregroundTerminalRuntime_1.isForegroundPtyClientMode)(parsed)) {
|
|
890
|
+
await (0, foregroundTerminalRuntime_1.runForegroundPtyRuntime)({
|
|
891
|
+
envPath,
|
|
892
|
+
packageRoot,
|
|
893
|
+
printBanner,
|
|
894
|
+
});
|
|
895
|
+
return;
|
|
658
896
|
}
|
|
659
897
|
const runnerPath = node_path_1.default.join(packageRoot, "node_modules", "moleculer", "bin", "moleculer-runner.js");
|
|
660
898
|
const configPath = node_path_1.default.join(packageRoot, "dist", "moleculer.config.js");
|
|
@@ -669,13 +907,7 @@ function runRuntime(args) {
|
|
|
669
907
|
fail(`Missing compiled services: ${servicesPath}`);
|
|
670
908
|
}
|
|
671
909
|
printBanner("run", "Starting packaged runtime");
|
|
672
|
-
|
|
673
|
-
if (tmux.found) {
|
|
674
|
-
process.stdout.write(`${picocolors_1.default.green("tmux detected:")} ${tmux.version}\n`);
|
|
675
|
-
}
|
|
676
|
-
else {
|
|
677
|
-
process.stdout.write(`${picocolors_1.default.yellow("tmux not found.")} Live view and nudges may be limited.\n`);
|
|
678
|
-
}
|
|
910
|
+
process.stdout.write(`${picocolors_1.default.green("terminal runtime:")} built-in PTY\n`);
|
|
679
911
|
process.stdout.write(`${picocolors_1.default.cyan("Using env:")} ${envPath}\n\n`);
|
|
680
912
|
const child = (0, node_child_process_1.spawn)(process.execPath, [
|
|
681
913
|
runnerPath,
|
|
@@ -691,6 +923,12 @@ function runRuntime(args) {
|
|
|
691
923
|
...process.env,
|
|
692
924
|
ENV_FILE: envPath,
|
|
693
925
|
TELLYMCP_STANDALONE_HTTP: "true",
|
|
926
|
+
...(parsed.TELLYMCP_SESSION_ID
|
|
927
|
+
? { TELLYMCP_SESSION_ID: parsed.TELLYMCP_SESSION_ID }
|
|
928
|
+
: {}),
|
|
929
|
+
...(parsed.TELLYMCP_SESSION_LABEL
|
|
930
|
+
? { TELLYMCP_SESSION_LABEL: parsed.TELLYMCP_SESSION_LABEL }
|
|
931
|
+
: {}),
|
|
694
932
|
},
|
|
695
933
|
});
|
|
696
934
|
child.on("exit", (code, signal) => {
|
|
@@ -703,7 +941,8 @@ function runRuntime(args) {
|
|
|
703
941
|
}
|
|
704
942
|
async function main(argv) {
|
|
705
943
|
const [rawCommand, firstArg, secondArg] = argv;
|
|
706
|
-
const command = rawCommand === "init" || rawCommand === "run" || rawCommand === "help" || rawCommand === "mcp" || rawCommand === "doctor" || rawCommand === "browser"
|
|
944
|
+
const command = rawCommand === "init" || rawCommand === "run" || rawCommand === "help" || rawCommand === "mcp" || rawCommand === "doctor" || rawCommand === "browser" || rawCommand === "system-prune"
|
|
945
|
+
|| rawCommand === "codex-plugin"
|
|
707
946
|
? rawCommand
|
|
708
947
|
: "help";
|
|
709
948
|
if (command === "help" || !rawCommand || rawCommand === "--help" || rawCommand === "-h") {
|
|
@@ -726,6 +965,14 @@ async function main(argv) {
|
|
|
726
965
|
runBrowserCommand(argv.slice(1));
|
|
727
966
|
return;
|
|
728
967
|
}
|
|
729
|
-
|
|
968
|
+
if (command === "codex-plugin") {
|
|
969
|
+
runCodexPluginCommand(argv.slice(1));
|
|
970
|
+
return;
|
|
971
|
+
}
|
|
972
|
+
if (command === "system-prune") {
|
|
973
|
+
await runSystemPrune(argv.slice(1));
|
|
974
|
+
return;
|
|
975
|
+
}
|
|
976
|
+
await runRuntime(argv.slice(1));
|
|
730
977
|
}
|
|
731
978
|
void main(process.argv.slice(2));
|