@jsayubi/ccgram 1.1.1 → 1.2.1

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 (55) hide show
  1. package/.env.example +3 -0
  2. package/README.md +82 -51
  3. package/dist/elicitation-notify.d.ts +20 -0
  4. package/dist/elicitation-notify.d.ts.map +1 -0
  5. package/dist/elicitation-notify.js +241 -0
  6. package/dist/elicitation-notify.js.map +1 -0
  7. package/dist/enhanced-hook-notify.d.ts +8 -1
  8. package/dist/enhanced-hook-notify.d.ts.map +1 -1
  9. package/dist/enhanced-hook-notify.js +119 -5
  10. package/dist/enhanced-hook-notify.js.map +1 -1
  11. package/dist/permission-denied-notify.d.ts +11 -0
  12. package/dist/permission-denied-notify.d.ts.map +1 -0
  13. package/dist/permission-denied-notify.js +193 -0
  14. package/dist/permission-denied-notify.js.map +1 -0
  15. package/dist/permission-hook.js +43 -18
  16. package/dist/permission-hook.js.map +1 -1
  17. package/dist/pre-compact-notify.d.ts +13 -0
  18. package/dist/pre-compact-notify.d.ts.map +1 -0
  19. package/dist/pre-compact-notify.js +197 -0
  20. package/dist/pre-compact-notify.js.map +1 -0
  21. package/dist/question-notify.d.ts +6 -5
  22. package/dist/question-notify.d.ts.map +1 -1
  23. package/dist/question-notify.js +107 -23
  24. package/dist/question-notify.js.map +1 -1
  25. package/dist/setup.js +26 -10
  26. package/dist/setup.js.map +1 -1
  27. package/dist/src/types/callbacks.d.ts +11 -1
  28. package/dist/src/types/callbacks.d.ts.map +1 -1
  29. package/dist/src/types/session.d.ts +13 -1
  30. package/dist/src/types/session.d.ts.map +1 -1
  31. package/dist/src/utils/callback-parser.d.ts +7 -5
  32. package/dist/src/utils/callback-parser.d.ts.map +1 -1
  33. package/dist/src/utils/callback-parser.js +11 -5
  34. package/dist/src/utils/callback-parser.js.map +1 -1
  35. package/dist/src/utils/deep-link.d.ts +22 -0
  36. package/dist/src/utils/deep-link.d.ts.map +1 -0
  37. package/dist/src/utils/deep-link.js +43 -0
  38. package/dist/src/utils/deep-link.js.map +1 -0
  39. package/dist/src/utils/ghostty-session-manager.d.ts +81 -0
  40. package/dist/src/utils/ghostty-session-manager.d.ts.map +1 -0
  41. package/dist/src/utils/ghostty-session-manager.js +370 -0
  42. package/dist/src/utils/ghostty-session-manager.js.map +1 -0
  43. package/dist/src/utils/transcript-reader.d.ts +57 -0
  44. package/dist/src/utils/transcript-reader.d.ts.map +1 -0
  45. package/dist/src/utils/transcript-reader.js +229 -0
  46. package/dist/src/utils/transcript-reader.js.map +1 -0
  47. package/dist/workspace-router.d.ts +19 -4
  48. package/dist/workspace-router.d.ts.map +1 -1
  49. package/dist/workspace-router.js +57 -1
  50. package/dist/workspace-router.js.map +1 -1
  51. package/dist/workspace-telegram-bot.js +515 -114
  52. package/dist/workspace-telegram-bot.js.map +1 -1
  53. package/package.json +1 -1
  54. package/src/types/callbacks.ts +15 -1
  55. package/src/types/session.ts +14 -1
package/.env.example CHANGED
@@ -16,4 +16,7 @@ TELEGRAM_CHAT_ID=
16
16
  # Suppress Telegram notifications when actively at terminal (seconds, default: 300)
17
17
  # ACTIVE_THRESHOLD_SECONDS=300
18
18
 
19
+ # Injection backend: tmux (default), ghostty, or pty
20
+ # INJECTION_MODE=ghostty
21
+
19
22
  # For advanced options (email relay, LINE, webhooks), see .env.full-example
