@deadragdoll/tellymcp 0.0.9 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/.env.example.client +42 -50
  2. package/.env.example.gateway +49 -61
  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 +36 -10
  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 +40 -20
  15. package/config/templates/env.client.template +34 -18
  16. package/config/templates/env.gateway.template +38 -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/approval.service.js +1 -1
  23. package/dist/services/features/telegram-mcp/browser.service.js +95 -2
  24. package/dist/services/features/telegram-mcp/collaboration.service.js +41 -4
  25. package/dist/services/features/telegram-mcp/ensuredb.service.js +145 -26
  26. package/dist/services/features/telegram-mcp/gateway-delivery.service.js +285 -103
  27. package/dist/services/features/telegram-mcp/gateway-rmq.service.js +3 -2
  28. package/dist/services/features/telegram-mcp/gateway-socket.service.js +905 -87
  29. package/dist/services/features/telegram-mcp/gateway.service.js +876 -81
  30. package/dist/services/features/telegram-mcp/mcp-http.service.js +9 -1
  31. package/dist/services/features/telegram-mcp/mcp-server.service.js +17 -26
  32. package/dist/services/features/telegram-mcp/notify.service.js +128 -2
  33. package/dist/services/features/telegram-mcp/runtime.service.js +27 -7
  34. package/dist/services/features/telegram-mcp/session-context.service.js +29 -2
  35. package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +133 -10
  36. package/dist/services/features/telegram-mcp/src/app/config/env.js +161 -51
  37. package/dist/services/features/telegram-mcp/src/app/http.js +375 -42
  38. package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +386 -58
  39. package/dist/services/features/telegram-mcp/src/app/webapp/auth.js +3 -0
  40. package/dist/services/features/telegram-mcp/src/app/webapp/terminal.js +12 -0
  41. package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +116 -104
  42. package/dist/services/features/telegram-mcp/src/entities/xchange/model/types.js +2 -0
  43. package/dist/services/features/telegram-mcp/src/features/ask-user/model/askUserTelegram.js +1 -1
  44. package/dist/services/features/telegram-mcp/src/features/browser/model/browserScreenshotTool.js +1 -1
  45. package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +249 -19
  46. package/dist/services/features/telegram-mcp/src/features/collaboration/model/gatewaySessionsService.js +71 -0
  47. package/dist/services/features/telegram-mcp/src/features/collaboration/model/listGatewaySessionsTool.js +33 -0
  48. package/dist/services/features/telegram-mcp/src/features/collaboration/model/localCollaborationBackend.js +93 -82
  49. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +47 -5
  50. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileTool.js +1 -1
  51. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerNoteTool.js +1 -1
  52. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayClientAccess.js +82 -0
  53. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayCollaborationBackend.js +22 -14
  54. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +649 -75
  55. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/remoteConsoleActionClient.js +76 -0
  56. package/dist/services/features/telegram-mcp/src/features/embedded-runtime/model/embeddedRuntimeBroker.js +92 -0
  57. package/dist/services/features/telegram-mcp/src/features/foreground-terminal/model/foregroundTerminalRuntime.js +192 -0
  58. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +382 -3
  59. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyTelegramTool.js +1 -1
  60. package/dist/services/features/telegram-mcp/src/features/notify/model/sendFileToTelegramTool.js +33 -0
  61. package/dist/services/features/telegram-mcp/src/features/session-context/model/clearSessionContextTool.js +1 -1
  62. package/dist/services/features/telegram-mcp/src/features/session-context/model/getSessionContextTool.js +1 -1
  63. package/dist/services/features/telegram-mcp/src/features/session-context/model/renameSessionTool.js +1 -1
  64. package/dist/services/features/telegram-mcp/src/features/session-context/model/sessionContextService.js +42 -200
  65. package/dist/services/features/telegram-mcp/src/features/session-context/model/setSessionContextTool.js +1 -1
  66. package/dist/services/features/telegram-mcp/src/features/terminal-buffer/model/terminalBufferService.js +96 -0
  67. package/dist/services/features/telegram-mcp/src/features/terminal-input/model/terminalInputService.js +97 -0
  68. package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownService.js +107 -58
  69. package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownTool.js +1 -1
  70. package/dist/services/features/telegram-mcp/src/features/xchange/model/getXchangeRecordTool.js +28 -0
  71. package/dist/services/features/telegram-mcp/src/features/xchange/model/listXchangeRecordsTool.js +28 -0
  72. package/dist/services/features/telegram-mcp/src/features/xchange/model/markXchangeRecordReadTool.js +28 -0
  73. package/dist/services/features/telegram-mcp/src/features/xchange/model/xchangeService.js +169 -0
  74. package/dist/services/features/telegram-mcp/src/processes/human-approval/model/orchestrator.js +5 -4
  75. package/dist/services/features/telegram-mcp/src/shared/i18n/index.js +46 -0
  76. package/dist/services/features/telegram-mcp/src/shared/i18n/resources/en.js +652 -0
  77. package/dist/services/features/telegram-mcp/src/shared/i18n/resources/ru.js +652 -0
  78. package/dist/services/features/telegram-mcp/src/shared/integrations/memory/processLocalSessionStore.js +27 -0
  79. package/dist/services/features/telegram-mcp/src/shared/integrations/object-storage/minioExchangeStore.js +11 -8
  80. package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +51 -71
  81. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/proxyFetch.js +21 -22
  82. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +411 -6524
  83. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportAttachmentStore.js +93 -0
  84. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportBroadcastActions.js +385 -0
  85. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConsoleRegistry.js +143 -0
  86. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConstructorWiring.js +633 -0
  87. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContent.js +84 -0
  88. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContext.js +78 -0
  89. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportDocumentActions.js +36 -0
  90. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportEventActions.js +292 -0
  91. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFileHandoffActions.js +352 -0
  92. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFormatting.js +75 -0
  93. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportGatewayActions.js +44 -0
  94. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLifecycleActions.js +161 -0
  95. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLive.js +56 -0
  96. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLiveActions.js +77 -0
  97. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuCallbacks.js +254 -0
  98. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFactories.js +538 -0
  99. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFingerprints.js +93 -0
  100. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFlow.js +344 -0
  101. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuShell.js +62 -0
  102. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuState.js +408 -0
  103. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuText.js +216 -0
  104. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMessageFlow.js +452 -0
  105. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportOutputActions.js +189 -0
  106. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPartnerActions.js +286 -0
  107. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPayloadState.js +101 -0
  108. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectActions.js +463 -0
  109. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEntryActions.js +202 -0
  110. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEvents.js +99 -0
  111. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectMenus.js +138 -0
  112. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectState.js +308 -0
  113. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectView.js +426 -0
  114. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportRequestFlow.js +278 -0
  115. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportSessionActions.js +143 -0
  116. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalActions.js +468 -0
  117. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalRuntime.js +171 -0
  118. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTypes.js +2 -0
  119. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportUtils.js +330 -0
  120. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportXchangeState.js +107 -0
  121. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/client.js +255 -0
  122. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/ptyRegistry.js +543 -0
  123. package/dist/services/features/telegram-mcp/src/shared/integrations/xchange/sqliteRecordStore.js +223 -0
  124. package/dist/services/features/telegram-mcp/src/shared/lib/gatewayScope.js +24 -0
  125. package/dist/services/features/telegram-mcp/src/shared/lib/logger/logger.js +6 -0
  126. package/dist/services/features/telegram-mcp/src/shared/lib/project-identity/projectIdentity.js +147 -76
  127. package/dist/services/features/telegram-mcp/src/shared/lib/telegramXchangeRecords.js +72 -0
  128. package/dist/services/features/telegram-mcp/src/shared/lib/terminalPromptDetection.js +237 -0
  129. package/dist/services/features/telegram-mcp/src/shared/lib/version/versionHandshake.js +129 -1
  130. package/dist/services/features/telegram-mcp/src/shared/lib/xchangeRecordHints.js +98 -0
  131. package/dist/services/features/telegram-mcp/standalone-http.service.js +13 -1
  132. package/dist/services/features/telegram-mcp/terminal-buffer.service.js +42 -0
  133. package/dist/services/features/telegram-mcp/terminal-input.service.js +41 -0
  134. package/dist/services/features/telegram-mcp/tools-sync.service.js +16 -2
  135. package/dist/services/features/telegram-mcp/xchange.service.js +123 -0
  136. package/docs/STANDALONE-ru.md +172 -0
  137. package/docs/STANDALONE.md +172 -0
  138. package/package.json +11 -5
  139. package/scripts/build-package-artifact.sh +27 -0
  140. package/scripts/deploy-gateway.sh +64 -0
  141. package/scripts/deploy-onebot-branch.sh +27 -0
  142. package/scripts/postinstall.js +11 -36
  143. package/STANDALONE-ru.md +0 -274
  144. package/STANDALONE.md +0 -274
  145. package/dist/services/features/telegram-mcp/inbox.service.js +0 -33
  146. package/dist/services/features/telegram-mcp/pair.service.js +0 -33
  147. package/dist/services/features/telegram-mcp/src/app/webapp/tmux.js +0 -10
  148. package/dist/services/features/telegram-mcp/src/features/inbox/model/deleteTelegramInboxMessageTool.js +0 -33
  149. package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxCountTool.js +0 -33
  150. package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxTool.js +0 -33
  151. package/dist/services/features/telegram-mcp/src/features/inbox/model/inboxService.js +0 -77
  152. package/dist/services/features/telegram-mcp/src/features/pair-session/model/clearSessionPairingTool.js +0 -33
  153. package/dist/services/features/telegram-mcp/src/features/pair-session/model/createSessionPairCodeTool.js +0 -33
  154. package/dist/services/features/telegram-mcp/src/features/pair-session/model/generatePairCode.js +0 -202
  155. package/dist/services/features/telegram-mcp/src/features/session-context/model/getTmuxTargetTool.js +0 -33
  156. package/dist/services/features/telegram-mcp/src/features/session-context/model/setTmuxTargetTool.js +0 -33
  157. 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,29 +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),
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()),
62
82
  REDIS_HOST: z.string().min(1),
