@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.
Files changed (153) hide show
  1. package/.env.example.client +42 -52
  2. package/.env.example.gateway +48 -62
  3. package/CHANGELOG.md +3 -3
  4. package/README-ru.md +205 -384
  5. package/README.md +195 -1194
  6. package/TOOLS.md +294 -377
  7. package/VERSION.md +11 -11
  8. package/config/codex/plugins/telly-workflows/.codex-plugin/plugin.json +18 -0
  9. package/config/codex/plugins/telly-workflows/references/invariants.md +10 -0
  10. package/config/codex/plugins/telly-workflows/skills/telly-browser-screenshot/SKILL.md +27 -0
  11. package/config/codex/plugins/telly-workflows/skills/telly-collab-artifact/SKILL.md +22 -0
  12. package/config/codex/plugins/telly-workflows/skills/telly-human-telegram/SKILL.md +31 -0
  13. package/config/codex/plugins/telly-workflows/skills/telly-partner-note/SKILL.md +36 -0
  14. package/config/templates/env.both.template +39 -20
  15. package/config/templates/env.client.template +34 -19
  16. package/config/templates/env.gateway.template +37 -22
  17. package/dist/cli.js +322 -75
  18. package/dist/codexPluginInstaller.js +215 -0
  19. package/dist/lib/mixins/session.errors.js +34 -1
  20. package/dist/lib/pinoTargets.js +2 -2
  21. package/dist/moleculer.config.js +7 -5
  22. package/dist/services/features/telegram-mcp/browser.service.js +94 -1
  23. package/dist/services/features/telegram-mcp/collaboration.service.js +40 -3
  24. package/dist/services/features/telegram-mcp/ensuredb.service.js +145 -26
  25. package/dist/services/features/telegram-mcp/gateway-delivery.service.js +285 -103
  26. package/dist/services/features/telegram-mcp/gateway-socket.service.js +897 -85
  27. package/dist/services/features/telegram-mcp/gateway.service.js +876 -81
  28. package/dist/services/features/telegram-mcp/mcp-http.service.js +8 -0
  29. package/dist/services/features/telegram-mcp/mcp-server.service.js +17 -26
  30. package/dist/services/features/telegram-mcp/notify.service.js +127 -1
  31. package/dist/services/features/telegram-mcp/session-context.service.js +28 -1
  32. package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +132 -10
  33. package/dist/services/features/telegram-mcp/src/app/config/env.js +158 -52
  34. package/dist/services/features/telegram-mcp/src/app/http.js +375 -42
  35. package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +386 -58
  36. package/dist/services/features/telegram-mcp/src/app/webapp/auth.js +3 -0
  37. package/dist/services/features/telegram-mcp/src/app/webapp/terminal.js +12 -0
  38. package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +116 -104
  39. package/dist/services/features/telegram-mcp/src/entities/xchange/model/types.js +2 -0
  40. package/dist/services/features/telegram-mcp/src/features/ask-user/model/askUserTelegram.js +1 -1
  41. package/dist/services/features/telegram-mcp/src/features/browser/model/browserScreenshotTool.js +1 -1
  42. package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +249 -19
  43. package/dist/services/features/telegram-mcp/src/features/collaboration/model/gatewaySessionsService.js +71 -0
  44. package/dist/services/features/telegram-mcp/src/features/collaboration/model/listGatewaySessionsTool.js +33 -0
  45. package/dist/services/features/telegram-mcp/src/features/collaboration/model/localCollaborationBackend.js +93 -82
  46. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +47 -5
  47. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileTool.js +1 -1
  48. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerNoteTool.js +1 -1
  49. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayClientAccess.js +82 -0
  50. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayCollaborationBackend.js +22 -14
  51. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +649 -75
  52. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/remoteConsoleActionClient.js +76 -0
  53. package/dist/services/features/telegram-mcp/src/features/embedded-runtime/model/embeddedRuntimeBroker.js +92 -0
  54. package/dist/services/features/telegram-mcp/src/features/foreground-terminal/model/foregroundTerminalRuntime.js +192 -0
  55. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +382 -3
  56. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyTelegramTool.js +1 -1
  57. package/dist/services/features/telegram-mcp/src/features/notify/model/sendFileToTelegramTool.js +33 -0
  58. package/dist/services/features/telegram-mcp/src/features/session-context/model/clearSessionContextTool.js +1 -1
  59. package/dist/services/features/telegram-mcp/src/features/session-context/model/getSessionContextTool.js +1 -1
  60. package/dist/services/features/telegram-mcp/src/features/session-context/model/renameSessionTool.js +1 -1
  61. package/dist/services/features/telegram-mcp/src/features/session-context/model/sessionContextService.js +42 -200
  62. package/dist/services/features/telegram-mcp/src/features/session-context/model/setSessionContextTool.js +1 -1
  63. package/dist/services/features/telegram-mcp/src/features/terminal-buffer/model/terminalBufferService.js +96 -0
  64. package/dist/services/features/telegram-mcp/src/features/terminal-input/model/terminalInputService.js +97 -0
  65. package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownService.js +107 -58
  66. package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownTool.js +1 -1
  67. package/dist/services/features/telegram-mcp/src/features/xchange/model/getXchangeRecordTool.js +28 -0
  68. package/dist/services/features/telegram-mcp/src/features/xchange/model/listXchangeRecordsTool.js +28 -0
  69. package/dist/services/features/telegram-mcp/src/features/xchange/model/markXchangeRecordReadTool.js +28 -0
  70. package/dist/services/features/telegram-mcp/src/features/xchange/model/xchangeService.js +169 -0
  71. package/dist/services/features/telegram-mcp/src/processes/human-approval/model/orchestrator.js +5 -4
  72. package/dist/services/features/telegram-mcp/src/shared/i18n/resources/en.js +139 -42
  73. package/dist/services/features/telegram-mcp/src/shared/i18n/resources/ru.js +135 -38
  74. package/dist/services/features/telegram-mcp/src/shared/integrations/memory/processLocalSessionStore.js +27 -0
  75. package/dist/services/features/telegram-mcp/src/shared/integrations/object-storage/minioExchangeStore.js +11 -8
  76. package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +42 -71
  77. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/proxyFetch.js +21 -22
  78. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +415 -7101
  79. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportAttachmentStore.js +93 -0
  80. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportBroadcastActions.js +385 -0
  81. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConsoleRegistry.js +143 -0
  82. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConstructorWiring.js +633 -0
  83. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContent.js +84 -0
  84. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContext.js +78 -0
  85. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportDocumentActions.js +36 -0
  86. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportEventActions.js +292 -0
  87. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFileHandoffActions.js +352 -0
  88. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFormatting.js +75 -0
  89. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportGatewayActions.js +44 -0
  90. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLifecycleActions.js +161 -0
  91. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLive.js +56 -0
  92. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLiveActions.js +77 -0
  93. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuCallbacks.js +254 -0
  94. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFactories.js +538 -0
  95. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFingerprints.js +93 -0
  96. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFlow.js +344 -0
  97. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuShell.js +62 -0
  98. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuState.js +408 -0
  99. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuText.js +216 -0
  100. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMessageFlow.js +452 -0
  101. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportOutputActions.js +189 -0
  102. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPartnerActions.js +286 -0
  103. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPayloadState.js +101 -0
  104. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectActions.js +463 -0
  105. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEntryActions.js +202 -0
  106. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEvents.js +99 -0
  107. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectMenus.js +138 -0
  108. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectState.js +308 -0
  109. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectView.js +426 -0
  110. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportRequestFlow.js +278 -0
  111. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportSessionActions.js +143 -0
  112. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalActions.js +468 -0
  113. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalRuntime.js +171 -0
  114. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTypes.js +2 -0
  115. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportUtils.js +330 -0
  116. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportXchangeState.js +107 -0
  117. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/client.js +255 -0
  118. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/ptyRegistry.js +543 -0
  119. package/dist/services/features/telegram-mcp/src/shared/integrations/xchange/sqliteRecordStore.js +223 -0
  120. package/dist/services/features/telegram-mcp/src/shared/lib/gatewayScope.js +24 -0
  121. package/dist/services/features/telegram-mcp/src/shared/lib/logger/logger.js +6 -0
  122. package/dist/services/features/telegram-mcp/src/shared/lib/project-identity/projectIdentity.js +147 -76
  123. package/dist/services/features/telegram-mcp/src/shared/lib/telegramXchangeRecords.js +72 -0
  124. package/dist/services/features/telegram-mcp/src/shared/lib/terminalPromptDetection.js +237 -0
  125. package/dist/services/features/telegram-mcp/src/shared/lib/version/versionHandshake.js +129 -1
  126. package/dist/services/features/telegram-mcp/src/shared/lib/xchangeRecordHints.js +98 -0
  127. package/dist/services/features/telegram-mcp/standalone-http.service.js +12 -0
  128. package/dist/services/features/telegram-mcp/terminal-buffer.service.js +42 -0
  129. package/dist/services/features/telegram-mcp/terminal-input.service.js +41 -0
  130. package/dist/services/features/telegram-mcp/tools-sync.service.js +15 -1
  131. package/dist/services/features/telegram-mcp/xchange.service.js +123 -0
  132. package/docs/STANDALONE-ru.md +172 -0
  133. package/docs/STANDALONE.md +172 -0
  134. package/package.json +10 -5
  135. package/scripts/build-package-artifact.sh +27 -0
  136. package/scripts/deploy-gateway.sh +64 -0
  137. package/scripts/deploy-onebot-branch.sh +27 -0
  138. package/scripts/postinstall.js +11 -36
  139. package/STANDALONE-ru.md +0 -274
  140. package/STANDALONE.md +0 -274
  141. package/dist/services/features/telegram-mcp/inbox.service.js +0 -33
  142. package/dist/services/features/telegram-mcp/pair.service.js +0 -33
  143. package/dist/services/features/telegram-mcp/src/app/webapp/tmux.js +0 -10
  144. package/dist/services/features/telegram-mcp/src/features/inbox/model/deleteTelegramInboxMessageTool.js +0 -33
  145. package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxCountTool.js +0 -33
  146. package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxTool.js +0 -33
  147. package/dist/services/features/telegram-mcp/src/features/inbox/model/inboxService.js +0 -77
  148. package/dist/services/features/telegram-mcp/src/features/pair-session/model/clearSessionPairingTool.js +0 -33
  149. package/dist/services/features/telegram-mcp/src/features/pair-session/model/createSessionPairCodeTool.js +0 -33
  150. package/dist/services/features/telegram-mcp/src/features/pair-session/model/generatePairCode.js +0 -202
  151. package/dist/services/features/telegram-mcp/src/features/session-context/model/getTmuxTargetTool.js +0 -33
  152. package/dist/services/features/telegram-mcp/src/features/session-context/model/setTmuxTargetTool.js +0 -33
  153. package/dist/services/features/telegram-mcp/src/shared/integrations/tmux/client.js +0 -363
