@deadragdoll/tellymcp 0.0.10 → 0.0.12
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 -52
- package/.env.example.gateway +48 -62
- package/CHANGELOG.md +3 -3
- package/README-ru.md +226 -376
- package/README.md +213 -1184
- package/TOOLS.md +320 -377
- package/VERSION.md +13 -13
- 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 +39 -20
- package/config/templates/env.client.template +34 -19
- package/config/templates/env.gateway.template +37 -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/browser.service.js +94 -1
- package/dist/services/features/telegram-mcp/collaboration.service.js +40 -3
- 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-socket.service.js +907 -85
- package/dist/services/features/telegram-mcp/gateway.service.js +876 -81
- package/dist/services/features/telegram-mcp/mcp-http.service.js +8 -0
- package/dist/services/features/telegram-mcp/mcp-server.service.js +17 -26
- package/dist/services/features/telegram-mcp/notify.service.js +127 -1
- package/dist/services/features/telegram-mcp/session-context.service.js +28 -1
- package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +132 -10
- package/dist/services/features/telegram-mcp/src/app/config/env.js +158 -52
- 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 +120 -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/browserOpenTool.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 +306 -26
- 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 +697 -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/resources/en.js +143 -42
- package/dist/services/features/telegram-mcp/src/shared/i18n/resources/ru.js +139 -38
- 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 +69 -70
- 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 +444 -7093
- 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 +149 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConstructorWiring.js +642 -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 +65 -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 +108 -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 +665 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalRuntime.js +226 -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 +409 -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 +12 -0
- 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 +15 -1
- 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 +10 -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/services/features/telegram-mcp/src/features/pair-session/model/generatePairCode.js
DELETED
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PairSessionService = void 0;
|
|
4
|
-
const ids_1 = require("../../../shared/lib/ids/ids");
|
|
5
|
-
class PairSessionService {
|
|
6
|
-
config;
|
|
7
|
-
sessionStore;
|
|
8
|
-
bindingStore;
|
|
9
|
-
maintenanceStore;
|
|
10
|
-
logger;
|
|
11
|
-
projectIdentityResolver;
|
|
12
|
-
static MAX_PAIR_CODE_ATTEMPTS = 20;
|
|
13
|
-
constructor(config, sessionStore, bindingStore, maintenanceStore, logger, projectIdentityResolver) {
|
|
14
|
-
this.config = config;
|
|
15
|
-
this.sessionStore = sessionStore;
|
|
16
|
-
this.bindingStore = bindingStore;
|
|
17
|
-
this.maintenanceStore = maintenanceStore;
|
|
18
|
-
this.logger = logger;
|
|
19
|
-
this.projectIdentityResolver = projectIdentityResolver;
|
|
20
|
-
}
|
|
21
|
-
async unregisterGatewaySession(localSessionId) {
|
|
22
|
-
if (!this.config.distributed.gatewayPublicUrl) {
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
const clientUuid = await this.maintenanceStore.getGatewayClientUuid();
|
|
26
|
-
if (!clientUuid) {
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
const url = new URL(this.config.distributed.gatewayPublicUrl);
|
|
30
|
-
url.pathname = url.pathname.replace(/\/+$/u, "");
|
|
31
|
-
if (!url.pathname.endsWith("/gateway")) {
|
|
32
|
-
url.pathname = `${url.pathname}/gateway`.replace(/\/{2,}/gu, "/");
|
|
33
|
-
}
|
|
34
|
-
url.pathname = `${url.pathname}/sessions/unregister`.replace(/\/{2,}/gu, "/");
|
|
35
|
-
const response = await fetch(url, {
|
|
36
|
-
method: "POST",
|
|
37
|
-
headers: {
|
|
38
|
-
"content-type": "application/json",
|
|
39
|
-
...(this.config.distributed.gatewayAuthToken
|
|
40
|
-
? { authorization: `Bearer ${this.config.distributed.gatewayAuthToken}` }
|
|
41
|
-
: {}),
|
|
42
|
-
},
|
|
43
|
-
body: JSON.stringify({
|
|
44
|
-
client_uuid: clientUuid,
|
|
45
|
-
local_session_id: localSessionId,
|
|
46
|
-
}),
|
|
47
|
-
});
|
|
48
|
-
if (!response.ok) {
|
|
49
|
-
const text = await response.text();
|
|
50
|
-
throw new Error(`Gateway session unregister failed with status ${response.status}: ${text || response.statusText}`);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
async createPairCode(input) {
|
|
54
|
-
const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
|
|
55
|
-
const now = new Date();
|
|
56
|
-
const ttlSeconds = input.expires_in_seconds ?? this.config.pairCodeTtlSeconds;
|
|
57
|
-
const expiresAt = new Date(now.getTime() + ttlSeconds * 1000).toISOString();
|
|
58
|
-
let code = null;
|
|
59
|
-
const existingSession = await this.sessionStore.getSession(resolved.sessionId);
|
|
60
|
-
await this.sessionStore.setSession({
|
|
61
|
-
sessionId: resolved.sessionId,
|
|
62
|
-
...(input.session_label
|
|
63
|
-
? { label: input.session_label }
|
|
64
|
-
: resolved.sessionLabel
|
|
65
|
-
? { label: resolved.sessionLabel }
|
|
66
|
-
: existingSession?.label
|
|
67
|
-
? { label: existingSession.label }
|
|
68
|
-
: {}),
|
|
69
|
-
...(input.cwd
|
|
70
|
-
? { cwd: resolved.cwd }
|
|
71
|
-
: existingSession?.cwd
|
|
72
|
-
? { cwd: existingSession.cwd }
|
|
73
|
-
: { cwd: resolved.cwd }),
|
|
74
|
-
...(existingSession?.linkedSessionId
|
|
75
|
-
? { linkedSessionId: existingSession.linkedSessionId }
|
|
76
|
-
: {}),
|
|
77
|
-
...(existingSession?.activeProjectUuid
|
|
78
|
-
? { activeProjectUuid: existingSession.activeProjectUuid }
|
|
79
|
-
: {}),
|
|
80
|
-
...(existingSession?.activeProjectName
|
|
81
|
-
? { activeProjectName: existingSession.activeProjectName }
|
|
82
|
-
: {}),
|
|
83
|
-
...(existingSession?.task ? { task: existingSession.task } : {}),
|
|
84
|
-
...(existingSession?.summary ? { summary: existingSession.summary } : {}),
|
|
85
|
-
...(existingSession?.files ? { files: existingSession.files } : {}),
|
|
86
|
-
...(existingSession?.decisions
|
|
87
|
-
? { decisions: existingSession.decisions }
|
|
88
|
-
: {}),
|
|
89
|
-
...(existingSession?.risks ? { risks: existingSession.risks } : {}),
|
|
90
|
-
...(input.tmux_session_name
|
|
91
|
-
? { tmuxSessionName: input.tmux_session_name }
|
|
92
|
-
: existingSession?.tmuxSessionName
|
|
93
|
-
? { tmuxSessionName: existingSession.tmuxSessionName }
|
|
94
|
-
: {}),
|
|
95
|
-
...(input.tmux_window_name
|
|
96
|
-
? { tmuxWindowName: input.tmux_window_name }
|
|
97
|
-
: existingSession?.tmuxWindowName
|
|
98
|
-
? { tmuxWindowName: existingSession.tmuxWindowName }
|
|
99
|
-
: {}),
|
|
100
|
-
...(typeof input.tmux_window_index === "number"
|
|
101
|
-
? { tmuxWindowIndex: input.tmux_window_index }
|
|
102
|
-
: typeof existingSession?.tmuxWindowIndex === "number"
|
|
103
|
-
? { tmuxWindowIndex: existingSession.tmuxWindowIndex }
|
|
104
|
-
: {}),
|
|
105
|
-
...(input.tmux_pane_id
|
|
106
|
-
? { tmuxPaneId: input.tmux_pane_id, tmuxTarget: input.tmux_pane_id }
|
|
107
|
-
: existingSession?.tmuxPaneId
|
|
108
|
-
? {
|
|
109
|
-
tmuxPaneId: existingSession.tmuxPaneId,
|
|
110
|
-
...(existingSession.tmuxTarget
|
|
111
|
-
? { tmuxTarget: existingSession.tmuxTarget }
|
|
112
|
-
: {}),
|
|
113
|
-
}
|
|
114
|
-
: existingSession?.tmuxTarget
|
|
115
|
-
? { tmuxTarget: existingSession.tmuxTarget }
|
|
116
|
-
: {}),
|
|
117
|
-
...(typeof input.tmux_pane_index === "number"
|
|
118
|
-
? { tmuxPaneIndex: input.tmux_pane_index }
|
|
119
|
-
: typeof existingSession?.tmuxPaneIndex === "number"
|
|
120
|
-
? { tmuxPaneIndex: existingSession.tmuxPaneIndex }
|
|
121
|
-
: {}),
|
|
122
|
-
...(existingSession?.lastTmuxNudgeAt
|
|
123
|
-
? { lastTmuxNudgeAt: existingSession.lastTmuxNudgeAt }
|
|
124
|
-
: {}),
|
|
125
|
-
updatedAt: now.toISOString(),
|
|
126
|
-
});
|
|
127
|
-
this.projectIdentityResolver.persistSessionMarker({
|
|
128
|
-
cwd: resolved.cwd,
|
|
129
|
-
sessionId: resolved.sessionId,
|
|
130
|
-
sessionLabel: input.session_label?.trim() || resolved.sessionLabel,
|
|
131
|
-
});
|
|
132
|
-
for (let attempt = 0; attempt < PairSessionService.MAX_PAIR_CODE_ATTEMPTS; attempt += 1) {
|
|
133
|
-
const candidate = (0, ids_1.createPairCode)();
|
|
134
|
-
const record = {
|
|
135
|
-
code: candidate,
|
|
136
|
-
sessionId: resolved.sessionId,
|
|
137
|
-
...(resolved.sessionLabel
|
|
138
|
-
? { sessionLabel: resolved.sessionLabel }
|
|
139
|
-
: {}),
|
|
140
|
-
createdAt: now.toISOString(),
|
|
141
|
-
expiresAt,
|
|
142
|
-
};
|
|
143
|
-
const reserved = await this.bindingStore.createPairCode(record, ttlSeconds);
|
|
144
|
-
if (reserved) {
|
|
145
|
-
code = candidate;
|
|
146
|
-
break;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
if (!code) {
|
|
150
|
-
throw new Error("Failed to reserve a unique 3-digit pairing code. Try again in a moment.");
|
|
151
|
-
}
|
|
152
|
-
this.logger.info("Session pair code created", {
|
|
153
|
-
sessionId: resolved.sessionId,
|
|
154
|
-
sessionLabel: resolved.sessionLabel,
|
|
155
|
-
sessionIdDerived: resolved.sessionIdDerived,
|
|
156
|
-
sessionLabelDerived: resolved.sessionLabelDerived,
|
|
157
|
-
cwd: input.cwd?.trim(),
|
|
158
|
-
tmuxSessionName: input.tmux_session_name,
|
|
159
|
-
tmuxWindowName: input.tmux_window_name,
|
|
160
|
-
tmuxWindowIndex: input.tmux_window_index,
|
|
161
|
-
tmuxPaneId: input.tmux_pane_id,
|
|
162
|
-
tmuxPaneIndex: input.tmux_pane_index,
|
|
163
|
-
expiresAt,
|
|
164
|
-
ttlSeconds,
|
|
165
|
-
});
|
|
166
|
-
return {
|
|
167
|
-
session_id: resolved.sessionId,
|
|
168
|
-
code,
|
|
169
|
-
expires_at: expiresAt,
|
|
170
|
-
status: "pending",
|
|
171
|
-
status_message: "Pairing code created. Send it to the Telegram bot and then use get_session_context to confirm that pairing is active.",
|
|
172
|
-
...(this.config.telegram.botUsername
|
|
173
|
-
? {
|
|
174
|
-
telegram_link_hint: `https://t.me/${this.config.telegram.botUsername}?start=${encodeURIComponent(code)}`,
|
|
175
|
-
}
|
|
176
|
-
: {}),
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
async clearPairing(input) {
|
|
180
|
-
const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
|
|
181
|
-
const existingSession = await this.sessionStore.getSession(resolved.sessionId);
|
|
182
|
-
if (existingSession) {
|
|
183
|
-
await this.unregisterGatewaySession(resolved.sessionId);
|
|
184
|
-
await this.sessionStore.setSession({
|
|
185
|
-
...existingSession,
|
|
186
|
-
activeProjectUuid: undefined,
|
|
187
|
-
activeProjectName: undefined,
|
|
188
|
-
updatedAt: new Date().toISOString(),
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
await this.bindingStore.clearBinding(resolved.sessionId);
|
|
192
|
-
this.logger.info("Session pairing cleared", {
|
|
193
|
-
sessionId: resolved.sessionId,
|
|
194
|
-
sessionIdDerived: resolved.sessionIdDerived,
|
|
195
|
-
});
|
|
196
|
-
return {
|
|
197
|
-
cleared: true,
|
|
198
|
-
session_id: resolved.sessionId,
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
exports.PairSessionService = PairSessionService;
|
package/dist/services/features/telegram-mcp/src/features/session-context/model/getTmuxTargetTool.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.GetTmuxTargetTool = void 0;
|
|
4
|
-
const schema_1 = require("../../../entities/request/model/schema");
|
|
5
|
-
function createContent(output) {
|
|
6
|
-
return [
|
|
7
|
-
{
|
|
8
|
-
type: "text",
|
|
9
|
-
text: JSON.stringify(output, null, 2),
|
|
10
|
-
},
|
|
11
|
-
];
|
|
12
|
-
}
|
|
13
|
-
class GetTmuxTargetTool {
|
|
14
|
-
sessionContextService;
|
|
15
|
-
constructor(sessionContextService) {
|
|
16
|
-
this.sessionContextService = sessionContextService;
|
|
17
|
-
}
|
|
18
|
-
register(server) {
|
|
19
|
-
server.registerTool("get_tmux_target", {
|
|
20
|
-
title: "Get tmux Target",
|
|
21
|
-
description: "Debug/setup tool. Return the stored tmux pane target for a session, including the last time the service nudged that tmux pane. Do not call this in the normal inbox-processing path after a tmux nudge.",
|
|
22
|
-
inputSchema: schema_1.getTmuxTargetInputSchema,
|
|
23
|
-
outputSchema: schema_1.getTmuxTargetOutputSchema,
|
|
24
|
-
}, async (args) => {
|
|
25
|
-
const output = await this.sessionContextService.getTmuxTarget(args);
|
|
26
|
-
return {
|
|
27
|
-
content: createContent(output),
|
|
28
|
-
structuredContent: output,
|
|
29
|
-
};
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
exports.GetTmuxTargetTool = GetTmuxTargetTool;
|
package/dist/services/features/telegram-mcp/src/features/session-context/model/setTmuxTargetTool.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SetTmuxTargetTool = void 0;
|
|
4
|
-
const schema_1 = require("../../../entities/request/model/schema");
|
|
5
|
-
function createContent(output) {
|
|
6
|
-
return [
|
|
7
|
-
{
|
|
8
|
-
type: "text",
|
|
9
|
-
text: JSON.stringify(output, null, 2),
|
|
10
|
-
},
|
|
11
|
-
];
|
|
12
|
-
}
|
|
13
|
-
class SetTmuxTargetTool {
|
|
14
|
-
sessionContextService;
|
|
15
|
-
constructor(sessionContextService) {
|
|
16
|
-
this.sessionContextService = sessionContextService;
|
|
17
|
-
}
|
|
18
|
-
register(server) {
|
|
19
|
-
server.registerTool("set_tmux_target", {
|
|
20
|
-
title: "Set tmux Target",
|
|
21
|
-
description: "Use this to repair or complete Telegram session setup after pairing, or when tmux pane/session changed. Store the tmux pane target for a session so the long-running MCP service can nudge the agent to check Telegram inbox when new ordinary Telegram messages arrive.",
|
|
22
|
-
inputSchema: schema_1.setTmuxTargetInputSchema,
|
|
23
|
-
outputSchema: schema_1.setTmuxTargetOutputSchema,
|
|
24
|
-
}, async (args) => {
|
|
25
|
-
const output = await this.sessionContextService.setTmuxTarget(args);
|
|
26
|
-
return {
|
|
27
|
-
content: createContent(output),
|
|
28
|
-
structuredContent: output,
|
|
29
|
-
};
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
exports.SetTmuxTargetTool = SetTmuxTargetTool;
|
|
@@ -1,363 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.ensureXchangeDir = ensureXchangeDir;
|
|
7
|
-
exports.writeXchangeFile = writeXchangeFile;
|
|
8
|
-
exports.writeXchangeRelativeFile = writeXchangeRelativeFile;
|
|
9
|
-
exports.listXchangeFiles = listXchangeFiles;
|
|
10
|
-
exports.deleteXchangeFile = deleteXchangeFile;
|
|
11
|
-
exports.readWorkspaceFile = readWorkspaceFile;
|
|
12
|
-
exports.isTmuxUnavailableError = isTmuxUnavailableError;
|
|
13
|
-
exports.isTmuxTargetInvalidError = isTmuxTargetInvalidError;
|
|
14
|
-
exports.resolveTmuxTargetFromHint = resolveTmuxTargetFromHint;
|
|
15
|
-
exports.getTmuxWindowHeight = getTmuxWindowHeight;
|
|
16
|
-
exports.captureTmuxPaneRange = captureTmuxPaneRange;
|
|
17
|
-
exports.captureVisibleTmuxPane = captureVisibleTmuxPane;
|
|
18
|
-
exports.sendAllowedTmuxAction = sendAllowedTmuxAction;
|
|
19
|
-
exports.sendTmuxLiteralText = sendTmuxLiteralText;
|
|
20
|
-
exports.sendTmuxLiteralLine = sendTmuxLiteralLine;
|
|
21
|
-
const node_child_process_1 = require("node:child_process");
|
|
22
|
-
const promises_1 = require("node:fs/promises");
|
|
23
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
24
|
-
const ENTER_AFTER_PASTE_DELAY_MS = 75;
|
|
25
|
-
const SUBMIT_LINE_KEY = "C-m";
|
|
26
|
-
function sanitizeFileName(fileName) {
|
|
27
|
-
const baseName = node_path_1.default.basename(fileName).trim();
|
|
28
|
-
const withoutControlChars = Array.from(baseName)
|
|
29
|
-
.map((char) => (char.charCodeAt(0) < 32 ? "-" : char))
|
|
30
|
-
.join("");
|
|
31
|
-
const normalized = withoutControlChars
|
|
32
|
-
.replace(/[/\\]/g, "-")
|
|
33
|
-
.replace(/[<>:"|?*]/g, "-")
|
|
34
|
-
.replace(/\s+/g, " ")
|
|
35
|
-
.trim();
|
|
36
|
-
return normalized || "file.bin";
|
|
37
|
-
}
|
|
38
|
-
function sanitizeRelativeXchangePath(relativePath) {
|
|
39
|
-
const normalized = relativePath
|
|
40
|
-
.split(/[/\\]+/u)
|
|
41
|
-
.map((segment) => segment.trim())
|
|
42
|
-
.filter((segment) => segment.length > 0 && segment !== "." && segment !== "..")
|
|
43
|
-
.join("/");
|
|
44
|
-
if (!normalized) {
|
|
45
|
-
throw new Error("Relative exchange path is required.");
|
|
46
|
-
}
|
|
47
|
-
return normalized;
|
|
48
|
-
}
|
|
49
|
-
function resolvePathInsideRoot(rootDir, relativePath) {
|
|
50
|
-
const safeRelativePath = sanitizeRelativeXchangePath(relativePath);
|
|
51
|
-
const resolvedPath = node_path_1.default.resolve(rootDir, safeRelativePath);
|
|
52
|
-
const relative = node_path_1.default.relative(rootDir, resolvedPath);
|
|
53
|
-
if (relative.startsWith("..") ||
|
|
54
|
-
node_path_1.default.isAbsolute(relative) ||
|
|
55
|
-
relative.trim() === "") {
|
|
56
|
-
throw new Error("Resolved path is outside the exchange directory.");
|
|
57
|
-
}
|
|
58
|
-
return resolvedPath;
|
|
59
|
-
}
|
|
60
|
-
function resolvePathInsideWorkspace(workspaceDir, filePath) {
|
|
61
|
-
const resolvedWorkspaceDir = node_path_1.default.resolve(workspaceDir);
|
|
62
|
-
const resolvedFilePath = node_path_1.default.isAbsolute(filePath)
|
|
63
|
-
? node_path_1.default.resolve(filePath)
|
|
64
|
-
: node_path_1.default.resolve(resolvedWorkspaceDir, filePath);
|
|
65
|
-
const relative = node_path_1.default.relative(resolvedWorkspaceDir, resolvedFilePath);
|
|
66
|
-
if (relative.startsWith("..") ||
|
|
67
|
-
node_path_1.default.isAbsolute(relative) ||
|
|
68
|
-
relative.trim() === "") {
|
|
69
|
-
throw new Error("File path is outside the workspace directory.");
|
|
70
|
-
}
|
|
71
|
-
return resolvedFilePath;
|
|
72
|
-
}
|
|
73
|
-
async function allocateAvailableFilePath(dir, fileName) {
|
|
74
|
-
const safeFileName = sanitizeFileName(fileName);
|
|
75
|
-
const extension = node_path_1.default.extname(safeFileName);
|
|
76
|
-
const baseName = node_path_1.default.basename(safeFileName, extension);
|
|
77
|
-
for (let attempt = 0; attempt < 1000; attempt += 1) {
|
|
78
|
-
const candidateName = attempt === 0
|
|
79
|
-
? safeFileName
|
|
80
|
-
: `${baseName}--${attempt}${extension}`;
|
|
81
|
-
const candidatePath = node_path_1.default.join(dir, candidateName);
|
|
82
|
-
try {
|
|
83
|
-
await (0, promises_1.access)(candidatePath);
|
|
84
|
-
}
|
|
85
|
-
catch {
|
|
86
|
-
return candidatePath;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
throw new Error("Could not allocate a unique file name in exchange directory.");
|
|
90
|
-
}
|
|
91
|
-
function delay(ms) {
|
|
92
|
-
return new Promise((resolve) => {
|
|
93
|
-
setTimeout(resolve, ms);
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
function execFileAsync(command, args) {
|
|
97
|
-
return new Promise((resolve, reject) => {
|
|
98
|
-
(0, node_child_process_1.execFile)(command, args, (error) => {
|
|
99
|
-
if (error) {
|
|
100
|
-
reject(error);
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
resolve();
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
function execFileOutputAsync(command, args) {
|
|
108
|
-
return new Promise((resolve, reject) => {
|
|
109
|
-
(0, node_child_process_1.execFile)(command, args, (error, stdout, stderr) => {
|
|
110
|
-
if (error) {
|
|
111
|
-
reject(error);
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
resolve({ stdout, stderr });
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
function buildTmuxArgs(config, args, socketPath) {
|
|
119
|
-
const resolvedSocketPath = socketPath ?? config.socketPath;
|
|
120
|
-
return resolvedSocketPath ? ["-S", resolvedSocketPath, ...args] : args;
|
|
121
|
-
}
|
|
122
|
-
async function ensureXchangeDir(config, workspaceDir, exchangeDirName) {
|
|
123
|
-
const resolvedDir = node_path_1.default.resolve(workspaceDir, exchangeDirName);
|
|
124
|
-
await (0, promises_1.mkdir)(resolvedDir, { recursive: true });
|
|
125
|
-
return resolvedDir;
|
|
126
|
-
}
|
|
127
|
-
async function writeXchangeFile(config, workspaceDir, exchangeDirName, fileName, content) {
|
|
128
|
-
const dir = await ensureXchangeDir(config, workspaceDir, exchangeDirName);
|
|
129
|
-
const outputPath = await allocateAvailableFilePath(dir, fileName);
|
|
130
|
-
await (0, promises_1.writeFile)(outputPath, content);
|
|
131
|
-
return outputPath;
|
|
132
|
-
}
|
|
133
|
-
async function writeXchangeRelativeFile(config, workspaceDir, exchangeDirName, relativePath, content, options) {
|
|
134
|
-
const dir = await ensureXchangeDir(config, workspaceDir, exchangeDirName);
|
|
135
|
-
const outputPath = resolvePathInsideRoot(dir, relativePath);
|
|
136
|
-
await (0, promises_1.mkdir)(node_path_1.default.dirname(outputPath), { recursive: true });
|
|
137
|
-
if (options?.append) {
|
|
138
|
-
await (0, promises_1.appendFile)(outputPath, content);
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
await (0, promises_1.writeFile)(outputPath, content);
|
|
142
|
-
}
|
|
143
|
-
return outputPath;
|
|
144
|
-
}
|
|
145
|
-
async function listXchangeFiles(config, workspaceDir, exchangeDirName) {
|
|
146
|
-
const dir = await ensureXchangeDir(config, workspaceDir, exchangeDirName);
|
|
147
|
-
return listFilesRecursively(dir);
|
|
148
|
-
}
|
|
149
|
-
async function listFilesRecursively(rootDir) {
|
|
150
|
-
const files = [];
|
|
151
|
-
const stack = [rootDir];
|
|
152
|
-
while (stack.length > 0) {
|
|
153
|
-
const currentDir = stack.pop();
|
|
154
|
-
if (!currentDir) {
|
|
155
|
-
continue;
|
|
156
|
-
}
|
|
157
|
-
const entries = await (0, promises_1.readdir)(currentDir, { withFileTypes: true });
|
|
158
|
-
for (const entry of entries) {
|
|
159
|
-
const fullPath = node_path_1.default.join(currentDir, entry.name);
|
|
160
|
-
if (entry.isDirectory()) {
|
|
161
|
-
stack.push(fullPath);
|
|
162
|
-
continue;
|
|
163
|
-
}
|
|
164
|
-
if (entry.isFile()) {
|
|
165
|
-
files.push(fullPath);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
return files.sort((left, right) => right.localeCompare(left));
|
|
170
|
-
}
|
|
171
|
-
async function deleteXchangeFile(config, workspaceDir, exchangeDirName, filePath) {
|
|
172
|
-
const dir = await ensureXchangeDir(config, workspaceDir, exchangeDirName);
|
|
173
|
-
const resolvedFilePath = node_path_1.default.resolve(filePath);
|
|
174
|
-
const relative = node_path_1.default.relative(dir, resolvedFilePath);
|
|
175
|
-
if (relative.startsWith("..") ||
|
|
176
|
-
node_path_1.default.isAbsolute(relative) ||
|
|
177
|
-
relative.trim() === "") {
|
|
178
|
-
throw new Error("File path is outside the exchange directory.");
|
|
179
|
-
}
|
|
180
|
-
await (0, promises_1.rm)(resolvedFilePath, { force: true });
|
|
181
|
-
return true;
|
|
182
|
-
}
|
|
183
|
-
async function readWorkspaceFile(config, workspaceDir, filePath) {
|
|
184
|
-
const resolvedFilePath = resolvePathInsideWorkspace(workspaceDir, filePath);
|
|
185
|
-
return (0, promises_1.readFile)(resolvedFilePath);
|
|
186
|
-
}
|
|
187
|
-
function isTmuxUnavailableError(error) {
|
|
188
|
-
const message = error instanceof Error ? (error.stack ?? error.message) : String(error);
|
|
189
|
-
return (message.includes("error connecting to /tmp/tmux-") ||
|
|
190
|
-
message.includes("No such file or directory") ||
|
|
191
|
-
message.includes("ENOENT") ||
|
|
192
|
-
message.includes("tmux is unavailable"));
|
|
193
|
-
}
|
|
194
|
-
function isTmuxTargetInvalidError(error) {
|
|
195
|
-
const message = error instanceof Error ? (error.stack ?? error.message) : String(error);
|
|
196
|
-
return (message.includes("can't find pane") ||
|
|
197
|
-
message.includes("can't find window") ||
|
|
198
|
-
message.includes("can't find session"));
|
|
199
|
-
}
|
|
200
|
-
async function listTmuxPanes(config) {
|
|
201
|
-
const { stdout } = await execFileOutputAsync("tmux", buildTmuxArgs(config, [
|
|
202
|
-
"list-panes",
|
|
203
|
-
"-a",
|
|
204
|
-
"-F",
|
|
205
|
-
"#{session_name}\t#{window_name}\t#{window_index}\t#{pane_id}\t#{pane_index}",
|
|
206
|
-
]));
|
|
207
|
-
return stdout
|
|
208
|
-
.split("\n")
|
|
209
|
-
.map((line) => line.trim())
|
|
210
|
-
.filter((line) => line.length > 0)
|
|
211
|
-
.map((line) => {
|
|
212
|
-
const [sessionName = "", windowName = "", windowIndexRaw = "", paneId = "", paneIndexRaw = ""] = line.split("\t");
|
|
213
|
-
return {
|
|
214
|
-
sessionName,
|
|
215
|
-
windowName,
|
|
216
|
-
windowIndex: Number.parseInt(windowIndexRaw, 10),
|
|
217
|
-
paneId,
|
|
218
|
-
paneIndex: Number.parseInt(paneIndexRaw, 10),
|
|
219
|
-
};
|
|
220
|
-
})
|
|
221
|
-
.filter((pane) => pane.sessionName &&
|
|
222
|
-
pane.paneId &&
|
|
223
|
-
Number.isFinite(pane.windowIndex) &&
|
|
224
|
-
Number.isFinite(pane.paneIndex));
|
|
225
|
-
}
|
|
226
|
-
async function resolveTmuxTargetFromHint(config, hint) {
|
|
227
|
-
const panes = await listTmuxPanes(config);
|
|
228
|
-
const byPaneId = hint.tmuxPaneId
|
|
229
|
-
? panes.find((pane) => pane.paneId === hint.tmuxPaneId)
|
|
230
|
-
: null;
|
|
231
|
-
if (byPaneId) {
|
|
232
|
-
return byPaneId.paneId;
|
|
233
|
-
}
|
|
234
|
-
const exactMatch = panes.find((pane) => {
|
|
235
|
-
if (!hint.tmuxSessionName) {
|
|
236
|
-
return false;
|
|
237
|
-
}
|
|
238
|
-
if (pane.sessionName !== hint.tmuxSessionName) {
|
|
239
|
-
return false;
|
|
240
|
-
}
|
|
241
|
-
if (typeof hint.tmuxWindowIndex === "number" &&
|
|
242
|
-
pane.windowIndex !== hint.tmuxWindowIndex) {
|
|
243
|
-
return false;
|
|
244
|
-
}
|
|
245
|
-
if (typeof hint.tmuxPaneIndex === "number" &&
|
|
246
|
-
pane.paneIndex !== hint.tmuxPaneIndex) {
|
|
247
|
-
return false;
|
|
248
|
-
}
|
|
249
|
-
if (hint.tmuxWindowName &&
|
|
250
|
-
pane.windowName !== hint.tmuxWindowName) {
|
|
251
|
-
return false;
|
|
252
|
-
}
|
|
253
|
-
return true;
|
|
254
|
-
});
|
|
255
|
-
if (exactMatch) {
|
|
256
|
-
return exactMatch.paneId;
|
|
257
|
-
}
|
|
258
|
-
const fallbackBySessionAndPane = panes.find((pane) => {
|
|
259
|
-
if (!hint.tmuxSessionName || typeof hint.tmuxPaneIndex !== "number") {
|
|
260
|
-
return false;
|
|
261
|
-
}
|
|
262
|
-
return (pane.sessionName === hint.tmuxSessionName &&
|
|
263
|
-
pane.paneIndex === hint.tmuxPaneIndex);
|
|
264
|
-
});
|
|
265
|
-
return fallbackBySessionAndPane?.paneId ?? null;
|
|
266
|
-
}
|
|
267
|
-
async function getTmuxWindowHeight(config, target) {
|
|
268
|
-
const { stdout: heightRaw } = await execFileOutputAsync("tmux", buildTmuxArgs(config, ["display-message", "-p", "-t", target, "#{window_height}"]));
|
|
269
|
-
const height = Number.parseInt(heightRaw.trim(), 10);
|
|
270
|
-
return Number.isFinite(height) && height > 0 ? height : null;
|
|
271
|
-
}
|
|
272
|
-
async function captureTmuxPaneRange(config, target, start, includeEscapes) {
|
|
273
|
-
const args = [
|
|
274
|
-
"capture-pane",
|
|
275
|
-
"-p",
|
|
276
|
-
...(includeEscapes ? ["-e"] : []),
|
|
277
|
-
"-t",
|
|
278
|
-
target,
|
|
279
|
-
"-S",
|
|
280
|
-
start,
|
|
281
|
-
];
|
|
282
|
-
const { stdout } = await execFileOutputAsync("tmux", buildTmuxArgs(config, args));
|
|
283
|
-
return stdout.replaceAll("\u0000", "");
|
|
284
|
-
}
|
|
285
|
-
async function captureVisibleTmuxPane(config, target, fallbackLines, visibleScreens) {
|
|
286
|
-
const height = await getTmuxWindowHeight(config, target);
|
|
287
|
-
const baseLines = typeof height === "number" && height > 0 ? height : Math.max(1, fallbackLines);
|
|
288
|
-
const lines = Math.max(1, baseLines * Math.max(1, visibleScreens));
|
|
289
|
-
let stdout = "";
|
|
290
|
-
try {
|
|
291
|
-
({ stdout } = await execFileOutputAsync("tmux", buildTmuxArgs(config, [
|
|
292
|
-
"capture-pane",
|
|
293
|
-
"-p",
|
|
294
|
-
"-e",
|
|
295
|
-
"-a",
|
|
296
|
-
"-t",
|
|
297
|
-
target,
|
|
298
|
-
"-S",
|
|
299
|
-
`-${lines}`,
|
|
300
|
-
])));
|
|
301
|
-
}
|
|
302
|
-
catch (error) {
|
|
303
|
-
const message = error instanceof Error ? (error.stack ?? error.message) : String(error);
|
|
304
|
-
if (!message.includes("no alternate screen")) {
|
|
305
|
-
throw error;
|
|
306
|
-
}
|
|
307
|
-
({ stdout } = await execFileOutputAsync("tmux", buildTmuxArgs(config, [
|
|
308
|
-
"capture-pane",
|
|
309
|
-
"-p",
|
|
310
|
-
"-e",
|
|
311
|
-
"-t",
|
|
312
|
-
target,
|
|
313
|
-
"-S",
|
|
314
|
-
`-${lines}`,
|
|
315
|
-
])));
|
|
316
|
-
}
|
|
317
|
-
return stdout.replaceAll("\u0000", "");
|
|
318
|
-
}
|
|
319
|
-
async function sendAllowedTmuxAction(config, target, action) {
|
|
320
|
-
const key = action === "up"
|
|
321
|
-
? "Up"
|
|
322
|
-
: action === "down"
|
|
323
|
-
? "Down"
|
|
324
|
-
: action === "slash"
|
|
325
|
-
? "/"
|
|
326
|
-
: action === "delete"
|
|
327
|
-
? "BSpace"
|
|
328
|
-
: action === "tab"
|
|
329
|
-
? "Tab"
|
|
330
|
-
: action === "escape"
|
|
331
|
-
? "Escape"
|
|
332
|
-
: action === "interrupt"
|
|
333
|
-
? "C-c"
|
|
334
|
-
: "Enter";
|
|
335
|
-
await execFileAsync("tmux", buildTmuxArgs(config, ["send-keys", "-t", target, key]));
|
|
336
|
-
}
|
|
337
|
-
async function sendTmuxLiteralText(config, target, text) {
|
|
338
|
-
const normalized = text.replace(/\r?\n/g, " ");
|
|
339
|
-
const bufferName = `telegram-mcp-${Date.now().toString(36)}`;
|
|
340
|
-
if (normalized.length > 0) {
|
|
341
|
-
try {
|
|
342
|
-
await execFileAsync("tmux", buildTmuxArgs(config, ["set-buffer", "-b", bufferName, normalized]));
|
|
343
|
-
await execFileAsync("tmux", buildTmuxArgs(config, [
|
|
344
|
-
"paste-buffer",
|
|
345
|
-
"-d",
|
|
346
|
-
"-b",
|
|
347
|
-
bufferName,
|
|
348
|
-
"-t",
|
|
349
|
-
target,
|
|
350
|
-
]));
|
|
351
|
-
}
|
|
352
|
-
finally {
|
|
353
|
-
await execFileAsync("tmux", buildTmuxArgs(config, ["delete-buffer", "-b", bufferName])).catch(() => undefined);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
async function sendTmuxLiteralLine(config, target, text) {
|
|
358
|
-
await sendTmuxLiteralText(config, target, text);
|
|
359
|
-
if (text.length > 0) {
|
|
360
|
-
await delay(ENTER_AFTER_PASTE_DELAY_MS);
|
|
361
|
-
}
|
|
362
|
-
await execFileAsync("tmux", buildTmuxArgs(config, ["send-keys", "-t", target, SUBMIT_LINE_KEY]));
|
|
363
|
-
}
|