procsi 0.2.7 → 0.4.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 (142) hide show
  1. package/README.md +341 -214
  2. package/dist/cli/commands/completions.d.ts +9 -0
  3. package/dist/cli/commands/completions.d.ts.map +1 -0
  4. package/dist/cli/commands/completions.js +170 -0
  5. package/dist/cli/commands/completions.js.map +1 -0
  6. package/dist/cli/commands/helpers.d.ts +9 -0
  7. package/dist/cli/commands/helpers.d.ts.map +1 -1
  8. package/dist/cli/commands/helpers.js +19 -1
  9. package/dist/cli/commands/helpers.js.map +1 -1
  10. package/dist/cli/commands/interceptors.d.ts.map +1 -1
  11. package/dist/cli/commands/interceptors.js +142 -0
  12. package/dist/cli/commands/interceptors.js.map +1 -1
  13. package/dist/cli/commands/off.d.ts.map +1 -1
  14. package/dist/cli/commands/off.js +1 -0
  15. package/dist/cli/commands/off.js.map +1 -1
  16. package/dist/cli/commands/on.d.ts.map +1 -1
  17. package/dist/cli/commands/on.js +3 -1
  18. package/dist/cli/commands/on.js.map +1 -1
  19. package/dist/cli/commands/request.d.ts +6 -0
  20. package/dist/cli/commands/request.d.ts.map +1 -0
  21. package/dist/cli/commands/request.js +216 -0
  22. package/dist/cli/commands/request.js.map +1 -0
  23. package/dist/cli/commands/requests.d.ts +6 -0
  24. package/dist/cli/commands/requests.d.ts.map +1 -0
  25. package/dist/cli/commands/requests.js +290 -0
  26. package/dist/cli/commands/requests.js.map +1 -0
  27. package/dist/cli/commands/sessions.d.ts +6 -0
  28. package/dist/cli/commands/sessions.d.ts.map +1 -0
  29. package/dist/cli/commands/sessions.js +39 -0
  30. package/dist/cli/commands/sessions.js.map +1 -0
  31. package/dist/cli/formatters/colour.d.ts +17 -0
  32. package/dist/cli/formatters/colour.d.ts.map +1 -0
  33. package/dist/cli/formatters/colour.js +23 -0
  34. package/dist/cli/formatters/colour.js.map +1 -0
  35. package/dist/cli/formatters/detail.d.ts +17 -0
  36. package/dist/cli/formatters/detail.d.ts.map +1 -0
  37. package/dist/cli/formatters/detail.js +135 -0
  38. package/dist/cli/formatters/detail.js.map +1 -0
  39. package/dist/cli/formatters/hints.d.ts +17 -0
  40. package/dist/cli/formatters/hints.d.ts.map +1 -0
  41. package/dist/cli/formatters/hints.js +29 -0
  42. package/dist/cli/formatters/hints.js.map +1 -0
  43. package/dist/cli/formatters/table.d.ts +17 -0
  44. package/dist/cli/formatters/table.d.ts.map +1 -0
  45. package/dist/cli/formatters/table.js +85 -0
  46. package/dist/cli/formatters/table.js.map +1 -0
  47. package/dist/cli/index.js +8 -0
  48. package/dist/cli/index.js.map +1 -1
  49. package/dist/cli/tui/App.d.ts.map +1 -1
  50. package/dist/cli/tui/App.js +67 -6
  51. package/dist/cli/tui/App.js.map +1 -1
  52. package/dist/cli/tui/components/AccordionPanel.d.ts.map +1 -1
  53. package/dist/cli/tui/components/AccordionPanel.js +1 -1
  54. package/dist/cli/tui/components/AccordionPanel.js.map +1 -1
  55. package/dist/cli/tui/components/EventFilterBar.d.ts +27 -0
  56. package/dist/cli/tui/components/EventFilterBar.d.ts.map +1 -0
  57. package/dist/cli/tui/components/EventFilterBar.js +145 -0
  58. package/dist/cli/tui/components/EventFilterBar.js.map +1 -0
  59. package/dist/cli/tui/components/FilterBar.d.ts.map +1 -1
  60. package/dist/cli/tui/components/FilterBar.js +34 -3
  61. package/dist/cli/tui/components/FilterBar.js.map +1 -1
  62. package/dist/cli/tui/components/HelpModal.d.ts.map +1 -1
  63. package/dist/cli/tui/components/HelpModal.js +3 -0
  64. package/dist/cli/tui/components/HelpModal.js.map +1 -1
  65. package/dist/cli/tui/components/InfoBar.d.ts +15 -0
  66. package/dist/cli/tui/components/InfoBar.d.ts.map +1 -0
  67. package/dist/cli/tui/components/InfoBar.js +45 -0
  68. package/dist/cli/tui/components/InfoBar.js.map +1 -0
  69. package/dist/cli/tui/components/InterceptorLogModal.d.ts +16 -0
  70. package/dist/cli/tui/components/InterceptorLogModal.d.ts.map +1 -0
  71. package/dist/cli/tui/components/InterceptorLogModal.js +229 -0
  72. package/dist/cli/tui/components/InterceptorLogModal.js.map +1 -0
  73. package/dist/cli/tui/components/RequestListItem.d.ts.map +1 -1
  74. package/dist/cli/tui/components/RequestListItem.js +3 -2
  75. package/dist/cli/tui/components/RequestListItem.js.map +1 -1
  76. package/dist/cli/tui/components/StatusBar.d.ts +7 -2
  77. package/dist/cli/tui/components/StatusBar.d.ts.map +1 -1
  78. package/dist/cli/tui/components/StatusBar.js +13 -6
  79. package/dist/cli/tui/components/StatusBar.js.map +1 -1
  80. package/dist/cli/tui/hooks/useInterceptorEvents.d.ts +33 -0
  81. package/dist/cli/tui/hooks/useInterceptorEvents.d.ts.map +1 -0
  82. package/dist/cli/tui/hooks/useInterceptorEvents.js +88 -0
  83. package/dist/cli/tui/hooks/useInterceptorEvents.js.map +1 -0
  84. package/dist/cli/tui/hooks/useRequests.d.ts +4 -0
  85. package/dist/cli/tui/hooks/useRequests.d.ts.map +1 -1
  86. package/dist/cli/tui/hooks/useRequests.js +36 -0
  87. package/dist/cli/tui/hooks/useRequests.js.map +1 -1
  88. package/dist/cli/tui/utils/filters.d.ts.map +1 -1
  89. package/dist/cli/tui/utils/filters.js +3 -1
  90. package/dist/cli/tui/utils/filters.js.map +1 -1
  91. package/dist/cli/utils/parse-time.d.ts +22 -0
  92. package/dist/cli/utils/parse-time.d.ts.map +1 -0
  93. package/dist/cli/utils/parse-time.js +160 -0
  94. package/dist/cli/utils/parse-time.js.map +1 -0
  95. package/dist/daemon/control.d.ts +2 -0
  96. package/dist/daemon/control.d.ts.map +1 -1
  97. package/dist/daemon/control.js +64 -2
  98. package/dist/daemon/control.js.map +1 -1
  99. package/dist/daemon/index.js +6 -1
  100. package/dist/daemon/index.js.map +1 -1
  101. package/dist/daemon/interceptor-event-log.d.ts +37 -0
  102. package/dist/daemon/interceptor-event-log.d.ts.map +1 -0
  103. package/dist/daemon/interceptor-event-log.js +163 -0
  104. package/dist/daemon/interceptor-event-log.js.map +1 -0
  105. package/dist/daemon/interceptor-loader.d.ts +3 -0
  106. package/dist/daemon/interceptor-loader.d.ts.map +1 -1
  107. package/dist/daemon/interceptor-loader.js +34 -2
  108. package/dist/daemon/interceptor-loader.js.map +1 -1
  109. package/dist/daemon/interceptor-runner.d.ts +3 -0
  110. package/dist/daemon/interceptor-runner.d.ts.map +1 -1
  111. package/dist/daemon/interceptor-runner.js +112 -8
  112. package/dist/daemon/interceptor-runner.js.map +1 -1
  113. package/dist/daemon/proxy.d.ts.map +1 -1
  114. package/dist/daemon/proxy.js +99 -4
  115. package/dist/daemon/proxy.js.map +1 -1
  116. package/dist/daemon/storage.d.ts +18 -4
  117. package/dist/daemon/storage.d.ts.map +1 -1
  118. package/dist/daemon/storage.js +111 -25
  119. package/dist/daemon/storage.js.map +1 -1
  120. package/dist/mcp/server.d.ts +3 -0
  121. package/dist/mcp/server.d.ts.map +1 -1
  122. package/dist/mcp/server.js +116 -3
  123. package/dist/mcp/server.js.map +1 -1
  124. package/dist/overrides/node.d.ts.map +1 -1
  125. package/dist/overrides/node.js +62 -0
  126. package/dist/overrides/node.js.map +1 -1
  127. package/dist/shared/constants.d.ts +10 -0
  128. package/dist/shared/constants.d.ts.map +1 -0
  129. package/dist/shared/constants.js +10 -0
  130. package/dist/shared/constants.js.map +1 -0
  131. package/dist/shared/control-client.d.ts +36 -3
  132. package/dist/shared/control-client.d.ts.map +1 -1
  133. package/dist/shared/control-client.js +27 -3
  134. package/dist/shared/control-client.js.map +1 -1
  135. package/dist/shared/process-name.d.ts +10 -0
  136. package/dist/shared/process-name.d.ts.map +1 -0
  137. package/dist/shared/process-name.js +27 -0
  138. package/dist/shared/process-name.js.map +1 -0
  139. package/dist/shared/types.d.ts +24 -0
  140. package/dist/shared/types.d.ts.map +1 -1
  141. package/package.json +2 -1
  142. package/skills/procsi/SKILL.md +5 -4
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Detailed request/session/event formatters for CLI output.
3
+ */
4
+ import type { CapturedRequest, InterceptorEvent, Session } from "../../shared/types.js";
5
+ /**
6
+ * Format the full detail view for a single request.
7
+ */
8
+ export declare function formatRequestDetail(request: CapturedRequest): string;
9
+ /**
10
+ * Format a session list as a table.
11
+ */
12
+ export declare function formatSessionTable(sessions: Session[]): string;
13
+ /**
14
+ * Format interceptor events as a table.
15
+ */
16
+ export declare function formatInterceptorEventTable(events: InterceptorEvent[]): string;
17
+ //# sourceMappingURL=detail.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detail.d.ts","sourceRoot":"","sources":["../../../src/cli/formatters/detail.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAgBxF;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAoFpE;AAaD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAoB9D;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAiB9E"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Detailed request/session/event formatters for CLI output.
3
+ */
4
+ import { formatDuration, formatSize, getStatusText, shortContentType, } from "../tui/utils/formatters.js";
5
+ import { GREEN, YELLOW, RED, CYAN, BOLD, DIM, RESET, useColour } from "./colour.js";
6
+ function colourForStatus(status) {
7
+ if (status >= 200 && status < 300)
8
+ return GREEN;
9
+ if (status >= 300 && status < 400)
10
+ return YELLOW;
11
+ if (status >= 400)
12
+ return RED;
13
+ return "";
14
+ }
15
+ /**
16
+ * Format the full detail view for a single request.
17
+ */
18
+ export function formatRequestDetail(request) {
19
+ const colour = useColour();
20
+ const lines = [];
21
+ // Title line: GET https://example.com/path → 200 OK (45ms)
22
+ const status = request.responseStatus;
23
+ const statusText = status !== undefined ? `${status} ${getStatusText(status)}` : "pending";
24
+ const arrow = colour ? `${DIM}→${RESET}` : "→";
25
+ const durationStr = request.durationMs !== undefined ? ` (${formatDuration(request.durationMs)})` : "";
26
+ let titleLine = ` ${request.method} ${request.url} ${arrow} `;
27
+ if (colour && status !== undefined) {
28
+ titleLine += `${colourForStatus(status)}${statusText}${RESET}${durationStr}`;
29
+ }
30
+ else {
31
+ titleLine += `${statusText}${durationStr}`;
32
+ }
33
+ lines.push(titleLine);
34
+ // Interception info
35
+ if (request.interceptedBy) {
36
+ const label = request.interceptionType === "mocked" ? "Mocked by" : "Modified by";
37
+ const indicator = colour
38
+ ? `${CYAN}${label}: ${request.interceptedBy}${RESET}`
39
+ : `${label}: ${request.interceptedBy}`;
40
+ lines.push(` ${indicator}`);
41
+ }
42
+ if (request.source) {
43
+ const sourceLabel = colour
44
+ ? `${DIM}Source: ${request.source}${RESET}`
45
+ : `Source: ${request.source}`;
46
+ lines.push(` ${sourceLabel}`);
47
+ }
48
+ lines.push("");
49
+ // Request Headers
50
+ const reqHeaderLabel = colour ? `${BOLD} Request Headers${RESET}` : " Request Headers";
51
+ lines.push(reqHeaderLabel);
52
+ for (const [name, value] of Object.entries(request.requestHeaders)) {
53
+ // Mask authorisation headers
54
+ const displayValue = name.toLowerCase() === "authorization" ? maskAuthValue(value) : value;
55
+ lines.push(` ${name}: ${displayValue}`);
56
+ }
57
+ lines.push("");
58
+ // Response Headers
59
+ if (request.responseHeaders) {
60
+ const resHeaderLabel = colour ? `${BOLD} Response Headers${RESET}` : " Response Headers";
61
+ lines.push(resHeaderLabel);
62
+ for (const [name, value] of Object.entries(request.responseHeaders)) {
63
+ lines.push(` ${name}: ${value}`);
64
+ }
65
+ lines.push("");
66
+ }
67
+ // Response Body preview
68
+ if (request.responseBody && request.responseBody.length > 0) {
69
+ const contentType = request.responseHeaders?.["content-type"] ?? request.responseHeaders?.["Content-Type"];
70
+ const shortCt = shortContentType(contentType);
71
+ const sizeStr = formatSize(request.responseBody.length);
72
+ const ctInfo = shortCt ? `, ${shortCt}` : "";
73
+ const bodyLabel = colour
74
+ ? `${BOLD} Response Body${RESET} (${sizeStr}${ctInfo})`
75
+ : ` Response Body (${sizeStr}${ctInfo})`;
76
+ lines.push(bodyLabel);
77
+ const MAX_PREVIEW_LENGTH = 2000;
78
+ const bodyStr = request.responseBody.toString("utf-8");
79
+ const preview = bodyStr.length > MAX_PREVIEW_LENGTH ? bodyStr.slice(0, MAX_PREVIEW_LENGTH) + "..." : bodyStr;
80
+ // Indent each line of the body preview
81
+ for (const line of preview.split("\n")) {
82
+ lines.push(` ${line}`);
83
+ }
84
+ if (request.responseBodyTruncated) {
85
+ lines.push(` ${colour ? DIM : ""}(body truncated at capture time)${colour ? RESET : ""}`);
86
+ }
87
+ }
88
+ return lines.join("\n");
89
+ }
90
+ /**
91
+ * Mask an authorisation header value, showing only the scheme.
92
+ */
93
+ function maskAuthValue(value) {
94
+ const spaceIdx = value.indexOf(" ");
95
+ if (spaceIdx > 0) {
96
+ return value.slice(0, spaceIdx) + " ***";
97
+ }
98
+ return "***";
99
+ }
100
+ /**
101
+ * Format a session list as a table.
102
+ */
103
+ export function formatSessionTable(sessions) {
104
+ const colour = useColour();
105
+ const lines = [];
106
+ const header = ` ${"ID".padEnd(38)} ${"Label".padEnd(20)} ${"Source".padEnd(12)} ${"PID".padEnd(8)} Started`;
107
+ lines.push(colour ? `${DIM}${header}${RESET}` : header);
108
+ for (const session of sessions) {
109
+ const label = session.label ?? "-";
110
+ const source = session.source ?? "-";
111
+ const startedAt = new Date(session.startedAt).toLocaleString();
112
+ lines.push(` ${session.id.padEnd(38)} ${label.padEnd(20)} ${source.padEnd(12)} ${String(session.pid).padEnd(8)} ${startedAt}`);
113
+ }
114
+ lines.push("");
115
+ lines.push(` ${sessions.length} session${sessions.length === 1 ? "" : "s"}`);
116
+ return lines.join("\n");
117
+ }
118
+ /**
119
+ * Format interceptor events as a table.
120
+ */
121
+ export function formatInterceptorEventTable(events) {
122
+ const colour = useColour();
123
+ const lines = [];
124
+ for (const event of events) {
125
+ const time = new Date(event.timestamp).toLocaleTimeString();
126
+ const levelColour = colour && event.level === "error" ? RED : colour && event.level === "warn" ? YELLOW : "";
127
+ const resetStr = levelColour ? RESET : "";
128
+ const level = `${levelColour}${event.level.toUpperCase().padEnd(5)}${resetStr}`;
129
+ const interceptor = event.interceptor.padEnd(24);
130
+ const message = event.message;
131
+ lines.push(` ${time} ${level} ${interceptor} ${message}`);
132
+ }
133
+ return lines.join("\n");
134
+ }
135
+ //# sourceMappingURL=detail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detail.js","sourceRoot":"","sources":["../../../src/cli/formatters/detail.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Contextual hint rendering for CLI output.
3
+ * Hints are dim lines shown at the bottom of output to guide users
4
+ * to related commands — the "gradual discovery" pattern.
5
+ *
6
+ * Only shown when stdout is a TTY and --json is not active.
7
+ */
8
+ /**
9
+ * Whether hints should be displayed.
10
+ * Suppressed when stdout is piped or NO_COLOR is set.
11
+ */
12
+ export declare function shouldShowHints(): boolean;
13
+ /**
14
+ * Render a hint line. Joins segments with " │ " separator and dims the output.
15
+ */
16
+ export declare function formatHint(segments: string[]): string;
17
+ //# sourceMappingURL=hints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hints.d.ts","sourceRoot":"","sources":["../../../src/cli/formatters/hints.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;GAGG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAIzC;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAIrD"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Contextual hint rendering for CLI output.
3
+ * Hints are dim lines shown at the bottom of output to guide users
4
+ * to related commands — the "gradual discovery" pattern.
5
+ *
6
+ * Only shown when stdout is a TTY and --json is not active.
7
+ */
8
+ import { DIM, RESET } from "./colour.js";
9
+ /**
10
+ * Whether hints should be displayed.
11
+ * Suppressed when stdout is piped or NO_COLOR is set.
12
+ */
13
+ export function shouldShowHints() {
14
+ if (!process.stdout.isTTY)
15
+ return false;
16
+ if (process.env["NO_COLOR"] !== undefined)
17
+ return false;
18
+ return true;
19
+ }
20
+ /**
21
+ * Render a hint line. Joins segments with " │ " separator and dims the output.
22
+ */
23
+ export function formatHint(segments) {
24
+ if (!shouldShowHints())
25
+ return "";
26
+ const joined = segments.join(" │ ");
27
+ return `${DIM} Hint: ${joined}${RESET}`;
28
+ }
29
+ //# sourceMappingURL=hints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hints.js","sourceRoot":"","sources":["../../../src/cli/formatters/hints.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACxD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,QAAkB;IAC3C,IAAI,CAAC,eAAe,EAAE;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpC,OAAO,GAAG,GAAG,WAAW,MAAM,GAAG,KAAK,EAAE,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Tabular request list formatter for CLI output.
3
+ * Renders summaries as a compact table with short IDs, colour-coded
4
+ * statuses, and interception indicators.
5
+ */
6
+ import type { CapturedRequestSummary } from "../../shared/types.js";
7
+ /** Length of abbreviated IDs shown in list views. */
8
+ export declare const SHORT_ID_LENGTH = 7;
9
+ export interface TableOptions {
10
+ /** Maximum URL column width. Defaults to 50. */
11
+ urlWidth?: number;
12
+ }
13
+ /**
14
+ * Format a list of request summaries as a table string.
15
+ */
16
+ export declare function formatRequestTable(summaries: CapturedRequestSummary[], total: number, options?: TableOptions): string;
17
+ //# sourceMappingURL=table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../src/cli/formatters/table.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAoB,MAAM,uBAAuB,CAAC;AAUtF,qDAAqD;AACrD,eAAO,MAAM,eAAe,IAAI,CAAC;AAuCjC,MAAM,WAAW,YAAY;IAC3B,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,sBAAsB,EAAE,EACnC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,YAAY,GACrB,MAAM,CAuCR"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Tabular request list formatter for CLI output.
3
+ * Renders summaries as a compact table with short IDs, colour-coded
4
+ * statuses, and interception indicators.
5
+ */
6
+ import { formatDuration, formatSize, truncate, padRight, padLeft, } from "../tui/utils/formatters.js";
7
+ import { GREEN, YELLOW, RED, CYAN, DIM, RESET, useColour } from "./colour.js";
8
+ /** Length of abbreviated IDs shown in list views. */
9
+ export const SHORT_ID_LENGTH = 7;
10
+ /**
11
+ * Colour a status code: green for 2xx, yellow for 3xx, red for 4xx/5xx.
12
+ */
13
+ function colourStatus(status) {
14
+ if (status === undefined)
15
+ return padLeft("...", 5);
16
+ const str = String(status);
17
+ if (!useColour())
18
+ return padLeft(str, 5);
19
+ if (status >= 200 && status < 300)
20
+ return padLeft(`${GREEN}${str}${RESET}`, 5 + GREEN.length + RESET.length);
21
+ if (status >= 300 && status < 400)
22
+ return padLeft(`${YELLOW}${str}${RESET}`, 5 + YELLOW.length + RESET.length);
23
+ if (status >= 400)
24
+ return padLeft(`${RED}${str}${RESET}`, 5 + RED.length + RESET.length);
25
+ return padLeft(str, 5);
26
+ }
27
+ /**
28
+ * Render an interception indicator: [M] for mocked, [I] for modified.
29
+ */
30
+ function interceptionIndicator(type) {
31
+ if (!type)
32
+ return " ";
33
+ const colour = useColour();
34
+ if (type === "mocked")
35
+ return colour ? `${CYAN}[M]${RESET}` : "[M]";
36
+ if (type === "modified")
37
+ return colour ? `${YELLOW}[I]${RESET}` : "[I]";
38
+ return " ";
39
+ }
40
+ /**
41
+ * Render a saved/bookmark indicator: [S] for saved requests.
42
+ */
43
+ function savedIndicator(saved) {
44
+ if (!saved)
45
+ return " ";
46
+ const colour = useColour();
47
+ return colour ? `${YELLOW}[S]${RESET}` : "[S]";
48
+ }
49
+ /**
50
+ * Format a list of request summaries as a table string.
51
+ */
52
+ export function formatRequestTable(summaries, total, options) {
53
+ const urlWidth = options?.urlWidth ?? 50;
54
+ const colour = useColour();
55
+ const lines = [];
56
+ // Header
57
+ const header = ` ${padRight("ID", SHORT_ID_LENGTH)} ${padRight("Method", 7)} ` +
58
+ `${padLeft("Status", 6)} ${padRight("URL", urlWidth)} ` +
59
+ `${padLeft("Duration", 10)} ${padLeft("Size", 8)}`;
60
+ lines.push(colour ? `${DIM}${header}${RESET}` : header);
61
+ // Rows
62
+ for (const req of summaries) {
63
+ const shortId = req.id.slice(0, SHORT_ID_LENGTH);
64
+ const method = padRight(req.method.toUpperCase(), 7);
65
+ const status = colourStatus(req.responseStatus);
66
+ const url = truncate(req.path, urlWidth);
67
+ const paddedUrl = padRight(url, urlWidth);
68
+ const duration = padLeft(formatDuration(req.durationMs), 10);
69
+ const size = padLeft(formatSize(req.responseBodySize || undefined), 8);
70
+ const indicator = interceptionIndicator(req.interceptionType);
71
+ const saved = savedIndicator(req.saved);
72
+ lines.push(` ${shortId} ${method} ${status} ${paddedUrl} ${duration} ${size} ${indicator}${saved}`);
73
+ }
74
+ // Summary line
75
+ lines.push("");
76
+ const showing = summaries.length;
77
+ if (showing < total) {
78
+ lines.push(` Showing ${showing} of ${total} requests`);
79
+ }
80
+ else {
81
+ lines.push(` Showing ${showing} request${showing === 1 ? "" : "s"}`);
82
+ }
83
+ return lines.join("\n");
84
+ }
85
+ //# sourceMappingURL=table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.js","sourceRoot":"","sources":["../../../src/cli/formatters/table.ts"],"names":[],"mappings":"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"}
package/dist/cli/index.js CHANGED
@@ -10,6 +10,10 @@ import { projectCommand } from "./commands/project.js";
10
10
  import { daemonCommand } from "./commands/daemon.js";