@@ -36,9 +36,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.loadConfig = loadConfig;
37
37
  const node_fs_1 = require("node:fs");
38
38
  const z = __importStar(require("zod/v4"));
39
+ const emptyStringToUndefined = (value) => {
40
+ if (typeof value !== "string") {
41
+ return value;
42
+ }
43
+ const trimmed = value.trim();
44
+ return trimmed === "" ? undefined : trimmed;
45
+ };
46
+ const optionalNonEmptyString = z.preprocess(emptyStringToUndefined, z.string().min(1).optional());
47
+ const optionalUrlString = z.preprocess(emptyStringToUndefined, z.string().url().optional());
39
48
  const envSchema = z.object({
40
- TELEGRAM_BOT_TOKEN: z.string().min(1),
41
- TELEGRAM_BOT_USERNAME: z.string().min(1).optional(),
49
+ TELEGRAM_BOT_TOKEN: optionalNonEmptyString,
50
+ TELEGRAM_BOT_USERNAME: optionalNonEmptyString,
51
+ ADMIN_TOKEN: optionalNonEmptyString,
42
52
  TELEGRAM_POLL_INTERVAL_MS: z.coerce.number().int().positive().default(2000),
43
53
  TELEGRAM_DEFAULT_TIMEOUT_SECONDS: z.coerce
44
54
  .number()
@@ -48,30 +58,41 @@ const envSchema = z.object({
48
58
  TELEGRAM_MAX_CONTEXT_CHARS: z.coerce.number().int().positive().default(3000),
49
59
  TELEGRAM_MAX_QUESTION_CHARS: z.coerce.number().int().positive().default(1000),
50
60
  TELEGRAM_MAX_MESSAGE_CHARS: z.coerce.number().int().positive().default(3900),
51
- TELEGRAM_INBOX_BATCH_SIZE: z.coerce
52
- .number()
53
- .int()
54
- .positive()
55
- .max(100)
56
- .default(20),
57
61
  TELEGRAM_MENU_PAYLOAD_TTL_SECONDS: z.coerce
58
62
  .number()
59
63
  .int()
60
64
  .positive()
61
65
  .default(300),
62
- DEBUG_LANGUAGE: z.enum(["en", "ru"]).optional(),
66
+ TELEGRAM_WEBHOOK_ENABLED: z
67
+ .string()
68
+ .optional()
69
+ .transform((value) => value === "true"),
70
+ TELEGRAM_WEBHOOK_PATH: z.string().min(1).default("/telegram/webhook"),
71
+ TELEGRAM_WEBHOOK_PUBLIC_URL: optionalUrlString,
72
+ TELEGRAM_WEBHOOK_SECRET: optionalNonEmptyString,
73
+ TELEGRAM_WEBHOOK_TRACE: z
74
+ .string()
75
+ .optional()
76
+ .transform((value) => value === "true"),
77
+ TELEGRAM_WEBHOOK_DROP_PENDING_UPDATES: z
78
+ .string()
79
+ .optional()
80
+ .transform((value) => value === "true"),
81
+ DEBUG_LANGUAGE: z.preprocess(emptyStringToUndefined, z.enum(["en", "ru"]).optional()),
63
82
  REDIS_HOST: z.string().min(1),
64
83
  REDIS_PORT: z.coerce.number().int().positive(),
65
84
  REDIS_DB: z.coerce.number().int().nonnegative(),
66
- REDIS_USERNAME: z.string().min(1).optional(),
67
- REDIS_PASSWORD: z.string().min(1).optional(),
85
+ REDIS_USERNAME: optionalNonEmptyString,
86
+ REDIS_PASSWORD: optionalNonEmptyString,
68
87
  MODE: z.enum(["queue", "reject"]).default("queue"),
69
88
  PAIR_CODE_TTL_SECONDS: z.coerce.number().int().positive().default(600),
70
- PROJECT_NAME: z.string().min(1).optional(),
89
+ PROJECT_NAME: optionalNonEmptyString,
90
+ TELLYMCP_SESSION_ID: optionalNonEmptyString,
91
+ TELLYMCP_SESSION_LABEL: optionalNonEmptyString,
71
92
  MCP_HTTP_HOST: z.string().min(1).default("127.0.0.1"),
72
93
  MCP_HTTP_PORT: z.coerce.number().int().positive().default(8787),
73
94
  MCP_HTTP_PATH: z.string().min(1).default("/mcp"),
74
- MCP_HTTP_BEARER_TOKEN: z.string().min(1).optional(),
95
+ MCP_HTTP_BEARER_TOKEN: optionalNonEmptyString,
75
96
  MCP_HTTP_ENABLE_DEBUG_ROUTES: z
76
97
  .string()
77
98
  .optional()
@@ -82,32 +103,34 @@ const envSchema = z.object({
82
103
  .transform((value) => value === "true"),
83
104
  MCP_VFS_SCOPE: z.string().min(1).default("mcp"),
84
105
  DISTRIBUTED_MODE: z.enum(["client", "gateway", "both"]).default("client"),
85
- GATEWAY_PUBLIC_URL: z.string().url().optional(),
106
+ GATEWAY_PUBLIC_URL: optionalUrlString,
86
107
  GATEWAY_BIND_HOST: z.string().min(1).default("127.0.0.1"),
87
108
  GATEWAY_BIND_PORT: z.coerce.number().int().positive().default(8790),
88
- GATEWAY_WS_URL: z.string().url().optional(),
109
+ GATEWAY_WS_URL: optionalUrlString,
89
110
  GATEWAY_WS_PATH: z
90
111
  .string()
91
112
  .min(1)
92
113
  .default(`${(process.env.ROOT_PREFIX || "/api").replace(/\/+$/u, "")}/gateway/ws`),
93
- GATEWAY_AUTH_TOKEN: z.string().min(1).optional(),
94
- GATEWAY_DATABASE_URL: z.string().min(1).optional(),
95
- GATEWAY_S3_ENDPOINT: z.string().min(1).optional(),
96
- GATEWAY_S3_BUCKET: z.string().min(1).optional(),
97
- GATEWAY_S3_ACCESS_KEY: z.string().min(1).optional(),
98
- GATEWAY_S3_SECRET_KEY: z.string().min(1).optional(),
99
- RMQ_HOST: z.string().min(1).optional(),
114
+ GATEWAY_TOKEN: optionalNonEmptyString,
115
+ GATEWAY_USER_UUID: optionalNonEmptyString,
116
+ GATEWAY_AUTH_TOKEN: optionalNonEmptyString,
117
+ GATEWAY_DATABASE_URL: optionalNonEmptyString,
118
+ GATEWAY_S3_ENDPOINT: optionalNonEmptyString,
119
+ GATEWAY_S3_BUCKET: optionalNonEmptyString,
120
+ GATEWAY_S3_ACCESS_KEY: optionalNonEmptyString,
121
+ GATEWAY_S3_SECRET_KEY: optionalNonEmptyString,
122
+ RMQ_HOST: optionalNonEmptyString,
100
123
  RMQ_PORT: z.coerce.number().int().positive().optional(),
101
- RMQ_USER: z.string().min(1).optional(),
102
- RMQ_PASSWORD: z.string().min(1).optional(),
103
- RMQ_VHOST: z.string().optional(),
124
+ RMQ_USER: optionalNonEmptyString,
125
+ RMQ_PASSWORD: optionalNonEmptyString,
126
+ RMQ_VHOST: z.preprocess(emptyStringToUndefined, z.string().optional()),
104
127
  RMQ_EXCHANGE: z.string().min(1).default("telegram_mcp.gateway"),
105
128
  WEBAPP_ENABLED: z
106
129
  .string()
107
130
  .optional()
108
131
  .transform((value) => value === "true"),
109
132
  WEBAPP_BASE_PATH: z.string().min(1).default("/webapp"),
110
- WEBAPP_PUBLIC_URL: z.string().url().optional(),
133
+ WEBAPP_PUBLIC_URL: optionalUrlString,
111
134
  WEBAPP_INITDATA_TTL_SECONDS: z.coerce
112
135
  .number()
113
136
  .int()
@@ -125,20 +148,48 @@ const envSchema = z.object({
125
148
  WEBAPP_POLL_INTERVAL_MS: z.coerce.number().int().positive().default(2000),
126
149
  WEBAPP_ACTION_COOLDOWN_MS: z.coerce.number().int().nonnegative().default(150),
127
150
  MCP_XCHANGE_DIR: z.string().min(1).default(".mcp-xchange"),
128
- TMUX_NUDGE_ENABLED: z
151
+ TERMINAL_SHELL: z.string().min(1).default(process.env.SHELL || "bash"),
152
+ TERMINAL_COLS: z.coerce.number().int().positive().default(120),
153
+ TERMINAL_ROWS: z.coerce.number().int().positive().default(40),
154
+ TERMINAL_SCROLLBACK_LINES: z.coerce.number().int().positive().default(4000),
155
+ TERMINAL_NUDGE_ENABLED: z
129
156
  .string()
130
157
  .optional()
131
158
  .transform((value) => value !== "false"),
132
- TMUX_SOCKET_PATH: z.string().min(1).optional(),
133
- TMUX_NUDGE_DEBOUNCE_SECONDS: z.coerce.number().int().positive().default(10),
134
- TMUX_NUDGE_COOLDOWN_SECONDS: z.coerce.number().int().positive().default(30),
135
- TMUX_NUDGE_MESSAGE: z.string().min(1).default("проверь inbox"),
136
- TMUX_PARTNER_NUDGE_MESSAGE: z
159
+ TERMINAL_NUDGE_DEBOUNCE_SECONDS: z.coerce.number().int().positive().default(10),
160
+ TERMINAL_NUDGE_COOLDOWN_SECONDS: z.coerce.number().int().positive().default(30),
161
+ TERMINAL_NUDGE_MESSAGE: z
162
+ .string()
163
+ .min(1)
164
+ .default("получи newest telegram_message через list_xchange_records/get_xchange_record, выполни запрос и ответь человеку через notify_telegram; не останавливайся на анализе"),
165
+ TERMINAL_PARTNER_NUDGE_MESSAGE: z
166
+ .string()
167
+ .min(1)
168
+ .default("получи newest partner_note через list_xchange_records/get_xchange_record, выполни задачу в текущей консоли и обязательно отправь результат через send_partner_note или send_partner_file; только потом mark_xchange_record_read"),
169
+ TERMINAL_PARTNER_REPLY_NUDGE_MESSAGE: z
137
170
  .string()
138
171
  .min(1)
139
- .default("не inbox: прочитай SHARED_INDEX.md и partner note"),
140
- TMUX_CAPTURE_MODE: z.enum(["visible", "lines"]).default("visible"),
141
- TMUX_CAPTURE_LINES: z.coerce.number().int().positive().default(300),
172
+ .default("получи newest partner_note через list_xchange_records/get_xchange_record; если newest note имеет kind=reply или не требует ответа, не отправляй новый send_partner_note/send_partner_file без явного нового запроса. Если этот reply завершает задачу от человека, сразу отправь финальный результат в Telegram через notify_telegram или send_file_to_telegram; только потом mark_xchange_record_read"),
173
+ TERMINAL_CAPTURE_MODE: z.enum(["visible", "lines"]).default("visible"),
174
+ TERMINAL_CAPTURE_LINES: z.coerce.number().int().positive().default(300),
175
+ TERMINAL_PROMPT_SCAN_ENABLED: z
176
+ .string()
177
+ .optional()
178
+ .transform((value) => value === "true"),
179
+ TERMINAL_PROMPT_SCAN_INTERVAL_SECONDS: z.coerce
180
+ .number()
181
+ .int()
182
+ .positive()
183
+ .default(15),
184
+ TERMINAL_PROMPT_SCAN_COOLDOWN_SECONDS: z.coerce
185
+ .number()
186
+ .int()
187
+ .positive()
188
+ .default(120),
189
+ TERMINAL_PROMPT_SCAN_STRATEGY: z
190
+ .enum(["strict", "balanced"])
191
+ .default("strict"),
192
+ TERMINAL_PROMPT_SCAN_MIN_SCORE: z.coerce.number().int().positive().default(5),
142
193
  BROWSER_ENABLED: z
143
194
  .string()
144
195
  .optional()
@@ -151,25 +202,28 @@ const envSchema = z.object({
151
202
  .string()
152
203
  .optional()
153
204
  .transform((value) => value === "true"),
154
- BROWSER_ADDRESS: z.string().url().optional(),
205
+ BROWSER_ADDRESS: optionalUrlString,
155
206
  BROWSER_TIMEOUT_MS: z.coerce.number().int().positive().default(20000),
156
207
  BROWSER_MAX_EVENTS: z.coerce.number().int().positive().default(200),
157
208
  BROWSER_WAIT_UNTIL: z
158
209
  .enum(["load", "domcontentloaded", "networkidle", "commit"])
159
210
  .default("load"),
160
- BROWSER_EXECUTABLE_PATH: z.string().min(1).optional(),
161
- BROWSER_CHANNEL: z.enum(["chrome", "chromium", "msedge"]).optional(),
211
+ BROWSER_EXECUTABLE_PATH: optionalNonEmptyString,
212
+ BROWSER_CHANNEL: z.preprocess(emptyStringToUndefined, z.enum(["chrome", "chromium", "msedge"]).optional()),
162
213
  BROWSER_SLOW_MO_MS: z.coerce.number().int().nonnegative().default(0),
163
- PROXY_USE: z.enum(["http", "socks5"]).optional(),
164
- HTTP_PROXY: z.string().min(1).optional(),
165
- SOCKS5_PROXY: z.string().min(1).optional(),
214
+ PROXY_USE: z.preprocess(emptyStringToUndefined, z.enum(["http", "socks5"]).optional()),
215
+ HTTP_PROXY: optionalNonEmptyString,
216
+ SOCKS5_PROXY: optionalNonEmptyString,
166
217
  LOG_LEVEL: z
167
218
  .enum(["fatal", "error", "warn", "info", "debug", "trace", "silent"])
168
219
  .default("info"),
220
+ LOG_STDERR_LEVEL: z
221
+ .preprocess(emptyStringToUndefined, z.enum(["fatal", "error", "warn", "info", "debug", "trace", "silent"]).optional()),
169
222
  LOG_FILE_ENABLED: z
170
223
  .string()
171
224
  .optional()
172
225
  .transform((value) => value === "true"),
226
+ LOG_FILE_LEVEL: z.preprocess(emptyStringToUndefined, z.enum(["fatal", "error", "warn", "info", "debug", "trace", "silent"]).optional()),
173
227
  LOG_FILE_PATH: z.string().min(1).default(".tellymcp/log.jsonl"),
174
228
  });
175
229
  function loadConfig() {
@@ -181,6 +235,21 @@ function loadConfig() {
181
235
  process.loadEnvFile(".env");
182
236
  }
183
237
  const parsed = envSchema.parse(process.env);
238
+ if (parsed.DISTRIBUTED_MODE !== "client" &&
239
+ !parsed.TELEGRAM_BOT_TOKEN?.trim()) {
240
+ throw new Error("TELEGRAM_BOT_TOKEN is required for gateway and both distributed modes.");
241
+ }
242
+ if (parsed.ADMIN_TOKEN?.trim() && !parsed.TELEGRAM_BOT_TOKEN?.trim()) {
243
+ throw new Error("ADMIN_TOKEN requires TELEGRAM_BOT_TOKEN because admin mode runs through the gateway bot.");
244
+ }
245
+ if (parsed.TELEGRAM_WEBHOOK_ENABLED) {
246
+ if (!parsed.TELEGRAM_WEBHOOK_PUBLIC_URL?.trim()) {
247
+ throw new Error("TELEGRAM_WEBHOOK_ENABLED=true requires TELEGRAM_WEBHOOK_PUBLIC_URL.");
248
+ }
249
+ if (!parsed.TELEGRAM_WEBHOOK_SECRET?.trim()) {
250
+ throw new Error("TELEGRAM_WEBHOOK_ENABLED=true requires TELEGRAM_WEBHOOK_SECRET.");
251
+ }
252
+ }
184
253
  const telegramProxy = parsed.PROXY_USE === "http"
185
254
  ? parsed.HTTP_PROXY
186
255
  ? {
@@ -202,10 +271,13 @@ function loadConfig() {
202
271
  : undefined;
203
272
  return {
204
273
  telegram: {
205
- botToken: parsed.TELEGRAM_BOT_TOKEN,
274
+ ...(parsed.TELEGRAM_BOT_TOKEN
275
+ ? { botToken: parsed.TELEGRAM_BOT_TOKEN }
276
+ : {}),
206
277
  ...(parsed.TELEGRAM_BOT_USERNAME
207
278
  ? { botUsername: parsed.TELEGRAM_BOT_USERNAME }
208
279
  : {}),
280
+ ...(parsed.ADMIN_TOKEN ? { adminToken: parsed.ADMIN_TOKEN } : {}),
209
281
  ...(parsed.DEBUG_LANGUAGE
210
282
  ? { debugLanguage: parsed.DEBUG_LANGUAGE }
211
283
  : {}),
@@ -214,8 +286,19 @@ function loadConfig() {
214
286
  maxContextChars: parsed.TELEGRAM_MAX_CONTEXT_CHARS,
215
287
  maxQuestionChars: parsed.TELEGRAM_MAX_QUESTION_CHARS,
216
288
  maxMessageChars: parsed.TELEGRAM_MAX_MESSAGE_CHARS,
217
- inboxBatchSize: parsed.TELEGRAM_INBOX_BATCH_SIZE,
218
289
  menuPayloadTtlSeconds: parsed.TELEGRAM_MENU_PAYLOAD_TTL_SECONDS,
290
+ webhook: {
291
+ enabled: parsed.TELEGRAM_WEBHOOK_ENABLED,
292
+ path: parsed.TELEGRAM_WEBHOOK_PATH,
293
+ ...(parsed.TELEGRAM_WEBHOOK_PUBLIC_URL
294
+ ? { publicUrl: parsed.TELEGRAM_WEBHOOK_PUBLIC_URL }
295
+ : {}),
296
+ ...(parsed.TELEGRAM_WEBHOOK_SECRET
297
+ ? { secret: parsed.TELEGRAM_WEBHOOK_SECRET }
298
+ : {}),
299
+ trace: parsed.TELEGRAM_WEBHOOK_TRACE,
300
+ dropPendingUpdates: parsed.TELEGRAM_WEBHOOK_DROP_PENDING_UPDATES,
301
+ },
219
302
  ...(telegramProxy ? { proxy: telegramProxy } : {}),
220
303
  },
221
304
  redis: {
@@ -249,6 +332,12 @@ function loadConfig() {
249
332
  ? { gatewayWsUrl: parsed.GATEWAY_WS_URL }
250
333
  : {}),
251
334
  gatewayWsPath: parsed.GATEWAY_WS_PATH,
335
+ ...(parsed.GATEWAY_TOKEN
336
+ ? { gatewayToken: parsed.GATEWAY_TOKEN }
337
+ : {}),
338
+ ...(parsed.GATEWAY_USER_UUID
339
+ ? { gatewayUserUuid: parsed.GATEWAY_USER_UUID }
340
+ : {}),
252
341
  ...(parsed.GATEWAY_AUTH_TOKEN
253
342
  ? { gatewayAuthToken: parsed.GATEWAY_AUTH_TOKEN }
254
343
  : {}),
@@ -296,15 +385,24 @@ function loadConfig() {
296
385
  exchange: {
297
386
  dir: parsed.MCP_XCHANGE_DIR,
298
387
  },
299
- tmux: {
300
- nudgeEnabled: parsed.TMUX_NUDGE_ENABLED,
301
- ...(parsed.TMUX_SOCKET_PATH ? { socketPath: parsed.TMUX_SOCKET_PATH } : {}),
302
- nudgeDebounceSeconds: parsed.TMUX_NUDGE_DEBOUNCE_SECONDS,
303
- nudgeCooldownSeconds: parsed.TMUX_NUDGE_COOLDOWN_SECONDS,
304
- nudgeMessage: parsed.TMUX_NUDGE_MESSAGE,
305
- partnerNudgeMessage: parsed.TMUX_PARTNER_NUDGE_MESSAGE,
306
- captureMode: parsed.TMUX_CAPTURE_MODE,
307
- captureLines: parsed.TMUX_CAPTURE_LINES,
388
+ terminal: {
389
+ shell: parsed.TERMINAL_SHELL,
390
+ cols: parsed.TERMINAL_COLS,
391
+ rows: parsed.TERMINAL_ROWS,
392
+ scrollbackLines: parsed.TERMINAL_SCROLLBACK_LINES,
393
+ nudgeEnabled: parsed.TERMINAL_NUDGE_ENABLED,
394
+ nudgeDebounceSeconds: parsed.TERMINAL_NUDGE_DEBOUNCE_SECONDS,
395
+ nudgeCooldownSeconds: parsed.TERMINAL_NUDGE_COOLDOWN_SECONDS,
396
+ nudgeMessage: parsed.TERMINAL_NUDGE_MESSAGE,
397
+ partnerNudgeMessage: parsed.TERMINAL_PARTNER_NUDGE_MESSAGE,
398
+ partnerReplyNudgeMessage: parsed.TERMINAL_PARTNER_REPLY_NUDGE_MESSAGE,
399
+ captureMode: parsed.TERMINAL_CAPTURE_MODE,
400
+ captureLines: parsed.TERMINAL_CAPTURE_LINES,
401
+ promptScanEnabled: parsed.TERMINAL_PROMPT_SCAN_ENABLED,
402
+ promptScanIntervalSeconds: parsed.TERMINAL_PROMPT_SCAN_INTERVAL_SECONDS,
403
+ promptScanCooldownSeconds: parsed.TERMINAL_PROMPT_SCAN_COOLDOWN_SECONDS,
404
+ promptScanStrategy: parsed.TERMINAL_PROMPT_SCAN_STRATEGY,
405
+ promptScanMinScore: parsed.TERMINAL_PROMPT_SCAN_MIN_SCORE,
308
406
  },
309
407
  browser: {
310
408
  enabled: parsed.BROWSER_ENABLED,
@@ -322,10 +420,18 @@ function loadConfig() {
322
420
  },
323
421
  project: {
324
422
  ...(parsed.PROJECT_NAME ? { name: parsed.PROJECT_NAME } : {}),
423
+ ...(parsed.TELLYMCP_SESSION_ID
424
+ ? { sessionId: parsed.TELLYMCP_SESSION_ID }
425
+ : {}),
426
+ ...(parsed.TELLYMCP_SESSION_LABEL
427
+ ? { sessionLabel: parsed.TELLYMCP_SESSION_LABEL }
428
+ : {}),
325
429
  },
326
430
  logging: {
327
431
  level: parsed.LOG_LEVEL,
432
+ ...(parsed.LOG_STDERR_LEVEL ? { stderrLevel: parsed.LOG_STDERR_LEVEL } : {}),
328
433
  fileEnabled: parsed.LOG_FILE_ENABLED,
434
+ ...(parsed.LOG_FILE_LEVEL ? { fileLevel: parsed.LOG_FILE_LEVEL } : {}),
329
435
  filePath: parsed.LOG_FILE_PATH,
330
436
  },
331
437
  };