package/README.md CHANGED
@@ -18,20 +18,23 @@ CCGram is a self-hosted Telegram bot that bridges Claude Code to your phone. Whe
18
18
  ```
19
19
  Claude Code → ccgram hooks → Telegram bot → 📱 your phone
20
20
  ↑ ↓
21
- └──── tmux or PTY injection ─────┘
21
+ └─ updatedInput / tmux / Ghostty / PTY ─┘
22
22
  ```
23
23
 
24
24
  ## Features
25
25
 
26
- - **Permission approvals** — Allow, Deny, or Always allow with a single tap
27
- - **Question answering** — Select from Claude's options via inline buttons (single and multi-select)
28
- - **Smart notifications** — Task completions, session start/end, and subagent activity silent when you're at your terminal, instant when you're away
26
+ - **Universal terminal support** — Works with tmux, Ghostty, bare zsh, screen anything. Question answers flow back to Claude Code directly via the `updatedInput` hook output, no keystroke injection needed.
27
+ - **Permission approvals** — Allow, Deny, Always, or Defer with a single tap
28
+ - **Question answering** — Single-select, multi-select, and free-text questions answered via Telegram buttons
29
+ - **Rich `/status`** — Model, version, git branch, session ID, context window % (auto-detects 1M mode), rate limit + reset time, last activity, last assistant message — all from Claude Code's transcript
30
+ - **MCP elicitation forwarding** — Schema-aware MCP server input requests routed to Telegram, one prompt per form field
31
+ - **Smart notifications** — Task completions, errors, compaction, session lifecycle, subagent activity — silent at your terminal, instant when you're away
29
32
  - **Remote command routing** — Send any command to any Claude session from Telegram
30
- - **Session management** — List, switch between, and interrupt active sessions
31
- - **Resume conversations** — `/resume` reads your full Claude Code session history with conversation snippets — pick up any past conversation in one tap
33
+ - **Session management** — List, switch, interrupt; resume past conversations with `/resume`
32
34
  - **Project launcher** — Start Claude in any project directory with `/new myproject`
35
+ - **Deep links** — `/link <prompt>` generates `claude-cli://open?q=...` URLs
33
36
  - **Smart routing** — Prefix matching, default workspace, reply-to routing
34
- - **Typing indicator** — See when the bot is waiting for Claude to respond
37
+ - **Ghostty support** — Auto-detected on macOS via `TERM_PROGRAM=ghostty`; full keystroke injection via AppleScript
35
38
  - **tmux optional** — Falls back to a headless PTY session (`node-pty`) when tmux is unavailable
36
39
  - **One-command setup** — Interactive wizard installs hooks, generates service file, starts bot
37
40
 
