claude-code-workflow 7.2.19 → 7.2.20

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 (196) hide show
  1. package/.claude/commands/workflow/analyze-with-file.md +33 -8
  2. package/.codex/skills/analyze-with-file/SKILL.md +55 -8
  3. package/ccw/frontend/dist/assets/{AlertDialog-zDuLRyN3.js → AlertDialog-Cukb0xv2.js} +2 -2
  4. package/ccw/frontend/dist/assets/{AlertDialog-zDuLRyN3.js.map → AlertDialog-Cukb0xv2.js.map} +1 -1
  5. package/ccw/frontend/dist/assets/{AnalysisPage-DGCGwIZY.js → AnalysisPage-Ddmv0J4x.js} +2 -2
  6. package/ccw/frontend/dist/assets/{AnalysisPage-DGCGwIZY.js.map → AnalysisPage-Ddmv0J4x.js.map} +1 -1
  7. package/ccw/frontend/dist/assets/{ApiSettingsPage-CgclCqmv.js → ApiSettingsPage-DMkrTZDX.js} +2 -2
  8. package/ccw/frontend/dist/assets/{ApiSettingsPage-CgclCqmv.js.map → ApiSettingsPage-DMkrTZDX.js.map} +1 -1
  9. package/ccw/frontend/dist/assets/{CliModeToggle-CbGH7qO4.js → CliModeToggle-DXenjpbe.js} +2 -2
  10. package/ccw/frontend/dist/assets/{CliModeToggle-CbGH7qO4.js.map → CliModeToggle-DXenjpbe.js.map} +1 -1
  11. package/ccw/frontend/dist/assets/{CliSessionSharePage-CJGlwyDw.js → CliSessionSharePage-B-ZIMqmX.js} +2 -2
  12. package/ccw/frontend/dist/assets/{CliSessionSharePage-CJGlwyDw.js.map → CliSessionSharePage-B-ZIMqmX.js.map} +1 -1
  13. package/ccw/frontend/dist/assets/{CliViewerPage-D-MHYyDt.js → CliViewerPage-9YxGyLxh.js} +2 -2
  14. package/ccw/frontend/dist/assets/{CliViewerPage-D-MHYyDt.js.map → CliViewerPage-9YxGyLxh.js.map} +1 -1
  15. package/ccw/frontend/dist/assets/{CodexLensPage-z6miX68P.js → CodexLensPage-B_uv5wdn.js} +2 -2
  16. package/ccw/frontend/dist/assets/{CodexLensPage-z6miX68P.js.map → CodexLensPage-B_uv5wdn.js.map} +1 -1
  17. package/ccw/frontend/dist/assets/{Collapsible-D5zS2wef.js → Collapsible-C2qk3yV0.js} +2 -2
  18. package/ccw/frontend/dist/assets/{Collapsible-D5zS2wef.js.map → Collapsible-C2qk3yV0.js.map} +1 -1
  19. package/ccw/frontend/dist/assets/{CommandsManagerPage-ChcTwmAn.js → CommandsManagerPage-DBtaWxLB.js} +2 -2
  20. package/ccw/frontend/dist/assets/{CommandsManagerPage-ChcTwmAn.js.map → CommandsManagerPage-DBtaWxLB.js.map} +1 -1
  21. package/ccw/frontend/dist/assets/{DeepWikiPage-Cv5LifSi.js → DeepWikiPage-d9K4_TgG.js} +2 -2
  22. package/ccw/frontend/dist/assets/{DeepWikiPage-Cv5LifSi.js.map → DeepWikiPage-d9K4_TgG.js.map} +1 -1
  23. package/ccw/frontend/dist/assets/{EndpointsPage-BcyNmqIa.js → EndpointsPage-DhW6hYrI.js} +2 -2
  24. package/ccw/frontend/dist/assets/{EndpointsPage-BcyNmqIa.js.map → EndpointsPage-DhW6hYrI.js.map} +1 -1
  25. package/ccw/frontend/dist/assets/{ExplorerPage-DfHtqeQM.js → ExplorerPage-DYYpCvtB.js} +2 -2
  26. package/ccw/frontend/dist/assets/{ExplorerPage-DfHtqeQM.js.map → ExplorerPage-DYYpCvtB.js.map} +1 -1
  27. package/ccw/frontend/dist/assets/{FixSessionPage-CbvZApeF.js → FixSessionPage-CSmiT5SE.js} +2 -2
  28. package/ccw/frontend/dist/assets/{FixSessionPage-CbvZApeF.js.map → FixSessionPage-CSmiT5SE.js.map} +1 -1
  29. package/ccw/frontend/dist/assets/{FloatingFileBrowser-DLz85cw9.js → FloatingFileBrowser-DvMsXLdP.js} +2 -2
  30. package/ccw/frontend/dist/assets/{FloatingFileBrowser-DLz85cw9.js.map → FloatingFileBrowser-DvMsXLdP.js.map} +1 -1
  31. package/ccw/frontend/dist/assets/{FloatingPanel-DrUTmgtV.js → FloatingPanel-sqezhSI8.js} +2 -2
  32. package/ccw/frontend/dist/assets/{FloatingPanel-DrUTmgtV.js.map → FloatingPanel-sqezhSI8.js.map} +1 -1
  33. package/ccw/frontend/dist/assets/{GraphExplorerPage-C439yLvH.js → GraphExplorerPage-DS8ghMFM.js} +2 -2
  34. package/ccw/frontend/dist/assets/{GraphExplorerPage-C439yLvH.js.map → GraphExplorerPage-DS8ghMFM.js.map} +1 -1
  35. package/ccw/frontend/dist/assets/{HistoryPage-BClJJMEy.js → HistoryPage-B-x1RyHu.js} +2 -2
  36. package/ccw/frontend/dist/assets/{HistoryPage-BClJJMEy.js.map → HistoryPage-B-x1RyHu.js.map} +1 -1
  37. package/ccw/frontend/dist/assets/{HookManagerPage-DI-2QDLJ.js → HookManagerPage-BbxpDb68.js} +2 -2
  38. package/ccw/frontend/dist/assets/{HookManagerPage-DI-2QDLJ.js.map → HookManagerPage-BbxpDb68.js.map} +1 -1
  39. package/ccw/frontend/dist/assets/{InstallationsPage-DKlz1ypL.js → InstallationsPage-3bShz_Ai.js} +2 -2
  40. package/ccw/frontend/dist/assets/{InstallationsPage-DKlz1ypL.js.map → InstallationsPage-3bShz_Ai.js.map} +1 -1
  41. package/ccw/frontend/dist/assets/{IssueHubPage--6DduN4j.js → IssueHubPage-BQY_Hh3e.js} +2 -2
  42. package/ccw/frontend/dist/assets/{IssueHubPage--6DduN4j.js.map → IssueHubPage-BQY_Hh3e.js.map} +1 -1
  43. package/ccw/frontend/dist/assets/{LiteTasksPage-39j6xEeL.js → LiteTasksPage-vD_8fQcR.js} +2 -2
  44. package/ccw/frontend/dist/assets/{LiteTasksPage-39j6xEeL.js.map → LiteTasksPage-vD_8fQcR.js.map} +1 -1
  45. package/ccw/frontend/dist/assets/{McpManagerPage-D00C9RVN.js → McpManagerPage-CI5ZzB8A.js} +2 -2
  46. package/ccw/frontend/dist/assets/{McpManagerPage-D00C9RVN.js.map → McpManagerPage-CI5ZzB8A.js.map} +1 -1
  47. package/ccw/frontend/dist/assets/{MemoryPage-BXWKdTyM.js → MemoryPage-CNuj2eNg.js} +2 -2
  48. package/ccw/frontend/dist/assets/{MemoryPage-BXWKdTyM.js.map → MemoryPage-CNuj2eNg.js.map} +1 -1
  49. package/ccw/frontend/dist/assets/{NotFoundPage-h5o3I7cF.js → NotFoundPage-BrnAXkb1.js} +2 -2
  50. package/ccw/frontend/dist/assets/{NotFoundPage-h5o3I7cF.js.map → NotFoundPage-BrnAXkb1.js.map} +1 -1
  51. package/ccw/frontend/dist/assets/{OrchestratorPage-jkyjmiI1.js → OrchestratorPage-CH81PGt4.js} +2 -2
  52. package/ccw/frontend/dist/assets/{OrchestratorPage-jkyjmiI1.js.map → OrchestratorPage-CH81PGt4.js.map} +1 -1
  53. package/ccw/frontend/dist/assets/{ProjectOverviewPage-C2bE5eb2.js → ProjectOverviewPage-dwiEXl2O.js} +2 -2
  54. package/ccw/frontend/dist/assets/{ProjectOverviewPage-C2bE5eb2.js.map → ProjectOverviewPage-dwiEXl2O.js.map} +1 -1
  55. package/ccw/frontend/dist/assets/{PromptHistoryPage-DzmPK4GZ.js → PromptHistoryPage-CabgLjJU.js} +2 -2
  56. package/ccw/frontend/dist/assets/{PromptHistoryPage-DzmPK4GZ.js.map → PromptHistoryPage-CabgLjJU.js.map} +1 -1
  57. package/ccw/frontend/dist/assets/{ReviewSessionPage-CVMH1K6G.js → ReviewSessionPage-DAMrNFn8.js} +2 -2
  58. package/ccw/frontend/dist/assets/{ReviewSessionPage-CVMH1K6G.js.map → ReviewSessionPage-DAMrNFn8.js.map} +1 -1
  59. package/ccw/frontend/dist/assets/{RulesManagerPage-BDZco-r2.js → RulesManagerPage-4jzmxPn0.js} +2 -2
  60. package/ccw/frontend/dist/assets/{RulesManagerPage-BDZco-r2.js.map → RulesManagerPage-4jzmxPn0.js.map} +1 -1
  61. package/ccw/frontend/dist/assets/{SessionDetailPage-D5cM-8Kk.js → SessionDetailPage-C5Btktmp.js} +2 -2
  62. package/ccw/frontend/dist/assets/{SessionDetailPage-D5cM-8Kk.js.map → SessionDetailPage-C5Btktmp.js.map} +1 -1
  63. package/ccw/frontend/dist/assets/{SessionsPage-BFy74ye3.js → SessionsPage-CQIB4E8m.js} +2 -2
  64. package/ccw/frontend/dist/assets/{SessionsPage-BFy74ye3.js.map → SessionsPage-CQIB4E8m.js.map} +1 -1
  65. package/ccw/frontend/dist/assets/SettingsPage-Yi9UAfm7.js +150 -0
  66. package/ccw/frontend/dist/assets/SettingsPage-Yi9UAfm7.js.map +1 -0
  67. package/ccw/frontend/dist/assets/{SkillsManagerPage-8Dsq4AUD.js → SkillsManagerPage-BqfvYSkT.js} +2 -2
  68. package/ccw/frontend/dist/assets/{SkillsManagerPage-8Dsq4AUD.js.map → SkillsManagerPage-BqfvYSkT.js.map} +1 -1
  69. package/ccw/frontend/dist/assets/{SpecsSettingsPage-CG77iAYQ.js → SpecsSettingsPage-BdVPM5R6.js} +2 -2
  70. package/ccw/frontend/dist/assets/{SpecsSettingsPage-CG77iAYQ.js.map → SpecsSettingsPage-BdVPM5R6.js.map} +1 -1
  71. package/ccw/frontend/dist/assets/{Switch-BbuvVsX-.js → Switch-BG929kV0.js} +2 -2
  72. package/ccw/frontend/dist/assets/{Switch-BbuvVsX-.js.map → Switch-BG929kV0.js.map} +1 -1
  73. package/ccw/frontend/dist/assets/{TabsNavigation-SGJhC8-P.js → TabsNavigation-Bol1y09b.js} +2 -2
  74. package/ccw/frontend/dist/assets/{TabsNavigation-SGJhC8-P.js.map → TabsNavigation-Bol1y09b.js.map} +1 -1
  75. package/ccw/frontend/dist/assets/{TaskDrawer-p51jeScU.js → TaskDrawer-Dwutrn8_.js} +2 -2
  76. package/ccw/frontend/dist/assets/{TaskDrawer-p51jeScU.js.map → TaskDrawer-Dwutrn8_.js.map} +1 -1
  77. package/ccw/frontend/dist/assets/{TeamPage-CvZBThbr.js → TeamPage-CpCSwpxD.js} +2 -2
  78. package/ccw/frontend/dist/assets/{TeamPage-CvZBThbr.js.map → TeamPage-CpCSwpxD.js.map} +1 -1
  79. package/ccw/frontend/dist/assets/{TerminalDashboardPage-uhM7kGKI.js → TerminalDashboardPage-DODKjOeK.js} +2 -2
  80. package/ccw/frontend/dist/assets/{TerminalDashboardPage-uhM7kGKI.js.map → TerminalDashboardPage-DODKjOeK.js.map} +1 -1
  81. package/ccw/frontend/dist/assets/{archive-D6ySrtHC.js → archive-CQw634kD.js} +2 -2
  82. package/ccw/frontend/dist/assets/{archive-D6ySrtHC.js.map → archive-CQw634kD.js.map} +1 -1
  83. package/ccw/frontend/dist/assets/{archive-restore-C1uI-5TY.js → archive-restore-B-_EG6wE.js} +2 -2
  84. package/ccw/frontend/dist/assets/{archive-restore-C1uI-5TY.js.map → archive-restore-B-_EG6wE.js.map} +1 -1
  85. package/ccw/frontend/dist/assets/{arrow-right-qE5-FMG8.js → arrow-right-CcQtxBrU.js} +2 -2
  86. package/ccw/frontend/dist/assets/{arrow-right-qE5-FMG8.js.map → arrow-right-CcQtxBrU.js.map} +1 -1
  87. package/ccw/frontend/dist/assets/{bookmark-plus-DL4iL38T.js → bookmark-plus-Cl-BbcpR.js} +2 -2
  88. package/ccw/frontend/dist/assets/{bookmark-plus-DL4iL38T.js.map → bookmark-plus-Cl-BbcpR.js.map} +1 -1
  89. package/ccw/frontend/dist/assets/{bot-CZzIeEkg.js → bot-CLSNSkW_.js} +2 -2
  90. package/ccw/frontend/dist/assets/{bot-CZzIeEkg.js.map → bot-CLSNSkW_.js.map} +1 -1
  91. package/ccw/frontend/dist/assets/{braces-MEPRT2LN.js → braces-DWwkaDS6.js} +2 -2
  92. package/ccw/frontend/dist/assets/{braces-MEPRT2LN.js.map → braces-DWwkaDS6.js.map} +1 -1
  93. package/ccw/frontend/dist/assets/{circle-stop-GQcecSUg.js → circle-stop-DiS7e6ma.js} +2 -2
  94. package/ccw/frontend/dist/assets/{circle-stop-GQcecSUg.js.map → circle-stop-DiS7e6ma.js.map} +1 -1
  95. package/ccw/frontend/dist/assets/{cpu-CzxYMs1Y.js → cpu-CuvHUVXO.js} +2 -2
  96. package/ccw/frontend/dist/assets/{cpu-CzxYMs1Y.js.map → cpu-CuvHUVXO.js.map} +1 -1
  97. package/ccw/frontend/dist/assets/{ellipsis-vertical-DZMfiFKo.js → ellipsis-vertical-BoVlINSw.js} +2 -2
  98. package/ccw/frontend/dist/assets/{ellipsis-vertical-DZMfiFKo.js.map → ellipsis-vertical-BoVlINSw.js.map} +1 -1
  99. package/ccw/frontend/dist/assets/{eye-BXfPoClW.js → eye-BEMOdcAN.js} +2 -2
  100. package/ccw/frontend/dist/assets/{eye-BXfPoClW.js.map → eye-BEMOdcAN.js.map} +1 -1
  101. package/ccw/frontend/dist/assets/{eye-off-CyaKXmAk.js → eye-off-C5HS4Ytm.js} +2 -2
  102. package/ccw/frontend/dist/assets/{eye-off-CyaKXmAk.js.map → eye-off-C5HS4Ytm.js.map} +1 -1
  103. package/ccw/frontend/dist/assets/{file-json-B4LbFfTU.js → file-json-DQ9XLq0B.js} +2 -2
  104. package/ccw/frontend/dist/assets/{file-json-B4LbFfTU.js.map → file-json-DQ9XLq0B.js.map} +1 -1
  105. package/ccw/frontend/dist/assets/{file-text-CIWG7Xgj.js → file-text-TGs_qCbw.js} +2 -2
  106. package/ccw/frontend/dist/assets/{file-text-CIWG7Xgj.js.map → file-text-TGs_qCbw.js.map} +1 -1
  107. package/ccw/frontend/dist/assets/{filter-CNBjjvBX.js → filter-CIuCqnDB.js} +2 -2
  108. package/ccw/frontend/dist/assets/{filter-CNBjjvBX.js.map → filter-CIuCqnDB.js.map} +1 -1
  109. package/ccw/frontend/dist/assets/{folder-DT_XOYw9.js → folder-BkivHBwn.js} +2 -2
  110. package/ccw/frontend/dist/assets/{folder-DT_XOYw9.js.map → folder-BkivHBwn.js.map} +1 -1
  111. package/ccw/frontend/dist/assets/{gauge-mvQWOG3S.js → gauge-CtM68fVY.js} +2 -2
  112. package/ccw/frontend/dist/assets/{gauge-mvQWOG3S.js.map → gauge-CtM68fVY.js.map} +1 -1
  113. package/ccw/frontend/dist/assets/{globe-B25jraBz.js → globe-DpnrINqP.js} +2 -2
  114. package/ccw/frontend/dist/assets/{globe-B25jraBz.js.map → globe-DpnrINqP.js.map} +1 -1
  115. package/ccw/frontend/dist/assets/{grid-3x3-CptugI_Z.js → grid-3x3-SjX0a5JH.js} +2 -2
  116. package/ccw/frontend/dist/assets/{grid-3x3-CptugI_Z.js.map → grid-3x3-SjX0a5JH.js.map} +1 -1
  117. package/ccw/frontend/dist/assets/{hard-drive-BUK9Wcoz.js → hard-drive-ByAmnoEg.js} +2 -2
  118. package/ccw/frontend/dist/assets/{hard-drive-BUK9Wcoz.js.map → hard-drive-ByAmnoEg.js.map} +1 -1
  119. package/ccw/frontend/dist/assets/{hash-dddMDYK7.js → hash-DbLc3VOZ.js} +2 -2
  120. package/ccw/frontend/dist/assets/{hash-dddMDYK7.js.map → hash-DbLc3VOZ.js.map} +1 -1
  121. package/ccw/frontend/dist/assets/{history-BdDj8MtC.js → history-Botz5Z5d.js} +2 -2
  122. package/ccw/frontend/dist/assets/{history-BdDj8MtC.js.map → history-Botz5Z5d.js.map} +1 -1
  123. package/ccw/frontend/dist/assets/{index-CcxBnbbQ.js → index-BGvyf4-9.js} +2 -2
  124. package/ccw/frontend/dist/assets/{index-CcxBnbbQ.js.map → index-BGvyf4-9.js.map} +1 -1
  125. package/ccw/frontend/dist/assets/index-BoqylFO4.css +39 -0
  126. package/ccw/frontend/dist/assets/{index-DZGHdspr.js → index-DP_mTJI8.js} +3 -3
  127. package/ccw/frontend/dist/assets/{index-DZGHdspr.js.map → index-DP_mTJI8.js.map} +1 -1
  128. package/ccw/frontend/dist/assets/{index-B6UfIzhR.js → index-MkgdhX7a.js} +2 -2
  129. package/ccw/frontend/dist/assets/{index-B6UfIzhR.js.map → index-MkgdhX7a.js.map} +1 -1
  130. package/ccw/frontend/dist/assets/{index-EFcT7h67.js → index-ni-tG9rm.js} +2 -2
  131. package/ccw/frontend/dist/assets/{index-EFcT7h67.js.map → index-ni-tG9rm.js.map} +1 -1
  132. package/ccw/frontend/dist/assets/{layout-grid-BVlT1oI7.js → layout-grid-11E4bGJz.js} +2 -2
  133. package/ccw/frontend/dist/assets/{layout-grid-BVlT1oI7.js.map → layout-grid-11E4bGJz.js.map} +1 -1
  134. package/ccw/frontend/dist/assets/{lightbulb-Mt3Tlwh4.js → lightbulb-8KrKY82b.js} +2 -2
  135. package/ccw/frontend/dist/assets/{lightbulb-Mt3Tlwh4.js.map → lightbulb-8KrKY82b.js.map} +1 -1
  136. package/ccw/frontend/dist/assets/{link-2-DXqT64qo.js → link-2-BUn6RILb.js} +2 -2
  137. package/ccw/frontend/dist/assets/{link-2-DXqT64qo.js.map → link-2-BUn6RILb.js.map} +1 -1
  138. package/ccw/frontend/dist/assets/{link-CBMtrpcI.js → link-CmP254Ai.js} +2 -2
  139. package/ccw/frontend/dist/assets/{link-CBMtrpcI.js.map → link-CmP254Ai.js.map} +1 -1
  140. package/ccw/frontend/dist/assets/{list-DDyEM4AO.js → list-BAwzl4a2.js} +2 -2
  141. package/ccw/frontend/dist/assets/{list-DDyEM4AO.js.map → list-BAwzl4a2.js.map} +1 -1
  142. package/ccw/frontend/dist/assets/{map-pin-B2FxBKfk.js → map-pin-gi342rqk.js} +2 -2
  143. package/ccw/frontend/dist/assets/{map-pin-B2FxBKfk.js.map → map-pin-gi342rqk.js.map} +1 -1
  144. package/ccw/frontend/dist/assets/{messages-square-zJfTY9pq.js → messages-square-C1Lh8q8b.js} +2 -2
  145. package/ccw/frontend/dist/assets/{messages-square-zJfTY9pq.js.map → messages-square-C1Lh8q8b.js.map} +1 -1
  146. package/ccw/frontend/dist/assets/{minimize-2-DnhGZj79.js → minimize-2-OgWNLKdq.js} +2 -2
  147. package/ccw/frontend/dist/assets/{minimize-2-DnhGZj79.js.map → minimize-2-OgWNLKdq.js.map} +1 -1
  148. package/ccw/frontend/dist/assets/{package-DYzAybhU.js → package-Djsvs5qp.js} +2 -2
  149. package/ccw/frontend/dist/assets/{package-DYzAybhU.js.map → package-Djsvs5qp.js.map} +1 -1
  150. package/ccw/frontend/dist/assets/{plug-B3kKHsu1.js → plug-DvSZP2cp.js} +2 -2
  151. package/ccw/frontend/dist/assets/{plug-B3kKHsu1.js.map → plug-DvSZP2cp.js.map} +1 -1
  152. package/ccw/frontend/dist/assets/{power-BPNNZgLy.js → power-BY7vTLmU.js} +2 -2
  153. package/ccw/frontend/dist/assets/{power-BPNNZgLy.js.map → power-BY7vTLmU.js.map} +1 -1
  154. package/ccw/frontend/dist/assets/{save-Cwry93p-.js → save-DXfqv84T.js} +2 -2
  155. package/ccw/frontend/dist/assets/{save-Cwry93p-.js.map → save-DXfqv84T.js.map} +1 -1
  156. package/ccw/frontend/dist/assets/{send-DuWWy2J8.js → send-E2o2LZSX.js} +2 -2
  157. package/ccw/frontend/dist/assets/{send-DuWWy2J8.js.map → send-E2o2LZSX.js.map} +1 -1
  158. package/ccw/frontend/dist/assets/{settings-2-C3U1eSK6.js → settings-2-ChD1LFHH.js} +2 -2
  159. package/ccw/frontend/dist/assets/{settings-2-C3U1eSK6.js.map → settings-2-ChD1LFHH.js.map} +1 -1
  160. package/ccw/frontend/dist/assets/{square-check-big-CrG1ejFB.js → square-check-big-CBymuqmD.js} +2 -2
  161. package/ccw/frontend/dist/assets/{square-check-big-CrG1ejFB.js.map → square-check-big-CBymuqmD.js.map} +1 -1
  162. package/ccw/frontend/dist/assets/{square-pen-eLWlCgZ5.js → square-pen-BfaiJgOX.js} +2 -2
  163. package/ccw/frontend/dist/assets/{square-pen-eLWlCgZ5.js.map → square-pen-BfaiJgOX.js.map} +1 -1
  164. package/ccw/frontend/dist/assets/{star-sveo4KRn.js → star-DHMWqZ09.js} +2 -2
  165. package/ccw/frontend/dist/assets/{star-sveo4KRn.js.map → star-DHMWqZ09.js.map} +1 -1
  166. package/ccw/frontend/dist/assets/{style-CRdAX7Cu.js → style-wvcOEAiM.js} +2 -2
  167. package/ccw/frontend/dist/assets/{style-CRdAX7Cu.js.map → style-wvcOEAiM.js.map} +1 -1
  168. package/ccw/frontend/dist/assets/{target-Oz1-z8Zu.js → target-B8AMmf_N.js} +2 -2
  169. package/ccw/frontend/dist/assets/{target-Oz1-z8Zu.js.map → target-B8AMmf_N.js.map} +1 -1
  170. package/ccw/frontend/dist/assets/{test-tube-BozkZKD6.js → test-tube-BpDeTJi1.js} +2 -2
  171. package/ccw/frontend/dist/assets/{test-tube-BozkZKD6.js.map → test-tube-BpDeTJi1.js.map} +1 -1
  172. package/ccw/frontend/dist/assets/{upload-CTlUsxyh.js → upload-pflkdIDG.js} +2 -2
  173. package/ccw/frontend/dist/assets/{upload-CTlUsxyh.js.map → upload-pflkdIDG.js.map} +1 -1
  174. package/ccw/frontend/dist/assets/{useApiSettings-D6WfgFYj.js → useApiSettings-BPx4DyKT.js} +2 -2
  175. package/ccw/frontend/dist/assets/{useApiSettings-D6WfgFYj.js.map → useApiSettings-BPx4DyKT.js.map} +1 -1
  176. package/ccw/frontend/dist/assets/{useCli-CgGVNN5I.js → useCli-D1jfH3XA.js} +2 -2
  177. package/ccw/frontend/dist/assets/{useCli-CgGVNN5I.js.map → useCli-D1jfH3XA.js.map} +1 -1
  178. package/ccw/frontend/dist/assets/{useCommands-o5CKv-10.js → useCommands-DhR71vpa.js} +2 -2
  179. package/ccw/frontend/dist/assets/{useCommands-o5CKv-10.js.map → useCommands-DhR71vpa.js.map} +1 -1
  180. package/ccw/frontend/dist/assets/{useDebounce-rKo_bCBK.js → useDebounce-a6Yyer3m.js} +2 -2
  181. package/ccw/frontend/dist/assets/{useDebounce-rKo_bCBK.js.map → useDebounce-a6Yyer3m.js.map} +1 -1
  182. package/ccw/frontend/dist/assets/{useFileExplorer-WeE4t9Hg.js → useFileExplorer-B8W2JTj2.js} +2 -2
  183. package/ccw/frontend/dist/assets/{useFileExplorer-WeE4t9Hg.js.map → useFileExplorer-B8W2JTj2.js.map} +1 -1
  184. package/ccw/frontend/dist/assets/{useLocale-BS0tTC-_.js → useLocale-aMHdQIL_.js} +2 -2
  185. package/ccw/frontend/dist/assets/{useLocale-BS0tTC-_.js.map → useLocale-aMHdQIL_.js.map} +1 -1
  186. package/ccw/frontend/dist/assets/{useSkills-BUgAhw6r.js → useSkills-BHpc2LtN.js} +3 -3
  187. package/ccw/frontend/dist/assets/{useSkills-BUgAhw6r.js.map → useSkills-BHpc2LtN.js.map} +1 -1
  188. package/ccw/frontend/dist/assets/{useSystemSettings-CLhmINg1.js → useSystemSettings-BFD0SvEF.js} +2 -2
  189. package/ccw/frontend/dist/assets/{useSystemSettings-CLhmINg1.js.map → useSystemSettings-BFD0SvEF.js.map} +1 -1
  190. package/ccw/frontend/dist/assets/{wand-sparkles-BUHKJH1X.js → wand-sparkles-dYtI2IKM.js} +2 -2
  191. package/ccw/frontend/dist/assets/{wand-sparkles-BUHKJH1X.js.map → wand-sparkles-dYtI2IKM.js.map} +1 -1
  192. package/ccw/frontend/dist/index.html +2 -2
  193. package/package.json +1 -1
  194. package/ccw/frontend/dist/assets/SettingsPage-Qj0fFDjX.js +0 -150
  195. package/ccw/frontend/dist/assets/SettingsPage-Qj0fFDjX.js.map +0 -1
  196. package/ccw/frontend/dist/assets/index-nU0QYi1y.css +0 -39
