@deadragdoll/tellymcp 0.0.10 → 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 -52
- package/.env.example.gateway +48 -62
- package/CHANGELOG.md +3 -3
- package/README-ru.md +205 -384
- package/README.md +195 -1194
- package/TOOLS.md +294 -377
- package/VERSION.md +11 -11
- 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 +897 -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 +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/resources/en.js +139 -42
- package/dist/services/features/telegram-mcp/src/shared/i18n/resources/ru.js +135 -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 +42 -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 +415 -7101
- 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 +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
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WEBAPP_APP_JS = exports.WEBAPP_STYLES_CSS = void 0;
|
|
4
4
|
exports.renderWebAppHtml = renderWebAppHtml;
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const XTERM_WEBAPP_CSS = (0, node_fs_1.readFileSync)(require.resolve("@xterm/xterm/css/xterm.css"), "utf8");
|
|
7
|
+
const XTERM_WEBAPP_JS = (0, node_fs_1.readFileSync)(require.resolve("@xterm/xterm/lib/xterm.js"), "utf8");
|
|
5
8
|
exports.WEBAPP_STYLES_CSS = `
|
|
6
9
|
:root {
|
|
7
10
|
color-scheme: dark;
|
|
@@ -22,9 +25,10 @@ exports.WEBAPP_STYLES_CSS = `
|
|
|
22
25
|
|
|
23
26
|
html, body {
|
|
24
27
|
margin: 0;
|
|
25
|
-
|
|
28
|
+
height: 100%;
|
|
26
29
|
background: linear-gradient(180deg, #121620 0%, #0d1017 100%);
|
|
27
30
|
color: var(--text);
|
|
31
|
+
overflow: hidden;
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
body {
|
|
@@ -32,15 +36,14 @@ body {
|
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
.app {
|
|
35
|
-
|
|
39
|
+
height: 100dvh;
|
|
40
|
+
display: grid;
|
|
41
|
+
grid-template-rows: 1fr auto auto;
|
|
42
|
+
overflow: hidden;
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
.toolbar {
|
|
39
|
-
|
|
40
|
-
left: 0;
|
|
41
|
-
right: 0;
|
|
42
|
-
bottom: calc(42px + env(safe-area-inset-bottom, 0px));
|
|
43
|
-
z-index: 30;
|
|
46
|
+
grid-row: 2;
|
|
44
47
|
display: flex;
|
|
45
48
|
justify-content: flex-start;
|
|
46
49
|
flex-wrap: wrap;
|
|
@@ -116,11 +119,7 @@ body {
|
|
|
116
119
|
}
|
|
117
120
|
|
|
118
121
|
.statusbar {
|
|
119
|
-
|
|
120
|
-
left: 0;
|
|
121
|
-
right: 0;
|
|
122
|
-
bottom: 0;
|
|
123
|
-
z-index: 25;
|
|
122
|
+
grid-row: 3;
|
|
124
123
|
display: flex;
|
|
125
124
|
flex-wrap: wrap;
|
|
126
125
|
align-items: center;
|
|
@@ -173,15 +172,37 @@ body {
|
|
|
173
172
|
}
|
|
174
173
|
|
|
175
174
|
.terminal {
|
|
175
|
+
grid-row: 1;
|
|
176
176
|
margin: 0;
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
overflow:
|
|
177
|
+
min-height: 0;
|
|
178
|
+
padding: 18px 14px;
|
|
179
|
+
overflow: hidden;
|
|
180
180
|
white-space: pre-wrap;
|
|
181
181
|
word-break: break-word;
|
|
182
182
|
font: 13px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
+
.terminal.xterm-host {
|
|
186
|
+
position: relative;
|
|
187
|
+
min-width: 0;
|
|
188
|
+
padding: 0;
|
|
189
|
+
overflow-x: auto;
|
|
190
|
+
overflow-y: hidden;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.terminal.xterm-host .xterm {
|
|
194
|
+
height: 100%;
|
|
195
|
+
width: max-content;
|
|
196
|
+
min-width: 100%;
|
|
197
|
+
padding: 0;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.terminal.xterm-host .xterm-viewport {
|
|
201
|
+
overflow-x: hidden !important;
|
|
202
|
+
overflow-y: auto !important;
|
|
203
|
+
-webkit-overflow-scrolling: touch !important;
|
|
204
|
+
}
|
|
205
|
+
|
|
185
206
|
.terminal.unwrap {
|
|
186
207
|
white-space: pre;
|
|
187
208
|
word-break: normal;
|
|
@@ -203,7 +224,6 @@ body {
|
|
|
203
224
|
|
|
204
225
|
@media (max-width: 680px) {
|
|
205
226
|
.toolbar {
|
|
206
|
-
bottom: calc(46px + env(safe-area-inset-bottom, 0px));
|
|
207
227
|
gap: 6px;
|
|
208
228
|
padding: 8px 10px;
|
|
209
229
|
}
|
|
@@ -223,7 +243,11 @@ body {
|
|
|
223
243
|
}
|
|
224
244
|
|
|
225
245
|
.terminal {
|
|
226
|
-
padding: 14px 12px
|
|
246
|
+
padding: 14px 12px;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.terminal.xterm-host .xterm {
|
|
250
|
+
padding: 0;
|
|
227
251
|
}
|
|
228
252
|
}
|
|
229
253
|
`;
|
|
@@ -239,6 +263,13 @@ const state = {
|
|
|
239
263
|
pollIntervalMs: 2000,
|
|
240
264
|
wrapEnabled: true,
|
|
241
265
|
recoverPromise: null,
|
|
266
|
+
xterm: null,
|
|
267
|
+
xtermInputBound: false,
|
|
268
|
+
liveSocket: null,
|
|
269
|
+
liveSocketConnected: false,
|
|
270
|
+
lastRenderSignature: null,
|
|
271
|
+
resizeObserver: null,
|
|
272
|
+
fittedRows: null,
|
|
242
273
|
};
|
|
243
274
|
|
|
244
275
|
const elements = {
|
|
@@ -270,6 +301,10 @@ function setUpdated(text) {
|
|
|
270
301
|
elements.updated.textContent = text;
|
|
271
302
|
}
|
|
272
303
|
|
|
304
|
+
function setLiveModeStatus(mode) {
|
|
305
|
+
setStatus(mode === "stream" ? "Live (stream)" : "Live (poll)");
|
|
306
|
+
}
|
|
307
|
+
|
|
273
308
|
function createHttpError(message, status) {
|
|
274
309
|
const error = new Error(message);
|
|
275
310
|
error.status = status;
|
|
@@ -284,7 +319,7 @@ function shouldRecoverWebAppSession(error) {
|
|
|
284
319
|
);
|
|
285
320
|
}
|
|
286
321
|
|
|
287
|
-
function
|
|
322
|
+
function applyTerminalAvailability(hasTarget) {
|
|
288
323
|
elements.interrupt.disabled = !hasTarget;
|
|
289
324
|
elements.type.disabled = !hasTarget;
|
|
290
325
|
elements.esc.disabled = !hasTarget;
|
|
@@ -333,6 +368,187 @@ function toggleWrapMode() {
|
|
|
333
368
|
}
|
|
334
369
|
}
|
|
335
370
|
|
|
371
|
+
function getXtermCtor() {
|
|
372
|
+
return window.Terminal || window.XtermTerminal || null;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function getTerminalCellHeight(terminal) {
|
|
376
|
+
const cell =
|
|
377
|
+
terminal &&
|
|
378
|
+
terminal._core &&
|
|
379
|
+
terminal._core._renderService &&
|
|
380
|
+
terminal._core._renderService.dimensions &&
|
|
381
|
+
terminal._core._renderService.dimensions.css &&
|
|
382
|
+
terminal._core._renderService.dimensions.css.cell;
|
|
383
|
+
|
|
384
|
+
if (!cell || !cell.height) {
|
|
385
|
+
return null;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
return cell.height;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function fitTerminalRows(notifyServer = true) {
|
|
392
|
+
const terminal = state.xterm;
|
|
393
|
+
if (!terminal || !elements.terminal) {
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const cellHeight = getTerminalCellHeight(terminal);
|
|
398
|
+
if (!cellHeight) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const nextRows = Math.max(5, Math.floor(elements.terminal.clientHeight / cellHeight));
|
|
403
|
+
if (!Number.isFinite(nextRows) || nextRows <= 0) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (state.fittedRows === nextRows) {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
state.fittedRows = nextRows;
|
|
412
|
+
const currentCols =
|
|
413
|
+
typeof terminal.cols === "number" && terminal.cols > 0 ? terminal.cols : 80;
|
|
414
|
+
terminal.resize(currentCols, nextRows);
|
|
415
|
+
|
|
416
|
+
if (
|
|
417
|
+
notifyServer &&
|
|
418
|
+
state.liveSocketConnected &&
|
|
419
|
+
state.liveSocket &&
|
|
420
|
+
state.liveSocket.readyState === WebSocket.OPEN
|
|
421
|
+
) {
|
|
422
|
+
state.liveSocket.send(
|
|
423
|
+
JSON.stringify({ type: "resize", cols: currentCols, rows: nextRows }),
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
function ensureXterm() {
|
|
429
|
+
if (state.xterm) {
|
|
430
|
+
return state.xterm;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const TerminalCtor = getXtermCtor();
|
|
434
|
+
if (!TerminalCtor || !elements.terminal) {
|
|
435
|
+
return null;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
elements.terminal.classList.add("xterm-host");
|
|
439
|
+
elements.terminal.textContent = "";
|
|
440
|
+
|
|
441
|
+
const terminal = new TerminalCtor({
|
|
442
|
+
convertEol: true,
|
|
443
|
+
disableStdin: false,
|
|
444
|
+
cursorBlink: false,
|
|
445
|
+
theme: {
|
|
446
|
+
background: "#0f1115",
|
|
447
|
+
foreground: "#edf1f7",
|
|
448
|
+
},
|
|
449
|
+
fontFamily:
|
|
450
|
+
'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',
|
|
451
|
+
fontSize: 13,
|
|
452
|
+
lineHeight: 1,
|
|
453
|
+
allowTransparency: true,
|
|
454
|
+
scrollback: 4000,
|
|
455
|
+
});
|
|
456
|
+
terminal.open(elements.terminal);
|
|
457
|
+
terminal.onData((data) => {
|
|
458
|
+
if (!state.liveSocketConnected || !state.liveSocket) {
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
if (state.liveSocket.readyState !== WebSocket.OPEN) {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
state.liveSocket.send(JSON.stringify({ type: "input", data }));
|
|
465
|
+
});
|
|
466
|
+
elements.terminal.addEventListener("pointerdown", (event) => {
|
|
467
|
+
if (event.pointerType === "mouse") {
|
|
468
|
+
terminal.focus();
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
if (!state.resizeObserver && typeof ResizeObserver !== "undefined") {
|
|
472
|
+
state.resizeObserver = new ResizeObserver(() => {
|
|
473
|
+
fitTerminalRows();
|
|
474
|
+
});
|
|
475
|
+
state.resizeObserver.observe(elements.terminal);
|
|
476
|
+
}
|
|
477
|
+
window.addEventListener("resize", () => {
|
|
478
|
+
fitTerminalRows();
|
|
479
|
+
});
|
|
480
|
+
state.xterm = terminal;
|
|
481
|
+
window.setTimeout(() => {
|
|
482
|
+
fitTerminalRows(false);
|
|
483
|
+
}, 0);
|
|
484
|
+
return terminal;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
function estimateTerminalSizeFromPayload(payload, options = {}) {
|
|
488
|
+
const text = payload.ansi || payload.content || "";
|
|
489
|
+
const lines = text.split("\\n");
|
|
490
|
+
const useViewportRows =
|
|
491
|
+
options.preferViewportRows === true &&
|
|
492
|
+
Number.isFinite(payload.rows) &&
|
|
493
|
+
payload.rows > 0;
|
|
494
|
+
const rows = useViewportRows
|
|
495
|
+
? Math.max(2, Math.min(120, payload.rows))
|
|
496
|
+
: Math.max(2, Math.min(400, lines.length || payload.rows || 24));
|
|
497
|
+
const baseCols = Number.isFinite(payload.cols) && payload.cols > 0
|
|
498
|
+
? payload.cols
|
|
499
|
+
: 40;
|
|
500
|
+
const cols = Math.max(
|
|
501
|
+
baseCols,
|
|
502
|
+
Math.min(
|
|
503
|
+
240,
|
|
504
|
+
Number.isFinite(payload.cols) && payload.cols > 0
|
|
505
|
+
? payload.cols
|
|
506
|
+
: lines.reduce((max, line) => Math.max(max, line.replace(/\\u001b\\[[0-9;]*m/g, "").length), 0) || 80,
|
|
507
|
+
),
|
|
508
|
+
);
|
|
509
|
+
return { cols, rows };
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function renderTerminalPayload(payload, options = {}) {
|
|
513
|
+
const signature = JSON.stringify({
|
|
514
|
+
ansi: payload.ansi || "",
|
|
515
|
+
content: payload.content || "",
|
|
516
|
+
cols: payload.cols || null,
|
|
517
|
+
rows: payload.rows || null,
|
|
518
|
+
preferViewportRows: options.preferViewportRows === true,
|
|
519
|
+
});
|
|
520
|
+
if (state.lastRenderSignature === signature) {
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
const terminal = ensureXterm();
|
|
525
|
+
if (!terminal) {
|
|
526
|
+
elements.terminal.innerHTML =
|
|
527
|
+
payload.html || renderAnsiToHtml(payload.content || "");
|
|
528
|
+
state.lastRenderSignature = signature;
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
const size = estimateTerminalSizeFromPayload(payload, options);
|
|
533
|
+
const previousViewportY = terminal.buffer.active.viewportY;
|
|
534
|
+
const previousBaseY = terminal.buffer.active.baseY;
|
|
535
|
+
const wasNearBottom =
|
|
536
|
+
previousBaseY <= 0 ||
|
|
537
|
+
previousViewportY >= Math.max(0, previousBaseY - 2);
|
|
538
|
+
terminal.reset();
|
|
539
|
+
terminal.resize(size.cols, size.rows);
|
|
540
|
+
terminal.write(payload.ansi || payload.content || "");
|
|
541
|
+
if (options.forceScrollBottom === true || wasNearBottom) {
|
|
542
|
+
terminal.scrollToBottom();
|
|
543
|
+
} else {
|
|
544
|
+
terminal.scrollToLine(Math.min(previousViewportY, terminal.buffer.active.baseY));
|
|
545
|
+
}
|
|
546
|
+
window.setTimeout(() => {
|
|
547
|
+
fitTerminalRows(false);
|
|
548
|
+
}, 0);
|
|
549
|
+
state.lastRenderSignature = signature;
|
|
550
|
+
}
|
|
551
|
+
|
|
336
552
|
function formatCapturedAt(value) {
|
|
337
553
|
if (!value) {
|
|
338
554
|
return "never";
|
|
@@ -677,9 +893,9 @@ function applyBootstrapPayload(bootstrapPayload) {
|
|
|
677
893
|
bootstrapPayload.session_label || bootstrapPayload.session_id;
|
|
678
894
|
elements.session.hidden = false;
|
|
679
895
|
|
|
680
|
-
const
|
|
681
|
-
|
|
682
|
-
setStatus(
|
|
896
|
+
const hasTerminalTarget = Boolean(bootstrapPayload.terminal_target);
|
|
897
|
+
applyTerminalAvailability(hasTerminalTarget);
|
|
898
|
+
setStatus(hasTerminalTarget ? "Live" : "No terminal target", !hasTerminalTarget);
|
|
683
899
|
}
|
|
684
900
|
|
|
685
901
|
async function recoverWebAppSession() {
|
|
@@ -736,21 +952,24 @@ async function sendAction(action) {
|
|
|
736
952
|
state.actionBusy = true;
|
|
737
953
|
try {
|
|
738
954
|
await withRecoveredSession(async () => {
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
955
|
+
if (state.liveSocketConnected && state.liveSocket?.readyState === WebSocket.OPEN) {
|
|
956
|
+
state.liveSocket.send(JSON.stringify({ type: "action", action }));
|
|
957
|
+
} else {
|
|
958
|
+
const response = await fetch(config.basePath + "/api/action", {
|
|
959
|
+
method: "POST",
|
|
960
|
+
headers: {
|
|
961
|
+
"content-type": "application/json",
|
|
962
|
+
authorization: "Bearer " + state.token,
|
|
963
|
+
},
|
|
964
|
+
body: JSON.stringify({ action }),
|
|
965
|
+
});
|
|
966
|
+
|
|
967
|
+
if (!response.ok) {
|
|
968
|
+
const text = await response.text();
|
|
969
|
+
throw createHttpError(text || "Failed to send action.", response.status);
|
|
970
|
+
}
|
|
751
971
|
}
|
|
752
972
|
});
|
|
753
|
-
await withRecoveredSession(refreshVisibleBuffer);
|
|
754
973
|
} finally {
|
|
755
974
|
state.actionBusy = false;
|
|
756
975
|
}
|
|
@@ -764,47 +983,147 @@ async function sendTextInput(text) {
|
|
|
764
983
|
state.actionBusy = true;
|
|
765
984
|
try {
|
|
766
985
|
await withRecoveredSession(async () => {
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
response.
|
|
781
|
-
|
|
986
|
+
if (state.liveSocketConnected && state.liveSocket?.readyState === WebSocket.OPEN) {
|
|
987
|
+
state.liveSocket.send(JSON.stringify({ type: "input", data: text }));
|
|
988
|
+
} else {
|
|
989
|
+
const response = await fetch(config.basePath + "/api/action", {
|
|
990
|
+
method: "POST",
|
|
991
|
+
headers: {
|
|
992
|
+
"content-type": "application/json",
|
|
993
|
+
authorization: "Bearer " + state.token,
|
|
994
|
+
},
|
|
995
|
+
body: JSON.stringify({ action: "text", text }),
|
|
996
|
+
});
|
|
997
|
+
|
|
998
|
+
if (!response.ok) {
|
|
999
|
+
const textResponse = await response.text();
|
|
1000
|
+
throw createHttpError(
|
|
1001
|
+
textResponse || "Failed to send text.",
|
|
1002
|
+
response.status,
|
|
1003
|
+
);
|
|
1004
|
+
}
|
|
782
1005
|
}
|
|
783
1006
|
});
|
|
784
1007
|
setStatus("Text sent");
|
|
785
|
-
await withRecoveredSession(refreshVisibleBuffer);
|
|
786
1008
|
} finally {
|
|
787
1009
|
state.actionBusy = false;
|
|
788
1010
|
}
|
|
789
1011
|
}
|
|
790
1012
|
|
|
1013
|
+
function getLiveWsUrl() {
|
|
1014
|
+
const liveWsPath =
|
|
1015
|
+
typeof config.liveWsPath === "string" && config.liveWsPath.trim()
|
|
1016
|
+
? config.liveWsPath.trim()
|
|
1017
|
+
: config.basePath + "/api/live/ws";
|
|
1018
|
+
const url = new URL(liveWsPath, window.location.href);
|
|
1019
|
+
if (state.token) {
|
|
1020
|
+
url.searchParams.set("token", state.token);
|
|
1021
|
+
}
|
|
1022
|
+
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
1023
|
+
return url.toString();
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
function closeLiveSocket() {
|
|
1027
|
+
if (!state.liveSocket) {
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
const socket = state.liveSocket;
|
|
1031
|
+
state.liveSocket = null;
|
|
1032
|
+
state.liveSocketConnected = false;
|
|
1033
|
+
try {
|
|
1034
|
+
socket.close();
|
|
1035
|
+
} catch (_error) {
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
async function connectLiveSocket() {
|
|
1040
|
+
closeLiveSocket();
|
|
1041
|
+
if (!state.token) {
|
|
1042
|
+
throw new Error("WebApp token is missing");
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
const socket = new WebSocket(getLiveWsUrl());
|
|
1046
|
+
state.liveSocket = socket;
|
|
1047
|
+
|
|
1048
|
+
await new Promise((resolve, reject) => {
|
|
1049
|
+
let settled = false;
|
|
1050
|
+
|
|
1051
|
+
socket.addEventListener("open", () => {
|
|
1052
|
+
state.liveSocketConnected = true;
|
|
1053
|
+
settled = true;
|
|
1054
|
+
stopPolling();
|
|
1055
|
+
resolve();
|
|
1056
|
+
}, { once: true });
|
|
1057
|
+
|
|
1058
|
+
socket.addEventListener("error", () => {
|
|
1059
|
+
if (settled) {
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1062
|
+
settled = true;
|
|
1063
|
+
reject(new Error("Live stream connection failed"));
|
|
1064
|
+
}, { once: true });
|
|
1065
|
+
});
|
|
1066
|
+
|
|
1067
|
+
socket.addEventListener("message", (event) => {
|
|
1068
|
+
const payload = JSON.parse(String(event.data));
|
|
1069
|
+
if (payload.type === "snapshot") {
|
|
1070
|
+
renderTerminalPayload(payload, {
|
|
1071
|
+
preferViewportRows: true,
|
|
1072
|
+
forceScrollBottom: true,
|
|
1073
|
+
});
|
|
1074
|
+
setUpdated(formatCapturedAt(payload.captured_at));
|
|
1075
|
+
setLiveModeStatus("stream");
|
|
1076
|
+
return;
|
|
1077
|
+
}
|
|
1078
|
+
if (payload.type === "data") {
|
|
1079
|
+
const terminal = ensureXterm();
|
|
1080
|
+
if (terminal && typeof payload.data === "string") {
|
|
1081
|
+
const previousViewportY = terminal.buffer.active.viewportY;
|
|
1082
|
+
const previousBaseY = terminal.buffer.active.baseY;
|
|
1083
|
+
const wasNearBottom =
|
|
1084
|
+
previousBaseY <= 0 ||
|
|
1085
|
+
previousViewportY >= Math.max(0, previousBaseY - 2);
|
|
1086
|
+
terminal.write(payload.data);
|
|
1087
|
+
if (wasNearBottom) {
|
|
1088
|
+
terminal.scrollToBottom();
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
if (payload.type === "exit") {
|
|
1094
|
+
setStatus("Terminal exited", true);
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
1097
|
+
});
|
|
1098
|
+
|
|
1099
|
+
socket.addEventListener("close", () => {
|
|
1100
|
+
state.liveSocketConnected = false;
|
|
1101
|
+
if (state.liveSocket === socket) {
|
|
1102
|
+
state.liveSocket = null;
|
|
1103
|
+
}
|
|
1104
|
+
setLiveModeStatus("poll");
|
|
1105
|
+
startPolling();
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
|
|
791
1109
|
function confirmInterrupt() {
|
|
792
1110
|
return new Promise((resolve) => {
|
|
793
1111
|
if (tg && typeof tg.showConfirm === "function") {
|
|
794
|
-
tg.showConfirm("Send Ctrl+C to the
|
|
1112
|
+
tg.showConfirm("Send Ctrl+C to the terminal session? This can stop the running agent.", (ok) => {
|
|
795
1113
|
resolve(Boolean(ok));
|
|
796
1114
|
});
|
|
797
1115
|
return;
|
|
798
1116
|
}
|
|
799
1117
|
|
|
800
|
-
resolve(window.confirm("Send Ctrl+C to the
|
|
1118
|
+
resolve(window.confirm("Send Ctrl+C to the terminal session? This can stop the running agent."));
|
|
801
1119
|
});
|
|
802
1120
|
}
|
|
803
1121
|
|
|
804
1122
|
async function refreshVisibleBuffer() {
|
|
805
1123
|
const payload = await withRecoveredSession(fetchVisibleBuffer);
|
|
806
|
-
|
|
1124
|
+
renderTerminalPayload(payload);
|
|
807
1125
|
setUpdated(formatCapturedAt(payload.captured_at));
|
|
1126
|
+
setLiveModeStatus("poll");
|
|
808
1127
|
}
|
|
809
1128
|
|
|
810
1129
|
function stopPolling() {
|
|
@@ -844,7 +1163,7 @@ function bindUi() {
|
|
|
844
1163
|
});
|
|
845
1164
|
|
|
846
1165
|
elements.type.addEventListener("click", () => {
|
|
847
|
-
const value = window.prompt("Send text to
|
|
1166
|
+
const value = window.prompt("Send text to terminal without Enter:", "");
|
|
848
1167
|
if (value === null || value.length === 0) {
|
|
849
1168
|
return;
|
|
850
1169
|
}
|
|
@@ -913,8 +1232,12 @@ async function main() {
|
|
|
913
1232
|
setStatus("Authorizing Mini App...");
|
|
914
1233
|
const bootstrapPayload = await bootstrap();
|
|
915
1234
|
applyBootstrapPayload(bootstrapPayload);
|
|
916
|
-
|
|
917
|
-
|
|
1235
|
+
try {
|
|
1236
|
+
await connectLiveSocket();
|
|
1237
|
+
} catch (_error) {
|
|
1238
|
+
await refreshVisibleBuffer();
|
|
1239
|
+
startPolling();
|
|
1240
|
+
}
|
|
918
1241
|
} catch (error) {
|
|
919
1242
|
const message = error instanceof Error ? error.message : String(error);
|
|
920
1243
|
setStatus(message, true);
|
|
@@ -935,7 +1258,8 @@ function renderWebAppHtml(input) {
|
|
|
935
1258
|
/>
|
|
936
1259
|
<title>Telegram MCP Live View</title>
|
|
937
1260
|
<script src="https://telegram.org/js/telegram-web-app.js"></script>
|
|
938
|
-
<
|
|
1261
|
+
<style>${exports.WEBAPP_STYLES_CSS}
|
|
1262
|
+
${XTERM_WEBAPP_CSS}</style>
|
|
939
1263
|
</head>
|
|
940
1264
|
<body>
|
|
941
1265
|
<div class="app">
|
|
@@ -951,7 +1275,7 @@ function renderWebAppHtml(input) {
|
|
|
951
1275
|
<span class="toolbar-spacer" aria-hidden="true"></span>
|
|
952
1276
|
<button class="btn compact danger" data-role="interrupt" type="button">Ctrl+C</button>
|
|
953
1277
|
</div>
|
|
954
|
-
<
|
|
1278
|
+
<div class="terminal" data-role="terminal">Waiting for terminal buffer…</div>
|
|
955
1279
|
<div class="statusbar">
|
|
956
1280
|
<div class="status-left">
|
|
957
1281
|
<span data-role="status">Loading… - Live View</span>
|
|
@@ -966,10 +1290,14 @@ function renderWebAppHtml(input) {
|
|
|
966
1290
|
<script>
|
|
967
1291
|
window.__TELEGRAM_MCP_WEBAPP__ = ${JSON.stringify({
|
|
968
1292
|
basePath: input.basePath,
|
|
1293
|
+
liveWsPath: input.liveWsPath,
|
|
969
1294
|
launchMode: input.launchMode,
|
|
970
1295
|
})};
|
|
971
1296
|
</script>
|
|
972
1297
|
<script>
|
|
1298
|
+
${XTERM_WEBAPP_JS}
|
|
1299
|
+
</script>
|
|
1300
|
+
<script>
|
|
973
1301
|
(() => {
|
|
974
1302
|
const source = ${JSON.stringify(exports.WEBAPP_APP_JS)};
|
|
975
1303
|
(0, eval)(source);
|
|
@@ -17,6 +17,9 @@ class WebAppLaunchRegistry {
|
|
|
17
17
|
...(details?.telegramMessageId !== undefined
|
|
18
18
|
? { telegramMessageId: details.telegramMessageId }
|
|
19
19
|
: {}),
|
|
20
|
+
...(details?.allowForeignBinding === true
|
|
21
|
+
? { allowForeignBinding: true }
|
|
22
|
+
: {}),
|
|
20
23
|
expiresAtMs: nowMs + ttlSeconds * 1000,
|
|
21
24
|
createdAtMs: nowMs,
|
|
22
25
|
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sendTerminalLiteralText = exports.sendAllowedTerminalAction = exports.isTerminalUnavailableError = exports.getTerminalWindowSize = exports.getTerminalWindowHeight = exports.captureVisibleTerminalAnsi = exports.captureVisibleTerminal = exports.captureTerminalPaneRange = void 0;
|
|
4
|
+
var client_1 = require("../../shared/integrations/terminal/client");
|
|
5
|
+
Object.defineProperty(exports, "captureTerminalPaneRange", { enumerable: true, get: function () { return client_1.captureTerminalPaneRange; } });
|
|
6
|
+
Object.defineProperty(exports, "captureVisibleTerminal", { enumerable: true, get: function () { return client_1.captureVisibleTerminal; } });
|
|
7
|
+
Object.defineProperty(exports, "captureVisibleTerminalAnsi", { enumerable: true, get: function () { return client_1.captureVisibleTerminalAnsi; } });
|
|
8
|
+
Object.defineProperty(exports, "getTerminalWindowHeight", { enumerable: true, get: function () { return client_1.getTerminalWindowHeight; } });
|
|
9
|
+
Object.defineProperty(exports, "getTerminalWindowSize", { enumerable: true, get: function () { return client_1.getTerminalWindowSize; } });
|
|
10
|
+
Object.defineProperty(exports, "isTerminalUnavailableError", { enumerable: true, get: function () { return client_1.isTerminalUnavailableError; } });
|
|
11
|
+
Object.defineProperty(exports, "sendAllowedTerminalAction", { enumerable: true, get: function () { return client_1.sendAllowedTerminalAction; } });
|
|
12
|
+
Object.defineProperty(exports, "sendTerminalLiteralText", { enumerable: true, get: function () { return client_1.sendTerminalLiteralText; } });
|