@deadragdoll/tellymcp 0.0.13 → 0.0.14
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 +5 -1
- package/.env.example.gateway +16 -1
- package/CHANGELOG.md +30 -0
- package/README-ru.md +14 -0
- package/README.md +14 -0
- package/TOOLS.md +182 -10
- package/config/templates/env.both.template +15 -2
- package/config/templates/env.client.template +5 -2
- package/config/templates/env.gateway.template +15 -2
- package/dist/cli.js +28 -1
- package/dist/services/features/telegram-mcp/browser.service.js +18 -0
- package/dist/services/features/telegram-mcp/file-content.service.js +94 -0
- package/dist/services/features/telegram-mcp/gateway-delivery.service.js +5 -1
- package/dist/services/features/telegram-mcp/gateway-socket.service.js +43 -11
- package/dist/services/features/telegram-mcp/mcp-http.service.js +1 -0
- package/dist/services/features/telegram-mcp/mcp-server.service.js +18 -0
- package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +9 -1
- package/dist/services/features/telegram-mcp/src/app/config/env.js +119 -2
- package/dist/services/features/telegram-mcp/src/app/http.js +139 -99
- package/dist/services/features/telegram-mcp/src/app/oauthFacade.js +642 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +151 -170
- package/dist/services/features/telegram-mcp/src/app/webapp/auth.js +96 -99
- package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +62 -19
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserAttachActiveTabTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserAttachTabTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserDetachTabTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserListAttachedInstancesTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserListTabsTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +410 -27
- package/dist/services/features/telegram-mcp/src/features/browser-attach/model/browserRecordingBundle.js +37 -3
- package/dist/services/features/telegram-mcp/src/features/browser-attach/model/firefoxAttachRegistry.js +7 -6
- package/dist/services/features/telegram-mcp/src/features/browser-attach/model/firefoxAttachServer.js +214 -37
- package/dist/services/features/telegram-mcp/src/features/browser-attach/model/types.js +186 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/collaborationService.js +2 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +6 -3
- package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayClientAccess.js +4 -1
- package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +33 -35
- package/dist/services/features/telegram-mcp/src/features/file-content/model/getFileListTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/file-content/model/getFileService.js +327 -0
- package/dist/services/features/telegram-mcp/src/features/file-content/model/getFileTool.js +81 -0
- package/dist/services/features/telegram-mcp/src/features/file-content/model/temporaryFileLinkStore.js +307 -0
- package/dist/services/features/telegram-mcp/src/features/file-content/model/workspaceFilePolicy.js +115 -0
- package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +5 -1
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +3 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFileHandoffActions.js +6 -3
- package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/client.js +29 -6
- package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/ptyRegistry.js +100 -2
- package/dist/services/features/telegram-mcp/src/shared/lib/bodyLimits.js +63 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/gatewayAuth.js +13 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/time/localTimestamp.js +21 -0
- package/docs/CHAT_CONNECTOR.md +134 -0
- package/docs/STANDALONE-ru.md +13 -0
- package/docs/STANDALONE.md +13 -0
- package/package.json +5 -3
- package/packages/chrome-attach-extension/dist/background.js +572 -163
- package/packages/chrome-attach-extension/dist/manifest.json +2 -1
- package/packages/chrome-attach-extension/dist/options.js +15 -2
- package/packages/chrome-attach-extension/dist/recorder-content.js +14 -1
- package/packages/chrome-attach-extension/dist/recorder-page.js +34 -18
- package/packages/firefox-attach-extension/dist/background.js +413 -33
- package/packages/firefox-attach-extension/dist/manifest.json +0 -12
- package/packages/firefox-attach-extension/dist/options.js +14 -1
- package/packages/firefox-attach-extension/dist/recorder-content.js +14 -1
- package/packages/firefox-attach-extension/dist/recorder-page.js +34 -18
package/.env.example.client
CHANGED
|
@@ -29,7 +29,7 @@ GATEWAY_WS_URL=wss://your-domain.example/api/gateway/ws
|
|
|
29
29
|
GATEWAY_WS_PATH=/api/gateway/ws
|
|
30
30
|
GATEWAY_TOKEN=change_me_gateway_token
|
|
31
31
|
GATEWAY_USER_UUID=
|
|
32
|
-
|
|
32
|
+
GATEWAY_AUTH_TOKEN=
|
|
33
33
|
|
|
34
34
|
TERMINAL_SHELL=bash
|
|
35
35
|
TERMINAL_COLS=120
|
|
@@ -71,6 +71,10 @@ BROWSER_WAIT_UNTIL=load
|
|
|
71
71
|
# BROWSER_EXECUTABLE_PATH=
|
|
72
72
|
# BROWSER_CHANNEL=chrome
|
|
73
73
|
BROWSER_SLOW_MO_MS=0
|
|
74
|
+
# BROWSER_ATTACH_ENABLED=true
|
|
75
|
+
# BROWSER_ATTACH_WS_HOST=127.0.0.1
|
|
76
|
+
# BROWSER_ATTACH_WS_PORT=9999
|
|
77
|
+
# BROWSER_ATTACH_WS_PATH=/browser-attach/ws
|
|
74
78
|
|
|
75
79
|
NAMESPACE=mcp
|
|
76
80
|
NODE_ID=agent
|
package/.env.example.gateway
CHANGED
|
@@ -29,12 +29,27 @@ MCP_HTTP_PATH=/mcp
|
|
|
29
29
|
MCP_HTTP_ENABLE_DEBUG_ROUTES=false
|
|
30
30
|
MCP_HTTP_ENABLE_PRUNE_ROUTE=false
|
|
31
31
|
|
|
32
|
+
# ChatGPT / Claude OAuth connector. Setting any OAuth value enables the facade.
|
|
33
|
+
# TELLYMCP_PUBLIC_URL=https://your-domain.example/api
|
|
34
|
+
# TELLYMCP_OAUTH_ISSUER=https://your-domain.example/api
|
|
35
|
+
# TELLYMCP_OAUTH_AUDIENCE=https://your-domain.example/api
|
|
36
|
+
# TELLYMCP_MAGIC_TOKEN=change_me_private_connector_token
|
|
37
|
+
# TELLYMCP_MAGIC_TOKEN_HASH=sha256:<hex>
|
|
38
|
+
# TELLYMCP_OAUTH_CLIENT_ID=tellymcp
|
|
39
|
+
# TELLYMCP_OAUTH_CLIENT_SECRET=
|
|
40
|
+
# TELLYMCP_ALLOWED_REDIRECT_URIS=https://chatgpt.com/connector/oauth/...,https://claude.ai/api/mcp/auth_callback
|
|
41
|
+
# TELLYMCP_OAUTH_PRIVATE_KEY_PEM="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
|
|
42
|
+
# TELLYMCP_AUTH_CODE_TTL_SECONDS=300
|
|
43
|
+
# TELLYMCP_OAUTH_SCOPES=tellymcp:read tellymcp:write
|
|
44
|
+
# TELLYMCP_OAUTH_KEY_ID=tellymcp-oauth
|
|
45
|
+
|
|
32
46
|
DISTRIBUTED_MODE=gateway
|
|
47
|
+
# Also used to derive short-lived file URLs under /api/files/.
|
|
33
48
|
GATEWAY_PUBLIC_URL=https://your-domain.example/api/gateway
|
|
34
49
|
GATEWAY_WS_URL=wss://your-domain.example/api/gateway/ws
|
|
35
50
|
GATEWAY_WS_PATH=/api/gateway/ws
|
|
36
51
|
GATEWAY_TOKEN=change_me_gateway_token
|
|
37
|
-
|
|
52
|
+
GATEWAY_AUTH_TOKEN=
|
|
38
53
|
|
|
39
54
|
ROOT_PREFIX=/api
|
|
40
55
|
PORT=8080
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,27 @@
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
5
|
### Added
|
|
6
|
+
|
|
7
|
+
- Добавлены связанные MCP tools `get_file_list` и `get_file` для получения
|
|
8
|
+
файлов из workspace выбранной live-консоли через gateway. Первый возвращает
|
|
9
|
+
список managed files и точные пути, второй принимает `file_path` либо
|
|
10
|
+
`selector=latest_screenshot`. По умолчанию `get_file(type="url")` возвращает
|
|
11
|
+
короткоживущую download-ссылку в `data`; временная gateway-копия хранится в
|
|
12
|
+
`.tellymcp/tmp/file-links`, а `type="base64"` остаётся fallback.
|
|
13
|
+
- Добавлен явный режим `get_file(type="image")`: download URL остаётся в
|
|
14
|
+
`structuredContent.data`, сам structured type равен `image`, а изображение
|
|
15
|
+
возвращается отдельным нативным MCP-блоком, чтобы Claude и другие совместимые
|
|
16
|
+
клиенты могли рендерить его inline.
|
|
17
|
+
- Для Claude.ai сохранён совместимый `type="base64"`: полный JSON вместе с raw
|
|
18
|
+
base64 в `data` возвращается обычным MCP text-блоком без native image, поскольку
|
|
19
|
+
некоторые MCP-host адаптеры заменяют изображение на `[image]` и скрывают
|
|
20
|
+
structured output от модели.
|
|
21
|
+
- Добавлен `get_file(type="text")` для прямого чтения UTF-8 Markdown и исходников
|
|
22
|
+
через native MCP text-блок. Для `.ts`, `.tsx` и других source-расширений добавлены
|
|
23
|
+
текстовые MIME overrides.
|
|
24
|
+
- Доступ к live `.env`, credential stores, private-key расширениям и чувствительным
|
|
25
|
+
директориям теперь блокируется на клиенте до чтения или отправки файла; выход
|
|
26
|
+
за workspace и через symlink по-прежнему запрещён.
|
|
6
27
|
- Перенос `telegram_mcp` на сервисную архитектуру `Moleculer`:
|
|
7
28
|
- `telegramMcp.runtime`
|
|
8
29
|
- `telegramMcp.http`
|
|
@@ -74,6 +95,14 @@
|
|
|
74
95
|
- безопасные packaged templates для `.env`
|
|
75
96
|
|
|
76
97
|
### Changed
|
|
98
|
+
|
|
99
|
+
- Общее чтение workspace-файлов теперь проверяет реальный путь после разрешения
|
|
100
|
+
symlink и не позволяет выйти за пределы workspace.
|
|
101
|
+
- Telegram Mini App Live Console переведена на WS-only rendering:
|
|
102
|
+
- HTTP polling и `/api/view` удалены
|
|
103
|
+
- после разрыва WebSocket автоматически восстанавливается с exponential backoff
|
|
104
|
+
- размеры xterm рассчитываются официальным `@xterm/addon-fit`
|
|
105
|
+
- resize колонок и строк передаётся локальным и relay PTY
|
|
77
106
|
- Полностью убран legacy standalone MCP transport. `telegram_mcp` работает только через REST/MCP over HTTP.
|
|
78
107
|
- Локальный standalone HTTP listener убран; `telegram_mcp` больше не поднимает отдельный сервер вне Moleculer gateway.
|
|
79
108
|
- UI Telegram переосмыслен по двум режимам:
|
|
@@ -113,6 +142,7 @@
|
|
|
113
142
|
- старый `go/node terminal-proxy` path полностью удалён, поддерживается только прямой локальный terminal runtime
|
|
114
143
|
|
|
115
144
|
### Fixed
|
|
145
|
+
|
|
116
146
|
- Исправлен `Headers have already sent` при работе MCP/WebApp через общий HTTP runtime.
|
|
117
147
|
- Исправлены route/alias проблемы после перехода под `${ROOT_PREFIX}`.
|
|
118
148
|
- Исправлены зависания Mini App bootstrap и проблемы с relative WebApp routes.
|
package/README-ru.md
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
- даёт MCP tools для human-in-the-loop через Telegram
|
|
29
29
|
- позволяет одной консоли агента ставить задачу другой консоли
|
|
30
|
+
- позволяет MCP chat-клиенту получать проектный текст, изображения и артефакты выбранной консоли
|
|
30
31
|
- хранит structured xchange records в `.mcp-xchange`
|
|
31
32
|
- поддерживает browser automation через Playwright
|
|
32
33
|
- умеет attach к уже открытому Firefox или Chrome через bundled local extensions
|
|
@@ -66,6 +67,7 @@ Gateway
|
|
|
66
67
|
- `telegram_message`
|
|
67
68
|
- `notify_telegram`
|
|
68
69
|
- `browser_screenshot(send_to_telegram=true)`
|
|
70
|
+
- `get_file` для возврата скриншотов и артефактов в MCP chat-клиент
|
|
69
71
|
|
|
70
72
|
Для agent-to-agent:
|
|
71
73
|
|
|
@@ -87,6 +89,15 @@ Gateway
|
|
|
87
89
|
- `browser_recording_stop`
|
|
88
90
|
- `browser_recording_status`
|
|
89
91
|
|
|
92
|
+
Файлы:
|
|
93
|
+
|
|
94
|
+
- `get_file_list(source=..., limit=...)`
|
|
95
|
+
- `get_file(file_path=..., type="url")`
|
|
96
|
+
- `get_file(file_path=..., type="image")`
|
|
97
|
+
- `get_file(file_path=..., type="text")`
|
|
98
|
+
- `get_file(file_path=..., type="base64")`
|
|
99
|
+
- `get_file(selector="latest_screenshot")`
|
|
100
|
+
|
|
90
101
|
Синхронизация инструкций:
|
|
91
102
|
|
|
92
103
|
- `refresh_tools_markdown`
|
|
@@ -157,6 +168,7 @@ tellymcp init gateway
|
|
|
157
168
|
- `GATEWAY_PUBLIC_URL`
|
|
158
169
|
- `GATEWAY_WS_URL`
|
|
159
170
|
- `GATEWAY_TOKEN`
|
|
171
|
+
- `GATEWAY_AUTH_TOKEN`
|
|
160
172
|
|
|
161
173
|
Запуск:
|
|
162
174
|
|
|
@@ -183,6 +195,7 @@ tellymcp init client
|
|
|
183
195
|
- `GATEWAY_PUBLIC_URL`
|
|
184
196
|
- `GATEWAY_WS_URL`
|
|
185
197
|
- `GATEWAY_TOKEN`
|
|
198
|
+
- `GATEWAY_AUTH_TOKEN` (тот же transport-токен, который задан на gateway)
|
|
186
199
|
- `GATEWAY_USER_UUID`, если консоль должна быть видна конкретному владельцу в gateway-боте
|
|
187
200
|
|
|
188
201
|
Рекомендуется:
|
|
@@ -375,6 +388,7 @@ tellymcp system-prune --env .env --yes
|
|
|
375
388
|
- [README.md](./README.md)
|
|
376
389
|
- [STANDALONE.md](./docs/STANDALONE.md)
|
|
377
390
|
- [STANDALONE-ru.md](./docs/STANDALONE-ru.md)
|
|
391
|
+
- [CHAT_CONNECTOR.md](./docs/CHAT_CONNECTOR.md) — OAuth-коннектор ChatGPT/Claude
|
|
378
392
|
- [TOOLS.md](./TOOLS.md)
|
|
379
393
|
- [screenshots/README.md](./screenshots/README.md)
|
|
380
394
|
|
package/README.md
CHANGED
|
@@ -27,6 +27,7 @@ The current model is gateway-first:
|
|
|
27
27
|
|
|
28
28
|
- exposes MCP tools for human Telegram interaction
|
|
29
29
|
- lets one agent ask another agent to do work and return files or notes
|
|
30
|
+
- lets MCP chat clients retrieve project text, images, and artifacts from a selected console
|
|
30
31
|
- stores structured xchange records in `.mcp-xchange`
|
|
31
32
|
- supports browser automation with Playwright
|
|
32
33
|
- can attach to an already running Firefox or Chrome tab through bundled local extensions
|
|
@@ -66,6 +67,7 @@ Human-facing:
|
|
|
66
67
|
- `telegram_message` records
|
|
67
68
|
- `notify_telegram`
|
|
68
69
|
- `browser_screenshot(send_to_telegram=true)`
|
|
70
|
+
- `get_file` for returning screenshots and artifacts to MCP chat clients
|
|
69
71
|
|
|
70
72
|
Agent-to-agent:
|
|
71
73
|
|
|
@@ -87,6 +89,15 @@ Browser:
|
|
|
87
89
|
- `browser_recording_stop`
|
|
88
90
|
- `browser_recording_status`
|
|
89
91
|
|
|
92
|
+
Files:
|
|
93
|
+
|
|
94
|
+
- `get_file_list(source=..., limit=...)`
|
|
95
|
+
- `get_file(file_path=..., type="url")`
|
|
96
|
+
- `get_file(file_path=..., type="image")`
|
|
97
|
+
- `get_file(file_path=..., type="text")`
|
|
98
|
+
- `get_file(file_path=..., type="base64")`
|
|
99
|
+
- `get_file(selector="latest_screenshot")`
|
|
100
|
+
|
|
90
101
|
Tools sync:
|
|
91
102
|
|
|
92
103
|
- `refresh_tools_markdown`
|
|
@@ -157,6 +168,7 @@ Required gateway values:
|
|
|
157
168
|
- `GATEWAY_PUBLIC_URL`
|
|
158
169
|
- `GATEWAY_WS_URL`
|
|
159
170
|
- `GATEWAY_TOKEN`
|
|
171
|
+
- `GATEWAY_AUTH_TOKEN`
|
|
160
172
|
|
|
161
173
|
Then run:
|
|
162
174
|
|
|
@@ -183,6 +195,7 @@ Required client values:
|
|
|
183
195
|
- `GATEWAY_PUBLIC_URL`
|
|
184
196
|
- `GATEWAY_WS_URL`
|
|
185
197
|
- `GATEWAY_TOKEN`
|
|
198
|
+
- `GATEWAY_AUTH_TOKEN` (the same transport token configured on the gateway)
|
|
186
199
|
- `GATEWAY_USER_UUID` if this console should be scoped to a specific Telegram owner
|
|
187
200
|
|
|
188
201
|
Recommended:
|
|
@@ -374,6 +387,7 @@ tellymcp system-prune --env .env --yes
|
|
|
374
387
|
- [README-ru.md](./README-ru.md)
|
|
375
388
|
- [STANDALONE.md](./docs/STANDALONE.md)
|
|
376
389
|
- [STANDALONE-ru.md](./docs/STANDALONE-ru.md)
|
|
390
|
+
- [CHAT_CONNECTOR.md](./docs/CHAT_CONNECTOR.md) — ChatGPT/Claude OAuth connector
|
|
377
391
|
- [TOOLS.md](./TOOLS.md)
|
|
378
392
|
- [screenshots/README.md](./screenshots/README.md)
|
|
379
393
|
|
package/TOOLS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Tools
|
|
2
2
|
|
|
3
|
-
Version: `2026-06-06.
|
|
3
|
+
Version: `2026-06-06.2`
|
|
4
4
|
|
|
5
5
|
Gateway/client runtime compatibility:
|
|
6
6
|
|
|
@@ -18,6 +18,9 @@ Browser tools:
|
|
|
18
18
|
|
|
19
19
|
- `browser_list_attached_instances`
|
|
20
20
|
- `browser_list_tabs`
|
|
21
|
+
- `browser_attach_active_tab`
|
|
22
|
+
- `browser_attach_tab`
|
|
23
|
+
- `browser_detach_tab`
|
|
21
24
|
- `browser_recording_start`
|
|
22
25
|
- `browser_recording_stop`
|
|
23
26
|
- `browser_recording_status`
|
|
@@ -44,8 +47,8 @@ Browser runtime rule:
|
|
|
44
47
|
- attached browser tab backend for a real user Firefox or Chrome session
|
|
45
48
|
- isolated Playwright Chromium backend
|
|
46
49
|
- `browser_open` is only for the isolated Playwright backend.
|
|
47
|
-
- `browser_list_attached_instances` and `
|
|
48
|
-
-
|
|
50
|
+
- `browser_list_attached_instances`, `browser_list_tabs`, `browser_attach_active_tab`, `browser_attach_tab`, and `browser_detach_tab` are for the attached browser backend.
|
|
51
|
+
- after a tab is attached for the current session, `browser_click`, `browser_fill`, `browser_inject_script`, `browser_press`, `browser_wait_for`, `browser_wait_for_url`, `browser_dom`, `browser_computed_style`, `browser_reload`, `browser_screenshot`, `browser_console`, `browser_errors`, `browser_network_failures`, `browser_clear_logs`, and `browser_close` use that attached browser tab without requiring `browser_open`
|
|
49
52
|
- `browser_recording_start`, `browser_recording_stop`, and `browser_recording_status` are also for the attached browser backend
|
|
50
53
|
- browser recordings are written under `.mcp-xchange/web/{tab-title-slug}-{timestamp}/`
|
|
51
54
|
- each recording bundle contains `session.json`, `timeline.ndjson`, `pages/`, `network/`, and `console/`
|
|
@@ -80,13 +83,16 @@ Collaboration tools:
|
|
|
80
83
|
|
|
81
84
|
Utility tools:
|
|
82
85
|
|
|
86
|
+
- `get_file_list`
|
|
87
|
+
- `get_file`
|
|
83
88
|
- `refresh_tools_markdown`
|
|
84
89
|
|
|
85
90
|
## Console model
|
|
86
91
|
|
|
87
92
|
Gateway-first runtime model:
|
|
88
93
|
|
|
89
|
-
- agents
|
|
94
|
+
- agents authenticate the gateway HTTP/WS transport through `GATEWAY_AUTH_TOKEN`
|
|
95
|
+
and register into their gateway scope through `GATEWAY_TOKEN`
|
|
90
96
|
- Telegram no longer links sessions with pair codes
|
|
91
97
|
- `/menu` in the gateway bot shows available remote consoles directly
|
|
92
98
|
- one running agent console is one logical session/console target
|
|
@@ -111,7 +117,18 @@ Preferred order for cross-console work:
|
|
|
111
117
|
- `send_partner_note`
|
|
112
118
|
- `send_partner_file`
|
|
113
119
|
- browser tools
|
|
114
|
-
|
|
120
|
+
with explicit `session_id` for the current console or explicit target routing fields for another console.
|
|
121
|
+
|
|
122
|
+
Preferred file-return flow for MCP chat clients:
|
|
123
|
+
|
|
124
|
+
1. Resolve the selected live console and keep its canonical `session_id`.
|
|
125
|
+
2. If the user refers to an existing managed file without an exact path, call `get_file_list` and select the matching `file_path`.
|
|
126
|
+
3. If creating a screenshot now, call `browser_screenshot` and keep its returned `file_path`.
|
|
127
|
+
4. For an exact Markdown, source-code, or other UTF-8 project path, call `get_file(type = "text")`; arbitrary project files are not discovered by `get_file_list`.
|
|
128
|
+
5. For binary files, call `get_file` with the selected or newly returned `file_path`; default to `type = "url"`.
|
|
129
|
+
6. If the chat cannot fetch an image URL, repeat the same call with `type = "image"` for a native inline MCP image block.
|
|
130
|
+
7. If a host such as Claude.ai replaces the native block with `[image]`, retry with `type = "base64"`; this host-independent fallback returns the complete JSON, including raw `data`, in a regular MCP text block.
|
|
131
|
+
8. If the user asks for the most recent existing screenshot, `get_file(selector = "latest_screenshot")` is the direct shortcut.
|
|
115
132
|
|
|
116
133
|
## `set_session_context`
|
|
117
134
|
|
|
@@ -190,6 +207,99 @@ Output:
|
|
|
190
207
|
- `terminal?`
|
|
191
208
|
Terminal runtime metadata for the console.
|
|
192
209
|
|
|
210
|
+
## `get_file_list`
|
|
211
|
+
|
|
212
|
+
Purpose:
|
|
213
|
+
|
|
214
|
+
- List managed files available in a selected console workspace before calling `get_file`.
|
|
215
|
+
- Return exact `file_path` values accepted by `get_file`.
|
|
216
|
+
|
|
217
|
+
Input:
|
|
218
|
+
|
|
219
|
+
- `session_id`
|
|
220
|
+
- `source?`
|
|
221
|
+
- `telegram-upload`
|
|
222
|
+
- `browser-screenshot`
|
|
223
|
+
- `partner-artifact`
|
|
224
|
+
- `limit?`
|
|
225
|
+
- default: `50`
|
|
226
|
+
- maximum: `200`
|
|
227
|
+
|
|
228
|
+
Output:
|
|
229
|
+
|
|
230
|
+
- `total`
|
|
231
|
+
- `files[]`
|
|
232
|
+
- `file_path`
|
|
233
|
+
- `filename`
|
|
234
|
+
- `mimetype`
|
|
235
|
+
- `source`
|
|
236
|
+
- `size_bytes?`
|
|
237
|
+
- `created_at`
|
|
238
|
+
|
|
239
|
+
Behavior:
|
|
240
|
+
|
|
241
|
+
- results are ordered newest first
|
|
242
|
+
- `total` is the number of matching managed files before `limit` is applied
|
|
243
|
+
- this tool lists TellyMCP-managed Telegram uploads, browser screenshots, and partner artifacts; it does not recursively enumerate arbitrary source files in the workspace
|
|
244
|
+
- in gateway mode, always pass the canonical `session_id = client_uuid:local_session_id`
|
|
245
|
+
- pass the chosen `files[].file_path` unchanged to `get_file`
|
|
246
|
+
|
|
247
|
+
## `get_file`
|
|
248
|
+
|
|
249
|
+
Purpose:
|
|
250
|
+
|
|
251
|
+
- Return the actual content of a file from a selected console workspace to an MCP chat client.
|
|
252
|
+
- URL mode creates a bounded temporary gateway copy; text and base64 modes relay content directly.
|
|
253
|
+
|
|
254
|
+
Input:
|
|
255
|
+
|
|
256
|
+
- `session_id`
|
|
257
|
+
- `type?`
|
|
258
|
+
- `url` (default)
|
|
259
|
+
- `image` (native inline image plus download URL)
|
|
260
|
+
- `text` (native UTF-8 MCP text content)
|
|
261
|
+
- `base64` (fallback)
|
|
262
|
+
- exactly one of:
|
|
263
|
+
- `file_path`
|
|
264
|
+
- `selector = "latest_screenshot"`
|
|
265
|
+
|
|
266
|
+
Output:
|
|
267
|
+
|
|
268
|
+
- `type`
|
|
269
|
+
- `data`
|
|
270
|
+
- short-lived HTTPS URL when `type = "url"`
|
|
271
|
+
- short-lived HTTPS URL when `type = "image"`; the actual pixels are in the native MCP image content block
|
|
272
|
+
- decoded UTF-8 file content when `type = "text"`
|
|
273
|
+
- base64 payload when `type = "base64"`
|
|
274
|
+
- `mimetype`
|
|
275
|
+
- `filename`
|
|
276
|
+
- `size_bytes`
|
|
277
|
+
- `expires_at?`
|
|
278
|
+
|
|
279
|
+
Behavior:
|
|
280
|
+
|
|
281
|
+
- in gateway mode, always pass the canonical `session_id = client_uuid:local_session_id` returned by `list_gateway_sessions`
|
|
282
|
+
- `file_path` may be the exact path returned by `browser_screenshot`, so the human does not need to know generated filenames
|
|
283
|
+
- `selector = "latest_screenshot"` selects the newest file metadata with `source = "browser-screenshot"` for that session
|
|
284
|
+
- file reads are limited to the selected console workspace, including after symlink resolution
|
|
285
|
+
- exact project-relative paths such as `README.md` or `src/test.ts` are accepted even though `get_file_list` only discovers managed artifacts
|
|
286
|
+
- text mode returns the decoded file directly as a native MCP text content block and rejects invalid UTF-8 or binary NUL content
|
|
287
|
+
- source extensions such as `.ts` and `.tsx` use text MIME overrides instead of the generic MPEG/octet-stream mappings
|
|
288
|
+
- sensitive paths including live `.env` files, credential stores, private-key extensions, and secret directories are rejected server-side; documented `.env.example`/`.env.sample`/`.env.template` files remain readable
|
|
289
|
+
- URL mode uploads the file as a binary stream to `.tellymcp/tmp/file-links` on the gateway and returns a link valid for 10 minutes
|
|
290
|
+
- image mode is explicit: `structuredContent.type` is `image`, `structuredContent.data` contains the URL, and the native top-level MCP `image` is the first content block without duplicating base64 into structured output
|
|
291
|
+
- image mode accepts only `image/*` files up to the safe native-inline limit; use `url` for larger images
|
|
292
|
+
- URL links allow up to three GET downloads; HEAD requests do not consume the limit
|
|
293
|
+
- if URL fetching fails for an image, retry with `type = "image"`
|
|
294
|
+
- base64 mode is the compatibility fallback for hosts that replace native images with `[image]` or hide `structuredContent`: it returns the complete JSON payload, including raw base64 in `data`, as a regular MCP text block and does not emit a native image
|
|
295
|
+
- base64 mode is bounded by the final MCP response body limit
|
|
296
|
+
- do not attempt to bypass the sensitive-file policy or retrieve renamed secrets
|
|
297
|
+
|
|
298
|
+
Screenshot examples:
|
|
299
|
+
|
|
300
|
+
- "take a screenshot and send it": call `browser_screenshot`, then pass its returned `file_path` to `get_file`
|
|
301
|
+
- "send the latest screenshot": call `get_file` with `selector = "latest_screenshot"`
|
|
302
|
+
|
|
193
303
|
## `refresh_tools_markdown`
|
|
194
304
|
|
|
195
305
|
Purpose:
|
|
@@ -447,7 +557,7 @@ Required agent practice:
|
|
|
447
557
|
- "tell frontend what changed"
|
|
448
558
|
- "send the error to your teammate"
|
|
449
559
|
- "tell the other agent what's new"
|
|
450
|
-
|
|
560
|
+
then the correct path is `send_partner_note`
|
|
451
561
|
|
|
452
562
|
How to find the partner correctly:
|
|
453
563
|
|
|
@@ -507,7 +617,7 @@ Reply rule for project asks:
|
|
|
507
617
|
- `Reply project_uuid: ...`
|
|
508
618
|
- `Reply target_client_uuid: ...`
|
|
509
619
|
- `Reply target_local_session_id: ...`
|
|
510
|
-
|
|
620
|
+
or a `Reply Params` section with the same data
|
|
511
621
|
- then reply with those exact values
|
|
512
622
|
- if `in_reply_to` is available, prefer `Reply message_uuid`
|
|
513
623
|
- if only the note `share_id` is available, gateway now also accepts that value in `in_reply_to`
|
|
@@ -608,7 +718,7 @@ How the receiving agent must react:
|
|
|
608
718
|
- `проверь xchange records`
|
|
609
719
|
- `telegram_message`
|
|
610
720
|
- `partner_note`
|
|
611
|
-
|
|
721
|
+
then do not start with a legacy inbox-specific tool
|
|
612
722
|
- instead:
|
|
613
723
|
1. call `list_xchange_records`
|
|
614
724
|
2. identify the newest relevant record by category:
|
|
@@ -836,10 +946,68 @@ Output:
|
|
|
836
946
|
Notes:
|
|
837
947
|
|
|
838
948
|
- if only one attached browser instance is connected, `instance_id` can be omitted
|
|
839
|
-
-
|
|
949
|
+
- tab selection for the attach backend can be done either from the browser extension control panel or through `browser_attach_active_tab` / `browser_attach_tab`
|
|
840
950
|
- `active=true` means the tab is active in its browser window; there may be more than one such tab across multiple windows
|
|
841
951
|
- for the tab currently selected for this MCP session, prefer `selected=true`
|
|
842
952
|
|
|
953
|
+
## `browser_attach_active_tab`
|
|
954
|
+
|
|
955
|
+
Purpose:
|
|
956
|
+
|
|
957
|
+
- attach the current MCP session to the active tab of a connected attached browser instance
|
|
958
|
+
|
|
959
|
+
Input:
|
|
960
|
+
|
|
961
|
+
- `session_id?`
|
|
962
|
+
- `instance_id?`
|
|
963
|
+
|
|
964
|
+
Output:
|
|
965
|
+
|
|
966
|
+
- `session_id`
|
|
967
|
+
- `backend`
|
|
968
|
+
- `instance_id`
|
|
969
|
+
- `tab_id`
|
|
970
|
+
- `attached_at`
|
|
971
|
+
- `title?`
|
|
972
|
+
- `url?`
|
|
973
|
+
|
|
974
|
+
## `browser_attach_tab`
|
|
975
|
+
|
|
976
|
+
Purpose:
|
|
977
|
+
|
|
978
|
+
- attach the current MCP session to a specific attached browser tab by `tab_id`
|
|
979
|
+
|
|
980
|
+
Input:
|
|
981
|
+
|
|
982
|
+
- `session_id?`
|
|
983
|
+
- `instance_id?`
|
|
984
|
+
- `tab_id`
|
|
985
|
+
|
|
986
|
+
Output:
|
|
987
|
+
|
|
988
|
+
- `session_id`
|
|
989
|
+
- `backend`
|
|
990
|
+
- `instance_id`
|
|
991
|
+
- `tab_id`
|
|
992
|
+
- `attached_at`
|
|
993
|
+
- `title?`
|
|
994
|
+
- `url?`
|
|
995
|
+
|
|
996
|
+
## `browser_detach_tab`
|
|
997
|
+
|
|
998
|
+
Purpose:
|
|
999
|
+
|
|
1000
|
+
- detach the current MCP session from the currently selected attached browser tab
|
|
1001
|
+
|
|
1002
|
+
Input:
|
|
1003
|
+
|
|
1004
|
+
- `session_id?`
|
|
1005
|
+
|
|
1006
|
+
Output:
|
|
1007
|
+
|
|
1008
|
+
- `session_id`
|
|
1009
|
+
- `detached`
|
|
1010
|
+
|
|
843
1011
|
## `browser_recording_start`
|
|
844
1012
|
|
|
845
1013
|
Purpose:
|
|
@@ -1227,6 +1395,8 @@ Output:
|
|
|
1227
1395
|
Purpose:
|
|
1228
1396
|
|
|
1229
1397
|
- inspect computed styles and box metrics for a DOM element in the session browser tab
|
|
1398
|
+
- if the session has a selected attached browser tab, inspect that real browser tab
|
|
1399
|
+
- otherwise inspect the isolated Playwright page
|
|
1230
1400
|
|
|
1231
1401
|
Input:
|
|
1232
1402
|
|
|
@@ -1284,7 +1454,9 @@ Notes:
|
|
|
1284
1454
|
|
|
1285
1455
|
Purpose:
|
|
1286
1456
|
|
|
1287
|
-
- close the
|
|
1457
|
+
- close the current browser target for the session
|
|
1458
|
+
- if the session has a selected attached browser tab, close that real browser tab and clear the attach state
|
|
1459
|
+
- otherwise close the isolated Playwright browser context
|
|
1288
1460
|
|
|
1289
1461
|
Input:
|
|
1290
1462
|
|
|
@@ -29,13 +29,27 @@ MCP_HTTP_PATH=/mcp
|
|
|
29
29
|
MCP_HTTP_ENABLE_DEBUG_ROUTES=false
|
|
30
30
|
MCP_HTTP_ENABLE_PRUNE_ROUTE=false
|
|
31
31
|
|
|
32
|
+
# ChatGPT / Claude OAuth connector. Setting any OAuth value enables the facade.
|
|
33
|
+
# TELLYMCP_PUBLIC_URL=https://your-domain.example/api
|
|
34
|
+
# TELLYMCP_OAUTH_ISSUER=https://your-domain.example/api
|
|
35
|
+
# TELLYMCP_OAUTH_AUDIENCE=https://your-domain.example/api
|
|
36
|
+
# TELLYMCP_MAGIC_TOKEN=change_me_private_connector_token
|
|
37
|
+
# TELLYMCP_MAGIC_TOKEN_HASH=sha256:<hex>
|
|
38
|
+
# TELLYMCP_OAUTH_CLIENT_ID=tellymcp
|
|
39
|
+
# TELLYMCP_OAUTH_CLIENT_SECRET=
|
|
40
|
+
# TELLYMCP_ALLOWED_REDIRECT_URIS=https://chatgpt.com/connector/oauth/...,https://claude.ai/api/mcp/auth_callback
|
|
41
|
+
# TELLYMCP_OAUTH_PRIVATE_KEY_PEM="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
|
|
42
|
+
# TELLYMCP_AUTH_CODE_TTL_SECONDS=300
|
|
43
|
+
# TELLYMCP_OAUTH_SCOPES=tellymcp:read tellymcp:write
|
|
44
|
+
# TELLYMCP_OAUTH_KEY_ID=tellymcp-oauth
|
|
45
|
+
|
|
32
46
|
DISTRIBUTED_MODE=both
|
|
33
47
|
GATEWAY_PUBLIC_URL=
|
|
34
48
|
GATEWAY_WS_URL=
|
|
35
49
|
GATEWAY_WS_PATH=/api/gateway/ws
|
|
36
50
|
GATEWAY_TOKEN=
|
|
37
51
|
GATEWAY_USER_UUID=
|
|
38
|
-
|
|
52
|
+
GATEWAY_AUTH_TOKEN=
|
|
39
53
|
|
|
40
54
|
ROOT_PREFIX=/api
|
|
41
55
|
PORT=8080
|
|
@@ -63,7 +77,6 @@ WEBAPP_INITDATA_TTL_SECONDS=300
|
|
|
63
77
|
WEBAPP_SESSION_TTL_SECONDS=900
|
|
64
78
|
WEBAPP_LAUNCH_MODE=fullscreen
|
|
65
79
|
WEBAPP_VISIBLE_SCREENS=10
|
|
66
|
-
WEBAPP_POLL_INTERVAL_MS=2000
|
|
67
80
|
WEBAPP_ACTION_COOLDOWN_MS=150
|
|
68
81
|
|
|
69
82
|
MCP_XCHANGE_DIR=.mcp-xchange
|
|
@@ -24,7 +24,7 @@ GATEWAY_WS_URL=
|
|
|
24
24
|
GATEWAY_WS_PATH=/api/gateway/ws
|
|
25
25
|
GATEWAY_TOKEN=
|
|
26
26
|
GATEWAY_USER_UUID=
|
|
27
|
-
|
|
27
|
+
GATEWAY_AUTH_TOKEN=
|
|
28
28
|
|
|
29
29
|
TERMINAL_SHELL=bash
|
|
30
30
|
TERMINAL_COLS=120
|
|
@@ -51,7 +51,6 @@ WEBAPP_INITDATA_TTL_SECONDS=300
|
|
|
51
51
|
WEBAPP_SESSION_TTL_SECONDS=900
|
|
52
52
|
WEBAPP_LAUNCH_MODE=fullscreen
|
|
53
53
|
WEBAPP_VISIBLE_SCREENS=10
|
|
54
|
-
WEBAPP_POLL_INTERVAL_MS=2000
|
|
55
54
|
WEBAPP_ACTION_COOLDOWN_MS=150
|
|
56
55
|
|
|
57
56
|
MCP_XCHANGE_DIR=.mcp-xchange
|
|
@@ -66,6 +65,10 @@ BROWSER_WAIT_UNTIL=load
|
|
|
66
65
|
# BROWSER_EXECUTABLE_PATH=
|
|
67
66
|
# BROWSER_CHANNEL=chrome
|
|
68
67
|
BROWSER_SLOW_MO_MS=0
|
|
68
|
+
# BROWSER_ATTACH_ENABLED=true
|
|
69
|
+
# BROWSER_ATTACH_WS_HOST=127.0.0.1
|
|
70
|
+
# BROWSER_ATTACH_WS_PORT=9999
|
|
71
|
+
# BROWSER_ATTACH_WS_PATH=/browser-attach/ws
|
|
69
72
|
|
|
70
73
|
NAMESPACE=mcp
|
|
71
74
|
NODE_ID=agent
|
|
@@ -25,12 +25,26 @@ MCP_HTTP_PATH=/mcp
|
|
|
25
25
|
MCP_HTTP_ENABLE_DEBUG_ROUTES=false
|
|
26
26
|
MCP_HTTP_ENABLE_PRUNE_ROUTE=false
|
|
27
27
|
|
|
28
|
+
# ChatGPT / Claude OAuth connector. Setting any OAuth value enables the facade.
|
|
29
|
+
# TELLYMCP_PUBLIC_URL=https://your-domain.example/api
|
|
30
|
+
# TELLYMCP_OAUTH_ISSUER=https://your-domain.example/api
|
|
31
|
+
# TELLYMCP_OAUTH_AUDIENCE=https://your-domain.example/api
|
|
32
|
+
# TELLYMCP_MAGIC_TOKEN=change_me_private_connector_token
|
|
33
|
+
# TELLYMCP_MAGIC_TOKEN_HASH=sha256:<hex>
|
|
34
|
+
# TELLYMCP_OAUTH_CLIENT_ID=tellymcp
|
|
35
|
+
# TELLYMCP_OAUTH_CLIENT_SECRET=
|
|
36
|
+
# TELLYMCP_ALLOWED_REDIRECT_URIS=https://chatgpt.com/connector/oauth/...,https://claude.ai/api/mcp/auth_callback
|
|
37
|
+
# TELLYMCP_OAUTH_PRIVATE_KEY_PEM="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
|
|
38
|
+
# TELLYMCP_AUTH_CODE_TTL_SECONDS=300
|
|
39
|
+
# TELLYMCP_OAUTH_SCOPES=tellymcp:read tellymcp:write
|
|
40
|
+
# TELLYMCP_OAUTH_KEY_ID=tellymcp-oauth
|
|
41
|
+
|
|
28
42
|
DISTRIBUTED_MODE=gateway
|
|
29
43
|
GATEWAY_PUBLIC_URL=
|
|
30
44
|
GATEWAY_WS_URL=
|
|
31
45
|
GATEWAY_WS_PATH=/api/gateway/ws
|
|
32
46
|
GATEWAY_TOKEN=
|
|
33
|
-
|
|
47
|
+
GATEWAY_AUTH_TOKEN=
|
|
34
48
|
|
|
35
49
|
ROOT_PREFIX=/api
|
|
36
50
|
PORT=8080
|
|
@@ -58,7 +72,6 @@ WEBAPP_INITDATA_TTL_SECONDS=300
|
|
|
58
72
|
WEBAPP_SESSION_TTL_SECONDS=900
|
|
59
73
|
WEBAPP_LAUNCH_MODE=fullscreen
|
|
60
74
|
WEBAPP_VISIBLE_SCREENS=10
|
|
61
|
-
WEBAPP_POLL_INTERVAL_MS=2000
|
|
62
75
|
WEBAPP_ACTION_COOLDOWN_MS=150
|
|
63
76
|
|
|
64
77
|
MCP_XCHANGE_DIR=.mcp-xchange
|
package/dist/cli.js
CHANGED
|
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
const node_fs_1 = require("node:fs");
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const node_child_process_1 = require("node:child_process");
|
|
10
|
+
const node_crypto_1 = require("node:crypto");
|
|
10
11
|
const node_net_1 = __importDefault(require("node:net"));
|
|
11
12
|
const dotenv_1 = require("dotenv");
|
|
12
13
|
const ioredis_1 = __importDefault(require("ioredis"));
|
|
@@ -77,6 +78,7 @@ function printHelp() {
|
|
|
77
78
|
" tellymcp codex-plugin install",
|
|
78
79
|
" tellymcp codex-plugin status",
|
|
79
80
|
" tellymcp mcp [--url <url>] [--bearer <token>] [--format claude|legacy]",
|
|
81
|
+
" tellymcp oauth key",
|
|
80
82
|
" tellymcp help",
|
|
81
83
|
]);
|
|
82
84
|
printSection("Examples", [
|
|
@@ -94,6 +96,7 @@ function printHelp() {
|
|
|
94
96
|
" tellymcp codex-plugin install",
|
|
95
97
|
" tellymcp codex-plugin status",
|
|
96
98
|
" tellymcp mcp --help",
|
|
99
|
+
" tellymcp oauth key",
|
|
97
100
|
]);
|
|
98
101
|
printSection("terminal", [
|
|
99
102
|
`${picocolors_1.default.green(" OK")} built-in PTY runtime`,
|
|
@@ -238,6 +241,26 @@ function printMcpHelp() {
|
|
|
238
241
|
" tellymcp mcp --url https://builder.undoo.ru/api/mcp --format legacy",
|
|
239
242
|
]);
|
|
240
243
|
}
|
|
244
|
+
function runOAuthCommand(args) {
|
|
245
|
+
const [subcommand] = args;
|
|
246
|
+
if (!subcommand || subcommand === "--help" || subcommand === "-h") {
|
|
247
|
+
printBanner("OAuth helper", "Generate connector signing material");
|
|
248
|
+
printSection("Usage", [" tellymcp oauth key"]);
|
|
249
|
+
printSection("Output", [
|
|
250
|
+
" Prints a dotenv-ready TELLYMCP_OAUTH_PRIVATE_KEY_PEM value.",
|
|
251
|
+
" Store it only on the gateway and never expose it to chat clients.",
|
|
252
|
+
]);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
if (subcommand !== "key") {
|
|
256
|
+
fail("Supported OAuth subcommands: key");
|
|
257
|
+
}
|
|
258
|
+
const privateKeyPem = (0, node_crypto_1.generateKeyPairSync)("rsa", { modulusLength: 2048 })
|
|
259
|
+
.privateKey.export({ type: "pkcs8", format: "pem" })
|
|
260
|
+
.toString()
|
|
261
|
+
.replace(/\n/gu, "\\n");
|
|
262
|
+
process.stdout.write(`TELLYMCP_OAUTH_PRIVATE_KEY_PEM="${privateKeyPem}"\n`);
|
|
263
|
+
}
|
|
241
264
|
function printBrowserHelp() {
|
|
242
265
|
printBanner("browser helper", "Manage Playwright browser binaries used by browser_* tools");
|
|
243
266
|
printSection("Usage", [
|
|
@@ -1045,7 +1068,7 @@ async function runRuntime(args) {
|
|
|
1045
1068
|
}
|
|
1046
1069
|
async function main(argv) {
|
|
1047
1070
|
const [rawCommand, firstArg, secondArg] = argv;
|
|
1048
|
-
const command = rawCommand === "init" || rawCommand === "run" || rawCommand === "help" || rawCommand === "mcp" || rawCommand === "doctor" || rawCommand === "browser" || rawCommand === "system-prune"
|
|
1071
|
+
const command = rawCommand === "init" || rawCommand === "run" || rawCommand === "help" || rawCommand === "mcp" || rawCommand === "oauth" || rawCommand === "doctor" || rawCommand === "browser" || rawCommand === "system-prune"
|
|
1049
1072
|
|| rawCommand === "codex-plugin" || rawCommand === "extension"
|
|
1050
1073
|
? rawCommand
|
|
1051
1074
|
: "help";
|
|
@@ -1061,6 +1084,10 @@ async function main(argv) {
|
|
|
1061
1084
|
printMcpConfig(argv.slice(1));
|
|
1062
1085
|
return;
|
|
1063
1086
|
}
|
|
1087
|
+
if (command === "oauth") {
|
|
1088
|
+
runOAuthCommand(argv.slice(1));
|
|
1089
|
+
return;
|
|
1090
|
+
}
|
|
1064
1091
|
if (command === "doctor") {
|
|
1065
1092
|
await runDoctor(argv.slice(1));
|
|
1066
1093
|
return;
|