63
83
  REDIS_PORT: z.coerce.number().int().positive(),
64
84
  REDIS_DB: z.coerce.number().int().nonnegative(),
65
- REDIS_USERNAME: z.string().min(1).optional(),
66
- REDIS_PASSWORD: z.string().min(1).optional(),
85
+ REDIS_USERNAME: optionalNonEmptyString,
86
+ REDIS_PASSWORD: optionalNonEmptyString,
67
87
  MODE: z.enum(["queue", "reject"]).default("queue"),
68
88
  PAIR_CODE_TTL_SECONDS: z.coerce.number().int().positive().default(600),
69
- PROJECT_NAME: z.string().min(1).optional(),
89
+ PROJECT_NAME: optionalNonEmptyString,
90
+ TELLYMCP_SESSION_ID: optionalNonEmptyString,
91
+ TELLYMCP_SESSION_LABEL: optionalNonEmptyString,
70
92
  MCP_HTTP_HOST: z.string().min(1).default("127.0.0.1"),
71
93
  MCP_HTTP_PORT: z.coerce.number().int().positive().default(8787),
72
94
  MCP_HTTP_PATH: z.string().min(1).default("/mcp"),
73
- MCP_HTTP_BEARER_TOKEN: z.string().min(1).optional(),
95
+ MCP_HTTP_BEARER_TOKEN: optionalNonEmptyString,
74
96
  MCP_HTTP_ENABLE_DEBUG_ROUTES: z
