brosh 0.1.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 (200) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +181 -0
  3. package/brosh_brandmark.svg +3 -0
  4. package/brosh_logo.svg +27 -0
  5. package/cli_icon.svg +52 -0
  6. package/dist/client.d.ts +5 -0
  7. package/dist/client.d.ts.map +1 -0
  8. package/dist/client.js +138 -0
  9. package/dist/client.js.map +1 -0
  10. package/dist/index.d.ts +3 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +618 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/lib.d.ts +25 -0
  15. package/dist/lib.d.ts.map +1 -0
  16. package/dist/lib.js +28 -0
  17. package/dist/lib.js.map +1 -0
  18. package/dist/mode-selector.d.ts +7 -0
  19. package/dist/mode-selector.d.ts.map +1 -0
  20. package/dist/mode-selector.js +138 -0
  21. package/dist/mode-selector.js.map +1 -0
  22. package/dist/prompts/index.d.ts +3 -0
  23. package/dist/prompts/index.d.ts.map +1 -0
  24. package/dist/prompts/index.js +79 -0
  25. package/dist/prompts/index.js.map +1 -0
  26. package/dist/recording/index.d.ts +4 -0
  27. package/dist/recording/index.d.ts.map +1 -0
  28. package/dist/recording/index.js +3 -0
  29. package/dist/recording/index.js.map +1 -0
  30. package/dist/recording/manager.d.ts +62 -0
  31. package/dist/recording/manager.d.ts.map +1 -0
  32. package/dist/recording/manager.js +123 -0
  33. package/dist/recording/manager.js.map +1 -0
  34. package/dist/recording/recorder.d.ts +95 -0
  35. package/dist/recording/recorder.d.ts.map +1 -0
  36. package/dist/recording/recorder.js +330 -0
  37. package/dist/recording/recorder.js.map +1 -0
  38. package/dist/recording/types.d.ts +65 -0
  39. package/dist/recording/types.d.ts.map +1 -0
  40. package/dist/recording/types.js +2 -0
  41. package/dist/recording/types.js.map +1 -0
  42. package/dist/sandbox/ModeSelector.d.ts +2 -0
  43. package/dist/sandbox/ModeSelector.d.ts.map +1 -0
  44. package/dist/sandbox/ModeSelector.js +2 -0
  45. package/dist/sandbox/ModeSelector.js.map +1 -0
  46. package/dist/sandbox/config.d.ts +46 -0
  47. package/dist/sandbox/config.d.ts.map +1 -0
  48. package/dist/sandbox/config.js +144 -0
  49. package/dist/sandbox/config.js.map +1 -0
  50. package/dist/sandbox/controller.d.ts +72 -0
  51. package/dist/sandbox/controller.d.ts.map +1 -0
  52. package/dist/sandbox/controller.js +208 -0
  53. package/dist/sandbox/controller.js.map +1 -0
  54. package/dist/sandbox/index.d.ts +6 -0
  55. package/dist/sandbox/index.d.ts.map +1 -0
  56. package/dist/sandbox/index.js +4 -0
  57. package/dist/sandbox/index.js.map +1 -0
  58. package/dist/sandbox/mode-prompt.d.ts +10 -0
  59. package/dist/sandbox/mode-prompt.d.ts.map +1 -0
  60. package/dist/sandbox/mode-prompt.js +130 -0
  61. package/dist/sandbox/mode-prompt.js.map +1 -0
  62. package/dist/sandbox/prompt.d.ts +10 -0
  63. package/dist/sandbox/prompt.d.ts.map +1 -0
  64. package/dist/sandbox/prompt.js +434 -0
  65. package/dist/sandbox/prompt.js.map +1 -0
  66. package/dist/server.d.ts +28 -0
  67. package/dist/server.d.ts.map +1 -0
  68. package/dist/server.js +59 -0
  69. package/dist/server.js.map +1 -0
  70. package/dist/terminal/index.d.ts +5 -0
  71. package/dist/terminal/index.d.ts.map +1 -0
  72. package/dist/terminal/index.js +3 -0
  73. package/dist/terminal/index.js.map +1 -0
  74. package/dist/terminal/manager.d.ts +153 -0
  75. package/dist/terminal/manager.d.ts.map +1 -0
  76. package/dist/terminal/manager.js +276 -0
  77. package/dist/terminal/manager.js.map +1 -0
  78. package/dist/terminal/session.d.ts +137 -0
  79. package/dist/terminal/session.d.ts.map +1 -0
  80. package/dist/terminal/session.js +752 -0
  81. package/dist/terminal/session.js.map +1 -0
  82. package/dist/tools/definitions.d.ts +18 -0
  83. package/dist/tools/definitions.d.ts.map +1 -0
  84. package/dist/tools/definitions.js +114 -0
  85. package/dist/tools/definitions.js.map +1 -0
  86. package/dist/tools/getContent.d.ts +32 -0
  87. package/dist/tools/getContent.d.ts.map +1 -0
  88. package/dist/tools/getContent.js +38 -0
  89. package/dist/tools/getContent.js.map +1 -0
  90. package/dist/tools/index.d.ts +4 -0
  91. package/dist/tools/index.d.ts.map +1 -0
  92. package/dist/tools/index.js +49 -0
  93. package/dist/tools/index.js.map +1 -0
  94. package/dist/tools/screenshot.d.ts +20 -0
  95. package/dist/tools/screenshot.d.ts.map +1 -0
  96. package/dist/tools/screenshot.js +28 -0
  97. package/dist/tools/screenshot.js.map +1 -0
  98. package/dist/tools/sendKey.d.ts +31 -0
  99. package/dist/tools/sendKey.d.ts.map +1 -0
  100. package/dist/tools/sendKey.js +38 -0
  101. package/dist/tools/sendKey.js.map +1 -0
  102. package/dist/tools/startRecording.d.ts +68 -0
  103. package/dist/tools/startRecording.d.ts.map +1 -0
  104. package/dist/tools/startRecording.js +111 -0
  105. package/dist/tools/startRecording.js.map +1 -0
  106. package/dist/tools/stopRecording.d.ts +31 -0
  107. package/dist/tools/stopRecording.d.ts.map +1 -0
  108. package/dist/tools/stopRecording.js +76 -0
  109. package/dist/tools/stopRecording.js.map +1 -0
  110. package/dist/tools/type.d.ts +31 -0
  111. package/dist/tools/type.d.ts.map +1 -0
  112. package/dist/tools/type.js +31 -0
  113. package/dist/tools/type.js.map +1 -0
  114. package/dist/transport/gui-protocol.d.ts +163 -0
  115. package/dist/transport/gui-protocol.d.ts.map +1 -0
  116. package/dist/transport/gui-protocol.js +68 -0
  117. package/dist/transport/gui-protocol.js.map +1 -0
  118. package/dist/transport/gui-stream.d.ts +139 -0
  119. package/dist/transport/gui-stream.d.ts.map +1 -0
  120. package/dist/transport/gui-stream.js +440 -0
  121. package/dist/transport/gui-stream.js.map +1 -0
  122. package/dist/transport/index.d.ts +6 -0
  123. package/dist/transport/index.d.ts.map +1 -0
  124. package/dist/transport/index.js +6 -0
  125. package/dist/transport/index.js.map +1 -0
  126. package/dist/transport/socket.d.ts +46 -0
  127. package/dist/transport/socket.d.ts.map +1 -0
  128. package/dist/transport/socket.js +310 -0
  129. package/dist/transport/socket.js.map +1 -0
  130. package/dist/types/mcp-client-info.d.ts +226 -0
  131. package/dist/types/mcp-client-info.d.ts.map +1 -0
  132. package/dist/types/mcp-client-info.js +62 -0
  133. package/dist/types/mcp-client-info.js.map +1 -0
  134. package/dist/ui/index.d.ts +12 -0
  135. package/dist/ui/index.d.ts.map +1 -0
  136. package/dist/ui/index.js +84 -0
  137. package/dist/ui/index.js.map +1 -0
  138. package/dist/utils/env.d.ts +17 -0
  139. package/dist/utils/env.d.ts.map +1 -0
  140. package/dist/utils/env.js +35 -0
  141. package/dist/utils/env.js.map +1 -0
  142. package/dist/utils/keys.d.ts +16 -0
  143. package/dist/utils/keys.d.ts.map +1 -0
  144. package/dist/utils/keys.js +155 -0
  145. package/dist/utils/keys.js.map +1 -0
  146. package/dist/utils/platform.d.ts +16 -0
  147. package/dist/utils/platform.d.ts.map +1 -0
  148. package/dist/utils/platform.js +41 -0
  149. package/dist/utils/platform.js.map +1 -0
  150. package/dist/utils/session-logger.d.ts +31 -0
  151. package/dist/utils/session-logger.d.ts.map +1 -0
  152. package/dist/utils/session-logger.js +125 -0
  153. package/dist/utils/session-logger.js.map +1 -0
  154. package/dist/utils/stats.d.ts +46 -0
  155. package/dist/utils/stats.d.ts.map +1 -0
  156. package/dist/utils/stats.js +89 -0
  157. package/dist/utils/stats.js.map +1 -0
  158. package/dist/utils/version.d.ts +2 -0
  159. package/dist/utils/version.d.ts.map +1 -0
  160. package/dist/utils/version.js +9 -0
  161. package/dist/utils/version.js.map +1 -0
  162. package/logo.png +0 -0
  163. package/package.json +61 -0
  164. package/packages/desktop-electron/THIRD-PARTY-NOTICES +56 -0
  165. package/packages/desktop-electron/build/afterPack.cjs +147 -0
  166. package/packages/desktop-electron/package-lock.json +10071 -0
  167. package/packages/desktop-electron/package.json +172 -0
  168. package/packages/desktop-electron/resources/icons/mac/icon.icns +0 -0
  169. package/packages/desktop-electron/resources/icons/png/1024x1024.png +0 -0
  170. package/packages/desktop-electron/resources/icons/png/128x128.png +0 -0
  171. package/packages/desktop-electron/resources/icons/png/16x16.png +0 -0
  172. package/packages/desktop-electron/resources/icons/png/24x24.png +0 -0
  173. package/packages/desktop-electron/resources/icons/png/256x256.png +0 -0
  174. package/packages/desktop-electron/resources/icons/png/32x32.png +0 -0
  175. package/packages/desktop-electron/resources/icons/png/48x48.png +0 -0
  176. package/packages/desktop-electron/resources/icons/png/512x512.png +0 -0
  177. package/packages/desktop-electron/resources/icons/png/64x64.png +0 -0
  178. package/packages/desktop-electron/resources/icons/win/icon.ico +0 -0
  179. package/packages/desktop-electron/scripts/download-models.js +97 -0
  180. package/packages/desktop-electron/scripts/prepare-sandbox-bins.js +186 -0
  181. package/packages/desktop-electron/tests/main/ai-detection/additionalFunctions.test.ts +224 -0
  182. package/packages/desktop-electron/tests/main/ai-detection/checkOverridePrefix.test.ts +162 -0
  183. package/packages/desktop-electron/tests/main/ai-detection/classifyInput.test.ts +132 -0
  184. package/packages/desktop-electron/tests/main/ai-detection/detectTypos.test.ts +342 -0
  185. package/packages/desktop-electron/tests/main/ai-detection/fixtures/commands.ts +134 -0
  186. package/packages/desktop-electron/tests/main/ai-detection/fixtures/natural-language.ts +133 -0
  187. package/packages/desktop-electron/tests/main/ai-detection/fixtures/typos.ts +123 -0
  188. package/packages/desktop-electron/tests/main/ai-detection/hasValidSubcommand.test.ts +218 -0
  189. package/packages/desktop-electron/tests/main/ai-detection/isCommandNotFound.test.ts +117 -0
  190. package/packages/desktop-electron/tests/main/error-triage/buildTriagePrompt.test.ts +133 -0
  191. package/packages/desktop-electron/tests/main/error-triage/parseTriageResponse.test.ts +123 -0
  192. package/packages/desktop-electron/tests/main/terminal-bridge/battery-optimization.test.ts +243 -0
  193. package/packages/desktop-electron/tests/main/terminal-bridge/command-fast-track.test.ts +292 -0
  194. package/packages/desktop-electron/tests/main/terminal-bridge/default-cwd.test.ts +70 -0
  195. package/packages/desktop-electron/tests/setup.ts +274 -0
  196. package/packages/desktop-electron/tsconfig.json +18 -0
  197. package/packages/desktop-electron/tsconfig.main.json +20 -0
  198. package/packages/desktop-electron/vite.config.ts +19 -0
  199. package/packages/desktop-electron/vitest.config.ts +18 -0
  200. package/tsconfig.json +19 -0
