@industry-theme/xterm-terminal-panel 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -26,6 +26,28 @@ import {
26
26
  } from "react";
27
27
  import"@xterm/xterm/css/xterm.css";
28
28
 
29
+ // src/telemetry.ts
30
+ import {
31
+ trace,
32
+ context,
33
+ SpanStatusCode
34
+ } from "@opentelemetry/api";
35
+ var PACKAGE_VERSION = "0.5.1";
36
+ var TRACER_NAME = "@industry-theme/xterm-terminal-panel";
37
+ var TRACER_VERSION = PACKAGE_VERSION;
38
+ function getTracer() {
39
+ return trace.getTracer(TRACER_NAME, TRACER_VERSION);
40
+ }
41
+ function getActiveSpan() {
42
+ return trace.getActiveSpan();
43
+ }
44
+ async function withSpan(span, fn) {
45
+ return context.with(trace.setSpan(context.active(), span), fn);
46
+ }
47
+ function withSpanSync(span, fn) {
48
+ return context.with(trace.setSpan(context.active(), span), fn);
49
+ }
50
+
29
51
  // src/utils/terminalTheme.ts
30
52
  function createTerminalTheme(theme) {
31
53
  return {
@@ -65,8 +87,101 @@ function getTerminalCSSVariables(theme) {
65
87
  };
66
88
  }
67
89
 
90
+ // src/components/WorkingOverlay.tsx
91
+ import { jsx, jsxs } from "react/jsx-runtime";
92
+ var WorkingOverlay = ({
93
+ theme,
94
+ message = "Agent working...",
95
+ subtitle,
96
+ isClosing = false,
97
+ onCloseComplete
98
+ }) => {
99
+ const handleAnimationEnd = (e) => {
100
+ if (isClosing && e.animationName === "blinds-up" && onCloseComplete) {
101
+ onCloseComplete();
102
+ }
103
+ };
104
+ return /* @__PURE__ */ jsxs("div", {
105
+ className: `terminal-working-overlay${isClosing ? " closing" : ""}`,
106
+ onAnimationEnd: handleAnimationEnd,
107
+ style: {
108
+ position: "absolute",
109
+ top: 0,
110
+ left: 0,
111
+ right: 0,
112
+ bottom: 0,
113
+ display: "flex",
114
+ flexDirection: "column",
115
+ alignItems: "center",
116
+ justifyContent: "center",
117
+ backgroundColor: theme.colors.background,
118
+ gap: "12px",
119
+ padding: "32px",
120
+ zIndex: 10
121
+ },
122
+ children: [
123
+ /* @__PURE__ */ jsxs("div", {
124
+ style: {
125
+ display: "flex",
126
+ gap: "6px",
127
+ marginBottom: "8px"
128
+ },
129
+ children: [
130
+ /* @__PURE__ */ jsx("div", {
131
+ className: "working-dot",
132
+ style: {
133
+ width: "8px",
134
+ height: "8px",
135
+ borderRadius: "50%",
136
+ backgroundColor: theme.colors.primary,
137
+ animation: "pulse 1.4s ease-in-out infinite"
138
+ }
139
+ }),
140
+ /* @__PURE__ */ jsx("div", {
141
+ className: "working-dot",
142
+ style: {
143
+ width: "8px",
144
+ height: "8px",
145
+ borderRadius: "50%",
146
+ backgroundColor: theme.colors.primary,
147
+ animation: "pulse 1.4s ease-in-out 0.2s infinite"
148
+ }
149
+ }),
150
+ /* @__PURE__ */ jsx("div", {
151
+ className: "working-dot",
152
+ style: {
153
+ width: "8px",
154
+ height: "8px",
155
+ borderRadius: "50%",
156
+ backgroundColor: theme.colors.primary,
157
+ animation: "pulse 1.4s ease-in-out 0.4s infinite"
158
+ }
159
+ })
160
+ ]
161
+ }),
162
+ /* @__PURE__ */ jsx("div", {
163
+ style: {
164
+ fontSize: "15px",
165
+ fontWeight: "500",
166
+ color: theme.colors.text,
167
+ textAlign: "center"
168
+ },
169
+ children: message
170
+ }),
171
+ subtitle && /* @__PURE__ */ jsx("div", {
172
+ style: {
173
+ fontSize: "13px",
174
+ color: theme.colors.textSecondary,
175
+ textAlign: "center"
176
+ },
177
+ children: subtitle
178
+ })
179
+ ]
180
+ });
181
+ };
182
+
68
183
  // src/components/ThemedTerminal.tsx
69
- import { jsx, jsxs, Fragment } from "react/jsx-runtime";
184
+ import { jsx as jsx2, jsxs as jsxs2, Fragment } from "react/jsx-runtime";
70
185
  var SCROLL_DEBOUNCE_MS = 1000;
71
186
  var DEBUG_RESIZE = true;
72
187
  var ThemedTerminal = forwardRef(({
@@ -90,6 +205,13 @@ var ThemedTerminal = forwardRef(({
90
205
  onPopOut,
91
206
  onShortcut,
92
207
  overlayState,
208
+ isWorking: isWorkingProp = false,
209
+ workingMessage = "Agent working...",
210
+ workingSubtitle,
211
+ activityDetection = true,
212
+ activityTimeout = 500,
213
+ onActivityChange,
214
+ autoShowBlinds = false,
93
215
  cursorBlink = true,
94
216
  cursorStyle = "block",
95
217
  scrollback = 1e4,
@@ -100,6 +222,7 @@ var ThemedTerminal = forwardRef(({
100
222
  }, ref) => {
101
223
  const terminalRef = useRef(null);
102
224
  const [terminal, setTerminal] = useState(null);
225
+ const [isClosingOverlay, setIsClosingOverlay] = useState(false);
103
226
  const fitAddonRef = useRef(null);
104
227
  const searchAddonRef = useRef(null);
105
228
  const webglAddonRef = useRef(null);
@@ -108,9 +231,105 @@ var ThemedTerminal = forwardRef(({
108
231
  const isVisibleRef = useRef(isVisible);
109
232
  const isScrollLockedRef = useRef(defaultScrollLocked);
110
233
  const onShortcutRef = useRef(onShortcut);
234
+ const [isActivityDetected, setIsActivityDetected] = useState(false);
235
+ const activityTimeoutRef = useRef(null);
236
+ const activityStartTimeRef = useRef(null);
237
+ const onActivityChangeRef = useRef(onActivityChange);
111
238
  useEffect(() => {
112
239
  onShortcutRef.current = onShortcut;
113
240
  }, [onShortcut]);
241
+ useEffect(() => {
242
+ onActivityChangeRef.current = onActivityChange;
243
+ }, [onActivityChange]);
244
+ const isWorking = isWorkingProp || autoShowBlinds && isActivityDetected;
245
+ const [showWorkingOverlay, setShowWorkingOverlay] = useState(isWorking);
246
+ useEffect(() => {
247
+ if (isWorking) {
248
+ setIsClosingOverlay(false);
249
+ setShowWorkingOverlay(true);
250
+ const tracer = getTracer();
251
+ const span = tracer.startSpan("terminal.blinds", {
252
+ attributes: {
253
+ "blinds.action": "shown"
254
+ }
255
+ });
256
+ span.addEvent("terminal.blinds.shown");
257
+ span.setStatus({ code: SpanStatusCode.OK });
258
+ span.end();
259
+ } else if (showWorkingOverlay) {
260
+ setIsClosingOverlay(true);
261
+ }
262
+ }, [isWorking]);
263
+ const handleOverlayCloseComplete = useCallback(() => {
264
+ setShowWorkingOverlay(false);
265
+ setIsClosingOverlay(false);
266
+ const tracer = getTracer();
267
+ const span = tracer.startSpan("terminal.blinds", {
268
+ attributes: {
269
+ "blinds.action": "hidden"
270
+ }
271
+ });
272
+ span.addEvent("terminal.blinds.hidden");
273
+ span.setStatus({ code: SpanStatusCode.OK });
274
+ span.end();
275
+ }, []);
276
+ const trackActivity = useCallback(() => {
277
+ if (!activityDetection)
278
+ return;
279
+ if (activityTimeoutRef.current) {
280
+ clearTimeout(activityTimeoutRef.current);
281
+ }
282
+ if (!activityStartTimeRef.current) {
283
+ activityStartTimeRef.current = Date.now();
284
+ setIsActivityDetected(true);
285
+ const tracer = getTracer();
286
+ const span = tracer.startSpan("terminal.activity", {
287
+ attributes: {
288
+ "activity.type": "started"
289
+ }
290
+ });
291
+ span.addEvent("terminal.activity.started", {
292
+ "activity.startedAt": activityStartTimeRef.current
293
+ });
294
+ span.setStatus({ code: SpanStatusCode.OK });
295
+ span.end();
296
+ const state = {
297
+ isActive: true,
298
+ startedAt: activityStartTimeRef.current
299
+ };
300
+ onActivityChangeRef.current?.(state);
301
+ }
302
+ activityTimeoutRef.current = setTimeout(() => {
303
+ const startedAt = activityStartTimeRef.current;
304
+ const duration = startedAt ? Date.now() - startedAt : undefined;
305
+ activityStartTimeRef.current = null;
306
+ setIsActivityDetected(false);
307
+ const tracer = getTracer();
308
+ const span = tracer.startSpan("terminal.activity", {
309
+ attributes: {
310
+ "activity.type": "stopped",
311
+ "activity.duration.ms": duration
312
+ }
313
+ });
314
+ span.addEvent("terminal.activity.stopped", {
315
+ "activity.duration.ms": duration ?? 0
316
+ });
317
+ span.setStatus({ code: SpanStatusCode.OK });
318
+ span.end();
319
+ const state = {
320
+ isActive: false,
321
+ duration
322
+ };
323
+ onActivityChangeRef.current?.(state);
324
+ }, activityTimeout);
325
+ }, [activityDetection, activityTimeout]);
326
+ useEffect(() => {
327
+ return () => {
328
+ if (activityTimeoutRef.current) {
329
+ clearTimeout(activityTimeoutRef.current);
330
+ }
331
+ };
332
+ }, []);
114
333
  const handleDroppedContent = useCallback((content) => {
115
334
  if (terminal) {
116
335
  terminal.paste(content);
@@ -178,6 +397,7 @@ var ThemedTerminal = forwardRef(({
178
397
  if (terminal) {
179
398
  terminal.write(data);
180
399
  scheduleScrollToBottom();
400
+ trackActivity();
181
401
  } else {
182
402
  console.warn("[ThemedTerminal] write called but terminal is null!");
183
403
  }
@@ -185,6 +405,7 @@ var ThemedTerminal = forwardRef(({
185
405
  writeln: (data) => {
186
406
  if (terminal) {
187
407
  terminal.writeln(data);
408
+ trackActivity();
188
409
  scheduleScrollToBottom();
189
410
  }
190
411
  },
@@ -259,7 +480,7 @@ var ThemedTerminal = forwardRef(({
259
480
  },
260
481
  isScrollLocked: () => isScrollLockedRef.current,
261
482
  getScrollPosition
262
- }), [terminal]);
483
+ }), [terminal, trackActivity]);
263
484
  const initialConfigRef = useRef({
264
485
  cursorBlink,
265
486
  cursorStyle,
@@ -595,7 +816,7 @@ var ThemedTerminal = forwardRef(({
595
816
  }
596
817
  }
597
818
  };
598
- return /* @__PURE__ */ jsxs("div", {
819
+ return /* @__PURE__ */ jsxs2("div", {
599
820
  className,
600
821
  style: {
601
822
  display: "flex",
@@ -605,7 +826,7 @@ var ThemedTerminal = forwardRef(({
605
826
  backgroundColor: theme.colors.background
606
827
  },
607
828
  children: [
608
- !hideHeader && /* @__PURE__ */ jsxs("div", {
829
+ !hideHeader && /* @__PURE__ */ jsxs2("div", {
609
830
  style: {
610
831
  display: "flex",
611
832
  alignItems: "center",
@@ -615,14 +836,14 @@ var ThemedTerminal = forwardRef(({
615
836
  backgroundColor: theme.colors.backgroundSecondary || theme.colors.background
616
837
  },
617
838
  children: [
618
- /* @__PURE__ */ jsxs("div", {
839
+ /* @__PURE__ */ jsxs2("div", {
619
840
  style: { display: "flex", alignItems: "center", gap: "8px" },
620
841
  children: [
621
- /* @__PURE__ */ jsx(TerminalIcon, {
842
+ /* @__PURE__ */ jsx2(TerminalIcon, {
622
843
  size: 16,
623
844
  color: theme.colors.text
624
845
  }),
625
- /* @__PURE__ */ jsx("span", {
846
+ /* @__PURE__ */ jsx2("span", {
626
847
  style: {
627
848
  fontSize: "14px",
628
849
  color: theme.colors.text,
@@ -630,23 +851,23 @@ var ThemedTerminal = forwardRef(({
630
851
  },
631
852
  children: headerTitle
632
853
  }),
633
- headerSubtitle && /* @__PURE__ */ jsx("span", {
854
+ headerSubtitle && /* @__PURE__ */ jsx2("span", {
634
855
  style: {
635
856
  fontSize: "12px",
636
857
  color: theme.colors.textSecondary
637
858
  },
638
859
  children: headerSubtitle
639
860
  }),
640
- headerBadge && /* @__PURE__ */ jsxs(Fragment, {
861
+ headerBadge && /* @__PURE__ */ jsxs2(Fragment, {
641
862
  children: [
642
- /* @__PURE__ */ jsx("span", {
863
+ /* @__PURE__ */ jsx2("span", {
643
864
  style: {
644
865
  fontSize: "12px",
645
866
  color: theme.colors.textSecondary
646
867
  },
647
868
  children: "•"
648
869
  }),
649
- /* @__PURE__ */ jsx("span", {
870
+ /* @__PURE__ */ jsx2("span", {
650
871
  style: {
651
872
  fontSize: "12px",
652
873
  color: headerBadge.color || theme.colors.primary
@@ -657,10 +878,10 @@ var ThemedTerminal = forwardRef(({
657
878
  })
658
879
  ]
659
880
  }),
660
- /* @__PURE__ */ jsxs("div", {
881
+ /* @__PURE__ */ jsxs2("div", {
661
882
  style: { display: "flex", gap: "8px" },
662
883
  children: [
663
- onPopOut && /* @__PURE__ */ jsx("button", {
884
+ onPopOut && /* @__PURE__ */ jsx2("button", {
664
885
  type: "button",
665
886
  "aria-label": "Pop out terminal to new window",
666
887
  onClick: onPopOut,
@@ -685,11 +906,11 @@ var ThemedTerminal = forwardRef(({
685
906
  e.currentTarget.style.color = theme.colors.textSecondary;
686
907
  },
687
908
  title: "Open terminal in new window",
688
- children: /* @__PURE__ */ jsx(ExternalLink, {
909
+ children: /* @__PURE__ */ jsx2(ExternalLink, {
689
910
  size: 16
690
911
  })
691
912
  }),
692
- onClose && /* @__PURE__ */ jsx("button", {
913
+ onClose && /* @__PURE__ */ jsx2("button", {
693
914
  type: "button",
694
915
  "aria-label": "Hide terminal",
695
916
  onClick: onClose,
@@ -714,11 +935,11 @@ var ThemedTerminal = forwardRef(({
714
935
  e.currentTarget.style.color = theme.colors.textSecondary;
715
936
  },
716
937
  title: "Hide terminal (keeps session running)",
717
- children: /* @__PURE__ */ jsx(ChevronDown, {
938
+ children: /* @__PURE__ */ jsx2(ChevronDown, {
718
939
  size: 16
719
940
  })
720
941
  }),
721
- onDestroy && /* @__PURE__ */ jsx("button", {
942
+ onDestroy && /* @__PURE__ */ jsx2("button", {
722
943
  type: "button",
723
944
  "aria-label": "Close terminal session",
724
945
  onClick: handleDestroy,
@@ -743,7 +964,7 @@ var ThemedTerminal = forwardRef(({
743
964
  e.currentTarget.style.color = theme.colors.textSecondary;
744
965
  },
745
966
  title: "Close terminal session (terminate process)",
746
- children: /* @__PURE__ */ jsx(X, {
967
+ children: /* @__PURE__ */ jsx2(X, {
747
968
  size: 16
748
969
  })
749
970
  })
@@ -751,7 +972,7 @@ var ThemedTerminal = forwardRef(({
751
972
  })
752
973
  ]
753
974
  }),
754
- /* @__PURE__ */ jsxs("div", {
975
+ /* @__PURE__ */ jsxs2("div", {
755
976
  ref: terminalRef,
756
977
  ...dropZoneProps,
757
978
  className: `terminal-container-fix ${scrollbarStyle === "hidden" ? "hide-scrollbar" : scrollbarStyle === "thin" ? "thin-scrollbar" : scrollbarStyle === "auto-hide" ? "auto-hide-scrollbar" : ""}`,
@@ -764,7 +985,7 @@ var ThemedTerminal = forwardRef(({
764
985
  minHeight: 0
765
986
  },
766
987
  children: [
767
- isDragOver && /* @__PURE__ */ jsx("div", {
988
+ isDragOver && /* @__PURE__ */ jsx2("div", {
768
989
  style: {
769
990
  position: "absolute",
770
991
  inset: 0,
@@ -777,7 +998,7 @@ var ThemedTerminal = forwardRef(({
777
998
  pointerEvents: "none",
778
999
  zIndex: 1000
779
1000
  },
780
- children: /* @__PURE__ */ jsx("div", {
1001
+ children: /* @__PURE__ */ jsx2("div", {
781
1002
  style: {
782
1003
  padding: "8px 16px",
783
1004
  background: "#3b82f6",
@@ -789,7 +1010,7 @@ var ThemedTerminal = forwardRef(({
789
1010
  children: "Drop to insert"
790
1011
  })
791
1012
  }),
792
- overlayState && /* @__PURE__ */ jsxs("div", {
1013
+ overlayState && /* @__PURE__ */ jsxs2("div", {
793
1014
  style: {
794
1015
  position: "absolute",
795
1016
  top: 0,
@@ -807,11 +1028,11 @@ var ThemedTerminal = forwardRef(({
807
1028
  zIndex: 10
808
1029
  },
809
1030
  children: [
810
- /* @__PURE__ */ jsx(Monitor, {
1031
+ /* @__PURE__ */ jsx2(Monitor, {
811
1032
  size: 48,
812
1033
  color: theme.colors.textSecondary
813
1034
  }),
814
- /* @__PURE__ */ jsx("div", {
1035
+ /* @__PURE__ */ jsx2("div", {
815
1036
  style: {
816
1037
  fontSize: "16px",
817
1038
  fontWeight: "500",
@@ -820,7 +1041,7 @@ var ThemedTerminal = forwardRef(({
820
1041
  },
821
1042
  children: overlayState.message
822
1043
  }),
823
- overlayState.subtitle && /* @__PURE__ */ jsx("div", {
1044
+ overlayState.subtitle && /* @__PURE__ */ jsx2("div", {
824
1045
  style: {
825
1046
  fontSize: "14px",
826
1047
  color: theme.colors.textSecondary,
@@ -829,13 +1050,13 @@ var ThemedTerminal = forwardRef(({
829
1050
  },
830
1051
  children: overlayState.subtitle
831
1052
  }),
832
- overlayState.actions && overlayState.actions.length > 0 && /* @__PURE__ */ jsx("div", {
1053
+ overlayState.actions && overlayState.actions.length > 0 && /* @__PURE__ */ jsx2("div", {
833
1054
  style: {
834
1055
  display: "flex",
835
1056
  gap: "12px",
836
1057
  marginTop: "8px"
837
1058
  },
838
- children: overlayState.actions.map((action) => /* @__PURE__ */ jsxs("button", {
1059
+ children: overlayState.actions.map((action) => /* @__PURE__ */ jsxs2("button", {
839
1060
  type: "button",
840
1061
  onClick: action.onClick,
841
1062
  style: {
@@ -873,6 +1094,13 @@ var ThemedTerminal = forwardRef(({
873
1094
  }, action.label))
874
1095
  })
875
1096
  ]
1097
+ }),
1098
+ showWorkingOverlay && !overlayState && /* @__PURE__ */ jsx2(WorkingOverlay, {
1099
+ theme,
1100
+ message: workingMessage,
1101
+ subtitle: workingSubtitle,
1102
+ isClosing: isClosingOverlay,
1103
+ onCloseComplete: handleOverlayCloseComplete
876
1104
  })
877
1105
  ]
878
1106
  })
@@ -883,10 +1111,10 @@ ThemedTerminal.displayName = "ThemedTerminal";
883
1111
  // src/components/ThemedTerminalWithProvider.tsx
884
1112
  import { useTheme } from "@principal-ade/industry-theme";
885
1113
  import { forwardRef as forwardRef2 } from "react";
886
- import { jsx as jsx2 } from "react/jsx-runtime";
1114
+ import { jsx as jsx3 } from "react/jsx-runtime";
887
1115
  var ThemedTerminalWithProvider = forwardRef2((props, ref) => {
888
1116
  const { theme } = useTheme();
889
- return /* @__PURE__ */ jsx2(ThemedTerminal, {
1117
+ return /* @__PURE__ */ jsx3(ThemedTerminal, {
890
1118
  ref,
891
1119
  theme,
892
1120
  ...props
@@ -935,7 +1163,7 @@ import { useState as useState2 } from "react";
935
1163
 
936
1164
  // src/components/TabBar/TabButton.tsx
937
1165
  import { useTheme as useTheme3 } from "@principal-ade/industry-theme";
938
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1166
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
939
1167
  var TabButton = ({
940
1168
  tab,
941
1169
  isActive,
@@ -952,7 +1180,7 @@ var TabButton = ({
952
1180
  const { theme } = useTheme3();
953
1181
  const showCloseButton = isHovered || isActive;
954
1182
  const closable = tab.closable !== false;
955
- return /* @__PURE__ */ jsxs2("div", {
1183
+ return /* @__PURE__ */ jsxs3("div", {
956
1184
  onMouseEnter,
957
1185
  onMouseLeave,
958
1186
  onClick,
@@ -977,7 +1205,7 @@ var TabButton = ({
977
1205
  boxSizing: "border-box"
978
1206
  },
979
1207
  children: [
980
- closable && showCloseButton && /* @__PURE__ */ jsx3("button", {
1208
+ closable && showCloseButton && /* @__PURE__ */ jsx4("button", {
981
1209
  onClick: (e) => {
982
1210
  e.stopPropagation();
983
1211
  onClose();
@@ -1009,7 +1237,7 @@ var TabButton = ({
1009
1237
  (() => {
1010
1238
  const icon = renderIcon ? renderIcon(tab) : undefined;
1011
1239
  const displayIcon = icon !== undefined ? icon : tab.icon;
1012
- return displayIcon ? /* @__PURE__ */ jsx3("div", {
1240
+ return displayIcon ? /* @__PURE__ */ jsx4("div", {
1013
1241
  style: { flexShrink: 0, display: "flex", alignItems: "center" },
1014
1242
  children: displayIcon
1015
1243
  }) : null;
@@ -1017,7 +1245,7 @@ var TabButton = ({
1017
1245
  (() => {
1018
1246
  const label = renderLabel ? renderLabel(tab) : undefined;
1019
1247
  const displayLabel = label !== undefined ? label : tab.label;
1020
- return /* @__PURE__ */ jsx3("span", {
1248
+ return /* @__PURE__ */ jsx4("span", {
1021
1249
  style: {
1022
1250
  overflow: "hidden",
1023
1251
  textOverflow: "ellipsis",
@@ -1027,7 +1255,7 @@ var TabButton = ({
1027
1255
  children: displayLabel
1028
1256
  });
1029
1257
  })(),
1030
- renderAccessory ? renderAccessory(tab) : keyboardHint && /* @__PURE__ */ jsx3("span", {
1258
+ renderAccessory ? renderAccessory(tab) : keyboardHint && /* @__PURE__ */ jsx4("span", {
1031
1259
  style: {
1032
1260
  fontSize: theme.fontSizes[0],
1033
1261
  color: theme.colors.textSecondary,
@@ -1042,7 +1270,7 @@ var TabButton = ({
1042
1270
  TabButton.displayName = "TabButton";
1043
1271
 
1044
1272
  // src/components/TabBar/TabBar.tsx
1045
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1273
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1046
1274
  var TabBar = ({
1047
1275
  tabs,
1048
1276
  activeTabId,
@@ -1059,7 +1287,7 @@ var TabBar = ({
1059
1287
  }) => {
1060
1288
  const { theme } = useTheme4();
1061
1289
  const [hoveredTabId, setHoveredTabId] = useState2(null);
1062
- return /* @__PURE__ */ jsxs3("div", {
1290
+ return /* @__PURE__ */ jsxs4("div", {
1063
1291
  className,
1064
1292
  style: {
1065
1293
  display: "flex",
@@ -1069,7 +1297,7 @@ var TabBar = ({
1069
1297
  boxSizing: "border-box"
1070
1298
  },
1071
1299
  children: [
1072
- leftSection && /* @__PURE__ */ jsx4("div", {
1300
+ leftSection && /* @__PURE__ */ jsx5("div", {
1073
1301
  style: {
1074
1302
  display: "flex",
1075
1303
  alignItems: "center",
@@ -1082,7 +1310,7 @@ var TabBar = ({
1082
1310
  },
1083
1311
  children: leftSection
1084
1312
  }),
1085
- /* @__PURE__ */ jsx4("div", {
1313
+ /* @__PURE__ */ jsx5("div", {
1086
1314
  style: {
1087
1315
  display: "flex",
1088
1316
  alignItems: "center",
@@ -1092,7 +1320,7 @@ var TabBar = ({
1092
1320
  borderBottom: `1px solid ${theme.colors.border}`,
1093
1321
  boxSizing: "border-box"
1094
1322
  },
1095
- children: tabs.map((tab, index) => /* @__PURE__ */ jsx4(TabButton, {
1323
+ children: tabs.map((tab, index) => /* @__PURE__ */ jsx5(TabButton, {
1096
1324
  tab,
1097
1325
  isActive: tab.id === activeTabId,
1098
1326
  isHovered: tab.id === hoveredTabId,
@@ -1106,7 +1334,7 @@ var TabBar = ({
1106
1334
  renderLabel: renderTabLabel
1107
1335
  }, tab.id))
1108
1336
  }),
1109
- rightSection !== undefined ? rightSection && /* @__PURE__ */ jsx4("div", {
1337
+ rightSection !== undefined ? rightSection && /* @__PURE__ */ jsx5("div", {
1110
1338
  style: {
1111
1339
  display: "flex",
1112
1340
  alignItems: "center",
@@ -1118,7 +1346,7 @@ var TabBar = ({
1118
1346
  boxSizing: "border-box"
1119
1347
  },
1120
1348
  children: rightSection
1121
- }) : onNewTab && /* @__PURE__ */ jsx4("div", {
1349
+ }) : onNewTab && /* @__PURE__ */ jsx5("div", {
1122
1350
  style: {
1123
1351
  display: "flex",
1124
1352
  alignItems: "center",
@@ -1129,7 +1357,7 @@ var TabBar = ({
1129
1357
  borderBottom: `1px solid ${theme.colors.border}`,
1130
1358
  boxSizing: "border-box"
1131
1359
  },
1132
- children: /* @__PURE__ */ jsx4("button", {
1360
+ children: /* @__PURE__ */ jsx5("button", {
1133
1361
  onClick: onNewTab,
1134
1362
  style: {
1135
1363
  display: "flex",
@@ -1150,7 +1378,7 @@ var TabBar = ({
1150
1378
  e.currentTarget.style.backgroundColor = "transparent";
1151
1379
  },
1152
1380
  title: "New Tab (⌘T)",
1153
- children: /* @__PURE__ */ jsx4(Plus, {
1381
+ children: /* @__PURE__ */ jsx5(Plus, {
1154
1382
  size: 14
1155
1383
  })
1156
1384
  })
@@ -1206,40 +1434,40 @@ import { Lock, Unlock, ArrowDown } from "lucide-react";
1206
1434
  import { useCallback as useCallback2, useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
1207
1435
 
1208
1436
  // src/panel-types/index.ts
1209
- function getTerminalSessions(context) {
1210
- return context.terminal?.data ?? [];
1437
+ function getTerminalSessions(context2) {
1438
+ return context2.terminal?.data ?? [];
1211
1439
  }
1212
- function getTerminalSession(context, sessionId) {
1213
- const sessions = getTerminalSessions(context);
1440
+ function getTerminalSession(context2, sessionId) {
1441
+ const sessions = getTerminalSessions(context2);
1214
1442
  return sessions.find((s) => s.id === sessionId);
1215
1443
  }
1216
- function isTerminalLoading(context) {
1217
- return context.terminal?.loading ?? false;
1444
+ function isTerminalLoading(context2) {
1445
+ return context2.terminal?.loading ?? false;
1218
1446
  }
1219
- function getRepositoryPath(context) {
1220
- return context.currentScope.repository?.path ?? null;
1447
+ function getRepositoryPath(context2) {
1448
+ return context2.currentScope.repository?.path ?? null;
1221
1449
  }
1222
- function getWorkspacePath(context) {
1223
- return context.currentScope.workspace?.path ?? null;
1450
+ function getWorkspacePath(context2) {
1451
+ return context2.currentScope.workspace?.path ?? null;
1224
1452
  }
1225
- function getTerminalDirectory(context, terminalScope = "repository") {
1453
+ function getTerminalDirectory(context2, terminalScope = "repository") {
1226
1454
  switch (terminalScope) {
1227
1455
  case "workspace":
1228
- return getWorkspacePath(context);
1456
+ return getWorkspacePath(context2);
1229
1457
  case "repository":
1230
- return getRepositoryPath(context) ?? getWorkspacePath(context);
1458
+ return getRepositoryPath(context2) ?? getWorkspacePath(context2);
1231
1459
  default:
1232
- return getRepositoryPath(context) ?? getWorkspacePath(context);
1460
+ return getRepositoryPath(context2) ?? getWorkspacePath(context2);
1233
1461
  }
1234
1462
  }
1235
- function getTerminalSlice(context) {
1236
- return context.terminal;
1463
+ function getTerminalSlice(context2) {
1464
+ return context2.terminal;
1237
1465
  }
1238
1466
 
1239
1467
  // src/panels/TerminalPanel.tsx
1240
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1468
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1241
1469
  var TerminalPanel = ({
1242
- context,
1470
+ context: context2,
1243
1471
  actions,
1244
1472
  events: _events,
1245
1473
  terminalScope = "repository"
@@ -1257,7 +1485,7 @@ var TerminalPanel = ({
1257
1485
  const terminalRef = useRef2(null);
1258
1486
  const dataPortRef = useRef2(null);
1259
1487
  const isScrollLockedRef = useRef2(scrollPosition.isScrollLocked);
1260
- const terminalDirectory = getTerminalDirectory(context, terminalScope);
1488
+ const terminalDirectory = getTerminalDirectory(context2, terminalScope);
1261
1489
  const pendingSessionIdRef = useRef2(null);
1262
1490
  useEffect3(() => {
1263
1491
  let mounted = true;
@@ -1394,9 +1622,9 @@ var TerminalPanel = ({
1394
1622
  setScrollPosition(position);
1395
1623
  isScrollLockedRef.current = position.isScrollLocked;
1396
1624
  }, []);
1397
- const sessionInfo = sessionId ? getTerminalSession(context, sessionId) : undefined;
1625
+ const sessionInfo = sessionId ? getTerminalSession(context2, sessionId) : undefined;
1398
1626
  if (error) {
1399
- return /* @__PURE__ */ jsxs4("div", {
1627
+ return /* @__PURE__ */ jsxs5("div", {
1400
1628
  style: {
1401
1629
  padding: "20px",
1402
1630
  color: "#ef4444",
@@ -1409,11 +1637,11 @@ var TerminalPanel = ({
1409
1637
  gap: "10px"
1410
1638
  },
1411
1639
  children: [
1412
- /* @__PURE__ */ jsx5("div", {
1640
+ /* @__PURE__ */ jsx6("div", {
1413
1641
  style: { fontSize: "16px", fontWeight: "bold" },
1414
1642
  children: "Terminal Error"
1415
1643
  }),
1416
- /* @__PURE__ */ jsx5("div", {
1644
+ /* @__PURE__ */ jsx6("div", {
1417
1645
  style: { fontSize: "14px", opacity: 0.8 },
1418
1646
  children: error
1419
1647
  })
@@ -1421,7 +1649,7 @@ var TerminalPanel = ({
1421
1649
  });
1422
1650
  }
1423
1651
  if (isInitializing || !sessionId) {
1424
- return /* @__PURE__ */ jsx5("div", {
1652
+ return /* @__PURE__ */ jsx6("div", {
1425
1653
  style: {
1426
1654
  padding: "20px",
1427
1655
  color: "#a0a0a0",
@@ -1447,10 +1675,10 @@ var TerminalPanel = ({
1447
1675
  terminalRef.current?.scrollToBottom();
1448
1676
  }
1449
1677
  };
1450
- return /* @__PURE__ */ jsxs4("div", {
1678
+ return /* @__PURE__ */ jsxs5("div", {
1451
1679
  style: { height: "100%", width: "100%", display: "flex", flexDirection: "column" },
1452
1680
  children: [
1453
- /* @__PURE__ */ jsxs4("div", {
1681
+ /* @__PURE__ */ jsxs5("div", {
1454
1682
  style: {
1455
1683
  display: "flex",
1456
1684
  gap: "8px",
@@ -1460,7 +1688,7 @@ var TerminalPanel = ({
1460
1688
  alignItems: "center"
1461
1689
  },
1462
1690
  children: [
1463
- /* @__PURE__ */ jsxs4("span", {
1691
+ /* @__PURE__ */ jsxs5("span", {
1464
1692
  style: {
1465
1693
  fontSize: "12px",
1466
1694
  color: theme.colors.textSecondary,
@@ -1473,7 +1701,7 @@ var TerminalPanel = ({
1473
1701
  sessionInfo?.shell
1474
1702
  ]
1475
1703
  }),
1476
- /* @__PURE__ */ jsxs4("button", {
1704
+ /* @__PURE__ */ jsxs5("button", {
1477
1705
  onClick: handleToggleScrollLock,
1478
1706
  style: {
1479
1707
  display: "flex",
@@ -1492,17 +1720,17 @@ var TerminalPanel = ({
1492
1720
  onMouseLeave: (e) => e.currentTarget.style.opacity = "1",
1493
1721
  title: scrollPosition.isScrollLocked ? "Click to unlock scroll" : "Click to lock scroll to bottom",
1494
1722
  children: [
1495
- scrollPosition.isScrollLocked ? /* @__PURE__ */ jsx5(Lock, {
1723
+ scrollPosition.isScrollLocked ? /* @__PURE__ */ jsx6(Lock, {
1496
1724
  size: 12
1497
- }) : /* @__PURE__ */ jsx5(Unlock, {
1725
+ }) : /* @__PURE__ */ jsx6(Unlock, {
1498
1726
  size: 12
1499
1727
  }),
1500
- /* @__PURE__ */ jsx5("span", {
1728
+ /* @__PURE__ */ jsx6("span", {
1501
1729
  children: scrollPosition.isScrollLocked ? "Locked" : "Unlocked"
1502
1730
  })
1503
1731
  ]
1504
1732
  }),
1505
- /* @__PURE__ */ jsxs4("button", {
1733
+ /* @__PURE__ */ jsxs5("button", {
1506
1734
  onClick: handleScrollToBottom,
1507
1735
  disabled: scrollPosition.isAtBottom,
1508
1736
  style: {
@@ -1523,19 +1751,19 @@ var TerminalPanel = ({
1523
1751
  onMouseLeave: (e) => !scrollPosition.isAtBottom && (e.currentTarget.style.opacity = "1"),
1524
1752
  title: "Scroll to bottom and lock",
1525
1753
  children: [
1526
- /* @__PURE__ */ jsx5(ArrowDown, {
1754
+ /* @__PURE__ */ jsx6(ArrowDown, {
1527
1755
  size: 12
1528
1756
  }),
1529
- /* @__PURE__ */ jsx5("span", {
1757
+ /* @__PURE__ */ jsx6("span", {
1530
1758
  children: "Bottom"
1531
1759
  })
1532
1760
  ]
1533
1761
  })
1534
1762
  ]
1535
1763
  }),
1536
- /* @__PURE__ */ jsx5("div", {
1764
+ /* @__PURE__ */ jsx6("div", {
1537
1765
  style: { flex: 1 },
1538
- children: /* @__PURE__ */ jsx5(ThemedTerminalWithProvider, {
1766
+ children: /* @__PURE__ */ jsx6(ThemedTerminalWithProvider, {
1539
1767
  ref: terminalRef,
1540
1768
  onData: handleTerminalData,
1541
1769
  onResize: handleTerminalResize,
@@ -1554,16 +1782,16 @@ var TerminalPanel = ({
1554
1782
  };
1555
1783
  // src/panels/TabbedTerminalPanel.tsx
1556
1784
  import { useTheme as useTheme6 } from "@principal-ade/industry-theme";
1557
- import { Terminal as TerminalIcon2, Lock as Lock2, Unlock as Unlock2, Box, Boxes } from "lucide-react";
1785
+ import { Terminal as TerminalIcon2, Lock as Lock2, Unlock as Unlock2, Box, Boxes, Loader2 } from "lucide-react";
1558
1786
  import React2, {
1559
1787
  useState as useState4,
1560
1788
  useCallback as useCallback3,
1561
1789
  useEffect as useEffect4,
1562
1790
  useRef as useRef3
1563
1791
  } from "react";
1564
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1792
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1565
1793
  function TerminalTabContentInner(props, ref) {
1566
- const { tab, sessionId, isActive, isVisible, actions, events, terminalContext, onSessionCreated, onScrollPositionChange, isForeign = false, defaultScrollLocked } = props;
1794
+ const { tab, sessionId, isActive, isVisible, actions, events, terminalContext, onSessionCreated, onScrollPositionChange, isForeign = false, defaultScrollLocked, activityDetection = true, activityTimeout = 500, autoShowBlinds = false } = props;
1567
1795
  console.log("[TerminalTabContent] RENDER", { tabId: tab.id, isActive, sessionId });
1568
1796
  const terminalRef = useRef3(null);
1569
1797
  const [localSessionId, setLocalSessionId] = useState4(sessionId);
@@ -1627,12 +1855,39 @@ function TerminalTabContentInner(props, ref) {
1627
1855
  });
1628
1856
  if (!mounted)
1629
1857
  return;
1858
+ const tracer = getTracer();
1859
+ const span = tracer.startSpan("terminal.session", {
1860
+ attributes: {
1861
+ "session.id": newSessionId,
1862
+ "session.cwd": tab.directory,
1863
+ "session.context": `${terminalContext}:${tab.id}`
1864
+ }
1865
+ });
1866
+ span.addEvent("terminal.session.created", {
1867
+ "session.id": newSessionId,
1868
+ "session.cwd": tab.directory
1869
+ });
1870
+ span.setStatus({ code: SpanStatusCode.OK });
1871
+ span.end();
1630
1872
  setLocalSessionId(newSessionId);
1631
1873
  setIsInitialized(true);
1632
1874
  onSessionCreated(tab.id, newSessionId);
1633
1875
  await claimAndConnect(newSessionId);
1634
1876
  } catch (error) {
1635
1877
  console.error("[TerminalTabContent] Failed to create session:", error);
1878
+ const tracer = getTracer();
1879
+ const span = tracer.startSpan("terminal.session", {
1880
+ attributes: {
1881
+ "session.action": "create",
1882
+ "error.occurred": true
1883
+ }
1884
+ });
1885
+ span.addEvent("terminal.session.error", {
1886
+ "error.message": error instanceof Error ? error.message : "Unknown error"
1887
+ });
1888
+ span.recordException(error);
1889
+ span.setStatus({ code: SpanStatusCode.ERROR, message: "Session creation failed" });
1890
+ span.end();
1636
1891
  }
1637
1892
  };
1638
1893
  initSession();
@@ -1731,6 +1986,20 @@ function TerminalTabContentInner(props, ref) {
1731
1986
  });
1732
1987
  }
1733
1988
  }, [localSessionId, events]);
1989
+ const handleActivityChange = useCallback3((state) => {
1990
+ if (localSessionId) {
1991
+ events.emit({
1992
+ type: "terminal:activity-changed",
1993
+ source: "TabbedTerminalPanel",
1994
+ timestamp: Date.now(),
1995
+ payload: {
1996
+ sessionId: localSessionId,
1997
+ activityType: state.isActive ? "started" : "stopped",
1998
+ isWorking: state.isActive
1999
+ }
2000
+ });
2001
+ }
2002
+ }, [localSessionId, events]);
1734
2003
  const handleScrollToBottom = useCallback3(() => {
1735
2004
  terminalRef.current?.scrollToBottom();
1736
2005
  }, []);
@@ -1749,7 +2018,7 @@ function TerminalTabContentInner(props, ref) {
1749
2018
  toggleScrollLock: handleToggleScrollLock
1750
2019
  }), [handleScrollToBottom, handleToggleScrollLock]);
1751
2020
  if (!isInitialized) {
1752
- return /* @__PURE__ */ jsx6("div", {
2021
+ return /* @__PURE__ */ jsx7("div", {
1753
2022
  style: {
1754
2023
  display: isActive ? "flex" : "none",
1755
2024
  height: "100%",
@@ -1772,14 +2041,14 @@ function TerminalTabContentInner(props, ref) {
1772
2041
  ],
1773
2042
  opacity: 1
1774
2043
  } : undefined;
1775
- return /* @__PURE__ */ jsx6("div", {
2044
+ return /* @__PURE__ */ jsx7("div", {
1776
2045
  style: {
1777
2046
  display: isActive ? "flex" : "none",
1778
2047
  flexDirection: "column",
1779
2048
  height: "100%",
1780
2049
  width: "100%"
1781
2050
  },
1782
- children: /* @__PURE__ */ jsx6(ThemedTerminalWithProvider, {
2051
+ children: /* @__PURE__ */ jsx7(ThemedTerminalWithProvider, {
1783
2052
  ref: terminalRef,
1784
2053
  onData: shouldRenderTerminal ? handleData : undefined,
1785
2054
  onResize: shouldRenderTerminal ? handleResize : undefined,
@@ -1795,6 +2064,10 @@ function TerminalTabContentInner(props, ref) {
1795
2064
  cursorBlink: shouldRenderTerminal,
1796
2065
  scrollback: 1e4,
1797
2066
  enableSearch: true,
2067
+ activityDetection,
2068
+ activityTimeout,
2069
+ autoShowBlinds,
2070
+ onActivityChange: shouldRenderTerminal ? handleActivityChange : undefined,
1798
2071
  enableWebLinks: true,
1799
2072
  overlayState
1800
2073
  }, shouldRenderTerminal ? "active" : "overlay")
@@ -1815,6 +2088,12 @@ var areTerminalTabContentPropsEqual = (prevProps, nextProps) => {
1815
2088
  changes.push("terminalContext");
1816
2089
  if (prevProps.isForeign !== nextProps.isForeign)
1817
2090
  changes.push("isForeign");
2091
+ if (prevProps.activityDetection !== nextProps.activityDetection)
2092
+ changes.push("activityDetection");
2093
+ if (prevProps.activityTimeout !== nextProps.activityTimeout)
2094
+ changes.push("activityTimeout");
2095
+ if (prevProps.autoShowBlinds !== nextProps.autoShowBlinds)
2096
+ changes.push("autoShowBlinds");
1818
2097
  if (changes.length > 0) {
1819
2098
  console.log("[TerminalTabContent] MEMO - will re-render, props changed:", changes, { tabId: nextProps.tab.id });
1820
2099
  }
@@ -1844,7 +2123,11 @@ var TabbedTerminalPanelInner = ({
1844
2123
  activeTabId: activeTabIdProp,
1845
2124
  onActiveTabChange,
1846
2125
  requestFocusTabId,
1847
- onFocusTabHandled
2126
+ onFocusTabHandled,
2127
+ workingStates,
2128
+ activityDetection = true,
2129
+ activityTimeout = 500,
2130
+ autoShowBlinds = false
1848
2131
  }) => {
1849
2132
  console.log("[TabbedTerminalPanel] RENDER", { terminalContext, directory, width });
1850
2133
  const { theme } = useTheme6();
@@ -2051,8 +2334,8 @@ var TabbedTerminalPanelInner = ({
2051
2334
  useEffect4(() => {
2052
2335
  const handleSessionCreated2 = (event) => {
2053
2336
  const customEvent = event;
2054
- const { context } = customEvent.detail || {};
2055
- if (context && context.startsWith(terminalContext)) {
2337
+ const { context: context2 } = customEvent.detail || {};
2338
+ if (context2 && context2.startsWith(terminalContext)) {
2056
2339
  console.log("[TabbedTerminalPanel] External session created, restoring owned sessions...");
2057
2340
  restoreOwnedSessions();
2058
2341
  }
@@ -2099,8 +2382,34 @@ var TabbedTerminalPanelInner = ({
2099
2382
  if (!isForeign && sessionId && actions.destroyTerminalSession) {
2100
2383
  try {
2101
2384
  await actions.destroyTerminalSession(sessionId);
2385
+ const tracer = getTracer();
2386
+ const span = tracer.startSpan("terminal.session", {
2387
+ attributes: {
2388
+ "session.id": sessionId,
2389
+ "session.action": "destroyed"
2390
+ }
2391
+ });
2392
+ span.addEvent("terminal.session.destroyed", {
2393
+ "session.id": sessionId
2394
+ });
2395
+ span.setStatus({ code: SpanStatusCode.OK });
2396
+ span.end();
2102
2397
  } catch (err) {
2103
2398
  console.error("[TabbedTerminalPanel] Failed to destroy session:", err);
2399
+ const tracer = getTracer();
2400
+ const span = tracer.startSpan("terminal.session", {
2401
+ attributes: {
2402
+ "session.id": sessionId,
2403
+ "session.action": "destroy",
2404
+ "error.occurred": true
2405
+ }
2406
+ });
2407
+ span.addEvent("terminal.session.error", {
2408
+ "error.message": err instanceof Error ? err.message : "Unknown error"
2409
+ });
2410
+ span.recordException(err);
2411
+ span.setStatus({ code: SpanStatusCode.ERROR, message: "Session destruction failed" });
2412
+ span.end();
2104
2413
  }
2105
2414
  }
2106
2415
  setSessionIds((prev) => {
@@ -2161,42 +2470,67 @@ var TabbedTerminalPanelInner = ({
2161
2470
  }
2162
2471
  });
2163
2472
  const renderTabAccessory = useCallback3((tab) => {
2164
- if (tab.id !== activeTabId)
2473
+ const tabSessionId = sessionIds.get(tab.id);
2474
+ const isWorking = tabSessionId ? workingStates?.[tabSessionId]?.isWorking : false;
2475
+ const isActive = tab.id === activeTabId;
2476
+ if (!isActive && !isWorking)
2165
2477
  return null;
2166
2478
  const scrollPosition = scrollPositions.get(tab.id) ?? defaultScrollPosition;
2167
- return /* @__PURE__ */ jsx6("button", {
2168
- onClick: (e) => {
2169
- e.stopPropagation();
2170
- handleToggleScrollLock();
2171
- },
2172
- style: {
2173
- display: "flex",
2174
- alignItems: "center",
2175
- justifyContent: "center",
2176
- width: "16px",
2177
- height: "16px",
2178
- borderRadius: "3px",
2179
- border: "none",
2180
- backgroundColor: "transparent",
2181
- cursor: "pointer",
2182
- color: scrollPosition.isScrollLocked ? theme.colors.success : theme.colors.warning,
2183
- padding: 0
2184
- },
2185
- onMouseEnter: (e) => {
2186
- e.currentTarget.style.backgroundColor = theme.colors.backgroundTertiary;
2187
- },
2188
- onMouseLeave: (e) => {
2189
- e.currentTarget.style.backgroundColor = "transparent";
2190
- },
2191
- title: scrollPosition.isScrollLocked ? "Scroll locked" : "Scroll unlocked",
2192
- children: scrollPosition.isScrollLocked ? /* @__PURE__ */ jsx6(Lock2, {
2193
- size: 10
2194
- }) : /* @__PURE__ */ jsx6(Unlock2, {
2195
- size: 10
2196
- })
2479
+ return /* @__PURE__ */ jsxs6("div", {
2480
+ style: { display: "flex", alignItems: "center", gap: "4px" },
2481
+ children: [
2482
+ isWorking && /* @__PURE__ */ jsx7("div", {
2483
+ style: {
2484
+ display: "flex",
2485
+ alignItems: "center",
2486
+ justifyContent: "center",
2487
+ width: "16px",
2488
+ height: "16px",
2489
+ color: theme.colors.primary
2490
+ },
2491
+ title: "Agent working",
2492
+ children: /* @__PURE__ */ jsx7(Loader2, {
2493
+ size: 12,
2494
+ style: {
2495
+ animation: "spin 1s linear infinite"
2496
+ }
2497
+ })
2498
+ }),
2499
+ isActive && /* @__PURE__ */ jsx7("button", {
2500
+ onClick: (e) => {
2501
+ e.stopPropagation();
2502
+ handleToggleScrollLock();
2503
+ },
2504
+ style: {
2505
+ display: "flex",
2506
+ alignItems: "center",
2507
+ justifyContent: "center",
2508
+ width: "16px",
2509
+ height: "16px",
2510
+ borderRadius: "3px",
2511
+ border: "none",
2512
+ backgroundColor: "transparent",
2513
+ cursor: "pointer",
2514
+ color: scrollPosition.isScrollLocked ? theme.colors.success : theme.colors.warning,
2515
+ padding: 0
2516
+ },
2517
+ onMouseEnter: (e) => {
2518
+ e.currentTarget.style.backgroundColor = theme.colors.backgroundTertiary;
2519
+ },
2520
+ onMouseLeave: (e) => {
2521
+ e.currentTarget.style.backgroundColor = "transparent";
2522
+ },
2523
+ title: scrollPosition.isScrollLocked ? "Scroll locked" : "Scroll unlocked",
2524
+ children: scrollPosition.isScrollLocked ? /* @__PURE__ */ jsx7(Lock2, {
2525
+ size: 10
2526
+ }) : /* @__PURE__ */ jsx7(Unlock2, {
2527
+ size: 10
2528
+ })
2529
+ })
2530
+ ]
2197
2531
  });
2198
- }, [activeTabId, scrollPositions, defaultScrollPosition, handleToggleScrollLock, theme]);
2199
- return /* @__PURE__ */ jsxs5("div", {
2532
+ }, [activeTabId, scrollPositions, defaultScrollPosition, handleToggleScrollLock, theme, sessionIds, workingStates]);
2533
+ return /* @__PURE__ */ jsxs6("div", {
2200
2534
  style: {
2201
2535
  display: "flex",
2202
2536
  flexDirection: "column",
@@ -2204,15 +2538,15 @@ var TabbedTerminalPanelInner = ({
2204
2538
  backgroundColor: theme.colors.background
2205
2539
  },
2206
2540
  children: [
2207
- !hideHeader && /* @__PURE__ */ jsx6("div", {
2541
+ !hideHeader && /* @__PURE__ */ jsx7("div", {
2208
2542
  ref: headerRef,
2209
- children: /* @__PURE__ */ jsx6(TabBar, {
2543
+ children: /* @__PURE__ */ jsx7(TabBar, {
2210
2544
  tabs: genericTabs,
2211
2545
  activeTabId,
2212
2546
  onTabClick: switchTab,
2213
2547
  onTabClose: closeTab,
2214
2548
  onNewTab: addNewTab,
2215
- leftSection: /* @__PURE__ */ jsx6("button", {
2549
+ leftSection: /* @__PURE__ */ jsx7("button", {
2216
2550
  onClick: () => onShowAllTerminalsChange?.(!showAllTerminals),
2217
2551
  style: {
2218
2552
  display: "flex",
@@ -2237,9 +2571,9 @@ var TabbedTerminalPanelInner = ({
2237
2571
  }
2238
2572
  },
2239
2573
  title: showAllTerminals ? "Showing all terminals (click to filter by context)" : "Show all terminals",
2240
- children: showAllTerminals ? /* @__PURE__ */ jsx6(Boxes, {
2574
+ children: showAllTerminals ? /* @__PURE__ */ jsx7(Boxes, {
2241
2575
  size: 14
2242
- }) : /* @__PURE__ */ jsx6(Box, {
2576
+ }) : /* @__PURE__ */ jsx7(Box, {
2243
2577
  size: 14
2244
2578
  })
2245
2579
  }),
@@ -2249,7 +2583,7 @@ var TabbedTerminalPanelInner = ({
2249
2583
  showKeyboardHints: false
2250
2584
  })
2251
2585
  }),
2252
- /* @__PURE__ */ jsxs5("div", {
2586
+ /* @__PURE__ */ jsxs6("div", {
2253
2587
  style: {
2254
2588
  flex: 1,
2255
2589
  display: "flex",
@@ -2265,7 +2599,7 @@ var TabbedTerminalPanelInner = ({
2265
2599
  if (renderTabContent) {
2266
2600
  const customContent = renderTabContent(tab, isActive, sessionId, width);
2267
2601
  if (customContent === null && tab.contentType === "terminal") {
2268
- return /* @__PURE__ */ jsx6(TerminalTabContent, {
2602
+ return /* @__PURE__ */ jsx7(TerminalTabContent, {
2269
2603
  ref: getRefCallback(tab.id),
2270
2604
  tab,
2271
2605
  sessionId,
@@ -2277,10 +2611,13 @@ var TabbedTerminalPanelInner = ({
2277
2611
  onSessionCreated: handleSessionCreated,
2278
2612
  onScrollPositionChange: handleTabScrollPositionChange,
2279
2613
  isForeign: tab.id.startsWith("tab-foreign-"),
2280
- defaultScrollLocked
2614
+ defaultScrollLocked,
2615
+ activityDetection,
2616
+ activityTimeout,
2617
+ autoShowBlinds
2281
2618
  }, tab.id);
2282
2619
  }
2283
- return /* @__PURE__ */ jsx6("div", {
2620
+ return /* @__PURE__ */ jsx7("div", {
2284
2621
  style: {
2285
2622
  display: isActive ? "flex" : "none",
2286
2623
  flexDirection: "column",
@@ -2291,7 +2628,7 @@ var TabbedTerminalPanelInner = ({
2291
2628
  }, tab.id);
2292
2629
  }
2293
2630
  if (tab.contentType === "terminal") {
2294
- return /* @__PURE__ */ jsx6(TerminalTabContent, {
2631
+ return /* @__PURE__ */ jsx7(TerminalTabContent, {
2295
2632
  ref: getRefCallback(tab.id),
2296
2633
  tab,
2297
2634
  sessionId,
@@ -2303,10 +2640,13 @@ var TabbedTerminalPanelInner = ({
2303
2640
  onSessionCreated: handleSessionCreated,
2304
2641
  onScrollPositionChange: handleTabScrollPositionChange,
2305
2642
  isForeign: tab.id.startsWith("tab-foreign-"),
2306
- defaultScrollLocked
2643
+ defaultScrollLocked,
2644
+ activityDetection,
2645
+ activityTimeout,
2646
+ autoShowBlinds
2307
2647
  }, tab.id);
2308
2648
  }
2309
- return /* @__PURE__ */ jsxs5("div", {
2649
+ return /* @__PURE__ */ jsxs6("div", {
2310
2650
  style: {
2311
2651
  display: isActive ? "flex" : "none",
2312
2652
  alignItems: "center",
@@ -2315,20 +2655,20 @@ var TabbedTerminalPanelInner = ({
2315
2655
  color: theme.colors.textSecondary
2316
2656
  },
2317
2657
  children: [
2318
- /* @__PURE__ */ jsxs5("p", {
2658
+ /* @__PURE__ */ jsxs6("p", {
2319
2659
  children: [
2320
2660
  "Unknown content type: ",
2321
2661
  tab.contentType
2322
2662
  ]
2323
2663
  }),
2324
- /* @__PURE__ */ jsx6("p", {
2664
+ /* @__PURE__ */ jsx7("p", {
2325
2665
  style: { fontSize: theme.fontSizes[0], marginTop: "8px" },
2326
2666
  children: "Provide a renderTabContent prop to render custom tab types"
2327
2667
  })
2328
2668
  ]
2329
2669
  }, tab.id);
2330
2670
  }),
2331
- tabs.length === 0 && /* @__PURE__ */ jsxs5("div", {
2671
+ tabs.length === 0 && /* @__PURE__ */ jsxs6("div", {
2332
2672
  style: {
2333
2673
  display: "flex",
2334
2674
  flexDirection: "column",
@@ -2338,14 +2678,14 @@ var TabbedTerminalPanelInner = ({
2338
2678
  color: theme.colors.textSecondary
2339
2679
  },
2340
2680
  children: [
2341
- /* @__PURE__ */ jsx6(TerminalIcon2, {
2681
+ /* @__PURE__ */ jsx7(TerminalIcon2, {
2342
2682
  size: 32,
2343
2683
  style: { opacity: 0.5, marginBottom: "16px" }
2344
2684
  }),
2345
- /* @__PURE__ */ jsx6("p", {
2685
+ /* @__PURE__ */ jsx7("p", {
2346
2686
  children: "No terminal sessions"
2347
2687
  }),
2348
- /* @__PURE__ */ jsx6("button", {
2688
+ /* @__PURE__ */ jsx7("button", {
2349
2689
  onClick: () => addNewTab(),
2350
2690
  style: {
2351
2691
  marginTop: "16px",
@@ -2402,6 +2742,14 @@ var TabbedTerminalPanelMemoized = React2.memo(TabbedTerminalPanelInner, (prevPro
2402
2742
  changes.push("activeTabId");
2403
2743
  if (prevProps.onActiveTabChange !== nextProps.onActiveTabChange)
2404
2744
  changes.push("onActiveTabChange");
2745
+ if (prevProps.workingStates !== nextProps.workingStates)
2746
+ changes.push("workingStates");
2747
+ if (prevProps.activityDetection !== nextProps.activityDetection)
2748
+ changes.push("activityDetection");
2749
+ if (prevProps.activityTimeout !== nextProps.activityTimeout)
2750
+ changes.push("activityTimeout");
2751
+ if (prevProps.autoShowBlinds !== nextProps.autoShowBlinds)
2752
+ changes.push("autoShowBlinds");
2405
2753
  const ignoredChanges = [];
2406
2754
  if (prevProps.context !== nextProps.context)
2407
2755
  ignoredChanges.push("context");
@@ -2597,8 +2945,11 @@ var onPackageUnload = async () => {
2597
2945
  };
2598
2946
  export {
2599
2947
  writeToTerminalTool,
2948
+ withSpanSync,
2949
+ withSpan,
2600
2950
  useThemedTerminal,
2601
2951
  useTabKeyboardShortcuts,
2952
+ trace,
2602
2953
  terminalPanelToolsMetadata,
2603
2954
  terminalPanelTools,
2604
2955
  panels,
@@ -2607,21 +2958,28 @@ export {
2607
2958
  isTerminalLoading,
2608
2959
  isTabOfType,
2609
2960
  getWorkspacePath,
2961
+ getTracer,
2610
2962
  getTerminalSlice,
2611
2963
  getTerminalSessions,
2612
2964
  getTerminalSession,
2613
2965
  getTerminalDirectory,
2614
2966
  getTerminalCSSVariables,
2615
2967
  getRepositoryPath,
2968
+ getActiveSpan,
2616
2969
  focusTerminalTool,
2617
2970
  createTerminalTheme,
2618
2971
  createTerminalSessionTool,
2972
+ context,
2619
2973
  closeTerminalSessionTool,
2620
2974
  clearTerminalTool,
2975
+ WorkingOverlay,
2621
2976
  ThemedTerminalWithProvider,
2622
2977
  ThemedTerminal,
2623
2978
  TerminalPanel,
2624
2979
  TabbedTerminalPanel,
2625
2980
  TabButton,
2626
- TabBar
2981
+ TabBar,
2982
+ TRACER_VERSION,
2983
+ TRACER_NAME,
2984
+ SpanStatusCode
2627
2985
  };