75
97
  .string()
76
98
  .optional()
@@ -81,32 +103,34 @@ const envSchema = z.object({
81
103
  .transform((value) => value === "true"),
82
104
  MCP_VFS_SCOPE: z.string().min(1).default("mcp"),
83
105
  DISTRIBUTED_MODE: z.enum(["client", "gateway", "both"]).default("client"),
84
- GATEWAY_PUBLIC_URL: z.string().url().optional(),
106
+ GATEWAY_PUBLIC_URL: optionalUrlString,
85
107
  GATEWAY_BIND_HOST: z.string().min(1).default("127.0.0.1"),
86
108
  GATEWAY_BIND_PORT: z.coerce.number().int().positive().default(8790),
87
- GATEWAY_WS_URL: z.string().url().optional(),
109
+ GATEWAY_WS_URL: optionalUrlString,
88
110
  GATEWAY_WS_PATH: z
89
111
  .string()
90
112
  .min(1)
91
113
  .default(`${(process.env.ROOT_PREFIX || "/api").replace(/\/+$/u, "")}/gateway/ws`),
92
- GATEWAY_AUTH_TOKEN: z.string().min(1).optional(),
93
- GATEWAY_DATABASE_URL: z.string().min(1).optional(),
94
- GATEWAY_S3_ENDPOINT: z.string().min(1).optional(),
95
- GATEWAY_S3_BUCKET: z.string().min(1).optional(),
96
- GATEWAY_S3_ACCESS_KEY: z.string().min(1).optional(),
97
- GATEWAY_S3_SECRET_KEY: z.string().min(1).optional(),
98
- 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,
99
123
  RMQ_PORT: z.coerce.number().int().positive().optional(),
100
- RMQ_USER: z.string().min(1).optional(),
101
- RMQ_PASSWORD: z.string().min(1).optional(),
102
- RMQ_VHOST: z.string().optional(),
124
+ RMQ_USER: optionalNonEmptyString,
125
+ RMQ_PASSWORD: optionalNonEmptyString,
126
+ RMQ_VHOST: z.preprocess(emptyStringToUndefined, z.string().optional()),
103
127
  RMQ_EXCHANGE: z.string().min(1).default("telegram_mcp.gateway"),
104
128
  WEBAPP_ENABLED: z
105
129
  .string()
106
130
  .optional()
107
131
  .transform((value) => value === "true"),
108
132
  WEBAPP_BASE_PATH: z.string().min(1).default("/webapp"),
109
- WEBAPP_PUBLIC_URL: z.string().url().optional(),
133
+ WEBAPP_PUBLIC_URL: optionalUrlString,
110
134
  WEBAPP_INITDATA_TTL_SECONDS: z.coerce
111
135
  .number()
112
136
  .int()
@@ -124,20 +148,48 @@ const envSchema = z.object({
124
148
  WEBAPP_POLL_INTERVAL_MS: z.coerce.number().int().positive().default(2000),
125
149
  WEBAPP_ACTION_COOLDOWN_MS: z.coerce.number().int().nonnegative().default(150),
126
150
  MCP_XCHANGE_DIR: z.string().min(1).default(".mcp-xchange"),
127
- 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
128
156
  .string()
129
157
  .optional()
130
158
  .transform((value) => value !== "false"),
131
- TMUX_SOCKET_PATH: z.string().min(1).optional(),
132
- TMUX_NUDGE_DEBOUNCE_SECONDS: z.coerce.number().int().positive().default(10),
133
- TMUX_NUDGE_COOLDOWN_SECONDS: z.coerce.number().int().positive().default(30),
134
- TMUX_NUDGE_MESSAGE: z.string().min(1).default("проверь inbox"),
135
- 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
136
162
  .string()
137
163
  .min(1)
138
- .default("не inbox: прочитай SHARED_INDEX.md и partner note"),
139
- TMUX_CAPTURE_MODE: z.enum(["visible", "lines"]).default("visible"),
140
- TMUX_CAPTURE_LINES: z.coerce.number().int().positive().default(300),
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
170
+ .string()
171
+ .min(1)
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),
141
193
  BROWSER_ENABLED: z
142
194
  .string()
143
195
  .optional()
@@ -150,25 +202,28 @@ const envSchema = z.object({
150
202
  .string()
151
203
  .optional()
152
204
  .transform((value) => value === "true"),
153
- BROWSER_ADDRESS: z.string().url().optional(),
205
+ BROWSER_ADDRESS: optionalUrlString,
154
206
  BROWSER_TIMEOUT_MS: z.coerce.number().int().positive().default(20000),
155
207
  BROWSER_MAX_EVENTS: z.coerce.number().int().positive().default(200),
156
208
  BROWSER_WAIT_UNTIL: z
157
209
  .enum(["load", "domcontentloaded", "networkidle", "commit"])
158
210
  .default("load"),
159
- BROWSER_EXECUTABLE_PATH: z.string().min(1).optional(),
160
- 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()),
161
213
  BROWSER_SLOW_MO_MS: z.coerce.number().int().nonnegative().default(0),
162
- PROXY_USE: z.enum(["http", "socks5"]).optional(),
163
- HTTP_PROXY: z.string().min(1).optional(),
164
- 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,
165
217
  LOG_LEVEL: z
166
218
  .enum(["fatal", "error", "warn", "info", "debug", "trace", "silent"])
167
219
  .default("info"),
220
+ LOG_STDERR_LEVEL: z
221
+ .preprocess(emptyStringToUndefined, z.enum(["fatal", "error", "warn", "info", "debug", "trace", "silent"]).optional()),
168
222
  LOG_FILE_ENABLED: z
169
223
  .string()
170
224
  .optional()
171
225
  .transform((value) => value === "true"),
226
+ LOG_FILE_LEVEL: z.preprocess(emptyStringToUndefined, z.enum(["fatal", "error", "warn", "info", "debug", "trace", "silent"]).optional()),
172
227
  LOG_FILE_PATH: z.string().min(1).default(".tellymcp/log.jsonl"),
173
228
  });
174
229
  function loadConfig() {
@@ -180,6 +235,21 @@ function loadConfig() {
180
235
  process.loadEnvFile(".env");
181
236
  }
182
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
+ }
183
253
  const telegramProxy = parsed.PROXY_USE === "http"
184
254
  ? parsed.HTTP_PROXY
185
255
  ? {
@@ -201,17 +271,34 @@ function loadConfig() {
201
271
  : undefined;
202
272
  return {
203
273
  telegram: {
204
- botToken: parsed.TELEGRAM_BOT_TOKEN,
274
+ ...(parsed.TELEGRAM_BOT_TOKEN
275
+ ? { botToken: parsed.TELEGRAM_BOT_TOKEN }
276
+ : {}),
205
277
  ...(parsed.TELEGRAM_BOT_USERNAME
206
278
  ? { botUsername: parsed.TELEGRAM_BOT_USERNAME }
207
279
  : {}),
280
+ ...(parsed.ADMIN_TOKEN ? { adminToken: parsed.ADMIN_TOKEN } : {}),
281
+ ...(parsed.DEBUG_LANGUAGE
282
+ ? { debugLanguage: parsed.DEBUG_LANGUAGE }
283
+ : {}),
208
284
  pollIntervalMs: parsed.TELEGRAM_POLL_INTERVAL_MS,
209
285
  defaultTimeoutSeconds: parsed.TELEGRAM_DEFAULT_TIMEOUT_SECONDS,
210
286
  maxContextChars: parsed.TELEGRAM_MAX_CONTEXT_CHARS,
211
287
  maxQuestionChars: parsed.TELEGRAM_MAX_QUESTION_CHARS,
212
288
  maxMessageChars: parsed.TELEGRAM_MAX_MESSAGE_CHARS,
213
- inboxBatchSize: parsed.TELEGRAM_INBOX_BATCH_SIZE,
214
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
+ },
215
302
  ...(telegramProxy ? { proxy: telegramProxy } : {}),
216
303
  },
217
304
  redis: {
@@ -245,6 +332,12 @@ function loadConfig() {
245
332
  ? { gatewayWsUrl: parsed.GATEWAY_WS_URL }
246
333
  : {}),
247
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
+ : {}),
248
341
  ...(parsed.GATEWAY_AUTH_TOKEN
249
342
  ? { gatewayAuthToken: parsed.GATEWAY_AUTH_TOKEN }
250
343
  : {}),
@@ -292,15 +385,24 @@ function loadConfig() {
292
385
  exchange: {
293
386
  dir: parsed.MCP_XCHANGE_DIR,
294
387
  },
295
- tmux: {
296
- nudgeEnabled: parsed.TMUX_NUDGE_ENABLED,
297
- ...(parsed.TMUX_SOCKET_PATH ? { socketPath: parsed.TMUX_SOCKET_PATH } : {}),
298
- nudgeDebounceSeconds: parsed.TMUX_NUDGE_DEBOUNCE_SECONDS,
299
- nudgeCooldownSeconds: parsed.TMUX_NUDGE_COOLDOWN_SECONDS,
300
- nudgeMessage: parsed.TMUX_NUDGE_MESSAGE,
301
- partnerNudgeMessage: parsed.TMUX_PARTNER_NUDGE_MESSAGE,
302
- captureMode: parsed.TMUX_CAPTURE_MODE,
303
- 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,
304
406
  },
305
407
  browser: {
306
408
  enabled: parsed.BROWSER_ENABLED,
@@ -318,10 +420,18 @@ function loadConfig() {
318
420
  },
319
421
  project: {
320
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
+ : {}),
321
429
  },
322
430
  logging: {
323
431
  level: parsed.LOG_LEVEL,
432
+ ...(parsed.LOG_STDERR_LEVEL ? { stderrLevel: parsed.LOG_STDERR_LEVEL } : {}),
324
433
  fileEnabled: parsed.LOG_FILE_ENABLED,
434
+ ...(parsed.LOG_FILE_LEVEL ? { fileLevel: parsed.LOG_FILE_LEVEL } : {}),
325
435
  filePath: parsed.LOG_FILE_PATH,
326
436
  },
327
437
  };