@@ -1 +1 @@
1
- {"version":3,"file":"CliViewerPage-D-MHYyDt.js","sources":["../../../../node_modules/lucide-react/dist/esm/icons/ellipsis.js","../../../../node_modules/lucide-react/dist/esm/icons/keyboard.js","../../../../node_modules/lucide-react/dist/esm/icons/pin-off.js","../../../../node_modules/lucide-react/dist/esm/icons/pin.js","../../src/components/cli-viewer/ExecutionPicker.tsx","../../src/components/cli-viewer/TabBar.tsx","../../src/components/cli-viewer/ContentArea.tsx","../../src/components/cli-viewer/PaneContent.tsx","../../src/components/cli-viewer/EmptyState.tsx","../../src/components/cli-viewer/LayoutContainer.tsx","../../src/components/cli-viewer/CliViewerToolbar.tsx","../../src/pages/cliViewerPage.utils.ts","../../src/pages/CliViewerPage.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Ellipsis = createLucideIcon(\"Ellipsis\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"1\", key: \"41hilf\" }],\n [\"circle\", { cx: \"19\", cy: \"12\", r: \"1\", key: \"1wjl8i\" }],\n [\"circle\", { cx: \"5\", cy: \"12\", r: \"1\", key: \"1pcz8c\" }]\n]);\n\nexport { Ellipsis as default };\n//# sourceMappingURL=ellipsis.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Keyboard = createLucideIcon(\"Keyboard\", [\n [\"path\", { d: \"M10 8h.01\", key: \"1r9ogq\" }],\n [\"path\", { d: \"M12 12h.01\", key: \"1mp3jc\" }],\n [\"path\", { d: \"M14 8h.01\", key: \"1primd\" }],\n [\"path\", { d: \"M16 12h.01\", key: \"1l6xoz\" }],\n [\"path\", { d: \"M18 8h.01\", key: \"emo2bl\" }],\n [\"path\", { d: \"M6 8h.01\", key: \"x9i8wu\" }],\n [\"path\", { d: \"M7 16h10\", key: \"wp8him\" }],\n [\"path\", { d: \"M8 12h.01\", key: \"czm47f\" }],\n [\"rect\", { width: \"20\", height: \"16\", x: \"2\", y: \"4\", rx: \"2\", key: \"18n3k1\" }]\n]);\n\nexport { Keyboard as default };\n//# sourceMappingURL=keyboard.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst PinOff = createLucideIcon(\"PinOff\", [\n [\"path\", { d: \"M12 17v5\", key: \"bb1du9\" }],\n [\"path\", { d: \"M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89\", key: \"znwnzq\" }],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }],\n [\n \"path\",\n {\n d: \"M9 9v1.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h11\",\n key: \"c9qhm2\"\n }\n ]\n]);\n\nexport { PinOff as default };\n//# sourceMappingURL=pin-off.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Pin = createLucideIcon(\"Pin\", [\n [\"path\", { d: \"M12 17v5\", key: \"bb1du9\" }],\n [\n \"path\",\n {\n d: \"M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z\",\n key: \"1nkz8b\"\n }\n ]\n]);\n\nexport { Pin as default };\n//# sourceMappingURL=pin.js.map\n","// ========================================\r\n// ExecutionPicker Component\r\n// ========================================\r\n// Dialog for selecting CLI executions to open as tabs\r\n\r\nimport { useState, useMemo, useCallback } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { Plus, Search, Terminal, Clock, CheckCircle2, XCircle, Loader2 } from 'lucide-react';\r\nimport { cn } from '@/lib/utils';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Input } from '@/components/ui/Input';\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogHeader,\r\n DialogTitle,\r\n DialogTrigger,\r\n} from '@/components/ui/Dialog';\r\nimport {\r\n useCliStreamStore,\r\n type CliExecutionState,\r\n type CliExecutionStatus,\r\n} from '@/stores/cliStreamStore';\r\nimport { useViewerStore, type PaneId } from '@/stores/viewerStore';\r\n\r\n// ========== Types ==========\r\n\r\nexport interface ExecutionPickerProps {\r\n paneId: PaneId;\r\n className?: string;\r\n}\r\n\r\n// ========== Constants ==========\r\n\r\nconst STATUS_CONFIG: Record<CliExecutionStatus, { icon: typeof CheckCircle2; color: string; label: string }> = {\r\n running: {\r\n icon: Loader2,\r\n color: 'text-indigo-500',\r\n label: 'Running',\r\n },\r\n completed: {\r\n icon: CheckCircle2,\r\n color: 'text-emerald-500',\r\n label: 'Completed',\r\n },\r\n error: {\r\n icon: XCircle,\r\n color: 'text-rose-500',\r\n label: 'Error',\r\n },\r\n};\r\n\r\n// ========== Helper Functions ==========\r\n\r\n/**\r\n * Format timestamp to relative or absolute time\r\n */\r\nfunction formatTime(timestamp: number): string {\r\n const now = Date.now();\r\n const diff = now - timestamp;\r\n\r\n if (diff < 60000) {\r\n return 'Just now';\r\n } else if (diff < 3600000) {\r\n const minutes = Math.floor(diff / 60000);\r\n return `${minutes}m ago`;\r\n } else if (diff < 86400000) {\r\n const hours = Math.floor(diff / 3600000);\r\n return `${hours}h ago`;\r\n } else {\r\n return new Date(timestamp).toLocaleDateString();\r\n }\r\n}\r\n\r\n/**\r\n * Get execution display title\r\n */\r\nfunction getExecutionTitle(_executionId: string, execution: CliExecutionState): string {\r\n return `${execution.tool}-${execution.mode}`;\r\n}\r\n\r\n// ========== Sub-Components ==========\r\n\r\ninterface ExecutionItemProps {\r\n executionId: string;\r\n execution: CliExecutionState;\r\n onSelect: () => void;\r\n}\r\n\r\n/**\r\n * Single execution item in the picker list\r\n */\r\nfunction ExecutionItem({ executionId, execution, onSelect }: ExecutionItemProps) {\r\n const statusConfig = STATUS_CONFIG[execution.status];\r\n const StatusIcon = statusConfig.icon;\r\n\r\n return (\r\n <button\r\n onClick={onSelect}\r\n className={cn(\r\n 'w-full flex items-center gap-3 p-3 rounded-lg',\r\n 'border border-border/50 bg-muted/30',\r\n 'hover:bg-muted/50 hover:border-border',\r\n 'transition-all duration-150',\r\n 'text-left'\r\n )}\r\n >\r\n {/* Tool icon */}\r\n <div className=\"flex items-center justify-center w-8 h-8 rounded-md bg-primary/10\">\r\n <Terminal className=\"h-4 w-4 text-primary\" />\r\n </div>\r\n\r\n {/* Execution info */}\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium text-sm text-foreground truncate\">\r\n {getExecutionTitle(executionId, execution)}\r\n </span>\r\n <StatusIcon\r\n className={cn(\r\n 'h-3.5 w-3.5 shrink-0',\r\n statusConfig.color,\r\n execution.status === 'running' && 'animate-spin'\r\n )}\r\n />\r\n </div>\r\n <div className=\"flex items-center gap-2 mt-0.5\">\r\n <span className=\"text-xs text-muted-foreground truncate\">\r\n {executionId}\r\n </span>\r\n </div>\r\n </div>\r\n\r\n {/* Time */}\r\n <div className=\"flex items-center gap-1 text-xs text-muted-foreground shrink-0\">\r\n <Clock className=\"h-3 w-3\" />\r\n <span>{formatTime(execution.startTime)}</span>\r\n </div>\r\n </button>\r\n );\r\n}\r\n\r\n// ========== Main Component ==========\r\n\r\n/**\r\n * ExecutionPicker - Dialog for selecting CLI executions to open as tabs\r\n *\r\n * Features:\r\n * - Lists all available CLI executions from store\r\n * - Search/filter by tool name or execution ID\r\n * - Shows execution status, tool, and timestamp\r\n * - Click to add as new tab in the specified pane\r\n */\r\nexport function ExecutionPicker({ paneId, className }: ExecutionPickerProps) {\r\n const { formatMessage } = useIntl();\r\n const [open, setOpen] = useState(false);\r\n const [searchQuery, setSearchQuery] = useState('');\r\n\r\n // Store hooks\r\n const executions = useCliStreamStore((state) => state.executions);\r\n const addTab = useViewerStore((state) => state.addTab);\r\n const panes = useViewerStore((state) => state.panes);\r\n\r\n // Get current pane's existing execution IDs\r\n const existingExecutionIds = useMemo(() => {\r\n const pane = panes[paneId];\r\n if (!pane) return new Set<string>();\r\n return new Set(pane.tabs.map((tab) => tab.executionId));\r\n }, [panes, paneId]);\r\n\r\n // Filter and sort executions\r\n const filteredExecutions = useMemo(() => {\r\n const entries = Object.entries(executions);\r\n\r\n // Filter by search query\r\n const filtered = entries.filter(([id, exec]) => {\r\n if (!searchQuery) return true;\r\n const query = searchQuery.toLowerCase();\r\n return (\r\n id.toLowerCase().includes(query) ||\r\n exec.tool.toLowerCase().includes(query) ||\r\n exec.mode.toLowerCase().includes(query)\r\n );\r\n });\r\n\r\n // Sort by start time (newest first)\r\n filtered.sort((a, b) => b[1].startTime - a[1].startTime);\r\n\r\n return filtered;\r\n }, [executions, searchQuery]);\r\n\r\n // Handle execution selection\r\n const handleSelect = useCallback((executionId: string, execution: CliExecutionState) => {\r\n const title = getExecutionTitle(executionId, execution);\r\n addTab(paneId, executionId, title);\r\n setOpen(false);\r\n setSearchQuery('');\r\n }, [paneId, addTab]);\r\n\r\n // Count available vs total\r\n const totalCount = Object.keys(executions).length;\r\n const availableCount = filteredExecutions.filter(\r\n ([id]) => !existingExecutionIds.has(id)\r\n ).length;\r\n\r\n return (\r\n <Dialog open={open} onOpenChange={setOpen}>\r\n <DialogTrigger asChild>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className={cn('h-6 w-6 shrink-0', className)}\r\n aria-label={formatMessage({\r\n id: 'cliViewer.tabs.addTab',\r\n defaultMessage: 'Add tab'\r\n })}\r\n >\r\n <Plus className=\"h-4 w-4\" />\r\n </Button>\r\n </DialogTrigger>\r\n\r\n <DialogContent className=\"sm:max-w-md\">\r\n <DialogHeader>\r\n <DialogTitle>\r\n {formatMessage({\r\n id: 'cliViewer.picker.selectExecution',\r\n defaultMessage: 'Select Execution'\r\n })}\r\n </DialogTitle>\r\n </DialogHeader>\r\n\r\n {/* Search input */}\r\n <div className=\"relative\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\r\n <Input\r\n placeholder={formatMessage({\r\n id: 'cliViewer.picker.searchExecutions',\r\n defaultMessage: 'Search executions...'\r\n })}\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n className=\"pl-9\"\r\n />\r\n </div>\r\n\r\n {/* Execution list */}\r\n <div className=\"max-h-[300px] overflow-y-auto space-y-2\">\r\n {filteredExecutions.length === 0 ? (\r\n <div className=\"flex flex-col items-center justify-center py-8 text-center\">\r\n <Terminal className=\"h-8 w-8 text-muted-foreground mb-2\" />\r\n <p className=\"text-sm text-muted-foreground\">\r\n {totalCount === 0\r\n ? formatMessage({\r\n id: 'cliViewer.picker.noExecutions',\r\n defaultMessage: 'No executions available'\r\n })\r\n : formatMessage({\r\n id: 'cliViewer.picker.noMatchingExecutions',\r\n defaultMessage: 'No matching executions'\r\n })\r\n }\r\n </p>\r\n </div>\r\n ) : (\r\n filteredExecutions.map(([id, exec]) => {\r\n const isAlreadyOpen = existingExecutionIds.has(id);\r\n return (\r\n <div key={id} className=\"relative\">\r\n <ExecutionItem\r\n executionId={id}\r\n execution={exec}\r\n onSelect={() => handleSelect(id, exec)}\r\n />\r\n {isAlreadyOpen && (\r\n <div className=\"absolute inset-0 bg-background/60 rounded-lg flex items-center justify-center\">\r\n <span className=\"text-xs text-muted-foreground bg-muted px-2 py-1 rounded\">\r\n {formatMessage({\r\n id: 'cliViewer.picker.alreadyOpen',\r\n defaultMessage: 'Already open'\r\n })}\r\n </span>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })\r\n )}\r\n </div>\r\n\r\n {/* Footer with count */}\r\n {totalCount > 0 && (\r\n <div className=\"text-xs text-muted-foreground text-center pt-2 border-t border-border/50\">\r\n {formatMessage(\r\n {\r\n id: 'cliViewer.picker.executionCount',\r\n defaultMessage: '{available} of {total} executions available'\r\n },\r\n { available: availableCount, total: totalCount }\r\n )}\r\n </div>\r\n )}\r\n </DialogContent>\r\n </Dialog>\r\n );\r\n}\r\n\r\nexport default ExecutionPicker;\r\n","// ========================================\n// TabBar Component\n// ========================================\n// Tab management for CLI viewer panes with drag-and-drop support\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { useIntl } from 'react-intl';\nimport { X, Pin, PinOff, MoreHorizontal, SplitSquareHorizontal, SplitSquareVertical } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport { Button } from '@/components/ui/Button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@/components/ui/Dropdown';\nimport {\n useViewerStore,\n useViewerPanes,\n type PaneId,\n type TabState,\n} from '@/stores/viewerStore';\nimport { ExecutionPicker } from './ExecutionPicker';\n\n// ========== Types ==========\n\nexport interface TabBarProps {\n paneId: PaneId;\n className?: string;\n}\n\ninterface TabItemProps {\n tab: TabState;\n paneId: PaneId;\n isActive: boolean;\n onSelect: () => void;\n onClose: (e: React.MouseEvent) => void;\n onTogglePin: (e: React.MouseEvent) => void;\n}\n\n// ========== Constants ==========\n\nconst STATUS_COLORS = {\n running: 'bg-indigo-500 shadow-[0_0_6px_rgba(99,102,241,0.4)] animate-pulse',\n completed: 'bg-emerald-500',\n error: 'bg-rose-500',\n idle: 'bg-slate-400 dark:bg-slate-500',\n};\n\n// ========== Helper Components ==========\n\n// Data transfer key for tab drag-and-drop\nconst TAB_DRAG_DATA_TYPE = 'application/x-cli-viewer-tab';\n\ninterface TabDragData {\n tabId: string;\n sourcePaneId: string;\n}\n\n/**\n * Individual tab item with drag-and-drop support\n */\nfunction TabItem({ tab, paneId, isActive, onSelect, onClose, onTogglePin }: TabItemProps) {\n const [isDragging, setIsDragging] = useState(false);\n const [isDragOver, setIsDragOver] = useState(false);\n const moveTab = useViewerStore((state) => state.moveTab);\n const panes = useViewerPanes();\n\n // Simplify title for display\n const displayTitle = useMemo(() => {\n // If title contains tool name pattern, extract it\n const parts = tab.title.split('-');\n return parts[0] || tab.title;\n }, [tab.title]);\n\n // Drag start handler\n const handleDragStart = useCallback((e: React.DragEvent) => {\n const dragData: TabDragData = {\n tabId: tab.id,\n sourcePaneId: paneId,\n };\n e.dataTransfer.setData(TAB_DRAG_DATA_TYPE, JSON.stringify(dragData));\n e.dataTransfer.effectAllowed = 'move';\n setIsDragging(true);\n }, [tab.id, paneId]);\n\n // Drag end handler\n const handleDragEnd = useCallback(() => {\n setIsDragging(false);\n }, []);\n\n // Drag over handler\n const handleDragOver = useCallback((e: React.DragEvent) => {\n if (e.dataTransfer.types.includes(TAB_DRAG_DATA_TYPE)) {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n setIsDragOver(true);\n }\n }, []);\n\n // Drag leave handler\n const handleDragLeave = useCallback(() => {\n setIsDragOver(false);\n }, []);\n\n // Drop handler\n const handleDrop = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n setIsDragOver(false);\n\n const rawData = e.dataTransfer.getData(TAB_DRAG_DATA_TYPE);\n if (!rawData) return;\n\n try {\n const dragData: TabDragData = JSON.parse(rawData);\n const { tabId: sourceTabId, sourcePaneId } = dragData;\n\n // Don't do anything if dropping on the same tab\n if (sourceTabId === tab.id) return;\n\n // Find the target index\n const targetPane = panes[paneId];\n if (!targetPane) return;\n\n const targetIndex = targetPane.tabs.findIndex((t) => t.id === tab.id);\n if (targetIndex === -1) return;\n\n // Move the tab\n moveTab(sourcePaneId, sourceTabId, paneId, targetIndex);\n } catch (err) {\n console.error('[TabBar] Failed to parse drag data:', err);\n }\n }, [tab.id, paneId, panes, moveTab]);\n\n return (\n <div\n role=\"tab\"\n tabIndex={0}\n draggable={!tab.isPinned}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n onClick={onSelect}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onSelect();\n }\n }}\n className={cn(\n 'group relative flex items-center gap-1.5 px-2.5 py-1.5 rounded-md text-xs',\n 'border border-border/50 shrink-0 min-w-0 max-w-[160px]',\n 'transition-all duration-150 select-none',\n isActive\n ? 'bg-slate-100 dark:bg-slate-800 border-slate-300 dark:border-slate-600 shadow-sm'\n : 'bg-muted/30 hover:bg-muted/50 border-border/30',\n tab.isPinned && 'border-amber-500/50',\n isDragging && 'opacity-50 cursor-grabbing',\n isDragOver && 'border-primary border-dashed bg-primary/10',\n !tab.isPinned && 'cursor-grab'\n )}\n title={tab.title}\n >\n {/* Status indicator dot */}\n <span className={cn('w-1.5 h-1.5 rounded-full shrink-0', STATUS_COLORS.idle)} />\n\n {/* Tool name */}\n <span className=\"font-medium text-[11px] truncate\">{displayTitle}</span>\n\n {/* Pin indicator (always visible if pinned) */}\n {tab.isPinned && (\n <Pin className=\"h-2.5 w-2.5 text-amber-500 shrink-0\" />\n )}\n\n {/* Action buttons (visible on hover) */}\n <div className=\"flex items-center gap-0.5 ml-auto opacity-0 group-hover:opacity-100 transition-opacity\">\n {/* Pin/Unpin button */}\n <button\n onClick={onTogglePin}\n className=\"p-0.5 rounded hover:bg-primary/10 transition-colors\"\n aria-label={tab.isPinned ? 'Unpin tab' : 'Pin tab'}\n >\n {tab.isPinned ? (\n <PinOff className=\"h-2.5 w-2.5 text-amber-500\" />\n ) : (\n <Pin className=\"h-2.5 w-2.5 text-muted-foreground hover:text-amber-500\" />\n )}\n </button>\n\n {/* Close button (hidden if pinned) */}\n {!tab.isPinned && (\n <button\n onClick={onClose}\n className=\"p-0.5 rounded hover:bg-rose-500/20 transition-colors\"\n aria-label=\"Close tab\"\n >\n <X className=\"h-2.5 w-2.5 text-rose-600 dark:text-rose-400\" />\n </button>\n )}\n </div>\n </div>\n );\n}\n\n// ========== Main Component ==========\n\n/**\n * TabBar - Manages tabs within a pane\n *\n * Features:\n * - Tab display with status indicators\n * - Active tab highlighting\n * - Close button on hover\n * - Pin/unpin functionality\n * - Drag-and-drop tab reordering and moving between panes\n * - Pane actions dropdown\n */\nexport function TabBar({ paneId, className }: TabBarProps) {\n const { formatMessage } = useIntl();\n const [isDragOver, setIsDragOver] = useState(false);\n const panes = useViewerPanes();\n const pane = panes[paneId];\n const setActiveTab = useViewerStore((state) => state.setActiveTab);\n const removeTab = useViewerStore((state) => state.removeTab);\n const togglePinTab = useViewerStore((state) => state.togglePinTab);\n const addPane = useViewerStore((state) => state.addPane);\n const removePane = useViewerStore((state) => state.removePane);\n const moveTab = useViewerStore((state) => state.moveTab);\n\n const handleTabSelect = useCallback(\n (tabId: string) => {\n setActiveTab(paneId, tabId);\n },\n [paneId, setActiveTab]\n );\n\n const handleTabClose = useCallback(\n (e: React.MouseEvent, tabId: string) => {\n e.stopPropagation();\n removeTab(paneId, tabId);\n },\n [paneId, removeTab]\n );\n\n const handleTogglePin = useCallback(\n (e: React.MouseEvent, tabId: string) => {\n e.stopPropagation();\n togglePinTab(tabId);\n },\n [togglePinTab]\n );\n\n const handleSplitHorizontal = useCallback(() => {\n addPane(paneId, 'horizontal');\n }, [paneId, addPane]);\n\n const handleSplitVertical = useCallback(() => {\n addPane(paneId, 'vertical');\n }, [paneId, addPane]);\n\n const handleClosePane = useCallback(() => {\n removePane(paneId);\n }, [paneId, removePane]);\n\n // Drag over handler for tab bar container (allows dropping to end of list)\n const handleContainerDragOver = useCallback((e: React.DragEvent) => {\n if (e.dataTransfer.types.includes(TAB_DRAG_DATA_TYPE)) {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n setIsDragOver(true);\n }\n }, []);\n\n // Drag leave handler for container\n const handleContainerDragLeave = useCallback((e: React.DragEvent) => {\n // Only set false if leaving the container entirely, not just moving to a child\n if (!e.currentTarget.contains(e.relatedTarget as Node)) {\n setIsDragOver(false);\n }\n }, []);\n\n // Drop handler for tab bar container (drops to end of list)\n const handleContainerDrop = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n setIsDragOver(false);\n\n const rawData = e.dataTransfer.getData(TAB_DRAG_DATA_TYPE);\n if (!rawData) return;\n\n try {\n const dragData: TabDragData = JSON.parse(rawData);\n const { tabId: sourceTabId, sourcePaneId } = dragData;\n\n // Move the tab to the end of this pane\n const targetIndex = pane?.tabs.length || 0;\n moveTab(sourcePaneId, sourceTabId, paneId, targetIndex);\n } catch (err) {\n console.error('[TabBar] Failed to parse drag data:', err);\n }\n }, [paneId, pane, moveTab]);\n\n // Sort tabs: pinned first, then by order\n const sortedTabs = useMemo(() => {\n if (!pane) return [];\n return [...pane.tabs].sort((a, b) => {\n if (a.isPinned !== b.isPinned) {\n return a.isPinned ? -1 : 1;\n }\n return a.order - b.order;\n });\n }, [pane]);\n\n if (!pane) {\n return null;\n }\n\n return (\n <div\n className={cn(\n 'flex items-center gap-1 px-2 py-1.5',\n 'bg-muted/30 border-b border-border/50',\n 'overflow-x-auto scrollbar-thin scrollbar-thumb-muted scrollbar-track-transparent',\n className\n )}\n >\n {/* Tabs */}\n <div\n onDragOver={handleContainerDragOver}\n onDragLeave={handleContainerDragLeave}\n onDrop={handleContainerDrop}\n className={cn(\n 'flex items-center gap-1 flex-1 min-w-0 overflow-x-auto',\n isDragOver && 'bg-primary/5 border border-primary border-dashed rounded'\n )}\n >\n {sortedTabs.length === 0 ? (\n <span className=\"text-xs text-muted-foreground px-2\">\n {formatMessage({ id: 'cliViewer.tabs.noTabs', defaultMessage: 'No tabs open' })}\n </span>\n ) : (\n sortedTabs.map((tab) => (\n <TabItem\n key={tab.id}\n tab={tab}\n paneId={paneId}\n isActive={pane.activeTabId === tab.id}\n onSelect={() => handleTabSelect(tab.id)}\n onClose={(e) => handleTabClose(e, tab.id)}\n onTogglePin={(e) => handleTogglePin(e, tab.id)}\n />\n ))\n )}\n </div>\n\n {/* Add tab button */}\n <ExecutionPicker paneId={paneId} />\n\n {/* Pane actions dropdown */}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6 shrink-0\"\n aria-label=\"Pane actions\"\n >\n <MoreHorizontal className=\"h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-48\">\n <DropdownMenuItem onClick={handleSplitHorizontal}>\n <SplitSquareHorizontal className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'cliViewer.paneActions.splitHorizontal', defaultMessage: 'Split Horizontal' })}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={handleSplitVertical}>\n <SplitSquareVertical className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'cliViewer.paneActions.splitVertical', defaultMessage: 'Split Vertical' })}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={handleClosePane}\n className=\"text-rose-600 dark:text-rose-400\"\n >\n <X className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'cliViewer.paneActions.closePane', defaultMessage: 'Close Pane' })}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n );\n}\n\nexport default TabBar;\n","// ========================================\n// ContentArea Component\n// ========================================\n// Displays CLI output for the active tab in a pane\n\nimport { useMemo } from 'react';\nimport { useIntl } from 'react-intl';\nimport { Terminal, Loader2 } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport {\n useViewerStore,\n selectActiveTab,\n type PaneId,\n} from '@/stores/viewerStore';\nimport { useCliStreamStore, type CliExecutionState, type CliOutputLine } from '@/stores/cliStreamStore';\nimport { MonitorBody } from '@/components/shared/CliStreamMonitor/MonitorBody';\nimport { MessageRenderer } from '@/components/shared/CliStreamMonitor/MessageRenderer';\nimport { useActiveCliExecutions } from '@/hooks/useActiveCliExecutions';\n\n// ========== Types ==========\n\nexport interface ContentAreaProps {\n paneId: PaneId;\n className?: string;\n}\n\n// ========== Helper Components ==========\n\n/**\n * Empty state when no tab is active\n */\nfunction EmptyTabState() {\n const { formatMessage } = useIntl();\n\n return (\n <div className=\"flex-1 flex flex-col items-center justify-center text-muted-foreground gap-4\">\n <Terminal className=\"h-12 w-12 opacity-30\" />\n <div className=\"text-center\">\n <p className=\"text-sm font-medium\">\n {formatMessage({ id: 'cliViewer.noActiveTab', defaultMessage: 'No active tab' })}\n </p>\n <p className=\"text-xs mt-1\">\n {formatMessage({\n id: 'cliViewer.selectOrCreate',\n defaultMessage: 'Select a tab or start a new CLI execution',\n })}\n </p>\n </div>\n </div>\n );\n}\n\n/**\n * Execution not found state\n */\nfunction ExecutionNotFoundState({ executionId }: { executionId: string }) {\n const { formatMessage } = useIntl();\n\n return (\n <div className=\"flex-1 flex flex-col items-center justify-center text-muted-foreground gap-4\">\n <Terminal className=\"h-12 w-12 opacity-30\" />\n <div className=\"text-center\">\n <p className=\"text-sm font-medium\">\n {formatMessage({ id: 'cliViewer.executionNotFound', defaultMessage: 'Execution not found' })}\n </p>\n <p className=\"text-xs mt-1 font-mono opacity-50\">{executionId}</p>\n </div>\n </div>\n );\n}\n\n/**\n * FIX-002: Loading state while syncing executions from server\n * Shown after page refresh while execution data is being recovered\n */\nfunction ExecutionLoadingState() {\n const { formatMessage } = useIntl();\n\n return (\n <div className=\"flex-1 flex flex-col items-center justify-center text-muted-foreground gap-4\">\n <Loader2 className=\"h-8 w-8 animate-spin opacity-50\" />\n <div className=\"text-center\">\n <p className=\"text-sm\">\n {formatMessage({ id: 'cliViewer.syncingExecution', defaultMessage: 'Syncing execution data...' })}\n </p>\n </div>\n </div>\n );\n}\n\n/**\n * Single output line component with type-based styling\n */\nfunction OutputLineItem({ line }: { line: CliOutputLine }) {\n // Type-based styling\n const typeStyles: Record<CliOutputLine['type'], string> = {\n stdout: 'text-foreground',\n stderr: 'text-rose-600 dark:text-rose-400 bg-rose-500/5',\n thought: 'text-blue-600 dark:text-blue-400 italic bg-blue-500/5',\n system: 'text-amber-600 dark:text-amber-400 bg-amber-500/5',\n metadata: 'text-muted-foreground text-xs',\n tool_call: 'text-emerald-600 dark:text-emerald-400 bg-emerald-500/5 font-mono',\n };\n\n return (\n <div\n className={cn(\n 'px-3 py-1 text-sm',\n 'border-l-2 border-transparent',\n typeStyles[line.type] || 'text-foreground',\n line.type === 'stderr' && 'border-l-rose-500',\n line.type === 'thought' && 'border-l-blue-500',\n line.type === 'system' && 'border-l-amber-500',\n line.type === 'tool_call' && 'border-l-emerald-500'\n )}\n >\n {line.type === 'thought' || line.type === 'tool_call' ? (\n <MessageRenderer content={line.content} format=\"markdown\" />\n ) : (\n <pre className=\"whitespace-pre-wrap break-words font-mono text-xs\">\n {line.content}\n </pre>\n )}\n </div>\n );\n}\n\n/**\n * CLI output display component\n */\nfunction CliOutputDisplay({ execution, executionId }: { execution: CliExecutionState; executionId: string }) {\n const { formatMessage } = useIntl();\n\n if (!execution.output || execution.output.length === 0) {\n return (\n <div className=\"flex-1 flex flex-col items-center justify-center text-muted-foreground gap-4\">\n <Terminal className=\"h-12 w-12 opacity-30\" />\n <div className=\"text-center\">\n <p className=\"text-sm\">\n {execution.status === 'running'\n ? formatMessage({ id: 'cliViewer.waitingForOutput', defaultMessage: 'Waiting for output...' })\n : formatMessage({ id: 'cliViewer.noOutput', defaultMessage: 'No output' })}\n </p>\n {execution.status === 'running' && (\n <Loader2 className=\"h-4 w-4 animate-spin mt-2 mx-auto opacity-50\" />\n )}\n </div>\n </div>\n );\n }\n\n return (\n <MonitorBody autoScroll={execution.status === 'running'} showScrollButton>\n <div className=\"py-2\">\n {execution.output.map((line, index) => (\n <OutputLineItem\n key={`${executionId}-line-${index}`}\n line={line}\n />\n ))}\n </div>\n </MonitorBody>\n );\n}\n\n// ========== Main Component ==========\n\n/**\n * ContentArea - Displays CLI output for active tab\n *\n * Features:\n * - Integration with CliStreamStore for execution data\n * - Auto-scroll during active execution\n * - Empty state handling\n * - Message rendering with proper formatting\n */\nexport function ContentArea({ paneId, className }: ContentAreaProps) {\n // Get active tab using the selector\n const activeTab = useViewerStore((state) => selectActiveTab(state, paneId));\n\n // Get execution data from cliStreamStore\n const executions = useCliStreamStore((state) => state.executions);\n\n // FIX-002: Get loading state from useActiveCliExecutions\n // This helps distinguish between \"not found\" and \"still loading\"\n const { isLoading: isSyncing } = useActiveCliExecutions(true);\n\n const execution = useMemo(() => {\n if (!activeTab?.executionId) return null;\n return executions[activeTab.executionId] || null;\n }, [activeTab?.executionId, executions]);\n\n // Determine what to render\n const content = useMemo(() => {\n // No active tab\n if (!activeTab) {\n return <EmptyTabState />;\n }\n\n // FIX-002: Show loading state while syncing if execution not yet available\n if (!execution && isSyncing) {\n return <ExecutionLoadingState />;\n }\n\n // No execution data found (after sync completed)\n if (!execution) {\n return <ExecutionNotFoundState executionId={activeTab.executionId} />;\n }\n\n // Show CLI output\n return <CliOutputDisplay execution={execution} executionId={activeTab.executionId} />;\n }, [activeTab, execution, isSyncing]);\n\n return (\n <div\n className={cn(\n 'flex-1 min-h-0 flex flex-col overflow-hidden',\n 'bg-background',\n className\n )}\n >\n {content}\n </div>\n );\n}\n\nexport default ContentArea;\n","// ========================================\n// PaneContent Component\n// ========================================\n// Container for TabBar and ContentArea within a pane\n\nimport { useCallback } from 'react';\nimport { cn } from '@/lib/utils';\nimport {\n useViewerStore,\n useViewerPanes,\n useFocusedPaneId,\n type PaneId,\n} from '@/stores/viewerStore';\nimport { TabBar } from './TabBar';\nimport { ContentArea } from './ContentArea';\n\n// ========== Types ==========\n\nexport interface PaneContentProps {\n paneId: PaneId;\n className?: string;\n}\n\n// ========== Component ==========\n\n/**\n * PaneContent - Combines TabBar and ContentArea for a single pane\n *\n * Features:\n * - Focused pane highlighting\n * - Click to focus\n * - TabBar for tab management\n * - ContentArea for CLI output display\n */\nexport function PaneContent({ paneId, className }: PaneContentProps) {\n const panes = useViewerPanes();\n const pane = panes[paneId];\n const focusedPaneId = useFocusedPaneId();\n const setFocusedPane = useViewerStore((state) => state.setFocusedPane);\n\n const isFocused = focusedPaneId === paneId;\n\n const handleClick = useCallback(() => {\n if (!isFocused) {\n setFocusedPane(paneId);\n }\n }, [isFocused, paneId, setFocusedPane]);\n\n if (!pane) {\n return (\n <div className={cn('h-full flex items-center justify-center', className)}>\n <span className=\"text-muted-foreground text-sm\">Pane not found</span>\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n 'h-full flex flex-col',\n 'bg-card dark:bg-surface-900',\n 'border border-border/50',\n 'rounded-sm overflow-hidden',\n // Focus ring when pane is focused\n isFocused && 'ring-1 ring-primary/50',\n className\n )}\n onClick={handleClick}\n role=\"region\"\n aria-label={`CLI Viewer Pane ${paneId}`}\n >\n {/* Tab Bar */}\n <TabBar paneId={paneId} />\n\n {/* Content Area */}\n <ContentArea paneId={paneId} />\n </div>\n );\n}\n\nexport default PaneContent;\n","// ========================================\n// EmptyState Component\n// ========================================\n// Empty state display for CLI viewer\n\nimport { useIntl } from 'react-intl';\nimport { Terminal, Play, Keyboard } from 'lucide-react';\nimport { cn } from '@/lib/utils';\n\n// ========== Types ==========\n\nexport interface EmptyStateProps {\n className?: string;\n}\n\n// ========== Component ==========\n\n/**\n * EmptyState - Displays when no CLI executions are active\n *\n * Features:\n * - Informative empty state message\n * - Quick start hints\n * - Dark theme compatible\n */\nexport function EmptyState({ className }: EmptyStateProps) {\n const { formatMessage } = useIntl();\n\n return (\n <div\n className={cn(\n 'h-full flex flex-col items-center justify-center',\n 'bg-card dark:bg-surface-900',\n 'text-muted-foreground',\n className\n )}\n >\n <div className=\"flex flex-col items-center gap-6 max-w-md text-center p-8\">\n {/* Icon */}\n <div className=\"relative\">\n <Terminal className=\"h-16 w-16 opacity-20\" />\n <div className=\"absolute -bottom-1 -right-1 bg-primary/10 rounded-full p-1.5\">\n <Play className=\"h-4 w-4 text-primary\" />\n </div>\n </div>\n\n {/* Title */}\n <div>\n <h3 className=\"text-lg font-semibold text-foreground mb-2\">\n {formatMessage({\n id: 'cliViewer.emptyState.title',\n defaultMessage: 'CLI Viewer',\n })}\n </h3>\n <p className=\"text-sm\">\n {formatMessage({\n id: 'cliViewer.emptyState.description',\n defaultMessage: 'Start a CLI execution to see the output here.',\n })}\n </p>\n </div>\n\n {/* Hints */}\n <div className=\"flex flex-col gap-3 text-xs\">\n <div className=\"flex items-center gap-2\">\n <Keyboard className=\"h-4 w-4 shrink-0\" />\n <span>\n {formatMessage({\n id: 'cliViewer.emptyState.hint1',\n defaultMessage: 'Use \"ccw cli\" command to start an execution',\n })}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <Terminal className=\"h-4 w-4 shrink-0\" />\n <span>\n {formatMessage({\n id: 'cliViewer.emptyState.hint2',\n defaultMessage: 'Active executions will appear as tabs',\n })}\n </span>\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nexport default EmptyState;\n","// ========================================\n// LayoutContainer Component\n// ========================================\n// Manages allotment-based split panes for CLI viewer\n\nimport { useMemo, useRef, useEffect, useCallback } from 'react';\nimport { Allotment } from 'allotment';\nimport 'allotment/dist/style.css';\nimport { cn } from '@/lib/utils';\nimport {\n useViewerStore,\n useViewerLayout,\n useViewerPanes,\n type AllotmentLayoutGroup,\n type PaneId,\n} from '@/stores/viewerStore';\nimport { PaneContent } from './PaneContent';\nimport { EmptyState } from './EmptyState';\n\n// ========== Types ==========\n\ninterface LayoutGroupRendererProps {\n group: AllotmentLayoutGroup;\n minSize: number;\n onSizeChange: (sizes: number[]) => void;\n}\n\ninterface LayoutContainerProps {\n className?: string;\n}\n\n// ========== Helper Functions ==========\n\n/**\n * Check if a layout child is a pane ID (string) or a nested group\n */\nfunction isPaneId(child: PaneId | AllotmentLayoutGroup): child is PaneId {\n return typeof child === 'string';\n}\n\n// ========== Helper Components ==========\n\n/**\n * Renders a layout group with Allotment\n */\nfunction LayoutGroupRenderer({ group, minSize, onSizeChange }: LayoutGroupRendererProps) {\n const panes = useViewerPanes();\n\n // Check if all panes in this group exist\n const validChildren = useMemo(() => {\n return group.children.filter(child => {\n if (isPaneId(child)) {\n return panes[child] !== undefined;\n }\n return true; // Groups are always valid (they will recursively filter)\n });\n }, [group.children, panes]);\n\n if (validChildren.length === 0) {\n return <EmptyState />;\n }\n\n return (\n <Allotment\n vertical={group.direction === 'vertical'}\n defaultSizes={group.sizes}\n onChange={onSizeChange}\n className=\"h-full\"\n >\n {validChildren.map((child, index) => (\n <Allotment.Pane key={isPaneId(child) ? child : `group-${index}`} minSize={minSize}>\n {isPaneId(child) ? (\n <PaneContent paneId={child} />\n ) : (\n <LayoutGroupRenderer\n group={child}\n minSize={minSize}\n onSizeChange={onSizeChange}\n />\n )}\n </Allotment.Pane>\n ))}\n </Allotment>\n );\n}\n\n// ========== Main Component ==========\n\n/**\n * LayoutContainer - Main container for CLI viewer with split panes\n *\n * Features:\n * - Recursive rendering of nested allotment layouts\n * - Support for horizontal and vertical splits\n * - Minimum pane size enforcement\n * - Empty state handling\n */\nexport function LayoutContainer({ className }: LayoutContainerProps) {\n const layout = useViewerLayout();\n const panes = useViewerPanes();\n\n // Use ref to track if we're currently updating to prevent infinite loops\n const isUpdatingRef = useRef(false);\n // Track previous sizes to avoid unnecessary updates\n const prevSizesRef = useRef<number[] | undefined>(layout.sizes);\n\n // Update prevSizesRef when layout.sizes changes from external sources\n useEffect(() => {\n if (!isUpdatingRef.current) {\n prevSizesRef.current = layout.sizes;\n }\n }, [layout.sizes]);\n\n // Stable callback with no dependencies - prevents Allotment onChange infinite loop\n const handleSizeChange = useCallback(\n (sizes: number[]) => {\n // Skip if sizes haven't actually changed (compare by value)\n if (\n prevSizesRef.current &&\n sizes.length === prevSizesRef.current.length &&\n sizes.every((s, i) => Math.abs(s - prevSizesRef.current![i]) < 0.1)\n ) {\n return;\n }\n\n // Use functional update to avoid dependency on layout\n isUpdatingRef.current = true;\n prevSizesRef.current = sizes;\n\n useViewerStore.getState().setLayout((prev) => ({\n ...prev,\n sizes,\n }));\n\n // Reset updating flag after a microtask\n queueMicrotask(() => {\n isUpdatingRef.current = false;\n });\n },\n [] // No dependencies - uses getState() and refs to prevent infinite loops\n );\n\n // Render based on layout type\n const content = useMemo(() => {\n // No children - show empty state\n if (!layout.children || layout.children.length === 0) {\n return <EmptyState />;\n }\n\n // Single pane layout\n if (layout.children.length === 1 && isPaneId(layout.children[0])) {\n const paneId = layout.children[0];\n if (!panes[paneId]) {\n return <EmptyState />;\n }\n return <PaneContent paneId={paneId} />;\n }\n\n // Group layout\n return (\n <LayoutGroupRenderer\n group={layout}\n minSize={200}\n onSizeChange={handleSizeChange}\n />\n );\n }, [layout, panes, handleSizeChange]);\n\n return (\n <div\n className={cn(\n 'h-full w-full overflow-hidden',\n 'bg-background',\n className\n )}\n >\n {content}\n </div>\n );\n}\n\nexport default LayoutContainer;\n","// ========================================\r\n// CliViewerToolbar Component\r\n// ========================================\r\n// Compact icon-based toolbar for CLI Viewer page\r\n// Follows DashboardToolbar design pattern\r\n\r\nimport { useCallback, useMemo, useState } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport {\r\n ArrowLeft,\r\n Square,\r\n Columns2,\r\n Rows2,\r\n LayoutGrid,\r\n Plus,\r\n ChevronDown,\r\n Maximize2,\r\n Minimize2,\r\n RotateCcw,\r\n Terminal,\r\n} from 'lucide-react';\r\nimport { cn } from '@/lib/utils';\r\nimport {\r\n DropdownMenu,\r\n DropdownMenuContent,\r\n DropdownMenuItem,\r\n DropdownMenuLabel,\r\n DropdownMenuSeparator,\r\n DropdownMenuTrigger,\r\n} from '@/components/ui/Dropdown';\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogHeader,\r\n DialogTitle,\r\n DialogTrigger,\r\n} from '@/components/ui/Dialog';\r\nimport { Input } from '@/components/ui/Input';\r\nimport { Search, Clock } from 'lucide-react';\r\nimport {\r\n useViewerStore,\r\n useViewerLayout,\r\n useFocusedPaneId,\r\n type AllotmentLayout,\r\n} from '@/stores/viewerStore';\r\nimport { useCliStreamStore, type CliExecutionStatus } from '@/stores/cliStreamStore';\r\n\r\n// ========== Types ==========\r\n\r\nexport interface CliViewerToolbarProps {\r\n /** Whether fullscreen mode is active */\r\n isFullscreen?: boolean;\r\n /** Callback to toggle fullscreen mode */\r\n onToggleFullscreen?: () => void;\r\n}\r\n\r\nexport type LayoutType = 'single' | 'split-h' | 'split-v' | 'grid-2x2';\r\n\r\n// ========== Constants ==========\r\n\r\nconst LAYOUT_PRESETS = [\r\n { id: 'single' as const, icon: Square, labelId: 'cliViewer.layout.single' },\r\n { id: 'split-h' as const, icon: Columns2, labelId: 'cliViewer.layout.splitH' },\r\n { id: 'split-v' as const, icon: Rows2, labelId: 'cliViewer.layout.splitV' },\r\n { id: 'grid-2x2' as const, icon: LayoutGrid, labelId: 'cliViewer.layout.grid' },\r\n];\r\n\r\nconst DEFAULT_LAYOUT: LayoutType = 'split-h';\r\n\r\nconst STATUS_CONFIG: Record<CliExecutionStatus, { color: string }> = {\r\n running: { color: 'bg-blue-500 animate-pulse' },\r\n completed: { color: 'bg-green-500' },\r\n error: { color: 'bg-red-500' },\r\n};\r\n\r\n// ========== Helper Functions ==========\r\n\r\n/**\r\n * Detect layout type from AllotmentLayout structure\r\n */\r\nfunction detectLayoutType(layout: AllotmentLayout): LayoutType {\r\n const childCount = layout.children.length;\r\n\r\n if (childCount === 0 || childCount === 1) {\r\n return 'single';\r\n }\r\n\r\n if (childCount === 2) {\r\n const hasNestedGroups = layout.children.some(\r\n (child) => typeof child !== 'string'\r\n );\r\n\r\n if (!hasNestedGroups) {\r\n return layout.direction === 'horizontal' ? 'split-h' : 'split-v';\r\n }\r\n\r\n const allNested = layout.children.every(\r\n (child) => typeof child !== 'string'\r\n );\r\n if (allNested) {\r\n return 'grid-2x2';\r\n }\r\n }\r\n\r\n return layout.direction === 'horizontal' ? 'split-h' : 'split-v';\r\n}\r\n\r\nfunction formatTime(timestamp: number): string {\r\n const now = Date.now();\r\n const diff = now - timestamp;\r\n\r\n if (diff < 60000) return 'Just now';\r\n if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`;\r\n if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`;\r\n return new Date(timestamp).toLocaleDateString();\r\n}\r\n\r\n// ========== Component ==========\r\n\r\nexport function CliViewerToolbar({\r\n isFullscreen,\r\n onToggleFullscreen,\r\n}: CliViewerToolbarProps) {\r\n const { formatMessage } = useIntl();\r\n const navigate = useNavigate();\r\n\r\n // Store hooks\r\n const layout = useViewerLayout();\r\n const focusedPaneId = useFocusedPaneId();\r\n const { initializeDefaultLayout, reset, addTab } = useViewerStore();\r\n\r\n // CLI Stream Store\r\n const executions = useCliStreamStore((state) => state.executions);\r\n\r\n // Detect current layout type\r\n const currentLayoutType = useMemo(() => detectLayoutType(layout), [layout]);\r\n\r\n // Get execution count for display\r\n const executionCount = useMemo(() => Object.keys(executions).length, [executions]);\r\n const runningCount = useMemo(\r\n () => Object.values(executions).filter((e) => e.status === 'running').length,\r\n [executions]\r\n );\r\n\r\n // Handle back navigation\r\n const handleBack = useCallback(() => {\r\n navigate(-1);\r\n }, [navigate]);\r\n\r\n // Handle layout change\r\n const handleLayoutChange = useCallback(\r\n (layoutType: LayoutType) => {\r\n initializeDefaultLayout(layoutType);\r\n },\r\n [initializeDefaultLayout]\r\n );\r\n\r\n // Handle reset\r\n const handleReset = useCallback(() => {\r\n reset();\r\n initializeDefaultLayout(DEFAULT_LAYOUT);\r\n }, [reset, initializeDefaultLayout]);\r\n\r\n return (\r\n <div className=\"flex items-center gap-1 px-2 h-[40px] border-b border-border bg-muted/30 shrink-0\">\r\n {/* Back button */}\r\n <button\r\n onClick={handleBack}\r\n className={cn(\r\n 'p-1.5 rounded transition-colors',\r\n 'text-muted-foreground hover:text-foreground hover:bg-muted'\r\n )}\r\n title={formatMessage({ id: 'cliViewer.toolbar.back', defaultMessage: 'Back' })}\r\n >\r\n <ArrowLeft className=\"w-3.5 h-3.5\" />\r\n </button>\r\n\r\n {/* Separator */}\r\n <div className=\"w-px h-5 bg-border mx-1\" />\r\n\r\n {/* Layout presets */}\r\n {LAYOUT_PRESETS.map((preset) => {\r\n const isActive = currentLayoutType === preset.id;\r\n return (\r\n <button\r\n key={preset.id}\r\n onClick={() => handleLayoutChange(preset.id)}\r\n className={cn(\r\n 'p-1.5 rounded transition-colors',\r\n isActive\r\n ? 'bg-primary/10 text-primary'\r\n : 'text-muted-foreground hover:text-foreground hover:bg-muted'\r\n )}\r\n title={formatMessage({ id: preset.labelId })}\r\n >\r\n <preset.icon className=\"w-3.5 h-3.5\" />\r\n </button>\r\n );\r\n })}\r\n\r\n {/* Separator */}\r\n <div className=\"w-px h-5 bg-border mx-1\" />\r\n\r\n {/* Add execution button - Inline Picker */}\r\n <AddExecutionButton focusedPaneId={focusedPaneId} />\r\n\r\n {/* Separator */}\r\n <div className=\"w-px h-5 bg-border mx-1\" />\r\n\r\n {/* Reset button */}\r\n <button\r\n onClick={handleReset}\r\n className={cn(\r\n 'p-1.5 rounded transition-colors',\r\n 'text-muted-foreground hover:text-foreground hover:bg-muted'\r\n )}\r\n title={formatMessage({ id: 'cliViewer.toolbar.clearAll' })}\r\n >\r\n <RotateCcw className=\"w-3.5 h-3.5\" />\r\n </button>\r\n\r\n {/* Right side - Execution selector & fullscreen */}\r\n <div className=\"flex items-center gap-1 ml-auto\">\r\n {/* Execution dropdown */}\r\n <DropdownMenu>\r\n <DropdownMenuTrigger asChild>\r\n <button\r\n className={cn(\r\n 'flex items-center gap-1.5 px-2.5 py-1.5 rounded-md text-xs transition-colors',\r\n 'text-muted-foreground hover:text-foreground hover:bg-muted'\r\n )}\r\n >\r\n <Terminal className=\"w-3.5 h-3.5\" />\r\n <span>\r\n {runningCount > 0\r\n ? `${runningCount} ${formatMessage({ id: 'cliViewer.toolbar.running', defaultMessage: 'running' })}`\r\n : `${executionCount} ${formatMessage({ id: 'cliViewer.toolbar.executions', defaultMessage: 'executions' })}`}\r\n </span>\r\n {runningCount > 0 && (\r\n <span className=\"w-2 h-2 rounded-full bg-green-500 animate-pulse\" />\r\n )}\r\n <ChevronDown className=\"w-3 h-3\" />\r\n </button>\r\n </DropdownMenuTrigger>\r\n <DropdownMenuContent align=\"end\" sideOffset={4}>\r\n <DropdownMenuLabel>\r\n {formatMessage({ id: 'cliViewer.toolbar.executionsList', defaultMessage: 'Recent Executions' })}\r\n </DropdownMenuLabel>\r\n <DropdownMenuSeparator />\r\n {Object.entries(executions).length === 0 ? (\r\n <div className=\"px-2 py-4 text-center text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'cliViewer.picker.noExecutions', defaultMessage: 'No executions available' })}\r\n </div>\r\n ) : (\r\n Object.entries(executions)\r\n .sort((a, b) => b[1].startTime - a[1].startTime)\r\n .slice(0, 10)\r\n .map(([id, exec]) => (\r\n <DropdownMenuItem\r\n key={id}\r\n className=\"flex items-center gap-2 text-xs\"\r\n onClick={() => {\r\n if (focusedPaneId) {\r\n const title = `${exec.tool}-${exec.mode}`;\r\n addTab(focusedPaneId, id, title);\r\n }\r\n }}\r\n >\r\n <span\r\n className={cn(\r\n 'w-2 h-2 rounded-full shrink-0',\r\n STATUS_CONFIG[exec.status].color\r\n )}\r\n />\r\n <span className=\"truncate flex-1\">{exec.tool}</span>\r\n <span className=\"text-muted-foreground\">{exec.mode}</span>\r\n </DropdownMenuItem>\r\n ))\r\n )}\r\n </DropdownMenuContent>\r\n </DropdownMenu>\r\n\r\n {/* Separator */}\r\n <div className=\"w-px h-5 bg-border mx-1\" />\r\n\r\n {/* Fullscreen toggle */}\r\n <button\r\n onClick={onToggleFullscreen}\r\n className={cn(\r\n 'p-1.5 rounded transition-colors',\r\n isFullscreen\r\n ? 'bg-primary/10 text-primary'\r\n : 'text-muted-foreground hover:text-foreground hover:bg-muted'\r\n )}\r\n title={\r\n isFullscreen\r\n ? formatMessage({ id: 'cliViewer.toolbar.exitFullscreen', defaultMessage: 'Exit Fullscreen' })\r\n : formatMessage({ id: 'cliViewer.toolbar.fullscreen', defaultMessage: 'Fullscreen' })\r\n }\r\n >\r\n {isFullscreen ? (\r\n <Minimize2 className=\"w-3.5 h-3.5\" />\r\n ) : (\r\n <Maximize2 className=\"w-3.5 h-3.5\" />\r\n )}\r\n </button>\r\n\r\n {/* Page title */}\r\n <span className=\"text-xs text-muted-foreground font-medium ml-2\">\r\n {formatMessage({ id: 'cliViewer.page.title' })}\r\n </span>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// ========== Add Execution Button Sub-Component ==========\r\n\r\nfunction AddExecutionButton({ focusedPaneId }: { focusedPaneId: string | null }) {\r\n const { formatMessage } = useIntl();\r\n const [open, setOpen] = useState(false);\r\n const [searchQuery, setSearchQuery] = useState('');\r\n\r\n const executions = useCliStreamStore((state) => state.executions);\r\n const panes = useViewerStore((state) => state.panes);\r\n const addTab = useViewerStore((state) => state.addTab);\r\n\r\n // Get existing execution IDs in current pane\r\n const existingExecutionIds = useMemo(() => {\r\n if (!focusedPaneId) return new Set<string>();\r\n const pane = panes[focusedPaneId];\r\n if (!pane) return new Set<string>();\r\n return new Set(pane.tabs.map((tab) => tab.executionId));\r\n }, [panes, focusedPaneId]);\r\n\r\n // Filter executions\r\n const filteredExecutions = useMemo(() => {\r\n const entries = Object.entries(executions);\r\n const filtered = entries.filter(([id, exec]) => {\r\n if (!searchQuery) return true;\r\n const query = searchQuery.toLowerCase();\r\n return (\r\n id.toLowerCase().includes(query) ||\r\n exec.tool.toLowerCase().includes(query) ||\r\n exec.mode.toLowerCase().includes(query)\r\n );\r\n });\r\n filtered.sort((a, b) => b[1].startTime - a[1].startTime);\r\n return filtered;\r\n }, [executions, searchQuery]);\r\n\r\n const handleSelect = useCallback((executionId: string, tool: string, mode: string) => {\r\n if (focusedPaneId) {\r\n addTab(focusedPaneId, executionId, `${tool}-${mode}`);\r\n setOpen(false);\r\n setSearchQuery('');\r\n }\r\n }, [focusedPaneId, addTab]);\r\n\r\n if (!focusedPaneId) return null;\r\n\r\n return (\r\n <Dialog open={open} onOpenChange={setOpen}>\r\n <DialogTrigger asChild>\r\n <button\r\n className={cn(\r\n 'flex items-center gap-1.5 px-2.5 py-1.5 rounded-md text-xs transition-colors',\r\n 'text-muted-foreground hover:text-foreground hover:bg-muted'\r\n )}\r\n >\r\n <Plus className=\"w-3.5 h-3.5\" />\r\n <span>{formatMessage({ id: 'cliViewer.toolbar.addExecution', defaultMessage: 'Add' })}</span>\r\n </button>\r\n </DialogTrigger>\r\n\r\n <DialogContent className=\"sm:max-w-md\">\r\n <DialogHeader>\r\n <DialogTitle>\r\n {formatMessage({ id: 'cliViewer.picker.selectExecution', defaultMessage: 'Select Execution' })}\r\n </DialogTitle>\r\n </DialogHeader>\r\n\r\n {/* Search input */}\r\n <div className=\"relative\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\r\n <Input\r\n placeholder={formatMessage({\r\n id: 'cliViewer.picker.searchExecutions',\r\n defaultMessage: 'Search executions...'\r\n })}\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n className=\"pl-9\"\r\n />\r\n </div>\r\n\r\n {/* Execution list */}\r\n <div className=\"max-h-[300px] overflow-y-auto space-y-2\">\r\n {filteredExecutions.length === 0 ? (\r\n <div className=\"flex flex-col items-center justify-center py-8 text-center\">\r\n <Terminal className=\"h-8 w-8 text-muted-foreground mb-2\" />\r\n <p className=\"text-sm text-muted-foreground\">\r\n {Object.keys(executions).length === 0\r\n ? formatMessage({ id: 'cliViewer.picker.noExecutions', defaultMessage: 'No executions available' })\r\n : formatMessage({ id: 'cliViewer.picker.noMatchingExecutions', defaultMessage: 'No matching executions' })}\r\n </p>\r\n </div>\r\n ) : (\r\n filteredExecutions.map(([id, exec]) => {\r\n const isAlreadyOpen = existingExecutionIds.has(id);\r\n return (\r\n <div key={id} className=\"relative\">\r\n <button\r\n onClick={() => handleSelect(id, exec.tool, exec.mode)}\r\n disabled={isAlreadyOpen}\r\n className={cn(\r\n 'w-full flex items-center gap-3 p-3 rounded-lg',\r\n 'border border-border/50 bg-muted/30',\r\n 'hover:bg-muted/50 hover:border-border',\r\n 'transition-all duration-150',\r\n 'text-left',\r\n isAlreadyOpen && 'opacity-50 cursor-not-allowed'\r\n )}\r\n >\r\n {/* Tool icon */}\r\n <div className=\"flex items-center justify-center w-8 h-8 rounded-md bg-primary/10\">\r\n <Terminal className=\"h-4 w-4 text-primary\" />\r\n </div>\r\n\r\n {/* Execution info */}\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium text-sm text-foreground truncate\">\r\n {exec.tool}-{exec.mode}\r\n </span>\r\n <span\r\n className={cn(\r\n 'w-2 h-2 rounded-full shrink-0',\r\n STATUS_CONFIG[exec.status].color\r\n )}\r\n />\r\n </div>\r\n <span className=\"text-xs text-muted-foreground truncate\">\r\n {id}\r\n </span>\r\n </div>\r\n\r\n {/* Time */}\r\n <div className=\"flex items-center gap-1 text-xs text-muted-foreground shrink-0\">\r\n <Clock className=\"h-3 w-3\" />\r\n <span>{formatTime(exec.startTime)}</span>\r\n </div>\r\n </button>\r\n {isAlreadyOpen && (\r\n <div className=\"absolute inset-0 bg-background/60 rounded-lg flex items-center justify-center\">\r\n <span className=\"text-xs text-muted-foreground bg-muted px-2 py-1 rounded\">\r\n {formatMessage({ id: 'cliViewer.picker.alreadyOpen', defaultMessage: 'Already open' })}\r\n </span>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })\r\n )}\r\n </div>\r\n </DialogContent>\r\n </Dialog>\r\n );\r\n}\r\n\r\nexport default CliViewerToolbar;\r\n","// ========================================\n// CliViewerPage Utilities\n// ========================================\n\nimport type { PaneId, PaneState, TabId } from '@/stores/viewerStore';\n\nexport function getStaleViewerTabs(\n panes: Record<PaneId, PaneState>,\n executions: Record<string, unknown>\n): Array<{ paneId: PaneId; tabId: TabId; executionId: string }> {\n const executionIds = new Set(Object.keys(executions));\n\n return Object.entries(panes).flatMap(([paneId, pane]) => (\n pane.tabs\n .filter((tab) => !executionIds.has(tab.executionId))\n .map((tab) => ({\n paneId,\n tabId: tab.id,\n executionId: tab.executionId,\n }))\n ));\n}\n","// ========================================\r\n// CLI Viewer Page\r\n// ========================================\r\n// Multi-pane CLI output viewer with configurable layouts\r\n// Integrates with viewerStore for state management\r\n// Includes WebSocket integration and execution recovery\r\n\r\nimport { useEffect, useRef, useState } from 'react';\r\nimport { useSearchParams } from 'react-router-dom';\r\nimport { LayoutContainer, CliViewerToolbar } from '@/components/cli-viewer';\r\nimport {\r\n useViewerStore,\r\n useViewerLayout,\r\n useViewerPanes,\r\n useFocusedPaneId,\r\n type AllotmentLayout,\r\n} from '@/stores/viewerStore';\r\nimport { useCliStreamStore } from '@/stores/cliStreamStore';\r\nimport { useActiveCliExecutions } from '@/hooks/useActiveCliExecutions';\r\nimport { useCliStreamWebSocket } from '@/hooks/useCliStreamWebSocket';\r\nimport { getStaleViewerTabs } from './cliViewerPage.utils';\r\n\r\n// ========================================\r\n// Constants\r\n// ========================================\r\n\r\nconst DEFAULT_LAYOUT = 'split-h' as const;\r\n\r\n// ========================================\r\n// Helper Functions\r\n// ========================================\r\n\r\n/**\r\n * Count total panes in layout\r\n */\r\nfunction countPanes(layout: AllotmentLayout): number {\r\n let count = 0;\r\n const traverse = (children: (string | AllotmentLayout)[]) => {\r\n for (const child of children) {\r\n if (typeof child === 'string') {\r\n count++;\r\n } else {\r\n traverse(child.children);\r\n }\r\n }\r\n };\r\n traverse(layout.children);\r\n return count;\r\n}\r\n\r\n// ========================================\r\n// Main Component\r\n// ========================================\r\n\r\nexport function CliViewerPage() {\r\n const [searchParams, setSearchParams] = useSearchParams();\r\n\r\n // Fullscreen state\r\n const [isFullscreen, setIsFullscreen] = useState(false);\r\n\r\n // Store hooks\r\n const layout = useViewerLayout();\r\n const panes = useViewerPanes();\r\n const focusedPaneId = useFocusedPaneId();\r\n const { initializeDefaultLayout, addTab, removeTab } = useViewerStore();\r\n\r\n // CLI Stream Store hooks\r\n const executions = useCliStreamStore((state) => state.executions);\r\n\r\n // Active execution sync from server\r\n const { isLoading: isSyncing, isFetching: isRefreshing } = useActiveCliExecutions(true);\r\n\r\n // CENTRALIZED WebSocket handler - processes each message only ONCE globally\r\n useCliStreamWebSocket();\r\n\r\n // Auto-add new executions as tabs, distributing across available panes\r\n const addedExecutionsRef = useRef<Set<string>>(new Set());\r\n\r\n // FIX-001: Initialize addedExecutionsRef with existing tab executionIds on mount\r\n // This prevents duplicate tabs from being added after page refresh\r\n useEffect(() => {\r\n // Extract executionIds from all existing tabs in all panes\r\n const existingExecutionIds = Object.values(panes).flatMap((pane) =>\r\n pane.tabs.map((tab) => tab.executionId)\r\n );\r\n existingExecutionIds.forEach((id) => addedExecutionsRef.current.add(id));\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []); // Empty deps - only run once on mount\r\n\r\n useEffect(() => {\r\n const paneIds = Object.keys(panes);\r\n if (paneIds.length === 0) return;\r\n\r\n const storeAddTab = useViewerStore.getState().addTab;\r\n const newExecutionIds = Object.keys(executions).filter(\r\n (id) => !addedExecutionsRef.current.has(id)\r\n );\r\n\r\n if (newExecutionIds.length === 0) return;\r\n\r\n newExecutionIds.forEach((executionId, index) => {\r\n addedExecutionsRef.current.add(executionId);\r\n const exec = executions[executionId];\r\n const toolShort = exec.tool.split('-')[0];\r\n const targetPaneId = paneIds[index % paneIds.length];\r\n storeAddTab(targetPaneId, executionId, `${toolShort} (${exec.mode})`);\r\n });\r\n }, [executions, panes]);\r\n\r\n useEffect(() => {\r\n if (isSyncing || isRefreshing) return;\r\n\r\n const staleTabs = getStaleViewerTabs(panes, executions);\r\n if (staleTabs.length === 0) return;\r\n\r\n staleTabs.forEach(({ paneId, tabId, executionId }) => {\r\n addedExecutionsRef.current.delete(executionId);\r\n removeTab(paneId, tabId);\r\n });\r\n }, [executions, isRefreshing, isSyncing, panes, removeTab]);\r\n\r\n // Initialize layout if empty\r\n useEffect(() => {\r\n const paneCount = countPanes(layout);\r\n if (paneCount === 0) {\r\n initializeDefaultLayout(DEFAULT_LAYOUT);\r\n }\r\n }, [layout, initializeDefaultLayout]);\r\n\r\n // Handle executionId from URL params\r\n useEffect(() => {\r\n const executionId = searchParams.get('executionId');\r\n if (executionId && focusedPaneId) {\r\n addTab(focusedPaneId, executionId, `Execution ${executionId.slice(0, 8)}`);\r\n setSearchParams((prev) => {\r\n const newParams = new URLSearchParams(prev);\r\n newParams.delete('executionId');\r\n return newParams;\r\n });\r\n }\r\n }, [searchParams, focusedPaneId, addTab, setSearchParams]);\r\n\r\n // Toggle fullscreen handler\r\n const handleToggleFullscreen = () => {\r\n setIsFullscreen((prev) => !prev);\r\n };\r\n\r\n return (\r\n <div className=\"h-full flex flex-col\">\r\n {/* ======================================== */}\r\n {/* Toolbar */}\r\n {/* ======================================== */}\r\n <CliViewerToolbar\r\n isFullscreen={isFullscreen}\r\n onToggleFullscreen={handleToggleFullscreen}\r\n />\r\n\r\n {/* ======================================== */}\r\n {/* Layout Container */}\r\n {/* ======================================== */}\r\n <div className=\"flex-1 min-h-0 bg-background\">\r\n <LayoutContainer />\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport default CliViewerPage;\r\n"],"names":["Ellipsis","createLucideIcon","Keyboard","PinOff","Pin","STATUS_CONFIG","Loader2","CheckCircle2","XCircle","formatTime","timestamp","diff","getExecutionTitle","_executionId","execution","ExecutionItem","executionId","onSelect","statusConfig","StatusIcon","jsxs","cn","jsx","Terminal","Clock","ExecutionPicker","paneId","className","formatMessage","useIntl","open","setOpen","useState","searchQuery","setSearchQuery","executions","useCliStreamStore","state","addTab","useViewerStore","panes","existingExecutionIds","useMemo","pane","tab","filteredExecutions","filtered","id","exec","query","a","b","handleSelect","useCallback","title","totalCount","availableCount","Dialog","DialogTrigger","Button","Plus","DialogContent","DialogHeader","DialogTitle","Search","Input","e","isAlreadyOpen","STATUS_COLORS","TAB_DRAG_DATA_TYPE","TabItem","isActive","onClose","onTogglePin","isDragging","setIsDragging","isDragOver","setIsDragOver","moveTab","useViewerPanes","displayTitle","handleDragStart","dragData","handleDragEnd","handleDragOver","handleDragLeave","handleDrop","rawData","sourceTabId","sourcePaneId","targetPane","targetIndex","t","err","X","TabBar","setActiveTab","removeTab","togglePinTab","addPane","removePane","handleTabSelect","tabId","handleTabClose","handleTogglePin","handleSplitHorizontal","handleSplitVertical","handleClosePane","handleContainerDragOver","handleContainerDragLeave","handleContainerDrop","sortedTabs","DropdownMenu","DropdownMenuTrigger","MoreHorizontal","DropdownMenuContent","DropdownMenuItem","SplitSquareHorizontal","SplitSquareVertical","DropdownMenuSeparator","EmptyTabState","ExecutionNotFoundState","ExecutionLoadingState","OutputLineItem","line","typeStyles","MessageRenderer","CliOutputDisplay","MonitorBody","index","ContentArea","activeTab","selectActiveTab","isSyncing","useActiveCliExecutions","content","PaneContent","focusedPaneId","useFocusedPaneId","setFocusedPane","isFocused","handleClick","EmptyState","Play","isPaneId","child","LayoutGroupRenderer","group","minSize","onSizeChange","validChildren","Allotment","LayoutContainer","layout","useViewerLayout","isUpdatingRef","useRef","prevSizesRef","useEffect","handleSizeChange","sizes","s","i","prev","LAYOUT_PRESETS","Square","Columns2","Rows2","LayoutGrid","DEFAULT_LAYOUT","detectLayoutType","childCount","CliViewerToolbar","isFullscreen","onToggleFullscreen","navigate","useNavigate","initializeDefaultLayout","reset","currentLayoutType","executionCount","runningCount","handleBack","handleLayoutChange","layoutType","handleReset","ArrowLeft","preset","AddExecutionButton","RotateCcw","ChevronDown","DropdownMenuLabel","Minimize2","Maximize2","tool","mode","getStaleViewerTabs","executionIds","countPanes","count","traverse","children","CliViewerPage","searchParams","setSearchParams","useSearchParams","setIsFullscreen","isRefreshing","useCliStreamWebSocket","addedExecutionsRef","paneIds","storeAddTab","newExecutionIds","toolShort","targetPaneId","staleTabs","newParams","handleToggleFullscreen"],"mappings":"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","x_google_ignoreList":[0,1,2,3]}
1
+ {"version":3,"file":"CliViewerPage-9YxGyLxh.js","sources":["../../../../node_modules/lucide-react/dist/esm/icons/ellipsis.js","../../../../node_modules/lucide-react/dist/esm/icons/keyboard.js","../../../../node_modules/lucide-react/dist/esm/icons/pin-off.js","../../../../node_modules/lucide-react/dist/esm/icons/pin.js","../../src/components/cli-viewer/ExecutionPicker.tsx","../../src/components/cli-viewer/TabBar.tsx","../../src/components/cli-viewer/ContentArea.tsx","../../src/components/cli-viewer/PaneContent.tsx","../../src/components/cli-viewer/EmptyState.tsx","../../src/components/cli-viewer/LayoutContainer.tsx","../../src/components/cli-viewer/CliViewerToolbar.tsx","../../src/pages/cliViewerPage.utils.ts","../../src/pages/CliViewerPage.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Ellipsis = createLucideIcon(\"Ellipsis\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"1\", key: \"41hilf\" }],\n [\"circle\", { cx: \"19\", cy: \"12\", r: \"1\", key: \"1wjl8i\" }],\n [\"circle\", { cx: \"5\", cy: \"12\", r: \"1\", key: \"1pcz8c\" }]\n]);\n\nexport { Ellipsis as default };\n//# sourceMappingURL=ellipsis.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Keyboard = createLucideIcon(\"Keyboard\", [\n [\"path\", { d: \"M10 8h.01\", key: \"1r9ogq\" }],\n [\"path\", { d: \"M12 12h.01\", key: \"1mp3jc\" }],\n [\"path\", { d: \"M14 8h.01\", key: \"1primd\" }],\n [\"path\", { d: \"M16 12h.01\", key: \"1l6xoz\" }],\n [\"path\", { d: \"M18 8h.01\", key: \"emo2bl\" }],\n [\"path\", { d: \"M6 8h.01\", key: \"x9i8wu\" }],\n [\"path\", { d: \"M7 16h10\", key: \"wp8him\" }],\n [\"path\", { d: \"M8 12h.01\", key: \"czm47f\" }],\n [\"rect\", { width: \"20\", height: \"16\", x: \"2\", y: \"4\", rx: \"2\", key: \"18n3k1\" }]\n]);\n\nexport { Keyboard as default };\n//# sourceMappingURL=keyboard.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst PinOff = createLucideIcon(\"PinOff\", [\n [\"path\", { d: \"M12 17v5\", key: \"bb1du9\" }],\n [\"path\", { d: \"M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89\", key: \"znwnzq\" }],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }],\n [\n \"path\",\n {\n d: \"M9 9v1.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h11\",\n key: \"c9qhm2\"\n }\n ]\n]);\n\nexport { PinOff as default };\n//# sourceMappingURL=pin-off.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Pin = createLucideIcon(\"Pin\", [\n [\"path\", { d: \"M12 17v5\", key: \"bb1du9\" }],\n [\n \"path\",\n {\n d: \"M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z\",\n key: \"1nkz8b\"\n }\n ]\n]);\n\nexport { Pin as default };\n//# sourceMappingURL=pin.js.map\n","// ========================================\r\n// ExecutionPicker Component\r\n// ========================================\r\n// Dialog for selecting CLI executions to open as tabs\r\n\r\nimport { useState, useMemo, useCallback } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { Plus, Search, Terminal, Clock, CheckCircle2, XCircle, Loader2 } from 'lucide-react';\r\nimport { cn } from '@/lib/utils';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Input } from '@/components/ui/Input';\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogHeader,\r\n DialogTitle,\r\n DialogTrigger,\r\n} from '@/components/ui/Dialog';\r\nimport {\r\n useCliStreamStore,\r\n type CliExecutionState,\r\n type CliExecutionStatus,\r\n} from '@/stores/cliStreamStore';\r\nimport { useViewerStore, type PaneId } from '@/stores/viewerStore';\r\n\r\n// ========== Types ==========\r\n\r\nexport interface ExecutionPickerProps {\r\n paneId: PaneId;\r\n className?: string;\r\n}\r\n\r\n// ========== Constants ==========\r\n\r\nconst STATUS_CONFIG: Record<CliExecutionStatus, { icon: typeof CheckCircle2; color: string; label: string }> = {\r\n running: {\r\n icon: Loader2,\r\n color: 'text-indigo-500',\r\n label: 'Running',\r\n },\r\n completed: {\r\n icon: CheckCircle2,\r\n color: 'text-emerald-500',\r\n label: 'Completed',\r\n },\r\n error: {\r\n icon: XCircle,\r\n color: 'text-rose-500',\r\n label: 'Error',\r\n },\r\n};\r\n\r\n// ========== Helper Functions ==========\r\n\r\n/**\r\n * Format timestamp to relative or absolute time\r\n */\r\nfunction formatTime(timestamp: number): string {\r\n const now = Date.now();\r\n const diff = now - timestamp;\r\n\r\n if (diff < 60000) {\r\n return 'Just now';\r\n } else if (diff < 3600000) {\r\n const minutes = Math.floor(diff / 60000);\r\n return `${minutes}m ago`;\r\n } else if (diff < 86400000) {\r\n const hours = Math.floor(diff / 3600000);\r\n return `${hours}h ago`;\r\n } else {\r\n return new Date(timestamp).toLocaleDateString();\r\n }\r\n}\r\n\r\n/**\r\n * Get execution display title\r\n */\r\nfunction getExecutionTitle(_executionId: string, execution: CliExecutionState): string {\r\n return `${execution.tool}-${execution.mode}`;\r\n}\r\n\r\n// ========== Sub-Components ==========\r\n\r\ninterface ExecutionItemProps {\r\n executionId: string;\r\n execution: CliExecutionState;\r\n onSelect: () => void;\r\n}\r\n\r\n/**\r\n * Single execution item in the picker list\r\n */\r\nfunction ExecutionItem({ executionId, execution, onSelect }: ExecutionItemProps) {\r\n const statusConfig = STATUS_CONFIG[execution.status];\r\n const StatusIcon = statusConfig.icon;\r\n\r\n return (\r\n <button\r\n onClick={onSelect}\r\n className={cn(\r\n 'w-full flex items-center gap-3 p-3 rounded-lg',\r\n 'border border-border/50 bg-muted/30',\r\n 'hover:bg-muted/50 hover:border-border',\r\n 'transition-all duration-150',\r\n 'text-left'\r\n )}\r\n >\r\n {/* Tool icon */}\r\n <div className=\"flex items-center justify-center w-8 h-8 rounded-md bg-primary/10\">\r\n <Terminal className=\"h-4 w-4 text-primary\" />\r\n </div>\r\n\r\n {/* Execution info */}\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium text-sm text-foreground truncate\">\r\n {getExecutionTitle(executionId, execution)}\r\n </span>\r\n <StatusIcon\r\n className={cn(\r\n 'h-3.5 w-3.5 shrink-0',\r\n statusConfig.color,\r\n execution.status === 'running' && 'animate-spin'\r\n )}\r\n />\r\n </div>\r\n <div className=\"flex items-center gap-2 mt-0.5\">\r\n <span className=\"text-xs text-muted-foreground truncate\">\r\n {executionId}\r\n </span>\r\n </div>\r\n </div>\r\n\r\n {/* Time */}\r\n <div className=\"flex items-center gap-1 text-xs text-muted-foreground shrink-0\">\r\n <Clock className=\"h-3 w-3\" />\r\n <span>{formatTime(execution.startTime)}</span>\r\n </div>\r\n </button>\r\n );\r\n}\r\n\r\n// ========== Main Component ==========\r\n\r\n/**\r\n * ExecutionPicker - Dialog for selecting CLI executions to open as tabs\r\n *\r\n * Features:\r\n * - Lists all available CLI executions from store\r\n * - Search/filter by tool name or execution ID\r\n * - Shows execution status, tool, and timestamp\r\n * - Click to add as new tab in the specified pane\r\n */\r\nexport function ExecutionPicker({ paneId, className }: ExecutionPickerProps) {\r\n const { formatMessage } = useIntl();\r\n const [open, setOpen] = useState(false);\r\n const [searchQuery, setSearchQuery] = useState('');\r\n\r\n // Store hooks\r\n const executions = useCliStreamStore((state) => state.executions);\r\n const addTab = useViewerStore((state) => state.addTab);\r\n const panes = useViewerStore((state) => state.panes);\r\n\r\n // Get current pane's existing execution IDs\r\n const existingExecutionIds = useMemo(() => {\r\n const pane = panes[paneId];\r\n if (!pane) return new Set<string>();\r\n return new Set(pane.tabs.map((tab) => tab.executionId));\r\n }, [panes, paneId]);\r\n\r\n // Filter and sort executions\r\n const filteredExecutions = useMemo(() => {\r\n const entries = Object.entries(executions);\r\n\r\n // Filter by search query\r\n const filtered = entries.filter(([id, exec]) => {\r\n if (!searchQuery) return true;\r\n const query = searchQuery.toLowerCase();\r\n return (\r\n id.toLowerCase().includes(query) ||\r\n exec.tool.toLowerCase().includes(query) ||\r\n exec.mode.toLowerCase().includes(query)\r\n );\r\n });\r\n\r\n // Sort by start time (newest first)\r\n filtered.sort((a, b) => b[1].startTime - a[1].startTime);\r\n\r\n return filtered;\r\n }, [executions, searchQuery]);\r\n\r\n // Handle execution selection\r\n const handleSelect = useCallback((executionId: string, execution: CliExecutionState) => {\r\n const title = getExecutionTitle(executionId, execution);\r\n addTab(paneId, executionId, title);\r\n setOpen(false);\r\n setSearchQuery('');\r\n }, [paneId, addTab]);\r\n\r\n // Count available vs total\r\n const totalCount = Object.keys(executions).length;\r\n const availableCount = filteredExecutions.filter(\r\n ([id]) => !existingExecutionIds.has(id)\r\n ).length;\r\n\r\n return (\r\n <Dialog open={open} onOpenChange={setOpen}>\r\n <DialogTrigger asChild>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n className={cn('h-6 w-6 shrink-0', className)}\r\n aria-label={formatMessage({\r\n id: 'cliViewer.tabs.addTab',\r\n defaultMessage: 'Add tab'\r\n })}\r\n >\r\n <Plus className=\"h-4 w-4\" />\r\n </Button>\r\n </DialogTrigger>\r\n\r\n <DialogContent className=\"sm:max-w-md\">\r\n <DialogHeader>\r\n <DialogTitle>\r\n {formatMessage({\r\n id: 'cliViewer.picker.selectExecution',\r\n defaultMessage: 'Select Execution'\r\n })}\r\n </DialogTitle>\r\n </DialogHeader>\r\n\r\n {/* Search input */}\r\n <div className=\"relative\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\r\n <Input\r\n placeholder={formatMessage({\r\n id: 'cliViewer.picker.searchExecutions',\r\n defaultMessage: 'Search executions...'\r\n })}\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n className=\"pl-9\"\r\n />\r\n </div>\r\n\r\n {/* Execution list */}\r\n <div className=\"max-h-[300px] overflow-y-auto space-y-2\">\r\n {filteredExecutions.length === 0 ? (\r\n <div className=\"flex flex-col items-center justify-center py-8 text-center\">\r\n <Terminal className=\"h-8 w-8 text-muted-foreground mb-2\" />\r\n <p className=\"text-sm text-muted-foreground\">\r\n {totalCount === 0\r\n ? formatMessage({\r\n id: 'cliViewer.picker.noExecutions',\r\n defaultMessage: 'No executions available'\r\n })\r\n : formatMessage({\r\n id: 'cliViewer.picker.noMatchingExecutions',\r\n defaultMessage: 'No matching executions'\r\n })\r\n }\r\n </p>\r\n </div>\r\n ) : (\r\n filteredExecutions.map(([id, exec]) => {\r\n const isAlreadyOpen = existingExecutionIds.has(id);\r\n return (\r\n <div key={id} className=\"relative\">\r\n <ExecutionItem\r\n executionId={id}\r\n execution={exec}\r\n onSelect={() => handleSelect(id, exec)}\r\n />\r\n {isAlreadyOpen && (\r\n <div className=\"absolute inset-0 bg-background/60 rounded-lg flex items-center justify-center\">\r\n <span className=\"text-xs text-muted-foreground bg-muted px-2 py-1 rounded\">\r\n {formatMessage({\r\n id: 'cliViewer.picker.alreadyOpen',\r\n defaultMessage: 'Already open'\r\n })}\r\n </span>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })\r\n )}\r\n </div>\r\n\r\n {/* Footer with count */}\r\n {totalCount > 0 && (\r\n <div className=\"text-xs text-muted-foreground text-center pt-2 border-t border-border/50\">\r\n {formatMessage(\r\n {\r\n id: 'cliViewer.picker.executionCount',\r\n defaultMessage: '{available} of {total} executions available'\r\n },\r\n { available: availableCount, total: totalCount }\r\n )}\r\n </div>\r\n )}\r\n </DialogContent>\r\n </Dialog>\r\n );\r\n}\r\n\r\nexport default ExecutionPicker;\r\n","// ========================================\n// TabBar Component\n// ========================================\n// Tab management for CLI viewer panes with drag-and-drop support\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { useIntl } from 'react-intl';\nimport { X, Pin, PinOff, MoreHorizontal, SplitSquareHorizontal, SplitSquareVertical } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport { Button } from '@/components/ui/Button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@/components/ui/Dropdown';\nimport {\n useViewerStore,\n useViewerPanes,\n type PaneId,\n type TabState,\n} from '@/stores/viewerStore';\nimport { ExecutionPicker } from './ExecutionPicker';\n\n// ========== Types ==========\n\nexport interface TabBarProps {\n paneId: PaneId;\n className?: string;\n}\n\ninterface TabItemProps {\n tab: TabState;\n paneId: PaneId;\n isActive: boolean;\n onSelect: () => void;\n onClose: (e: React.MouseEvent) => void;\n onTogglePin: (e: React.MouseEvent) => void;\n}\n\n// ========== Constants ==========\n\nconst STATUS_COLORS = {\n running: 'bg-indigo-500 shadow-[0_0_6px_rgba(99,102,241,0.4)] animate-pulse',\n completed: 'bg-emerald-500',\n error: 'bg-rose-500',\n idle: 'bg-slate-400 dark:bg-slate-500',\n};\n\n// ========== Helper Components ==========\n\n// Data transfer key for tab drag-and-drop\nconst TAB_DRAG_DATA_TYPE = 'application/x-cli-viewer-tab';\n\ninterface TabDragData {\n tabId: string;\n sourcePaneId: string;\n}\n\n/**\n * Individual tab item with drag-and-drop support\n */\nfunction TabItem({ tab, paneId, isActive, onSelect, onClose, onTogglePin }: TabItemProps) {\n const [isDragging, setIsDragging] = useState(false);\n const [isDragOver, setIsDragOver] = useState(false);\n const moveTab = useViewerStore((state) => state.moveTab);\n const panes = useViewerPanes();\n\n // Simplify title for display\n const displayTitle = useMemo(() => {\n // If title contains tool name pattern, extract it\n const parts = tab.title.split('-');\n return parts[0] || tab.title;\n }, [tab.title]);\n\n // Drag start handler\n const handleDragStart = useCallback((e: React.DragEvent) => {\n const dragData: TabDragData = {\n tabId: tab.id,\n sourcePaneId: paneId,\n };\n e.dataTransfer.setData(TAB_DRAG_DATA_TYPE, JSON.stringify(dragData));\n e.dataTransfer.effectAllowed = 'move';\n setIsDragging(true);\n }, [tab.id, paneId]);\n\n // Drag end handler\n const handleDragEnd = useCallback(() => {\n setIsDragging(false);\n }, []);\n\n // Drag over handler\n const handleDragOver = useCallback((e: React.DragEvent) => {\n if (e.dataTransfer.types.includes(TAB_DRAG_DATA_TYPE)) {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n setIsDragOver(true);\n }\n }, []);\n\n // Drag leave handler\n const handleDragLeave = useCallback(() => {\n setIsDragOver(false);\n }, []);\n\n // Drop handler\n const handleDrop = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n setIsDragOver(false);\n\n const rawData = e.dataTransfer.getData(TAB_DRAG_DATA_TYPE);\n if (!rawData) return;\n\n try {\n const dragData: TabDragData = JSON.parse(rawData);\n const { tabId: sourceTabId, sourcePaneId } = dragData;\n\n // Don't do anything if dropping on the same tab\n if (sourceTabId === tab.id) return;\n\n // Find the target index\n const targetPane = panes[paneId];\n if (!targetPane) return;\n\n const targetIndex = targetPane.tabs.findIndex((t) => t.id === tab.id);\n if (targetIndex === -1) return;\n\n // Move the tab\n moveTab(sourcePaneId, sourceTabId, paneId, targetIndex);\n } catch (err) {\n console.error('[TabBar] Failed to parse drag data:', err);\n }\n }, [tab.id, paneId, panes, moveTab]);\n\n return (\n <div\n role=\"tab\"\n tabIndex={0}\n draggable={!tab.isPinned}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n onClick={onSelect}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onSelect();\n }\n }}\n className={cn(\n 'group relative flex items-center gap-1.5 px-2.5 py-1.5 rounded-md text-xs',\n 'border border-border/50 shrink-0 min-w-0 max-w-[160px]',\n 'transition-all duration-150 select-none',\n isActive\n ? 'bg-slate-100 dark:bg-slate-800 border-slate-300 dark:border-slate-600 shadow-sm'\n : 'bg-muted/30 hover:bg-muted/50 border-border/30',\n tab.isPinned && 'border-amber-500/50',\n isDragging && 'opacity-50 cursor-grabbing',\n isDragOver && 'border-primary border-dashed bg-primary/10',\n !tab.isPinned && 'cursor-grab'\n )}\n title={tab.title}\n >\n {/* Status indicator dot */}\n <span className={cn('w-1.5 h-1.5 rounded-full shrink-0', STATUS_COLORS.idle)} />\n\n {/* Tool name */}\n <span className=\"font-medium text-[11px] truncate\">{displayTitle}</span>\n\n {/* Pin indicator (always visible if pinned) */}\n {tab.isPinned && (\n <Pin className=\"h-2.5 w-2.5 text-amber-500 shrink-0\" />\n )}\n\n {/* Action buttons (visible on hover) */}\n <div className=\"flex items-center gap-0.5 ml-auto opacity-0 group-hover:opacity-100 transition-opacity\">\n {/* Pin/Unpin button */}\n <button\n onClick={onTogglePin}\n className=\"p-0.5 rounded hover:bg-primary/10 transition-colors\"\n aria-label={tab.isPinned ? 'Unpin tab' : 'Pin tab'}\n >\n {tab.isPinned ? (\n <PinOff className=\"h-2.5 w-2.5 text-amber-500\" />\n ) : (\n <Pin className=\"h-2.5 w-2.5 text-muted-foreground hover:text-amber-500\" />\n )}\n </button>\n\n {/* Close button (hidden if pinned) */}\n {!tab.isPinned && (\n <button\n onClick={onClose}\n className=\"p-0.5 rounded hover:bg-rose-500/20 transition-colors\"\n aria-label=\"Close tab\"\n >\n <X className=\"h-2.5 w-2.5 text-rose-600 dark:text-rose-400\" />\n </button>\n )}\n </div>\n </div>\n );\n}\n\n// ========== Main Component ==========\n\n/**\n * TabBar - Manages tabs within a pane\n *\n * Features:\n * - Tab display with status indicators\n * - Active tab highlighting\n * - Close button on hover\n * - Pin/unpin functionality\n * - Drag-and-drop tab reordering and moving between panes\n * - Pane actions dropdown\n */\nexport function TabBar({ paneId, className }: TabBarProps) {\n const { formatMessage } = useIntl();\n const [isDragOver, setIsDragOver] = useState(false);\n const panes = useViewerPanes();\n const pane = panes[paneId];\n const setActiveTab = useViewerStore((state) => state.setActiveTab);\n const removeTab = useViewerStore((state) => state.removeTab);\n const togglePinTab = useViewerStore((state) => state.togglePinTab);\n const addPane = useViewerStore((state) => state.addPane);\n const removePane = useViewerStore((state) => state.removePane);\n const moveTab = useViewerStore((state) => state.moveTab);\n\n const handleTabSelect = useCallback(\n (tabId: string) => {\n setActiveTab(paneId, tabId);\n },\n [paneId, setActiveTab]\n );\n\n const handleTabClose = useCallback(\n (e: React.MouseEvent, tabId: string) => {\n e.stopPropagation();\n removeTab(paneId, tabId);\n },\n [paneId, removeTab]\n );\n\n const handleTogglePin = useCallback(\n (e: React.MouseEvent, tabId: string) => {\n e.stopPropagation();\n togglePinTab(tabId);\n },\n [togglePinTab]\n );\n\n const handleSplitHorizontal = useCallback(() => {\n addPane(paneId, 'horizontal');\n }, [paneId, addPane]);\n\n const handleSplitVertical = useCallback(() => {\n addPane(paneId, 'vertical');\n }, [paneId, addPane]);\n\n const handleClosePane = useCallback(() => {\n removePane(paneId);\n }, [paneId, removePane]);\n\n // Drag over handler for tab bar container (allows dropping to end of list)\n const handleContainerDragOver = useCallback((e: React.DragEvent) => {\n if (e.dataTransfer.types.includes(TAB_DRAG_DATA_TYPE)) {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n setIsDragOver(true);\n }\n }, []);\n\n // Drag leave handler for container\n const handleContainerDragLeave = useCallback((e: React.DragEvent) => {\n // Only set false if leaving the container entirely, not just moving to a child\n if (!e.currentTarget.contains(e.relatedTarget as Node)) {\n setIsDragOver(false);\n }\n }, []);\n\n // Drop handler for tab bar container (drops to end of list)\n const handleContainerDrop = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n setIsDragOver(false);\n\n const rawData = e.dataTransfer.getData(TAB_DRAG_DATA_TYPE);\n if (!rawData) return;\n\n try {\n const dragData: TabDragData = JSON.parse(rawData);\n const { tabId: sourceTabId, sourcePaneId } = dragData;\n\n // Move the tab to the end of this pane\n const targetIndex = pane?.tabs.length || 0;\n moveTab(sourcePaneId, sourceTabId, paneId, targetIndex);\n } catch (err) {\n console.error('[TabBar] Failed to parse drag data:', err);\n }\n }, [paneId, pane, moveTab]);\n\n // Sort tabs: pinned first, then by order\n const sortedTabs = useMemo(() => {\n if (!pane) return [];\n return [...pane.tabs].sort((a, b) => {\n if (a.isPinned !== b.isPinned) {\n return a.isPinned ? -1 : 1;\n }\n return a.order - b.order;\n });\n }, [pane]);\n\n if (!pane) {\n return null;\n }\n\n return (\n <div\n className={cn(\n 'flex items-center gap-1 px-2 py-1.5',\n 'bg-muted/30 border-b border-border/50',\n 'overflow-x-auto scrollbar-thin scrollbar-thumb-muted scrollbar-track-transparent',\n className\n )}\n >\n {/* Tabs */}\n <div\n onDragOver={handleContainerDragOver}\n onDragLeave={handleContainerDragLeave}\n onDrop={handleContainerDrop}\n className={cn(\n 'flex items-center gap-1 flex-1 min-w-0 overflow-x-auto',\n isDragOver && 'bg-primary/5 border border-primary border-dashed rounded'\n )}\n >\n {sortedTabs.length === 0 ? (\n <span className=\"text-xs text-muted-foreground px-2\">\n {formatMessage({ id: 'cliViewer.tabs.noTabs', defaultMessage: 'No tabs open' })}\n </span>\n ) : (\n sortedTabs.map((tab) => (\n <TabItem\n key={tab.id}\n tab={tab}\n paneId={paneId}\n isActive={pane.activeTabId === tab.id}\n onSelect={() => handleTabSelect(tab.id)}\n onClose={(e) => handleTabClose(e, tab.id)}\n onTogglePin={(e) => handleTogglePin(e, tab.id)}\n />\n ))\n )}\n </div>\n\n {/* Add tab button */}\n <ExecutionPicker paneId={paneId} />\n\n {/* Pane actions dropdown */}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6 shrink-0\"\n aria-label=\"Pane actions\"\n >\n <MoreHorizontal className=\"h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-48\">\n <DropdownMenuItem onClick={handleSplitHorizontal}>\n <SplitSquareHorizontal className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'cliViewer.paneActions.splitHorizontal', defaultMessage: 'Split Horizontal' })}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={handleSplitVertical}>\n <SplitSquareVertical className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'cliViewer.paneActions.splitVertical', defaultMessage: 'Split Vertical' })}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={handleClosePane}\n className=\"text-rose-600 dark:text-rose-400\"\n >\n <X className=\"h-4 w-4 mr-2\" />\n {formatMessage({ id: 'cliViewer.paneActions.closePane', defaultMessage: 'Close Pane' })}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n );\n}\n\nexport default TabBar;\n","// ========================================\n// ContentArea Component\n// ========================================\n// Displays CLI output for the active tab in a pane\n\nimport { useMemo } from 'react';\nimport { useIntl } from 'react-intl';\nimport { Terminal, Loader2 } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport {\n useViewerStore,\n selectActiveTab,\n type PaneId,\n} from '@/stores/viewerStore';\nimport { useCliStreamStore, type CliExecutionState, type CliOutputLine } from '@/stores/cliStreamStore';\nimport { MonitorBody } from '@/components/shared/CliStreamMonitor/MonitorBody';\nimport { MessageRenderer } from '@/components/shared/CliStreamMonitor/MessageRenderer';\nimport { useActiveCliExecutions } from '@/hooks/useActiveCliExecutions';\n\n// ========== Types ==========\n\nexport interface ContentAreaProps {\n paneId: PaneId;\n className?: string;\n}\n\n// ========== Helper Components ==========\n\n/**\n * Empty state when no tab is active\n */\nfunction EmptyTabState() {\n const { formatMessage } = useIntl();\n\n return (\n <div className=\"flex-1 flex flex-col items-center justify-center text-muted-foreground gap-4\">\n <Terminal className=\"h-12 w-12 opacity-30\" />\n <div className=\"text-center\">\n <p className=\"text-sm font-medium\">\n {formatMessage({ id: 'cliViewer.noActiveTab', defaultMessage: 'No active tab' })}\n </p>\n <p className=\"text-xs mt-1\">\n {formatMessage({\n id: 'cliViewer.selectOrCreate',\n defaultMessage: 'Select a tab or start a new CLI execution',\n })}\n </p>\n </div>\n </div>\n );\n}\n\n/**\n * Execution not found state\n */\nfunction ExecutionNotFoundState({ executionId }: { executionId: string }) {\n const { formatMessage } = useIntl();\n\n return (\n <div className=\"flex-1 flex flex-col items-center justify-center text-muted-foreground gap-4\">\n <Terminal className=\"h-12 w-12 opacity-30\" />\n <div className=\"text-center\">\n <p className=\"text-sm font-medium\">\n {formatMessage({ id: 'cliViewer.executionNotFound', defaultMessage: 'Execution not found' })}\n </p>\n <p className=\"text-xs mt-1 font-mono opacity-50\">{executionId}</p>\n </div>\n </div>\n );\n}\n\n/**\n * FIX-002: Loading state while syncing executions from server\n * Shown after page refresh while execution data is being recovered\n */\nfunction ExecutionLoadingState() {\n const { formatMessage } = useIntl();\n\n return (\n <div className=\"flex-1 flex flex-col items-center justify-center text-muted-foreground gap-4\">\n <Loader2 className=\"h-8 w-8 animate-spin opacity-50\" />\n <div className=\"text-center\">\n <p className=\"text-sm\">\n {formatMessage({ id: 'cliViewer.syncingExecution', defaultMessage: 'Syncing execution data...' })}\n </p>\n </div>\n </div>\n );\n}\n\n/**\n * Single output line component with type-based styling\n */\nfunction OutputLineItem({ line }: { line: CliOutputLine }) {\n // Type-based styling\n const typeStyles: Record<CliOutputLine['type'], string> = {\n stdout: 'text-foreground',\n stderr: 'text-rose-600 dark:text-rose-400 bg-rose-500/5',\n thought: 'text-blue-600 dark:text-blue-400 italic bg-blue-500/5',\n system: 'text-amber-600 dark:text-amber-400 bg-amber-500/5',\n metadata: 'text-muted-foreground text-xs',\n tool_call: 'text-emerald-600 dark:text-emerald-400 bg-emerald-500/5 font-mono',\n };\n\n return (\n <div\n className={cn(\n 'px-3 py-1 text-sm',\n 'border-l-2 border-transparent',\n typeStyles[line.type] || 'text-foreground',\n line.type === 'stderr' && 'border-l-rose-500',\n line.type === 'thought' && 'border-l-blue-500',\n line.type === 'system' && 'border-l-amber-500',\n line.type === 'tool_call' && 'border-l-emerald-500'\n )}\n >\n {line.type === 'thought' || line.type === 'tool_call' ? (\n <MessageRenderer content={line.content} format=\"markdown\" />\n ) : (\n <pre className=\"whitespace-pre-wrap break-words font-mono text-xs\">\n {line.content}\n </pre>\n )}\n </div>\n );\n}\n\n/**\n * CLI output display component\n */\nfunction CliOutputDisplay({ execution, executionId }: { execution: CliExecutionState; executionId: string }) {\n const { formatMessage } = useIntl();\n\n if (!execution.output || execution.output.length === 0) {\n return (\n <div className=\"flex-1 flex flex-col items-center justify-center text-muted-foreground gap-4\">\n <Terminal className=\"h-12 w-12 opacity-30\" />\n <div className=\"text-center\">\n <p className=\"text-sm\">\n {execution.status === 'running'\n ? formatMessage({ id: 'cliViewer.waitingForOutput', defaultMessage: 'Waiting for output...' })\n : formatMessage({ id: 'cliViewer.noOutput', defaultMessage: 'No output' })}\n </p>\n {execution.status === 'running' && (\n <Loader2 className=\"h-4 w-4 animate-spin mt-2 mx-auto opacity-50\" />\n )}\n </div>\n </div>\n );\n }\n\n return (\n <MonitorBody autoScroll={execution.status === 'running'} showScrollButton>\n <div className=\"py-2\">\n {execution.output.map((line, index) => (\n <OutputLineItem\n key={`${executionId}-line-${index}`}\n line={line}\n />\n ))}\n </div>\n </MonitorBody>\n );\n}\n\n// ========== Main Component ==========\n\n/**\n * ContentArea - Displays CLI output for active tab\n *\n * Features:\n * - Integration with CliStreamStore for execution data\n * - Auto-scroll during active execution\n * - Empty state handling\n * - Message rendering with proper formatting\n */\nexport function ContentArea({ paneId, className }: ContentAreaProps) {\n // Get active tab using the selector\n const activeTab = useViewerStore((state) => selectActiveTab(state, paneId));\n\n // Get execution data from cliStreamStore\n const executions = useCliStreamStore((state) => state.executions);\n\n // FIX-002: Get loading state from useActiveCliExecutions\n // This helps distinguish between \"not found\" and \"still loading\"\n const { isLoading: isSyncing } = useActiveCliExecutions(true);\n\n const execution = useMemo(() => {\n if (!activeTab?.executionId) return null;\n return executions[activeTab.executionId] || null;\n }, [activeTab?.executionId, executions]);\n\n // Determine what to render\n const content = useMemo(() => {\n // No active tab\n if (!activeTab) {\n return <EmptyTabState />;\n }\n\n // FIX-002: Show loading state while syncing if execution not yet available\n if (!execution && isSyncing) {\n return <ExecutionLoadingState />;\n }\n\n // No execution data found (after sync completed)\n if (!execution) {\n return <ExecutionNotFoundState executionId={activeTab.executionId} />;\n }\n\n // Show CLI output\n return <CliOutputDisplay execution={execution} executionId={activeTab.executionId} />;\n }, [activeTab, execution, isSyncing]);\n\n return (\n <div\n className={cn(\n 'flex-1 min-h-0 flex flex-col overflow-hidden',\n 'bg-background',\n className\n )}\n >\n {content}\n </div>\n );\n}\n\nexport default ContentArea;\n","// ========================================\n// PaneContent Component\n// ========================================\n// Container for TabBar and ContentArea within a pane\n\nimport { useCallback } from 'react';\nimport { cn } from '@/lib/utils';\nimport {\n useViewerStore,\n useViewerPanes,\n useFocusedPaneId,\n type PaneId,\n} from '@/stores/viewerStore';\nimport { TabBar } from './TabBar';\nimport { ContentArea } from './ContentArea';\n\n// ========== Types ==========\n\nexport interface PaneContentProps {\n paneId: PaneId;\n className?: string;\n}\n\n// ========== Component ==========\n\n/**\n * PaneContent - Combines TabBar and ContentArea for a single pane\n *\n * Features:\n * - Focused pane highlighting\n * - Click to focus\n * - TabBar for tab management\n * - ContentArea for CLI output display\n */\nexport function PaneContent({ paneId, className }: PaneContentProps) {\n const panes = useViewerPanes();\n const pane = panes[paneId];\n const focusedPaneId = useFocusedPaneId();\n const setFocusedPane = useViewerStore((state) => state.setFocusedPane);\n\n const isFocused = focusedPaneId === paneId;\n\n const handleClick = useCallback(() => {\n if (!isFocused) {\n setFocusedPane(paneId);\n }\n }, [isFocused, paneId, setFocusedPane]);\n\n if (!pane) {\n return (\n <div className={cn('h-full flex items-center justify-center', className)}>\n <span className=\"text-muted-foreground text-sm\">Pane not found</span>\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n 'h-full flex flex-col',\n 'bg-card dark:bg-surface-900',\n 'border border-border/50',\n 'rounded-sm overflow-hidden',\n // Focus ring when pane is focused\n isFocused && 'ring-1 ring-primary/50',\n className\n )}\n onClick={handleClick}\n role=\"region\"\n aria-label={`CLI Viewer Pane ${paneId}`}\n >\n {/* Tab Bar */}\n <TabBar paneId={paneId} />\n\n {/* Content Area */}\n <ContentArea paneId={paneId} />\n </div>\n );\n}\n\nexport default PaneContent;\n","// ========================================\n// EmptyState Component\n// ========================================\n// Empty state display for CLI viewer\n\nimport { useIntl } from 'react-intl';\nimport { Terminal, Play, Keyboard } from 'lucide-react';\nimport { cn } from '@/lib/utils';\n\n// ========== Types ==========\n\nexport interface EmptyStateProps {\n className?: string;\n}\n\n// ========== Component ==========\n\n/**\n * EmptyState - Displays when no CLI executions are active\n *\n * Features:\n * - Informative empty state message\n * - Quick start hints\n * - Dark theme compatible\n */\nexport function EmptyState({ className }: EmptyStateProps) {\n const { formatMessage } = useIntl();\n\n return (\n <div\n className={cn(\n 'h-full flex flex-col items-center justify-center',\n 'bg-card dark:bg-surface-900',\n 'text-muted-foreground',\n className\n )}\n >\n <div className=\"flex flex-col items-center gap-6 max-w-md text-center p-8\">\n {/* Icon */}\n <div className=\"relative\">\n <Terminal className=\"h-16 w-16 opacity-20\" />\n <div className=\"absolute -bottom-1 -right-1 bg-primary/10 rounded-full p-1.5\">\n <Play className=\"h-4 w-4 text-primary\" />\n </div>\n </div>\n\n {/* Title */}\n <div>\n <h3 className=\"text-lg font-semibold text-foreground mb-2\">\n {formatMessage({\n id: 'cliViewer.emptyState.title',\n defaultMessage: 'CLI Viewer',\n })}\n </h3>\n <p className=\"text-sm\">\n {formatMessage({\n id: 'cliViewer.emptyState.description',\n defaultMessage: 'Start a CLI execution to see the output here.',\n })}\n </p>\n </div>\n\n {/* Hints */}\n <div className=\"flex flex-col gap-3 text-xs\">\n <div className=\"flex items-center gap-2\">\n <Keyboard className=\"h-4 w-4 shrink-0\" />\n <span>\n {formatMessage({\n id: 'cliViewer.emptyState.hint1',\n defaultMessage: 'Use \"ccw cli\" command to start an execution',\n })}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <Terminal className=\"h-4 w-4 shrink-0\" />\n <span>\n {formatMessage({\n id: 'cliViewer.emptyState.hint2',\n defaultMessage: 'Active executions will appear as tabs',\n })}\n </span>\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nexport default EmptyState;\n","// ========================================\n// LayoutContainer Component\n// ========================================\n// Manages allotment-based split panes for CLI viewer\n\nimport { useMemo, useRef, useEffect, useCallback } from 'react';\nimport { Allotment } from 'allotment';\nimport 'allotment/dist/style.css';\nimport { cn } from '@/lib/utils';\nimport {\n useViewerStore,\n useViewerLayout,\n useViewerPanes,\n type AllotmentLayoutGroup,\n type PaneId,\n} from '@/stores/viewerStore';\nimport { PaneContent } from './PaneContent';\nimport { EmptyState } from './EmptyState';\n\n// ========== Types ==========\n\ninterface LayoutGroupRendererProps {\n group: AllotmentLayoutGroup;\n minSize: number;\n onSizeChange: (sizes: number[]) => void;\n}\n\ninterface LayoutContainerProps {\n className?: string;\n}\n\n// ========== Helper Functions ==========\n\n/**\n * Check if a layout child is a pane ID (string) or a nested group\n */\nfunction isPaneId(child: PaneId | AllotmentLayoutGroup): child is PaneId {\n return typeof child === 'string';\n}\n\n// ========== Helper Components ==========\n\n/**\n * Renders a layout group with Allotment\n */\nfunction LayoutGroupRenderer({ group, minSize, onSizeChange }: LayoutGroupRendererProps) {\n const panes = useViewerPanes();\n\n // Check if all panes in this group exist\n const validChildren = useMemo(() => {\n return group.children.filter(child => {\n if (isPaneId(child)) {\n return panes[child] !== undefined;\n }\n return true; // Groups are always valid (they will recursively filter)\n });\n }, [group.children, panes]);\n\n if (validChildren.length === 0) {\n return <EmptyState />;\n }\n\n return (\n <Allotment\n vertical={group.direction === 'vertical'}\n defaultSizes={group.sizes}\n onChange={onSizeChange}\n className=\"h-full\"\n >\n {validChildren.map((child, index) => (\n <Allotment.Pane key={isPaneId(child) ? child : `group-${index}`} minSize={minSize}>\n {isPaneId(child) ? (\n <PaneContent paneId={child} />\n ) : (\n <LayoutGroupRenderer\n group={child}\n minSize={minSize}\n onSizeChange={onSizeChange}\n />\n )}\n </Allotment.Pane>\n ))}\n </Allotment>\n );\n}\n\n// ========== Main Component ==========\n\n/**\n * LayoutContainer - Main container for CLI viewer with split panes\n *\n * Features:\n * - Recursive rendering of nested allotment layouts\n * - Support for horizontal and vertical splits\n * - Minimum pane size enforcement\n * - Empty state handling\n */\nexport function LayoutContainer({ className }: LayoutContainerProps) {\n const layout = useViewerLayout();\n const panes = useViewerPanes();\n\n // Use ref to track if we're currently updating to prevent infinite loops\n const isUpdatingRef = useRef(false);\n // Track previous sizes to avoid unnecessary updates\n const prevSizesRef = useRef<number[] | undefined>(layout.sizes);\n\n // Update prevSizesRef when layout.sizes changes from external sources\n useEffect(() => {\n if (!isUpdatingRef.current) {\n prevSizesRef.current = layout.sizes;\n }\n }, [layout.sizes]);\n\n // Stable callback with no dependencies - prevents Allotment onChange infinite loop\n const handleSizeChange = useCallback(\n (sizes: number[]) => {\n // Skip if sizes haven't actually changed (compare by value)\n if (\n prevSizesRef.current &&\n sizes.length === prevSizesRef.current.length &&\n sizes.every((s, i) => Math.abs(s - prevSizesRef.current![i]) < 0.1)\n ) {\n return;\n }\n\n // Use functional update to avoid dependency on layout\n isUpdatingRef.current = true;\n prevSizesRef.current = sizes;\n\n useViewerStore.getState().setLayout((prev) => ({\n ...prev,\n sizes,\n }));\n\n // Reset updating flag after a microtask\n queueMicrotask(() => {\n isUpdatingRef.current = false;\n });\n },\n [] // No dependencies - uses getState() and refs to prevent infinite loops\n );\n\n // Render based on layout type\n const content = useMemo(() => {\n // No children - show empty state\n if (!layout.children || layout.children.length === 0) {\n return <EmptyState />;\n }\n\n // Single pane layout\n if (layout.children.length === 1 && isPaneId(layout.children[0])) {\n const paneId = layout.children[0];\n if (!panes[paneId]) {\n return <EmptyState />;\n }\n return <PaneContent paneId={paneId} />;\n }\n\n // Group layout\n return (\n <LayoutGroupRenderer\n group={layout}\n minSize={200}\n onSizeChange={handleSizeChange}\n />\n );\n }, [layout, panes, handleSizeChange]);\n\n return (\n <div\n className={cn(\n 'h-full w-full overflow-hidden',\n 'bg-background',\n className\n )}\n >\n {content}\n </div>\n );\n}\n\nexport default LayoutContainer;\n","// ========================================\r\n// CliViewerToolbar Component\r\n// ========================================\r\n// Compact icon-based toolbar for CLI Viewer page\r\n// Follows DashboardToolbar design pattern\r\n\r\nimport { useCallback, useMemo, useState } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport {\r\n ArrowLeft,\r\n Square,\r\n Columns2,\r\n Rows2,\r\n LayoutGrid,\r\n Plus,\r\n ChevronDown,\r\n Maximize2,\r\n Minimize2,\r\n RotateCcw,\r\n Terminal,\r\n} from 'lucide-react';\r\nimport { cn } from '@/lib/utils';\r\nimport {\r\n DropdownMenu,\r\n DropdownMenuContent,\r\n DropdownMenuItem,\r\n DropdownMenuLabel,\r\n DropdownMenuSeparator,\r\n DropdownMenuTrigger,\r\n} from '@/components/ui/Dropdown';\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogHeader,\r\n DialogTitle,\r\n DialogTrigger,\r\n} from '@/components/ui/Dialog';\r\nimport { Input } from '@/components/ui/Input';\r\nimport { Search, Clock } from 'lucide-react';\r\nimport {\r\n useViewerStore,\r\n useViewerLayout,\r\n useFocusedPaneId,\r\n type AllotmentLayout,\r\n} from '@/stores/viewerStore';\r\nimport { useCliStreamStore, type CliExecutionStatus } from '@/stores/cliStreamStore';\r\n\r\n// ========== Types ==========\r\n\r\nexport interface CliViewerToolbarProps {\r\n /** Whether fullscreen mode is active */\r\n isFullscreen?: boolean;\r\n /** Callback to toggle fullscreen mode */\r\n onToggleFullscreen?: () => void;\r\n}\r\n\r\nexport type LayoutType = 'single' | 'split-h' | 'split-v' | 'grid-2x2';\r\n\r\n// ========== Constants ==========\r\n\r\nconst LAYOUT_PRESETS = [\r\n { id: 'single' as const, icon: Square, labelId: 'cliViewer.layout.single' },\r\n { id: 'split-h' as const, icon: Columns2, labelId: 'cliViewer.layout.splitH' },\r\n { id: 'split-v' as const, icon: Rows2, labelId: 'cliViewer.layout.splitV' },\r\n { id: 'grid-2x2' as const, icon: LayoutGrid, labelId: 'cliViewer.layout.grid' },\r\n];\r\n\r\nconst DEFAULT_LAYOUT: LayoutType = 'split-h';\r\n\r\nconst STATUS_CONFIG: Record<CliExecutionStatus, { color: string }> = {\r\n running: { color: 'bg-blue-500 animate-pulse' },\r\n completed: { color: 'bg-green-500' },\r\n error: { color: 'bg-red-500' },\r\n};\r\n\r\n// ========== Helper Functions ==========\r\n\r\n/**\r\n * Detect layout type from AllotmentLayout structure\r\n */\r\nfunction detectLayoutType(layout: AllotmentLayout): LayoutType {\r\n const childCount = layout.children.length;\r\n\r\n if (childCount === 0 || childCount === 1) {\r\n return 'single';\r\n }\r\n\r\n if (childCount === 2) {\r\n const hasNestedGroups = layout.children.some(\r\n (child) => typeof child !== 'string'\r\n );\r\n\r\n if (!hasNestedGroups) {\r\n return layout.direction === 'horizontal' ? 'split-h' : 'split-v';\r\n }\r\n\r\n const allNested = layout.children.every(\r\n (child) => typeof child !== 'string'\r\n );\r\n if (allNested) {\r\n return 'grid-2x2';\r\n }\r\n }\r\n\r\n return layout.direction === 'horizontal' ? 'split-h' : 'split-v';\r\n}\r\n\r\nfunction formatTime(timestamp: number): string {\r\n const now = Date.now();\r\n const diff = now - timestamp;\r\n\r\n if (diff < 60000) return 'Just now';\r\n if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`;\r\n if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`;\r\n return new Date(timestamp).toLocaleDateString();\r\n}\r\n\r\n// ========== Component ==========\r\n\r\nexport function CliViewerToolbar({\r\n isFullscreen,\r\n onToggleFullscreen,\r\n}: CliViewerToolbarProps) {\r\n const { formatMessage } = useIntl();\r\n const navigate = useNavigate();\r\n\r\n // Store hooks\r\n const layout = useViewerLayout();\r\n const focusedPaneId = useFocusedPaneId();\r\n const { initializeDefaultLayout, reset, addTab } = useViewerStore();\r\n\r\n // CLI Stream Store\r\n const executions = useCliStreamStore((state) => state.executions);\r\n\r\n // Detect current layout type\r\n const currentLayoutType = useMemo(() => detectLayoutType(layout), [layout]);\r\n\r\n // Get execution count for display\r\n const executionCount = useMemo(() => Object.keys(executions).length, [executions]);\r\n const runningCount = useMemo(\r\n () => Object.values(executions).filter((e) => e.status === 'running').length,\r\n [executions]\r\n );\r\n\r\n // Handle back navigation\r\n const handleBack = useCallback(() => {\r\n navigate(-1);\r\n }, [navigate]);\r\n\r\n // Handle layout change\r\n const handleLayoutChange = useCallback(\r\n (layoutType: LayoutType) => {\r\n initializeDefaultLayout(layoutType);\r\n },\r\n [initializeDefaultLayout]\r\n );\r\n\r\n // Handle reset\r\n const handleReset = useCallback(() => {\r\n reset();\r\n initializeDefaultLayout(DEFAULT_LAYOUT);\r\n }, [reset, initializeDefaultLayout]);\r\n\r\n return (\r\n <div className=\"flex items-center gap-1 px-2 h-[40px] border-b border-border bg-muted/30 shrink-0\">\r\n {/* Back button */}\r\n <button\r\n onClick={handleBack}\r\n className={cn(\r\n 'p-1.5 rounded transition-colors',\r\n 'text-muted-foreground hover:text-foreground hover:bg-muted'\r\n )}\r\n title={formatMessage({ id: 'cliViewer.toolbar.back', defaultMessage: 'Back' })}\r\n >\r\n <ArrowLeft className=\"w-3.5 h-3.5\" />\r\n </button>\r\n\r\n {/* Separator */}\r\n <div className=\"w-px h-5 bg-border mx-1\" />\r\n\r\n {/* Layout presets */}\r\n {LAYOUT_PRESETS.map((preset) => {\r\n const isActive = currentLayoutType === preset.id;\r\n return (\r\n <button\r\n key={preset.id}\r\n onClick={() => handleLayoutChange(preset.id)}\r\n className={cn(\r\n 'p-1.5 rounded transition-colors',\r\n isActive\r\n ? 'bg-primary/10 text-primary'\r\n : 'text-muted-foreground hover:text-foreground hover:bg-muted'\r\n )}\r\n title={formatMessage({ id: preset.labelId })}\r\n >\r\n <preset.icon className=\"w-3.5 h-3.5\" />\r\n </button>\r\n );\r\n })}\r\n\r\n {/* Separator */}\r\n <div className=\"w-px h-5 bg-border mx-1\" />\r\n\r\n {/* Add execution button - Inline Picker */}\r\n <AddExecutionButton focusedPaneId={focusedPaneId} />\r\n\r\n {/* Separator */}\r\n <div className=\"w-px h-5 bg-border mx-1\" />\r\n\r\n {/* Reset button */}\r\n <button\r\n onClick={handleReset}\r\n className={cn(\r\n 'p-1.5 rounded transition-colors',\r\n 'text-muted-foreground hover:text-foreground hover:bg-muted'\r\n )}\r\n title={formatMessage({ id: 'cliViewer.toolbar.clearAll' })}\r\n >\r\n <RotateCcw className=\"w-3.5 h-3.5\" />\r\n </button>\r\n\r\n {/* Right side - Execution selector & fullscreen */}\r\n <div className=\"flex items-center gap-1 ml-auto\">\r\n {/* Execution dropdown */}\r\n <DropdownMenu>\r\n <DropdownMenuTrigger asChild>\r\n <button\r\n className={cn(\r\n 'flex items-center gap-1.5 px-2.5 py-1.5 rounded-md text-xs transition-colors',\r\n 'text-muted-foreground hover:text-foreground hover:bg-muted'\r\n )}\r\n >\r\n <Terminal className=\"w-3.5 h-3.5\" />\r\n <span>\r\n {runningCount > 0\r\n ? `${runningCount} ${formatMessage({ id: 'cliViewer.toolbar.running', defaultMessage: 'running' })}`\r\n : `${executionCount} ${formatMessage({ id: 'cliViewer.toolbar.executions', defaultMessage: 'executions' })}`}\r\n </span>\r\n {runningCount > 0 && (\r\n <span className=\"w-2 h-2 rounded-full bg-green-500 animate-pulse\" />\r\n )}\r\n <ChevronDown className=\"w-3 h-3\" />\r\n </button>\r\n </DropdownMenuTrigger>\r\n <DropdownMenuContent align=\"end\" sideOffset={4}>\r\n <DropdownMenuLabel>\r\n {formatMessage({ id: 'cliViewer.toolbar.executionsList', defaultMessage: 'Recent Executions' })}\r\n </DropdownMenuLabel>\r\n <DropdownMenuSeparator />\r\n {Object.entries(executions).length === 0 ? (\r\n <div className=\"px-2 py-4 text-center text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'cliViewer.picker.noExecutions', defaultMessage: 'No executions available' })}\r\n </div>\r\n ) : (\r\n Object.entries(executions)\r\n .sort((a, b) => b[1].startTime - a[1].startTime)\r\n .slice(0, 10)\r\n .map(([id, exec]) => (\r\n <DropdownMenuItem\r\n key={id}\r\n className=\"flex items-center gap-2 text-xs\"\r\n onClick={() => {\r\n if (focusedPaneId) {\r\n const title = `${exec.tool}-${exec.mode}`;\r\n addTab(focusedPaneId, id, title);\r\n }\r\n }}\r\n >\r\n <span\r\n className={cn(\r\n 'w-2 h-2 rounded-full shrink-0',\r\n STATUS_CONFIG[exec.status].color\r\n )}\r\n />\r\n <span className=\"truncate flex-1\">{exec.tool}</span>\r\n <span className=\"text-muted-foreground\">{exec.mode}</span>\r\n </DropdownMenuItem>\r\n ))\r\n )}\r\n </DropdownMenuContent>\r\n </DropdownMenu>\r\n\r\n {/* Separator */}\r\n <div className=\"w-px h-5 bg-border mx-1\" />\r\n\r\n {/* Fullscreen toggle */}\r\n <button\r\n onClick={onToggleFullscreen}\r\n className={cn(\r\n 'p-1.5 rounded transition-colors',\r\n isFullscreen\r\n ? 'bg-primary/10 text-primary'\r\n : 'text-muted-foreground hover:text-foreground hover:bg-muted'\r\n )}\r\n title={\r\n isFullscreen\r\n ? formatMessage({ id: 'cliViewer.toolbar.exitFullscreen', defaultMessage: 'Exit Fullscreen' })\r\n : formatMessage({ id: 'cliViewer.toolbar.fullscreen', defaultMessage: 'Fullscreen' })\r\n }\r\n >\r\n {isFullscreen ? (\r\n <Minimize2 className=\"w-3.5 h-3.5\" />\r\n ) : (\r\n <Maximize2 className=\"w-3.5 h-3.5\" />\r\n )}\r\n </button>\r\n\r\n {/* Page title */}\r\n <span className=\"text-xs text-muted-foreground font-medium ml-2\">\r\n {formatMessage({ id: 'cliViewer.page.title' })}\r\n </span>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// ========== Add Execution Button Sub-Component ==========\r\n\r\nfunction AddExecutionButton({ focusedPaneId }: { focusedPaneId: string | null }) {\r\n const { formatMessage } = useIntl();\r\n const [open, setOpen] = useState(false);\r\n const [searchQuery, setSearchQuery] = useState('');\r\n\r\n const executions = useCliStreamStore((state) => state.executions);\r\n const panes = useViewerStore((state) => state.panes);\r\n const addTab = useViewerStore((state) => state.addTab);\r\n\r\n // Get existing execution IDs in current pane\r\n const existingExecutionIds = useMemo(() => {\r\n if (!focusedPaneId) return new Set<string>();\r\n const pane = panes[focusedPaneId];\r\n if (!pane) return new Set<string>();\r\n return new Set(pane.tabs.map((tab) => tab.executionId));\r\n }, [panes, focusedPaneId]);\r\n\r\n // Filter executions\r\n const filteredExecutions = useMemo(() => {\r\n const entries = Object.entries(executions);\r\n const filtered = entries.filter(([id, exec]) => {\r\n if (!searchQuery) return true;\r\n const query = searchQuery.toLowerCase();\r\n return (\r\n id.toLowerCase().includes(query) ||\r\n exec.tool.toLowerCase().includes(query) ||\r\n exec.mode.toLowerCase().includes(query)\r\n );\r\n });\r\n filtered.sort((a, b) => b[1].startTime - a[1].startTime);\r\n return filtered;\r\n }, [executions, searchQuery]);\r\n\r\n const handleSelect = useCallback((executionId: string, tool: string, mode: string) => {\r\n if (focusedPaneId) {\r\n addTab(focusedPaneId, executionId, `${tool}-${mode}`);\r\n setOpen(false);\r\n setSearchQuery('');\r\n }\r\n }, [focusedPaneId, addTab]);\r\n\r\n if (!focusedPaneId) return null;\r\n\r\n return (\r\n <Dialog open={open} onOpenChange={setOpen}>\r\n <DialogTrigger asChild>\r\n <button\r\n className={cn(\r\n 'flex items-center gap-1.5 px-2.5 py-1.5 rounded-md text-xs transition-colors',\r\n 'text-muted-foreground hover:text-foreground hover:bg-muted'\r\n )}\r\n >\r\n <Plus className=\"w-3.5 h-3.5\" />\r\n <span>{formatMessage({ id: 'cliViewer.toolbar.addExecution', defaultMessage: 'Add' })}</span>\r\n </button>\r\n </DialogTrigger>\r\n\r\n <DialogContent className=\"sm:max-w-md\">\r\n <DialogHeader>\r\n <DialogTitle>\r\n {formatMessage({ id: 'cliViewer.picker.selectExecution', defaultMessage: 'Select Execution' })}\r\n </DialogTitle>\r\n </DialogHeader>\r\n\r\n {/* Search input */}\r\n <div className=\"relative\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\r\n <Input\r\n placeholder={formatMessage({\r\n id: 'cliViewer.picker.searchExecutions',\r\n defaultMessage: 'Search executions...'\r\n })}\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n className=\"pl-9\"\r\n />\r\n </div>\r\n\r\n {/* Execution list */}\r\n <div className=\"max-h-[300px] overflow-y-auto space-y-2\">\r\n {filteredExecutions.length === 0 ? (\r\n <div className=\"flex flex-col items-center justify-center py-8 text-center\">\r\n <Terminal className=\"h-8 w-8 text-muted-foreground mb-2\" />\r\n <p className=\"text-sm text-muted-foreground\">\r\n {Object.keys(executions).length === 0\r\n ? formatMessage({ id: 'cliViewer.picker.noExecutions', defaultMessage: 'No executions available' })\r\n : formatMessage({ id: 'cliViewer.picker.noMatchingExecutions', defaultMessage: 'No matching executions' })}\r\n </p>\r\n </div>\r\n ) : (\r\n filteredExecutions.map(([id, exec]) => {\r\n const isAlreadyOpen = existingExecutionIds.has(id);\r\n return (\r\n <div key={id} className=\"relative\">\r\n <button\r\n onClick={() => handleSelect(id, exec.tool, exec.mode)}\r\n disabled={isAlreadyOpen}\r\n className={cn(\r\n 'w-full flex items-center gap-3 p-3 rounded-lg',\r\n 'border border-border/50 bg-muted/30',\r\n 'hover:bg-muted/50 hover:border-border',\r\n 'transition-all duration-150',\r\n 'text-left',\r\n isAlreadyOpen && 'opacity-50 cursor-not-allowed'\r\n )}\r\n >\r\n {/* Tool icon */}\r\n <div className=\"flex items-center justify-center w-8 h-8 rounded-md bg-primary/10\">\r\n <Terminal className=\"h-4 w-4 text-primary\" />\r\n </div>\r\n\r\n {/* Execution info */}\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium text-sm text-foreground truncate\">\r\n {exec.tool}-{exec.mode}\r\n </span>\r\n <span\r\n className={cn(\r\n 'w-2 h-2 rounded-full shrink-0',\r\n STATUS_CONFIG[exec.status].color\r\n )}\r\n />\r\n </div>\r\n <span className=\"text-xs text-muted-foreground truncate\">\r\n {id}\r\n </span>\r\n </div>\r\n\r\n {/* Time */}\r\n <div className=\"flex items-center gap-1 text-xs text-muted-foreground shrink-0\">\r\n <Clock className=\"h-3 w-3\" />\r\n <span>{formatTime(exec.startTime)}</span>\r\n </div>\r\n </button>\r\n {isAlreadyOpen && (\r\n <div className=\"absolute inset-0 bg-background/60 rounded-lg flex items-center justify-center\">\r\n <span className=\"text-xs text-muted-foreground bg-muted px-2 py-1 rounded\">\r\n {formatMessage({ id: 'cliViewer.picker.alreadyOpen', defaultMessage: 'Already open' })}\r\n </span>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })\r\n )}\r\n </div>\r\n </DialogContent>\r\n </Dialog>\r\n );\r\n}\r\n\r\nexport default CliViewerToolbar;\r\n","// ========================================\n// CliViewerPage Utilities\n// ========================================\n\nimport type { PaneId, PaneState, TabId } from '@/stores/viewerStore';\n\nexport function getStaleViewerTabs(\n panes: Record<PaneId, PaneState>,\n executions: Record<string, unknown>\n): Array<{ paneId: PaneId; tabId: TabId; executionId: string }> {\n const executionIds = new Set(Object.keys(executions));\n\n return Object.entries(panes).flatMap(([paneId, pane]) => (\n pane.tabs\n .filter((tab) => !executionIds.has(tab.executionId))\n .map((tab) => ({\n paneId,\n tabId: tab.id,\n executionId: tab.executionId,\n }))\n ));\n}\n","// ========================================\r\n// CLI Viewer Page\r\n// ========================================\r\n// Multi-pane CLI output viewer with configurable layouts\r\n// Integrates with viewerStore for state management\r\n// Includes WebSocket integration and execution recovery\r\n\r\nimport { useEffect, useRef, useState } from 'react';\r\nimport { useSearchParams } from 'react-router-dom';\r\nimport { LayoutContainer, CliViewerToolbar } from '@/components/cli-viewer';\r\nimport {\r\n useViewerStore,\r\n useViewerLayout,\r\n useViewerPanes,\r\n useFocusedPaneId,\r\n type AllotmentLayout,\r\n} from '@/stores/viewerStore';\r\nimport { useCliStreamStore } from '@/stores/cliStreamStore';\r\nimport { useActiveCliExecutions } from '@/hooks/useActiveCliExecutions';\r\nimport { useCliStreamWebSocket } from '@/hooks/useCliStreamWebSocket';\r\nimport { getStaleViewerTabs } from './cliViewerPage.utils';\r\n\r\n// ========================================\r\n// Constants\r\n// ========================================\r\n\r\nconst DEFAULT_LAYOUT = 'split-h' as const;\r\n\r\n// ========================================\r\n// Helper Functions\r\n// ========================================\r\n\r\n/**\r\n * Count total panes in layout\r\n */\r\nfunction countPanes(layout: AllotmentLayout): number {\r\n let count = 0;\r\n const traverse = (children: (string | AllotmentLayout)[]) => {\r\n for (const child of children) {\r\n if (typeof child === 'string') {\r\n count++;\r\n } else {\r\n traverse(child.children);\r\n }\r\n }\r\n };\r\n traverse(layout.children);\r\n return count;\r\n}\r\n\r\n// ========================================\r\n// Main Component\r\n// ========================================\r\n\r\nexport function CliViewerPage() {\r\n const [searchParams, setSearchParams] = useSearchParams();\r\n\r\n // Fullscreen state\r\n const [isFullscreen, setIsFullscreen] = useState(false);\r\n\r\n // Store hooks\r\n const layout = useViewerLayout();\r\n const panes = useViewerPanes();\r\n const focusedPaneId = useFocusedPaneId();\r\n const { initializeDefaultLayout, addTab, removeTab } = useViewerStore();\r\n\r\n // CLI Stream Store hooks\r\n const executions = useCliStreamStore((state) => state.executions);\r\n\r\n // Active execution sync from server\r\n const { isLoading: isSyncing, isFetching: isRefreshing } = useActiveCliExecutions(true);\r\n\r\n // CENTRALIZED WebSocket handler - processes each message only ONCE globally\r\n useCliStreamWebSocket();\r\n\r\n // Auto-add new executions as tabs, distributing across available panes\r\n const addedExecutionsRef = useRef<Set<string>>(new Set());\r\n\r\n // FIX-001: Initialize addedExecutionsRef with existing tab executionIds on mount\r\n // This prevents duplicate tabs from being added after page refresh\r\n useEffect(() => {\r\n // Extract executionIds from all existing tabs in all panes\r\n const existingExecutionIds = Object.values(panes).flatMap((pane) =>\r\n pane.tabs.map((tab) => tab.executionId)\r\n );\r\n existingExecutionIds.forEach((id) => addedExecutionsRef.current.add(id));\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []); // Empty deps - only run once on mount\r\n\r\n useEffect(() => {\r\n const paneIds = Object.keys(panes);\r\n if (paneIds.length === 0) return;\r\n\r\n const storeAddTab = useViewerStore.getState().addTab;\r\n const newExecutionIds = Object.keys(executions).filter(\r\n (id) => !addedExecutionsRef.current.has(id)\r\n );\r\n\r\n if (newExecutionIds.length === 0) return;\r\n\r\n newExecutionIds.forEach((executionId, index) => {\r\n addedExecutionsRef.current.add(executionId);\r\n const exec = executions[executionId];\r\n const toolShort = exec.tool.split('-')[0];\r\n const targetPaneId = paneIds[index % paneIds.length];\r\n storeAddTab(targetPaneId, executionId, `${toolShort} (${exec.mode})`);\r\n });\r\n }, [executions, panes]);\r\n\r\n useEffect(() => {\r\n if (isSyncing || isRefreshing) return;\r\n\r\n const staleTabs = getStaleViewerTabs(panes, executions);\r\n if (staleTabs.length === 0) return;\r\n\r\n staleTabs.forEach(({ paneId, tabId, executionId }) => {\r\n addedExecutionsRef.current.delete(executionId);\r\n removeTab(paneId, tabId);\r\n });\r\n }, [executions, isRefreshing, isSyncing, panes, removeTab]);\r\n\r\n // Initialize layout if empty\r\n useEffect(() => {\r\n const paneCount = countPanes(layout);\r\n if (paneCount === 0) {\r\n initializeDefaultLayout(DEFAULT_LAYOUT);\r\n }\r\n }, [layout, initializeDefaultLayout]);\r\n\r\n // Handle executionId from URL params\r\n useEffect(() => {\r\n const executionId = searchParams.get('executionId');\r\n if (executionId && focusedPaneId) {\r\n addTab(focusedPaneId, executionId, `Execution ${executionId.slice(0, 8)}`);\r\n setSearchParams((prev) => {\r\n const newParams = new URLSearchParams(prev);\r\n newParams.delete('executionId');\r\n return newParams;\r\n });\r\n }\r\n }, [searchParams, focusedPaneId, addTab, setSearchParams]);\r\n\r\n // Toggle fullscreen handler\r\n const handleToggleFullscreen = () => {\r\n setIsFullscreen((prev) => !prev);\r\n };\r\n\r\n return (\r\n <div className=\"h-full flex flex-col\">\r\n {/* ======================================== */}\r\n {/* Toolbar */}\r\n {/* ======================================== */}\r\n <CliViewerToolbar\r\n isFullscreen={isFullscreen}\r\n onToggleFullscreen={handleToggleFullscreen}\r\n />\r\n\r\n {/* ======================================== */}\r\n {/* Layout Container */}\r\n {/* ======================================== */}\r\n <div className=\"flex-1 min-h-0 bg-background\">\r\n <LayoutContainer />\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport default CliViewerPage;\r\n"],"names":["Ellipsis","createLucideIcon","Keyboard","PinOff","Pin","STATUS_CONFIG","Loader2","CheckCircle2","XCircle","formatTime","timestamp","diff","getExecutionTitle","_executionId","execution","ExecutionItem","executionId","onSelect","statusConfig","StatusIcon","jsxs","cn","jsx","Terminal","Clock","ExecutionPicker","paneId","className","formatMessage","useIntl","open","setOpen","useState","searchQuery","setSearchQuery","executions","useCliStreamStore","state","addTab","useViewerStore","panes","existingExecutionIds","useMemo","pane","tab","filteredExecutions","filtered","id","exec","query","a","b","handleSelect","useCallback","title","totalCount","availableCount","Dialog","DialogTrigger","Button","Plus","DialogContent","DialogHeader","DialogTitle","Search","Input","e","isAlreadyOpen","STATUS_COLORS","TAB_DRAG_DATA_TYPE","TabItem","isActive","onClose","onTogglePin","isDragging","setIsDragging","isDragOver","setIsDragOver","moveTab","useViewerPanes","displayTitle","handleDragStart","dragData","handleDragEnd","handleDragOver","handleDragLeave","handleDrop","rawData","sourceTabId","sourcePaneId","targetPane","targetIndex","t","err","X","TabBar","setActiveTab","removeTab","togglePinTab","addPane","removePane","handleTabSelect","tabId","handleTabClose","handleTogglePin","handleSplitHorizontal","handleSplitVertical","handleClosePane","handleContainerDragOver","handleContainerDragLeave","handleContainerDrop","sortedTabs","DropdownMenu","DropdownMenuTrigger","MoreHorizontal","DropdownMenuContent","DropdownMenuItem","SplitSquareHorizontal","SplitSquareVertical","DropdownMenuSeparator","EmptyTabState","ExecutionNotFoundState","ExecutionLoadingState","OutputLineItem","line","typeStyles","MessageRenderer","CliOutputDisplay","MonitorBody","index","ContentArea","activeTab","selectActiveTab","isSyncing","useActiveCliExecutions","content","PaneContent","focusedPaneId","useFocusedPaneId","setFocusedPane","isFocused","handleClick","EmptyState","Play","isPaneId","child","LayoutGroupRenderer","group","minSize","onSizeChange","validChildren","Allotment","LayoutContainer","layout","useViewerLayout","isUpdatingRef","useRef","prevSizesRef","useEffect","handleSizeChange","sizes","s","i","prev","LAYOUT_PRESETS","Square","Columns2","Rows2","LayoutGrid","DEFAULT_LAYOUT","detectLayoutType","childCount","CliViewerToolbar","isFullscreen","onToggleFullscreen","navigate","useNavigate","initializeDefaultLayout","reset","currentLayoutType","executionCount","runningCount","handleBack","handleLayoutChange","layoutType","handleReset","ArrowLeft","preset","AddExecutionButton","RotateCcw","ChevronDown","DropdownMenuLabel","Minimize2","Maximize2","tool","mode","getStaleViewerTabs","executionIds","countPanes","count","traverse","children","CliViewerPage","searchParams","setSearchParams","useSearchParams","setIsFullscreen","isRefreshing","useCliStreamWebSocket","addedExecutionsRef","paneIds","storeAddTab","newExecutionIds","toolShort","targetPaneId","staleTabs","newParams","handleToggleFullscreen"],"mappings":"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","x_google_ignoreList":[0,1,2,3]}