@deadragdoll/tellymcp 0.0.10 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) 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 +226 -376
  5. package/README.md +213 -1184
  6. package/TOOLS.md +320 -377
  7. package/VERSION.md +13 -13
  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 +907 -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 +120 -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/browserOpenTool.js +1 -1
  42. package/dist/services/features/telegram-mcp/src/features/browser/model/browserScreenshotTool.js +1 -1
  43. package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +306 -26
  44. package/dist/services/features/telegram-mcp/src/features/collaboration/model/gatewaySessionsService.js +71 -0
  45. package/dist/services/features/telegram-mcp/src/features/collaboration/model/listGatewaySessionsTool.js +33 -0
  46. package/dist/services/features/telegram-mcp/src/features/collaboration/model/localCollaborationBackend.js +93 -82
  47. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +47 -5
  48. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileTool.js +1 -1
  49. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerNoteTool.js +1 -1
  50. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayClientAccess.js +82 -0
  51. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayCollaborationBackend.js +22 -14
  52. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +697 -75
  53. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/remoteConsoleActionClient.js +76 -0
  54. package/dist/services/features/telegram-mcp/src/features/embedded-runtime/model/embeddedRuntimeBroker.js +92 -0
  55. package/dist/services/features/telegram-mcp/src/features/foreground-terminal/model/foregroundTerminalRuntime.js +192 -0
  56. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +382 -3
  57. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyTelegramTool.js +1 -1
  58. package/dist/services/features/telegram-mcp/src/features/notify/model/sendFileToTelegramTool.js +33 -0
  59. package/dist/services/features/telegram-mcp/src/features/session-context/model/clearSessionContextTool.js +1 -1
  60. package/dist/services/features/telegram-mcp/src/features/session-context/model/getSessionContextTool.js +1 -1
  61. package/dist/services/features/telegram-mcp/src/features/session-context/model/renameSessionTool.js +1 -1
  62. package/dist/services/features/telegram-mcp/src/features/session-context/model/sessionContextService.js +42 -200
  63. package/dist/services/features/telegram-mcp/src/features/session-context/model/setSessionContextTool.js +1 -1
  64. package/dist/services/features/telegram-mcp/src/features/terminal-buffer/model/terminalBufferService.js +96 -0
  65. package/dist/services/features/telegram-mcp/src/features/terminal-input/model/terminalInputService.js +97 -0
  66. package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownService.js +107 -58
  67. package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownTool.js +1 -1
  68. package/dist/services/features/telegram-mcp/src/features/xchange/model/getXchangeRecordTool.js +28 -0
  69. package/dist/services/features/telegram-mcp/src/features/xchange/model/listXchangeRecordsTool.js +28 -0
  70. package/dist/services/features/telegram-mcp/src/features/xchange/model/markXchangeRecordReadTool.js +28 -0
  71. package/dist/services/features/telegram-mcp/src/features/xchange/model/xchangeService.js +169 -0
  72. package/dist/services/features/telegram-mcp/src/processes/human-approval/model/orchestrator.js +5 -4
  73. package/dist/services/features/telegram-mcp/src/shared/i18n/resources/en.js +143 -42
  74. package/dist/services/features/telegram-mcp/src/shared/i18n/resources/ru.js +139 -38
  75. package/dist/services/features/telegram-mcp/src/shared/integrations/memory/processLocalSessionStore.js +27 -0
  76. package/dist/services/features/telegram-mcp/src/shared/integrations/object-storage/minioExchangeStore.js +11 -8
  77. package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +69 -70
  78. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/proxyFetch.js +21 -22
  79. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +444 -7093
  80. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportAttachmentStore.js +93 -0
  81. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportBroadcastActions.js +385 -0
  82. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConsoleRegistry.js +149 -0
  83. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConstructorWiring.js +642 -0
  84. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContent.js +84 -0
  85. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContext.js +78 -0
  86. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportDocumentActions.js +36 -0
  87. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportEventActions.js +292 -0
  88. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFileHandoffActions.js +352 -0
  89. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFormatting.js +75 -0
  90. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportGatewayActions.js +44 -0
  91. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLifecycleActions.js +161 -0
  92. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLive.js +56 -0
  93. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLiveActions.js +77 -0
  94. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuCallbacks.js +254 -0
  95. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFactories.js +538 -0
  96. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFingerprints.js +93 -0
  97. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFlow.js +344 -0
  98. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuShell.js +65 -0
  99. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuState.js +408 -0
  100. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuText.js +216 -0
  101. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMessageFlow.js +452 -0
  102. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportOutputActions.js +189 -0
  103. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPartnerActions.js +286 -0
  104. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPayloadState.js +108 -0
  105. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectActions.js +463 -0
  106. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEntryActions.js +202 -0
  107. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEvents.js +99 -0
  108. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectMenus.js +138 -0
  109. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectState.js +308 -0
  110. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectView.js +426 -0
  111. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportRequestFlow.js +278 -0
  112. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportSessionActions.js +143 -0
  113. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalActions.js +665 -0
  114. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalRuntime.js +226 -0
  115. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTypes.js +2 -0
  116. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportUtils.js +330 -0
  117. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportXchangeState.js +107 -0
  118. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/client.js +255 -0
  119. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/ptyRegistry.js +543 -0
  120. package/dist/services/features/telegram-mcp/src/shared/integrations/xchange/sqliteRecordStore.js +223 -0
  121. package/dist/services/features/telegram-mcp/src/shared/lib/gatewayScope.js +24 -0
  122. package/dist/services/features/telegram-mcp/src/shared/lib/logger/logger.js +6 -0
  123. package/dist/services/features/telegram-mcp/src/shared/lib/project-identity/projectIdentity.js +147 -76
  124. package/dist/services/features/telegram-mcp/src/shared/lib/telegramXchangeRecords.js +72 -0
  125. package/dist/services/features/telegram-mcp/src/shared/lib/terminalPromptDetection.js +409 -0
  126. package/dist/services/features/telegram-mcp/src/shared/lib/version/versionHandshake.js +129 -1
  127. package/dist/services/features/telegram-mcp/src/shared/lib/xchangeRecordHints.js +98 -0
  128. package/dist/services/features/telegram-mcp/standalone-http.service.js +12 -0
  129. package/dist/services/features/telegram-mcp/terminal-buffer.service.js +42 -0
  130. package/dist/services/features/telegram-mcp/terminal-input.service.js +41 -0
  131. package/dist/services/features/telegram-mcp/tools-sync.service.js +15 -1
  132. package/dist/services/features/telegram-mcp/xchange.service.js +123 -0
  133. package/docs/STANDALONE-ru.md +172 -0
  134. package/docs/STANDALONE.md +172 -0
  135. package/package.json +10 -5
  136. package/scripts/build-package-artifact.sh +27 -0
  137. package/scripts/deploy-gateway.sh +64 -0
  138. package/scripts/deploy-onebot-branch.sh +27 -0
  139. package/scripts/postinstall.js +11 -36
  140. package/STANDALONE-ru.md +0 -274
  141. package/STANDALONE.md +0 -274
  142. package/dist/services/features/telegram-mcp/inbox.service.js +0 -33
  143. package/dist/services/features/telegram-mcp/pair.service.js +0 -33
  144. package/dist/services/features/telegram-mcp/src/app/webapp/tmux.js +0 -10
  145. package/dist/services/features/telegram-mcp/src/features/inbox/model/deleteTelegramInboxMessageTool.js +0 -33
  146. package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxCountTool.js +0 -33
  147. package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxTool.js +0 -33
  148. package/dist/services/features/telegram-mcp/src/features/inbox/model/inboxService.js +0 -77
  149. package/dist/services/features/telegram-mcp/src/features/pair-session/model/clearSessionPairingTool.js +0 -33
  150. package/dist/services/features/telegram-mcp/src/features/pair-session/model/createSessionPairCodeTool.js +0 -33
  151. package/dist/services/features/telegram-mcp/src/features/pair-session/model/generatePairCode.js +0 -202
  152. package/dist/services/features/telegram-mcp/src/features/session-context/model/getTmuxTargetTool.js +0 -33
  153. package/dist/services/features/telegram-mcp/src/features/session-context/model/setTmuxTargetTool.js +0 -33
  154. package/dist/services/features/telegram-mcp/src/shared/integrations/tmux/client.js +0 -363