@@ -0,0 +1,84 @@
1
+ import { VERSION } from "../utils/version.js";
2
+ import { getToolNames } from "../tools/definitions.js";
3
+ // Brand color (RGB: 49, 202, 225)
4
+ const BRAND_COLOR = "\x1b[38;2;49;202;225m";
5
+ // Bright yellow for borders
6
+ const YELLOW_COLOR = "\x1b[38;2;255;255;0m";
7
+ // White for text content
8
+ const WHITE_COLOR = "\x1b[38;2;255;255;255m";
9
+ // Green for sandbox indicator
10
+ const GREEN_COLOR = "\x1b[38;2;50;205;50m";
11
+ const RESET = "\x1b[0m";
12
+ // ANSI Shadow style figlet logo for "BROSH"
13
+ const LOGO = `
14
+ ██████╗ ██████╗ ██████╗ ███████╗██╗ ██╗
15
+ ██╔══██╗██╔══██╗██╔═══██╗██╔════╝██║ ██║
16
+ ██████╔╝██████╔╝██║ ██║███████╗███████║
17
+ ██╔══██╗██╔══██╗██║ ██║╚════██║██╔══██║
18
+ ██████╔╝██║ ██║╚██████╔╝███████║██║ ██║
19
+ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝╚══════╝╚═╝ ╚═╝
20
+ `.trim();
21
+ /**
22
+ * Generate the startup banner string
23
+ */
24
+ export function getBanner(options) {
25
+ // Build the logo with box around it
26
+ const logoLines = LOGO.split("\n");
27
+ // Find the widest logo line to determine box width
28
+ const maxLogoWidth = Math.max(...logoLines.map((l) => l.length));
29
+ const boxWidth = maxLogoWidth + 4; // 2 chars padding on each side
30
+ const horizontalLine = "─".repeat(boxWidth);
31
+ // Center the logo as a block (same left padding for all lines)
32
+ const centeredLogo = logoLines.map((line) => {
33
+ const rightPad = boxWidth - 2 - line.length;
34
+ return YELLOW_COLOR + "│ " + BRAND_COLOR + line + " ".repeat(rightPad) + " " + YELLOW_COLOR + "│";
35
+ });
36
+ // Generate tool lines - first line has "Tools:" label, rest are indented
37
+ const toolNames = getToolNames();
38
+ const toolLines = toolNames.map((tool, index) => {
39
+ const prefix = index === 0 ? " Tools: " : " ";
40
+ const bullet = "• ";
41
+ return `${YELLOW_COLOR}│${WHITE_COLOR}${prefix}${bullet}${padRight(tool, boxWidth - prefix.length - 3)}${YELLOW_COLOR}│`;
42
+ });
43
+ const mcpConfig = `{
44
+ "mcpServers": {
45
+ "terminal": {
46
+ "command": "brosh"
47
+ }
48
+ }
49
+ }`;
50
+ // Build sandbox status line if enabled
51
+ const sandboxLine = options.sandboxEnabled
52
+ ? `${YELLOW_COLOR}│${WHITE_COLOR} Sandbox: ${GREEN_COLOR}ENABLED${WHITE_COLOR} (restricted access)${" ".repeat(boxWidth - 41)}${YELLOW_COLOR}│\n`
53
+ : "";
54
+ return `
55
+ ${YELLOW_COLOR}╭${horizontalLine}╮
56
+ ${centeredLogo.join("\n")}
57
+ ${YELLOW_COLOR}├${horizontalLine}┤
58
+ ${YELLOW_COLOR}│${WHITE_COLOR} Socket: ${padRight(options.socketPath, boxWidth - 11)}${YELLOW_COLOR}│
59
+ ${YELLOW_COLOR}│${WHITE_COLOR} Terminal: ${padRight(`${options.cols}x${options.rows}`, 12)}Shell: ${padRight(options.shell, boxWidth - 30)}${YELLOW_COLOR}│
60
+ ${sandboxLine}${YELLOW_COLOR}├${horizontalLine}┤
61
+ ${toolLines.join("\n")}
62
+ ${YELLOW_COLOR}├${horizontalLine}┤
63
+ ${YELLOW_COLOR}│${WHITE_COLOR}${" ".repeat(boxWidth - 7)}v${VERSION} ${YELLOW_COLOR}│
64
+ ${YELLOW_COLOR}╰${horizontalLine}╯${RESET}
65
+
66
+ ${WHITE_COLOR}MCP Configuration (add to your MCP client):${RESET}
67
+
68
+ ${mcpConfig}
69
+
70
+ ${YELLOW_COLOR}╭${horizontalLine}╮
71
+ │${WHITE_COLOR} Restart your MCP client to connect.${" ".repeat(boxWidth - 38)}${YELLOW_COLOR}│
72
+ ╰${horizontalLine}╯${RESET}
73
+ `;
74
+ }
75
+ /**
76
+ * Pad a string to the right with spaces
77
+ */
78
+ function padRight(str, length) {
79
+ if (str.length >= length) {
80
+ return str.substring(0, length - 1) + " ";
81
+ }
82
+ return str + " ".repeat(length - str.length);
83
+ }
84
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Environment variable helpers for brosh.
3
+ *
4
+ * Supports both BROSH_* and legacy TERMINAL_MCP_* env vars.
5
+ * Legacy vars trigger a one-time deprecation warning on stderr.
6
+ */
7
+ /**
8
+ * Read an environment variable, checking the new BROSH_* name first,
9
+ * then falling back to the legacy TERMINAL_MCP_* name with a deprecation warning.
10
+ */
11
+ export declare function getEnv(broshName: string, legacyName: string): string | undefined;
12
+ /**
13
+ * Set both the new and legacy env var names on a process env object.
14
+ * Used when spawning child processes that may check either name.
15
+ */
16
+ export declare function setEnv(env: Record<string, string>, broshName: string, legacyName: string, value: string): void;
17
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/utils/env.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;GAGG;AACH,wBAAgB,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAkBhF;AAED;;;GAGG;AACH,wBAAgB,MAAM,CACpB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,GACZ,IAAI,CAGN"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Environment variable helpers for brosh.
3
+ *
4
+ * Supports both BROSH_* and legacy TERMINAL_MCP_* env vars.
5
+ * Legacy vars trigger a one-time deprecation warning on stderr.
6
+ */
7
+ const warnedVars = new Set();
8
+ /**
9
+ * Read an environment variable, checking the new BROSH_* name first,
10
+ * then falling back to the legacy TERMINAL_MCP_* name with a deprecation warning.
11
+ */
12
+ export function getEnv(broshName, legacyName) {
13
+ const broshVal = process.env[broshName];
14
+ if (broshVal !== undefined) {
15
+ return broshVal;
16
+ }
17
+ const legacyVal = process.env[legacyName];
18
+ if (legacyVal !== undefined) {
19
+ if (!warnedVars.has(legacyName)) {
20
+ warnedVars.add(legacyName);
21
+ console.error(`[brosh] Warning: ${legacyName} is deprecated, use ${broshName} instead.`);
22
+ }
23
+ return legacyVal;
24
+ }
25
+ return undefined;
26
+ }
27
+ /**
28
+ * Set both the new and legacy env var names on a process env object.
29
+ * Used when spawning child processes that may check either name.
30
+ */
31
+ export function setEnv(env, broshName, legacyName, value) {
32
+ env[broshName] = value;
33
+ env[legacyName] = value;
34
+ }
35
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/utils/env.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;AAErC;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAC,SAAiB,EAAE,UAAkB;IAC1D,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACxC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC1C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YAChC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC3B,OAAO,CAAC,KAAK,CACX,oBAAoB,UAAU,uBAAuB,SAAS,WAAW,CAC1E,CAAC;QACJ,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,MAAM,CACpB,GAA2B,EAC3B,SAAiB,EACjB,UAAkB,EAClB,KAAa;IAEb,GAAG,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;IACvB,GAAG,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Key code mappings for terminal special keys
3
+ * Maps human-readable key names to their ANSI escape sequences
4
+ */
5
+ export declare const KEY_SEQUENCES: Record<string, string>;
6
+ /**
7
+ * Get the escape sequence for a key name
8
+ * @param key - The key name (e.g., "Enter", "Ctrl+C", "ArrowUp")
9
+ * @returns The escape sequence or null if not found
10
+ */
11
+ export declare function getKeySequence(key: string): string | null;
12
+ /**
13
+ * Get all available key names
14
+ */
15
+ export declare function getAvailableKeys(): string[];
16
+ //# sourceMappingURL=keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../src/utils/keys.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAmIhD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBzD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAE3C"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Key code mappings for terminal special keys
3
+ * Maps human-readable key names to their ANSI escape sequences
4
+ */
5
+ export const KEY_SEQUENCES = {
6
+ // Control keys
7
+ "Enter": "\r",
8
+ "Tab": "\t",
9
+ "Escape": "\x1b",
10
+ "Backspace": "\x7f",
11
+ "Delete": "\x1b[3~",
12
+ "Space": " ",
13
+ // Arrow keys (with aliases)
14
+ "ArrowUp": "\x1b[A",
15
+ "ArrowDown": "\x1b[B",
16
+ "ArrowRight": "\x1b[C",
17
+ "ArrowLeft": "\x1b[D",
18
+ "Up": "\x1b[A",
19
+ "Down": "\x1b[B",
20
+ "Right": "\x1b[C",
21
+ "Left": "\x1b[D",
22
+ // Navigation keys
23
+ "Home": "\x1b[H",
24
+ "End": "\x1b[F",
25
+ "PageUp": "\x1b[5~",
26
+ "PageDown": "\x1b[6~",
27
+ "Insert": "\x1b[2~",
28
+ // Function keys
29
+ "F1": "\x1bOP",
30
+ "F2": "\x1bOQ",
31
+ "F3": "\x1bOR",
32
+ "F4": "\x1bOS",
33
+ "F5": "\x1b[15~",
34
+ "F6": "\x1b[17~",
35
+ "F7": "\x1b[18~",
36
+ "F8": "\x1b[19~",
37
+ "F9": "\x1b[20~",
38
+ "F10": "\x1b[21~",
39
+ "F11": "\x1b[23~",
40
+ "F12": "\x1b[24~",
41
+ // Ctrl combinations
42
+ "Ctrl+A": "\x01",
43
+ "Ctrl+B": "\x02",
44
+ "Ctrl+C": "\x03",
45
+ "Ctrl+D": "\x04",
46
+ "Ctrl+E": "\x05",
47
+ "Ctrl+F": "\x06",
48
+ "Ctrl+G": "\x07",
49
+ "Ctrl+H": "\x08",
50
+ "Ctrl+I": "\x09",
51
+ "Ctrl+J": "\x0a",
52
+ "Ctrl+K": "\x0b",
53
+ "Ctrl+L": "\x0c",
54
+ "Ctrl+M": "\x0d",
55
+ "Ctrl+N": "\x0e",
56
+ "Ctrl+O": "\x0f",
57
+ "Ctrl+P": "\x10",
58
+ "Ctrl+Q": "\x11",
59
+ "Ctrl+R": "\x12",
60
+ "Ctrl+S": "\x13",
61
+ "Ctrl+T": "\x14",
62
+ "Ctrl+U": "\x15",
63
+ "Ctrl+V": "\x16",
64
+ "Ctrl+W": "\x17",
65
+ "Ctrl+X": "\x18",
66
+ "Ctrl+Y": "\x19",
67
+ "Ctrl+Z": "\x1a",
68
+ "Ctrl+[": "\x1b",
69
+ "Ctrl+\\": "\x1c",
70
+ "Ctrl+]": "\x1d",
71
+ "Ctrl+^": "\x1e",
72
+ "Ctrl+_": "\x1f",
73
+ // Common shortcuts
74
+ "Ctrl+Space": "\x00",
75
+ // Alt combinations (ESC + char)
76
+ "Alt+0": "\x1b0",
77
+ "Alt+1": "\x1b1",
78
+ "Alt+2": "\x1b2",
79
+ "Alt+3": "\x1b3",
80
+ "Alt+4": "\x1b4",
81
+ "Alt+5": "\x1b5",
82
+ "Alt+6": "\x1b6",
83
+ "Alt+7": "\x1b7",
84
+ "Alt+8": "\x1b8",
85
+ "Alt+9": "\x1b9",
86
+ "Alt+A": "\x1ba",
87
+ "Alt+B": "\x1bb",
88
+ "Alt+C": "\x1bc",
89
+ "Alt+D": "\x1bd",
90
+ "Alt+E": "\x1be",
91
+ "Alt+F": "\x1bf",
92
+ "Alt+G": "\x1bg",
93
+ "Alt+H": "\x1bh",
94
+ "Alt+I": "\x1bi",
95
+ "Alt+J": "\x1bj",
96
+ "Alt+K": "\x1bk",
97
+ "Alt+L": "\x1bl",
98
+ "Alt+M": "\x1bm",
99
+ "Alt+N": "\x1bn",
100
+ "Alt+O": "\x1bo",
101
+ "Alt+P": "\x1bp",
102
+ "Alt+Q": "\x1bq",
103
+ "Alt+R": "\x1br",
104
+ "Alt+S": "\x1bs",
105
+ "Alt+T": "\x1bt",
106
+ "Alt+U": "\x1bu",
107
+ "Alt+V": "\x1bv",
108
+ "Alt+W": "\x1bw",
109
+ "Alt+X": "\x1bx",
110
+ "Alt+Y": "\x1by",
111
+ "Alt+Z": "\x1bz",
112
+ // Alt+Arrow combinations
113
+ "Alt+Up": "\x1b[1;3A",
114
+ "Alt+Down": "\x1b[1;3B",
115
+ "Alt+Right": "\x1b[1;3C",
116
+ "Alt+Left": "\x1b[1;3D",
117
+ // Shift+Arrow combinations
118
+ "Shift+Up": "\x1b[1;2A",
119
+ "Shift+Down": "\x1b[1;2B",
120
+ "Shift+Right": "\x1b[1;2C",
121
+ "Shift+Left": "\x1b[1;2D",
122
+ // Ctrl+Arrow combinations
123
+ "Ctrl+Up": "\x1b[1;5A",
124
+ "Ctrl+Down": "\x1b[1;5B",
125
+ "Ctrl+Right": "\x1b[1;5C",
126
+ "Ctrl+Left": "\x1b[1;5D",
127
+ };
128
+ /**
129
+ * Get the escape sequence for a key name
130
+ * @param key - The key name (e.g., "Enter", "Ctrl+C", "ArrowUp")
131
+ * @returns The escape sequence or null if not found
132
+ */
133
+ export function getKeySequence(key) {
134
+ // Normalize key name
135
+ const normalized = key.trim();
136
+ // Check direct match
137
+ if (KEY_SEQUENCES[normalized]) {
138
+ return KEY_SEQUENCES[normalized];
139
+ }
140
+ // Check case-insensitive match
141
+ const lowerKey = normalized.toLowerCase();
142
+ for (const [name, seq] of Object.entries(KEY_SEQUENCES)) {
143
+ if (name.toLowerCase() === lowerKey) {
144
+ return seq;
145
+ }
146
+ }
147
+ return null;
148
+ }
149
+ /**
150
+ * Get all available key names
151
+ */
152
+ export function getAvailableKeys() {
153
+ return Object.keys(KEY_SEQUENCES);
154
+ }
155
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/utils/keys.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Get the default recording directory.
3
+ * Uses XDG_STATE_HOME or falls back to ~/.local/state/brosh/recordings.
4
+ * Can be overridden with BROSH_RECORD_DIR (or legacy TERMINAL_MCP_RECORD_DIR) environment variable.
5
+ */
6
+ export declare function getDefaultRecordDir(): string;
7
+ /**
8
+ * Get the default IPC path for cross-platform communication.
9
+ * Uses named pipes on Windows, Unix sockets elsewhere.
10
+ */
11
+ export declare function getDefaultSocketPath(): string;
12
+ /**
13
+ * Get the default shell for the current platform.
14
+ */
15
+ export declare function getDefaultShell(): string;
16
+ //# sourceMappingURL=platform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/utils/platform.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAY5C;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAO7C;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAKxC"}
@@ -0,0 +1,41 @@
1
+ import * as path from "path";
2
+ import * as os from "os";
3
+ import { getEnv } from "./env.js";
4
+ /**
5
+ * Get the default recording directory.
6
+ * Uses XDG_STATE_HOME or falls back to ~/.local/state/brosh/recordings.
7
+ * Can be overridden with BROSH_RECORD_DIR (or legacy TERMINAL_MCP_RECORD_DIR) environment variable.
8
+ */
9
+ export function getDefaultRecordDir() {
10
+ // Check env var override first (supports legacy TERMINAL_MCP_RECORD_DIR)
11
+ const envDir = getEnv('BROSH_RECORD_DIR', 'TERMINAL_MCP_RECORD_DIR');
12
+ if (envDir) {
13
+ return envDir;
14
+ }
15
+ // Use XDG_STATE_HOME or fallback
16
+ const stateHome = process.env.XDG_STATE_HOME
17
+ || path.join(os.homedir(), '.local', 'state');
18
+ return path.join(stateHome, 'brosh', 'recordings');
19
+ }
20
+ /**
21
+ * Get the default IPC path for cross-platform communication.
22
+ * Uses named pipes on Windows, Unix sockets elsewhere.
23
+ */
24
+ export function getDefaultSocketPath() {
25
+ if (process.platform === "win32") {
26
+ return "\\\\.\\pipe\\brosh";
27
+ }
28
+ // Use /tmp directly instead of os.tmpdir() which returns user-specific paths on macOS
29
+ // (e.g., /var/folders/vj/.../T/). This ensures CLI and GUI use the same socket path.
30
+ return "/tmp/brosh.sock";
31
+ }
32
+ /**
33
+ * Get the default shell for the current platform.
34
+ */
35
+ export function getDefaultShell() {
36
+ if (process.platform === "win32") {
37
+ return process.env.COMSPEC || "cmd.exe";
38
+ }
39
+ return process.env.SHELL || "/bin/bash";
40
+ }
41
+ //# sourceMappingURL=platform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/utils/platform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC;;;;GAIG;AACH,MAAM,UAAU,mBAAmB;IACjC,yEAAyE;IACzE,MAAM,MAAM,GAAG,MAAM,CAAC,kBAAkB,EAAE,yBAAyB,CAAC,CAAC;IACrE,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,iCAAiC;IACjC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc;WACvC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAEhD,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;AACrD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB;IAClC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IACD,sFAAsF;IACtF,qFAAqF;IACrF,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,SAAS,CAAC;IAC1C,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,WAAW,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Session Logger
3
+ *
4
+ * Logs MCP session activity to temp files in JSONL format.
5
+ * Files are named with PID to enable stale file cleanup on startup.
6
+ */
7
+ import type { SessionLogEntry } from "../types/mcp-client-info.js";
8
+ export declare class SessionLogger {
9
+ private filePath;
10
+ private writeStream;
11
+ private isDisposed;
12
+ constructor();
13
+ /**
14
+ * Log an entry to the session file
15
+ */
16
+ log(entry: SessionLogEntry): void;
17
+ /**
18
+ * Get the path to the log file
19
+ */
20
+ getFilePath(): string;
21
+ /**
22
+ * Close the logger and clean up the temp file
23
+ */
24
+ close(): void;
25
+ /**
26
+ * Clean up stale session files from crashed processes
27
+ * Should be called on application startup
28
+ */
29
+ static cleanupStale(): Promise<number>;
30
+ }
31
+ //# sourceMappingURL=session-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-logger.d.ts","sourceRoot":"","sources":["../../src/utils/session-logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAInE,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,UAAU,CAAS;;IAmB3B;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAYjC;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACH,KAAK,IAAI,IAAI;IAqBb;;;OAGG;IACH,MAAM,CAAC,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;CA0CvC"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Session Logger
3
+ *
4
+ * Logs MCP session activity to temp files in JSONL format.
5
+ * Files are named with PID to enable stale file cleanup on startup.
6
+ */
7
+ import * as fs from "fs";
8
+ import * as path from "path";
9
+ import * as os from "os";
10
+ const SESSION_DIR = path.join(os.tmpdir(), "brosh-sessions");
11
+ export class SessionLogger {
12
+ filePath;
13
+ writeStream = null;
14
+ isDisposed = false;
15
+ constructor() {
16
+ // Ensure directory exists
17
+ fs.mkdirSync(SESSION_DIR, { recursive: true });
18
+ // Create file with PID in name for stale detection
19
+ const timestamp = Date.now();
20
+ this.filePath = path.join(SESSION_DIR, `session-${process.pid}-${timestamp}.jsonl`);
21
+ // Open write stream in append mode
22
+ this.writeStream = fs.createWriteStream(this.filePath, { flags: "a" });
23
+ // Handle stream errors gracefully
24
+ this.writeStream.on("error", (err) => {
25
+ console.error("[session-logger] Write stream error:", err);
26
+ });
27
+ }
28
+ /**
29
+ * Log an entry to the session file
30
+ */
31
+ log(entry) {
32
+ if (this.isDisposed || !this.writeStream) {
33
+ return;
34
+ }
35
+ try {
36
+ this.writeStream.write(JSON.stringify(entry) + "\n");
37
+ }
38
+ catch (err) {
39
+ console.error("[session-logger] Failed to write log entry:", err);
40
+ }
41
+ }
42
+ /**
43
+ * Get the path to the log file
44
+ */
45
+ getFilePath() {
46
+ return this.filePath;
47
+ }
48
+ /**
49
+ * Close the logger and clean up the temp file
50
+ */
51
+ close() {
52
+ if (this.isDisposed) {
53
+ return;
54
+ }
55
+ this.isDisposed = true;
56
+ // End the write stream
57
+ if (this.writeStream) {
58
+ this.writeStream.end();
59
+ this.writeStream = null;
60
+ }
61
+ // Remove the temp file
62
+ try {
63
+ fs.unlinkSync(this.filePath);
64
+ }
65
+ catch {
66
+ // Ignore errors if file doesn't exist
67
+ }
68
+ }
69
+ /**
70
+ * Clean up stale session files from crashed processes
71
+ * Should be called on application startup
72
+ */
73
+ static cleanupStale() {
74
+ return new Promise((resolve) => {
75
+ let cleaned = 0;
76
+ try {
77
+ // Ensure directory exists
78
+ if (!fs.existsSync(SESSION_DIR)) {
79
+ resolve(0);
80
+ return;
81
+ }
82
+ const files = fs.readdirSync(SESSION_DIR);
83
+ for (const file of files) {
84
+ // Parse PID from filename: session-<pid>-<timestamp>.jsonl
85
+ const match = file.match(/^session-(\d+)-\d+\.jsonl$/);
86
+ if (!match) {
87
+ continue;
88
+ }
89
+ const filePid = parseInt(match[1], 10);
90
+ // Check if process is still running
91
+ if (!isProcessRunning(filePid)) {
92
+ // Process is dead, clean up the file
93
+ const filePath = path.join(SESSION_DIR, file);
94
+ try {
95
+ fs.unlinkSync(filePath);
96
+ cleaned++;
97
+ console.log(`[session-logger] Cleaned stale file: ${file}`);
98
+ }
99
+ catch (err) {
100
+ console.error(`[session-logger] Failed to clean ${file}:`, err);
101
+ }
102
+ }
103
+ }
104
+ }
105
+ catch (err) {
106
+ console.error("[session-logger] Error during stale cleanup:", err);
107
+ }
108
+ resolve(cleaned);
109
+ });
110
+ }
111
+ }
112
+ /**
113
+ * Check if a process with given PID is still running
114
+ */
115
+ function isProcessRunning(pid) {
116
+ try {
117
+ // Signal 0 doesn't send anything but checks if process exists
118
+ process.kill(pid, 0);
119
+ return true;
120
+ }
121
+ catch {
122
+ return false;
123
+ }
124
+ }
125
+ //# sourceMappingURL=session-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-logger.js","sourceRoot":"","sources":["../../src/utils/session-logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Simple stats tracking for terminal MCP sessions
3
+ */
4
+ export declare class Stats {
5
+ private startTime;
6
+ private toolCalls;
7
+ private totalCalls;
8
+ constructor();
9
+ /**
10
+ * Record a tool call
11
+ */
12
+ recordToolCall(toolName: string): void;
13
+ /**
14
+ * Get uptime in seconds
15
+ */
16
+ getUptimeSeconds(): number;
17
+ /**
18
+ * Get formatted uptime string
19
+ */
20
+ getFormattedUptime(): string;
21
+ /**
22
+ * Get total tool calls
23
+ */
24
+ getTotalCalls(): number;
25
+ /**
26
+ * Get tool calls breakdown
27
+ */
28
+ getToolCallsBreakdown(): Map<string, number>;
29
+ /**
30
+ * Get stats summary
31
+ */
32
+ getSummary(): {
33
+ uptime: string;
34
+ totalCalls: number;
35
+ toolCalls: Record<string, number>;
36
+ };
37
+ }
38
+ /**
39
+ * Get or create the global stats instance
40
+ */
41
+ export declare function getStats(): Stats;
42
+ /**
43
+ * Reset stats (mainly for testing)
44
+ */
45
+ export declare function resetStats(): void;
46
+ //# sourceMappingURL=stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/utils/stats.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,KAAK;IAChB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,UAAU,CAAS;;IAQ3B;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAMtC;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAI1B;;OAEG;IACH,kBAAkB,IAAI,MAAM;IAe5B;;OAEG;IACH,aAAa,IAAI,MAAM;IAIvB;;OAEG;IACH,qBAAqB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAI5C;;OAEG;IACH,UAAU,IAAI;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACnC;CAWF;AAKD;;GAEG;AACH,wBAAgB,QAAQ,IAAI,KAAK,CAKhC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAEjC"}