@jsayubi/ccgram 1.1.1 → 1.2.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 (55) hide show
  1. package/.env.example +3 -0
  2. package/README.md +18 -7
  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
@@ -1 +1 @@
1
- {"version":3,"file":"callback-parser.js","sourceRoot":"","sources":["../../../src/utils/callback-parser.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AAcH,8CAwDC;AAlED;;;;;;;;;GASG;AACH,SAAgB,iBAAiB,CAAC,IAA+B;IAC/D,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAEtB,qDAAqD;IACrD,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACnB,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7C,IAAI,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC;QAC9B,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IACtC,CAAC;IAED,0EAA0E;IAC1E,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7C,IAAI,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC;QAC9B,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IACrC,CAAC;IAED,0DAA0D;IAC1D,2EAA2E;IAC3E,2EAA2E;IAC3E,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QACnC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAClC,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACzD,IAAI,KAAK,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC;QACnC,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/D,IAAI,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC;QAC9B,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAoB,CAAC;IAC7D,CAAC;IAED,uCAAuC;IACvC,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;QAC1B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/C,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,CAAC;IAED,8DAA8D;IAC9D,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAElC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAExB,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE3B,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,MAAM;YACT,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QAC5C,KAAK,KAAK;YACR,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;QACtE,KAAK,OAAO;YACV,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;QACxE;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"callback-parser.js","sourceRoot":"","sources":["../../../src/utils/callback-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Deep Link Utility — Generate Claude Code deep links.
3
+ *
4
+ * Claude Code supports `claude-cli://open?q=...` deep links (v2.1.85+).
5
+ * - Up to 5,000 characters
6
+ * - Multi-line support via %0A
7
+ * - Opens in user's preferred terminal
8
+ */
9
+ /**
10
+ * Generate a Claude Code deep link for the given prompt.
11
+ * Returns null if prompt is too long.
12
+ */
13
+ export declare function generateDeepLink(prompt: string): string | null;
14
+ /**
15
+ * Generate a deep link with a specific working directory.
16
+ */
17
+ export declare function generateDeepLinkWithCwd(prompt: string, cwd: string): string | null;
18
+ /**
19
+ * Check if a prompt can be converted to a deep link.
20
+ */
21
+ export declare function canGenerateDeepLink(prompt: string): boolean;
22
+ //# sourceMappingURL=deep-link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deep-link.d.ts","sourceRoot":"","sources":["../../../src/utils/deep-link.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM9D;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOlF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE3D"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ /**
3
+ * Deep Link Utility — Generate Claude Code deep links.
4
+ *
5
+ * Claude Code supports `claude-cli://open?q=...` deep links (v2.1.85+).
6
+ * - Up to 5,000 characters
7
+ * - Multi-line support via %0A
8
+ * - Opens in user's preferred terminal
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.generateDeepLink = generateDeepLink;
12
+ exports.generateDeepLinkWithCwd = generateDeepLinkWithCwd;
13
+ exports.canGenerateDeepLink = canGenerateDeepLink;
14
+ const MAX_PROMPT_LENGTH = 4500; // Leave room for URL overhead
15
+ /**
16
+ * Generate a Claude Code deep link for the given prompt.
17
+ * Returns null if prompt is too long.
18
+ */
19
+ function generateDeepLink(prompt) {
20
+ if (prompt.length > MAX_PROMPT_LENGTH) {
21
+ return null;
22
+ }
23
+ const encoded = encodeURIComponent(prompt);
24
+ return `claude-cli://open?q=${encoded}`;
25
+ }
26
+ /**
27
+ * Generate a deep link with a specific working directory.
28
+ */
29
+ function generateDeepLinkWithCwd(prompt, cwd) {
30
+ if (prompt.length + cwd.length > MAX_PROMPT_LENGTH) {
31
+ return null;
32
+ }
33
+ const encodedPrompt = encodeURIComponent(prompt);
34
+ const encodedCwd = encodeURIComponent(cwd);
35
+ return `claude-cli://open?q=${encodedPrompt}&cwd=${encodedCwd}`;
36
+ }
37
+ /**
38
+ * Check if a prompt can be converted to a deep link.
39
+ */
40
+ function canGenerateDeepLink(prompt) {
41
+ return prompt.length <= MAX_PROMPT_LENGTH;
42
+ }
43
+ //# sourceMappingURL=deep-link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deep-link.js","sourceRoot":"","sources":["../../../src/utils/deep-link.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AAQH,4CAMC;AAKD,0DAOC;AAKD,kDAEC;AA/BD,MAAM,iBAAiB,GAAG,IAAI,CAAC,CAAC,8BAA8B;AAE9D;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,MAAc;IAC7C,IAAI,MAAM,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3C,OAAO,uBAAuB,OAAO,EAAE,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,SAAgB,uBAAuB,CAAC,MAAc,EAAE,GAAW;IACjE,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;QACnD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,aAAa,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAC3C,OAAO,uBAAuB,aAAa,QAAQ,UAAU,EAAE,CAAC;AAClE,CAAC;AAED;;GAEG;AACH,SAAgB,mBAAmB,CAAC,MAAc;IAChD,OAAO,MAAM,CAAC,MAAM,IAAI,iBAAiB,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Ghostty Session Manager — controls Ghostty terminal sessions via AppleScript.
3
+ *
4
+ * Ghostty 1.3.0+ supports native AppleScript for controlling terminal windows,
5
+ * tabs, and splits. This backend is used when TERM_PROGRAM=ghostty and no
6
+ * tmux session is available.
7
+ *
8
+ * Session identity: CWD-based. Stores Map<sessionName, cwd> as handles.
9
+ * Text injection: input text "..." to terminal (paste-style, handles ANSI).
10
+ * Key sequences: arrow keys via ANSI (send key "down" is broken in 1.3.0).
11
+ * Modifier keys (C-c, C-u): use "send key KEY modifiers MOD to term" (no "with").
12
+ */
13
+ export declare class GhosttySessionManager {
14
+ /** Map from session name to registered CWD. */
15
+ private handles;
16
+ /**
17
+ * Whether Ghostty is available and running on this machine.
18
+ * Re-checked each call (fast) so the bot handles Ghostty launching after startup.
19
+ */
20
+ isAvailable(): boolean;
21
+ /** Whether a handle is registered for this session name. */
22
+ has(name: string): boolean;
23
+ /** Register (or update) a session handle with its CWD. */
24
+ register(name: string, cwd: string): void;
25
+ /** Remove a session handle. */
26
+ unregister(name: string): void;
27
+ /**
28
+ * Execute an AppleScript via osascript stdin pipe.
29
+ * Using stdin pipe avoids all shell-quoting issues and supports multi-line scripts.
30
+ */
31
+ private runScript;
32
+ /**
33
+ * Build an AppleScript string literal expression for the given value.
34
+ * Handles embedded double-quotes via & quote & concatenation.
35
+ */
36
+ private buildAppleScriptString;
37
+ /**
38
+ * Build an AppleScript expression that produces the given text when evaluated.
39
+ * Uses (character id N) for control characters/non-printable bytes,
40
+ * and quote for embedded double-quotes.
41
+ */
42
+ private buildAppleScriptText;
43
+ /**
44
+ * Build the AppleScript fragment that finds the terminal for a registered CWD.
45
+ * Iterates all windows and tabs to find the terminal whose working directory matches.
46
+ */
47
+ private findTermScript;
48
+ /**
49
+ * Write raw text to a Ghostty terminal (paste-style).
50
+ * Handles printable ASCII, control characters (e.g. \r for Enter),
51
+ * and ANSI escape sequences (e.g. \x1B[B for Down arrow).
52
+ */
53
+ write(name: string, text: string): Promise<boolean>;
54
+ /**
55
+ * Write text then immediately press Return — all in one AppleScript execution.
56
+ * Avoids a second CWD lookup between write and Enter, which can miss the terminal.
57
+ */
58
+ writeLine(name: string, text: string): Promise<boolean>;
59
+ /**
60
+ * Send a named key to a session.
61
+ * C-c and C-u use "send key ... with modifiers" (required by Ghostty AppleScript).
62
+ * Down, Up, Enter, Space use ANSI sequences via input text
63
+ * (send key "down" is broken in Ghostty 1.3.0).
64
+ */
65
+ sendKey(name: string, key: string): Promise<boolean>;
66
+ /** Send Ctrl+C interrupt to the terminal. */
67
+ interrupt(name: string): Promise<boolean>;
68
+ /**
69
+ * Capture terminal scrollback by triggering write_scrollback_file.
70
+ * Finds the new file in the OS temp directory and reads its content.
71
+ * Returns null if unavailable or no file produced within 1s.
72
+ */
73
+ capture(name: string): Promise<string | null>;
74
+ /**
75
+ * Open a new tab in the front Ghostty window and run a command.
76
+ * Uses AppleScript's quoted form of for safe shell quoting of the cwd.
77
+ */
78
+ openNewTab(cwd: string, command: string): Promise<boolean>;
79
+ }
80
+ export declare const ghosttySessionManager: GhosttySessionManager;
81
+ //# sourceMappingURL=ghostty-session-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ghostty-session-manager.d.ts","sourceRoot":"","sources":["../../../src/utils/ghostty-session-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA2BH,qBAAa,qBAAqB;IAChC,+CAA+C;IAC/C,OAAO,CAAC,OAAO,CAAkC;IAEjD;;;OAGG;IACH,WAAW,IAAI,OAAO;IActB,4DAA4D;IAC5D,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAIzC,+BAA+B;IAC/B,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9B;;;OAGG;IACH,OAAO,CAAC,SAAS;IAWjB;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAK9B;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAwB5B;;;OAGG;IACH,OAAO,CAAC,cAAc;IAqBtB;;;;OAIG;IACG,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAkBzD;;;OAGG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAqB7D;;;;;OAKG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA4D1D,6CAA6C;IACvC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI/C;;;;OAIG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA0DnD;;;OAGG;IACG,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAwBjE;AAED,eAAO,MAAM,qBAAqB,uBAA8B,CAAC"}
@@ -0,0 +1,370 @@
1
+ "use strict";
2
+ /**
3
+ * Ghostty Session Manager — controls Ghostty terminal sessions via AppleScript.
4
+ *
5
+ * Ghostty 1.3.0+ supports native AppleScript for controlling terminal windows,
6
+ * tabs, and splits. This backend is used when TERM_PROGRAM=ghostty and no
7
+ * tmux session is available.
8
+ *
9
+ * Session identity: CWD-based. Stores Map<sessionName, cwd> as handles.
10
+ * Text injection: input text "..." to terminal (paste-style, handles ANSI).
11
+ * Key sequences: arrow keys via ANSI (send key "down" is broken in 1.3.0).
12
+ * Modifier keys (C-c, C-u): use "send key KEY modifiers MOD to term" (no "with").
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.ghosttySessionManager = exports.GhosttySessionManager = void 0;
19
+ const os_1 = __importDefault(require("os"));
20
+ const fs_1 = __importDefault(require("fs"));
21
+ const child_process_1 = require("child_process");
22
+ // Key name → macOS key code (sent via System Events after focus, bypasses bracketed paste)
23
+ // send key "down" is unsupported in Ghostty AppleScript; input text ANSI is wrapped in
24
+ // bracketed paste which Claude Code's TUI doesn't recognise as navigation.
25
+ const KEY_CODES = {
26
+ 'Down': 125,
27
+ 'Up': 126,
28
+ 'Space': 49,
29
+ };
30
+ // Keys sent via "send key NAME to term" (no modifiers)
31
+ const SEND_KEYS = {
32
+ 'Enter': 'enter',
33
+ 'C-m': 'enter',
34
+ };
35
+ // Keys using "send key KEY modifiers MOD to term" (no "with" — plain param per Ghostty sdef)
36
+ const MODIFIER_KEYS = {
37
+ 'C-c': { key: 'c', modifiers: 'control' },
38
+ 'C-u': { key: 'u', modifiers: 'control' },
39
+ };
40
+ class GhosttySessionManager {
41
+ /** Map from session name to registered CWD. */
42
+ handles = new Map();
43
+ /**
44
+ * Whether Ghostty is available and running on this machine.
45
+ * Re-checked each call (fast) so the bot handles Ghostty launching after startup.
46
+ */
47
+ isAvailable() {
48
+ if (process.platform !== 'darwin')
49
+ return false;
50
+ try {
51
+ const result = (0, child_process_1.execSync)('osascript -e "application \\"Ghostty\\" is running"', {
52
+ encoding: 'utf8',
53
+ stdio: 'pipe',
54
+ timeout: 2000,
55
+ }).trim();
56
+ return result === 'true';
57
+ }
58
+ catch {
59
+ return false;
60
+ }
61
+ }
62
+ /** Whether a handle is registered for this session name. */
63
+ has(name) {
64
+ return this.handles.has(name);
65
+ }
66
+ /** Register (or update) a session handle with its CWD. */
67
+ register(name, cwd) {
68
+ this.handles.set(name, cwd);
69
+ }
70
+ /** Remove a session handle. */
71
+ unregister(name) {
72
+ this.handles.delete(name);
73
+ }
74
+ /**
75
+ * Execute an AppleScript via osascript stdin pipe.
76
+ * Using stdin pipe avoids all shell-quoting issues and supports multi-line scripts.
77
+ */
78
+ runScript(script) {
79
+ return new Promise((resolve, reject) => {
80
+ const child = (0, child_process_1.exec)('osascript -', { timeout: 5000 }, (err, stdout) => {
81
+ if (err)
82
+ reject(err);
83
+ else
84
+ resolve(stdout.trim());
85
+ });
86
+ child.stdin.write(script);
87
+ child.stdin.end();
88
+ });
89
+ }
90
+ /**
91
+ * Build an AppleScript string literal expression for the given value.
92
+ * Handles embedded double-quotes via & quote & concatenation.
93
+ */
94
+ buildAppleScriptString(str) {
95
+ const parts = str.split('"');
96
+ return parts.map(p => `"${p}"`).join(' & quote & ');
97
+ }
98
+ /**
99
+ * Build an AppleScript expression that produces the given text when evaluated.
100
+ * Uses (character id N) for control characters/non-printable bytes,
101
+ * and quote for embedded double-quotes.
102
+ */
103
+ buildAppleScriptText(text) {
104
+ const parts = [];
105
+ let current = '';
106
+ for (let i = 0; i < text.length; i++) {
107
+ const code = text.charCodeAt(i);
108
+ if (code >= 32 && code < 127 && code !== 34) {
109
+ // Printable ASCII except " — include in string literal
110
+ current += text[i];
111
+ }
112
+ else if (code === 34) { // "
113
+ if (current) {
114
+ parts.push(`"${current}"`);
115
+ current = '';
116
+ }
117
+ parts.push('quote');
118
+ }
119
+ else {
120
+ // Control character or non-ASCII — use character id
121
+ if (current) {
122
+ parts.push(`"${current}"`);
123
+ current = '';
124
+ }
125
+ parts.push(`(character id ${code})`);
126
+ }
127
+ }
128
+ if (current)
129
+ parts.push(`"${current}"`);
130
+ if (parts.length === 0)
131
+ return '""';
132
+ return parts.join(' & ');
133
+ }
134
+ /**
135
+ * Build the AppleScript fragment that finds the terminal for a registered CWD.
136
+ * Iterates all windows and tabs to find the terminal whose working directory matches.
137
+ */
138
+ findTermScript(cwd) {
139
+ const cwdExpr = this.buildAppleScriptString(cwd);
140
+ return `set targetCwd to ${cwdExpr}
141
+ set foundTerm to missing value
142
+ tell application "Ghostty"
143
+ repeat with w in windows
144
+ repeat with t in tabs of w
145
+ repeat with term in terminals of t
146
+ if working directory of term is targetCwd then
147
+ set foundTerm to term
148
+ exit repeat
149
+ end if
150
+ end repeat
151
+ if foundTerm is not missing value then exit repeat
152
+ end repeat
153
+ if foundTerm is not missing value then exit repeat
154
+ end repeat
155
+ if foundTerm is missing value then error "No Ghostty terminal found for cwd: " & targetCwd
156
+ end tell`;
157
+ }
158
+ /**
159
+ * Write raw text to a Ghostty terminal (paste-style).
160
+ * Handles printable ASCII, control characters (e.g. \r for Enter),
161
+ * and ANSI escape sequences (e.g. \x1B[B for Down arrow).
162
+ */
163
+ async write(name, text) {
164
+ const cwd = this.handles.get(name);
165
+ if (!cwd)
166
+ return false;
167
+ try {
168
+ const textExpr = this.buildAppleScriptText(text);
169
+ const script = `${this.findTermScript(cwd)}
170
+ tell application "Ghostty"
171
+ input text ${textExpr} to foundTerm
172
+ end tell`;
173
+ await this.runScript(script);
174
+ return true;
175
+ }
176
+ catch (err) {
177
+ process.stderr.write(`[ghostty-session-manager] write failed for ${name}: ${err.message}\n`);
178
+ return false;
179
+ }
180
+ }
181
+ /**
182
+ * Write text then immediately press Return — all in one AppleScript execution.
183
+ * Avoids a second CWD lookup between write and Enter, which can miss the terminal.
184
+ */
185
+ async writeLine(name, text) {
186
+ const cwd = this.handles.get(name);
187
+ if (!cwd)
188
+ return false;
189
+ try {
190
+ const textExpr = this.buildAppleScriptText(text);
191
+ const script = `${this.findTermScript(cwd)}
192
+ tell application "Ghostty"
193
+ focus foundTerm
194
+ input text ${textExpr} to foundTerm
195
+ delay 0.1
196
+ send key "enter" to foundTerm
197
+ end tell`;
198
+ await this.runScript(script);
199
+ return true;
200
+ }
201
+ catch (err) {
202
+ process.stderr.write(`[ghostty-session-manager] writeLine failed for ${name}: ${err.message}\n`);
203
+ return false;
204
+ }
205
+ }
206
+ /**
207
+ * Send a named key to a session.
208
+ * C-c and C-u use "send key ... with modifiers" (required by Ghostty AppleScript).
209
+ * Down, Up, Enter, Space use ANSI sequences via input text
210
+ * (send key "down" is broken in Ghostty 1.3.0).
211
+ */
212
+ async sendKey(name, key) {
213
+ const cwd = this.handles.get(name);
214
+ if (!cwd)
215
+ return false;
216
+ const modKey = MODIFIER_KEYS[key];
217
+ if (modKey) {
218
+ try {
219
+ const script = `${this.findTermScript(cwd)}
220
+ tell application "Ghostty"
221
+ focus foundTerm
222
+ send key "${modKey.key}" modifiers "${modKey.modifiers}" to foundTerm
223
+ end tell`;
224
+ await this.runScript(script);
225
+ return true;
226
+ }
227
+ catch (err) {
228
+ process.stderr.write(`[ghostty-session-manager] sendKey(${key}) failed for ${name}: ${err.message}\n`);
229
+ return false;
230
+ }
231
+ }
232
+ const sendKeyName = SEND_KEYS[key];
233
+ if (sendKeyName) {
234
+ try {
235
+ const script = `${this.findTermScript(cwd)}
236
+ tell application "Ghostty"
237
+ focus foundTerm
238
+ send key "${sendKeyName}" to foundTerm
239
+ end tell`;
240
+ await this.runScript(script);
241
+ return true;
242
+ }
243
+ catch (err) {
244
+ process.stderr.write(`[ghostty-session-manager] sendKey(${key}) failed for ${name}: ${err.message}\n`);
245
+ return false;
246
+ }
247
+ }
248
+ const keyCode = KEY_CODES[key];
249
+ if (keyCode !== undefined) {
250
+ try {
251
+ const script = `${this.findTermScript(cwd)}
252
+ tell application "Ghostty"
253
+ focus foundTerm
254
+ end tell
255
+ tell application "System Events"
256
+ tell process "Ghostty"
257
+ key code ${keyCode}
258
+ end tell
259
+ end tell`;
260
+ await this.runScript(script);
261
+ return true;
262
+ }
263
+ catch (err) {
264
+ process.stderr.write(`[ghostty-session-manager] sendKey(${key}) failed for ${name}: ${err.message}\n`);
265
+ return false;
266
+ }
267
+ }
268
+ // Unknown key — pass through as text
269
+ return this.write(name, key);
270
+ }
271
+ /** Send Ctrl+C interrupt to the terminal. */
272
+ async interrupt(name) {
273
+ return this.sendKey(name, 'C-c');
274
+ }
275
+ /**
276
+ * Capture terminal scrollback by triggering write_scrollback_file.
277
+ * Finds the new file in the OS temp directory and reads its content.
278
+ * Returns null if unavailable or no file produced within 1s.
279
+ */
280
+ async capture(name) {
281
+ const cwd = this.handles.get(name);
282
+ if (!cwd)
283
+ return null;
284
+ const tmpDir = os_1.default.tmpdir();
285
+ // 1. Note existing Ghostty temp files and their mtimes
286
+ const existingFiles = new Map();
287
+ try {
288
+ const files = fs_1.default.readdirSync(tmpDir);
289
+ for (const f of files) {
290
+ const fl = f.toLowerCase();
291
+ if (fl.startsWith('ghostty') || fl.startsWith('com.mitchellh.ghostty')) {
292
+ try {
293
+ const mtime = fs_1.default.statSync(`${tmpDir}/${f}`).mtimeMs;
294
+ existingFiles.set(f, mtime);
295
+ }
296
+ catch { }
297
+ }
298
+ }
299
+ }
300
+ catch { }
301
+ // 2. Trigger write_scrollback_file
302
+ try {
303
+ const script = `${this.findTermScript(cwd)}
304
+ tell application "Ghostty"
305
+ perform action "write_scrollback_file" on foundTerm
306
+ end tell`;
307
+ await this.runScript(script);
308
+ }
309
+ catch (err) {
310
+ process.stderr.write(`[ghostty-session-manager] capture trigger failed for ${name}: ${err.message}\n`);
311
+ return null;
312
+ }
313
+ // 3. Wait up to 1s for a new (or updated) file to appear
314
+ const deadline = Date.now() + 1000;
315
+ while (Date.now() < deadline) {
316
+ try {
317
+ const files = fs_1.default.readdirSync(tmpDir);
318
+ for (const f of files) {
319
+ const fl = f.toLowerCase();
320
+ if (fl.startsWith('ghostty') || fl.startsWith('com.mitchellh.ghostty')) {
321
+ const filePath = `${tmpDir}/${f}`;
322
+ try {
323
+ const mtime = fs_1.default.statSync(filePath).mtimeMs;
324
+ const prevMtime = existingFiles.get(f);
325
+ if (prevMtime === undefined || mtime > prevMtime) {
326
+ return fs_1.default.readFileSync(filePath, 'utf8');
327
+ }
328
+ }
329
+ catch { }
330
+ }
331
+ }
332
+ }
333
+ catch { }
334
+ await new Promise(r => setTimeout(r, 100));
335
+ }
336
+ return null;
337
+ }
338
+ /**
339
+ * Open a new tab in the front Ghostty window and run a command.
340
+ * Uses AppleScript's quoted form of for safe shell quoting of the cwd.
341
+ */
342
+ async openNewTab(cwd, command) {
343
+ try {
344
+ // Build AppleScript expression for cwd (used with quoted form of)
345
+ const cwdExpr = this.buildAppleScriptString(cwd);
346
+ // Build AppleScript expression for the command (plain text)
347
+ const cmdExpr = this.buildAppleScriptText(command);
348
+ const script = `tell application "Ghostty"
349
+ if (count of windows) is 0 then error "No Ghostty windows open"
350
+ set w to front window
351
+ perform action "new_tab" on w
352
+ delay 0.5
353
+ set term to focused terminal of selected tab of w
354
+ focus term
355
+ input text "cd " & quoted form of ${cwdExpr} & " && " & ${cmdExpr} to term
356
+ delay 0.1
357
+ send key "enter" to term
358
+ end tell`;
359
+ await this.runScript(script);
360
+ return true;
361
+ }
362
+ catch (err) {
363
+ process.stderr.write(`[ghostty-session-manager] openNewTab failed: ${err.message}\n`);
364
+ return false;
365
+ }
366
+ }
367
+ }
368
+ exports.GhosttySessionManager = GhosttySessionManager;
369
+ exports.ghosttySessionManager = new GhosttySessionManager();
370
+ //# sourceMappingURL=ghostty-session-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ghostty-session-manager.js","sourceRoot":"","sources":["../../../src/utils/ghostty-session-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Transcript Reader — reads Claude Code session JSONL transcripts to surface
3
+ * developer-useful status info (model, context %, last assistant message, etc.)
4
+ *
5
+ * Path: ~/.claude/projects/<encoded-cwd>/<sessionId>.jsonl
6
+ * Encoding: cwd with `/` replaced by `-` (so `/Users/foo/bar` → `-Users-foo-bar`)
7
+ */
8
+ /** Status fields parsed from a session transcript. */
9
+ export interface TranscriptStatus {
10
+ model?: string;
11
+ version?: string;
12
+ gitBranch?: string;
13
+ slug?: string;
14
+ cwd?: string;
15
+ sessionId?: string;
16
+ /** Total prompt+output tokens from the most recent assistant turn. */
17
+ contextTokens?: number;
18
+ /** Inferred from model name; null if unknown. */
19
+ contextLimit?: number | null;
20
+ /** 0-100, omitted when contextLimit is null. */
21
+ contextPct?: number;
22
+ /** Plain-text snippet of the last assistant message, truncated. */
23
+ lastAssistantMessage?: string;
24
+ /** ISO timestamp of the last assistant message. */
25
+ lastAssistantTimestamp?: string;
26
+ }
27
+ /** Encode a cwd into Claude Code's project directory name. */
28
+ export declare function encodeCwd(cwd: string): string;
29
+ /** Build the full path to a session's JSONL transcript. */
30
+ export declare function getTranscriptPath(cwd: string, sessionId: string): string;
31
+ /**
32
+ * Find the most recently modified transcript for a cwd when sessionId is unknown.
33
+ * Returns null if no transcripts exist for that cwd.
34
+ */
35
+ export declare function findLatestTranscript(cwd: string): {
36
+ sessionId: string;
37
+ path: string;
38
+ mtimeMs: number;
39
+ } | null;
40
+ /**
41
+ * Inferred context window size for known model name patterns.
42
+ * Returns null when we don't know the limit (caller should omit % display).
43
+ *
44
+ * Note: the [1m] suffix that enables 1M context is an API parameter — the model
45
+ * field in transcripts does NOT include it. So we conservatively assume 200K
46
+ * for Opus 4.6 unless we find a way to detect 1m mode.
47
+ */
48
+ export declare function inferContextLimit(model: string | undefined): number | null;
49
+ /**
50
+ * Read the latest status info from a session's transcript.
51
+ * Returns null when the transcript file doesn't exist or is unreadable.
52
+ *
53
+ * `maxAssistantChars` truncates the last-message snippet to keep Telegram
54
+ * messages under their 4096-char limit.
55
+ */
56
+ export declare function readTranscriptStatus(cwd: string, sessionId: string | undefined, maxAssistantChars?: number): TranscriptStatus | null;
57
+ //# sourceMappingURL=transcript-reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript-reader.d.ts","sourceRoot":"","sources":["../../../src/utils/transcript-reader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,sDAAsD;AACtD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,mDAAmD;IACnD,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,8DAA8D;AAC9D,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,2DAA2D;AAC3D,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAGxE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAgB7G;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAO1E;AA6DD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,iBAAiB,GAAE,MAAY,GAC9B,gBAAgB,GAAG,IAAI,CAsFzB"}