@jsayubi/ccgram 1.0.0

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 (247) hide show
  1. package/.env.example +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +338 -0
  4. package/ccgram.service +24 -0
  5. package/config/channels.json +58 -0
  6. package/config/default.json +27 -0
  7. package/config/defaults/config.json +16 -0
  8. package/config/defaults/i18n.json +32 -0
  9. package/config/email-template.json +31 -0
  10. package/config/test-with-subagent.json +16 -0
  11. package/config/user.json +27 -0
  12. package/dist/claude-hook-notify.d.ts +7 -0
  13. package/dist/claude-hook-notify.d.ts.map +1 -0
  14. package/dist/claude-hook-notify.js +154 -0
  15. package/dist/claude-hook-notify.js.map +1 -0
  16. package/dist/claude-remote.d.ts +50 -0
  17. package/dist/claude-remote.d.ts.map +1 -0
  18. package/dist/claude-remote.js +927 -0
  19. package/dist/claude-remote.js.map +1 -0
  20. package/dist/cli.d.ts +3 -0
  21. package/dist/cli.d.ts.map +1 -0
  22. package/dist/cli.js +110 -0
  23. package/dist/cli.js.map +1 -0
  24. package/dist/enhanced-hook-notify.d.ts +16 -0
  25. package/dist/enhanced-hook-notify.d.ts.map +1 -0
  26. package/dist/enhanced-hook-notify.js +288 -0
  27. package/dist/enhanced-hook-notify.js.map +1 -0
  28. package/dist/permission-hook.d.ts +15 -0
  29. package/dist/permission-hook.d.ts.map +1 -0
  30. package/dist/permission-hook.js +357 -0
  31. package/dist/permission-hook.js.map +1 -0
  32. package/dist/prompt-bridge.d.ts +50 -0
  33. package/dist/prompt-bridge.d.ts.map +1 -0
  34. package/dist/prompt-bridge.js +173 -0
  35. package/dist/prompt-bridge.js.map +1 -0
  36. package/dist/question-notify.d.ts +16 -0
  37. package/dist/question-notify.d.ts.map +1 -0
  38. package/dist/question-notify.js +272 -0
  39. package/dist/question-notify.js.map +1 -0
  40. package/dist/setup.d.ts +10 -0
  41. package/dist/setup.d.ts.map +1 -0
  42. package/dist/setup.js +649 -0
  43. package/dist/setup.js.map +1 -0
  44. package/dist/smart-monitor.d.ts +7 -0
  45. package/dist/smart-monitor.d.ts.map +1 -0
  46. package/dist/smart-monitor.js +256 -0
  47. package/dist/smart-monitor.js.map +1 -0
  48. package/dist/src/automation/claude-automation.d.ts +45 -0
  49. package/dist/src/automation/claude-automation.d.ts.map +1 -0
  50. package/dist/src/automation/claude-automation.js +367 -0
  51. package/dist/src/automation/claude-automation.js.map +1 -0
  52. package/dist/src/automation/clipboard-automation.d.ts +35 -0
  53. package/dist/src/automation/clipboard-automation.d.ts.map +1 -0
  54. package/dist/src/automation/clipboard-automation.js +242 -0
  55. package/dist/src/automation/clipboard-automation.js.map +1 -0
  56. package/dist/src/automation/simple-automation.d.ts +56 -0
  57. package/dist/src/automation/simple-automation.d.ts.map +1 -0
  58. package/dist/src/automation/simple-automation.js +283 -0
  59. package/dist/src/automation/simple-automation.js.map +1 -0
  60. package/dist/src/channels/base/channel.d.ts +60 -0
  61. package/dist/src/channels/base/channel.d.ts.map +1 -0
  62. package/dist/src/channels/base/channel.js +96 -0
  63. package/dist/src/channels/base/channel.js.map +1 -0
  64. package/dist/src/channels/email/smtp.d.ts +74 -0
  65. package/dist/src/channels/email/smtp.d.ts.map +1 -0
  66. package/dist/src/channels/email/smtp.js +605 -0
  67. package/dist/src/channels/email/smtp.js.map +1 -0
  68. package/dist/src/channels/line/line.d.ts +36 -0
  69. package/dist/src/channels/line/line.d.ts.map +1 -0
  70. package/dist/src/channels/line/line.js +180 -0
  71. package/dist/src/channels/line/line.js.map +1 -0
  72. package/dist/src/channels/line/webhook.d.ts +55 -0
  73. package/dist/src/channels/line/webhook.d.ts.map +1 -0
  74. package/dist/src/channels/line/webhook.js +191 -0
  75. package/dist/src/channels/line/webhook.js.map +1 -0
  76. package/dist/src/channels/local/desktop.d.ts +30 -0
  77. package/dist/src/channels/local/desktop.d.ts.map +1 -0
  78. package/dist/src/channels/local/desktop.js +161 -0
  79. package/dist/src/channels/local/desktop.js.map +1 -0
  80. package/dist/src/channels/telegram/telegram.d.ts +43 -0
  81. package/dist/src/channels/telegram/telegram.d.ts.map +1 -0
  82. package/dist/src/channels/telegram/telegram.js +223 -0
  83. package/dist/src/channels/telegram/telegram.js.map +1 -0
  84. package/dist/src/channels/telegram/webhook.d.ts +75 -0
  85. package/dist/src/channels/telegram/webhook.d.ts.map +1 -0
  86. package/dist/src/channels/telegram/webhook.js +278 -0
  87. package/dist/src/channels/telegram/webhook.js.map +1 -0
  88. package/dist/src/config-manager.d.ts +16 -0
  89. package/dist/src/config-manager.d.ts.map +1 -0
  90. package/dist/src/config-manager.js +152 -0
  91. package/dist/src/config-manager.js.map +1 -0
  92. package/dist/src/core/config.d.ts +28 -0
  93. package/dist/src/core/config.d.ts.map +1 -0
  94. package/dist/src/core/config.js +248 -0
  95. package/dist/src/core/config.js.map +1 -0
  96. package/dist/src/core/logger.d.ts +19 -0
  97. package/dist/src/core/logger.d.ts.map +1 -0
  98. package/dist/src/core/logger.js +47 -0
  99. package/dist/src/core/logger.js.map +1 -0
  100. package/dist/src/core/notifier.d.ts +45 -0
  101. package/dist/src/core/notifier.d.ts.map +1 -0
  102. package/dist/src/core/notifier.js +189 -0
  103. package/dist/src/core/notifier.js.map +1 -0
  104. package/dist/src/daemon/taskping-daemon.d.ts +38 -0
  105. package/dist/src/daemon/taskping-daemon.d.ts.map +1 -0
  106. package/dist/src/daemon/taskping-daemon.js +306 -0
  107. package/dist/src/daemon/taskping-daemon.js.map +1 -0
  108. package/dist/src/relay/claude-command-bridge.d.ts +57 -0
  109. package/dist/src/relay/claude-command-bridge.d.ts.map +1 -0
  110. package/dist/src/relay/claude-command-bridge.js +188 -0
  111. package/dist/src/relay/claude-command-bridge.js.map +1 -0
  112. package/dist/src/relay/command-relay.d.ts +94 -0
  113. package/dist/src/relay/command-relay.d.ts.map +1 -0
  114. package/dist/src/relay/command-relay.js +463 -0
  115. package/dist/src/relay/command-relay.js.map +1 -0
  116. package/dist/src/relay/email-listener.d.ts +65 -0
  117. package/dist/src/relay/email-listener.d.ts.map +1 -0
  118. package/dist/src/relay/email-listener.js +460 -0
  119. package/dist/src/relay/email-listener.js.map +1 -0
  120. package/dist/src/relay/relay-pty.d.ts +21 -0
  121. package/dist/src/relay/relay-pty.d.ts.map +1 -0
  122. package/dist/src/relay/relay-pty.js +696 -0
  123. package/dist/src/relay/relay-pty.js.map +1 -0
  124. package/dist/src/relay/smart-injector.d.ts +30 -0
  125. package/dist/src/relay/smart-injector.d.ts.map +1 -0
  126. package/dist/src/relay/smart-injector.js +233 -0
  127. package/dist/src/relay/smart-injector.js.map +1 -0
  128. package/dist/src/relay/tmux-injector.d.ts +46 -0
  129. package/dist/src/relay/tmux-injector.d.ts.map +1 -0
  130. package/dist/src/relay/tmux-injector.js +413 -0
  131. package/dist/src/relay/tmux-injector.js.map +1 -0
  132. package/dist/src/tools/config-manager.d.ts +33 -0
  133. package/dist/src/tools/config-manager.d.ts.map +1 -0
  134. package/dist/src/tools/config-manager.js +448 -0
  135. package/dist/src/tools/config-manager.js.map +1 -0
  136. package/dist/src/tools/installer.d.ts +38 -0
  137. package/dist/src/tools/installer.d.ts.map +1 -0
  138. package/dist/src/tools/installer.js +222 -0
  139. package/dist/src/tools/installer.js.map +1 -0
  140. package/dist/src/types/callbacks.d.ts +29 -0
  141. package/dist/src/types/callbacks.d.ts.map +1 -0
  142. package/dist/src/types/callbacks.js +7 -0
  143. package/dist/src/types/callbacks.js.map +1 -0
  144. package/dist/src/types/config.d.ts +56 -0
  145. package/dist/src/types/config.d.ts.map +1 -0
  146. package/dist/src/types/config.js +6 -0
  147. package/dist/src/types/config.js.map +1 -0
  148. package/dist/src/types/hooks.d.ts +47 -0
  149. package/dist/src/types/hooks.d.ts.map +1 -0
  150. package/dist/src/types/hooks.js +6 -0
  151. package/dist/src/types/hooks.js.map +1 -0
  152. package/dist/src/types/index.d.ts +7 -0
  153. package/dist/src/types/index.d.ts.map +1 -0
  154. package/dist/src/types/index.js +23 -0
  155. package/dist/src/types/index.js.map +1 -0
  156. package/dist/src/types/ipc.d.ts +43 -0
  157. package/dist/src/types/ipc.d.ts.map +1 -0
  158. package/dist/src/types/ipc.js +7 -0
  159. package/dist/src/types/ipc.js.map +1 -0
  160. package/dist/src/types/session.d.ts +70 -0
  161. package/dist/src/types/session.d.ts.map +1 -0
  162. package/dist/src/types/session.js +9 -0
  163. package/dist/src/types/session.js.map +1 -0
  164. package/dist/src/types/telegram.d.ts +58 -0
  165. package/dist/src/types/telegram.d.ts.map +1 -0
  166. package/dist/src/types/telegram.js +6 -0
  167. package/dist/src/types/telegram.js.map +1 -0
  168. package/dist/src/utils/active-check.d.ts +19 -0
  169. package/dist/src/utils/active-check.d.ts.map +1 -0
  170. package/dist/src/utils/active-check.js +41 -0
  171. package/dist/src/utils/active-check.js.map +1 -0
  172. package/dist/src/utils/callback-parser.d.ts +21 -0
  173. package/dist/src/utils/callback-parser.d.ts.map +1 -0
  174. package/dist/src/utils/callback-parser.js +58 -0
  175. package/dist/src/utils/callback-parser.js.map +1 -0
  176. package/dist/src/utils/controller-injector.d.ts +21 -0
  177. package/dist/src/utils/controller-injector.d.ts.map +1 -0
  178. package/dist/src/utils/controller-injector.js +108 -0
  179. package/dist/src/utils/controller-injector.js.map +1 -0
  180. package/dist/src/utils/conversation-tracker.d.ts +32 -0
  181. package/dist/src/utils/conversation-tracker.d.ts.map +1 -0
  182. package/dist/src/utils/conversation-tracker.js +119 -0
  183. package/dist/src/utils/conversation-tracker.js.map +1 -0
  184. package/dist/src/utils/http-request.d.ts +25 -0
  185. package/dist/src/utils/http-request.d.ts.map +1 -0
  186. package/dist/src/utils/http-request.js +66 -0
  187. package/dist/src/utils/http-request.js.map +1 -0
  188. package/dist/src/utils/optional-require.d.ts +13 -0
  189. package/dist/src/utils/optional-require.d.ts.map +1 -0
  190. package/dist/src/utils/optional-require.js +37 -0
  191. package/dist/src/utils/optional-require.js.map +1 -0
  192. package/dist/src/utils/paths.d.ts +11 -0
  193. package/dist/src/utils/paths.d.ts.map +1 -0
  194. package/dist/src/utils/paths.js +28 -0
  195. package/dist/src/utils/paths.js.map +1 -0
  196. package/dist/src/utils/pty-session-manager.d.ts +42 -0
  197. package/dist/src/utils/pty-session-manager.d.ts.map +1 -0
  198. package/dist/src/utils/pty-session-manager.js +182 -0
  199. package/dist/src/utils/pty-session-manager.js.map +1 -0
  200. package/dist/src/utils/subagent-tracker.d.ts +64 -0
  201. package/dist/src/utils/subagent-tracker.d.ts.map +1 -0
  202. package/dist/src/utils/subagent-tracker.js +191 -0
  203. package/dist/src/utils/subagent-tracker.js.map +1 -0
  204. package/dist/src/utils/tmux-monitor.d.ts +102 -0
  205. package/dist/src/utils/tmux-monitor.d.ts.map +1 -0
  206. package/dist/src/utils/tmux-monitor.js +642 -0
  207. package/dist/src/utils/tmux-monitor.js.map +1 -0
  208. package/dist/src/utils/trace-capture.d.ts +42 -0
  209. package/dist/src/utils/trace-capture.d.ts.map +1 -0
  210. package/dist/src/utils/trace-capture.js +102 -0
  211. package/dist/src/utils/trace-capture.js.map +1 -0
  212. package/dist/start-all-webhooks.d.ts +7 -0
  213. package/dist/start-all-webhooks.d.ts.map +1 -0
  214. package/dist/start-all-webhooks.js +98 -0
  215. package/dist/start-all-webhooks.js.map +1 -0
  216. package/dist/start-line-webhook.d.ts +7 -0
  217. package/dist/start-line-webhook.d.ts.map +1 -0
  218. package/dist/start-line-webhook.js +59 -0
  219. package/dist/start-line-webhook.js.map +1 -0
  220. package/dist/start-relay-pty.d.ts +7 -0
  221. package/dist/start-relay-pty.d.ts.map +1 -0
  222. package/dist/start-relay-pty.js +173 -0
  223. package/dist/start-relay-pty.js.map +1 -0
  224. package/dist/start-telegram-webhook.d.ts +7 -0
  225. package/dist/start-telegram-webhook.d.ts.map +1 -0
  226. package/dist/start-telegram-webhook.js +80 -0
  227. package/dist/start-telegram-webhook.js.map +1 -0
  228. package/dist/user-prompt-hook.d.ts +13 -0
  229. package/dist/user-prompt-hook.d.ts.map +1 -0
  230. package/dist/user-prompt-hook.js +45 -0
  231. package/dist/user-prompt-hook.js.map +1 -0
  232. package/dist/workspace-router.d.ts +78 -0
  233. package/dist/workspace-router.d.ts.map +1 -0
  234. package/dist/workspace-router.js +408 -0
  235. package/dist/workspace-router.js.map +1 -0
  236. package/dist/workspace-telegram-bot.d.ts +3 -0
  237. package/dist/workspace-telegram-bot.d.ts.map +1 -0
  238. package/dist/workspace-telegram-bot.js +1172 -0
  239. package/dist/workspace-telegram-bot.js.map +1 -0
  240. package/package.json +80 -0
  241. package/src/types/callbacks.ts +39 -0
  242. package/src/types/config.ts +63 -0
  243. package/src/types/hooks.ts +50 -0
  244. package/src/types/index.ts +6 -0
  245. package/src/types/ipc.ts +55 -0
  246. package/src/types/session.ts +72 -0
  247. package/src/types/telegram.ts +66 -0