@@ -0,0 +1,409 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectTerminalInteractivePrompt = detectTerminalInteractivePrompt;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const ANSI_ESCAPE_SEQUENCE_PATTERN =
6
+ // eslint-disable-next-line no-control-regex
7
+ /\u001B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/gu;
8
+ const STRONG_PATTERNS = [
9
+ {
10
+ pattern: /\[(?:[Yy]\/[Nn]|[Nn]\/[Yy])\]|\((?:[Yy]\/[Nn]|[Nn]\/[Yy])\)/u,
11
+ score: 5,
12
+ reason: "yes_no_prompt",
13
+ },
14
+ {
15
+ pattern: /press\s+enter\s+to\s+continue|hit\s+enter\s+to\s+continue/iu,
16
+ score: 5,
17
+ reason: "press_enter_prompt",
18
+ },
19
+ {
20
+ pattern: /press\s+enter\s+to\s+confirm\b.*\besc\s+to\s+cancel/iu,
21
+ score: 5,
22
+ reason: "confirm_cancel_prompt",
23
+ },
24
+ {
25
+ pattern: /waiting\s+for\s+(?:user\s+)?input|awaiting\s+(?:user\s+)?(?:input|confirmation)|requires?\s+approval|need\s+your\s+(?:input|permission|approval)|cannot\s+continue\s+without/iu,
26
+ score: 4,
27
+ reason: "waiting_for_input",
28
+ },
29
+ {
30
+ pattern: /\b(do\s+you\s+want|are\s+you\s+sure|would\s+you\s+like|should\s+i|can\s+i\s+go\s+ahead|may\s+i\s+proceed)\b/iu,
31
+ score: 4,
32
+ reason: "direct_question_phrase",
33
+ },
34
+ {
35
+ pattern: /\[\s*!\s*\]\s*action\s+required\b/iu,
36
+ score: 5,
37
+ reason: "action_required_banner",
38
+ },
39
+ {
40
+ pattern: /\bfield\s+\d+\/\d+\s+\(\d+\s+required\s+unanswered\)/iu,
41
+ score: 5,
42
+ reason: "required_unanswered_field",
43
+ },
44
+ {
45
+ pattern: /\ballow\s+the\s+.+\?\s*$/iu,
46
+ score: 4,
47
+ reason: "allow_question",
48
+ },
49
+ {
50
+ pattern: /\brun\s+the\s+tool\s+and\s+continue\b/iu,
51
+ score: 4,
52
+ reason: "tool_continue_prompt",
53
+ },
54
+ {
55
+ pattern: /\bwould\s+you\s+like\s+to\s+run\s+the\s+following\s+command\b/iu,
56
+ score: 5,
57
+ reason: "command_approval_prompt",
58
+ },
59
+ ];
60
+ const MEDIUM_PATTERNS = [
61
+ {
62
+ pattern: /\b(confirm|approve|allow|continue|proceed|select|choose)\b/iu,
63
+ score: 1,
64
+ reason: "action_keyword",
65
+ },
66
+ {
67
+ pattern: /\?\s*$/u,
68
+ score: 1,
69
+ reason: "question_mark",
70
+ },
71
+ {
72
+ pattern: /\b(?:always\s+allow|allow\s+for\s+this\s+session|cancel\s+this\s+tool\s+call)\b/iu,
73
+ score: 1,
74
+ reason: "tool_choice_keyword",
75
+ },
76
+ ];
77
+ const NUMBERED_CHOICE_LINE_PATTERN = /^(?:[>›*•-]\s*)?\d+\.\s+.+$/u;
78
+ const CONFIRM_CANCEL_FOOTER_PATTERN = /\b(?:press\s+enter\s+to\s+confirm|enter\s+to\s+submit)\b.*\besc\s+to\s+cancel\b/iu;
79
+ const SUBMIT_CANCEL_FOOTER_PATTERN = /\benter\s+to\s+submit\b.*\besc\s+to\s+cancel\b/iu;
80
+ const CONTINUE_FOOTER_PATTERN = /\b(?:press\s+enter\s+to\s+continue|hit\s+enter\s+to\s+continue)\b/iu;
81
+ const NUMBERED_HOTKEY_FOOTER_PATTERN = /\bpress\s+(?:(?:\d+\s*,\s*)+\s*(?:or\s+)?\d+\s*,?\s*)?(?:enter\b.*\besc|esc\b.*\benter|\d+\b.*\benter|\d+\b.*\besc).*\b(?:quit|continue|cancel|confirm|submit)\b/iu;
82
+ const POSITIVE_CHOICE_PATTERN = /\b(?:yes|allow|approve|proceed|continue)\b/iu;
83
+ const NEGATIVE_CHOICE_PATTERN = /\b(?:no|cancel|deny|reject)\b/iu;
84
+ const STICKY_CHOICE_PATTERN = /\bdon'?t\s+ask\s+again|always\s+allow|for\s+this\s+session\b/iu;
85
+ const SKIP_CHOICE_PATTERN = /\bskip\b/iu;
86
+ const LEADING_SELECTION_MARKER_PATTERN = /^(?:[>›*•-]\s*)(?=\d+\.\s)/u;
87
+ const ACTION_HINT_PATTERN = /\b(?:press|input|choose|choice|select|option|enter|esc(?:ape)?|accept|decline|confirm|cancel|continue|proceed|yes|no)\b|(?:\[[Yy](?:es)?\/[Nn](?:o)?\])|(?:\([Yy](?:es)?\/[Nn](?:o)?\))/u;
88
+ function normalizeLine(line) {
89
+ return line
90
+ .replaceAll("\r", "")
91
+ .replace(ANSI_ESCAPE_SEQUENCE_PATTERN, "")
92
+ .replace(/\s+/gu, " ")
93
+ .trim();
94
+ }
95
+ function isNoiseLine(line) {
96
+ if (!line) {
97
+ return true;
98
+ }
99
+ if (line.length > 260) {
100
+ return true;
101
+ }
102
+ return (/^\[[0-9]{4}-[0-9]{2}-[0-9]{2}\b/u.test(line) ||
103
+ /^at\s+.+\(.+\)$/u.test(line) ||
104
+ /^diff --git\b/u.test(line) ||
105
+ /^(---|\+\+\+|@@)\b/u.test(line) ||
106
+ /^[~/.\w-]+:\d+:\d+/u.test(line) ||
107
+ /^https?:\/\/\S+$/u.test(line));
108
+ }
109
+ function scoreStrongLine(line) {
110
+ const contributions = [];
111
+ for (const candidate of STRONG_PATTERNS) {
112
+ if (candidate.pattern.test(line)) {
113
+ contributions.push({
114
+ score: candidate.score,
115
+ reason: candidate.reason,
116
+ });
117
+ }
118
+ }
119
+ return contributions;
120
+ }
121
+ function scoreMediumLine(line, strategy) {
122
+ const contributions = [];
123
+ for (const candidate of MEDIUM_PATTERNS) {
124
+ if (candidate.pattern.test(line)) {
125
+ contributions.push({
126
+ score: candidate.score,
127
+ reason: candidate.reason,
128
+ });
129
+ }
130
+ }
131
+ if (strategy === "balanced" &&
132
+ /\b(input|reply|answer|decision|permission|approval)\b/iu.test(line)) {
133
+ contributions.push({
134
+ score: 1,
135
+ reason: "balanced_context_keyword",
136
+ });
137
+ }
138
+ return contributions;
139
+ }
140
+ function isStrongReason(reason) {
141
+ return STRONG_PATTERNS.some((candidate) => candidate.reason === reason);
142
+ }
143
+ function collectCandidateLines(rawText, maxLines) {
144
+ const normalized = rawText
145
+ .split("\n")
146
+ .map(normalizeLine)
147
+ .filter((line) => line.length > 0);
148
+ return normalized.slice(-Math.max(1, maxLines));
149
+ }
150
+ function normalizeFingerprintLine(line) {
151
+ return normalizeLine(line)
152
+ .replace(LEADING_SELECTION_MARKER_PATTERN, "")
153
+ .replace(/\s+/gu, " ")
154
+ .trim();
155
+ }
156
+ function buildDetectionFingerprint(strategy, matchedLines) {
157
+ const normalizedExcerpt = matchedLines
158
+ .map(normalizeFingerprintLine)
159
+ .join("\n");
160
+ return (0, node_crypto_1.createHash)("sha1")
161
+ .update(`${strategy}\n${normalizedExcerpt}`)
162
+ .digest("hex");
163
+ }
164
+ function buildExcerptWithContext(candidateLines, matchedLines) {
165
+ if (matchedLines.length === 0) {
166
+ return "";
167
+ }
168
+ const firstMatchedIndex = candidateLines.findIndex((line) => line === matchedLines[0]);
169
+ const lastMatchedIndex = matchedLines.length === 1
170
+ ? firstMatchedIndex
171
+ : candidateLines.findIndex((line, index) => index >= Math.max(0, firstMatchedIndex) &&
172
+ line === matchedLines[matchedLines.length - 1]);
173
+ if (firstMatchedIndex < 0 || lastMatchedIndex < 0) {
174
+ return matchedLines.slice(-8).join("\n");
175
+ }
176
+ const excerptStart = Math.max(0, firstMatchedIndex - 2);
177
+ const excerptEnd = Math.min(candidateLines.length, lastMatchedIndex + 1);
178
+ return candidateLines.slice(excerptStart, excerptEnd).slice(-8).join("\n");
179
+ }
180
+ function findChoiceActionBlock(candidateLines) {
181
+ for (let startIndex = candidateLines.length - 1; startIndex >= 0; startIndex -= 1) {
182
+ const line = candidateLines[startIndex] ?? "";
183
+ if (!NUMBERED_CHOICE_LINE_PATTERN.test(line)) {
184
+ continue;
185
+ }
186
+ const choiceLines = [];
187
+ let firstChoiceIndex = startIndex;
188
+ while (firstChoiceIndex >= 0) {
189
+ const currentLine = candidateLines[firstChoiceIndex] ?? "";
190
+ if (!NUMBERED_CHOICE_LINE_PATTERN.test(currentLine)) {
191
+ break;
192
+ }
193
+ choiceLines.unshift(currentLine);
194
+ firstChoiceIndex -= 1;
195
+ }
196
+ firstChoiceIndex += 1;
197
+ if (choiceLines.length < 2) {
198
+ continue;
199
+ }
200
+ const lastChoiceIndex = firstChoiceIndex + choiceLines.length - 1;
201
+ const headerLines = candidateLines.slice(Math.max(0, firstChoiceIndex - 5), firstChoiceIndex);
202
+ const tailLines = candidateLines.slice(lastChoiceIndex + 1, Math.min(candidateLines.length, lastChoiceIndex + 4));
203
+ const footerLine = tailLines[0] ?? null;
204
+ const nearbyLines = [...headerLines, ...tailLines];
205
+ const hasActionHint = nearbyLines.some((candidate) => ACTION_HINT_PATTERN.test(candidate));
206
+ const hasChoiceSemantics = POSITIVE_CHOICE_PATTERN.test(choiceLines.join("\n")) ||
207
+ NEGATIVE_CHOICE_PATTERN.test(choiceLines.join("\n")) ||
208
+ STICKY_CHOICE_PATTERN.test(choiceLines.join("\n")) ||
209
+ SKIP_CHOICE_PATTERN.test(choiceLines.join("\n"));
210
+ if (!hasActionHint && !hasChoiceSemantics) {
211
+ continue;
212
+ }
213
+ return {
214
+ footerLine,
215
+ choiceLines,
216
+ headerLines,
217
+ tailLines,
218
+ };
219
+ }
220
+ return null;
221
+ }
222
+ function detectChoiceFooterSignals(candidateLines, strategy) {
223
+ const block = findChoiceActionBlock(candidateLines);
224
+ if (!block) {
225
+ return null;
226
+ }
227
+ const choiceText = block.choiceLines.join("\n");
228
+ const contextLines = [
229
+ ...block.headerLines,
230
+ ...block.choiceLines,
231
+ ...(block.footerLine ? [block.footerLine] : []),
232
+ ...block.tailLines,
233
+ ];
234
+ const reasons = new Set(["numbered_choice_group"]);
235
+ const matchedLines = [
236
+ ...block.choiceLines,
237
+ ...(block.footerLine ? [block.footerLine] : []),
238
+ ...block.tailLines,
239
+ ];
240
+ let score = strategy === "balanced" ? 5 : 6;
241
+ const footerLine = block.footerLine ?? "";
242
+ if (CONFIRM_CANCEL_FOOTER_PATTERN.test(footerLine)) {
243
+ reasons.add("confirm_cancel_footer");
244
+ score += strategy === "balanced" ? 2 : 3;
245
+ }
246
+ if (CONTINUE_FOOTER_PATTERN.test(footerLine)) {
247
+ reasons.add("continue_footer");
248
+ score += strategy === "balanced" ? 2 : 3;
249
+ }
250
+ if (NUMBERED_HOTKEY_FOOTER_PATTERN.test(footerLine)) {
251
+ reasons.add("numbered_hotkey_footer");
252
+ score += strategy === "balanced" ? 2 : 3;
253
+ }
254
+ if (SUBMIT_CANCEL_FOOTER_PATTERN.test(footerLine)) {
255
+ reasons.add("submit_cancel_hint");
256
+ }
257
+ if (/press\s+enter\s+to\s+confirm\b/iu.test(footerLine)) {
258
+ reasons.add("confirm_cancel_hint");
259
+ }
260
+ if (contextLines.some((line) => ACTION_HINT_PATTERN.test(line))) {
261
+ reasons.add("action_hint_present");
262
+ score += 2;
263
+ }
264
+ if (POSITIVE_CHOICE_PATTERN.test(choiceText)) {
265
+ reasons.add("positive_choice_present");
266
+ score += 2;
267
+ }
268
+ if (NEGATIVE_CHOICE_PATTERN.test(choiceText)) {
269
+ reasons.add("negative_choice_present");
270
+ score += 2;
271
+ }
272
+ if (STICKY_CHOICE_PATTERN.test(choiceText)) {
273
+ reasons.add("sticky_choice_present");
274
+ score += 2;
275
+ }
276
+ if (SKIP_CHOICE_PATTERN.test(choiceText)) {
277
+ reasons.add("skip_choice_present");
278
+ score += 2;
279
+ }
280
+ if (reasons.has("positive_choice_present") && reasons.has("negative_choice_present")) {
281
+ reasons.add("yes_no_choice_group");
282
+ reasons.add("approval_choice_group");
283
+ score += 3;
284
+ }
285
+ if (reasons.has("positive_choice_present") && reasons.has("skip_choice_present")) {
286
+ reasons.add("choice_update_group");
287
+ score += 2;
288
+ }
289
+ if (/^(?:[>›*•-]\s*)?(?:\d+\.\s+)?yes,\s+proceed\b/imu.test(choiceText) &&
290
+ reasons.has("sticky_choice_present")) {
291
+ reasons.add("proceed_choice_group");
292
+ }
293
+ for (const line of contextLines) {
294
+ for (const contribution of scoreStrongLine(line)) {
295
+ reasons.add(contribution.reason);
296
+ score += contribution.score;
297
+ }
298
+ }
299
+ return {
300
+ score,
301
+ reasons: Array.from(reasons),
302
+ matchedLines,
303
+ promptActions: {
304
+ numberedOptions: block.choiceLines
305
+ .map((line) => line.match(/^(?:[>›*•-]\s*)?(\d+)\.\s+/u)?.[1] ?? null)
306
+ .filter((value) => Boolean(value)),
307
+ hasEnter: contextLines.some((line) => /\benter\b/iu.test(line)),
308
+ hasEscape: contextLines.some((line) => /\besc(?:ape)?\b/iu.test(line)),
309
+ },
310
+ };
311
+ }
312
+ function detectTerminalInteractivePrompt(rawText, options = {}) {
313
+ const strategy = options.strategy ?? "strict";
314
+ const minScore = options.minScore ?? (strategy === "balanced" ? 4 : 5);
315
+ const candidateLines = collectCandidateLines(rawText, options.maxLines ?? 40);
316
+ if (candidateLines.length === 0) {
317
+ return null;
318
+ }
319
+ const choiceFooterDetection = detectChoiceFooterSignals(candidateLines, strategy);
320
+ if (choiceFooterDetection && choiceFooterDetection.score >= minScore) {
321
+ const matchedLines = choiceFooterDetection.matchedLines.slice(-6);
322
+ const excerpt = buildExcerptWithContext(candidateLines, matchedLines);
323
+ const fingerprint = buildDetectionFingerprint(strategy, matchedLines);
324
+ return {
325
+ score: choiceFooterDetection.score,
326
+ fingerprint,
327
+ excerpt,
328
+ matchedLines,
329
+ reasons: choiceFooterDetection.reasons,
330
+ promptActions: choiceFooterDetection.promptActions,
331
+ };
332
+ }
333
+ const scoredLines = [];
334
+ let score = 0;
335
+ const reasons = new Set();
336
+ for (const line of candidateLines) {
337
+ if (isNoiseLine(line)) {
338
+ continue;
339
+ }
340
+ const contributions = scoreStrongLine(line);
341
+ if (contributions.length === 0) {
342
+ continue;
343
+ }
344
+ scoredLines.push({ line, contributions });
345
+ for (const contribution of contributions) {
346
+ score += contribution.score;
347
+ reasons.add(contribution.reason);
348
+ }
349
+ }
350
+ const optionLineCount = candidateLines.filter((line) => /^(\d+\.\s+|[-*]\s+|\[[ xX]\]\s+)/u.test(line)).length;
351
+ if (scoredLines.length > 0 && optionLineCount >= 2) {
352
+ score += 3;
353
+ reasons.add("multiple_options");
354
+ }
355
+ const hasStrongReason = Array.from(reasons).some(isStrongReason);
356
+ const hasGroupedReason = reasons.has("multiple_options");
357
+ const hasOnlyQuestionMarkReason = reasons.size === 1 && reasons.has("question_mark");
358
+ if (strategy === "strict") {
359
+ if (hasOnlyQuestionMarkReason) {
360
+ return null;
361
+ }
362
+ if (!hasStrongReason) {
363
+ if (!hasGroupedReason) {
364
+ return null;
365
+ }
366
+ }
367
+ }
368
+ const canUseMediumSignals = strategy === "balanced" ||
369
+ hasStrongReason ||
370
+ hasGroupedReason ||
371
+ reasons.has("multiple_options");
372
+ if (canUseMediumSignals) {
373
+ for (const line of candidateLines) {
374
+ if (isNoiseLine(line)) {
375
+ continue;
376
+ }
377
+ const contributions = scoreMediumLine(line, strategy);
378
+ if (contributions.length === 0) {
379
+ continue;
380
+ }
381
+ const existing = scoredLines.find((entry) => entry.line === line);
382
+ if (existing) {
383
+ existing.contributions.push(...contributions);
384
+ }
385
+ else {
386
+ scoredLines.push({ line, contributions: [...contributions] });
387
+ }
388
+ for (const contribution of contributions) {
389
+ score += contribution.score;
390
+ reasons.add(contribution.reason);
391
+ }
392
+ }
393
+ }
394
+ if (score < minScore || scoredLines.length === 0) {
395
+ return null;
396
+ }
397
+ const matchedLines = scoredLines
398
+ .map((entry) => entry.line)
399
+ .slice(-6);
400
+ const excerpt = buildExcerptWithContext(candidateLines, matchedLines);
401
+ const fingerprint = buildDetectionFingerprint(strategy, matchedLines);
402
+ return {
403
+ score,
404
+ fingerprint,
405
+ excerpt,
406
+ matchedLines,
407
+ reasons: Array.from(reasons),
408
+ };
409
+ }
@@ -3,14 +3,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.TELLYMCP_CAPABILITIES = exports.TELLYMCP_PROTOCOL_VERSION = void 0;
6
+ exports.TELLYMCP_CAPABILITIES = exports.TELLYMCP_PACKAGE_NAME = exports.TELLYMCP_PROTOCOL_VERSION = void 0;
7
7
  exports.parseProtocolVersion = parseProtocolVersion;
8
8
  exports.evaluateVersionCompatibility = evaluateVersionCompatibility;
9
9
  exports.findPackageRoot = findPackageRoot;
10
+ exports.getTellyMcpPackageRoot = getTellyMcpPackageRoot;
10
11
  exports.getTellyMcpPackageVersion = getTellyMcpPackageVersion;
12
+ exports.comparePackageVersions = comparePackageVersions;
13
+ exports.fetchLatestPublishedPackageVersion = fetchLatestPublishedPackageVersion;
14
+ exports.detectAvailablePackageUpdate = detectAvailablePackageUpdate;
11
15
  const node_fs_1 = require("node:fs");
12
16
  const node_path_1 = __importDefault(require("node:path"));
13
17
  exports.TELLYMCP_PROTOCOL_VERSION = "1.0";
18
+ exports.TELLYMCP_PACKAGE_NAME = "@deadragdoll/tellymcp";
14
19
  exports.TELLYMCP_CAPABILITIES = [
15
20
  "collab_projects",
16
21
  "delivery_status_push",
@@ -103,7 +108,11 @@ function findPackageRoot(startDir) {
103
108
  currentDir = parentDir;
104
109
  }
105
110
  }
111
+ function getTellyMcpPackageRoot(startDir) {
112
+ return findPackageRoot(startDir);
113
+ }
106
114
  let cachedPackageVersion = null;
115
+ let latestPublishedVersionPromise = null;
107
116
  function getTellyMcpPackageVersion(startDir) {
108
117
  if (cachedPackageVersion) {
109
118
  return cachedPackageVersion;
@@ -122,3 +131,122 @@ function getTellyMcpPackageVersion(startDir) {
122
131
  return "0.0.0-unknown";
123
132
  }
124
133
  }
134
+ function parseSemver(value) {
135
+ const match = value
136
+ .trim()
137
+ .match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/u);
138
+ if (!match) {
139
+ return null;
140
+ }
141
+ return {
142
+ major: Number(match[1]),
143
+ minor: Number(match[2]),
144
+ patch: Number(match[3]),
145
+ prerelease: match[4]?.split(".").filter(Boolean) ?? [],
146
+ };
147
+ }
148
+ function comparePrerelease(left, right) {
149
+ if (left.length === 0 && right.length === 0) {
150
+ return 0;
151
+ }
152
+ if (left.length === 0) {
153
+ return 1;
154
+ }
155
+ if (right.length === 0) {
156
+ return -1;
157
+ }
158
+ const maxLength = Math.max(left.length, right.length);
159
+ for (let index = 0; index < maxLength; index += 1) {
160
+ const leftPart = left[index];
161
+ const rightPart = right[index];
162
+ if (leftPart === undefined) {
163
+ return -1;
164
+ }
165
+ if (rightPart === undefined) {
166
+ return 1;
167
+ }
168
+ const leftNumber = /^\d+$/u.test(leftPart) ? Number(leftPart) : null;
169
+ const rightNumber = /^\d+$/u.test(rightPart) ? Number(rightPart) : null;
170
+ if (leftNumber !== null && rightNumber !== null) {
171
+ if (leftNumber !== rightNumber) {
172
+ return leftNumber > rightNumber ? 1 : -1;
173
+ }
174
+ continue;
175
+ }
176
+ if (leftNumber !== null) {
177
+ return -1;
178
+ }
179
+ if (rightNumber !== null) {
180
+ return 1;
181
+ }
182
+ if (leftPart !== rightPart) {
183
+ return leftPart > rightPart ? 1 : -1;
184
+ }
185
+ }
186
+ return 0;
187
+ }
188
+ function comparePackageVersions(leftVersion, rightVersion) {
189
+ const left = parseSemver(leftVersion);
190
+ const right = parseSemver(rightVersion);
191
+ if (!left || !right) {
192
+ return null;
193
+ }
194
+ if (left.major !== right.major) {
195
+ return left.major > right.major ? 1 : -1;
196
+ }
197
+ if (left.minor !== right.minor) {
198
+ return left.minor > right.minor ? 1 : -1;
199
+ }
200
+ if (left.patch !== right.patch) {
201
+ return left.patch > right.patch ? 1 : -1;
202
+ }
203
+ return comparePrerelease(left.prerelease, right.prerelease);
204
+ }
205
+ async function fetchLatestPublishedPackageVersion(timeoutMs = 1500) {
206
+ if (!latestPublishedVersionPromise) {
207
+ latestPublishedVersionPromise = (async () => {
208
+ const controller = new AbortController();
209
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
210
+ try {
211
+ const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(exports.TELLYMCP_PACKAGE_NAME)}/latest`, {
212
+ method: "GET",
213
+ headers: {
214
+ accept: "application/json",
215
+ },
216
+ signal: controller.signal,
217
+ });
218
+ if (!response.ok) {
219
+ return null;
220
+ }
221
+ const parsed = (await response.json());
222
+ return typeof parsed.version === "string" && parsed.version.trim()
223
+ ? parsed.version.trim()
224
+ : null;
225
+ }
226
+ catch {
227
+ return null;
228
+ }
229
+ finally {
230
+ clearTimeout(timeout);
231
+ }
232
+ })();
233
+ }
234
+ return latestPublishedVersionPromise;
235
+ }
236
+ async function detectAvailablePackageUpdate(input) {
237
+ if (!input.currentVersion.trim() || input.currentVersion === "0.0.0-unknown") {
238
+ return null;
239
+ }
240
+ const latestVersion = await fetchLatestPublishedPackageVersion(input.timeoutMs);
241
+ if (!latestVersion) {
242
+ return null;
243
+ }
244
+ const comparison = comparePackageVersions(latestVersion, input.currentVersion);
245
+ if (comparison === null || comparison <= 0) {
246
+ return null;
247
+ }
248
+ return {
249
+ currentVersion: input.currentVersion,
250
+ latestVersion,
251
+ };
252
+ }
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildIncomingPartnerActionDesc = buildIncomingPartnerActionDesc;
4
+ exports.buildIncomingPartnerTools = buildIncomingPartnerTools;
5
+ exports.buildOutgoingPartnerActionDesc = buildOutgoingPartnerActionDesc;
6
+ exports.buildOutgoingPartnerTools = buildOutgoingPartnerTools;
7
+ exports.buildLocalHandoffActionDesc = buildLocalHandoffActionDesc;
8
+ exports.buildLocalHandoffTools = buildLocalHandoffTools;
9
+ exports.buildIncomingTelegramMessageActionDesc = buildIncomingTelegramMessageActionDesc;
10
+ exports.buildIncomingTelegramMessageTools = buildIncomingTelegramMessageTools;
11
+ exports.detectIncomingTelegramBrowserScreenshotRequest = detectIncomingTelegramBrowserScreenshotRequest;
12
+ function looksLikeBrowserScreenshotRequest(text) {
13
+ const haystack = text.toLowerCase();
14
+ return (/\b(browser_open|browser_screenshot|playwright)\b/u.test(haystack) ||
15
+ /\b(скриншот|screenshot|скрин)\b/u.test(haystack) ||
16
+ /\bhttps?:\/\/[^\s]+/u.test(haystack));
17
+ }
18
+ function buildIncomingPartnerActionDesc(kind, requiresReply, prefersFileDelivery = false, prefersBrowserScreenshot = false) {
19
+ if (requiresReply || kind === "question" || kind === "request") {
20
+ if (prefersBrowserScreenshot) {
21
+ return "Start with get_xchange_record for the newest partner_note. For a webpage screenshot request, use browser_open and browser_screenshot in this console to create the screenshot artifact, then send that real file back with send_partner_file. Do not stop at analysis, do not just summarize the request, and do not replace the browser workflow with a shell fallback unless the browser tools actually fail. The task is not complete until send_partner_file succeeds. Only after that may you call mark_xchange_record_read.";
22
+ }
23
+ if (prefersFileDelivery) {
24
+ return "Start with get_xchange_record for the newest partner_note, then carry out the requested work in this session and send the result back as a real file with send_partner_file. Do not stop at analysis, do not just summarize the request, and do not paste file contents into send_partner_note. The task is not complete until send_partner_file succeeds. Only after that may you call mark_xchange_record_read.";
25
+ }
26
+ return "Start with get_xchange_record for the newest partner_note, then carry out the requested work in this session and send the result back with send_partner_note. Do not stop at analysis and do not just restate the request. The task is not complete until send_partner_note succeeds. Only after that may you call mark_xchange_record_read.";
27
+ }
28
+ if (kind === "reply") {
29
+ return "Read the reply and inspect any returned artifacts. If this reply completes a task that originally came from a human telegram_message in this session, you must forward the final result to the human now. Use notify_telegram for text-only results. If the reply returned a real local artifact or file, use send_file_to_telegram to deliver that file to the human Telegram chat. Do not leave the result only in local xchange records. Only after the human-facing delivery succeeds, or after you have incorporated the reply into a non-human internal task, may you call mark_xchange_record_read.";
30
+ }
31
+ if (kind === "handoff") {
32
+ return "Inspect the attached artifacts and body_text, then continue the task in this session. Reply only if the sender requested confirmation or more work.";
33
+ }
34
+ return "Read the shared update and attached artifacts, then continue the task in this session.";
35
+ }
36
+ function buildIncomingPartnerTools(kind, requiresReply, prefersFileDelivery = false, prefersBrowserScreenshot = false) {
37
+ const tools = ["get_xchange_record"];
38
+ if (prefersBrowserScreenshot) {
39
+ tools.push("browser_open", "browser_screenshot");
40
+ }
41
+ if (prefersFileDelivery) {
42
+ tools.push("send_partner_file");
43
+ }
44
+ if (requiresReply || kind === "question" || kind === "request") {
45
+ tools.push("send_partner_note");
46
+ }
47
+ if (kind === "handoff" && !tools.includes("send_partner_file")) {
48
+ tools.push("send_partner_file");
49
+ }
50
+ if (kind === "reply") {
51
+ tools.push("notify_telegram", "send_file_to_telegram");
52
+ }
53
+ tools.push("mark_xchange_record_read");
54
+ return tools;
55
+ }
56
+ function buildOutgoingPartnerActionDesc(kind, requiresReply) {
57
+ if (requiresReply || kind === "question" || kind === "request") {
58
+ return "Outgoing collaboration note was sent to the target session. Do not block on sleep, polling, or repeated list_xchange_records calls in the same turn. The target console will be nudged separately and can reply later through the normal xchange path.";
59
+ }
60
+ return "Outgoing collaboration note was sent to the target session.";
61
+ }
62
+ function buildOutgoingPartnerTools(kind, requiresReply) {
63
+ void kind;
64
+ void requiresReply;
65
+ return ["get_xchange_record"];
66
+ }
67
+ function buildLocalHandoffActionDesc() {
68
+ return "Read body_text, inspect the attached local artifacts, and continue the task in this same session.";
69
+ }
70
+ function buildLocalHandoffTools() {
71
+ return ["get_xchange_record", "mark_xchange_record_read"];
72
+ }
73
+ function buildIncomingTelegramMessageActionDesc(kind, prefersBrowserScreenshot = false) {
74
+ if (kind === "question" || kind === "request") {
75
+ if (prefersBrowserScreenshot) {
76
+ return "Start with get_xchange_record for the newest telegram_message. For a webpage screenshot request, use browser_open and browser_screenshot in this console, and set send_to_telegram=true on browser_screenshot so the PNG goes directly back to the human Telegram chat. Do not stop at analysis, do not just restate the request, do not save the screenshot locally and then search for route metadata, and do not call get_session_context just to deliver the screenshot. The task is not complete until browser_screenshot succeeds with send_to_telegram=true. Only after that may you call mark_xchange_record_read.";
77
+ }
78
+ return "Start with get_xchange_record for the newest telegram_message, then carry out the requested work in this session and reply to the human through notify_telegram. Do not stop at analysis and do not just restate the request. The task is not complete until notify_telegram succeeds. Only after that may you call mark_xchange_record_read.";
79
+ }
80
+ return "Read the Telegram message and attachments, continue the task in this session, and use notify_telegram only if a human-facing reply is needed.";
81
+ }
82
+ function buildIncomingTelegramMessageTools(kind, prefersBrowserScreenshot = false) {
83
+ const tools = ["get_xchange_record"];
84
+ if (prefersBrowserScreenshot && (kind === "question" || kind === "request")) {
85
+ tools.push("browser_open", "browser_screenshot");
86
+ }
87
+ else if (kind === "question" || kind === "request") {
88
+ tools.push("notify_telegram");
89
+ }
90
+ tools.push("mark_xchange_record_read");
91
+ return tools;
92
+ }
93
+ function detectIncomingTelegramBrowserScreenshotRequest(input) {
94
+ if (input.kind !== "question" && input.kind !== "request") {
95
+ return false;
96
+ }
97
+ return looksLikeBrowserScreenshotRequest([input.summary ?? "", input.text].join("\n"));
98
+ }