11
11
  import { tuiCommand } from "./commands/tui.js";
12
12
  import { statusCommand } from "./commands/status.js";
13
+ import { requestsCommand } from "./commands/requests.js";
14
+ import { requestCommand } from "./commands/request.js";
15
+ import { sessionsCommand } from "./commands/sessions.js";
16
+ import { completionsCommand } from "./commands/completions.js";
13
17
  import { getProcsiVersion } from "../shared/version.js";
14
18
  program
15
19
  .name("procsi")
@@ -27,6 +31,10 @@ program.addCommand(projectCommand);
27
31
  program.addCommand(daemonCommand);
28
32
  program.addCommand(tuiCommand);
29
33
  program.addCommand(statusCommand);
34
+ program.addCommand(requestsCommand);
35
+ program.addCommand(requestCommand);
36
+ program.addCommand(sessionsCommand);
37
+ program.addCommand(completionsCommand);
30
38
  program.addHelpText("after", `
31
39
  Quick start:
32
40
  procsi on Start intercepting HTTP traffic
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,oCAAoC,CAAC;KACjD,OAAO,CAAC,gBAAgB,EAAE,CAAC;KAC3B,MAAM,CACL,eAAe,EACf,+CAA+C,EAC/C,CAAC,CAAC,EAAE,IAAY,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,EAC7B,CAAC,CACF;KACA,MAAM,CAAC,kBAAkB,EAAE,iCAAiC,CAAC,CAAC;AAEjE,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;AACrC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;AAC9B,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAElC,OAAO,CAAC,WAAW,CACjB,OAAO,EACP;;;;;yCAKuC,CACxC,CAAC;AAEF,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,oCAAoC,CAAC;KACjD,OAAO,CAAC,gBAAgB,EAAE,CAAC;KAC3B,MAAM,CACL,eAAe,EACf,+CAA+C,EAC/C,CAAC,CAAC,EAAE,IAAY,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,EAC7B,CAAC,CACF;KACA,MAAM,CAAC,kBAAkB,EAAE,iCAAiC,CAAC,CAAC;AAEjE,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;AACrC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;AAC9B,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;AAEvC,OAAO,CAAC,WAAW,CACjB,OAAO,EACP;;;;;yCAKuC,CACxC,CAAC;AAEF,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../../src/cli/tui/App.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAA4D,MAAM,OAAO,CAAC;AAkCjF,UAAU,QAAQ;IAChB,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAID,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAkrBpC,wBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,KAAK,CAAC,YAAY,CAMvD"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../../src/cli/tui/App.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAA4D,MAAM,OAAO,CAAC;AAqCjF,UAAU,QAAQ;IAChB,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAID,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,iBAAiB,KAAK,CAAC;AA6vBpC,wBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,KAAK,CAAC,YAAY,CAMvD"}
@@ -21,10 +21,13 @@ import { FilterBar } from "./components/FilterBar.js";
21
21
  import { ExportModal } from "./components/ExportModal.js";
22
22
  import { HelpModal } from "./components/HelpModal.js";
23
23
  import { InfoModal } from "./components/InfoModal.js";
24
+ import { InterceptorLogModal } from "./components/InterceptorLogModal.js";
25
+ import { InfoBar } from "./components/InfoBar.js";
24
26
  import { isFilterActive } from "./utils/filters.js";
25
27
  import { isJsonContent } from "./utils/content-type.js";
26
28
  import { JsonExplorerModal } from "./components/JsonExplorerModal.js";
27
29
  import { TextViewerModal } from "./components/TextViewerModal.js";
30
+ import { useInterceptorEvents } from "./hooks/useInterceptorEvents.js";
28
31
  import { findProjectRoot, getProcsiPaths, readProxyPort } from "../../shared/project.js";
29
32
  import { loadConfig } from "../../shared/config.js";
30
33
  export const MIN_TERMINAL_COLUMNS = 60;
@@ -41,11 +44,16 @@ function AppContent({ __testEnableInput, projectRoot }) {
41
44
  // Filter state
42
45
  const [filter, setFilter] = useState({});
43
46
  const [showFilter, setShowFilter] = useState(false);
44
- const { requests, isLoading, error, refresh, getFullRequest, getAllFullRequests } = useRequests({
47
+ const { requests, isLoading, error, refresh, getFullRequest, getAllFullRequests, toggleSaved, clearRequests } = useRequests({
45
48
  filter,
46
49
  projectRoot,
47
50
  pollInterval: config?.pollInterval,
48
51
  });
52
+ const interceptorEvents = useInterceptorEvents({
53
+ projectRoot,
54
+ pollInterval: config?.pollInterval,
55
+ });
56
+ const startTime = useMemo(() => Date.now(), []);
49
57
  const { exportCurl, exportHar } = useExport();
50
58
  const { saveBody } = useBodyExport();
51
59
  const spinnerFrame = useSpinner(isLoading && requests.length === 0);
@@ -61,6 +69,10 @@ function AppContent({ __testEnableInput, projectRoot }) {
61
69
  const [showHelp, setShowHelp] = useState(false);
62
70
  // Info modal state
63
71
  const [showInfo, setShowInfo] = useState(false);
72
+ // Interceptor log modal state
73
+ const [showInterceptorLog, setShowInterceptorLog] = useState(false);
74
+ // Clear confirmation state — when true, the next 'y' press confirms the clear
75
+ const [pendingClear, setPendingClear] = useState(false);
64
76
  // Proxy details for info modal (one-time sync read)
65
77
  const proxyPort = useMemo(() => {
66
78
  const root = projectRoot ?? findProjectRoot();
@@ -231,6 +243,19 @@ function AppContent({ __testEnableInput, projectRoot }) {
231
243
  }, [selectedFullRequest, savingBodyType, saveBody, showStatus]);
232
244
  // Handle keyboard input (only when raw mode is supported, i.e. running in a TTY)
233
245
  useInput((input, key) => {
246
+ // Handle clear confirmation — any key other than 'y' cancels
247
+ if (pendingClear) {
248
+ setPendingClear(false);
249
+ if (input === "y") {
250
+ void clearRequests().then((success) => {
251
+ showStatus(success ? "Requests cleared (bookmarks preserved)" : "Failed to clear requests");
252
+ });
253
+ }
254
+ else {
255
+ setStatusMessage(undefined);
256
+ }
257
+ return;
258
+ }
234
259
  // Navigation - behaviour depends on active panel
235
260
  if (input === "j" || key.downArrow) {
236
261
  if (activePanel === "list") {
@@ -438,6 +463,9 @@ function AppContent({ __testEnableInput, projectRoot }) {
438
463
  else if (input === "i") {
439
464
  setShowInfo(true);
440
465
  }
466
+ else if (input === "L") {
467
+ setShowInterceptorLog(true);
468
+ }
441
469
  else if (input === "/") {
442
470
  preOpenFilterRef.current = filter;
443
471
  setShowFilter(true);
@@ -470,13 +498,41 @@ function AppContent({ __testEnableInput, projectRoot }) {
470
498
  showStatus("No body to export");
471
499
  }
472
500
  }
473
- }, { isActive: (__testEnableInput || isRawModeSupported === true) && !showSaveModal && !showHelp && !showInfo && !showFilter && !showJsonExplorer && !showTextViewer });
501
+ else if (input === "x" || input === "D") {
502
+ // Clear all unsaved requests (with confirmation)
503
+ if (requests.length > 0) {
504
+ setPendingClear(true);
505
+ showStatus("Clear all requests? (y to confirm, any key to cancel)");
506
+ }
507
+ else {
508
+ showStatus("No requests to clear");
509
+ }
510
+ }
511
+ else if (input === "b" && !key.ctrl) {
512
+ // Toggle bookmark on selected request
513
+ if (selectedSummary) {
514
+ const currentlySaved = selectedSummary.saved === true;
515
+ void toggleSaved(selectedSummary.id, currentlySaved).then((success) => {
516
+ if (success) {
517
+ showStatus(currentlySaved ? "Bookmark removed" : "Bookmarked");
518
+ }
519
+ else {
520
+ showStatus("Failed to toggle bookmark");
521
+ }
522
+ });
523
+ }
524
+ else {
525
+ showStatus("No request selected");
526
+ }
527
+ }
528
+ }, { isActive: (__testEnableInput || isRawModeSupported === true) && !showSaveModal && !showHelp && !showInfo && !showInterceptorLog && !showFilter && !showJsonExplorer && !showTextViewer });
474
529
  // Calculate layout
475
530
  const listWidth = Math.floor(columns * 0.4);
476
531
  const accordionWidth = columns - listWidth;
477
- // Status bar takes 2 rows (border line + content line), filter bar takes 2 rows when visible
532
+ // Status bar takes 2 rows (border line + content line), InfoBar takes 1 row, filter bar takes 2 rows when visible
478
533
  const filterBarHeight = showFilter ? 2 : 0;
479
- const contentHeight = rows - 2 - filterBarHeight;
534
+ const infoBarHeight = 1;
535
+ const contentHeight = rows - 2 - infoBarHeight - filterBarHeight;
480
536
  // Keep selection in bounds when requests change
481
537
  React.useEffect(() => {
482
538
  if (selectedIndex >= requests.length && requests.length > 0) {
@@ -492,7 +548,8 @@ function AppContent({ __testEnableInput, projectRoot }) {
492
548
  else if (selectedIndex >= listScrollOffset + visibleHeight) {
493
549
  setListScrollOffset(selectedIndex - visibleHeight + 1);
494
550
  }
495
- }, [selectedIndex, contentHeight, listScrollOffset]);
551
+ // Intentionally omit listScrollOffset to allow free mouse wheel scrolling
552
+ }, [selectedIndex, contentHeight]);
496
553
  // Terminal size check — re-evaluates on resize via useStdoutDimensions
497
554
  if (columns < MIN_TERMINAL_COLUMNS || rows < MIN_TERMINAL_ROWS) {
498
555
  return (_jsxs(Box, { flexDirection: "column", alignItems: "center", justifyContent: "center", height: rows, width: columns, children: [_jsx(Text, { color: "red", bold: true, children: "Terminal too small" }), _jsx(Text, { children: " " }), _jsxs(Text, { children: ["Current: ", columns, "x", rows] }), _jsxs(Text, { children: ["Required: ", MIN_TERMINAL_COLUMNS, "x", MIN_TERMINAL_ROWS] }), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: "Please resize your terminal." })] }));
@@ -524,6 +581,10 @@ function AppContent({ __testEnableInput, projectRoot }) {
524
581
  if (showInfo) {
525
582
  return (_jsx(InfoModal, { proxyPort: proxyPort, caCertPath: caCertPath, width: columns, height: rows, onClose: () => setShowInfo(false), isActive: __testEnableInput || isRawModeSupported === true }));
526
583
  }
584
+ // Interceptor log modal - full screen replacement
585
+ if (showInterceptorLog) {
586
+ return (_jsx(InterceptorLogModal, { events: interceptorEvents.events, width: columns, height: rows, onClose: () => setShowInterceptorLog(false), isActive: __testEnableInput || isRawModeSupported === true }));
587
+ }
527
588
  // Help modal - full screen replacement
528
589
  if (showHelp) {
529
590
  return (_jsx(HelpModal, { width: columns, height: rows, onClose: () => setShowHelp(false), isActive: __testEnableInput || isRawModeSupported === true }));
@@ -536,7 +597,7 @@ function AppContent({ __testEnableInput, projectRoot }) {
536
597
  if (showTextViewer && textViewerData) {
537
598
  return (_jsx(TextViewerModal, { text: textViewerData.text, title: textViewerData.title, contentType: textViewerData.contentType, bodySize: textViewerData.bodySize, width: columns, height: rows, onClose: () => setShowTextViewer(false), onStatus: showStatus, isActive: __testEnableInput || isRawModeSupported === true }));
538
599
  }
539
- return (_jsxs(Box, { flexDirection: "column", height: rows, children: [_jsxs(Box, { flexDirection: "row", height: contentHeight, children: [_jsx(RequestList, { ref: listPanelRef, requests: requests, selectedIndex: selectedIndex, isActive: activePanel === "list", isHovered: hoveredPanel === "list", width: listWidth, height: contentHeight, showFullUrl: showFullUrl, onItemClick: handleItemClick, scrollOffset: listScrollOffset, searchTerm: filter.search }), _jsx(AccordionPanel, { ref: accordionPanelRef, request: selectedFullRequest, isActive: activePanel === "accordion", width: accordionWidth, height: contentHeight, focusedSection: focusedSection, expandedSections: new Set([focusedSection]) })] }), showFilter && (_jsx(FilterBar, { isActive: (__testEnableInput || isRawModeSupported === true) && showFilter, filter: filter, onFilterChange: handleFilterChange, onClose: () => setShowFilter(false), onCancel: handleFilterCancel, width: columns })), _jsx(StatusBar, { message: statusMessage, filterActive: isFilterActive(filter), filterOpen: showFilter, activePanel: activePanel, hasSelection: selectedFullRequest !== null, hasRequests: requests.length > 0, onBodySection: currentBodyIsExportable, onViewableBodySection: currentBodyIsExportable && !currentBodyIsBinary, width: columns })] }));
600
+ return (_jsxs(Box, { flexDirection: "column", height: rows, children: [_jsxs(Box, { flexDirection: "row", height: contentHeight, children: [_jsx(RequestList, { ref: listPanelRef, requests: requests, selectedIndex: selectedIndex, isActive: activePanel === "list", isHovered: hoveredPanel === "list", width: listWidth, height: contentHeight, showFullUrl: showFullUrl, onItemClick: handleItemClick, scrollOffset: listScrollOffset, searchTerm: filter.search }), _jsx(AccordionPanel, { ref: accordionPanelRef, request: selectedFullRequest, isActive: activePanel === "accordion", width: accordionWidth, height: contentHeight, focusedSection: focusedSection, expandedSections: new Set([focusedSection]) })] }), showFilter && (_jsx(FilterBar, { isActive: (__testEnableInput || isRawModeSupported === true) && showFilter, filter: filter, onFilterChange: handleFilterChange, onClose: () => setShowFilter(false), onCancel: handleFilterCancel, width: columns })), _jsx(InfoBar, { interceptorErrorCount: interceptorEvents.counts.error, requestCount: requests.length, interceptorCount: interceptorEvents.interceptorCount, startTime: startTime, width: columns }), _jsx(StatusBar, { message: statusMessage, filterActive: isFilterActive(filter), filterOpen: showFilter, activePanel: activePanel, hasSelection: selectedFullRequest !== null, hasRequests: requests.length > 0, onBodySection: currentBodyIsExportable, onViewableBodySection: currentBodyIsExportable && !currentBodyIsBinary, interceptorCount: interceptorEvents.interceptorCount, interceptorErrorCount: interceptorEvents.counts.error, hasEvents: interceptorEvents.totalEventCount > 0, width: columns })] }));
540
601
  }
541
602
  export function App(props) {
542
603
  return (_jsx(MouseProvider, { children: _jsx(AppContent, { ...props }) }));