procsi 0.2.6

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 (296) hide show
  1. package/LICENSE +665 -0
  2. package/README.md +587 -0
  3. package/dist/cli/commands/clear.d.ts +3 -0
  4. package/dist/cli/commands/clear.d.ts.map +1 -0
  5. package/dist/cli/commands/clear.js +30 -0
  6. package/dist/cli/commands/clear.js.map +1 -0
  7. package/dist/cli/commands/daemon.d.ts +3 -0
  8. package/dist/cli/commands/daemon.d.ts.map +1 -0
  9. package/dist/cli/commands/daemon.js +59 -0
  10. package/dist/cli/commands/daemon.js.map +1 -0
  11. package/dist/cli/commands/debug-dump.d.ts +27 -0
  12. package/dist/cli/commands/debug-dump.d.ts.map +1 -0
  13. package/dist/cli/commands/debug-dump.js +102 -0
  14. package/dist/cli/commands/debug-dump.js.map +1 -0
  15. package/dist/cli/commands/helpers.d.ts +18 -0
  16. package/dist/cli/commands/helpers.d.ts.map +1 -0
  17. package/dist/cli/commands/helpers.js +34 -0
  18. package/dist/cli/commands/helpers.js.map +1 -0
  19. package/dist/cli/commands/init.d.ts +9 -0
  20. package/dist/cli/commands/init.d.ts.map +1 -0
  21. package/dist/cli/commands/init.js +28 -0
  22. package/dist/cli/commands/init.js.map +1 -0
  23. package/dist/cli/commands/intercept.d.ts +9 -0
  24. package/dist/cli/commands/intercept.d.ts.map +1 -0
  25. package/dist/cli/commands/intercept.js +121 -0
  26. package/dist/cli/commands/intercept.js.map +1 -0
  27. package/dist/cli/commands/interceptors.d.ts +3 -0
  28. package/dist/cli/commands/interceptors.d.ts.map +1 -0
  29. package/dist/cli/commands/interceptors.js +163 -0
  30. package/dist/cli/commands/interceptors.js.map +1 -0
  31. package/dist/cli/commands/mcp.d.ts +3 -0
  32. package/dist/cli/commands/mcp.d.ts.map +1 -0
  33. package/dist/cli/commands/mcp.js +24 -0
  34. package/dist/cli/commands/mcp.js.map +1 -0
  35. package/dist/cli/commands/off.d.ts +8 -0
  36. package/dist/cli/commands/off.d.ts.map +1 -0
  37. package/dist/cli/commands/off.js +34 -0
  38. package/dist/cli/commands/off.js.map +1 -0
  39. package/dist/cli/commands/on.d.ts +9 -0
  40. package/dist/cli/commands/on.d.ts.map +1 -0
  41. package/dist/cli/commands/on.js +121 -0
  42. package/dist/cli/commands/on.js.map +1 -0
  43. package/dist/cli/commands/project.d.ts +3 -0
  44. package/dist/cli/commands/project.d.ts.map +1 -0
  45. package/dist/cli/commands/project.js +15 -0
  46. package/dist/cli/commands/project.js.map +1 -0
  47. package/dist/cli/commands/restart.d.ts +3 -0
  48. package/dist/cli/commands/restart.d.ts.map +1 -0
  49. package/dist/cli/commands/restart.js +35 -0
  50. package/dist/cli/commands/restart.js.map +1 -0
  51. package/dist/cli/commands/status.d.ts +3 -0
  52. package/dist/cli/commands/status.d.ts.map +1 -0
  53. package/dist/cli/commands/status.js +66 -0
  54. package/dist/cli/commands/status.js.map +1 -0
  55. package/dist/cli/commands/stop.d.ts +3 -0
  56. package/dist/cli/commands/stop.d.ts.map +1 -0
  57. package/dist/cli/commands/stop.js +24 -0
  58. package/dist/cli/commands/stop.js.map +1 -0
  59. package/dist/cli/commands/tui.d.ts +3 -0
  60. package/dist/cli/commands/tui.d.ts.map +1 -0
  61. package/dist/cli/commands/tui.js +36 -0
  62. package/dist/cli/commands/tui.js.map +1 -0
  63. package/dist/cli/commands/vars.d.ts +36 -0
  64. package/dist/cli/commands/vars.d.ts.map +1 -0
  65. package/dist/cli/commands/vars.js +207 -0
  66. package/dist/cli/commands/vars.js.map +1 -0
  67. package/dist/cli/index.d.ts +3 -0
  68. package/dist/cli/index.d.ts.map +1 -0
  69. package/dist/cli/index.js +37 -0
  70. package/dist/cli/index.js.map +1 -0
  71. package/dist/cli/tui/App.d.ts +15 -0
  72. package/dist/cli/tui/App.d.ts.map +1 -0
  73. package/dist/cli/tui/App.js +544 -0
  74. package/dist/cli/tui/App.js.map +1 -0
  75. package/dist/cli/tui/components/AccordionContent.d.ts +28 -0
  76. package/dist/cli/tui/components/AccordionContent.d.ts.map +1 -0
  77. package/dist/cli/tui/components/AccordionContent.js +87 -0
  78. package/dist/cli/tui/components/AccordionContent.js.map +1 -0
  79. package/dist/cli/tui/components/AccordionPanel.d.ts +38 -0
  80. package/dist/cli/tui/components/AccordionPanel.d.ts.map +1 -0
  81. package/dist/cli/tui/components/AccordionPanel.js +110 -0
  82. package/dist/cli/tui/components/AccordionPanel.js.map +1 -0
  83. package/dist/cli/tui/components/AccordionSection.d.ts +32 -0
  84. package/dist/cli/tui/components/AccordionSection.d.ts.map +1 -0
  85. package/dist/cli/tui/components/AccordionSection.js +41 -0
  86. package/dist/cli/tui/components/AccordionSection.js.map +1 -0
  87. package/dist/cli/tui/components/BodyView.d.ts +14 -0
  88. package/dist/cli/tui/components/BodyView.d.ts.map +1 -0
  89. package/dist/cli/tui/components/BodyView.js +39 -0
  90. package/dist/cli/tui/components/BodyView.js.map +1 -0
  91. package/dist/cli/tui/components/ExportModal.d.ts +34 -0
  92. package/dist/cli/tui/components/ExportModal.d.ts.map +1 -0
  93. package/dist/cli/tui/components/ExportModal.js +109 -0
  94. package/dist/cli/tui/components/ExportModal.js.map +1 -0
  95. package/dist/cli/tui/components/FilterBar.d.ts +21 -0
  96. package/dist/cli/tui/components/FilterBar.d.ts.map +1 -0
  97. package/dist/cli/tui/components/FilterBar.js +155 -0
  98. package/dist/cli/tui/components/FilterBar.js.map +1 -0
  99. package/dist/cli/tui/components/HeadersView.d.ts +13 -0
  100. package/dist/cli/tui/components/HeadersView.d.ts.map +1 -0
  101. package/dist/cli/tui/components/HeadersView.js +8 -0
  102. package/dist/cli/tui/components/HeadersView.js.map +1 -0
  103. package/dist/cli/tui/components/HelpModal.d.ts +13 -0
  104. package/dist/cli/tui/components/HelpModal.d.ts.map +1 -0
  105. package/dist/cli/tui/components/HelpModal.js +78 -0
  106. package/dist/cli/tui/components/HelpModal.js.map +1 -0
  107. package/dist/cli/tui/components/HintContent.d.ts +25 -0
  108. package/dist/cli/tui/components/HintContent.d.ts.map +1 -0
  109. package/dist/cli/tui/components/HintContent.js +44 -0
  110. package/dist/cli/tui/components/HintContent.js.map +1 -0
  111. package/dist/cli/tui/components/InfoModal.d.ts +15 -0
  112. package/dist/cli/tui/components/InfoModal.d.ts.map +1 -0
  113. package/dist/cli/tui/components/InfoModal.js +17 -0
  114. package/dist/cli/tui/components/InfoModal.js.map +1 -0
  115. package/dist/cli/tui/components/JsonExplorerModal.d.ts +24 -0
  116. package/dist/cli/tui/components/JsonExplorerModal.d.ts.map +1 -0
  117. package/dist/cli/tui/components/JsonExplorerModal.js +311 -0
  118. package/dist/cli/tui/components/JsonExplorerModal.js.map +1 -0
  119. package/dist/cli/tui/components/Modal.d.ts +26 -0
  120. package/dist/cli/tui/components/Modal.d.ts.map +1 -0
  121. package/dist/cli/tui/components/Modal.js +15 -0
  122. package/dist/cli/tui/components/Modal.js.map +1 -0
  123. package/dist/cli/tui/components/Panel.d.ts +19 -0
  124. package/dist/cli/tui/components/Panel.d.ts.map +1 -0
  125. package/dist/cli/tui/components/Panel.js +37 -0
  126. package/dist/cli/tui/components/Panel.js.map +1 -0
  127. package/dist/cli/tui/components/RequestDetails.d.ts +16 -0
  128. package/dist/cli/tui/components/RequestDetails.d.ts.map +1 -0
  129. package/dist/cli/tui/components/RequestDetails.js +23 -0
  130. package/dist/cli/tui/components/RequestDetails.js.map +1 -0
  131. package/dist/cli/tui/components/RequestList.d.ts +21 -0
  132. package/dist/cli/tui/components/RequestList.d.ts.map +1 -0
  133. package/dist/cli/tui/components/RequestList.js +30 -0
  134. package/dist/cli/tui/components/RequestList.js.map +1 -0
  135. package/dist/cli/tui/components/RequestListItem.d.ts +36 -0
  136. package/dist/cli/tui/components/RequestListItem.d.ts.map +1 -0
  137. package/dist/cli/tui/components/RequestListItem.js +130 -0
  138. package/dist/cli/tui/components/RequestListItem.js.map +1 -0
  139. package/dist/cli/tui/components/SaveModal.d.ts +30 -0
  140. package/dist/cli/tui/components/SaveModal.d.ts.map +1 -0
  141. package/dist/cli/tui/components/SaveModal.js +95 -0
  142. package/dist/cli/tui/components/SaveModal.js.map +1 -0
  143. package/dist/cli/tui/components/StatusBar.d.ts +39 -0
  144. package/dist/cli/tui/components/StatusBar.d.ts.map +1 -0
  145. package/dist/cli/tui/components/StatusBar.js +53 -0
  146. package/dist/cli/tui/components/StatusBar.js.map +1 -0
  147. package/dist/cli/tui/components/TextViewerModal.d.ts +19 -0
  148. package/dist/cli/tui/components/TextViewerModal.d.ts.map +1 -0
  149. package/dist/cli/tui/components/TextViewerModal.js +227 -0
  150. package/dist/cli/tui/components/TextViewerModal.js.map +1 -0
  151. package/dist/cli/tui/hooks/useBodyExport.d.ts +26 -0
  152. package/dist/cli/tui/hooks/useBodyExport.d.ts.map +1 -0
  153. package/dist/cli/tui/hooks/useBodyExport.js +173 -0
  154. package/dist/cli/tui/hooks/useBodyExport.js.map +1 -0
  155. package/dist/cli/tui/hooks/useExport.d.ts +29 -0
  156. package/dist/cli/tui/hooks/useExport.d.ts.map +1 -0
  157. package/dist/cli/tui/hooks/useExport.js +64 -0
  158. package/dist/cli/tui/hooks/useExport.js.map +1 -0
  159. package/dist/cli/tui/hooks/useRequests.d.ts +26 -0
  160. package/dist/cli/tui/hooks/useRequests.d.ts.map +1 -0
  161. package/dist/cli/tui/hooks/useRequests.js +131 -0
  162. package/dist/cli/tui/hooks/useRequests.js.map +1 -0
  163. package/dist/cli/tui/hooks/useSaveBinary.d.ts +26 -0
  164. package/dist/cli/tui/hooks/useSaveBinary.d.ts.map +1 -0
  165. package/dist/cli/tui/hooks/useSaveBinary.js +165 -0
  166. package/dist/cli/tui/hooks/useSaveBinary.js.map +1 -0
  167. package/dist/cli/tui/hooks/useSpinner.d.ts +5 -0
  168. package/dist/cli/tui/hooks/useSpinner.d.ts.map +1 -0
  169. package/dist/cli/tui/hooks/useSpinner.js +25 -0
  170. package/dist/cli/tui/hooks/useSpinner.js.map +1 -0
  171. package/dist/cli/tui/hooks/useStdoutDimensions.d.ts +11 -0
  172. package/dist/cli/tui/hooks/useStdoutDimensions.d.ts.map +1 -0
  173. package/dist/cli/tui/hooks/useStdoutDimensions.js +29 -0
  174. package/dist/cli/tui/hooks/useStdoutDimensions.js.map +1 -0
  175. package/dist/cli/tui/utils/binary.d.ts +24 -0
  176. package/dist/cli/tui/utils/binary.d.ts.map +1 -0
  177. package/dist/cli/tui/utils/binary.js +152 -0
  178. package/dist/cli/tui/utils/binary.js.map +1 -0
  179. package/dist/cli/tui/utils/clipboard.d.ts +9 -0
  180. package/dist/cli/tui/utils/clipboard.d.ts.map +1 -0
  181. package/dist/cli/tui/utils/clipboard.js +58 -0
  182. package/dist/cli/tui/utils/clipboard.js.map +1 -0
  183. package/dist/cli/tui/utils/content-type.d.ts +8 -0
  184. package/dist/cli/tui/utils/content-type.d.ts.map +1 -0
  185. package/dist/cli/tui/utils/content-type.js +10 -0
  186. package/dist/cli/tui/utils/content-type.js.map +1 -0
  187. package/dist/cli/tui/utils/curl.d.ts +9 -0
  188. package/dist/cli/tui/utils/curl.d.ts.map +1 -0
  189. package/dist/cli/tui/utils/curl.js +54 -0
  190. package/dist/cli/tui/utils/curl.js.map +1 -0
  191. package/dist/cli/tui/utils/filters.d.ts +6 -0
  192. package/dist/cli/tui/utils/filters.d.ts.map +1 -0
  193. package/dist/cli/tui/utils/filters.js +13 -0
  194. package/dist/cli/tui/utils/filters.js.map +1 -0
  195. package/dist/cli/tui/utils/formatters.d.ts +49 -0
  196. package/dist/cli/tui/utils/formatters.d.ts.map +1 -0
  197. package/dist/cli/tui/utils/formatters.js +200 -0
  198. package/dist/cli/tui/utils/formatters.js.map +1 -0
  199. package/dist/cli/tui/utils/har.d.ts +75 -0
  200. package/dist/cli/tui/utils/har.d.ts.map +1 -0
  201. package/dist/cli/tui/utils/har.js +117 -0
  202. package/dist/cli/tui/utils/har.js.map +1 -0
  203. package/dist/cli/tui/utils/json-tree.d.ts +69 -0
  204. package/dist/cli/tui/utils/json-tree.d.ts.map +1 -0
  205. package/dist/cli/tui/utils/json-tree.js +339 -0
  206. package/dist/cli/tui/utils/json-tree.js.map +1 -0
  207. package/dist/cli/tui/utils/open-external.d.ts +17 -0
  208. package/dist/cli/tui/utils/open-external.d.ts.map +1 -0
  209. package/dist/cli/tui/utils/open-external.js +57 -0
  210. package/dist/cli/tui/utils/open-external.js.map +1 -0
  211. package/dist/cli/tui/utils/syntax-highlight.d.ts +16 -0
  212. package/dist/cli/tui/utils/syntax-highlight.d.ts.map +1 -0
  213. package/dist/cli/tui/utils/syntax-highlight.js +64 -0
  214. package/dist/cli/tui/utils/syntax-highlight.js.map +1 -0
  215. package/dist/daemon/control.d.ts +21 -0
  216. package/dist/daemon/control.d.ts.map +1 -0
  217. package/dist/daemon/control.js +311 -0
  218. package/dist/daemon/control.js.map +1 -0
  219. package/dist/daemon/htpx-client.d.ts +8 -0
  220. package/dist/daemon/htpx-client.d.ts.map +1 -0
  221. package/dist/daemon/htpx-client.js +25 -0
  222. package/dist/daemon/htpx-client.js.map +1 -0
  223. package/dist/daemon/index.d.ts +3 -0
  224. package/dist/daemon/index.d.ts.map +1 -0
  225. package/dist/daemon/index.js +178 -0
  226. package/dist/daemon/index.js.map +1 -0
  227. package/dist/daemon/interceptor-loader.d.ts +30 -0
  228. package/dist/daemon/interceptor-loader.d.ts.map +1 -0
  229. package/dist/daemon/interceptor-loader.js +249 -0
  230. package/dist/daemon/interceptor-loader.js.map +1 -0
  231. package/dist/daemon/interceptor-runner.d.ts +39 -0
  232. package/dist/daemon/interceptor-runner.d.ts.map +1 -0
  233. package/dist/daemon/interceptor-runner.js +312 -0
  234. package/dist/daemon/interceptor-runner.js.map +1 -0
  235. package/dist/daemon/procsi-client.d.ts +8 -0
  236. package/dist/daemon/procsi-client.d.ts.map +1 -0
  237. package/dist/daemon/procsi-client.js +25 -0
  238. package/dist/daemon/procsi-client.js.map +1 -0
  239. package/dist/daemon/proxy.d.ts +34 -0
  240. package/dist/daemon/proxy.d.ts.map +1 -0
  241. package/dist/daemon/proxy.js +213 -0
  242. package/dist/daemon/proxy.js.map +1 -0
  243. package/dist/daemon/storage.d.ts +130 -0
  244. package/dist/daemon/storage.d.ts.map +1 -0
  245. package/dist/daemon/storage.js +761 -0
  246. package/dist/daemon/storage.js.map +1 -0
  247. package/dist/interceptors.d.ts +2 -0
  248. package/dist/interceptors.d.ts.map +1 -0
  249. package/dist/interceptors.js +2 -0
  250. package/dist/interceptors.js.map +1 -0
  251. package/dist/mcp/server.d.ts +110 -0
  252. package/dist/mcp/server.d.ts.map +1 -0
  253. package/dist/mcp/server.js +806 -0
  254. package/dist/mcp/server.js.map +1 -0
  255. package/dist/overrides/node.d.ts +30 -0
  256. package/dist/overrides/node.d.ts.map +1 -0
  257. package/dist/overrides/node.js +66 -0
  258. package/dist/overrides/node.js.map +1 -0
  259. package/dist/shared/config.d.ts +21 -0
  260. package/dist/shared/config.d.ts.map +1 -0
  261. package/dist/shared/config.js +83 -0
  262. package/dist/shared/config.js.map +1 -0
  263. package/dist/shared/content-type.d.ts +64 -0
  264. package/dist/shared/content-type.d.ts.map +1 -0
  265. package/dist/shared/content-type.js +145 -0
  266. package/dist/shared/content-type.js.map +1 -0
  267. package/dist/shared/control-client.d.ts +144 -0
  268. package/dist/shared/control-client.d.ts.map +1 -0
  269. package/dist/shared/control-client.js +272 -0
  270. package/dist/shared/control-client.js.map +1 -0
  271. package/dist/shared/daemon.d.ts +33 -0
  272. package/dist/shared/daemon.d.ts.map +1 -0
  273. package/dist/shared/daemon.js +231 -0
  274. package/dist/shared/daemon.js.map +1 -0
  275. package/dist/shared/logger.d.ts +47 -0
  276. package/dist/shared/logger.d.ts.map +1 -0
  277. package/dist/shared/logger.js +200 -0
  278. package/dist/shared/logger.js.map +1 -0
  279. package/dist/shared/project.d.ts +76 -0
  280. package/dist/shared/project.d.ts.map +1 -0
  281. package/dist/shared/project.js +185 -0
  282. package/dist/shared/project.js.map +1 -0
  283. package/dist/shared/proxy-info.d.ts +10 -0
  284. package/dist/shared/proxy-info.d.ts.map +1 -0
  285. package/dist/shared/proxy-info.js +15 -0
  286. package/dist/shared/proxy-info.js.map +1 -0
  287. package/dist/shared/types.d.ts +128 -0
  288. package/dist/shared/types.d.ts.map +1 -0
  289. package/dist/shared/types.js +5 -0
  290. package/dist/shared/types.js.map +1 -0
  291. package/dist/shared/version.d.ts +5 -0
  292. package/dist/shared/version.d.ts.map +1 -0
  293. package/dist/shared/version.js +21 -0
  294. package/dist/shared/version.js.map +1 -0
  295. package/package.json +113 -0
  296. package/skills/procsi/SKILL.md +228 -0
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Hook for saving binary content to disk.
3
+ */
4
+ import { useCallback } from "react";
5
+ import * as fs from "node:fs";
6
+ import * as path from "node:path";
7
+ import * as os from "node:os";
8
+ import { copyToClipboard } from "../utils/clipboard.js";
9
+ import { findOrCreateProjectRoot, ensureHtpxDir } from "../../../shared/project.js";
10
+ /**
11
+ * Generate a filename for binary content based on request metadata.
12
+ */
13
+ export function generateFilename(requestId, contentType, url) {
14
+ // Try to extract extension from URL first
15
+ let extension = "";
16
+ try {
17
+ const urlPath = new URL(url).pathname;
18
+ const urlExtMatch = urlPath.match(/\.([a-zA-Z0-9]+)$/);
19
+ if (urlExtMatch?.[1]) {
20
+ extension = urlExtMatch[1].toLowerCase();
21
+ }
22
+ }
23
+ catch {
24
+ // Invalid URL, fall through to content-type detection
25
+ }
26
+ if (!extension && contentType) {
27
+ // Derive extension from content type
28
+ extension = getExtensionFromContentType(contentType);
29
+ }
30
+ // Generate timestamp for uniqueness
31
+ const timestamp = Date.now();
32
+ const shortId = requestId.slice(0, 8);
33
+ return extension ? `${shortId}-${timestamp}.${extension}` : `${shortId}-${timestamp}.bin`;
34
+ }
35
+ /**
36
+ * Map common content types to file extensions.
37
+ */
38
+ function getExtensionFromContentType(contentType) {
39
+ const type = contentType.split(";")[0]?.trim().toLowerCase() ?? "";
40
+ const mappings = {
41
+ // Images
42
+ "image/jpeg": "jpg",
43
+ "image/png": "png",
44
+ "image/gif": "gif",
45
+ "image/webp": "webp",
46
+ "image/svg+xml": "svg",
47
+ "image/x-icon": "ico",
48
+ "image/bmp": "bmp",
49
+ "image/tiff": "tiff",
50
+ // Audio
51
+ "audio/mpeg": "mp3",
52
+ "audio/wav": "wav",
53
+ "audio/ogg": "ogg",
54
+ "audio/webm": "weba",
55
+ "audio/aac": "aac",
56
+ "audio/flac": "flac",
57
+ // Video
58
+ "video/mp4": "mp4",
59
+ "video/webm": "webm",
60
+ "video/ogg": "ogv",
61
+ "video/quicktime": "mov",
62
+ "video/x-msvideo": "avi",
63
+ "video/x-matroska": "mkv",
64
+ // Documents
65
+ "application/pdf": "pdf",
66
+ "application/msword": "doc",
67
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
68
+ "application/vnd.ms-excel": "xls",
69
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
70
+ "application/vnd.ms-powerpoint": "ppt",
71
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
72
+ // Archives
73
+ "application/zip": "zip",
74
+ "application/gzip": "gz",
75
+ "application/x-tar": "tar",
76
+ "application/x-rar-compressed": "rar",
77
+ "application/x-7z-compressed": "7z",
78
+ // Other
79
+ "application/octet-stream": "bin",
80
+ "application/wasm": "wasm",
81
+ };
82
+ return mappings[type] ?? "bin";
83
+ }
84
+ /**
85
+ * Resolve the target directory based on save location.
86
+ */
87
+ function resolveTargetDir(location, customPath) {
88
+ switch (location) {
89
+ case "exports": {
90
+ const projectRoot = findOrCreateProjectRoot();
91
+ const htpxDir = ensureHtpxDir(projectRoot);
92
+ const exportsDir = path.join(htpxDir, "exports");
93
+ if (!fs.existsSync(exportsDir)) {
94
+ fs.mkdirSync(exportsDir, { recursive: true });
95
+ }
96
+ return exportsDir;
97
+ }
98
+ case "downloads": {
99
+ const downloadsDir = path.join(os.homedir(), "Downloads");
100
+ if (!fs.existsSync(downloadsDir)) {
101
+ fs.mkdirSync(downloadsDir, { recursive: true });
102
+ }
103
+ return downloadsDir;
104
+ }
105
+ case "custom": {
106
+ if (!customPath) {
107
+ throw new Error("Custom path required");
108
+ }
109
+ // Expand ~ to home directory
110
+ const expandedPath = customPath.startsWith("~")
111
+ ? path.join(os.homedir(), customPath.slice(1))
112
+ : customPath;
113
+ const resolvedPath = path.resolve(expandedPath);
114
+ // Ensure directory exists
115
+ if (!fs.existsSync(resolvedPath)) {
116
+ fs.mkdirSync(resolvedPath, { recursive: true });
117
+ }
118
+ return resolvedPath;
119
+ }
120
+ }
121
+ }
122
+ /**
123
+ * Save binary content to disk.
124
+ */
125
+ export async function saveBinaryContent(body, filename, location, customPath) {
126
+ try {
127
+ const targetDir = resolveTargetDir(location, customPath);
128
+ const filePath = path.join(targetDir, filename);
129
+ fs.writeFileSync(filePath, body);
130
+ // Copy path to clipboard
131
+ try {
132
+ await copyToClipboard(filePath);
133
+ return {
134
+ success: true,
135
+ message: `Saved to ${filePath} (path copied)`,
136
+ filePath,
137
+ };
138
+ }
139
+ catch {
140
+ // Clipboard failed but file was saved
141
+ return {
142
+ success: true,
143
+ message: `Saved to ${filePath}`,
144
+ filePath,
145
+ };
146
+ }
147
+ }
148
+ catch (err) {
149
+ return {
150
+ success: false,
151
+ message: err instanceof Error ? err.message : "Failed to save file",
152
+ };
153
+ }
154
+ }
155
+ /**
156
+ * Hook providing binary save functionality.
157
+ */
158
+ export function useSaveBinary() {
159
+ const saveBinary = useCallback(async (body, requestId, contentType, url, location, customPath) => {
160
+ const filename = generateFilename(requestId, contentType, url);
161
+ return saveBinaryContent(body, filename, location, customPath);
162
+ }, []);
163
+ return { saveBinary };
164
+ }
165
+ //# sourceMappingURL=useSaveBinary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSaveBinary.js","sourceRoot":"","sources":["../../../../src/cli/tui/hooks/useSaveBinary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Hook that cycles through braille spinner frames for loading indicators.
3
+ */
4
+ export declare function useSpinner(active?: boolean): string;
5
+ //# sourceMappingURL=useSpinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSpinner.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/hooks/useSpinner.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,wBAAgB,UAAU,CAAC,MAAM,UAAO,GAAG,MAAM,CAqBhD"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Hook that cycles through braille spinner frames for loading indicators.
3
+ */
4
+ import { useState, useEffect, useRef } from "react";
5
+ const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
6
+ const SPINNER_INTERVAL_MS = 80;
7
+ export function useSpinner(active = true) {
8
+ const [frameIndex, setFrameIndex] = useState(0);
9
+ const intervalRef = useRef(null);
10
+ useEffect(() => {
11
+ if (!active) {
12
+ return;
13
+ }
14
+ intervalRef.current = setInterval(() => {
15
+ setFrameIndex((prev) => (prev + 1) % SPINNER_FRAMES.length);
16
+ }, SPINNER_INTERVAL_MS);
17
+ return () => {
18
+ if (intervalRef.current) {
19
+ clearInterval(intervalRef.current);
20
+ }
21
+ };
22
+ }, [active]);
23
+ return SPINNER_FRAMES[frameIndex] ?? SPINNER_FRAMES[0];
24
+ }
25
+ //# sourceMappingURL=useSpinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSpinner.js","sourceRoot":"","sources":["../../../../src/cli/tui/hooks/useSpinner.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAEpD,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAU,CAAC;AACnF,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B,MAAM,UAAU,UAAU,CAAC,MAAM,GAAG,IAAI;IACtC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,MAAM,CAAwB,IAAI,CAAC,CAAC;IAExD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO;QACT,CAAC;QAED,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE;YACrC,aAAa,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9D,CAAC,EAAE,mBAAmB,CAAC,CAAC;QAExB,OAAO,GAAG,EAAE;YACV,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;gBACxB,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YACrC,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,OAAO,cAAc,CAAC,UAAU,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Hook for subscribing to stdout dimensions.
3
+ *
4
+ * Replaces ink-use-stdout-dimensions which has compatibility issues with
5
+ * Node.js 24 due to CJS/ESM interop problems.
6
+ */
7
+ /**
8
+ * Returns [columns, rows] of the terminal, updating when the terminal is resized.
9
+ */
10
+ export declare function useStdoutDimensions(): [number, number];
11
+ //# sourceMappingURL=useStdoutDimensions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStdoutDimensions.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/hooks/useStdoutDimensions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAqBtD"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Hook for subscribing to stdout dimensions.
3
+ *
4
+ * Replaces ink-use-stdout-dimensions which has compatibility issues with
5
+ * Node.js 24 due to CJS/ESM interop problems.
6
+ */
7
+ import { useState, useEffect } from "react";
8
+ import { useStdout } from "ink";
9
+ /**
10
+ * Returns [columns, rows] of the terminal, updating when the terminal is resized.
11
+ */
12
+ export function useStdoutDimensions() {
13
+ const { stdout } = useStdout();
14
+ const [dimensions, setDimensions] = useState([
15
+ stdout.columns || 80,
16
+ stdout.rows || 24,
17
+ ]);
18
+ useEffect(() => {
19
+ const handler = () => {
20
+ setDimensions([stdout.columns || 80, stdout.rows || 24]);
21
+ };
22
+ stdout.on("resize", handler);
23
+ return () => {
24
+ stdout.off("resize", handler);
25
+ };
26
+ }, [stdout]);
27
+ return dimensions;
28
+ }
29
+ //# sourceMappingURL=useStdoutDimensions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStdoutDimensions.js","sourceRoot":"","sources":["../../../../src/cli/tui/hooks/useStdoutDimensions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAEhC;;GAEG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;IAE/B,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAmB;QAC7D,MAAM,CAAC,OAAO,IAAI,EAAE;QACpB,MAAM,CAAC,IAAI,IAAI,EAAE;KAClB,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,aAAa,CAAC,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3D,CAAC,CAAC;QAEF,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAE7B,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAChC,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Binary content detection utilities.
3
+ *
4
+ * Determines whether a buffer contains binary or text content based on
5
+ * Content-Type headers and byte scanning.
6
+ */
7
+ export interface BinaryCheckResult {
8
+ isBinary: boolean;
9
+ reason: "content-type" | "content-scan" | "text-content-type";
10
+ }
11
+ /**
12
+ * Check if content is binary based on Content-Type and/or byte scanning.
13
+ *
14
+ * Detection logic:
15
+ * 1. Check Content-Type against text whitelist - if match, return not binary
16
+ * 2. Check Content-Type against binary patterns - if match, return binary
17
+ * 3. Fall back to scanning first 8KB for >10% non-printable characters
18
+ */
19
+ export declare function isBinaryContent(body: Buffer | undefined, contentType: string | undefined): BinaryCheckResult;
20
+ /**
21
+ * Get a human-readable description for a binary content type.
22
+ */
23
+ export declare function getBinaryTypeDescription(contentType: string | undefined): string;
24
+ //# sourceMappingURL=binary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/utils/binary.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA4CH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,cAAc,GAAG,cAAc,GAAG,mBAAmB,CAAC;CAC/D;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,iBAAiB,CAiDnB;AAoCD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CA2BhF"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Binary content detection utilities.
3
+ *
4
+ * Determines whether a buffer contains binary or text content based on
5
+ * Content-Type headers and byte scanning.
6
+ */
7
+ import { TEXT_CONTENT_TYPES, TEXT_SUFFIXES } from "../../../shared/content-type.js";
8
+ /**
9
+ * Content types that are definitively binary.
10
+ */
11
+ const BINARY_CONTENT_TYPES = [
12
+ "image/",
13
+ "audio/",
14
+ "video/",
15
+ "application/octet-stream",
16
+ "application/pdf",
17
+ "application/zip",
18
+ "application/gzip",
19
+ "application/x-tar",
20
+ "application/x-rar-compressed",
21
+ "application/x-7z-compressed",
22
+ "application/vnd.ms-excel",
23
+ "application/vnd.ms-powerpoint",
24
+ "application/vnd.ms-word",
25
+ "application/vnd.openxmlformats-officedocument",
26
+ "application/x-shockwave-flash",
27
+ "application/wasm",
28
+ "font/",
29
+ ];
30
+ /**
31
+ * Human-readable descriptions for binary content types.
32
+ */
33
+ const BINARY_DESCRIPTIONS = {
34
+ "image/": "Image",
35
+ "audio/": "Audio",
36
+ "video/": "Video",
37
+ "font/": "Font",
38
+ "application/pdf": "PDF",
39
+ "application/zip": "Archive",
40
+ "application/gzip": "Archive",
41
+ "application/x-tar": "Archive",
42
+ "application/x-rar-compressed": "Archive",
43
+ "application/x-7z-compressed": "Archive",
44
+ "application/wasm": "WebAssembly",
45
+ };
46
+ /**
47
+ * Check if content is binary based on Content-Type and/or byte scanning.
48
+ *
49
+ * Detection logic:
50
+ * 1. Check Content-Type against text whitelist - if match, return not binary
51
+ * 2. Check Content-Type against binary patterns - if match, return binary
52
+ * 3. Fall back to scanning first 8KB for >10% non-printable characters
53
+ */
54
+ export function isBinaryContent(body, contentType) {
55
+ // No body means not binary (nothing to display)
56
+ if (!body || body.length === 0) {
57
+ return { isBinary: false, reason: "text-content-type" };
58
+ }
59
+ // Normalise content type (remove charset and other parameters)
60
+ const normalisedType = contentType?.split(";")[0]?.trim().toLowerCase();
61
+ // Check text content types first
62
+ if (normalisedType) {
63
+ // Check prefixes
64
+ let isTextContentType = false;
65
+ for (const prefix of TEXT_CONTENT_TYPES) {
66
+ if (normalisedType.startsWith(prefix)) {
67
+ isTextContentType = true;
68
+ break;
69
+ }
70
+ }
71
+ // Check suffixes (e.g., application/hal+json)
72
+ if (!isTextContentType) {
73
+ for (const suffix of TEXT_SUFFIXES) {
74
+ if (normalisedType.endsWith(suffix)) {
75
+ isTextContentType = true;
76
+ break;
77
+ }
78
+ }
79
+ }
80
+ if (isTextContentType) {
81
+ // Content-type says text, but verify with byte scan as safety net.
82
+ // Handles compressed bodies still in the DB, mislabelled content types, etc.
83
+ const scanResult = scanForBinaryContent(body);
84
+ return scanResult.isBinary
85
+ ? { isBinary: true, reason: "content-scan" }
86
+ : { isBinary: false, reason: "text-content-type" };
87
+ }
88
+ // Check binary content types
89
+ for (const prefix of BINARY_CONTENT_TYPES) {
90
+ if (normalisedType.startsWith(prefix)) {
91
+ return { isBinary: true, reason: "content-type" };
92
+ }
93
+ }
94
+ }
95
+ // Fall back to byte scanning
96
+ return scanForBinaryContent(body);
97
+ }
98
+ /**
99
+ * Scan buffer for binary content by checking for non-printable characters.
100
+ * Scans first 8KB and considers binary if >10% are non-printable.
101
+ */
102
+ function scanForBinaryContent(body) {
103
+ const SCAN_SIZE = 8 * 1024; // 8KB
104
+ const BINARY_THRESHOLD = 0.1; // 10%
105
+ const bytesToScan = Math.min(body.length, SCAN_SIZE);
106
+ let nonPrintableCount = 0;
107
+ for (let i = 0; i < bytesToScan; i++) {
108
+ const byte = body[i];
109
+ if (byte === undefined)
110
+ continue;
111
+ // Allow common text characters:
112
+ // - Tab (9), LF (10), CR (13)
113
+ // - Printable ASCII (32-126)
114
+ // - Extended ASCII (128-255) for UTF-8
115
+ const isPrintable = byte === 9 || byte === 10 || byte === 13 || (byte >= 32 && byte <= 126) || byte >= 128;
116
+ if (!isPrintable) {
117
+ nonPrintableCount++;
118
+ }
119
+ }
120
+ const ratio = nonPrintableCount / bytesToScan;
121
+ return {
122
+ isBinary: ratio > BINARY_THRESHOLD,
123
+ reason: "content-scan",
124
+ };
125
+ }
126
+ /**
127
+ * Get a human-readable description for a binary content type.
128
+ */
129
+ export function getBinaryTypeDescription(contentType) {
130
+ if (!contentType) {
131
+ return "Binary";
132
+ }
133
+ const normalisedType = contentType.split(";")[0]?.trim().toLowerCase() ?? "";
134
+ // Check exact matches first
135
+ if (BINARY_DESCRIPTIONS[normalisedType]) {
136
+ return BINARY_DESCRIPTIONS[normalisedType];
137
+ }
138
+ // Check prefix matches
139
+ for (const [prefix, description] of Object.entries(BINARY_DESCRIPTIONS)) {
140
+ if (prefix.endsWith("/") && normalisedType.startsWith(prefix)) {
141
+ return description;
142
+ }
143
+ }
144
+ // Extract subtype for better description
145
+ if (normalisedType.startsWith("application/")) {
146
+ const subtype = normalisedType.replace("application/", "");
147
+ // Capitalise first letter
148
+ return subtype.charAt(0).toUpperCase() + subtype.slice(1);
149
+ }
150
+ return "Binary";
151
+ }
152
+ //# sourceMappingURL=binary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary.js","sourceRoot":"","sources":["../../../../src/cli/tui/utils/binary.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEpF;;GAEG;AACH,MAAM,oBAAoB,GAAG;IAC3B,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,0BAA0B;IAC1B,iBAAiB;IACjB,iBAAiB;IACjB,kBAAkB;IAClB,mBAAmB;IACnB,8BAA8B;IAC9B,6BAA6B;IAC7B,0BAA0B;IAC1B,+BAA+B;IAC/B,yBAAyB;IACzB,+CAA+C;IAC/C,+BAA+B;IAC/B,kBAAkB;IAClB,OAAO;CACR,CAAC;AAEF;;GAEG;AACH,MAAM,mBAAmB,GAA2B;IAClD,QAAQ,EAAE,OAAO;IACjB,QAAQ,EAAE,OAAO;IACjB,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,MAAM;IACf,iBAAiB,EAAE,KAAK;IACxB,iBAAiB,EAAE,SAAS;IAC5B,kBAAkB,EAAE,SAAS;IAC7B,mBAAmB,EAAE,SAAS;IAC9B,8BAA8B,EAAE,SAAS;IACzC,6BAA6B,EAAE,SAAS;IACxC,kBAAkB,EAAE,aAAa;CAClC,CAAC;AAOF;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAwB,EACxB,WAA+B;IAE/B,gDAAgD;IAChD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC1D,CAAC;IAED,+DAA+D;IAC/D,MAAM,cAAc,GAAG,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAExE,iCAAiC;IACjC,IAAI,cAAc,EAAE,CAAC;QACnB,iBAAiB;QACjB,IAAI,iBAAiB,GAAG,KAAK,CAAC;QAC9B,KAAK,MAAM,MAAM,IAAI,kBAAkB,EAAE,CAAC;YACxC,IAAI,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBACtC,iBAAiB,GAAG,IAAI,CAAC;gBACzB,MAAM;YACR,CAAC;QACH,CAAC;QAED,8CAA8C;QAC9C,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE,CAAC;gBACnC,IAAI,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;oBACpC,iBAAiB,GAAG,IAAI,CAAC;oBACzB,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,iBAAiB,EAAE,CAAC;YACtB,mEAAmE;YACnE,6EAA6E;YAC7E,MAAM,UAAU,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;YAC9C,OAAO,UAAU,CAAC,QAAQ;gBACxB,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE;gBAC5C,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;QACvD,CAAC;QAED,6BAA6B;QAC7B,KAAK,MAAM,MAAM,IAAI,oBAAoB,EAAE,CAAC;YAC1C,IAAI,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBACtC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;YACpD,CAAC;QACH,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC;AAED;;;GAGG;AACH,SAAS,oBAAoB,CAAC,IAAY;IACxC,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM;IAClC,MAAM,gBAAgB,GAAG,GAAG,CAAC,CAAC,MAAM;IAEpC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACrD,IAAI,iBAAiB,GAAG,CAAC,CAAC;IAE1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QAEjC,gCAAgC;QAChC,8BAA8B;QAC9B,6BAA6B;QAC7B,uCAAuC;QACvC,MAAM,WAAW,GACf,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,CAAC;QAEzF,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,iBAAiB,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,iBAAiB,GAAG,WAAW,CAAC;IAC9C,OAAO;QACL,QAAQ,EAAE,KAAK,GAAG,gBAAgB;QAClC,MAAM,EAAE,cAAc;KACvB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,WAA+B;IACtE,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,cAAc,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;IAE7E,4BAA4B;IAC5B,IAAI,mBAAmB,CAAC,cAAc,CAAC,EAAE,CAAC;QACxC,OAAO,mBAAmB,CAAC,cAAc,CAAC,CAAC;IAC7C,CAAC;IAED,uBAAuB;IACvB,KAAK,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACxE,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9D,OAAO,WAAW,CAAC;QACrB,CAAC;IACH,CAAC;IAED,yCAAyC;IACzC,IAAI,cAAc,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QAC3D,0BAA0B;QAC1B,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Cross-platform clipboard utilities using native commands.
3
+ */
4
+ /**
5
+ * Copy text to the system clipboard.
6
+ * Uses pbcopy on macOS, xclip on Linux, clip on Windows.
7
+ */
8
+ export declare function copyToClipboard(text: string): Promise<void>;
9
+ //# sourceMappingURL=clipboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/utils/clipboard.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;GAGG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDjE"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Cross-platform clipboard utilities using native commands.
3
+ */
4
+ import { spawn } from "node:child_process";
5
+ /**
6
+ * Copy text to the system clipboard.
7
+ * Uses pbcopy on macOS, xclip on Linux, clip on Windows.
8
+ */
9
+ export async function copyToClipboard(text) {
10
+ const platform = process.platform;
11
+ let command;
12
+ let args;
13
+ if (platform === "darwin") {
14
+ command = "pbcopy";
15
+ args = [];
16
+ }
17
+ else if (platform === "win32") {
18
+ command = "clip";
19
+ args = [];
20
+ }
21
+ else {
22
+ // Linux - try xclip first, fall back to xsel
23
+ command = "xclip";
24
+ args = ["-selection", "clipboard"];
25
+ }
26
+ return new Promise((resolve, reject) => {
27
+ const proc = spawn(command, args, { stdio: ["pipe", "ignore", "ignore"] });
28
+ proc.on("error", (err) => {
29
+ if (platform === "linux" && command === "xclip") {
30
+ // Try xsel as fallback
31
+ const xsel = spawn("xsel", ["--clipboard", "--input"], {
32
+ stdio: ["pipe", "ignore", "ignore"],
33
+ });
34
+ xsel.on("error", () => reject(new Error("No clipboard tool available (tried xclip and xsel)")));
35
+ xsel.on("close", (code) => {
36
+ if (code === 0)
37
+ resolve();
38
+ else
39
+ reject(new Error(`xsel exited with code ${code}`));
40
+ });
41
+ xsel.stdin.write(text);
42
+ xsel.stdin.end();
43
+ }
44
+ else {
45
+ reject(err);
46
+ }
47
+ });
48
+ proc.on("close", (code) => {
49
+ if (code === 0)
50
+ resolve();
51
+ else
52
+ reject(new Error(`${command} exited with code ${code}`));
53
+ });
54
+ proc.stdin.write(text);
55
+ proc.stdin.end();
56
+ });
57
+ }
58
+ //# sourceMappingURL=clipboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../../../src/cli/tui/utils/clipboard.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY;IAChD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAElC,IAAI,OAAe,CAAC;IACpB,IAAI,IAAc,CAAC;IAEnB,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,GAAG,QAAQ,CAAC;QACnB,IAAI,GAAG,EAAE,CAAC;IACZ,CAAC;SAAM,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QAChC,OAAO,GAAG,MAAM,CAAC;QACjB,IAAI,GAAG,EAAE,CAAC;IACZ,CAAC;SAAM,CAAC;QACN,6CAA6C;QAC7C,OAAO,GAAG,OAAO,CAAC;QAClB,IAAI,GAAG,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;QAE3E,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACvB,IAAI,QAAQ,KAAK,OAAO,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;gBAChD,uBAAuB;gBACvB,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,aAAa,EAAE,SAAS,CAAC,EAAE;oBACrD,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC;iBACpC,CAAC,CAAC;gBACH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CACpB,MAAM,CAAC,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC,CACxE,CAAC;gBACF,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;oBACxB,IAAI,IAAI,KAAK,CAAC;wBAAE,OAAO,EAAE,CAAC;;wBACrB,MAAM,CAAC,IAAI,KAAK,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC,CAAC;gBAC1D,CAAC,CAAC,CAAC;gBACH,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACvB,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YACnB,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACxB,IAAI,IAAI,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;;gBACrB,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,OAAO,qBAAqB,IAAI,EAAE,CAAC,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvB,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Content-type detection utilities.
3
+ */
4
+ /**
5
+ * Check whether a content-type string indicates JSON content.
6
+ */
7
+ export declare function isJsonContent(contentType: string | undefined): boolean;
8
+ //# sourceMappingURL=content-type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-type.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/utils/content-type.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEtE"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Content-type detection utilities.
3
+ */
4
+ /**
5
+ * Check whether a content-type string indicates JSON content.
6
+ */
7
+ export function isJsonContent(contentType) {
8
+ return !!(contentType?.includes("application/json") || contentType?.includes("+json"));
9
+ }
10
+ //# sourceMappingURL=content-type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-type.js","sourceRoot":"","sources":["../../../../src/cli/tui/utils/content-type.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,WAA+B;IAC3D,OAAO,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,kBAAkB,CAAC,IAAI,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AACzF,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Generate curl commands from captured requests.
3
+ */
4
+ import type { CapturedRequest } from "../../../shared/types.js";
5
+ /**
6
+ * Generate a curl command from a captured request.
7
+ */
8
+ export declare function generateCurl(request: CapturedRequest): string;
9
+ //# sourceMappingURL=curl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"curl.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/utils/curl.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AA6BhE;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CA0B7D"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Generate curl commands from captured requests.
3
+ */
4
+ /**
5
+ * Headers that should be excluded from curl output.
6
+ * These are typically set automatically by curl or are connection-specific.
7
+ */
8
+ const EXCLUDED_HEADERS = new Set([
9
+ "host",
10
+ "content-length",
11
+ "connection",
12
+ "accept-encoding",
13
+ "transfer-encoding",
14
+ ]);
15
+ /**
16
+ * Escape a string for use in a shell single-quoted context.
17
+ *
18
+ * Within single quotes, the shell does not interpret any special characters
19
+ * (`$`, `` ` ``, `\`, `!`, newlines, etc.) — the only character that cannot
20
+ * appear inside single quotes is the single quote itself. We handle that by
21
+ * ending the quote, inserting an escaped single quote, and reopening.
22
+ *
23
+ * Null bytes are stripped because some shells (e.g. bash) silently truncate
24
+ * strings at `\0`, which could cause the remainder of a value to be lost.
25
+ */
26
+ function shellEscape(str) {
27
+ return str.replace(/\0/g, "").replace(/'/g, "'\"'\"'");
28
+ }
29
+ /**
30
+ * Generate a curl command from a captured request.
31
+ */
32
+ export function generateCurl(request) {
33
+ const parts = ["curl"];
34
+ // Add method if not GET
35
+ if (request.method !== "GET") {
36
+ parts.push(`-X ${request.method}`);
37
+ }
38
+ // Add URL
39
+ parts.push(`'${shellEscape(request.url)}'`);
40
+ // Add headers (excluding certain automatic ones)
41
+ for (const [name, value] of Object.entries(request.requestHeaders)) {
42
+ if (EXCLUDED_HEADERS.has(name.toLowerCase())) {
43
+ continue;
44
+ }
45
+ parts.push(`-H '${shellEscape(name)}: ${shellEscape(value)}'`);
46
+ }
47
+ // Add body if present
48
+ if (request.requestBody && request.requestBody.length > 0) {
49
+ const bodyStr = request.requestBody.toString("utf-8");
50
+ parts.push(`-d '${shellEscape(bodyStr)}'`);
51
+ }
52
+ return parts.join(" \\\n ");
53
+ }
54
+ //# sourceMappingURL=curl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"curl.js","sourceRoot":"","sources":["../../../../src/cli/tui/utils/curl.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;GAGG;AACH,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IAC/B,MAAM;IACN,gBAAgB;IAChB,YAAY;IACZ,iBAAiB;IACjB,mBAAmB;CACpB,CAAC,CAAC;AAEH;;;;;;;;;;GAUG;AACH,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AACzD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,OAAwB;IACnD,MAAM,KAAK,GAAa,CAAC,MAAM,CAAC,CAAC;IAEjC,wBAAwB;IACxB,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,UAAU;IACV,KAAK,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAE5C,iDAAiD;IACjD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;QACnE,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YAC7C,SAAS;QACX,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,OAAO,WAAW,CAAC,IAAI,CAAC,KAAK,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjE,CAAC;IAED,sBAAsB;IACtB,IAAI,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACtD,KAAK,CAAC,IAAI,CAAC,OAAO,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { RequestFilter } from "../../../shared/types.js";
2
+ /**
3
+ * Check whether a filter has any active conditions.
4
+ */
5
+ export declare function isFilterActive(filter: RequestFilter): boolean;
6
+ //# sourceMappingURL=filters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/utils/filters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAU7D"}