@@ -0,0 +1,357 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Permission Hook — Called by Claude Code's PermissionRequest hook.
5
+ *
6
+ * Blocking approach:
7
+ * 1. Sends a Telegram message with inline keyboard buttons
8
+ * 2. Polls for a response file written by the bot's callback handler
9
+ * 3. Outputs the permission decision via stdout
10
+ * 4. Exits cleanly
11
+ *
12
+ * Stdin JSON: { tool_name, tool_input, cwd, session_id, hook_event_name }
13
+ * Stdout JSON: { hookSpecificOutput: { hookEventName, decision: { behavior } } }
14
+ */
15
+ var __importDefault = (this && this.__importDefault) || function (mod) {
16
+ return (mod && mod.__esModule) ? mod : { "default": mod };
17
+ };
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ const path_1 = __importDefault(require("path"));
20
+ const paths_1 = require("./src/utils/paths");
21
+ require('dotenv').config({ path: path_1.default.join(paths_1.PROJECT_ROOT, '.env'), quiet: true });
22
+ const fs_1 = __importDefault(require("fs"));
23
+ const https_1 = __importDefault(require("https"));
24
+ const child_process_1 = require("child_process");
25
+ const workspace_router_1 = require("./workspace-router");
26
+ const prompt_bridge_1 = require("./prompt-bridge");
27
+ const active_check_1 = require("./src/utils/active-check");
28
+ const BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN;
29
+ const CHAT_ID = process.env.TELEGRAM_CHAT_ID;
30
+ const POLL_INTERVAL_MS = 500;
31
+ const POLL_TIMEOUT_MS = 90000; // 90 seconds max wait
32
+ // Debug logging to file (since stdout is for Claude Code)
33
+ const LOG_FILE = path_1.default.join(paths_1.PROJECT_ROOT, 'logs', 'permission-hook-debug.log');
34
+ function debugLog(msg) {
35
+ const ts = new Date().toISOString();
36
+ try {
37
+ fs_1.default.appendFileSync(LOG_FILE, `${ts} ${msg}\n`);
38
+ }
39
+ catch { }
40
+ }
41
+ // ── Main ────────────────────────────────────────────────────────
42
+ async function main() {
43
+ const raw = await readStdin();
44
+ let payload;
45
+ try {
46
+ payload = JSON.parse(raw);
47
+ }
48
+ catch {
49
+ return; // Can't parse — exit without decision
50
+ }
51
+ const toolName = payload.tool_name || 'Unknown';
52
+ // AskUserQuestion: exit silently so Claude Code shows the interactive
53
+ // question/permission UI in the terminal. The question-notify.js PreToolUse
54
+ // hook sends the Telegram notification. Clicking an option injects arrow
55
+ // keys + Enter which both selects the answer AND grants permission.
56
+ if (toolName === 'AskUserQuestion') {
57
+ return;
58
+ }
59
+ // If user is actively at the terminal AND this wasn't injected from Telegram,
60
+ // exit without a decision so Claude Code shows its own permission UI locally.
61
+ // Uses the same 300s (5 min) threshold as notification hooks.
62
+ // If user stepped away more than 5 min ago, Telegram handles the permission
63
+ // so Claude isn't left stuck waiting with no way to respond.
64
+ const typingActivePath = path_1.default.join(paths_1.PROJECT_ROOT, 'src/data', 'typing-active');
65
+ const isTelegramInjected = fs_1.default.existsSync(typingActivePath);
66
+ if (!isTelegramInjected && (0, active_check_1.isUserActiveAtTerminal)()) {
67
+ debugLog(`[skip] User is at terminal (within 5 min) — deferring to Claude Code's own permission UI`);
68
+ return;
69
+ }
70
+ const toolInput = (payload.tool_input || {});
71
+ const cwd = payload.cwd || process.cwd();
72
+ const workspace = (0, workspace_router_1.extractWorkspaceName)(cwd);
73
+ const promptId = (0, prompt_bridge_1.generatePromptId)();
74
+ const tmuxSession = detectSessionName(cwd);
75
+ const isPlan = toolName === 'ExitPlanMode';
76
+ // Build Telegram message and keyboard
77
+ let messageText;
78
+ let keyboard;
79
+ if (isPlan) {
80
+ // Plan approval — try to capture plan content from tmux
81
+ let planContent = '';
82
+ if (tmuxSession) {
83
+ try {
84
+ const paneOutput = (0, child_process_1.execSync)(`tmux capture-pane -t ${tmuxSession} -p -S -50 2>/dev/null`, { encoding: 'utf8', timeout: 3000 });
85
+ planContent = cleanPlanOutput(paneOutput);
86
+ }
87
+ catch { }
88
+ }
89
+ messageText = `\u{1F4CB} *Plan Approval* — ${escapeMarkdown(workspace)}`;
90
+ if (planContent) {
91
+ const truncated = planContent.length > 2500
92
+ ? planContent.slice(0, 2497) + '...'
93
+ : planContent;
94
+ messageText += `\n\n${truncated}`;
95
+ }
96
+ keyboard = {
97
+ inline_keyboard: [
98
+ [
99
+ { text: '\u2705 Approve', callback_data: `perm:${promptId}:allow` },
100
+ { text: '\u274C Reject', callback_data: `perm:${promptId}:deny` },
101
+ ],
102
+ ],
103
+ };
104
+ }
105
+ else {
106
+ // Tool permission request
107
+ const toolDescription = formatToolDescription(toolName, toolInput);
108
+ messageText = `\u{1F510} *Permission* — ${escapeMarkdown(workspace)}\n\n*Tool:* ${escapeMarkdown(toolName)}`;
109
+ if (toolDescription) {
110
+ const truncated = toolDescription.length > 2500
111
+ ? toolDescription.slice(0, 2497) + '...'
112
+ : toolDescription;
113
+ messageText += `\n${truncated}`;
114
+ }
115
+ keyboard = {
116
+ inline_keyboard: [
117
+ [
118
+ { text: '\u2705 Allow', callback_data: `perm:${promptId}:allow` },
119
+ { text: '\u274C Deny', callback_data: `perm:${promptId}:deny` },
120
+ { text: '\u{1F513} Always', callback_data: `perm:${promptId}:always` },
121
+ ],
122
+ ],
123
+ };
124
+ }
125
+ // Write pending file so bot callback handler can write the response
126
+ (0, prompt_bridge_1.writePending)(promptId, {
127
+ type: isPlan ? 'plan' : 'permission',
128
+ workspace,
129
+ toolName,
130
+ toolInput,
131
+ tmuxSession,
132
+ });
133
+ // Send Telegram message with inline keyboard
134
+ debugLog(`[${promptId}] Sending Telegram message for ${toolName}...`);
135
+ try {
136
+ const result = await sendTelegramWithKeyboard(messageText, keyboard);
137
+ debugLog(`[${promptId}] Telegram message sent`);
138
+ if (result && result.message_id) {
139
+ (0, workspace_router_1.trackNotificationMessage)(result.message_id, workspace, 'permission');
140
+ }
141
+ }
142
+ catch (err) {
143
+ debugLog(`[${promptId}] Telegram send failed: ${err.message}`);
144
+ process.stderr.write(`[permission-hook] Telegram send failed: ${err.message}\n`);
145
+ (0, prompt_bridge_1.cleanPrompt)(promptId);
146
+ return; // Can't notify — exit without decision
147
+ }
148
+ // Poll for response file
149
+ debugLog(`[${promptId}] Starting to poll for response...`);
150
+ const response = await pollForResponse(promptId);
151
+ if (response) {
152
+ const action = response.action || 'allow';
153
+ debugLog(`[${promptId}] Got response: action=${action}`);
154
+ let decision;
155
+ if (action === 'deny') {
156
+ decision = 'deny';
157
+ }
158
+ else {
159
+ decision = 'allow';
160
+ }
161
+ const output = {
162
+ hookSpecificOutput: {
163
+ hookEventName: 'PermissionRequest',
164
+ decision: {
165
+ behavior: decision,
166
+ },
167
+ },
168
+ systemMessage: `Decision received via Telegram: user ${decision}ed`,
169
+ };
170
+ const outputStr = JSON.stringify(output);
171
+ debugLog(`[${promptId}] Writing to stdout: ${outputStr}`);
172
+ process.stdout.write(outputStr + '\n');
173
+ debugLog(`[${promptId}] Stdout written`);
174
+ }
175
+ else {
176
+ debugLog(`[${promptId}] No response received (timed out or error)`);
177
+ }
178
+ // Clean up
179
+ (0, prompt_bridge_1.cleanPrompt)(promptId);
180
+ debugLog(`[${promptId}] Cleaned up, letting process exit naturally`);
181
+ }
182
+ // ── Polling ─────────────────────────────────────────────────────
183
+ function pollForResponse(promptId) {
184
+ return new Promise((resolve) => {
185
+ const responseFile = path_1.default.join(prompt_bridge_1.PROMPTS_DIR, `response-${promptId}.json`);
186
+ const startTime = Date.now();
187
+ const interval = setInterval(() => {
188
+ // Check timeout
189
+ if (Date.now() - startTime > POLL_TIMEOUT_MS) {
190
+ clearInterval(interval);
191
+ process.stderr.write(`[permission-hook] Timed out waiting for response\n`);
192
+ resolve(null);
193
+ return;
194
+ }
195
+ // Check for response file
196
+ try {
197
+ if (fs_1.default.existsSync(responseFile)) {
198
+ const raw = fs_1.default.readFileSync(responseFile, 'utf8');
199
+ const data = JSON.parse(raw);
200
+ clearInterval(interval);
201
+ resolve(data);
202
+ }
203
+ }
204
+ catch {
205
+ // File not ready yet or parse error — keep polling
206
+ }
207
+ }, POLL_INTERVAL_MS);
208
+ });
209
+ }
210
+ // ── Telegram ────────────────────────────────────────────────────
211
+ function sendTelegramWithKeyboard(text, replyMarkup) {
212
+ return new Promise((resolve, reject) => {
213
+ const body = JSON.stringify({
214
+ chat_id: CHAT_ID,
215
+ text,
216
+ parse_mode: 'Markdown',
217
+ reply_markup: replyMarkup,
218
+ });
219
+ const options = {
220
+ hostname: 'api.telegram.org',
221
+ path: `/bot${BOT_TOKEN}/sendMessage`,
222
+ method: 'POST',
223
+ headers: {
224
+ 'Content-Type': 'application/json',
225
+ 'Content-Length': Buffer.byteLength(body),
226
+ },
227
+ timeout: 5000,
228
+ };
229
+ const req = https_1.default.request(options, (res) => {
230
+ let data = '';
231
+ res.on('data', (chunk) => { data += chunk; });
232
+ res.on('end', () => {
233
+ if (res.statusCode >= 200 && res.statusCode < 300) {
234
+ try {
235
+ const parsed = JSON.parse(data);
236
+ resolve(parsed.result || null);
237
+ }
238
+ catch {
239
+ resolve(null);
240
+ }
241
+ }
242
+ else {
243
+ reject(new Error(`Telegram API ${res.statusCode}: ${data}`));
244
+ }
245
+ });
246
+ });
247
+ req.on('error', reject);
248
+ req.on('timeout', () => {
249
+ req.destroy();
250
+ reject(new Error('Telegram request timed out'));
251
+ });
252
+ req.write(body);
253
+ req.end();
254
+ });
255
+ }
256
+ // ── Helpers ──────────────────────────────────────────────────────
257
+ function readStdin() {
258
+ return new Promise((resolve) => {
259
+ let data = '';
260
+ let resolved = false;
261
+ process.stdin.setEncoding('utf8');
262
+ process.stdin.on('data', (chunk) => { data += chunk; });
263
+ process.stdin.on('end', () => {
264
+ if (!resolved) {
265
+ resolved = true;
266
+ resolve(data);
267
+ }
268
+ });
269
+ setTimeout(() => {
270
+ if (!resolved) {
271
+ resolved = true;
272
+ process.stdin.destroy();
273
+ resolve(data || '{}');
274
+ }
275
+ }, 500);
276
+ });
277
+ }
278
+ function detectSessionName(cwd) {
279
+ // 1. Try tmux (existing behaviour)
280
+ if (process.env.TMUX) {
281
+ try {
282
+ return (0, child_process_1.execSync)('tmux display-message -p "#S"', { encoding: 'utf8' }).trim();
283
+ }
284
+ catch { }
285
+ }
286
+ // 2. Derive from CWD — apply the same sanitization /new uses for session names
287
+ // (dots, colons, spaces → hyphens) so the name matches the PTY handle key
288
+ const raw = (0, workspace_router_1.extractWorkspaceName)(cwd);
289
+ if (!raw)
290
+ return null;
291
+ return raw.replace(/[.:\s]/g, '-');
292
+ }
293
+ function formatToolDescription(toolName, toolInput) {
294
+ if (toolName === 'Bash' && toolInput.command) {
295
+ const cmd = toolInput.command;
296
+ const truncated = cmd.length > 500 ? cmd.slice(0, 497) + '...' : cmd;
297
+ return `*Command:* \`${escapeMarkdown(truncated)}\``;
298
+ }
299
+ if (toolName === 'Edit' && toolInput.file_path) {
300
+ const filePath = escapeMarkdown(toolInput.file_path);
301
+ if (toolInput.old_string && toolInput.new_string) {
302
+ const maxLines = 12;
303
+ const oldLines = toolInput.old_string.split('\n');
304
+ const newLines = toolInput.new_string.split('\n');
305
+ const oldTrunc = oldLines.length > maxLines;
306
+ const newTrunc = newLines.length > maxLines;
307
+ const oldStr = oldLines.slice(0, maxLines).map(l => `- ${l}`).join('\n') + (oldTrunc ? '\n ...' : '');
308
+ const newStr = newLines.slice(0, maxLines).map(l => `+ ${l}`).join('\n') + (newTrunc ? '\n ...' : '');
309
+ return `*File:* \`${filePath}\`\n\`\`\`\n${oldStr}\n${newStr}\n\`\`\``;
310
+ }
311
+ return `*File:* \`${filePath}\``;
312
+ }
313
+ if (toolName === 'Write' && toolInput.file_path) {
314
+ return `*File:* \`${escapeMarkdown(toolInput.file_path)}\``;
315
+ }
316
+ if (toolName === 'Read' && toolInput.file_path) {
317
+ return `*File:* \`${escapeMarkdown(toolInput.file_path)}\``;
318
+ }
319
+ const keys = Object.keys(toolInput);
320
+ if (keys.length > 0) {
321
+ const key = keys[0];
322
+ const val = String(toolInput[key]).slice(0, 200);
323
+ return `*${escapeMarkdown(key)}:* \`${escapeMarkdown(val)}\``;
324
+ }
325
+ return '';
326
+ }
327
+ function cleanPlanOutput(raw) {
328
+ let lines = raw.split('\n');
329
+ lines = lines.map(l => l
330
+ .replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '')
331
+ .replace(/\x1B\][^\x07]*\x07/g, ''));
332
+ while (lines.length && !lines[lines.length - 1].trim())
333
+ lines.pop();
334
+ while (lines.length && !lines[0].trim())
335
+ lines.shift();
336
+ lines = lines.filter(l => {
337
+ const t = l.trim();
338
+ if (!t)
339
+ return true;
340
+ if (/^[\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F]/.test(t))
341
+ return false;
342
+ if (/^(Clauding|Working|Waiting|Processing)/i.test(t))
343
+ return false;
344
+ if (/^.+\|.+\|.+\|.+\$/.test(t))
345
+ return false;
346
+ return true;
347
+ });
348
+ return lines.join('\n').trim();
349
+ }
350
+ function escapeMarkdown(text) {
351
+ return text.replace(/([_*`\[])/g, '\\$1');
352
+ }
353
+ // ── Run ─────────────────────────────────────────────────────────
354
+ main().catch((err) => {
355
+ process.stderr.write(`[permission-hook] Fatal: ${err.message}\n`);
356
+ });
357
+ //# sourceMappingURL=permission-hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permission-hook.js","sourceRoot":"","sources":["../permission-hook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Prompt Bridge — File-based IPC for Claude Code interactive prompts.
4
+ *
5
+ * Manages /tmp/claude-prompts/ directory with pending/response files
6
+ * so that hooks (permission-hook.js, question-notify.js) can communicate
7
+ * with the Telegram bot's callback query handler.
8
+ *
9
+ * File format:
10
+ * pending-<id>.json — written by hook, read by bot callback handler
11
+ * response-<id>.json — written by bot callback handler, read by hook
12
+ */
13
+ declare const PROMPTS_DIR: string;
14
+ /** Generate a unique 8-char prompt ID. */
15
+ declare function generatePromptId(): string;
16
+ /**
17
+ * Write a pending prompt file.
18
+ */
19
+ declare function writePending(id: string, data: Record<string, unknown>): void;
20
+ /**
21
+ * Write a response file (from bot callback).
22
+ */
23
+ declare function writeResponse(id: string, data: Record<string, unknown>): void;
24
+ /**
25
+ * Read a response file if it exists.
26
+ */
27
+ declare function readResponse(id: string): Record<string, unknown> | null;
28
+ /**
29
+ * Read a pending prompt file.
30
+ */
31
+ declare function readPending(id: string): Record<string, unknown> | null;
32
+ /**
33
+ * Check if there's a pending prompt for a given workspace.
34
+ * Used by enhanced-hook-notify.js for deduplication.
35
+ */
36
+ declare function hasPendingForWorkspace(workspace: string): boolean;
37
+ /**
38
+ * Remove pending and response files older than EXPIRY_MS.
39
+ */
40
+ declare function cleanExpired(): void;
41
+ /**
42
+ * Remove pending and response files for a given prompt ID.
43
+ */
44
+ declare function cleanPrompt(id: string): void;
45
+ /**
46
+ * Update fields on an existing pending prompt file.
47
+ */
48
+ declare function updatePending(id: string, updates: Record<string, unknown>): void;
49
+ export { generatePromptId, writePending, updatePending, writeResponse, readResponse, readPending, hasPendingForWorkspace, cleanExpired, cleanPrompt, PROMPTS_DIR, };
50
+ //# sourceMappingURL=prompt-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-bridge.d.ts","sourceRoot":"","sources":["../prompt-bridge.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;GAUG;AAMH,QAAA,MAAM,WAAW,QAAmD,CAAC;AAUrE,0CAA0C;AAC1C,iBAAS,gBAAgB,IAAI,MAAM,CAElC;AAED;;GAEG;AACH,iBAAS,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAKrE;AAED;;GAEG;AACH,iBAAS,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAItE;AAED;;GAEG;AACH,iBAAS,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAQhE;AAED;;GAEG;AACH,iBAAS,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAQ/D;AAED;;;GAGG;AACH,iBAAS,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAyB1D;AAED;;GAEG;AACH,iBAAS,YAAY,IAAI,IAAI,CAqB5B;AAED;;GAEG;AACH,iBAAS,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAKrC;AAED;;GAEG;AACH,iBAAS,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAKzE;AAED,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,YAAY,EACZ,WAAW,EACX,sBAAsB,EACtB,YAAY,EACZ,WAAW,EACX,WAAW,GACZ,CAAC"}
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Prompt Bridge — File-based IPC for Claude Code interactive prompts.
5
+ *
6
+ * Manages /tmp/claude-prompts/ directory with pending/response files
7
+ * so that hooks (permission-hook.js, question-notify.js) can communicate
8
+ * with the Telegram bot's callback query handler.
9
+ *
10
+ * File format:
11
+ * pending-<id>.json — written by hook, read by bot callback handler
12
+ * response-<id>.json — written by bot callback handler, read by hook
13
+ */
14
+ var __importDefault = (this && this.__importDefault) || function (mod) {
15
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16
+ };
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.PROMPTS_DIR = void 0;
19
+ exports.generatePromptId = generatePromptId;
20
+ exports.writePending = writePending;
21
+ exports.updatePending = updatePending;
22
+ exports.writeResponse = writeResponse;
23
+ exports.readResponse = readResponse;
24
+ exports.readPending = readPending;
25
+ exports.hasPendingForWorkspace = hasPendingForWorkspace;
26
+ exports.cleanExpired = cleanExpired;
27
+ exports.cleanPrompt = cleanPrompt;
28
+ const fs_1 = __importDefault(require("fs"));
29
+ const path_1 = __importDefault(require("path"));
30
+ const crypto_1 = __importDefault(require("crypto"));
31
+ const PROMPTS_DIR = process.env.PROMPTS_DIR || '/tmp/claude-prompts';
32
+ exports.PROMPTS_DIR = PROMPTS_DIR;
33
+ const EXPIRY_MS = 5 * 60 * 1000; // 5 minutes
34
+ /** Ensure the prompts directory exists. */
35
+ function ensureDir() {
36
+ if (!fs_1.default.existsSync(PROMPTS_DIR)) {
37
+ fs_1.default.mkdirSync(PROMPTS_DIR, { recursive: true });
38
+ }
39
+ }
40
+ /** Generate a unique 8-char prompt ID. */
41
+ function generatePromptId() {
42
+ return crypto_1.default.randomBytes(4).toString('hex');
43
+ }
44
+ /**
45
+ * Write a pending prompt file.
46
+ */
47
+ function writePending(id, data) {
48
+ ensureDir();
49
+ cleanExpired();
50
+ const filePath = path_1.default.join(PROMPTS_DIR, `pending-${id}.json`);
51
+ fs_1.default.writeFileSync(filePath, JSON.stringify({ ...data, createdAt: Date.now() }, null, 2));
52
+ }
53
+ /**
54
+ * Write a response file (from bot callback).
55
+ */
56
+ function writeResponse(id, data) {
57
+ ensureDir();
58
+ const filePath = path_1.default.join(PROMPTS_DIR, `response-${id}.json`);
59
+ fs_1.default.writeFileSync(filePath, JSON.stringify({ ...data, respondedAt: Date.now() }, null, 2));
60
+ }
61
+ /**
62
+ * Read a response file if it exists.
63
+ */
64
+ function readResponse(id) {
65
+ const filePath = path_1.default.join(PROMPTS_DIR, `response-${id}.json`);
66
+ try {
67
+ const raw = fs_1.default.readFileSync(filePath, 'utf8');
68
+ return JSON.parse(raw);
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ }
74
+ /**
75
+ * Read a pending prompt file.
76
+ */
77
+ function readPending(id) {
78
+ const filePath = path_1.default.join(PROMPTS_DIR, `pending-${id}.json`);
79
+ try {
80
+ const raw = fs_1.default.readFileSync(filePath, 'utf8');
81
+ return JSON.parse(raw);
82
+ }
83
+ catch {
84
+ return null;
85
+ }
86
+ }
87
+ /**
88
+ * Check if there's a pending prompt for a given workspace.
89
+ * Used by enhanced-hook-notify.js for deduplication.
90
+ */
91
+ function hasPendingForWorkspace(workspace) {
92
+ ensureDir();
93
+ try {
94
+ const files = fs_1.default.readdirSync(PROMPTS_DIR);
95
+ for (const file of files) {
96
+ if (!file.startsWith('pending-'))
97
+ continue;
98
+ try {
99
+ const raw = fs_1.default.readFileSync(path_1.default.join(PROMPTS_DIR, file), 'utf8');
100
+ const data = JSON.parse(raw);
101
+ // Only count non-expired pending files
102
+ if (data.workspace === workspace && (Date.now() - data.createdAt) < EXPIRY_MS) {
103
+ // Check that no response exists for this prompt
104
+ const id = file.replace('pending-', '').replace('.json', '');
105
+ if (!readResponse(id)) {
106
+ return true;
107
+ }
108
+ }
109
+ }
110
+ catch {
111
+ // Skip malformed files
112
+ }
113
+ }
114
+ }
115
+ catch {
116
+ // Directory read failed
117
+ }
118
+ return false;
119
+ }
120
+ /**
121
+ * Remove pending and response files older than EXPIRY_MS.
122
+ */
123
+ function cleanExpired() {
124
+ try {
125
+ if (!fs_1.default.existsSync(PROMPTS_DIR))
126
+ return;
127
+ const files = fs_1.default.readdirSync(PROMPTS_DIR);
128
+ const now = Date.now();
129
+ for (const file of files) {
130
+ if (!file.endsWith('.json'))
131
+ continue;
132
+ const filePath = path_1.default.join(PROMPTS_DIR, file);
133
+ try {
134
+ const stat = fs_1.default.statSync(filePath);
135
+ if (now - stat.mtimeMs > EXPIRY_MS) {
136
+ fs_1.default.unlinkSync(filePath);
137
+ }
138
+ }
139
+ catch {
140
+ // Skip if file was already removed
141
+ }
142
+ }
143
+ }
144
+ catch {
145
+ // Directory doesn't exist or isn't readable
146
+ }
147
+ }
148
+ /**
149
+ * Remove pending and response files for a given prompt ID.
150
+ */
151
+ function cleanPrompt(id) {
152
+ const pending = path_1.default.join(PROMPTS_DIR, `pending-${id}.json`);
153
+ const response = path_1.default.join(PROMPTS_DIR, `response-${id}.json`);
154
+ try {
155
+ fs_1.default.unlinkSync(pending);
156
+ }
157
+ catch { }
158
+ try {
159
+ fs_1.default.unlinkSync(response);
160
+ }
161
+ catch { }
162
+ }
163
+ /**
164
+ * Update fields on an existing pending prompt file.
165
+ */
166
+ function updatePending(id, updates) {
167
+ const existing = readPending(id);
168
+ if (!existing)
169
+ return;
170
+ const filePath = path_1.default.join(PROMPTS_DIR, `pending-${id}.json`);
171
+ fs_1.default.writeFileSync(filePath, JSON.stringify({ ...existing, ...updates }, null, 2));
172
+ }
173
+ //# sourceMappingURL=prompt-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-bridge.js","sourceRoot":"","sources":["../prompt-bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Question Notify — Called by Claude Code's PreToolUse hook (matcher: AskUserQuestion).
4
+ *
5
+ * Non-blocking: sends a Telegram message with option buttons, then returns
6
+ * without stdout output. AskUserQuestion must be in the permissions allow
7
+ * list (settings.json) so Claude Code handles permission automatically.
8
+ * The bot callback handler later injects the selected option number via tmux.
9
+ *
10
+ * Stdin JSON: { tool_name, tool_input, cwd, session_id, hook_event_name }
11
+ * tool_input.questions: [{ question, header, options: [{ label, description }], multiSelect }]
12
+ *
13
+ * Stdout: (none — intentionally omitted so Claude Code shows the interactive question UI)
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=question-notify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-notify.d.ts","sourceRoot":"","sources":["../question-notify.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;GAYG"}