@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.
- package/.env.example +3 -0
- package/README.md +82 -51
- package/dist/elicitation-notify.d.ts +20 -0
- package/dist/elicitation-notify.d.ts.map +1 -0
- package/dist/elicitation-notify.js +241 -0
- package/dist/elicitation-notify.js.map +1 -0
- package/dist/enhanced-hook-notify.d.ts +8 -1
- package/dist/enhanced-hook-notify.d.ts.map +1 -1
- package/dist/enhanced-hook-notify.js +119 -5
- package/dist/enhanced-hook-notify.js.map +1 -1
- package/dist/permission-denied-notify.d.ts +11 -0
- package/dist/permission-denied-notify.d.ts.map +1 -0
- package/dist/permission-denied-notify.js +193 -0
- package/dist/permission-denied-notify.js.map +1 -0
- package/dist/permission-hook.js +43 -18
- package/dist/permission-hook.js.map +1 -1
- package/dist/pre-compact-notify.d.ts +13 -0
- package/dist/pre-compact-notify.d.ts.map +1 -0
- package/dist/pre-compact-notify.js +197 -0
- package/dist/pre-compact-notify.js.map +1 -0
- package/dist/question-notify.d.ts +6 -5
- package/dist/question-notify.d.ts.map +1 -1
- package/dist/question-notify.js +107 -23
- package/dist/question-notify.js.map +1 -1
- package/dist/setup.js +26 -10
- package/dist/setup.js.map +1 -1
- package/dist/src/types/callbacks.d.ts +11 -1
- package/dist/src/types/callbacks.d.ts.map +1 -1
- package/dist/src/types/session.d.ts +13 -1
- package/dist/src/types/session.d.ts.map +1 -1
- package/dist/src/utils/callback-parser.d.ts +7 -5
- package/dist/src/utils/callback-parser.d.ts.map +1 -1
- package/dist/src/utils/callback-parser.js +11 -5
- package/dist/src/utils/callback-parser.js.map +1 -1
- package/dist/src/utils/deep-link.d.ts +22 -0
- package/dist/src/utils/deep-link.d.ts.map +1 -0
- package/dist/src/utils/deep-link.js +43 -0
- package/dist/src/utils/deep-link.js.map +1 -0
- package/dist/src/utils/ghostty-session-manager.d.ts +81 -0
- package/dist/src/utils/ghostty-session-manager.d.ts.map +1 -0
- package/dist/src/utils/ghostty-session-manager.js +370 -0
- package/dist/src/utils/ghostty-session-manager.js.map +1 -0
- package/dist/src/utils/transcript-reader.d.ts +57 -0
- package/dist/src/utils/transcript-reader.d.ts.map +1 -0
- package/dist/src/utils/transcript-reader.js +229 -0
- package/dist/src/utils/transcript-reader.js.map +1 -0
- package/dist/workspace-router.d.ts +19 -4
- package/dist/workspace-router.d.ts.map +1 -1
- package/dist/workspace-router.js +57 -1
- package/dist/workspace-router.js.map +1 -1
- package/dist/workspace-telegram-bot.js +515 -114
- package/dist/workspace-telegram-bot.js.map +1 -1
- package/package.json +1 -1
- package/src/types/callbacks.ts +15 -1
- 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
|
-
|
|
21
|
+
└─ updatedInput / tmux / Ghostty / PTY ─┘
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
## Features
|
|
25
25
|
|
|
26
|
-
- **
|
|
27
|
-
- **
|
|
28
|
-
- **
|
|
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
|
|
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
|
-
- **
|
|
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
|
-
-
|
|
46
|
+
- A terminal — any 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.
|
|
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.
|
|
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
|
|
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
|
|
98
|
-
→
|
|
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]` |
|
|
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
|
|
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
|
|
272
|
-
│ ├── pty-session-manager.ts
|
|
273
|
-
│ ├──
|
|
274
|
-
│ ├──
|
|
275
|
-
│ ├──
|
|
276
|
-
│
|
|
277
|
-
├──
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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
|
|
296
|
-
├── workspace-router.test.js
|
|
297
|
-
├── callback-parser.test.js
|
|
298
|
-
|
|
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.
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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
|
|
1
|
+
{"version":3,"file":"enhanced-hook-notify.d.ts","sourceRoot":"","sources":["../enhanced-hook-notify.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;GAmBG"}
|