@@ -40,7 +43,10 @@ Claude Code → ccgram hooks → Telegram bot → 📱 your phone
40
43
  - [Node.js](https://nodejs.org) 18+
41
44
  - A Telegram bot token (from [@BotFather](https://t.me/BotFather))
42
45
  - Your Telegram chat ID (from [@userinfobot](https://t.me/userinfobot))
43
- - [tmux](https://github.com/tmux/tmux/wiki) _(optionalfalls back to headless PTY via `node-pty` when absent)_
46
+ - A terminalany of:
47
+ - [tmux](https://github.com/tmux/tmux/wiki) (recommended; cross-platform)
48
+ - [Ghostty](https://ghostty.org) (auto-detected on macOS via `TERM_PROGRAM`)
49
+ - bare zsh / screen / anything else (PTY fallback via `node-pty`)
44
50
 
45
51
  ## Quick Start
46
52
 
@@ -58,20 +64,28 @@ Then open Telegram and message your bot — Claude Code will now notify you remo
58
64
 
59
65
  ## How It Works
60
66
 
61
- CCGram integrates with [Claude Code hooks](https://docs.anthropic.com/en/docs/claude-code/hooks) — shell scripts that Claude Code calls at key moments. Each hook script sends a Telegram message and, when you respond, injects keystrokes back into the tmux session running Claude.
67
+ CCGram integrates with [Claude Code hooks](https://docs.anthropic.com/en/docs/claude-code/hooks) — shell scripts that Claude Code calls at key moments. Hooks send Telegram messages and, depending on the event, return your response to Claude Code directly via stdout (`updatedInput` for questions, `decision` for permissions) or inject keystrokes into the active session (tmux, Ghostty, or PTY).
62
68
 
63
69
  ### Hooks installed
64
70
 
65
71
  | Hook | Event | What it does |
66
72
  |------|-------|-------------|
67
- | `permission-hook.js` | `PermissionRequest` | Sends a permission dialog with Allow / Deny / Always buttons. Blocks Claude until you respond. |
68
- | `question-notify.js` | `PreToolUse` (AskUserQuestion) | Sends Claude's question with selectable options. Your tap injects the selection via tmux/PTY. |
73
+ | `permission-hook.js` | `PermissionRequest` | Sends a permission dialog with Allow / Deny / Always / Defer buttons. Blocks Claude until you respond. |
74
+ | `question-notify.js` | `PreToolUse` (AskUserQuestion) | Sends Claude's question with selectable options. Returns answer directly via `updatedInput` works with any terminal. |
69
75
  | `enhanced-hook-notify.js completed` | `Stop` | Notifies you when Claude finishes a task, including the last response text. |
70
76
  | `enhanced-hook-notify.js waiting` | `Notification` | Notifies you when Claude is waiting for input. |
71
77
  | `user-prompt-hook.js` | `UserPromptSubmit` | Tracks terminal activity so notifications are suppressed when you're actively working. |
72
78
  | `enhanced-hook-notify.js session-start` | `SessionStart` | Notifies you when a new Claude session starts. |
73
- | `enhanced-hook-notify.js session-end` | `SessionEnd` | Notifies you when a Claude session ends, with the final response. |
79
+ | `enhanced-hook-notify.js session-end` | `SessionEnd` | Notifies you when a Claude session ends. |
74
80
  | `enhanced-hook-notify.js subagent-done` | `SubagentStop` | Notifies you when a subagent task completes. |
81
+ | `permission-denied-notify.js` | `PermissionDenied` | Notifies when auto mode blocks a tool. Retry button lets you override. |
82
+ | `enhanced-hook-notify.js stop-failure` | `StopFailure` | Notifies you on API errors (rate limits, network issues). |
83
+ | `enhanced-hook-notify.js post-compact` | `PostCompact` | Notifies when context compaction completes, with token savings. |
84
+ | `pre-compact-notify.js` | `PreCompact` | Warns before compaction starts. Block button lets you preserve context. |
85
+ | `elicitation-notify.js` | `Elicitation` | Forwards MCP server input requests to Telegram. Reply with your answer. |
86
+ | `enhanced-hook-notify.js task-created` | `TaskCreated` | Notifies when Claude creates a new task. |
87
+ | `enhanced-hook-notify.js cwd-changed` | `CwdChanged` | Notifies when Claude changes working directory. |
88
+ | `enhanced-hook-notify.js instructions-loaded` | `InstructionsLoaded` | Notifies when CLAUDE.md or rules are loaded. |
75
89
 
76
90
  > **Smart suppression** — all notifications (including permissions) are automatically silenced when you've sent a message to Claude within the last 5 minutes. The moment you step away, Telegram takes over. Telegram-injected commands always get their response back to Telegram regardless.
77
91
 
@@ -91,11 +105,11 @@ Claude requests permission
91
105
 
92
106
  ```
93
107
  Claude asks a question (AskUserQuestion)
94
- → Claude shows question UI in terminal
95
108
  → question-notify sends options to Telegram
96
109
  → you tap an option
97
- → bot injects arrow keys + Enter via tmux or PTY
98
- Claude's question UI captures the keystrokes
110
+ → bot writes response file with your selection
111
+ hook returns answer via updatedInput to Claude
112
+ → Claude receives answer directly (works with any terminal!)
99
113
  ```
100
114
 
101
115
  ## Bot Commands
@@ -114,9 +128,12 @@ Claude asks a question (AskUserQuestion)
114
128
  | Command | Description |
115
129
  |---------|-------------|
116
130
  | `/<workspace> <command>` | Send a command to a specific Claude session |
117
- | `/status [workspace]` | Show the last 20 lines of tmux pane output |
131
+ | `/status [workspace]` | Rich status: model, version, branch, session ID, context %, rate limit, last activity, last message (and recent pane output for tmux/PTY) |
118
132
  | `/stop [workspace]` | Send Ctrl+C to interrupt the running prompt |
119
133
  | `/compact [workspace]` | Run `/compact` and wait for it to complete |
134
+ | `/effort [workspace] low\|medium\|high` | Set Claude's thinking effort level |
135
+ | `/model [workspace] <model>` | Switch Claude model (sonnet, opus, haiku) |
136
+ | `/link <prompt>` | Generate a deep link to open Claude Code with your prompt |
120
137
 
121
138
  ### Project launcher
122
139
 
@@ -252,7 +269,7 @@ node dist/workspace-telegram-bot.js
252
269
  ```bash
253
270
  npm run build # Compile TypeScript → dist/
254
271
  npm run build:watch # Watch mode
255
- npm test # Run 84 tests (vitest)
272
+ npm test # Run 120 tests (vitest)
256
273
  ```
257
274
 
258
275
  **Note:** Claude Code hooks run from `~/.ccgram/dist/`, not the repo's `dist/`. After changing hook scripts during development, sync them:
@@ -268,34 +285,42 @@ End users don't need this — `ccgram init` handles it automatically.
268
285
  ```
269
286
  src/
270
287
  ├── utils/
271
- │ ├── active-check.ts # Detect terminal activity; suppress notifications when present
272
- │ ├── pty-session-manager.ts # Headless PTY backend via node-pty (tmux fallback)
273
- │ ├── callback-parser.ts # Parse Telegram callback_data strings
274
- │ ├── http-request.ts # Lightweight HTTPS wrapper (no axios)
275
- │ ├── optional-require.ts # Graceful optional dependency loading
276
- └── paths.ts # PROJECT_ROOT + CCGRAM_HOME constants
277
- ├── types/ # TypeScript interfaces
278
- └── data/ # Runtime data (session map, history)
279
-
280
- workspace-telegram-bot.ts # Main bot (long-polling, routing, callbacks)
281
- workspace-router.ts # Session map, prefix matching, default workspace
282
- prompt-bridge.ts # File-based IPC via /tmp/claude-prompts/
283
- permission-hook.ts # Blocking permission approval hook
284
- question-notify.ts # Non-blocking question notification hook
285
- enhanced-hook-notify.ts # Status notification hook (Stop, Notification, SessionStart, SessionEnd, SubagentStop)
286
- user-prompt-hook.ts # UserPromptSubmit hook writes terminal activity timestamp
287
- setup.ts # Interactive setup wizard
288
- cli.ts # ccgram CLI entry point
288
+ │ ├── active-check.ts # Detect terminal activity; suppress notifications when present
289
+ │ ├── pty-session-manager.ts # Headless PTY backend via node-pty (tmux fallback)
290
+ │ ├── ghostty-session-manager.ts # Ghostty AppleScript backend (macOS, auto-detected)
291
+ │ ├── transcript-reader.ts # Read Claude Code session JSONL for /status (model, context %, last message)
292
+ │ ├── deep-link.ts # Generate claude-cli://open?q=... URLs for /link
293
+ ├── callback-parser.ts # Parse Telegram callback_data strings
294
+ ├── http-request.ts # Lightweight HTTPS wrapper (no axios)
295
+ │ ├── optional-require.ts # Graceful optional dependency loading
296
+ │ └── paths.ts # PROJECT_ROOT + CCGRAM_HOME constants
297
+ ├── types/ # TypeScript interfaces
298
+ └── data/ # Runtime data (session map, history)
299
+
300
+ workspace-telegram-bot.ts # Main bot (long-polling, routing, callbacks, /status, /link, /effort, /model)
301
+ workspace-router.ts # Session map, prefix matching, default workspace, rate limit storage
302
+ prompt-bridge.ts # File-based IPC via /tmp/claude-prompts/
303
+ permission-hook.ts # Blocking permission approval hook
304
+ permission-denied-notify.ts # PermissionDenied hook with retry button
305
+ question-notify.ts # Blocking AskUserQuestion hook (returns updatedInput to Claude Code)
306
+ enhanced-hook-notify.ts # Status notifications (Stop, Notification, SessionStart/End, SubagentStop, StopFailure, PostCompact, TaskCreated, CwdChanged, InstructionsLoaded)
307
+ pre-compact-notify.ts # PreCompact hook with block button
308
+ elicitation-notify.ts # MCP elicitation hook (schema-aware, per-field)
309
+ user-prompt-hook.ts # UserPromptSubmit hook — writes terminal activity timestamp
310
+ setup.ts # Interactive setup wizard
311
+ cli.ts # ccgram CLI entry point
289
312
  ```
290
313
 
291
314
  ### Tests
292
315
 
293
316
  ```
294
317
  test/
295
- ├── prompt-bridge.test.js # 15 tests — IPC write/read/update/clean/expiry
296
- ├── workspace-router.test.js # 38 tests — session map, prefix matching, defaults, reply-to, session history
297
- ├── callback-parser.test.js # 23 tests — all callback_data formats (perm, opt, new, rp, rs, rc)
298
- └── active-check.test.js # 8 tests — terminal activity detection, thresholds
318
+ ├── prompt-bridge.test.js # 15 tests — IPC write/read/update/clean/expiry
319
+ ├── workspace-router.test.js # 43 tests — session map, prefix matching, defaults, reply-to, history, rate limits
320
+ ├── callback-parser.test.js # 27 tests — all callback_data formats (perm, opt, new, rp, rs, rc, perm-denied, pre-compact)
321
+ ├── active-check.test.js # 8 tests — terminal activity detection, thresholds
322
+ ├── deep-link.test.js # 11 tests — claude-cli:// URL generation, encoding, character limits
323
+ └── ghostty-session-manager.test.js # 16 tests — Ghostty AppleScript session management (mocked)
299
324
  ```
300
325
 
301
326
  Tests use isolated temp directories and run with `npm test` (vitest, no configuration needed).
@@ -325,18 +350,24 @@ Yes. Each Claude session maps to a named tmux or PTY session. Use `/sessions` to
325
350
  Yes. `/resume` reads from Claude Code's own session storage, so it sees every conversation — not just ones started through the bot. If the session is still running in your terminal, you'll get a warning before resuming to prevent conflicts.
326
351
 
327
352
  **Do I need tmux?**
328
- No. When tmux is not detected, CCGram automatically falls back to headless PTY sessions powered by [`node-pty`](https://github.com/microsoft/node-pty). No configuration required — it activates on its own.
329
-
330
- To use PTY mode:
331
- 1. Install the optional dependency: `npm install node-pty` inside `~/.ccgram/`
332
- 2. PTY activates automatically when `tmux` is not running, or force it explicitly:
333
- ```bash
334
- # in ~/.ccgram/.env
335
- INJECTION_MODE=pty
336
- ```
337
- 3. Restart the bot: `launchctl kickstart -k gui/$(id -u)/com.ccgram` (macOS) or `sudo systemctl restart ccgram` (Linux)
338
-
339
- Full remote control — permission approvals, question answering, `/new`, `/stop` — works identically in both modes.
353
+ No. CCGram supports three injection backends and picks the right one automatically:
354
+ - **tmux** (default when running) — cross-platform, recommended
355
+ - **Ghostty** auto-detected on macOS via `TERM_PROGRAM=ghostty`; uses AppleScript for keystroke injection and tab focus
356
+ - **PTY** (`node-pty`) headless fallback when neither tmux nor Ghostty is available
357
+
358
+ For question answering specifically (the `AskUserQuestion` hook), CCGram returns answers to Claude Code directly via the `updatedInput` hook output — so it works on **any** terminal, including bare zsh, screen, or anything else, without keystroke injection at all.
359
+
360
+ To force a specific backend:
361
+ ```bash
362
+ # in ~/.ccgram/.env
363
+ INJECTION_MODE=pty # or tmux
364
+ ```
365
+
366
+ Then restart the bot: `launchctl kickstart -k gui/$(id -u)/com.ccgram` (macOS) or `sudo systemctl restart ccgram` (Linux).
367
+
368
+ To use PTY mode, install the optional dependency: `npm install node-pty` inside `~/.ccgram/`.
369
+
370
+ Full remote control — permission approvals, question answering, `/new`, `/stop` — works identically in all modes.
340
371
 
341
372
  **Is my bot token stored securely?**
342
373
  The token is stored in `~/.ccgram/.env`, readable only by your user. It's never logged or transmitted beyond Telegram's API.
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Elicitation Notify — Called by Claude Code's Elicitation hook.
4
+ *
5
+ * BLOCKING mode: Forwards MCP server input requests to Telegram, polls for
6
+ * user responses (one per form field), then outputs the answer via stdout.
7
+ *
8
+ * Stdin JSON: { mcp_server_name, requested_schema, cwd, session_id, ... }
9
+ * requested_schema: JSON Schema object with `properties` describing form fields
10
+ *
11
+ * Stdout: {
12
+ * hookSpecificOutput: {
13
+ * hookEventName: "Elicitation",
14
+ * action: "accept" | "decline" | "cancel",
15
+ * content: { <fieldName>: <value> } // required when action === "accept"
16
+ * }
17
+ * }
18
+ */
19
+ export {};
20
+ //# sourceMappingURL=elicitation-notify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elicitation-notify.d.ts","sourceRoot":"","sources":["../elicitation-notify.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;GAgBG"}
@@ -0,0 +1,241 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Elicitation Notify — Called by Claude Code's Elicitation hook.
5
+ *
6
+ * BLOCKING mode: Forwards MCP server input requests to Telegram, polls for
7
+ * user responses (one per form field), then outputs the answer via stdout.
8
+ *
9
+ * Stdin JSON: { mcp_server_name, requested_schema, cwd, session_id, ... }
10
+ * requested_schema: JSON Schema object with `properties` describing form fields
11
+ *
12
+ * Stdout: {
13
+ * hookSpecificOutput: {
14
+ * hookEventName: "Elicitation",
15
+ * action: "accept" | "decline" | "cancel",
16
+ * content: { <fieldName>: <value> } // required when action === "accept"
17
+ * }
18
+ * }
19
+ */
20
+ var __importDefault = (this && this.__importDefault) || function (mod) {
21
+ return (mod && mod.__esModule) ? mod : { "default": mod };
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ const path_1 = __importDefault(require("path"));
25
+ const paths_1 = require("./src/utils/paths");
26
+ require('dotenv').config({ path: path_1.default.join(paths_1.PROJECT_ROOT, '.env'), quiet: true });
27
+ const fs_1 = __importDefault(require("fs"));
28
+ const https_1 = __importDefault(require("https"));
29
+ const workspace_router_1 = require("./workspace-router");
30
+ const prompt_bridge_1 = require("./prompt-bridge");
31
+ const active_check_1 = require("./src/utils/active-check");
32
+ const BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN;
33
+ const CHAT_ID = process.env.TELEGRAM_CHAT_ID;
34
+ // Polling configuration
35
+ const POLL_INTERVAL_MS = 500;
36
+ const POLL_TIMEOUT_MS = 120000; // 2 minutes for user input
37
+ // ── Main ────────────────────────────────────────────────────────
38
+ async function main() {
39
+ const raw = await readStdin();
40
+ // Skip Telegram notification if user is at terminal AND this wasn't Telegram-injected
41
+ const typingActivePath = path_1.default.join(paths_1.PROJECT_ROOT, 'src/data', 'typing-active');
42
+ const isTelegramInjected = fs_1.default.existsSync(typingActivePath);
43
+ if (!isTelegramInjected && (0, active_check_1.isUserActiveAtTerminal)()) {
44
+ return;
45
+ }
46
+ let payload;
47
+ try {
48
+ payload = JSON.parse(raw);
49
+ }
50
+ catch {
51
+ return;
52
+ }
53
+ // Payload uses `mcp_server_name` (newer) — fall back to `mcp_server` for safety
54
+ const mcpServer = payload.mcp_server_name || payload.mcp_server || 'Unknown MCP';
55
+ const schema = payload.requested_schema || {};
56
+ const properties = schema.properties || {};
57
+ const fieldNames = Object.keys(properties);
58
+ const cwd = payload.cwd || process.cwd();
59
+ const workspace = (0, workspace_router_1.extractWorkspaceName)(cwd);
60
+ // If the schema has no fields, decline — we can't build a meaningful response.
61
+ if (fieldNames.length === 0) {
62
+ emitDecline();
63
+ return;
64
+ }
65
+ // Prompt the user one field at a time. Any field that doesn't get an answer
66
+ // (timeout) cancels the whole elicitation.
67
+ const content = {};
68
+ for (let i = 0; i < fieldNames.length; i++) {
69
+ const fieldName = fieldNames[i];
70
+ const prop = properties[fieldName];
71
+ const promptId = (0, prompt_bridge_1.generatePromptId)();
72
+ let messageText = `\u{1F50C} *MCP Input Required* — ${escapeMarkdown(workspace)}\n\n`;
73
+ messageText += `*Server:* \`${escapeMarkdown(mcpServer)}\`\n`;
74
+ if (fieldNames.length > 1) {
75
+ messageText += `*Field ${i + 1} of ${fieldNames.length}:* \`${escapeMarkdown(fieldName)}\`\n\n`;
76
+ }
77
+ else {
78
+ messageText += `*Field:* \`${escapeMarkdown(fieldName)}\`\n\n`;
79
+ }
80
+ if (prop.description) {
81
+ messageText += `${escapeMarkdown(prop.description)}\n\n`;
82
+ }
83
+ if (prop.enum && prop.enum.length > 0) {
84
+ messageText += `_Allowed values:_ ${prop.enum.map(v => `\`${escapeMarkdown(v)}\``).join(', ')}\n\n`;
85
+ }
86
+ messageText += `_Reply to this message with your answer_`;
87
+ (0, prompt_bridge_1.writePending)(promptId, {
88
+ type: 'elicitation',
89
+ workspace,
90
+ mcpServer,
91
+ fieldName,
92
+ });
93
+ try {
94
+ const result = await sendTelegram(messageText);
95
+ if (result && result.message_id) {
96
+ (0, workspace_router_1.trackNotificationMessage)(result.message_id, workspace, 'elicitation');
97
+ }
98
+ }
99
+ catch (err) {
100
+ process.stderr.write(`[elicitation-notify] Telegram send failed: ${err.message}\n`);
101
+ (0, prompt_bridge_1.cleanPrompt)(promptId);
102
+ emitCancel();
103
+ return;
104
+ }
105
+ const response = await pollForResponse(promptId);
106
+ (0, prompt_bridge_1.cleanPrompt)(promptId);
107
+ if (!response || typeof response.textAnswer !== 'string') {
108
+ // Timeout or missing answer — cancel the whole elicitation
109
+ emitCancel();
110
+ return;
111
+ }
112
+ content[fieldName] = response.textAnswer;
113
+ }
114
+ const output = {
115
+ hookSpecificOutput: {
116
+ hookEventName: 'Elicitation',
117
+ action: 'accept',
118
+ content,
119
+ },
120
+ };
121
+ process.stdout.write(JSON.stringify(output) + '\n');
122
+ }
123
+ function emitDecline() {
124
+ const output = {
125
+ hookSpecificOutput: {
126
+ hookEventName: 'Elicitation',
127
+ action: 'decline',
128
+ },
129
+ };
130
+ process.stdout.write(JSON.stringify(output) + '\n');
131
+ }
132
+ function emitCancel() {
133
+ const output = {
134
+ hookSpecificOutput: {
135
+ hookEventName: 'Elicitation',
136
+ action: 'cancel',
137
+ },
138
+ };
139
+ process.stdout.write(JSON.stringify(output) + '\n');
140
+ }
141
+ // ── Polling ─────────────────────────────────────────────────────
142
+ function pollForResponse(promptId) {
143
+ return new Promise((resolve) => {
144
+ const responseFile = path_1.default.join(prompt_bridge_1.PROMPTS_DIR, `response-${promptId}.json`);
145
+ const startTime = Date.now();
146
+ const interval = setInterval(() => {
147
+ if (Date.now() - startTime > POLL_TIMEOUT_MS) {
148
+ clearInterval(interval);
149
+ process.stderr.write(`[elicitation-notify] Timed out waiting for response\n`);
150
+ resolve(null);
151
+ return;
152
+ }
153
+ try {
154
+ if (fs_1.default.existsSync(responseFile)) {
155
+ const raw = fs_1.default.readFileSync(responseFile, 'utf8');
156
+ const data = JSON.parse(raw);
157
+ clearInterval(interval);
158
+ resolve(data);
159
+ }
160
+ }
161
+ catch {
162
+ // File not ready yet or parse error — keep polling
163
+ }
164
+ }, POLL_INTERVAL_MS);
165
+ });
166
+ }
167
+ // ── Telegram ────────────────────────────────────────────────────
168
+ function sendTelegram(text) {
169
+ return new Promise((resolve, reject) => {
170
+ const body = JSON.stringify({
171
+ chat_id: CHAT_ID,
172
+ text,
173
+ parse_mode: 'Markdown',
174
+ });
175
+ const options = {
176
+ hostname: 'api.telegram.org',
177
+ path: `/bot${BOT_TOKEN}/sendMessage`,
178
+ method: 'POST',
179
+ headers: {
180
+ 'Content-Type': 'application/json',
181
+ 'Content-Length': Buffer.byteLength(body),
182
+ },
183
+ timeout: 5000,
184
+ };
185
+ const req = https_1.default.request(options, (res) => {
186
+ let data = '';
187
+ res.on('data', (chunk) => { data += chunk; });
188
+ res.on('end', () => {
189
+ if (res.statusCode >= 200 && res.statusCode < 300) {
190
+ try {
191
+ const parsed = JSON.parse(data);
192
+ resolve(parsed.result || null);
193
+ }
194
+ catch {
195
+ resolve(null);
196
+ }
197
+ }
198
+ else {
199
+ reject(new Error(`Telegram API ${res.statusCode}: ${data}`));
200
+ }
201
+ });
202
+ });
203
+ req.on('error', reject);
204
+ req.on('timeout', () => {
205
+ req.destroy();
206
+ reject(new Error('Telegram request timed out'));
207
+ });
208
+ req.write(body);
209
+ req.end();
210
+ });
211
+ }
212
+ // ── Helpers ──────────────────────────────────────────────────────
213
+ function readStdin() {
214
+ return new Promise((resolve) => {
215
+ let data = '';
216
+ let resolved = false;
217
+ process.stdin.setEncoding('utf8');
218
+ process.stdin.on('data', (chunk) => { data += chunk; });
219
+ process.stdin.on('end', () => {
220
+ if (!resolved) {
221
+ resolved = true;
222
+ resolve(data);
223
+ }
224
+ });
225
+ setTimeout(() => {
226
+ if (!resolved) {
227
+ resolved = true;
228
+ process.stdin.destroy();
229
+ resolve(data || '{}');
230
+ }
231
+ }, 500);
232
+ });
233
+ }
234
+ function escapeMarkdown(text) {
235
+ return text.replace(/([_*`\[])/g, '\\$1');
236
+ }
237
+ // ── Run ─────────────────────────────────────────────────────────
238
+ main().catch((err) => {
239
+ process.stderr.write(`[elicitation-notify] Fatal: ${err.message}\n`);
240
+ });
241
+ //# sourceMappingURL=elicitation-notify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elicitation-notify.js","sourceRoot":"","sources":["../elicitation-notify.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,9 @@
3
3
  * Enhanced Hook Notifier — called by Claude Code hooks.
4
4
  *
5
5
  * Handles: Stop (completed), Notification (waiting), SessionStart,
6
- * SessionEnd, SubagentStop (subagent-done).
6
+ * SessionEnd, SubagentStop (subagent-done), StopFailure (stop-failure),
7
+ * PostCompact (post-compact), TaskCreated (task-created),
8
+ * CwdChanged (cwd-changed), InstructionsLoaded (instructions-loaded).
7
9
  *
8
10
  * Usage (in ~/.claude/settings.json hooks):
9
11
  * node /path/to/ccgram/dist/enhanced-hook-notify.js completed
@@ -11,6 +13,11 @@
11
13
  * node /path/to/ccgram/dist/enhanced-hook-notify.js session-start
12
14
  * node /path/to/ccgram/dist/enhanced-hook-notify.js session-end
13
15
  * node /path/to/ccgram/dist/enhanced-hook-notify.js subagent-done
16
+ * node /path/to/ccgram/dist/enhanced-hook-notify.js stop-failure
17
+ * node /path/to/ccgram/dist/enhanced-hook-notify.js post-compact
18
+ * node /path/to/ccgram/dist/enhanced-hook-notify.js task-created
19
+ * node /path/to/ccgram/dist/enhanced-hook-notify.js cwd-changed
20
+ * node /path/to/ccgram/dist/enhanced-hook-notify.js instructions-loaded
14
21
  */
15
22
  export {};
16
23
  //# sourceMappingURL=enhanced-hook-notify.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"enhanced-hook-notify.d.ts","sourceRoot":"","sources":["../enhanced-hook-notify.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;GAYG"}
1
+ {"version":3,"file":"enhanced-hook-notify.d.ts","sourceRoot":"","sources":["../enhanced-hook-notify.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;GAmBG"}