@64mb/freelens-power 1.1.0 → 1.2.1

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 (214) hide show
  1. package/README.md +5 -4
  2. package/THIRD_PARTY_LICENSES +1707 -0
  3. package/out/main/ai.js +63 -23
  4. package/out/main/ai.js.map +1 -1
  5. package/out/main/cluster-icons-catalog.js +28 -0
  6. package/out/main/cluster-icons-catalog.js.map +1 -0
  7. package/out/main/cluster-icons.js +125 -0
  8. package/out/main/cluster-icons.js.map +1 -0
  9. package/out/main/common/ai-terminal-context.js +51 -0
  10. package/out/main/common/ai-terminal-context.js.map +1 -0
  11. package/out/main/common/ai.js.map +1 -1
  12. package/out/main/common/cluster-icon-ipc.js +6 -0
  13. package/out/main/common/cluster-icon-ipc.js.map +1 -0
  14. package/out/main/common/cluster-icons.js +121 -0
  15. package/out/main/common/cluster-icons.js.map +1 -0
  16. package/out/main/common/dashboard.js +2 -1
  17. package/out/main/common/dashboard.js.map +1 -1
  18. package/out/main/common/settings-export.js +4 -2
  19. package/out/main/common/settings-export.js.map +1 -1
  20. package/out/main/common/store/cluster-icons-store.js +32 -0
  21. package/out/main/common/store/cluster-icons-store.js.map +1 -0
  22. package/out/main/common/store/dashboard-preferences-store.js +2 -1
  23. package/out/main/common/store/dashboard-preferences-store.js.map +1 -1
  24. package/out/main/common/store/monitoring-preferences-store.js +5 -0
  25. package/out/main/common/store/monitoring-preferences-store.js.map +1 -1
  26. package/out/main/dashboard-views.js +20 -10
  27. package/out/main/dashboard-views.js.map +1 -1
  28. package/out/main/diagnostics-menu-order.js +57 -0
  29. package/out/main/diagnostics-menu-order.js.map +1 -0
  30. package/out/main/index.js +9 -1
  31. package/out/main/index.js.map +1 -1
  32. package/out/main/monitoring-history.js +13 -3
  33. package/out/main/monitoring-history.js.map +1 -1
  34. package/out/renderer/_virtual/_global-external_react-dom.js +2 -1
  35. package/out/renderer/_virtual/_global-external_react.js +10 -5
  36. package/out/renderer/_virtual/_rolldown/runtime.js +22 -0
  37. package/out/renderer/ai-terminal-context.js +200 -0
  38. package/out/renderer/ai-terminal-context.js.map +1 -0
  39. package/out/renderer/ai.js +90 -9
  40. package/out/renderer/ai.js.map +1 -1
  41. package/out/renderer/appearance.js +1 -0
  42. package/out/renderer/appearance.js.map +1 -1
  43. package/out/renderer/cluster-icon-colors.js +188 -0
  44. package/out/renderer/cluster-icon-colors.js.map +1 -0
  45. package/out/renderer/cluster-icons.js +304 -0
  46. package/out/renderer/cluster-icons.js.map +1 -0
  47. package/out/renderer/dashboard.js +51 -14
  48. package/out/renderer/dashboard.js.map +1 -1
  49. package/out/renderer/details/secret-certificate-details.js +9 -2
  50. package/out/renderer/details/secret-certificate-details.js.map +1 -1
  51. package/out/renderer/diagnostics.css.js +39 -0
  52. package/out/renderer/diagnostics.css.js.map +1 -0
  53. package/out/renderer/diagnostics.js +796 -343
  54. package/out/renderer/diagnostics.js.map +1 -1
  55. package/out/renderer/index.js +9 -4
  56. package/out/renderer/index.js.map +1 -1
  57. package/out/renderer/monitoring-details-chart.js +42 -0
  58. package/out/renderer/monitoring-details-chart.js.map +1 -0
  59. package/out/renderer/monitoring-history-collection.js +2 -18
  60. package/out/renderer/monitoring-history-collection.js.map +1 -1
  61. package/out/renderer/monitoring-history-view.js +111 -34
  62. package/out/renderer/monitoring-history-view.js.map +1 -1
  63. package/out/renderer/monitoring.js +68 -27
  64. package/out/renderer/monitoring.js.map +1 -1
  65. package/out/renderer/node-monitoring.js +23 -12
  66. package/out/renderer/node-monitoring.js.map +1 -1
  67. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js +10 -0
  68. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js.map +1 -0
  69. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js +8 -0
  70. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js.map +1 -0
  71. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js +9 -0
  72. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js.map +1 -0
  73. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js +9 -0
  74. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js.map +1 -0
  75. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/classCallCheck.js +8 -0
  76. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/classCallCheck.js.map +1 -0
  77. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/createClass.js +15 -0
  78. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/createClass.js.map +1 -0
  79. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/createSuper.js +19 -0
  80. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/createSuper.js.map +1 -0
  81. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/defineProperty.js +14 -0
  82. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/defineProperty.js.map +1 -0
  83. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/extends.js +19 -0
  84. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/extends.js.map +1 -0
  85. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js +15 -0
  86. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js.map +1 -0
  87. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/inherits.js +14 -0
  88. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/inherits.js.map +1 -0
  89. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/isNativeReflectConstruct.js +18 -0
  90. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/isNativeReflectConstruct.js.map +1 -0
  91. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/iterableToArray.js +8 -0
  92. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/iterableToArray.js.map +1 -0
  93. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js +26 -0
  94. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js.map +1 -0
  95. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/nonIterableRest.js +8 -0
  96. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/nonIterableRest.js.map +1 -0
  97. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js +8 -0
  98. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js.map +1 -0
  99. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectSpread2.js +27 -0
  100. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectSpread2.js.map +1 -0
  101. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js +15 -0
  102. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js.map +1 -0
  103. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js +14 -0
  104. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js.map +1 -0
  105. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/possibleConstructorReturn.js +12 -0
  106. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/possibleConstructorReturn.js.map +1 -0
  107. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js +15 -0
  108. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js.map +1 -0
  109. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/slicedToArray.js +12 -0
  110. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/slicedToArray.js.map +1 -0
  111. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/taggedTemplateLiteral.js +8 -0
  112. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/taggedTemplateLiteral.js.map +1 -0
  113. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toConsumableArray.js +12 -0
  114. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toConsumableArray.js.map +1 -0
  115. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toPrimitive.js +16 -0
  116. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toPrimitive.js.map +1 -0
  117. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toPropertyKey.js +11 -0
  118. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toPropertyKey.js.map +1 -0
  119. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/typeof.js +18 -0
  120. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/typeof.js.map +1 -0
  121. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js +13 -0
  122. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js.map +1 -0
  123. package/out/renderer/node_modules/.pnpm/@emotion_cache@11.14.0/node_modules/@emotion/cache/dist/emotion-cache.browser.esm.js +237 -0
  124. package/out/renderer/node_modules/.pnpm/@emotion_cache@11.14.0/node_modules/@emotion/cache/dist/emotion-cache.browser.esm.js.map +1 -0
  125. package/out/renderer/node_modules/.pnpm/@emotion_hash@0.9.2/node_modules/@emotion/hash/dist/emotion-hash.esm.js +25 -0
  126. package/out/renderer/node_modules/.pnpm/@emotion_hash@0.9.2/node_modules/@emotion/hash/dist/emotion-hash.esm.js.map +1 -0
  127. package/out/renderer/node_modules/.pnpm/@emotion_memoize@0.9.0/node_modules/@emotion/memoize/dist/emotion-memoize.esm.js +12 -0
  128. package/out/renderer/node_modules/.pnpm/@emotion_memoize@0.9.0/node_modules/@emotion/memoize/dist/emotion-memoize.esm.js.map +1 -0
  129. package/out/renderer/node_modules/.pnpm/@emotion_react@11.14.0_@types_react@17.0.93_react@17.0.2/node_modules/@emotion/react/dist/emotion-element-f0de968e.browser.esm.js +58 -0
  130. package/out/renderer/node_modules/.pnpm/@emotion_react@11.14.0_@types_react@17.0.93_react@17.0.2/node_modules/@emotion/react/dist/emotion-element-f0de968e.browser.esm.js.map +1 -0
  131. package/out/renderer/node_modules/.pnpm/@emotion_react@11.14.0_@types_react@17.0.93_react@17.0.2/node_modules/@emotion/react/dist/emotion-react.browser.esm.js +54 -0
  132. package/out/renderer/node_modules/.pnpm/@emotion_react@11.14.0_@types_react@17.0.93_react@17.0.2/node_modules/@emotion/react/dist/emotion-react.browser.esm.js.map +1 -0
  133. package/out/renderer/node_modules/.pnpm/@emotion_serialize@1.3.3/node_modules/@emotion/serialize/dist/emotion-serialize.esm.js +133 -0
  134. package/out/renderer/node_modules/.pnpm/@emotion_serialize@1.3.3/node_modules/@emotion/serialize/dist/emotion-serialize.esm.js.map +1 -0
  135. package/out/renderer/node_modules/.pnpm/@emotion_sheet@1.4.0/node_modules/@emotion/sheet/dist/emotion-sheet.esm.js +65 -0
  136. package/out/renderer/node_modules/.pnpm/@emotion_sheet@1.4.0/node_modules/@emotion/sheet/dist/emotion-sheet.esm.js.map +1 -0
  137. package/out/renderer/node_modules/.pnpm/@emotion_unitless@0.10.0/node_modules/@emotion/unitless/dist/emotion-unitless.esm.js +54 -0
  138. package/out/renderer/node_modules/.pnpm/@emotion_unitless@0.10.0/node_modules/@emotion/unitless/dist/emotion-unitless.esm.js.map +1 -0
  139. package/out/renderer/node_modules/.pnpm/@emotion_use-insertion-effect-with-fallbacks@1.2.0_react@17.0.2/node_modules/@emotion/use-insertion-effect-with-fallbacks/dist/emotion-use-insertion-effect-with-fallbacks.browser.esm.js +12 -0
  140. package/out/renderer/node_modules/.pnpm/@emotion_use-insertion-effect-with-fallbacks@1.2.0_react@17.0.2/node_modules/@emotion/use-insertion-effect-with-fallbacks/dist/emotion-use-insertion-effect-with-fallbacks.browser.esm.js.map +1 -0
  141. package/out/renderer/node_modules/.pnpm/@emotion_utils@1.4.2/node_modules/@emotion/utils/dist/emotion-utils.browser.esm.js +30 -0
  142. package/out/renderer/node_modules/.pnpm/@emotion_utils@1.4.2/node_modules/@emotion/utils/dist/emotion-utils.browser.esm.js.map +1 -0
  143. package/out/renderer/node_modules/.pnpm/@floating-ui_dom@1.7.2/node_modules/@floating-ui/dom/dist/floating-ui.dom.js +211 -0
  144. package/out/renderer/node_modules/.pnpm/@floating-ui_dom@1.7.2/node_modules/@floating-ui/dom/dist/floating-ui.dom.js.map +1 -0
  145. package/out/renderer/node_modules/.pnpm/@floating-ui_utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.js +97 -0
  146. package/out/renderer/node_modules/.pnpm/@floating-ui_utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.js.map +1 -0
  147. package/out/renderer/node_modules/.pnpm/@floating-ui_utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.js +31 -0
  148. package/out/renderer/node_modules/.pnpm/@floating-ui_utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.js.map +1 -0
  149. package/out/renderer/node_modules/.pnpm/hoist-non-react-statics@3.3.2/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js +93 -0
  150. package/out/renderer/node_modules/.pnpm/hoist-non-react-statics@3.3.2/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js.map +1 -0
  151. package/out/renderer/node_modules/.pnpm/memoize-one@6.0.0/node_modules/memoize-one/dist/memoize-one.esm.js +38 -0
  152. package/out/renderer/node_modules/.pnpm/memoize-one@6.0.0/node_modules/memoize-one/dist/memoize-one.esm.js.map +1 -0
  153. package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.development.js +159 -0
  154. package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.development.js.map +1 -0
  155. package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.production.min.js +103 -0
  156. package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.production.min.js.map +1 -0
  157. package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/index.js +18 -0
  158. package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/index.js.map +1 -0
  159. package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/Select-ef7c0426.esm.js +2200 -0
  160. package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/Select-ef7c0426.esm.js.map +1 -0
  161. package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/index-641ee5b8.esm.js +992 -0
  162. package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/index-641ee5b8.esm.js.map +1 -0
  163. package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/react-select.esm.js +14 -0
  164. package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/react-select.esm.js.map +1 -0
  165. package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/useStateManager-7e1e8489.esm.js +56 -0
  166. package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/useStateManager-7e1e8489.esm.js.map +1 -0
  167. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Enum.js +22 -0
  168. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Enum.js.map +1 -0
  169. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Middleware.js +30 -0
  170. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Middleware.js.map +1 -0
  171. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Parser.js +164 -0
  172. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Parser.js.map +1 -0
  173. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Serializer.js +37 -0
  174. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Serializer.js.map +1 -0
  175. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Tokenizer.js +245 -0
  176. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Tokenizer.js.map +1 -0
  177. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Utility.js +120 -0
  178. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Utility.js.map +1 -0
  179. package/out/renderer/node_modules/.pnpm/use-isomorphic-layout-effect@1.2.1_@types_react@17.0.93_react@17.0.2/node_modules/use-isomorphic-layout-effect/dist/use-isomorphic-layout-effect.browser.esm.js +6 -0
  180. package/out/renderer/node_modules/.pnpm/use-isomorphic-layout-effect@1.2.1_@types_react@17.0.93_react@17.0.2/node_modules/use-isomorphic-layout-effect/dist/use-isomorphic-layout-effect.browser.esm.js.map +1 -0
  181. package/out/renderer/pod-monitoring.js +15 -19
  182. package/out/renderer/pod-monitoring.js.map +1 -1
  183. package/out/renderer/preferences/ai-shortcuts-preferences.js +12 -4
  184. package/out/renderer/preferences/ai-shortcuts-preferences.js.map +1 -1
  185. package/out/renderer/preferences/dashboard-preferences.js +37 -6
  186. package/out/renderer/preferences/dashboard-preferences.js.map +1 -1
  187. package/out/renderer/preferences/monitoring-preferences.js +131 -44
  188. package/out/renderer/preferences/monitoring-preferences.js.map +1 -1
  189. package/out/renderer/preferences/preferences.js +31 -7
  190. package/out/renderer/preferences/preferences.js.map +1 -1
  191. package/out/renderer/read-only.js +2 -2
  192. package/out/renderer/read-only.js.map +1 -1
  193. package/out/renderer/src/common/ai-terminal-context.js +51 -0
  194. package/out/renderer/src/common/ai-terminal-context.js.map +1 -0
  195. package/out/renderer/src/common/ai.js.map +1 -1
  196. package/out/renderer/src/common/cluster-icon-ipc.js +6 -0
  197. package/out/renderer/src/common/cluster-icon-ipc.js.map +1 -0
  198. package/out/renderer/src/common/cluster-icons.js +133 -0
  199. package/out/renderer/src/common/cluster-icons.js.map +1 -0
  200. package/out/renderer/src/common/dashboard.js +2 -1
  201. package/out/renderer/src/common/dashboard.js.map +1 -1
  202. package/out/renderer/src/common/date-time.js +11 -0
  203. package/out/renderer/src/common/date-time.js.map +1 -0
  204. package/out/renderer/src/common/monitoring-history.js +2 -0
  205. package/out/renderer/src/common/monitoring-history.js.map +1 -1
  206. package/out/renderer/src/common/resource-diagnostics.js.map +1 -1
  207. package/out/renderer/src/common/settings-export.js.map +1 -1
  208. package/out/renderer/src/common/store/dashboard-preferences-store.js +2 -1
  209. package/out/renderer/src/common/store/dashboard-preferences-store.js.map +1 -1
  210. package/out/renderer/src/common/store/monitoring-preferences-store.js +5 -0
  211. package/out/renderer/src/common/store/monitoring-preferences-store.js.map +1 -1
  212. package/out/renderer/welcome.js +28 -6
  213. package/out/renderer/welcome.js.map +1 -1
  214. package/package.json +3 -2
@@ -1 +1 @@
1
- {"version":3,"file":"read-only.js","names":[],"sources":["../../src/renderer/read-only.ts"],"sourcesContent":["import { reaction } from \"mobx\";\nimport { ReadOnlyPreferencesStore } from \"../common/store/read-only-preferences-store\";\n\nconst marker = \"data-freelens-power-read-only\";\nconst excluded = \".freelens-power-preferences, #freelens-power-settings, .freelens-power-dashboard, .power-ai-panel\";\nconst directActions = [\n \".CatalogAddButton\",\n \".KubeObjectListLayout .AddRemoveButtons .add-button\",\n \".KubeObjectListLayout .AddRemoveButtons .remove-button\",\n \".create-resource-tab\",\n \".CreateResource .InfoPanel button.active\",\n '[data-testid^=\"save-edit-resource-from-tab-for-\"]',\n '[data-testid^=\"save-and-close-edit-resource-from-tab-for-\"]',\n '[data-testid^=\"menu-action-edit-for-\"]',\n '[data-testid^=\"menu-action-delete-for-\"]',\n '[data-testid^=\"menu-action-force-delete-for-\"]',\n '[data-testid^=\"menu-action-delete-with-finalizers-for-\"]',\n '.MenuActions [data-testid=\"menu-action-remove\"]',\n].join(\",\");\nconst menuActions = new Set([\n \"edit\",\n \"delete\",\n \"force delete\",\n \"delete with finalizers\",\n \"remove\",\n \"remove cluster\",\n \"delete cluster\",\n \"cordon\",\n \"uncordon\",\n \"drain\",\n \"scale\",\n \"restart\",\n]);\n\nexport function startReadOnlyMode(): () => void {\n const preferences = ReadOnlyPreferencesStore.getInstanceOrCreate<ReadOnlyPreferencesStore>();\n const style = document.createElement(\"style\");\n style.dataset.freelensPower = \"read-only\";\n style.textContent = `[${marker}] { display: none !important; }`;\n const hidden = new Set<HTMLElement>();\n\n function restore() {\n for (const element of hidden) element.removeAttribute(marker);\n hidden.clear();\n style.remove();\n }\n\n function isMutation(element: HTMLElement): boolean {\n if (element.closest(excluded)) return false;\n if (element.matches(directActions)) return true;\n if (!element.matches('.MenuActions .MenuItem, [data-testid^=\"menu-actions-for-kube-object-menu-\"] .MenuItem'))\n return false;\n const title = (element.querySelector(\".title\")?.textContent ?? element.textContent)?.trim().toLowerCase();\n if (title && menuActions.has(title)) return true;\n return !!element.querySelector(\n '[data-icon-name=\"edit\"], [data-icon-name=\"delete\"], [data-icon-name=\"delete_forever\"], [data-icon-name=\"delete_sweep\"], [data-icon-name=\"pause_circle_filled\"], [data-icon-name=\"play_circle_filled\"]',\n );\n }\n\n function refresh() {\n for (const element of hidden) {\n if (!element.isConnected || !isMutation(element)) {\n element.removeAttribute(marker);\n hidden.delete(element);\n }\n }\n for (const element of document.querySelectorAll<HTMLElement>(`${directActions}, .MenuActions .MenuItem`)) {\n if (isMutation(element)) {\n element.setAttribute(marker, \"\");\n hidden.add(element);\n }\n }\n }\n\n function intercept(event: Event) {\n if (!preferences.enabled || !(event.target instanceof Element)) return;\n if (event instanceof KeyboardEvent && ![\"Enter\", \" \"].includes(event.key)) return;\n const target = event.target.closest<HTMLElement>(`[${marker}], ${directActions}, .MenuItem`);\n if (!target || !isMutation(target)) return;\n event.preventDefault();\n event.stopImmediatePropagation();\n }\n\n const observer = new MutationObserver(refresh);\n const stop = reaction(\n () => preferences.enabled,\n (enabled) => {\n observer.disconnect();\n restore();\n if (!enabled) return;\n document.head.append(style);\n refresh();\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n characterData: true,\n attributes: true,\n attributeFilter: [\"class\", \"data-testid\", \"title\"],\n });\n },\n { fireImmediately: true },\n );\n document.addEventListener(\"click\", intercept, true);\n document.addEventListener(\"keydown\", intercept, true);\n\n return () => {\n stop();\n observer.disconnect();\n document.removeEventListener(\"click\", intercept, true);\n document.removeEventListener(\"keydown\", intercept, true);\n restore();\n };\n}\n"],"mappings":";;;AAGA,IAAM,SAAS;AACf,IAAM,WAAW;AACjB,IAAM,gBAAgB;CACpB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC,CAAC,KAAK,GAAG;AACV,IAAM,8BAAc,IAAI,IAAI;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,SAAgB,oBAAgC;CAC9C,MAAM,cAAc,oCAAA,yBAAyB,oBAA8C;CAC3F,MAAM,QAAQ,SAAS,cAAc,OAAO;CAC5C,MAAM,QAAQ,gBAAgB;CAC9B,MAAM,cAAc,IAAI,OAAO;CAC/B,MAAM,yBAAS,IAAI,IAAiB;CAEpC,SAAS,UAAU;EACjB,KAAK,MAAM,WAAW,QAAQ,QAAQ,gBAAgB,MAAM;EAC5D,OAAO,MAAM;EACb,MAAM,OAAO;CACf;CAEA,SAAS,WAAW,SAA+B;EACjD,IAAI,QAAQ,QAAQ,QAAQ,GAAG,OAAO;EACtC,IAAI,QAAQ,QAAQ,aAAa,GAAG,OAAO;EAC3C,IAAI,CAAC,QAAQ,QAAQ,yFAAuF,GAC1G,OAAO;EACT,MAAM,SAAS,QAAQ,cAAc,QAAQ,CAAC,EAAE,eAAe,QAAQ,YAAA,EAAc,KAAK,CAAC,CAAC,YAAY;EACxG,IAAI,SAAS,YAAY,IAAI,KAAK,GAAG,OAAO;EAC5C,OAAO,CAAC,CAAC,QAAQ,cACf,mNACF;CACF;CAEA,SAAS,UAAU;EACjB,KAAK,MAAM,WAAW,QACpB,IAAI,CAAC,QAAQ,eAAe,CAAC,WAAW,OAAO,GAAG;GAChD,QAAQ,gBAAgB,MAAM;GAC9B,OAAO,OAAO,OAAO;EACvB;EAEF,KAAK,MAAM,WAAW,SAAS,iBAA8B,GAAG,cAAc,yBAAyB,GACrG,IAAI,WAAW,OAAO,GAAG;GACvB,QAAQ,aAAa,QAAQ,EAAE;GAC/B,OAAO,IAAI,OAAO;EACpB;CAEJ;CAEA,SAAS,UAAU,OAAc;EAC/B,IAAI,CAAC,YAAY,WAAW,EAAE,MAAM,kBAAkB,UAAU;EAChE,IAAI,iBAAiB,iBAAiB,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,GAAG;EAC3E,MAAM,SAAS,MAAM,OAAO,QAAqB,IAAI,OAAO,KAAK,cAAc,YAAY;EAC3F,IAAI,CAAC,UAAU,CAAC,WAAW,MAAM,GAAG;EACpC,MAAM,eAAe;EACrB,MAAM,yBAAyB;CACjC;CAEA,MAAM,WAAW,IAAI,iBAAiB,OAAO;CAC7C,MAAM,OAAO,8BAAA,eACL,YAAY,UACjB,YAAY;EACX,SAAS,WAAW;EACpB,QAAQ;EACR,IAAI,CAAC,SAAS;EACd,SAAS,KAAK,OAAO,KAAK;EAC1B,QAAQ;EACR,SAAS,QAAQ,SAAS,MAAM;GAC9B,WAAW;GACX,SAAS;GACT,eAAe;GACf,YAAY;GACZ,iBAAiB;IAAC;IAAS;IAAe;GAAO;EACnD,CAAC;CACH,GACA,EAAE,iBAAiB,KAAK,CAC1B;CACA,SAAS,iBAAiB,SAAS,WAAW,IAAI;CAClD,SAAS,iBAAiB,WAAW,WAAW,IAAI;CAEpD,aAAa;EACX,KAAK;EACL,SAAS,WAAW;EACpB,SAAS,oBAAoB,SAAS,WAAW,IAAI;EACrD,SAAS,oBAAoB,WAAW,WAAW,IAAI;EACvD,QAAQ;CACV;AACF"}
1
+ {"version":3,"file":"read-only.js","names":[],"sources":["../../src/renderer/read-only.ts"],"sourcesContent":["import { reaction } from \"mobx\";\nimport { ReadOnlyPreferencesStore } from \"../common/store/read-only-preferences-store\";\n\nconst marker = \"data-freelens-power-read-only\";\nconst excluded = \".freelens-power-preferences, #freelens-power-settings, .freelens-power-dashboard, .power-ai-panel\";\nconst directActions = [\n \".CatalogAddButton\",\n \".KubeObjectListLayout .AddRemoveButtons .add-button\",\n \".AddRemoveButtons .remove-button\",\n \".create-resource-tab\",\n \".CreateResource .InfoPanel button.active\",\n '[data-testid^=\"save-edit-resource-from-tab-for-\"]',\n '[data-testid^=\"save-and-close-edit-resource-from-tab-for-\"]',\n '[data-testid^=\"menu-action-edit-for-\"]',\n '[data-testid^=\"menu-action-delete-for-\"]',\n '[data-testid^=\"menu-action-force-delete-for-\"]',\n '[data-testid^=\"menu-action-delete-with-finalizers-for-\"]',\n '.MenuActions [data-testid=\"menu-action-remove\"]',\n].join(\",\");\nconst menuActions = new Set([\n \"edit\",\n \"delete\",\n \"force delete\",\n \"delete with finalizers\",\n \"remove\",\n \"remove cluster\",\n \"delete cluster\",\n \"cordon\",\n \"uncordon\",\n \"drain\",\n \"scale\",\n \"restart\",\n]);\n\nexport function startReadOnlyMode(): () => void {\n const preferences = ReadOnlyPreferencesStore.getInstanceOrCreate<ReadOnlyPreferencesStore>();\n const style = document.createElement(\"style\");\n style.dataset.freelensPower = \"read-only\";\n style.textContent = `[${marker}], .AddRemoveButtons .remove-button { display: none !important; }`;\n const hidden = new Set<HTMLElement>();\n\n function restore() {\n for (const element of hidden) element.removeAttribute(marker);\n hidden.clear();\n style.remove();\n }\n\n function isMutation(element: HTMLElement): boolean {\n if (element.closest(excluded)) return false;\n if (element.matches(directActions)) return true;\n if (!element.matches('.MenuActions .MenuItem, [data-testid^=\"menu-actions-for-kube-object-menu-\"] .MenuItem'))\n return false;\n const title = (element.querySelector(\".title\")?.textContent ?? element.textContent)?.trim().toLowerCase();\n if (title && menuActions.has(title)) return true;\n return !!element.querySelector(\n '[data-icon-name=\"edit\"], [data-icon-name=\"delete\"], [data-icon-name=\"delete_forever\"], [data-icon-name=\"delete_sweep\"], [data-icon-name=\"pause_circle_filled\"], [data-icon-name=\"play_circle_filled\"]',\n );\n }\n\n function refresh() {\n for (const element of hidden) {\n if (!element.isConnected || !isMutation(element)) {\n element.removeAttribute(marker);\n hidden.delete(element);\n }\n }\n for (const element of document.querySelectorAll<HTMLElement>(`${directActions}, .MenuActions .MenuItem`)) {\n if (isMutation(element)) {\n element.setAttribute(marker, \"\");\n hidden.add(element);\n }\n }\n }\n\n function intercept(event: Event) {\n if (!preferences.enabled || !(event.target instanceof Element)) return;\n if (event instanceof KeyboardEvent && ![\"Enter\", \" \"].includes(event.key)) return;\n const target = event.target.closest<HTMLElement>(`[${marker}], ${directActions}, .MenuItem`);\n if (!target || !isMutation(target)) return;\n event.preventDefault();\n event.stopImmediatePropagation();\n }\n\n const observer = new MutationObserver(refresh);\n const stop = reaction(\n () => preferences.enabled,\n (enabled) => {\n observer.disconnect();\n restore();\n if (!enabled) return;\n document.head.append(style);\n refresh();\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n characterData: true,\n attributes: true,\n attributeFilter: [\"class\", \"data-testid\", \"title\"],\n });\n },\n { fireImmediately: true },\n );\n document.addEventListener(\"click\", intercept, true);\n document.addEventListener(\"keydown\", intercept, true);\n\n return () => {\n stop();\n observer.disconnect();\n document.removeEventListener(\"click\", intercept, true);\n document.removeEventListener(\"keydown\", intercept, true);\n restore();\n };\n}\n"],"mappings":";;;AAGA,IAAM,SAAS;AACf,IAAM,WAAW;AACjB,IAAM,gBAAgB;CACpB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC,CAAC,KAAK,GAAG;AACV,IAAM,8BAAc,IAAI,IAAI;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,SAAgB,oBAAgC;CAC9C,MAAM,cAAc,oCAAA,yBAAyB,oBAA8C;CAC3F,MAAM,QAAQ,SAAS,cAAc,OAAO;CAC5C,MAAM,QAAQ,gBAAgB;CAC9B,MAAM,cAAc,IAAI,OAAO;CAC/B,MAAM,yBAAS,IAAI,IAAiB;CAEpC,SAAS,UAAU;EACjB,KAAK,MAAM,WAAW,QAAQ,QAAQ,gBAAgB,MAAM;EAC5D,OAAO,MAAM;EACb,MAAM,OAAO;CACf;CAEA,SAAS,WAAW,SAA+B;EACjD,IAAI,QAAQ,QAAQ,QAAQ,GAAG,OAAO;EACtC,IAAI,QAAQ,QAAQ,aAAa,GAAG,OAAO;EAC3C,IAAI,CAAC,QAAQ,QAAQ,yFAAuF,GAC1G,OAAO;EACT,MAAM,SAAS,QAAQ,cAAc,QAAQ,CAAC,EAAE,eAAe,QAAQ,YAAA,EAAc,KAAK,CAAC,CAAC,YAAY;EACxG,IAAI,SAAS,YAAY,IAAI,KAAK,GAAG,OAAO;EAC5C,OAAO,CAAC,CAAC,QAAQ,cACf,mNACF;CACF;CAEA,SAAS,UAAU;EACjB,KAAK,MAAM,WAAW,QACpB,IAAI,CAAC,QAAQ,eAAe,CAAC,WAAW,OAAO,GAAG;GAChD,QAAQ,gBAAgB,MAAM;GAC9B,OAAO,OAAO,OAAO;EACvB;EAEF,KAAK,MAAM,WAAW,SAAS,iBAA8B,GAAG,cAAc,yBAAyB,GACrG,IAAI,WAAW,OAAO,GAAG;GACvB,QAAQ,aAAa,QAAQ,EAAE;GAC/B,OAAO,IAAI,OAAO;EACpB;CAEJ;CAEA,SAAS,UAAU,OAAc;EAC/B,IAAI,CAAC,YAAY,WAAW,EAAE,MAAM,kBAAkB,UAAU;EAChE,IAAI,iBAAiB,iBAAiB,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,GAAG;EAC3E,MAAM,SAAS,MAAM,OAAO,QAAqB,IAAI,OAAO,KAAK,cAAc,YAAY;EAC3F,IAAI,CAAC,UAAU,CAAC,WAAW,MAAM,GAAG;EACpC,MAAM,eAAe;EACrB,MAAM,yBAAyB;CACjC;CAEA,MAAM,WAAW,IAAI,iBAAiB,OAAO;CAC7C,MAAM,OAAO,8BAAA,eACL,YAAY,UACjB,YAAY;EACX,SAAS,WAAW;EACpB,QAAQ;EACR,IAAI,CAAC,SAAS;EACd,SAAS,KAAK,OAAO,KAAK;EAC1B,QAAQ;EACR,SAAS,QAAQ,SAAS,MAAM;GAC9B,WAAW;GACX,SAAS;GACT,eAAe;GACf,YAAY;GACZ,iBAAiB;IAAC;IAAS;IAAe;GAAO;EACnD,CAAC;CACH,GACA,EAAE,iBAAiB,KAAK,CAC1B;CACA,SAAS,iBAAiB,SAAS,WAAW,IAAI;CAClD,SAAS,iBAAiB,WAAW,WAAW,IAAI;CAEpD,aAAa;EACX,KAAK;EACL,SAAS,WAAW;EACpB,SAAS,oBAAoB,SAAS,WAAW,IAAI;EACrD,SAAS,oBAAoB,WAAW,WAAW,IAAI;EACvD,QAAQ;CACV;AACF"}
@@ -0,0 +1,51 @@
1
+ var AI_TERMINAL_MAX_BYTES = 32 * 1024;
2
+ var MAX_SOURCE_CHARACTERS = 1e6;
3
+ function redactAiTerminalText(text) {
4
+ text = text.replace(/\\\n/g, "");
5
+ const lines = text.split("\n");
6
+ let blockIndent;
7
+ for (let index = 0; index < lines.length; index++) {
8
+ const line = lines[index];
9
+ const indent = line.match(/^\s*/)?.[0].length ?? 0;
10
+ if (blockIndent !== void 0) {
11
+ if (!line.trim() || indent > blockIndent) {
12
+ lines[index] = "";
13
+ continue;
14
+ }
15
+ blockIndent = void 0;
16
+ }
17
+ const field = line.match(/^(\s*(?:-\s*)?)(client-key-data|client-certificate-data|token|password|passwd|secret|api[_-]?key|value)\s*:\s*(.*)$/i);
18
+ if (!field) continue;
19
+ lines[index] = `${field[1]}${field[2]}: [REDACTED]`;
20
+ if (!field[3].trim() || /^[|>]/.test(field[3])) blockIndent = indent;
21
+ }
22
+ return lines.join("\n").replace(/\u001b\][^\u0007]*(?:\u0007|\u001b\\)/g, "").replace(/\u001b\[[0-?]*[ -/]*[@-~]/g, "").replace(/[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/g, "").replace(/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?(?:-----END [A-Z ]*PRIVATE KEY-----|$)/g, "[REDACTED]").replace(/^[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g, "[REDACTED]").replace(/\b([A-Za-z_][A-Za-z0-9_]*)=("(?:\\[\s\S]|[^"\\])*(?:"|$)|'[^']*(?:'|$)|[^\n]*)/g, "$1=[REDACTED]").replace(/(["'](?:password|passwd|token|secret|api[_-]?key|authorization)["']\s*:\s*)("(?:\\[\s\S]|[^"\\])*(?:"|$)|'[^']*(?:'|$))/gi, "$1\"[REDACTED]\"").replace(/(--(?:password|passwd|token|secret|api[_-]?key)(?:\s+|=))(?:("[^"\n]*"|'[^'\n]*')|[^\s]+)/gi, "$1[REDACTED]").replace(/\b(Bearer|Basic)\s+[^\s"']+/gi, "$1 [REDACTED]").replace(/\b((?:password|passwd|token|secret|api[_-]?key|authorization)\s*[:=]\s*)[^\n]+/gi, "$1[REDACTED]").replace(/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g, "[REDACTED]").replace(/\b(?:gh[pousr]_[A-Za-z0-9_]+|github_pat_[A-Za-z0-9_]+|sk-[A-Za-z0-9_-]{16,}|eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+)\b/g, "[REDACTED]").replace(/(https?:\/\/)[^\s/@]+:[^\s/@]+@/gi, "$1[REDACTED]@");
23
+ }
24
+ function sanitizeAiTerminalSnapshot(value) {
25
+ if (!value || typeof value !== "object") return;
26
+ const input = value;
27
+ if (typeof input.text !== "string" || input.text.length > MAX_SOURCE_CHARACTERS || typeof input.capturedAt !== "string" || input.capturedAt.length > 40 || !Number.isFinite(Date.parse(input.capturedAt))) return;
28
+ const lines = redactAiTerminalText(input.text.replace(/\r\n?/g, "\n")).split("\n");
29
+ while (lines.length && !lines[lines.length - 1].trim()) lines.pop();
30
+ const tail = [];
31
+ let bytes = 0;
32
+ for (let index = lines.length - 1; index >= 0 && tail.length < 300; index--) {
33
+ const line = lines[index];
34
+ const size = new TextEncoder().encode(line).length + (tail.length ? 1 : 0);
35
+ if (bytes + size > 32768) break;
36
+ bytes += size;
37
+ tail.unshift(line);
38
+ }
39
+ if (!tail.length || !tail.some((line) => line.trim())) return;
40
+ return {
41
+ text: tail.join("\n"),
42
+ capturedAt: new Date(input.capturedAt).toISOString(),
43
+ truncated: input.truncated === true || tail.length < lines.length
44
+ };
45
+ }
46
+ //#endregion
47
+ exports.AI_TERMINAL_MAX_BYTES = AI_TERMINAL_MAX_BYTES;
48
+ exports.redactAiTerminalText = redactAiTerminalText;
49
+ exports.sanitizeAiTerminalSnapshot = sanitizeAiTerminalSnapshot;
50
+
51
+ //# sourceMappingURL=ai-terminal-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-terminal-context.js","names":[],"sources":["../../../../src/common/ai-terminal-context.ts"],"sourcesContent":["export const AI_TERMINAL_MAX_ROWS = 300;\nexport const AI_TERMINAL_MAX_BYTES = 32 * 1024;\nconst MAX_SOURCE_CHARACTERS = 1_000_000;\n\nexport interface AiTerminalSnapshot {\n text: string;\n capturedAt: string;\n truncated: boolean;\n}\n\nexport function redactAiTerminalText(text: string): string {\n // collapse shell continuations before matching assignments so their values stay together\n text = text.replace(/\\\\\\n/g, \"\");\n const lines = text.split(\"\\n\");\n let blockIndent: number | undefined;\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index];\n const indent = line.match(/^\\s*/)?.[0].length ?? 0;\n if (blockIndent !== undefined) {\n if (!line.trim() || indent > blockIndent) {\n lines[index] = \"\";\n continue;\n }\n blockIndent = undefined;\n }\n const field = line.match(\n /^(\\s*(?:-\\s*)?)(client-key-data|client-certificate-data|token|password|passwd|secret|api[_-]?key|value)\\s*:\\s*(.*)$/i,\n );\n if (!field) continue;\n lines[index] = `${field[1]}${field[2]}: [REDACTED]`;\n if (!field[3].trim() || /^[|>]/.test(field[3])) blockIndent = indent;\n }\n return lines\n .join(\"\\n\")\n .replace(/\\u001b\\][^\\u0007]*(?:\\u0007|\\u001b\\\\)/g, \"\")\n .replace(/\\u001b\\[[0-?]*[ -/]*[@-~]/g, \"\")\n .replace(/[\\u0000-\\u0008\\u000b-\\u001f\\u007f-\\u009f]/g, \"\")\n .replace(/-----BEGIN [A-Z ]*PRIVATE KEY-----[\\s\\S]*?(?:-----END [A-Z ]*PRIVATE KEY-----|$)/g, \"[REDACTED]\")\n .replace(/^[\\s\\S]*?-----END [A-Z ]*PRIVATE KEY-----/g, \"[REDACTED]\")\n .replace(/\\b([A-Za-z_][A-Za-z0-9_]*)=(\"(?:\\\\[\\s\\S]|[^\"\\\\])*(?:\"|$)|'[^']*(?:'|$)|[^\\n]*)/g, \"$1=[REDACTED]\")\n .replace(\n /([\"'](?:password|passwd|token|secret|api[_-]?key|authorization)[\"']\\s*:\\s*)(\"(?:\\\\[\\s\\S]|[^\"\\\\])*(?:\"|$)|'[^']*(?:'|$))/gi,\n '$1\"[REDACTED]\"',\n )\n .replace(\n /(--(?:password|passwd|token|secret|api[_-]?key)(?:\\s+|=))(?:(\"[^\"\\n]*\"|'[^'\\n]*')|[^\\s]+)/gi,\n \"$1[REDACTED]\",\n )\n .replace(/\\b(Bearer|Basic)\\s+[^\\s\"']+/gi, \"$1 [REDACTED]\")\n .replace(/\\b((?:password|passwd|token|secret|api[_-]?key|authorization)\\s*[:=]\\s*)[^\\n]+/gi, \"$1[REDACTED]\")\n .replace(/\\b(?:AKIA|ASIA)[A-Z0-9]{16}\\b/g, \"[REDACTED]\")\n .replace(\n /\\b(?:gh[pousr]_[A-Za-z0-9_]+|github_pat_[A-Za-z0-9_]+|sk-[A-Za-z0-9_-]{16,}|eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+)\\b/g,\n \"[REDACTED]\",\n )\n .replace(/(https?:\\/\\/)[^\\s/@]+:[^\\s/@]+@/gi, \"$1[REDACTED]@\");\n}\n\nexport function sanitizeAiTerminalSnapshot(value: unknown): AiTerminalSnapshot | undefined {\n if (!value || typeof value !== \"object\") return;\n const input = value as Record<string, unknown>;\n if (\n typeof input.text !== \"string\" ||\n input.text.length > MAX_SOURCE_CHARACTERS ||\n typeof input.capturedAt !== \"string\" ||\n input.capturedAt.length > 40 ||\n !Number.isFinite(Date.parse(input.capturedAt))\n )\n return;\n // redact the complete input before truncation to preserve multiline assignment boundaries\n const safe = redactAiTerminalText(input.text.replace(/\\r\\n?/g, \"\\n\"));\n const lines = safe.split(\"\\n\");\n while (lines.length && !lines[lines.length - 1].trim()) lines.pop();\n const tail: string[] = [];\n let bytes = 0;\n for (let index = lines.length - 1; index >= 0 && tail.length < AI_TERMINAL_MAX_ROWS; index--) {\n const line = lines[index];\n const size = new TextEncoder().encode(line).length + (tail.length ? 1 : 0);\n if (bytes + size > AI_TERMINAL_MAX_BYTES) break;\n bytes += size;\n tail.unshift(line);\n }\n if (!tail.length || !tail.some((line) => line.trim())) return;\n return {\n text: tail.join(\"\\n\"),\n capturedAt: new Date(input.capturedAt).toISOString(),\n truncated: input.truncated === true || tail.length < lines.length,\n };\n}\n"],"mappings":"AACA,IAAa,wBAAwB,KAAK;AAC1C,IAAM,wBAAwB;AAQ9B,SAAgB,qBAAqB,MAAsB;CAEzD,OAAO,KAAK,QAAQ,SAAS,EAAE;CAC/B,MAAM,QAAQ,KAAK,MAAM,IAAI;CAC7B,IAAI;CACJ,KAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS;EACjD,MAAM,OAAO,MAAM;EACnB,MAAM,SAAS,KAAK,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU;EACjD,IAAI,gBAAgB,KAAA,GAAW;GAC7B,IAAI,CAAC,KAAK,KAAK,KAAK,SAAS,aAAa;IACxC,MAAM,SAAS;IACf;GACF;GACA,cAAc,KAAA;EAChB;EACA,MAAM,QAAQ,KAAK,MACjB,sHACF;EACA,IAAI,CAAC,OAAO;EACZ,MAAM,SAAS,GAAG,MAAM,KAAK,MAAM,GAAG;EACtC,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,KAAK,QAAQ,KAAK,MAAM,EAAE,GAAG,cAAc;CAChE;CACA,OAAO,MACJ,KAAK,IAAI,CAAC,CACV,QAAQ,0CAA0C,EAAE,CAAC,CACrD,QAAQ,8BAA8B,EAAE,CAAC,CACzC,QAAQ,8CAA8C,EAAE,CAAC,CACzD,QAAQ,qFAAqF,YAAY,CAAC,CAC1G,QAAQ,8CAA8C,YAAY,CAAC,CACnE,QAAQ,mFAAmF,eAAe,CAAC,CAC3G,QACC,6HACA,kBACF,CAAC,CACA,QACC,+FACA,cACF,CAAC,CACA,QAAQ,iCAAiC,eAAe,CAAC,CACzD,QAAQ,oFAAoF,cAAc,CAAC,CAC3G,QAAQ,kCAAkC,YAAY,CAAC,CACvD,QACC,qIACA,YACF,CAAC,CACA,QAAQ,qCAAqC,eAAe;AACjE;AAEA,SAAgB,2BAA2B,OAAgD;CACzF,IAAI,CAAC,SAAS,OAAO,UAAU,UAAU;CACzC,MAAM,QAAQ;CACd,IACE,OAAO,MAAM,SAAS,YACtB,MAAM,KAAK,SAAS,yBACpB,OAAO,MAAM,eAAe,YAC5B,MAAM,WAAW,SAAS,MAC1B,CAAC,OAAO,SAAS,KAAK,MAAM,MAAM,UAAU,CAAC,GAE7C;CAGF,MAAM,QADO,qBAAqB,MAAM,KAAK,QAAQ,UAAU,IAAI,CACrD,CAAA,CAAK,MAAM,IAAI;CAC7B,OAAO,MAAM,UAAU,CAAC,MAAM,MAAM,SAAS,EAAE,CAAC,KAAK,GAAG,MAAM,IAAI;CAClE,MAAM,OAAiB,CAAC;CACxB,IAAI,QAAQ;CACZ,KAAK,IAAI,QAAQ,MAAM,SAAS,GAAG,SAAS,KAAK,KAAK,SAAA,KAA+B,SAAS;EAC5F,MAAM,OAAO,MAAM;EACnB,MAAM,OAAO,IAAI,YAAY,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,UAAU,KAAK,SAAS,IAAI;EACxE,IAAI,QAAQ,OAAA,OAA8B;EAC1C,SAAS;EACT,KAAK,QAAQ,IAAI;CACnB;CACA,IAAI,CAAC,KAAK,UAAU,CAAC,KAAK,MAAM,SAAS,KAAK,KAAK,CAAC,GAAG;CACvD,OAAO;EACL,MAAM,KAAK,KAAK,IAAI;EACpB,YAAY,IAAI,KAAK,MAAM,UAAU,CAAC,CAAC,YAAY;EACnD,WAAW,MAAM,cAAc,QAAQ,KAAK,SAAS,MAAM;CAC7D;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"ai.js","names":[],"sources":["../../../../src/common/ai.ts"],"sourcesContent":["import type { AiResourceReference } from \"./ai-extras\";\n\nexport type AiProvider = \"codex\" | \"claude\";\n\nexport interface AiReadActivity {\n method: \"pods\" | \"nodes\" | \"resources\" | \"logs\";\n status: \"ok\" | \"unavailable\";\n}\n\nexport interface AiChatMessage {\n role: \"user\" | \"assistant\";\n text: string;\n}\n\nexport interface AiChatRequest {\n provider?: AiProvider;\n requestId?: string;\n messages: AiChatMessage[];\n context: {\n clusterId?: string;\n screen?: string;\n resource?: { kind?: string; namespace?: string; name?: string };\n };\n systemPrompt?: string;\n reasoningEffort?: string;\n model: string;\n speed: \"default\" | \"fast\";\n}\n\nexport interface AiChatResponse {\n references?: AiResourceReference[];\n provider?: AiProvider;\n text: string;\n reads?: AiReadActivity[];\n}\n\nexport const AI_CHAT_CHANNEL = \"freelens-power:ai-chat\";\n\nexport type AiFailureCode =\n | \"CLI_FAILURE\"\n | \"INVALID_REPLY\"\n | \"READ_LIMIT\"\n | \"TIMEOUT\"\n | \"CANCELLED\"\n | \"INPUT_LIMIT\"\n | \"UNAVAILABLE\"\n | \"UNSAFE_POLICY\";\n\nexport interface AiReadActivityEvent {\n requestId: string;\n method: AiReadActivity[\"method\"];\n status: \"reading\" | \"ok\" | \"unavailable\";\n}\n\nexport const AI_READ_ACTIVITY_CHANNEL = \"freelens-power:ai-read-activity\";\n\nexport function validAiRequestId(value: unknown): value is string {\n return typeof value === \"string\" && /^[a-zA-Z0-9_-]{1,100}$/.test(value);\n}\n"],"mappings":";AAoCA,IAAa,kBAAkB;AAkB/B,IAAa,2BAA2B"}
1
+ {"version":3,"file":"ai.js","names":[],"sources":["../../../../src/common/ai.ts"],"sourcesContent":["import type { AiResourceReference } from \"./ai-extras\";\n\nexport type AiProvider = \"codex\" | \"claude\";\n\nexport interface AiReadActivity {\n method: \"pods\" | \"nodes\" | \"resources\" | \"logs\";\n status: \"ok\" | \"unavailable\";\n}\n\nexport interface AiChatMessage {\n role: \"user\" | \"assistant\";\n text: string;\n}\n\nexport interface AiChatRequest {\n provider?: AiProvider;\n terminalSnapshot?: import(\"./ai-terminal-context\").AiTerminalSnapshot;\n requestId?: string;\n messages: AiChatMessage[];\n context: {\n clusterId?: string;\n screen?: string;\n resource?: { kind?: string; namespace?: string; name?: string };\n };\n systemPrompt?: string;\n reasoningEffort?: string;\n model: string;\n speed: \"default\" | \"fast\";\n}\n\nexport interface AiChatResponse {\n references?: AiResourceReference[];\n provider?: AiProvider;\n text: string;\n reads?: AiReadActivity[];\n}\n\nexport const AI_CHAT_CHANNEL = \"freelens-power:ai-chat\";\n\nexport type AiFailureCode =\n | \"CLI_FAILURE\"\n | \"INVALID_REPLY\"\n | \"READ_LIMIT\"\n | \"TIMEOUT\"\n | \"CANCELLED\"\n | \"INPUT_LIMIT\"\n | \"UNAVAILABLE\"\n | \"UNSAFE_POLICY\";\n\nexport interface AiReadActivityEvent {\n requestId: string;\n method: AiReadActivity[\"method\"];\n status: \"reading\" | \"ok\" | \"unavailable\";\n}\n\nexport const AI_READ_ACTIVITY_CHANNEL = \"freelens-power:ai-read-activity\";\n\nexport function validAiRequestId(value: unknown): value is string {\n return typeof value === \"string\" && /^[a-zA-Z0-9_-]{1,100}$/.test(value);\n}\n"],"mappings":";AAqCA,IAAa,kBAAkB;AAkB/B,IAAa,2BAA2B"}
@@ -0,0 +1,6 @@
1
+ //#region src/common/cluster-icon-ipc.ts
2
+ var CLUSTER_ICONS_CHANNEL = "freelens-power:cluster-icons";
3
+ //#endregion
4
+ exports.CLUSTER_ICONS_CHANNEL = CLUSTER_ICONS_CHANNEL;
5
+
6
+ //# sourceMappingURL=cluster-icon-ipc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cluster-icon-ipc.js","names":[],"sources":["../../../../src/common/cluster-icon-ipc.ts"],"sourcesContent":["import type { ClusterIconDesign } from \"./cluster-icons\";\n\nexport const CLUSTER_ICONS_CHANNEL = \"freelens-power:cluster-icons\";\n\nexport interface ClusterIconEntry {\n id: string;\n name: string;\n icon?: string;\n design?: ClusterIconDesign;\n customized: boolean;\n}\n\nexport type ClusterIconRequest = { operation: \"list\" } | { operation: \"apply\"; id: string; design: ClusterIconDesign };\n"],"mappings":";AAEA,IAAa,wBAAwB"}
@@ -0,0 +1,133 @@
1
+ //#region src/common/cluster-icons.ts
2
+ var GLYPHS = Object.freeze([
3
+ Object.freeze({
4
+ id: "window",
5
+ label: "Window",
6
+ body: "<g transform=\"translate(32 11.4) scale(1.168000000) translate(-32 -14)\" stroke-width=\"2.397260274\"><rect x=\"16\" y=\"14\" width=\"32\" height=\"25\" rx=\"4\"/><path d=\"M16 22h32M23 18h.1M28 18h.1M24 28l-4 3 4 3M35 28h7M35 34h5\"/></g>"
7
+ }),
8
+ Object.freeze({
9
+ id: "server",
10
+ label: "Server",
11
+ body: "<g transform=\"translate(32 11.4) scale(1.006896552) translate(-32 -13)\" stroke-width=\"2.780821917\"><rect x=\"17\" y=\"13\" width=\"30\" height=\"12\" rx=\"4\"/><rect x=\"17\" y=\"30\" width=\"30\" height=\"12\" rx=\"4\"/><path d=\"M23 19h.1M23 36h.1M32 19h8M32 36h8\"/></g>"
12
+ }),
13
+ Object.freeze({
14
+ id: "database",
15
+ label: "Database",
16
+ body: "<g transform=\"translate(32 11.4) scale(0.941935484) translate(-32 -11)\" stroke-width=\"2.972602739\"><ellipse cx=\"32\" cy=\"17\" rx=\"15\" ry=\"6\"/><path d=\"M17 17v19c0 8 30 8 30 0V17M17 26c0 8 30 8 30 0\"/></g>"
17
+ }),
18
+ Object.freeze({
19
+ id: "briefcase",
20
+ label: "Briefcase",
21
+ body: "<g transform=\"translate(32 11.4) scale(0.973333333) translate(-32 -13)\" stroke-width=\"2.876712330\"><rect x=\"14\" y=\"20\" width=\"36\" height=\"23\" rx=\"4\"/><path d=\"M25 20v-5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v5M14 28c10 7 26 7 36 0\"/><rect x=\"29\" y=\"29\" width=\"6\" height=\"7\" rx=\"1.5\" fill=\"#292d38\"/></g>"
22
+ }),
23
+ Object.freeze({
24
+ id: "sailboat",
25
+ label: "Sailboat",
26
+ body: "<g transform=\"translate(32 11.4) scale(0.834285714) translate(-32 -11)\" stroke-width=\"3.356164385\"><path d=\"M31 11v23H17zM36 18l11 16H36zM13 39h38l-7 7H21z\"/></g>"
27
+ }),
28
+ Object.freeze({
29
+ id: "network",
30
+ label: "Network",
31
+ body: "<g transform=\"translate(32 11.4) scale(0.768421053) translate(-32 -7)\" stroke-width=\"3.643835615\"><circle cx=\"32\" cy=\"26\" r=\"7\"/><path d=\"M32 13v6M32 33v6M19 26h6M39 26h6\"/><circle cx=\"32\" cy=\"10\" r=\"3\"/><circle cx=\"32\" cy=\"42\" r=\"3\"/><circle cx=\"16\" cy=\"26\" r=\"3\"/><circle cx=\"48\" cy=\"26\" r=\"3\"/></g>"
32
+ }),
33
+ Object.freeze({
34
+ id: "box",
35
+ label: "Box",
36
+ body: "<g transform=\"translate(32 11.4) scale(0.834285714) translate(-32 -11)\" stroke-width=\"3.356164385\"><path d=\"M32 11l17 10v17L32 46 15 38V21zM15 21l17 9 17-9M32 30v16\"/></g>"
37
+ }),
38
+ Object.freeze({
39
+ id: "blocks",
40
+ label: "Blocks",
41
+ body: "<rect x=\"17\" y=\"11.4\" width=\"10\" height=\"9\" rx=\"1.6\"/><rect x=\"37\" y=\"11.4\" width=\"10\" height=\"9\" rx=\"1.6\"/><rect x=\"27\" y=\"31.6\" width=\"10\" height=\"9\" rx=\"1.6\"/><path d=\"M22 20.4V26h20v-5.6M32 26v5.6\"/>"
42
+ }),
43
+ Object.freeze({
44
+ id: "git-branch",
45
+ label: "Git branch",
46
+ body: "<g transform=\"translate(32 11.4) scale(0.973333333) translate(-32 -12)\" stroke-width=\"2.876712330\"><circle cx=\"22\" cy=\"16\" r=\"4\"/><circle cx=\"42\" cy=\"16\" r=\"4\"/><circle cx=\"22\" cy=\"38\" r=\"4\"/><path d=\"M22 20v14M42 20c0 10-20 3-20 13\"/></g>"
47
+ }),
48
+ Object.freeze({
49
+ id: "cloud",
50
+ label: "Cloud",
51
+ body: "<path d=\"M22 40.6c-6 0-10-4-10-10 0-5 3-9 8-10 0-5 5-9.2 12-9.2s12 5 12 12c5 0 8 4 8 9 0 5-4 8.2-9 8.2z\"/>"
52
+ }),
53
+ Object.freeze({
54
+ id: "cpu",
55
+ label: "CPU",
56
+ body: "<rect x=\"21\" y=\"15\" width=\"22\" height=\"22\" rx=\"4\"/><rect x=\"27\" y=\"21\" width=\"10\" height=\"10\" rx=\"1\"/><path d=\"M26 11.4V15M32 11.4V15M38 11.4V15M26 37v3.6M32 37v3.6M38 37v3.6M17.4 20H21M17.4 26H21M17.4 32H21M43 20h3.6M43 26h3.6M43 32h3.6\"/>"
57
+ }),
58
+ Object.freeze({
59
+ id: "shield",
60
+ label: "Shield",
61
+ body: "<path d=\"M32 11.4l13 5v10c0 7-6 12-13 14.2C25 38.4 19 33.4 19 26.4v-10zM25 26l5 5 9-10\"/>"
62
+ }),
63
+ Object.freeze({
64
+ id: "globe",
65
+ label: "Globe",
66
+ body: "<circle cx=\"32\" cy=\"26\" r=\"14.6\"/><ellipse cx=\"32\" cy=\"26\" rx=\"6.5\" ry=\"14.6\"/><path d=\"M17.4 26h29.2M20.2 17.5h23.6M20.2 34.5h23.6\"/>"
67
+ }),
68
+ Object.freeze({
69
+ id: "key",
70
+ label: "Key",
71
+ body: "<g transform=\"translate(32 11.4) scale(1.39047619) translate(-12.5 -1)\" stroke-width=\"2.01369863\"><path d=\"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z\"/><circle cx=\"16.5\" cy=\"7.5\" r=\".5\" stroke-width=\"1\"/></g>"
72
+ }),
73
+ Object.freeze({
74
+ id: "rocket",
75
+ label: "Rocket",
76
+ body: "<g transform=\"translate(32 11.4) scale(1.497435897) translate(-12.25 -2)\" stroke-width=\"1.869863014\"><path d=\"M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09M9 12a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.4 22.4 0 0 1-4 2zM9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05\"/></g>"
77
+ })
78
+ ]);
79
+ var COLOR = /^#[\da-f]{6}$/i;
80
+ var LABEL = /^[\p{L}\p{N}\p{M}\p{P}\p{S} ]*$/u;
81
+ function normalizeClusterIconDesign(input) {
82
+ if (!input || typeof input !== "object" || Array.isArray(input)) throw new Error("Invalid cluster icon design");
83
+ const value = input;
84
+ if (typeof value.label !== "string" || !LABEL.test(value.label)) throw new Error("Use up to three visible characters for the label");
85
+ const label = value.label.normalize("NFC").trim();
86
+ if (Array.from(label).length > 3) throw new Error("Use up to three visible characters for the label");
87
+ if (typeof value.glyph !== "string" || !GLYPHS.some((glyph) => glyph.id === value.glyph)) throw new Error("Choose an available cluster icon");
88
+ for (const key of [
89
+ "outlineColor",
90
+ "labelColor",
91
+ "iconColor"
92
+ ]) if (typeof value[key] !== "string" || !COLOR.test(value[key])) throw new Error("Use a six-digit hexadecimal color");
93
+ return {
94
+ label,
95
+ glyph: value.glyph,
96
+ outlineColor: value.outlineColor.toLowerCase(),
97
+ labelColor: value.labelColor.toLowerCase(),
98
+ iconColor: value.iconColor.toLowerCase()
99
+ };
100
+ }
101
+ function defaultClusterIconDesign(name) {
102
+ const words = name.normalize("NFC").match(/[\p{L}\p{N}][\p{L}\p{N}\p{M}]*/gu) ?? [];
103
+ const abbreviation = words.length > 1 ? words.map((word) => Array.from(word)[0]).join("") : words[0] ?? "K8S";
104
+ return {
105
+ label: Array.from(abbreviation.toUpperCase()).slice(0, 3).join(""),
106
+ outlineColor: "#b49aff",
107
+ labelColor: "#b49aff",
108
+ glyph: "network",
109
+ iconColor: "#b49aff"
110
+ };
111
+ }
112
+ function escapeXml(text) {
113
+ return text.replace(/[&<>"']/g, (character) => ({
114
+ "&": "&amp;",
115
+ "<": "&lt;",
116
+ ">": "&gt;",
117
+ "\"": "&quot;",
118
+ "'": "&apos;"
119
+ })[character]);
120
+ }
121
+ function clusterIconDataUrl(input) {
122
+ const design = normalizeClusterIconDesign(input);
123
+ const glyph = GLYPHS.find((candidate) => candidate.id === design.glyph);
124
+ const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 64 64"><rect x="2" y="2" width="60" height="60" rx="15" fill="#292d38" stroke="${design.outlineColor}" stroke-width="3"/><g fill="none" stroke="${design.iconColor}" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round">${glyph.body}</g><rect x="15" y="46" width="34" height="12" rx="6" fill="${design.labelColor}"/><text x="32" y="55.2" text-anchor="middle" font-family="Helvetica,Arial,sans-serif" font-size="9.5" font-weight="800" fill="#292d38">${escapeXml(design.label)}</text></svg>`;
125
+ return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
126
+ }
127
+ //#endregion
128
+ exports.GLYPHS = GLYPHS;
129
+ exports.clusterIconDataUrl = clusterIconDataUrl;
130
+ exports.defaultClusterIconDesign = defaultClusterIconDesign;
131
+ exports.normalizeClusterIconDesign = normalizeClusterIconDesign;
132
+
133
+ //# sourceMappingURL=cluster-icons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cluster-icons.js","names":[],"sources":["../../../../src/common/cluster-icons.ts"],"sourcesContent":["export interface ClusterIconDesign {\n label: string;\n outlineColor: string;\n labelColor: string;\n glyph: string;\n iconColor: string;\n}\n\n// glyphs share the reference fitting, with Lucide contours for [key] and [rocket]\nexport const GLYPHS = Object.freeze([\n Object.freeze({\n id: \"window\",\n label: \"Window\",\n body: '<g transform=\"translate(32 11.4) scale(1.168000000) translate(-32 -14)\" stroke-width=\"2.397260274\"><rect x=\"16\" y=\"14\" width=\"32\" height=\"25\" rx=\"4\"/><path d=\"M16 22h32M23 18h.1M28 18h.1M24 28l-4 3 4 3M35 28h7M35 34h5\"/></g>',\n }),\n Object.freeze({\n id: \"server\",\n label: \"Server\",\n body: '<g transform=\"translate(32 11.4) scale(1.006896552) translate(-32 -13)\" stroke-width=\"2.780821917\"><rect x=\"17\" y=\"13\" width=\"30\" height=\"12\" rx=\"4\"/><rect x=\"17\" y=\"30\" width=\"30\" height=\"12\" rx=\"4\"/><path d=\"M23 19h.1M23 36h.1M32 19h8M32 36h8\"/></g>',\n }),\n Object.freeze({\n id: \"database\",\n label: \"Database\",\n body: '<g transform=\"translate(32 11.4) scale(0.941935484) translate(-32 -11)\" stroke-width=\"2.972602739\"><ellipse cx=\"32\" cy=\"17\" rx=\"15\" ry=\"6\"/><path d=\"M17 17v19c0 8 30 8 30 0V17M17 26c0 8 30 8 30 0\"/></g>',\n }),\n Object.freeze({\n id: \"briefcase\",\n label: \"Briefcase\",\n body: '<g transform=\"translate(32 11.4) scale(0.973333333) translate(-32 -13)\" stroke-width=\"2.876712330\"><rect x=\"14\" y=\"20\" width=\"36\" height=\"23\" rx=\"4\"/><path d=\"M25 20v-5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v5M14 28c10 7 26 7 36 0\"/><rect x=\"29\" y=\"29\" width=\"6\" height=\"7\" rx=\"1.5\" fill=\"#292d38\"/></g>',\n }),\n Object.freeze({\n id: \"sailboat\",\n label: \"Sailboat\",\n body: '<g transform=\"translate(32 11.4) scale(0.834285714) translate(-32 -11)\" stroke-width=\"3.356164385\"><path d=\"M31 11v23H17zM36 18l11 16H36zM13 39h38l-7 7H21z\"/></g>',\n }),\n Object.freeze({\n id: \"network\",\n label: \"Network\",\n body: '<g transform=\"translate(32 11.4) scale(0.768421053) translate(-32 -7)\" stroke-width=\"3.643835615\"><circle cx=\"32\" cy=\"26\" r=\"7\"/><path d=\"M32 13v6M32 33v6M19 26h6M39 26h6\"/><circle cx=\"32\" cy=\"10\" r=\"3\"/><circle cx=\"32\" cy=\"42\" r=\"3\"/><circle cx=\"16\" cy=\"26\" r=\"3\"/><circle cx=\"48\" cy=\"26\" r=\"3\"/></g>',\n }),\n Object.freeze({\n id: \"box\",\n label: \"Box\",\n body: '<g transform=\"translate(32 11.4) scale(0.834285714) translate(-32 -11)\" stroke-width=\"3.356164385\"><path d=\"M32 11l17 10v17L32 46 15 38V21zM15 21l17 9 17-9M32 30v16\"/></g>',\n }),\n Object.freeze({\n id: \"blocks\",\n label: \"Blocks\",\n body: '<rect x=\"17\" y=\"11.4\" width=\"10\" height=\"9\" rx=\"1.6\"/><rect x=\"37\" y=\"11.4\" width=\"10\" height=\"9\" rx=\"1.6\"/><rect x=\"27\" y=\"31.6\" width=\"10\" height=\"9\" rx=\"1.6\"/><path d=\"M22 20.4V26h20v-5.6M32 26v5.6\"/>',\n }),\n Object.freeze({\n id: \"git-branch\",\n label: \"Git branch\",\n body: '<g transform=\"translate(32 11.4) scale(0.973333333) translate(-32 -12)\" stroke-width=\"2.876712330\"><circle cx=\"22\" cy=\"16\" r=\"4\"/><circle cx=\"42\" cy=\"16\" r=\"4\"/><circle cx=\"22\" cy=\"38\" r=\"4\"/><path d=\"M22 20v14M42 20c0 10-20 3-20 13\"/></g>',\n }),\n Object.freeze({\n id: \"cloud\",\n label: \"Cloud\",\n body: '<path d=\"M22 40.6c-6 0-10-4-10-10 0-5 3-9 8-10 0-5 5-9.2 12-9.2s12 5 12 12c5 0 8 4 8 9 0 5-4 8.2-9 8.2z\"/>',\n }),\n Object.freeze({\n id: \"cpu\",\n label: \"CPU\",\n body: '<rect x=\"21\" y=\"15\" width=\"22\" height=\"22\" rx=\"4\"/><rect x=\"27\" y=\"21\" width=\"10\" height=\"10\" rx=\"1\"/><path d=\"M26 11.4V15M32 11.4V15M38 11.4V15M26 37v3.6M32 37v3.6M38 37v3.6M17.4 20H21M17.4 26H21M17.4 32H21M43 20h3.6M43 26h3.6M43 32h3.6\"/>',\n }),\n Object.freeze({\n id: \"shield\",\n label: \"Shield\",\n body: '<path d=\"M32 11.4l13 5v10c0 7-6 12-13 14.2C25 38.4 19 33.4 19 26.4v-10zM25 26l5 5 9-10\"/>',\n }),\n Object.freeze({\n id: \"globe\",\n label: \"Globe\",\n body: '<circle cx=\"32\" cy=\"26\" r=\"14.6\"/><ellipse cx=\"32\" cy=\"26\" rx=\"6.5\" ry=\"14.6\"/><path d=\"M17.4 26h29.2M20.2 17.5h23.6M20.2 34.5h23.6\"/>',\n }),\n Object.freeze({\n id: \"key\",\n label: \"Key\",\n body: '<g transform=\"translate(32 11.4) scale(1.39047619) translate(-12.5 -1)\" stroke-width=\"2.01369863\"><path d=\"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z\"/><circle cx=\"16.5\" cy=\"7.5\" r=\".5\" stroke-width=\"1\"/></g>',\n }),\n Object.freeze({\n id: \"rocket\",\n label: \"Rocket\",\n body: '<g transform=\"translate(32 11.4) scale(1.497435897) translate(-12.25 -2)\" stroke-width=\"1.869863014\"><path d=\"M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09M9 12a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.4 22.4 0 0 1-4 2zM9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05\"/></g>',\n }),\n]);\nconst COLOR = /^#[\\da-f]{6}$/i;\nconst LABEL = /^[\\p{L}\\p{N}\\p{M}\\p{P}\\p{S} ]*$/u;\n\nexport function normalizeClusterIconDesign(input: unknown): ClusterIconDesign {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) {\n throw new Error(\"Invalid cluster icon design\");\n }\n const value = input as Record<string, unknown>;\n if (typeof value.label !== \"string\" || !LABEL.test(value.label)) {\n throw new Error(\"Use up to three visible characters for the label\");\n }\n const label = value.label.normalize(\"NFC\").trim();\n if (Array.from(label).length > 3) {\n throw new Error(\"Use up to three visible characters for the label\");\n }\n if (typeof value.glyph !== \"string\" || !GLYPHS.some((glyph) => glyph.id === value.glyph)) {\n throw new Error(\"Choose an available cluster icon\");\n }\n const colors = [\"outlineColor\", \"labelColor\", \"iconColor\"] as const;\n for (const key of colors) {\n if (typeof value[key] !== \"string\" || !COLOR.test(value[key] as string)) {\n throw new Error(\"Use a six-digit hexadecimal color\");\n }\n }\n return {\n label,\n glyph: value.glyph,\n outlineColor: (value.outlineColor as string).toLowerCase(),\n labelColor: (value.labelColor as string).toLowerCase(),\n iconColor: (value.iconColor as string).toLowerCase(),\n };\n}\n\nexport function defaultClusterIconDesign(name: string): ClusterIconDesign {\n const words = name.normalize(\"NFC\").match(/[\\p{L}\\p{N}][\\p{L}\\p{N}\\p{M}]*/gu) ?? [];\n const abbreviation = words.length > 1 ? words.map((word) => Array.from(word)[0]).join(\"\") : (words[0] ?? \"K8S\");\n return {\n label: Array.from(abbreviation.toUpperCase()).slice(0, 3).join(\"\"),\n outlineColor: \"#b49aff\",\n labelColor: \"#b49aff\",\n glyph: \"network\",\n iconColor: \"#b49aff\",\n };\n}\n\nfunction escapeXml(text: string): string {\n return text.replace(\n /[&<>\"']/g,\n (character) => ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\", \"'\": \"&apos;\" })[character]!,\n );\n}\n\nexport function clusterIconDataUrl(input: ClusterIconDesign): string {\n const design = normalizeClusterIconDesign(input);\n const glyph = GLYPHS.find((candidate) => candidate.id === design.glyph)!;\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"256\" height=\"256\" viewBox=\"0 0 64 64\"><rect x=\"2\" y=\"2\" width=\"60\" height=\"60\" rx=\"15\" fill=\"#292d38\" stroke=\"${design.outlineColor}\" stroke-width=\"3\"/><g fill=\"none\" stroke=\"${design.iconColor}\" stroke-width=\"2.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${glyph.body}</g><rect x=\"15\" y=\"46\" width=\"34\" height=\"12\" rx=\"6\" fill=\"${design.labelColor}\"/><text x=\"32\" y=\"55.2\" text-anchor=\"middle\" font-family=\"Helvetica,Arial,sans-serif\" font-size=\"9.5\" font-weight=\"800\" fill=\"#292d38\">${escapeXml(design.label)}</text></svg>`;\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;\n}\n"],"mappings":"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"}
@@ -25,8 +25,9 @@ function sanitizeDashboardCards(value) {
25
25
  id,
26
26
  title: typeof card.title === "string" && card.title.trim() ? card.title.trim() : new URL(url).hostname,
27
27
  url,
28
- size: card.size === "s" || card.size === "l" ? card.size : "m",
28
+ size: card.size === "xs" || card.size === "s" || card.size === "l" || card.size === "xl" ? card.size : "m",
29
29
  autoRefresh: card.autoRefresh === true,
30
+ ...card.refreshEvery10Seconds === true ? { refreshEvery10Seconds: true } : {},
30
31
  ...require_dashboard_selector.normalizeDashboardSelector(card.selector) ? { selector: require_dashboard_selector.normalizeDashboardSelector(card.selector) } : {}
31
32
  }];
32
33
  });
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard.js","names":[],"sources":["../../../../src/common/dashboard.ts"],"sourcesContent":["import { normalizeDashboardSelector } from \"./dashboard-selector\";\n\nexport type DashboardCardSize = \"s\" | \"m\" | \"l\";\n\nexport interface DashboardCard {\n id: string;\n title: string;\n url: string;\n size: DashboardCardSize;\n autoRefresh?: boolean;\n selector?: string;\n}\n\nexport function normalizeDashboardUrl(value: string): string | undefined {\n try {\n const url = new URL(value.trim());\n if ((url.protocol !== \"http:\" && url.protocol !== \"https:\") || !url.hostname) return undefined;\n return url.href;\n } catch {\n return undefined;\n }\n}\n\nexport function sanitizeDashboardCards(value: unknown): DashboardCard[] {\n if (!Array.isArray(value)) return [];\n const ids = new Set<string>();\n return value.flatMap((entry: unknown) => {\n if (!entry || typeof entry !== \"object\") return [];\n const card = entry as Partial<DashboardCard>;\n const url = typeof card.url === \"string\" ? normalizeDashboardUrl(card.url) : undefined;\n if (!url) return [];\n const preferredId = typeof card.id === \"string\" ? card.id.trim() : \"\";\n let id = preferredId || `card-${encodeURIComponent(url)}`;\n for (let suffix = 2; ids.has(id); suffix++) id = `${preferredId || `card-${encodeURIComponent(url)}`}-${suffix}`;\n ids.add(id);\n return [\n {\n id,\n title: typeof card.title === \"string\" && card.title.trim() ? card.title.trim() : new URL(url).hostname,\n url,\n size: card.size === \"s\" || card.size === \"l\" ? card.size : \"m\",\n autoRefresh: card.autoRefresh === true,\n ...(normalizeDashboardSelector(card.selector) ? { selector: normalizeDashboardSelector(card.selector) } : {}),\n } satisfies DashboardCard,\n ];\n });\n}\n"],"mappings":";;AAaA,SAAgB,sBAAsB,OAAmC;CACvE,IAAI;EACF,MAAM,MAAM,IAAI,IAAI,MAAM,KAAK,CAAC;EAChC,IAAK,IAAI,aAAa,WAAW,IAAI,aAAa,YAAa,CAAC,IAAI,UAAU,OAAO,KAAA;EACrF,OAAO,IAAI;CACb,QAAQ;EACN;CACF;AACF;AAEA,SAAgB,uBAAuB,OAAiC;CACtE,IAAI,CAAC,MAAM,QAAQ,KAAK,GAAG,OAAO,CAAC;CACnC,MAAM,sBAAM,IAAI,IAAY;CAC5B,OAAO,MAAM,SAAS,UAAmB;EACvC,IAAI,CAAC,SAAS,OAAO,UAAU,UAAU,OAAO,CAAC;EACjD,MAAM,OAAO;EACb,MAAM,MAAM,OAAO,KAAK,QAAQ,WAAW,sBAAsB,KAAK,GAAG,IAAI,KAAA;EAC7E,IAAI,CAAC,KAAK,OAAO,CAAC;EAClB,MAAM,cAAc,OAAO,KAAK,OAAO,WAAW,KAAK,GAAG,KAAK,IAAI;EACnE,IAAI,KAAK,eAAe,QAAQ,mBAAmB,GAAG;EACtD,KAAK,IAAI,SAAS,GAAG,IAAI,IAAI,EAAE,GAAG,UAAU,KAAK,GAAG,eAAe,QAAQ,mBAAmB,GAAG,IAAI,GAAG;EACxG,IAAI,IAAI,EAAE;EACV,OAAO,CACL;GACE;GACA,OAAO,OAAO,KAAK,UAAU,YAAY,KAAK,MAAM,KAAK,IAAI,KAAK,MAAM,KAAK,IAAI,IAAI,IAAI,GAAG,CAAC,CAAC;GAC9F;GACA,MAAM,KAAK,SAAS,OAAO,KAAK,SAAS,MAAM,KAAK,OAAO;GAC3D,aAAa,KAAK,gBAAgB;GAClC,GAAI,2BAAA,2BAA2B,KAAK,QAAQ,IAAI,EAAE,UAAU,2BAAA,2BAA2B,KAAK,QAAQ,EAAE,IAAI,CAAC;EAC7G,CACF;CACF,CAAC;AACH"}
1
+ {"version":3,"file":"dashboard.js","names":[],"sources":["../../../../src/common/dashboard.ts"],"sourcesContent":["import { normalizeDashboardSelector } from \"./dashboard-selector\";\n\nexport type DashboardCardSize = \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\";\n\nexport interface DashboardCard {\n id: string;\n title: string;\n url: string;\n size: DashboardCardSize;\n autoRefresh?: boolean;\n refreshEvery10Seconds?: boolean;\n selector?: string;\n}\n\nexport function normalizeDashboardUrl(value: string): string | undefined {\n try {\n const url = new URL(value.trim());\n if ((url.protocol !== \"http:\" && url.protocol !== \"https:\") || !url.hostname) return undefined;\n return url.href;\n } catch {\n return undefined;\n }\n}\n\nexport function sanitizeDashboardCards(value: unknown): DashboardCard[] {\n if (!Array.isArray(value)) return [];\n const ids = new Set<string>();\n return value.flatMap((entry: unknown) => {\n if (!entry || typeof entry !== \"object\") return [];\n const card = entry as Partial<DashboardCard>;\n const url = typeof card.url === \"string\" ? normalizeDashboardUrl(card.url) : undefined;\n if (!url) return [];\n const preferredId = typeof card.id === \"string\" ? card.id.trim() : \"\";\n let id = preferredId || `card-${encodeURIComponent(url)}`;\n for (let suffix = 2; ids.has(id); suffix++) id = `${preferredId || `card-${encodeURIComponent(url)}`}-${suffix}`;\n ids.add(id);\n return [\n {\n id,\n title: typeof card.title === \"string\" && card.title.trim() ? card.title.trim() : new URL(url).hostname,\n url,\n size: card.size === \"xs\" || card.size === \"s\" || card.size === \"l\" || card.size === \"xl\" ? card.size : \"m\",\n autoRefresh: card.autoRefresh === true,\n ...(card.refreshEvery10Seconds === true ? { refreshEvery10Seconds: true } : {}),\n ...(normalizeDashboardSelector(card.selector) ? { selector: normalizeDashboardSelector(card.selector) } : {}),\n } satisfies DashboardCard,\n ];\n });\n}\n"],"mappings":";;AAcA,SAAgB,sBAAsB,OAAmC;CACvE,IAAI;EACF,MAAM,MAAM,IAAI,IAAI,MAAM,KAAK,CAAC;EAChC,IAAK,IAAI,aAAa,WAAW,IAAI,aAAa,YAAa,CAAC,IAAI,UAAU,OAAO,KAAA;EACrF,OAAO,IAAI;CACb,QAAQ;EACN;CACF;AACF;AAEA,SAAgB,uBAAuB,OAAiC;CACtE,IAAI,CAAC,MAAM,QAAQ,KAAK,GAAG,OAAO,CAAC;CACnC,MAAM,sBAAM,IAAI,IAAY;CAC5B,OAAO,MAAM,SAAS,UAAmB;EACvC,IAAI,CAAC,SAAS,OAAO,UAAU,UAAU,OAAO,CAAC;EACjD,MAAM,OAAO;EACb,MAAM,MAAM,OAAO,KAAK,QAAQ,WAAW,sBAAsB,KAAK,GAAG,IAAI,KAAA;EAC7E,IAAI,CAAC,KAAK,OAAO,CAAC;EAClB,MAAM,cAAc,OAAO,KAAK,OAAO,WAAW,KAAK,GAAG,KAAK,IAAI;EACnE,IAAI,KAAK,eAAe,QAAQ,mBAAmB,GAAG;EACtD,KAAK,IAAI,SAAS,GAAG,IAAI,IAAI,EAAE,GAAG,UAAU,KAAK,GAAG,eAAe,QAAQ,mBAAmB,GAAG,IAAI,GAAG;EACxG,IAAI,IAAI,EAAE;EACV,OAAO,CACL;GACE;GACA,OAAO,OAAO,KAAK,UAAU,YAAY,KAAK,MAAM,KAAK,IAAI,KAAK,MAAM,KAAK,IAAI,IAAI,IAAI,GAAG,CAAC,CAAC;GAC9F;GACA,MAAM,KAAK,SAAS,QAAQ,KAAK,SAAS,OAAO,KAAK,SAAS,OAAO,KAAK,SAAS,OAAO,KAAK,OAAO;GACvG,aAAa,KAAK,gBAAgB;GAClC,GAAI,KAAK,0BAA0B,OAAO,EAAE,uBAAuB,KAAK,IAAI,CAAC;GAC7E,GAAI,2BAAA,2BAA2B,KAAK,QAAQ,IAAI,EAAE,UAAU,2BAAA,2BAA2B,KAAK,QAAQ,EAAE,IAAI,CAAC;EAC7G,CACF;CACF,CAAC;AACH"}
@@ -0,0 +1,11 @@
1
+ //#region src/common/date-time.ts
2
+ function formatDateTime(value) {
3
+ const date = value instanceof Date ? value : new Date(value);
4
+ if (!Number.isFinite(date.getTime())) return "Unavailable";
5
+ const pad = (part) => String(part).padStart(2, "0");
6
+ return `${pad(date.getDate())}.${pad(date.getMonth() + 1)}.${String(date.getFullYear()).padStart(4, "0")} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
7
+ }
8
+ //#endregion
9
+ exports.formatDateTime = formatDateTime;
10
+
11
+ //# sourceMappingURL=date-time.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-time.js","names":[],"sources":["../../../../src/common/date-time.ts"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\nexport function formatDateTime(value: string | number | Date): string {\n const date = value instanceof Date ? value : new Date(value);\n if (!Number.isFinite(date.getTime())) return \"Unavailable\";\n const pad = (part: number) => String(part).padStart(2, \"0\");\n return `${pad(date.getDate())}.${pad(date.getMonth() + 1)}.${String(date.getFullYear()).padStart(4, \"0\")} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;\n}\n"],"mappings":";AAEA,SAAgB,eAAe,OAAuC;CACpE,MAAM,OAAO,iBAAiB,OAAO,QAAQ,IAAI,KAAK,KAAK;CAC3D,IAAI,CAAC,OAAO,SAAS,KAAK,QAAQ,CAAC,GAAG,OAAO;CAC7C,MAAM,OAAO,SAAiB,OAAO,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG;CAC1D,OAAO,GAAG,IAAI,KAAK,QAAQ,CAAC,EAAE,GAAG,IAAI,KAAK,SAAS,IAAI,CAAC,EAAE,GAAG,OAAO,KAAK,YAAY,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE,IAAI,IAAI,KAAK,SAAS,CAAC,EAAE,GAAG,IAAI,KAAK,WAAW,CAAC,EAAE,GAAG,IAAI,KAAK,WAAW,CAAC;AACtL"}
@@ -1,5 +1,6 @@
1
1
  //#region src/common/monitoring-history.ts
2
2
  var MONITORING_HISTORY_CHANNEL = "freelens-power:monitoring-history";
3
+ var HISTORY_MAX_BYTES = 100 * 1024 * 1024;
3
4
  function validHistoryIdentity(value) {
4
5
  return !!value && [value.clusterId, value.uid].every((id) => typeof id === "string" && /^[a-zA-Z0-9_.:-]{1,128}$/.test(id)) && [
5
6
  "cluster",
@@ -9,6 +10,7 @@ function validHistoryIdentity(value) {
9
10
  ].includes(value.scope);
10
11
  }
11
12
  //#endregion
13
+ exports.HISTORY_MAX_BYTES = HISTORY_MAX_BYTES;
12
14
  exports.MONITORING_HISTORY_CHANNEL = MONITORING_HISTORY_CHANNEL;
13
15
  exports.validHistoryIdentity = validHistoryIdentity;
14
16
 
@@ -1 +1 @@
1
- {"version":3,"file":"monitoring-history.js","names":[],"sources":["../../../../src/common/monitoring-history.ts"],"sourcesContent":["export const MONITORING_HISTORY_CHANNEL = \"freelens-power:monitoring-history\";\nexport const HISTORY_RETENTION = 7 * 24 * 60 * 60 * 1000;\nexport const HISTORY_MAX_BYTES = 100 * 1024 * 1024;\nexport type HistoryIdentity = {\n clusterId: string;\n scope: \"cluster\" | \"node\" | \"pod\" | \"workload\";\n uid: string;\n};\nexport const HISTORY_METRICS = [\n \"cpu\",\n \"memory\",\n \"cpuRequests\",\n \"memoryRequests\",\n \"cpuLimits\",\n \"memoryLimits\",\n \"cpuCapacity\",\n \"memoryCapacity\",\n \"cpuAllocatable\",\n \"memoryAllocatable\",\n \"restarts\",\n] as const;\nexport type HistoryMetric = (typeof HISTORY_METRICS)[number];\nexport type HistorySample = HistoryIdentity & { time: number; values: Partial<Record<HistoryMetric, number>> };\nexport type HistoryQuery = HistoryIdentity & { from: number; to: number };\nexport type HistoryPoint = {\n time: number;\n resolution: number;\n metric: HistoryMetric;\n min: number;\n avg: number;\n max: number;\n count: number;\n gap: boolean;\n};\nexport type HistoryStatus = { available: boolean; enabled: boolean; bytes: number; samples: number; error?: string };\nexport type HistoryRequest =\n | { operation: \"status\" | \"clear\" }\n | { operation: \"append\"; samples: HistorySample[] }\n | { operation: \"query\"; query: HistoryQuery };\nexport function validHistoryIdentity(value: HistoryIdentity): boolean {\n return (\n !!value &&\n [value.clusterId, value.uid].every((id) => typeof id === \"string\" && /^[a-zA-Z0-9_.:-]{1,128}$/.test(id)) &&\n [\"cluster\", \"node\", \"pod\", \"workload\"].includes(value.scope)\n );\n}\nexport function projectHistorySamples(input: unknown, now = Date.now()): HistorySample[] {\n if (!Array.isArray(input) || input.length > 512) throw new Error(\"Invalid history samples\");\n return input.map((sample) => {\n if (\n !validHistoryIdentity(sample) ||\n !Number.isSafeInteger(sample.time) ||\n sample.time < now - HISTORY_RETENTION ||\n sample.time > now + 30_000 ||\n !sample.values ||\n typeof sample.values !== \"object\"\n )\n throw new Error(\"Invalid history sample\");\n const values: HistorySample[\"values\"] = {};\n for (const metric of HISTORY_METRICS) {\n const value = sample.values[metric];\n if (value === undefined) continue;\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0 || value > 1e30)\n throw new Error(\"Invalid history value\");\n values[metric] = value;\n }\n return { clusterId: sample.clusterId, scope: sample.scope, uid: sample.uid, time: sample.time, values };\n });\n}\n"],"mappings":";AAAA,IAAa,6BAA6B;AAuC1C,SAAgB,qBAAqB,OAAiC;CACpE,OACE,CAAC,CAAC,SACF,CAAC,MAAM,WAAW,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO,OAAO,OAAO,YAAY,2BAA2B,KAAK,EAAE,CAAC,KACxG;EAAC;EAAW;EAAQ;EAAO;CAAU,CAAC,CAAC,SAAS,MAAM,KAAK;AAE/D"}
1
+ {"version":3,"file":"monitoring-history.js","names":[],"sources":["../../../../src/common/monitoring-history.ts"],"sourcesContent":["export const MONITORING_HISTORY_CHANNEL = \"freelens-power:monitoring-history\";\nexport const HISTORY_RETENTION = 7 * 24 * 60 * 60 * 1000;\nexport const HISTORY_MAX_BYTES = 100 * 1024 * 1024;\nexport type HistoryIdentity = {\n clusterId: string;\n scope: \"cluster\" | \"node\" | \"pod\" | \"workload\";\n uid: string;\n};\nexport const HISTORY_METRICS = [\n \"cpu\",\n \"memory\",\n \"cpuRequests\",\n \"memoryRequests\",\n \"cpuLimits\",\n \"memoryLimits\",\n \"cpuCapacity\",\n \"memoryCapacity\",\n \"cpuAllocatable\",\n \"memoryAllocatable\",\n \"restarts\",\n] as const;\nexport type HistoryMetric = (typeof HISTORY_METRICS)[number];\nexport type HistorySample = HistoryIdentity & { time: number; values: Partial<Record<HistoryMetric, number>> };\nexport type HistoryQuery = HistoryIdentity & { from: number; to: number };\nexport type HistoryPoint = {\n time: number;\n resolution: number;\n metric: HistoryMetric;\n min: number;\n avg: number;\n max: number;\n count: number;\n gap: boolean;\n};\nexport type HistoryStatus = { available: boolean; enabled: boolean; bytes: number; samples: number; error?: string };\nexport type HistoryRequest =\n | { operation: \"status\" | \"clear\" }\n | { operation: \"append\"; samples: HistorySample[] }\n | { operation: \"query\"; query: HistoryQuery };\nexport function validHistoryIdentity(value: HistoryIdentity): boolean {\n return (\n !!value &&\n [value.clusterId, value.uid].every((id) => typeof id === \"string\" && /^[a-zA-Z0-9_.:-]{1,128}$/.test(id)) &&\n [\"cluster\", \"node\", \"pod\", \"workload\"].includes(value.scope)\n );\n}\nexport function projectHistorySamples(input: unknown, now = Date.now()): HistorySample[] {\n if (!Array.isArray(input) || input.length > 512) throw new Error(\"Invalid history samples\");\n return input.map((sample) => {\n if (\n !validHistoryIdentity(sample) ||\n !Number.isSafeInteger(sample.time) ||\n sample.time < now - HISTORY_RETENTION ||\n sample.time > now + 30_000 ||\n !sample.values ||\n typeof sample.values !== \"object\"\n )\n throw new Error(\"Invalid history sample\");\n const values: HistorySample[\"values\"] = {};\n for (const metric of HISTORY_METRICS) {\n const value = sample.values[metric];\n if (value === undefined) continue;\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0 || value > 1e30)\n throw new Error(\"Invalid history value\");\n values[metric] = value;\n }\n return { clusterId: sample.clusterId, scope: sample.scope, uid: sample.uid, time: sample.time, values };\n });\n}\n"],"mappings":";AAAA,IAAa,6BAA6B;AAE1C,IAAa,oBAAoB,MAAM,OAAO;AAqC9C,SAAgB,qBAAqB,OAAiC;CACpE,OACE,CAAC,CAAC,SACF,CAAC,MAAM,WAAW,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO,OAAO,OAAO,YAAY,2BAA2B,KAAK,EAAE,CAAC,KACxG;EAAC;EAAW;EAAQ;EAAO;CAAU,CAAC,CAAC,SAAS,MAAM,KAAK;AAE/D"}
@@ -1 +1 @@
1
- {"version":3,"file":"resource-diagnostics.js","names":[],"sources":["../../../../src/common/resource-diagnostics.ts"],"sourcesContent":["import { effectivePodResource as effectiveResource, parseQuantity } from \"./monitoring-math\";\n\nexport interface ResourceValues {\n requests?: Partial<Record<string, string>>;\n limits?: Partial<Record<string, string>>;\n}\nexport interface DiagnosticsObject {\n kind?: string;\n metadata: {\n uid?: string;\n name?: string;\n namespace?: string;\n labels?: Partial<Record<string, string>>;\n generation?: number;\n annotations?: Partial<Record<string, string>>;\n ownerReferences?: { uid: string; name?: string; kind?: string; controller?: boolean }[];\n };\n spec?: {\n nodeName?: string;\n schedulerName?: string;\n containers?: { resources?: ResourceValues }[];\n initContainers?: { resources?: ResourceValues; restartPolicy?: string }[];\n resources?: ResourceValues;\n overhead?: Partial<Record<string, string>>;\n nodeSelector?: Partial<Record<string, string>>;\n tolerations?: { key?: string; operator?: string; value?: string; effect?: string; tolerationSeconds?: number }[];\n taints?: { key: string; value?: string; effect: string }[];\n unschedulable?: boolean;\n affinity?: {\n nodeAffinity?: {\n requiredDuringSchedulingIgnoredDuringExecution?: unknown;\n };\n podAffinity?: unknown;\n podAntiAffinity?: unknown;\n };\n topologySpreadConstraints?: unknown[];\n volumes?: { persistentVolumeClaim?: { claimName: string } }[];\n };\n status?: {\n phase?: string;\n readyReplicas?: number;\n updatedReplicas?: number;\n observedGeneration?: number;\n conditions?: { type: string; status: string; reason?: string; message?: string; lastTransitionTime?: string }[];\n containerStatuses?: { name: string; restartCount: number; ready?: boolean }[];\n allocatable?: Partial<Record<string, string>>;\n };\n}\nexport interface PodUsage {\n uid: string;\n cpu?: number;\n memory?: number;\n}\nexport interface ResourceSummary {\n requests: number;\n scheduledRequests: number;\n unscheduledRequests: number;\n usage?: number;\n coveredPods: number;\n totalPods: number;\n unknownRequestPods: number;\n}\nexport interface ConsumerGroup {\n namespace: string;\n identity: string;\n kind: string;\n name: string;\n ownerResolved: boolean;\n pods: DiagnosticsObject[];\n cpu: ResourceSummary;\n memory: ResourceSummary;\n}\nexport { parseQuantity } from \"./monitoring-math\";\nexport function effectivePodResource(\n pod: DiagnosticsObject,\n metric: \"cpu\" | \"memory\",\n kind: \"requests\" | \"limits\" = \"requests\",\n): number {\n return effectiveResource(pod, metric, kind);\n}\nexport function buildConsumerGroups(\n pods: DiagnosticsObject[],\n owners: DiagnosticsObject[],\n usage: PodUsage[] = [],\n): ConsumerGroup[] {\n const objects = new Map(owners.filter((o) => o.metadata.uid).map((o) => [o.metadata.uid, o]));\n const metrics = new Map(usage.map((u) => [u.uid, u]));\n const groups = new Map<string, ConsumerGroup>();\n for (const [index, pod] of pods.entries()) {\n if (pod.status?.phase === \"Succeeded\" || pod.status?.phase === \"Failed\") continue;\n let owner = pod;\n let resolved = true;\n const visited = new Set<string>();\n let unresolved: { uid: string; name?: string; kind?: string } | undefined;\n while (true) {\n const references = owner.metadata.ownerReferences ?? [];\n const reference = references.find((r) => r.controller) ?? (references.length === 1 ? references[0] : undefined);\n if (!reference) break;\n if (visited.has(reference.uid)) {\n resolved = false;\n break;\n }\n visited.add(reference.uid);\n const next = objects.get(reference.uid);\n if (!next || next.metadata.namespace !== pod.metadata.namespace) {\n unresolved = reference;\n resolved = false;\n break;\n }\n owner = next;\n }\n const namespace = pod.metadata.namespace ?? \"default\";\n const identity = unresolved?.uid ?? owner.metadata.uid ?? `unidentified-pod-${index}`;\n const key = `${namespace}/${identity}`;\n let group = groups.get(key);\n if (!group) {\n const summary = (): ResourceSummary => ({\n requests: 0,\n scheduledRequests: 0,\n unscheduledRequests: 0,\n coveredPods: 0,\n totalPods: 0,\n unknownRequestPods: 0,\n });\n group = {\n namespace,\n identity,\n kind: unresolved?.kind ?? owner.kind ?? \"Pod\",\n name: unresolved?.name ?? owner.metadata.name ?? \"Unknown\",\n ownerResolved: resolved,\n pods: [],\n cpu: summary(),\n memory: summary(),\n };\n groups.set(key, group);\n }\n group.pods.push(pod);\n for (const metric of [\"cpu\", \"memory\"] as const) {\n const summary = group[metric];\n summary.totalPods++;\n try {\n const request = effectivePodResource(pod, metric);\n summary.requests += request;\n summary[pod.spec?.nodeName ? \"scheduledRequests\" : \"unscheduledRequests\"] += request;\n } catch {\n summary.unknownRequestPods++;\n }\n const value = pod.metadata.uid ? metrics.get(pod.metadata.uid)?.[metric] : undefined;\n if (value !== undefined && Number.isFinite(value) && value >= 0) {\n summary.coveredPods++;\n summary.usage = (summary.usage ?? 0) + value;\n }\n }\n }\n return [...groups.values()];\n}\nexport interface DiagnosticsEvent {\n metadata?: { uid?: string; creationTimestamp?: string };\n involvedObject?: { uid?: string; name?: string; namespace?: string };\n regarding?: { uid?: string; name?: string; namespace?: string };\n reason?: string;\n message?: string;\n note?: string;\n type?: string;\n count?: number;\n firstTimestamp?: string;\n lastTimestamp?: string;\n eventTime?: string;\n series?: { count?: number; lastObservedTime?: string };\n}\nexport interface TimelineEntry {\n id: string;\n reason: string;\n message: string;\n time?: string;\n firstTime?: string;\n count: number;\n certainty: \"reported\" | \"observed\" | \"unknown\";\n objectUid?: string;\n gap?: string;\n}\nconst validTime = (value?: string) => (value && Number.isFinite(Date.parse(value)) ? value : undefined);\nexport function normalizeEvents(events: DiagnosticsEvent[]): TimelineEntry[] {\n return events\n .map((event, index) => ({\n id: event.metadata?.uid ?? `event-${index}`,\n reason: event.reason ?? \"Event\",\n message: event.message ?? event.note ?? \"\",\n time:\n validTime(event.series?.lastObservedTime) ??\n validTime(event.lastTimestamp) ??\n validTime(event.eventTime) ??\n validTime(event.metadata?.creationTimestamp),\n firstTime: validTime(event.firstTimestamp) ?? validTime(event.eventTime),\n count: event.series?.count ?? event.count ?? 1,\n certainty: \"reported\" as const,\n objectUid: event.involvedObject?.uid ?? event.regarding?.uid,\n }))\n .map((entry) => ({ ...entry, certainty: entry.time ? entry.certainty : (\"unknown\" as const) }));\n}\nexport interface PendingEvidence {\n source: \"event\" | \"constraint\";\n message: string;\n node?: string;\n}\nexport function diagnosePendingPod(\n pod: DiagnosticsObject,\n nodes: DiagnosticsObject[],\n events: DiagnosticsEvent[] = [],\n pvcs?: DiagnosticsObject[],\n): { state: \"assigned-waiting\" | \"unscheduled\" | \"not-pending\"; evidence: PendingEvidence[]; limitations: string[] } {\n const state =\n pod.status?.phase !== \"Pending\" ? \"not-pending\" : pod.spec?.nodeName ? \"assigned-waiting\" : \"unscheduled\";\n const evidence: PendingEvidence[] = events\n .filter((event) => !!pod.metadata.uid && (event.involvedObject?.uid ?? event.regarding?.uid) === pod.metadata.uid)\n .map((event) => ({ source: \"event\", message: `${event.reason ?? \"Event\"}: ${event.message ?? event.note ?? \"\"}` }));\n const limitations = [\"Local checks do not establish exact schedulability or available node capacity\"];\n if (state !== \"unscheduled\") return { state, evidence, limitations };\n const spec = pod.spec;\n if (!nodes.length) limitations.push(\"Node data unavailable\");\n if (spec?.schedulerName && spec.schedulerName !== \"default-scheduler\")\n limitations.push(\"Custom scheduler profile is unknown\");\n if (spec?.affinity?.podAffinity || spec?.affinity?.podAntiAffinity || spec?.topologySpreadConstraints?.length)\n limitations.push(\"Pod affinity and topology constraints are not evaluated\");\n for (const node of nodes) {\n const reject = (message: string) => evidence.push({ source: \"constraint\", node: node.metadata.name, message });\n if (node.spec?.unschedulable) reject(\"Node is cordoned\");\n if (Object.entries(spec?.nodeSelector ?? {}).some(([key, value]) => node.metadata.labels?.[key] !== value))\n reject(\"Node selector does not match\");\n for (const taint of node.spec?.taints ?? []) {\n if (![\"NoSchedule\", \"NoExecute\"].includes(taint.effect)) continue;\n if (\n !(spec?.tolerations ?? []).some(\n (t) =>\n (!t.effect || t.effect === taint.effect) &&\n (t.operator === \"Exists\"\n ? !t.key || t.key === taint.key\n : t.key === taint.key && (t.value ?? \"\") === (taint.value ?? \"\")),\n )\n )\n reject(`Untolerated taint ${taint.key} (${taint.effect})`);\n }\n const required = spec?.affinity?.nodeAffinity?.requiredDuringSchedulingIgnoredDuringExecution;\n const terms =\n required &&\n typeof required === \"object\" &&\n \"nodeSelectorTerms\" in required &&\n Array.isArray(required.nodeSelectorTerms)\n ? (required.nodeSelectorTerms as {\n matchExpressions?: { key: string; operator: string; values?: string[] }[];\n matchFields?: unknown[];\n }[])\n : undefined;\n if (required && !terms) limitations.push(\"Required node affinity data is unsupported\");\n if (terms) {\n const unsupported = terms.some(\n (term) =>\n term.matchFields?.length ||\n term.matchExpressions?.some(\n (e) => ![\"In\", \"NotIn\", \"Exists\", \"DoesNotExist\", \"Gt\", \"Lt\"].includes(e.operator),\n ),\n );\n if (unsupported) {\n if (!limitations.includes(\"Required node affinity contains unsupported expressions\"))\n limitations.push(\"Required node affinity contains unsupported expressions\");\n } else if (\n !terms.some(\n (term) =>\n !!term.matchExpressions?.length &&\n term.matchExpressions.every((e) => {\n const value = node.metadata.labels?.[e.key];\n if (e.operator === \"Exists\") return value !== undefined;\n if (e.operator === \"DoesNotExist\") return value === undefined;\n if (e.operator === \"In\") return value !== undefined && !!e.values?.includes(value);\n if (e.operator === \"NotIn\") return value === undefined || !e.values?.includes(value);\n return (\n value !== undefined &&\n !!e.values?.length &&\n Number.isFinite(Number(value)) &&\n (e.operator === \"Gt\" ? Number(value) > Number(e.values[0]) : Number(value) < Number(e.values[0]))\n );\n }),\n )\n )\n reject(\"Required node affinity does not match\");\n }\n for (const metric of [\"cpu\", \"memory\"] as const) {\n try {\n if (\n node.status?.allocatable?.[metric] !== undefined &&\n effectivePodResource(pod, metric) > parseQuantity(node.status.allocatable[metric], metric === \"memory\")\n )\n reject(`Pod ${metric} request exceeds node allocatable`);\n } catch {\n limitations.push(`Invalid or unavailable ${metric} resource data`);\n }\n }\n }\n for (const volume of spec?.volumes ?? []) {\n const claim = volume.persistentVolumeClaim?.claimName;\n if (!claim) continue;\n const pvc = pvcs?.find(\n (item) => item.metadata.name === claim && item.metadata.namespace === pod.metadata.namespace,\n );\n if (!pvc) limitations.push(`PVC ${claim} data unavailable`);\n else if (pvc.status?.phase !== \"Bound\")\n limitations.push(`PVC ${claim} is not bound; delayed binding and storage topology require scheduler evidence`);\n }\n return { state, evidence, limitations: [...new Set(limitations)] };\n}\nexport function observePodChanges(\n previous: DiagnosticsObject[],\n current: DiagnosticsObject[],\n observedAt: string,\n): TimelineEntry[] {\n const entries: TimelineEntry[] = [];\n const prior = new Map(previous.filter((pod) => pod.metadata.uid).map((pod) => [pod.metadata.uid, pod]));\n for (const pod of current) {\n const old = pod.metadata.uid ? prior.get(pod.metadata.uid) : undefined;\n const add = (reason: string, message: string) =>\n entries.push({\n id: `${pod.metadata.uid ?? pod.metadata.name}/${reason}/${observedAt}`,\n reason,\n message,\n time: validTime(observedAt),\n count: 1,\n certainty: validTime(observedAt) ? \"observed\" : \"unknown\",\n objectUid: pod.metadata.uid,\n gap: \"Change occurred between snapshots; exact transition time is unknown\",\n });\n if (!old) {\n add(\"FirstObserved\", `${pod.metadata.name ?? \"Pod\"} first observed; creation or rollout time is unknown`);\n continue;\n }\n if (old.status?.phase !== pod.status?.phase)\n add(\"PhaseChanged\", `${old.status?.phase ?? \"Unknown\"} → ${pod.status?.phase ?? \"Unknown\"}`);\n for (const status of pod.status?.containerStatuses ?? []) {\n const before = old.status?.containerStatuses?.find((item) => item.name === status.name);\n if (before && status.restartCount !== before.restartCount)\n add(`Restarts/${status.name}`, `${status.name}: restart count ${before.restartCount} → ${status.restartCount}`);\n if (before && status.ready !== before.ready)\n add(`Readiness/${status.name}`, `${status.name}: ready ${String(before.ready)} → ${String(status.ready)}`);\n }\n }\n return entries;\n}\n\nexport function observeResourceChanges(\n previous: DiagnosticsObject[],\n current: DiagnosticsObject[],\n observedAt: string,\n): TimelineEntry[] {\n const entries = observePodChanges(\n previous,\n current.filter((object) => object.kind === \"Pod\" || !!object.spec?.containers),\n observedAt,\n );\n const prior = new Map(\n previous.filter((object) => object.metadata.uid).map((object) => [object.metadata.uid, object]),\n );\n for (const object of current) {\n if (object.kind === \"Pod\" || object.spec?.containers) continue;\n const old = object.metadata.uid ? prior.get(object.metadata.uid) : undefined;\n if (!old) continue;\n const changes = ([\"readyReplicas\", \"updatedReplicas\", \"observedGeneration\"] as const)\n .filter((key) => old.status?.[key] !== object.status?.[key])\n .map((key) => `${key}: ${old.status?.[key] ?? \"unknown\"} → ${object.status?.[key] ?? \"unknown\"}`);\n if (old.metadata.generation !== object.metadata.generation)\n changes.push(`generation: ${old.metadata.generation ?? \"unknown\"} → ${object.metadata.generation ?? \"unknown\"}`);\n const revisionKey = \"deployment.kubernetes.io/revision\";\n if (old.metadata.annotations?.[revisionKey] !== object.metadata.annotations?.[revisionKey])\n changes.push(\n `revision: ${old.metadata.annotations?.[revisionKey] ?? \"unknown\"} → ${object.metadata.annotations?.[revisionKey] ?? \"unknown\"}`,\n );\n if (changes.length)\n entries.push({\n id: `${object.metadata.uid}/rollout/${observedAt}`,\n reason: \"RolloutObserved\",\n message: `${object.metadata.name ?? \"Workload\"}: ${changes.join(\", \")}`,\n time: validTime(observedAt),\n count: 1,\n certainty: validTime(observedAt) ? \"observed\" : \"unknown\",\n objectUid: object.metadata.uid,\n gap: \"Change occurred between snapshots; exact transition time is unknown\",\n });\n }\n return entries;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"resource-diagnostics.js","names":[],"sources":["../../../../src/common/resource-diagnostics.ts"],"sourcesContent":["import { effectivePodResource as effectiveResource, parseQuantity } from \"./monitoring-math\";\n\nexport interface ResourceValues {\n requests?: Partial<Record<string, string>>;\n limits?: Partial<Record<string, string>>;\n}\nexport interface DiagnosticsObject {\n kind?: string;\n metadata: {\n uid?: string;\n name?: string;\n namespace?: string;\n labels?: Partial<Record<string, string>>;\n generation?: number;\n annotations?: Partial<Record<string, string>>;\n ownerReferences?: { uid: string; name?: string; kind?: string; controller?: boolean }[];\n };\n spec?: {\n nodeName?: string;\n schedulerName?: string;\n containers?: { resources?: ResourceValues }[];\n initContainers?: { resources?: ResourceValues; restartPolicy?: string }[];\n resources?: ResourceValues;\n overhead?: Partial<Record<string, string>>;\n nodeSelector?: Partial<Record<string, string>>;\n tolerations?: { key?: string; operator?: string; value?: string; effect?: string; tolerationSeconds?: number }[];\n taints?: { key: string; value?: string; effect: string }[];\n unschedulable?: boolean;\n affinity?: {\n nodeAffinity?: {\n requiredDuringSchedulingIgnoredDuringExecution?: unknown;\n };\n podAffinity?: unknown;\n podAntiAffinity?: unknown;\n };\n topologySpreadConstraints?: unknown[];\n volumes?: { persistentVolumeClaim?: { claimName: string } }[];\n };\n status?: {\n phase?: string;\n readyReplicas?: number;\n updatedReplicas?: number;\n observedGeneration?: number;\n conditions?: { type: string; status: string; reason?: string; message?: string; lastTransitionTime?: string }[];\n containerStatuses?: { name: string; restartCount: number; ready?: boolean }[];\n allocatable?: Partial<Record<string, string>>;\n };\n}\nexport interface PodUsage {\n uid: string;\n cpu?: number;\n memory?: number;\n}\nexport interface ResourceSummary {\n requests: number;\n scheduledRequests: number;\n unscheduledRequests: number;\n usage?: number;\n coveredPods: number;\n totalPods: number;\n unknownRequestPods: number;\n}\nexport interface ConsumerGroup {\n namespace: string;\n identity: string;\n kind: string;\n name: string;\n ownerResolved: boolean;\n pods: DiagnosticsObject[];\n cpu: ResourceSummary;\n memory: ResourceSummary;\n}\nexport { parseQuantity } from \"./monitoring-math\";\nexport function effectivePodResource(\n pod: DiagnosticsObject,\n metric: \"cpu\" | \"memory\",\n kind: \"requests\" | \"limits\" = \"requests\",\n): number {\n return effectiveResource(pod, metric, kind);\n}\nexport function buildConsumerGroups(\n pods: DiagnosticsObject[],\n owners: DiagnosticsObject[],\n usage: PodUsage[] = [],\n): ConsumerGroup[] {\n const objects = new Map(owners.filter((o) => o.metadata.uid).map((o) => [o.metadata.uid, o]));\n const metrics = new Map(usage.map((u) => [u.uid, u]));\n const groups = new Map<string, ConsumerGroup>();\n for (const [index, pod] of pods.entries()) {\n if (pod.status?.phase === \"Succeeded\" || pod.status?.phase === \"Failed\") continue;\n let owner = pod;\n let resolved = true;\n const visited = new Set<string>();\n let unresolved: { uid: string; name?: string; kind?: string } | undefined;\n while (true) {\n const references = owner.metadata.ownerReferences ?? [];\n const reference = references.find((r) => r.controller) ?? (references.length === 1 ? references[0] : undefined);\n if (!reference) break;\n if (visited.has(reference.uid)) {\n resolved = false;\n break;\n }\n visited.add(reference.uid);\n const next = objects.get(reference.uid);\n if (!next || next.metadata.namespace !== pod.metadata.namespace) {\n unresolved = reference;\n resolved = false;\n break;\n }\n owner = next;\n }\n const namespace = pod.metadata.namespace ?? \"default\";\n const identity = unresolved?.uid ?? owner.metadata.uid ?? `unidentified-pod-${index}`;\n const key = `${namespace}/${identity}`;\n let group = groups.get(key);\n if (!group) {\n const summary = (): ResourceSummary => ({\n requests: 0,\n scheduledRequests: 0,\n unscheduledRequests: 0,\n coveredPods: 0,\n totalPods: 0,\n unknownRequestPods: 0,\n });\n group = {\n namespace,\n identity,\n kind: unresolved?.kind ?? owner.kind ?? \"Pod\",\n name: unresolved?.name ?? owner.metadata.name ?? \"Unknown\",\n ownerResolved: resolved,\n pods: [],\n cpu: summary(),\n memory: summary(),\n };\n groups.set(key, group);\n }\n group.pods.push(pod);\n for (const metric of [\"cpu\", \"memory\"] as const) {\n const summary = group[metric];\n summary.totalPods++;\n try {\n const request = effectivePodResource(pod, metric);\n summary.requests += request;\n summary[pod.spec?.nodeName ? \"scheduledRequests\" : \"unscheduledRequests\"] += request;\n } catch {\n summary.unknownRequestPods++;\n }\n const value = pod.metadata.uid ? metrics.get(pod.metadata.uid)?.[metric] : undefined;\n if (value !== undefined && Number.isFinite(value) && value >= 0) {\n summary.coveredPods++;\n summary.usage = (summary.usage ?? 0) + value;\n }\n }\n }\n return [...groups.values()];\n}\nexport interface DiagnosticsEvent {\n metadata?: { uid?: string; creationTimestamp?: string };\n involvedObject?: { uid?: string; name?: string; namespace?: string; kind?: string };\n regarding?: { uid?: string; name?: string; namespace?: string; kind?: string };\n reason?: string;\n message?: string;\n note?: string;\n type?: string;\n count?: number;\n firstTimestamp?: string;\n lastTimestamp?: string;\n eventTime?: string;\n series?: { count?: number; lastObservedTime?: string };\n}\nexport interface TimelineEntry {\n id: string;\n reason: string;\n message: string;\n time?: string;\n firstTime?: string;\n count: number;\n certainty: \"reported\" | \"observed\" | \"unknown\";\n objectUid?: string;\n gap?: string;\n}\nconst validTime = (value?: string) => (value && Number.isFinite(Date.parse(value)) ? value : undefined);\nexport function normalizeEvents(events: DiagnosticsEvent[]): TimelineEntry[] {\n return events\n .map((event, index) => ({\n id: event.metadata?.uid ?? `event-${index}`,\n reason: event.reason ?? \"Event\",\n message: event.message ?? event.note ?? \"\",\n time:\n validTime(event.series?.lastObservedTime) ??\n validTime(event.lastTimestamp) ??\n validTime(event.eventTime) ??\n validTime(event.metadata?.creationTimestamp),\n firstTime: validTime(event.firstTimestamp) ?? validTime(event.eventTime),\n count: event.series?.count ?? event.count ?? 1,\n certainty: \"reported\" as const,\n objectUid: event.involvedObject?.uid ?? event.regarding?.uid,\n }))\n .map((entry) => ({ ...entry, certainty: entry.time ? entry.certainty : (\"unknown\" as const) }));\n}\nexport interface PendingEvidence {\n source: \"event\" | \"constraint\";\n message: string;\n node?: string;\n}\nexport function diagnosePendingPod(\n pod: DiagnosticsObject,\n nodes: DiagnosticsObject[],\n events: DiagnosticsEvent[] = [],\n pvcs?: DiagnosticsObject[],\n): { state: \"assigned-waiting\" | \"unscheduled\" | \"not-pending\"; evidence: PendingEvidence[]; limitations: string[] } {\n const state =\n pod.status?.phase !== \"Pending\" ? \"not-pending\" : pod.spec?.nodeName ? \"assigned-waiting\" : \"unscheduled\";\n const evidence: PendingEvidence[] = events\n .filter((event) => !!pod.metadata.uid && (event.involvedObject?.uid ?? event.regarding?.uid) === pod.metadata.uid)\n .map((event) => ({ source: \"event\", message: `${event.reason ?? \"Event\"}: ${event.message ?? event.note ?? \"\"}` }));\n const limitations = [\"Local checks do not establish exact schedulability or available node capacity\"];\n if (state !== \"unscheduled\") return { state, evidence, limitations };\n const spec = pod.spec;\n if (!nodes.length) limitations.push(\"Node data unavailable\");\n if (spec?.schedulerName && spec.schedulerName !== \"default-scheduler\")\n limitations.push(\"Custom scheduler profile is unknown\");\n if (spec?.affinity?.podAffinity || spec?.affinity?.podAntiAffinity || spec?.topologySpreadConstraints?.length)\n limitations.push(\"Pod affinity and topology constraints are not evaluated\");\n for (const node of nodes) {\n const reject = (message: string) => evidence.push({ source: \"constraint\", node: node.metadata.name, message });\n if (node.spec?.unschedulable) reject(\"Node is cordoned\");\n if (Object.entries(spec?.nodeSelector ?? {}).some(([key, value]) => node.metadata.labels?.[key] !== value))\n reject(\"Node selector does not match\");\n for (const taint of node.spec?.taints ?? []) {\n if (![\"NoSchedule\", \"NoExecute\"].includes(taint.effect)) continue;\n if (\n !(spec?.tolerations ?? []).some(\n (t) =>\n (!t.effect || t.effect === taint.effect) &&\n (t.operator === \"Exists\"\n ? !t.key || t.key === taint.key\n : t.key === taint.key && (t.value ?? \"\") === (taint.value ?? \"\")),\n )\n )\n reject(`Untolerated taint ${taint.key} (${taint.effect})`);\n }\n const required = spec?.affinity?.nodeAffinity?.requiredDuringSchedulingIgnoredDuringExecution;\n const terms =\n required &&\n typeof required === \"object\" &&\n \"nodeSelectorTerms\" in required &&\n Array.isArray(required.nodeSelectorTerms)\n ? (required.nodeSelectorTerms as {\n matchExpressions?: { key: string; operator: string; values?: string[] }[];\n matchFields?: unknown[];\n }[])\n : undefined;\n if (required && !terms) limitations.push(\"Required node affinity data is unsupported\");\n if (terms) {\n const unsupported = terms.some(\n (term) =>\n term.matchFields?.length ||\n term.matchExpressions?.some(\n (e) => ![\"In\", \"NotIn\", \"Exists\", \"DoesNotExist\", \"Gt\", \"Lt\"].includes(e.operator),\n ),\n );\n if (unsupported) {\n if (!limitations.includes(\"Required node affinity contains unsupported expressions\"))\n limitations.push(\"Required node affinity contains unsupported expressions\");\n } else if (\n !terms.some(\n (term) =>\n !!term.matchExpressions?.length &&\n term.matchExpressions.every((e) => {\n const value = node.metadata.labels?.[e.key];\n if (e.operator === \"Exists\") return value !== undefined;\n if (e.operator === \"DoesNotExist\") return value === undefined;\n if (e.operator === \"In\") return value !== undefined && !!e.values?.includes(value);\n if (e.operator === \"NotIn\") return value === undefined || !e.values?.includes(value);\n return (\n value !== undefined &&\n !!e.values?.length &&\n Number.isFinite(Number(value)) &&\n (e.operator === \"Gt\" ? Number(value) > Number(e.values[0]) : Number(value) < Number(e.values[0]))\n );\n }),\n )\n )\n reject(\"Required node affinity does not match\");\n }\n for (const metric of [\"cpu\", \"memory\"] as const) {\n try {\n if (\n node.status?.allocatable?.[metric] !== undefined &&\n effectivePodResource(pod, metric) > parseQuantity(node.status.allocatable[metric], metric === \"memory\")\n )\n reject(`Pod ${metric} request exceeds node allocatable`);\n } catch {\n limitations.push(`Invalid or unavailable ${metric} resource data`);\n }\n }\n }\n for (const volume of spec?.volumes ?? []) {\n const claim = volume.persistentVolumeClaim?.claimName;\n if (!claim) continue;\n const pvc = pvcs?.find(\n (item) => item.metadata.name === claim && item.metadata.namespace === pod.metadata.namespace,\n );\n if (!pvc) limitations.push(`PVC ${claim} data unavailable`);\n else if (pvc.status?.phase !== \"Bound\")\n limitations.push(`PVC ${claim} is not bound; delayed binding and storage topology require scheduler evidence`);\n }\n return { state, evidence, limitations: [...new Set(limitations)] };\n}\nexport function observePodChanges(\n previous: DiagnosticsObject[],\n current: DiagnosticsObject[],\n observedAt: string,\n): TimelineEntry[] {\n const entries: TimelineEntry[] = [];\n const prior = new Map(previous.filter((pod) => pod.metadata.uid).map((pod) => [pod.metadata.uid, pod]));\n for (const pod of current) {\n const old = pod.metadata.uid ? prior.get(pod.metadata.uid) : undefined;\n const add = (reason: string, message: string) =>\n entries.push({\n id: `${pod.metadata.uid ?? pod.metadata.name}/${reason}/${observedAt}`,\n reason,\n message,\n time: validTime(observedAt),\n count: 1,\n certainty: validTime(observedAt) ? \"observed\" : \"unknown\",\n objectUid: pod.metadata.uid,\n gap: \"Change occurred between snapshots; exact transition time is unknown\",\n });\n if (!old) {\n add(\"FirstObserved\", `${pod.metadata.name ?? \"Pod\"} first observed; creation or rollout time is unknown`);\n continue;\n }\n if (old.status?.phase !== pod.status?.phase)\n add(\"PhaseChanged\", `${old.status?.phase ?? \"Unknown\"} → ${pod.status?.phase ?? \"Unknown\"}`);\n for (const status of pod.status?.containerStatuses ?? []) {\n const before = old.status?.containerStatuses?.find((item) => item.name === status.name);\n if (before && status.restartCount !== before.restartCount)\n add(`Restarts/${status.name}`, `${status.name}: restart count ${before.restartCount} → ${status.restartCount}`);\n if (before && status.ready !== before.ready)\n add(`Readiness/${status.name}`, `${status.name}: ready ${String(before.ready)} → ${String(status.ready)}`);\n }\n }\n return entries;\n}\n\nexport function observeResourceChanges(\n previous: DiagnosticsObject[],\n current: DiagnosticsObject[],\n observedAt: string,\n): TimelineEntry[] {\n const entries = observePodChanges(\n previous,\n current.filter((object) => object.kind === \"Pod\" || !!object.spec?.containers),\n observedAt,\n );\n const prior = new Map(\n previous.filter((object) => object.metadata.uid).map((object) => [object.metadata.uid, object]),\n );\n for (const object of current) {\n if (object.kind === \"Pod\" || object.spec?.containers) continue;\n const old = object.metadata.uid ? prior.get(object.metadata.uid) : undefined;\n if (!old) continue;\n const changes = ([\"readyReplicas\", \"updatedReplicas\", \"observedGeneration\"] as const)\n .filter((key) => old.status?.[key] !== object.status?.[key])\n .map((key) => `${key}: ${old.status?.[key] ?? \"unknown\"} → ${object.status?.[key] ?? \"unknown\"}`);\n if (old.metadata.generation !== object.metadata.generation)\n changes.push(`generation: ${old.metadata.generation ?? \"unknown\"} → ${object.metadata.generation ?? \"unknown\"}`);\n const revisionKey = \"deployment.kubernetes.io/revision\";\n if (old.metadata.annotations?.[revisionKey] !== object.metadata.annotations?.[revisionKey])\n changes.push(\n `revision: ${old.metadata.annotations?.[revisionKey] ?? \"unknown\"} → ${object.metadata.annotations?.[revisionKey] ?? \"unknown\"}`,\n );\n if (changes.length)\n entries.push({\n id: `${object.metadata.uid}/rollout/${observedAt}`,\n reason: \"RolloutObserved\",\n message: `${object.metadata.name ?? \"Workload\"}: ${changes.join(\", \")}`,\n time: validTime(observedAt),\n count: 1,\n certainty: validTime(observedAt) ? \"observed\" : \"unknown\",\n objectUid: object.metadata.uid,\n gap: \"Change occurred between snapshots; exact transition time is unknown\",\n });\n }\n return entries;\n}\n"],"mappings":";;AAyEA,SAAgB,qBACd,KACA,QACA,OAA8B,YACtB;CACR,OAAO,wBAAA,qBAAkB,KAAK,QAAQ,IAAI;AAC5C;AACA,SAAgB,oBACd,MACA,QACA,QAAoB,CAAC,GACJ;CACjB,MAAM,UAAU,IAAI,IAAI,OAAO,QAAQ,MAAM,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,MAAM,CAAC,EAAE,SAAS,KAAK,CAAC,CAAC,CAAC;CAC5F,MAAM,UAAU,IAAI,IAAI,MAAM,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;CACpD,MAAM,yBAAS,IAAI,IAA2B;CAC9C,KAAK,MAAM,CAAC,OAAO,QAAQ,KAAK,QAAQ,GAAG;EACzC,IAAI,IAAI,QAAQ,UAAU,eAAe,IAAI,QAAQ,UAAU,UAAU;EACzE,IAAI,QAAQ;EACZ,IAAI,WAAW;EACf,MAAM,0BAAU,IAAI,IAAY;EAChC,IAAI;EACJ,OAAO,MAAM;GACX,MAAM,aAAa,MAAM,SAAS,mBAAmB,CAAC;GACtD,MAAM,YAAY,WAAW,MAAM,MAAM,EAAE,UAAU,MAAM,WAAW,WAAW,IAAI,WAAW,KAAK,KAAA;GACrG,IAAI,CAAC,WAAW;GAChB,IAAI,QAAQ,IAAI,UAAU,GAAG,GAAG;IAC9B,WAAW;IACX;GACF;GACA,QAAQ,IAAI,UAAU,GAAG;GACzB,MAAM,OAAO,QAAQ,IAAI,UAAU,GAAG;GACtC,IAAI,CAAC,QAAQ,KAAK,SAAS,cAAc,IAAI,SAAS,WAAW;IAC/D,aAAa;IACb,WAAW;IACX;GACF;GACA,QAAQ;EACV;EACA,MAAM,YAAY,IAAI,SAAS,aAAa;EAC5C,MAAM,WAAW,YAAY,OAAO,MAAM,SAAS,OAAO,oBAAoB;EAC9E,MAAM,MAAM,GAAG,UAAU,GAAG;EAC5B,IAAI,QAAQ,OAAO,IAAI,GAAG;EAC1B,IAAI,CAAC,OAAO;GACV,MAAM,iBAAkC;IACtC,UAAU;IACV,mBAAmB;IACnB,qBAAqB;IACrB,aAAa;IACb,WAAW;IACX,oBAAoB;GACtB;GACA,QAAQ;IACN;IACA;IACA,MAAM,YAAY,QAAQ,MAAM,QAAQ;IACxC,MAAM,YAAY,QAAQ,MAAM,SAAS,QAAQ;IACjD,eAAe;IACf,MAAM,CAAC;IACP,KAAK,QAAQ;IACb,QAAQ,QAAQ;GAClB;GACA,OAAO,IAAI,KAAK,KAAK;EACvB;EACA,MAAM,KAAK,KAAK,GAAG;EACnB,KAAK,MAAM,UAAU,CAAC,OAAO,QAAQ,GAAY;GAC/C,MAAM,UAAU,MAAM;GACtB,QAAQ;GACR,IAAI;IACF,MAAM,UAAU,qBAAqB,KAAK,MAAM;IAChD,QAAQ,YAAY;IACpB,QAAQ,IAAI,MAAM,WAAW,sBAAsB,0BAA0B;GAC/E,QAAQ;IACN,QAAQ;GACV;GACA,MAAM,QAAQ,IAAI,SAAS,MAAM,QAAQ,IAAI,IAAI,SAAS,GAAG,CAAC,GAAG,UAAU,KAAA;GAC3E,IAAI,UAAU,KAAA,KAAa,OAAO,SAAS,KAAK,KAAK,SAAS,GAAG;IAC/D,QAAQ;IACR,QAAQ,SAAS,QAAQ,SAAS,KAAK;GACzC;EACF;CACF;CACA,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC;AAC5B;AA0BA,IAAM,aAAa,UAAoB,SAAS,OAAO,SAAS,KAAK,MAAM,KAAK,CAAC,IAAI,QAAQ,KAAA;AAC7F,SAAgB,gBAAgB,QAA6C;CAC3E,OAAO,OACJ,KAAK,OAAO,WAAW;EACtB,IAAI,MAAM,UAAU,OAAO,SAAS;EACpC,QAAQ,MAAM,UAAU;EACxB,SAAS,MAAM,WAAW,MAAM,QAAQ;EACxC,MACE,UAAU,MAAM,QAAQ,gBAAgB,KACxC,UAAU,MAAM,aAAa,KAC7B,UAAU,MAAM,SAAS,KACzB,UAAU,MAAM,UAAU,iBAAiB;EAC7C,WAAW,UAAU,MAAM,cAAc,KAAK,UAAU,MAAM,SAAS;EACvE,OAAO,MAAM,QAAQ,SAAS,MAAM,SAAS;EAC7C,WAAW;EACX,WAAW,MAAM,gBAAgB,OAAO,MAAM,WAAW;CAC3D,EAAE,CAAC,CACF,KAAK,WAAW;EAAE,GAAG;EAAO,WAAW,MAAM,OAAO,MAAM,YAAa;CAAoB,EAAE;AAClG;AAMA,SAAgB,mBACd,KACA,OACA,SAA6B,CAAC,GAC9B,MACmH;CACnH,MAAM,QACJ,IAAI,QAAQ,UAAU,YAAY,gBAAgB,IAAI,MAAM,WAAW,qBAAqB;CAC9F,MAAM,WAA8B,OACjC,QAAQ,UAAU,CAAC,CAAC,IAAI,SAAS,QAAQ,MAAM,gBAAgB,OAAO,MAAM,WAAW,SAAS,IAAI,SAAS,GAAG,CAAC,CACjH,KAAK,WAAW;EAAE,QAAQ;EAAS,SAAS,GAAG,MAAM,UAAU,QAAQ,IAAI,MAAM,WAAW,MAAM,QAAQ;CAAK,EAAE;CACpH,MAAM,cAAc,CAAC,+EAA+E;CACpG,IAAI,UAAU,eAAe,OAAO;EAAE;EAAO;EAAU;CAAY;CACnE,MAAM,OAAO,IAAI;CACjB,IAAI,CAAC,MAAM,QAAQ,YAAY,KAAK,uBAAuB;CAC3D,IAAI,MAAM,iBAAiB,KAAK,kBAAkB,qBAChD,YAAY,KAAK,qCAAqC;CACxD,IAAI,MAAM,UAAU,eAAe,MAAM,UAAU,mBAAmB,MAAM,2BAA2B,QACrG,YAAY,KAAK,yDAAyD;CAC5E,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,UAAU,YAAoB,SAAS,KAAK;GAAE,QAAQ;GAAc,MAAM,KAAK,SAAS;GAAM;EAAQ,CAAC;EAC7G,IAAI,KAAK,MAAM,eAAe,OAAO,kBAAkB;EACvD,IAAI,OAAO,QAAQ,MAAM,gBAAgB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,WAAW,KAAK,SAAS,SAAS,SAAS,KAAK,GACvG,OAAO,8BAA8B;EACvC,KAAK,MAAM,SAAS,KAAK,MAAM,UAAU,CAAC,GAAG;GAC3C,IAAI,CAAC,CAAC,cAAc,WAAW,CAAC,CAAC,SAAS,MAAM,MAAM,GAAG;GACzD,IACE,EAAE,MAAM,eAAe,CAAC,EAAA,CAAG,MACxB,OACE,CAAC,EAAE,UAAU,EAAE,WAAW,MAAM,YAChC,EAAE,aAAa,WACZ,CAAC,EAAE,OAAO,EAAE,QAAQ,MAAM,MAC1B,EAAE,QAAQ,MAAM,QAAQ,EAAE,SAAS,SAAS,MAAM,SAAS,IACnE,GAEA,OAAO,qBAAqB,MAAM,IAAI,IAAI,MAAM,OAAO,EAAE;EAC7D;EACA,MAAM,WAAW,MAAM,UAAU,cAAc;EAC/C,MAAM,QACJ,YACA,OAAO,aAAa,YACpB,uBAAuB,YACvB,MAAM,QAAQ,SAAS,iBAAiB,IACnC,SAAS,oBAIV,KAAA;EACN,IAAI,YAAY,CAAC,OAAO,YAAY,KAAK,4CAA4C;EACrF,IAAI;OACkB,MAAM,MACvB,SACC,KAAK,aAAa,UAClB,KAAK,kBAAkB,MACpB,MAAM,CAAC;IAAC;IAAM;IAAS;IAAU;IAAgB;IAAM;GAAI,CAAC,CAAC,SAAS,EAAE,QAAQ,CACnF,CAEA;QACE,CAAC,YAAY,SAAS,yDAAyD,GACjF,YAAY,KAAK,yDAAyD;GAAA,OACvE,IACL,CAAC,MAAM,MACJ,SACC,CAAC,CAAC,KAAK,kBAAkB,UACzB,KAAK,iBAAiB,OAAO,MAAM;IACjC,MAAM,QAAQ,KAAK,SAAS,SAAS,EAAE;IACvC,IAAI,EAAE,aAAa,UAAU,OAAO,UAAU,KAAA;IAC9C,IAAI,EAAE,aAAa,gBAAgB,OAAO,UAAU,KAAA;IACpD,IAAI,EAAE,aAAa,MAAM,OAAO,UAAU,KAAA,KAAa,CAAC,CAAC,EAAE,QAAQ,SAAS,KAAK;IACjF,IAAI,EAAE,aAAa,SAAS,OAAO,UAAU,KAAA,KAAa,CAAC,EAAE,QAAQ,SAAS,KAAK;IACnF,OACE,UAAU,KAAA,KACV,CAAC,CAAC,EAAE,QAAQ,UACZ,OAAO,SAAS,OAAO,KAAK,CAAC,MAC5B,EAAE,aAAa,OAAO,OAAO,KAAK,IAAI,OAAO,EAAE,OAAO,EAAE,IAAI,OAAO,KAAK,IAAI,OAAO,EAAE,OAAO,EAAE;GAEnG,CAAC,CACL,GAEA,OAAO,uCAAuC;EAAA;EAElD,KAAK,MAAM,UAAU,CAAC,OAAO,QAAQ,GACnC,IAAI;GACF,IACE,KAAK,QAAQ,cAAc,YAAY,KAAA,KACvC,qBAAqB,KAAK,MAAM,IAAI,wBAAA,cAAc,KAAK,OAAO,YAAY,SAAS,WAAW,QAAQ,GAEtG,OAAO,OAAO,OAAO,kCAAkC;EAC3D,QAAQ;GACN,YAAY,KAAK,0BAA0B,OAAO,eAAe;EACnE;CAEJ;CACA,KAAK,MAAM,UAAU,MAAM,WAAW,CAAC,GAAG;EACxC,MAAM,QAAQ,OAAO,uBAAuB;EAC5C,IAAI,CAAC,OAAO;EACZ,MAAM,MAAM,MAAM,MACf,SAAS,KAAK,SAAS,SAAS,SAAS,KAAK,SAAS,cAAc,IAAI,SAAS,SACrF;EACA,IAAI,CAAC,KAAK,YAAY,KAAK,OAAO,MAAM,kBAAkB;OACrD,IAAI,IAAI,QAAQ,UAAU,SAC7B,YAAY,KAAK,OAAO,MAAM,+EAA+E;CACjH;CACA,OAAO;EAAE;EAAO;EAAU,aAAa,CAAC,GAAG,IAAI,IAAI,WAAW,CAAC;CAAE;AACnE;AACA,SAAgB,kBACd,UACA,SACA,YACiB;CACjB,MAAM,UAA2B,CAAC;CAClC,MAAM,QAAQ,IAAI,IAAI,SAAS,QAAQ,QAAQ,IAAI,SAAS,GAAG,CAAC,CAAC,KAAK,QAAQ,CAAC,IAAI,SAAS,KAAK,GAAG,CAAC,CAAC;CACtG,KAAK,MAAM,OAAO,SAAS;EACzB,MAAM,MAAM,IAAI,SAAS,MAAM,MAAM,IAAI,IAAI,SAAS,GAAG,IAAI,KAAA;EAC7D,MAAM,OAAO,QAAgB,YAC3B,QAAQ,KAAK;GACX,IAAI,GAAG,IAAI,SAAS,OAAO,IAAI,SAAS,KAAK,GAAG,OAAO,GAAG;GAC1D;GACA;GACA,MAAM,UAAU,UAAU;GAC1B,OAAO;GACP,WAAW,UAAU,UAAU,IAAI,aAAa;GAChD,WAAW,IAAI,SAAS;GACxB,KAAK;EACP,CAAC;EACH,IAAI,CAAC,KAAK;GACR,IAAI,iBAAiB,GAAG,IAAI,SAAS,QAAQ,MAAM,qDAAqD;GACxG;EACF;EACA,IAAI,IAAI,QAAQ,UAAU,IAAI,QAAQ,OACpC,IAAI,gBAAgB,GAAG,IAAI,QAAQ,SAAS,UAAU,KAAK,IAAI,QAAQ,SAAS,WAAW;EAC7F,KAAK,MAAM,UAAU,IAAI,QAAQ,qBAAqB,CAAC,GAAG;GACxD,MAAM,SAAS,IAAI,QAAQ,mBAAmB,MAAM,SAAS,KAAK,SAAS,OAAO,IAAI;GACtF,IAAI,UAAU,OAAO,iBAAiB,OAAO,cAC3C,IAAI,YAAY,OAAO,QAAQ,GAAG,OAAO,KAAK,kBAAkB,OAAO,aAAa,KAAK,OAAO,cAAc;GAChH,IAAI,UAAU,OAAO,UAAU,OAAO,OACpC,IAAI,aAAa,OAAO,QAAQ,GAAG,OAAO,KAAK,UAAU,OAAO,OAAO,KAAK,EAAE,KAAK,OAAO,OAAO,KAAK,GAAG;EAC7G;CACF;CACA,OAAO;AACT;AAEA,SAAgB,uBACd,UACA,SACA,YACiB;CACjB,MAAM,UAAU,kBACd,UACA,QAAQ,QAAQ,WAAW,OAAO,SAAS,SAAS,CAAC,CAAC,OAAO,MAAM,UAAU,GAC7E,UACF;CACA,MAAM,QAAQ,IAAI,IAChB,SAAS,QAAQ,WAAW,OAAO,SAAS,GAAG,CAAC,CAAC,KAAK,WAAW,CAAC,OAAO,SAAS,KAAK,MAAM,CAAC,CAChG;CACA,KAAK,MAAM,UAAU,SAAS;EAC5B,IAAI,OAAO,SAAS,SAAS,OAAO,MAAM,YAAY;EACtD,MAAM,MAAM,OAAO,SAAS,MAAM,MAAM,IAAI,OAAO,SAAS,GAAG,IAAI,KAAA;EACnE,IAAI,CAAC,KAAK;EACV,MAAM,UAAW;GAAC;GAAiB;GAAmB;EAAoB,CAAC,CACxE,QAAQ,QAAQ,IAAI,SAAS,SAAS,OAAO,SAAS,IAAI,CAAC,CAC3D,KAAK,QAAQ,GAAG,IAAI,IAAI,IAAI,SAAS,QAAQ,UAAU,KAAK,OAAO,SAAS,QAAQ,WAAW;EAClG,IAAI,IAAI,SAAS,eAAe,OAAO,SAAS,YAC9C,QAAQ,KAAK,eAAe,IAAI,SAAS,cAAc,UAAU,KAAK,OAAO,SAAS,cAAc,WAAW;EACjH,MAAM,cAAc;EACpB,IAAI,IAAI,SAAS,cAAc,iBAAiB,OAAO,SAAS,cAAc,cAC5E,QAAQ,KACN,aAAa,IAAI,SAAS,cAAc,gBAAgB,UAAU,KAAK,OAAO,SAAS,cAAc,gBAAgB,WACvH;EACF,IAAI,QAAQ,QACV,QAAQ,KAAK;GACX,IAAI,GAAG,OAAO,SAAS,IAAI,WAAW;GACtC,QAAQ;GACR,SAAS,GAAG,OAAO,SAAS,QAAQ,WAAW,IAAI,QAAQ,KAAK,IAAI;GACpE,MAAM,UAAU,UAAU;GAC1B,OAAO;GACP,WAAW,UAAU,UAAU,IAAI,aAAa;GAChD,WAAW,OAAO,SAAS;GAC3B,KAAK;EACP,CAAC;CACL;CACA,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"settings-export.js","names":[],"sources":["../../../../src/common/settings-export.ts"],"sourcesContent":["import { sanitizeAiShortcuts } from \"./ai-shortcuts\";\nimport { sanitizeDashboardCards } from \"./dashboard\";\nimport { normalizeDashboardSelector } from \"./dashboard-selector\";\n\nexport const SETTINGS_EXPORT = \"freelens-power:settings:export\";\nexport type SettingsExportResult = \"saved\" | \"canceled\" | \"error\";\nexport const SETTINGS_IMPORT = \"freelens-power:settings:import\";\nexport type SettingsImportResult = \"restored\" | \"canceled\" | \"error\";\nexport const SETTINGS_BACKUP_MAX_BYTES = 1024 * 1024;\n\nexport function parseSettingsImport(value: unknown) {\n const fail = () => {\n throw new Error(\"Invalid settings backup\");\n };\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return fail();\n const backup = value as {\n format?: unknown;\n version?: unknown;\n dashboard?: { cards?: unknown };\n ai?: { shortcuts?: unknown };\n };\n if (backup.format !== \"freelens-power-settings\" || backup.version !== 1) return fail();\n const cards = backup.dashboard?.cards;\n const shortcuts = backup.ai?.shortcuts;\n if (!Array.isArray(cards) || !Array.isArray(shortcuts)) return fail();\n const ids = new Set<string>();\n for (const card of cards) {\n if (\n !card ||\n typeof card !== \"object\" ||\n typeof card.id !== \"string\" ||\n !card.id.trim() ||\n ids.has(card.id) ||\n typeof card.title !== \"string\" ||\n !card.title.trim() ||\n typeof card.url !== \"string\" ||\n ![\"s\", \"m\", \"l\"].includes(card.size) ||\n (card.autoRefresh !== undefined && typeof card.autoRefresh !== \"boolean\") ||\n (card.selector !== undefined &&\n (typeof card.selector !== \"string\" || (card.selector.trim() && !normalizeDashboardSelector(card.selector))))\n )\n return fail();\n ids.add(card.id);\n }\n if (\n sanitizeDashboardCards(cards).length !== cards.length ||\n sanitizeAiShortcuts(shortcuts).length !== shortcuts.length\n )\n return fail();\n return createSettingsExport(cards, shortcuts);\n}\n\nfunction credentialKey(value: string): boolean {\n const key = value.toLowerCase().replace(/[^a-z0-9]/g, \"\");\n return (\n /(?:token|password|passwd|secret|credential|authorization|signature|apikey|session)/.test(key) ||\n [\"auth\", \"key\", \"sig\", \"code\", \"jwt\", \"assertion\", \"ticket\", \"samlresponse\"].includes(key)\n );\n}\n\nfunction exportUrl(value: string): string {\n const url = new URL(value);\n url.username = \"\";\n url.password = \"\";\n for (const key of [...url.searchParams.keys()]) {\n if (credentialKey(key)) url.searchParams.delete(key);\n }\n // preserve SPA routes unless the fragment contains credential parameters\n const fragment = url.hash.slice(1);\n const parameters = new URLSearchParams(fragment.includes(\"?\") ? fragment.slice(fragment.indexOf(\"?\") + 1) : fragment);\n if ([...parameters.keys()].some(credentialKey)) url.hash = \"\";\n return url.href;\n}\n\nexport function createSettingsExport(cards: unknown, shortcuts: unknown) {\n const backup = {\n format: \"freelens-power-settings\",\n version: 1,\n dashboard: {\n cards: sanitizeDashboardCards(cards).map((card, index, all) => {\n const url = exportUrl(card.url);\n let id = card.id;\n if (/^card-https?%3a%2f%2f/i.test(id)) {\n id = `export-card-${index + 1}`;\n while (all.some((entry) => entry.id === id)) id += \"-\";\n }\n return { ...card, url, id };\n }),\n },\n ai: { shortcuts: sanitizeAiShortcuts(shortcuts) },\n };\n if (new TextEncoder().encode(`${JSON.stringify(backup, null, 2)}\\n`).byteLength > SETTINGS_BACKUP_MAX_BYTES)\n throw new Error(\"Settings backup is too large\");\n return backup;\n}\n"],"mappings":";AAIA,IAAa,kBAAkB;AAE/B,IAAa,kBAAkB"}
1
+ {"version":3,"file":"settings-export.js","names":[],"sources":["../../../../src/common/settings-export.ts"],"sourcesContent":["import { sanitizeAiShortcuts } from \"./ai-shortcuts\";\nimport { sanitizeDashboardCards } from \"./dashboard\";\nimport { normalizeDashboardSelector } from \"./dashboard-selector\";\n\nexport const SETTINGS_EXPORT = \"freelens-power:settings:export\";\nexport type SettingsExportResult = \"saved\" | \"canceled\" | \"error\";\nexport const SETTINGS_IMPORT = \"freelens-power:settings:import\";\nexport type SettingsImportResult = \"restored\" | \"canceled\" | \"error\";\nexport const SETTINGS_BACKUP_MAX_BYTES = 1024 * 1024;\n\nexport function parseSettingsImport(value: unknown) {\n const fail = () => {\n throw new Error(\"Invalid settings backup\");\n };\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return fail();\n const backup = value as {\n format?: unknown;\n version?: unknown;\n dashboard?: { cards?: unknown };\n ai?: { shortcuts?: unknown };\n };\n if (backup.format !== \"freelens-power-settings\" || backup.version !== 1) return fail();\n const cards = backup.dashboard?.cards;\n const shortcuts = backup.ai?.shortcuts;\n if (!Array.isArray(cards) || !Array.isArray(shortcuts)) return fail();\n const ids = new Set<string>();\n for (const card of cards) {\n if (\n !card ||\n typeof card !== \"object\" ||\n typeof card.id !== \"string\" ||\n !card.id.trim() ||\n ids.has(card.id) ||\n typeof card.title !== \"string\" ||\n !card.title.trim() ||\n typeof card.url !== \"string\" ||\n ![\"xs\", \"s\", \"m\", \"l\", \"xl\"].includes(card.size) ||\n (card.autoRefresh !== undefined && typeof card.autoRefresh !== \"boolean\") ||\n (card.refreshEvery10Seconds !== undefined && typeof card.refreshEvery10Seconds !== \"boolean\") ||\n (card.selector !== undefined &&\n (typeof card.selector !== \"string\" || (card.selector.trim() && !normalizeDashboardSelector(card.selector))))\n )\n return fail();\n ids.add(card.id);\n }\n if (\n sanitizeDashboardCards(cards).length !== cards.length ||\n sanitizeAiShortcuts(shortcuts).length !== shortcuts.length\n )\n return fail();\n return createSettingsExport(cards, shortcuts);\n}\n\nfunction credentialKey(value: string): boolean {\n const key = value.toLowerCase().replace(/[^a-z0-9]/g, \"\");\n return (\n /(?:token|password|passwd|secret|credential|authorization|signature|apikey|session)/.test(key) ||\n [\"auth\", \"key\", \"sig\", \"code\", \"jwt\", \"assertion\", \"ticket\", \"samlresponse\"].includes(key)\n );\n}\n\nfunction exportUrl(value: string): string {\n const url = new URL(value);\n url.username = \"\";\n url.password = \"\";\n for (const key of [...url.searchParams.keys()]) {\n if (credentialKey(key)) url.searchParams.delete(key);\n }\n // preserve SPA routes unless the fragment contains credential parameters\n const fragment = url.hash.slice(1);\n const parameters = new URLSearchParams(fragment.includes(\"?\") ? fragment.slice(fragment.indexOf(\"?\") + 1) : fragment);\n if ([...parameters.keys()].some(credentialKey)) url.hash = \"\";\n return url.href;\n}\n\nexport function createSettingsExport(cards: unknown, shortcuts: unknown) {\n const backup = {\n format: \"freelens-power-settings\",\n version: 1,\n dashboard: {\n cards: sanitizeDashboardCards(cards).map((card, index, all) => {\n const url = exportUrl(card.url);\n let id = card.id;\n if (/^card-https?%3a%2f%2f/i.test(id)) {\n id = `export-card-${index + 1}`;\n while (all.some((entry) => entry.id === id)) id += \"-\";\n }\n return { ...card, url, id };\n }),\n },\n ai: { shortcuts: sanitizeAiShortcuts(shortcuts) },\n };\n if (new TextEncoder().encode(`${JSON.stringify(backup, null, 2)}\\n`).byteLength > SETTINGS_BACKUP_MAX_BYTES)\n throw new Error(\"Settings backup is too large\");\n return backup;\n}\n"],"mappings":";AAIA,IAAa,kBAAkB;AAE/B,IAAa,kBAAkB"}
@@ -39,12 +39,13 @@ var DashboardPreferencesStore = class extends require_extensions.Common.Store.Ex
39
39
  this.cards.splice(destination, 0, card);
40
40
  }
41
41
  toJSON() {
42
- return { cards: this.cards.map(({ id, title, url, size, autoRefresh, selector }) => ({
42
+ return { cards: this.cards.map(({ id, title, url, size, autoRefresh, refreshEvery10Seconds, selector }) => ({
43
43
  id,
44
44
  title,
45
45
  url,
46
46
  size,
47
47
  autoRefresh: autoRefresh === true,
48
+ ...refreshEvery10Seconds === true ? { refreshEvery10Seconds: true } : {},
48
49
  ...selector ? { selector } : {}
49
50
  })) };
50
51
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-preferences-store.js","names":[],"sources":["../../../../../src/common/store/dashboard-preferences-store.ts"],"sourcesContent":["import { Common } from \"@freelensapp/extensions\";\nimport { action, makeObservable, observable } from \"mobx\";\nimport { type DashboardCard, sanitizeDashboardCards } from \"../dashboard\";\n\nexport interface DashboardPreferencesModel {\n cards: DashboardCard[];\n}\n\nexport class DashboardPreferencesStore extends Common.Store.ExtensionStore<DashboardPreferencesModel> {\n cards: DashboardCard[] = [];\n\n constructor() {\n super({ configName: \"dashboard-preferences\", defaults: { cards: [] } });\n makeObservable(this, {\n cards: observable,\n fromStore: action,\n upsertCard: action,\n removeCard: action,\n moveCard: action,\n });\n }\n\n fromStore(data: Partial<DashboardPreferencesModel>): void {\n this.cards = sanitizeDashboardCards(data?.cards);\n }\n\n upsertCard(card: DashboardCard): void {\n const normalized = sanitizeDashboardCards([card])[0];\n if (!normalized) return;\n const index = this.cards.findIndex((entry) => entry.id === normalized.id);\n if (index < 0) this.cards.push(normalized);\n else this.cards[index] = normalized;\n }\n\n removeCard(id: string): void {\n this.cards = this.cards.filter((card) => card.id !== id);\n }\n\n moveCard(id: string, targetIndex: number): void {\n const index = this.cards.findIndex((card) => card.id === id);\n if (index < 0 || !Number.isFinite(targetIndex)) return;\n const destination = Math.max(0, Math.min(this.cards.length - 1, Math.trunc(targetIndex)));\n if (index === destination) return;\n const [card] = this.cards.splice(index, 1);\n this.cards.splice(destination, 0, card);\n }\n\n toJSON(): DashboardPreferencesModel {\n return {\n cards: this.cards.map(({ id, title, url, size, autoRefresh, selector }) => ({\n id,\n title,\n url,\n size,\n autoRefresh: autoRefresh === true,\n ...(selector ? { selector } : {}),\n })),\n };\n }\n}\n"],"mappings":";;;;AAQA,IAAa,4BAAb,cAA+C,mBAAA,OAAO,MAAM,eAA0C;CACpG,QAAyB,CAAC;CAE1B,cAAc;EACZ,MAAM;GAAE,YAAY;GAAyB,UAAU,EAAE,OAAO,CAAC,EAAE;EAAE,CAAC;EACtE,8BAAA,eAAe,MAAM;GACnB,OAAO,8BAAA;GACP,WAAW,8BAAA;GACX,YAAY,8BAAA;GACZ,YAAY,8BAAA;GACZ,UAAU,8BAAA;EACZ,CAAC;CACH;CAEA,UAAU,MAAgD;EACxD,KAAK,QAAQ,kBAAA,uBAAuB,MAAM,KAAK;CACjD;CAEA,WAAW,MAA2B;EACpC,MAAM,aAAa,kBAAA,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;EAClD,IAAI,CAAC,YAAY;EACjB,MAAM,QAAQ,KAAK,MAAM,WAAW,UAAU,MAAM,OAAO,WAAW,EAAE;EACxE,IAAI,QAAQ,GAAG,KAAK,MAAM,KAAK,UAAU;OACpC,KAAK,MAAM,SAAS;CAC3B;CAEA,WAAW,IAAkB;EAC3B,KAAK,QAAQ,KAAK,MAAM,QAAQ,SAAS,KAAK,OAAO,EAAE;CACzD;CAEA,SAAS,IAAY,aAA2B;EAC9C,MAAM,QAAQ,KAAK,MAAM,WAAW,SAAS,KAAK,OAAO,EAAE;EAC3D,IAAI,QAAQ,KAAK,CAAC,OAAO,SAAS,WAAW,GAAG;EAChD,MAAM,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,MAAM,SAAS,GAAG,KAAK,MAAM,WAAW,CAAC,CAAC;EACxF,IAAI,UAAU,aAAa;EAC3B,MAAM,CAAC,QAAQ,KAAK,MAAM,OAAO,OAAO,CAAC;EACzC,KAAK,MAAM,OAAO,aAAa,GAAG,IAAI;CACxC;CAEA,SAAoC;EAClC,OAAO,EACL,OAAO,KAAK,MAAM,KAAK,EAAE,IAAI,OAAO,KAAK,MAAM,aAAa,gBAAgB;GAC1E;GACA;GACA;GACA;GACA,aAAa,gBAAgB;GAC7B,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;EACjC,EAAE,EACJ;CACF;AACF"}
1
+ {"version":3,"file":"dashboard-preferences-store.js","names":[],"sources":["../../../../../src/common/store/dashboard-preferences-store.ts"],"sourcesContent":["import { Common } from \"@freelensapp/extensions\";\nimport { action, makeObservable, observable } from \"mobx\";\nimport { type DashboardCard, sanitizeDashboardCards } from \"../dashboard\";\n\nexport interface DashboardPreferencesModel {\n cards: DashboardCard[];\n}\n\nexport class DashboardPreferencesStore extends Common.Store.ExtensionStore<DashboardPreferencesModel> {\n cards: DashboardCard[] = [];\n\n constructor() {\n super({ configName: \"dashboard-preferences\", defaults: { cards: [] } });\n makeObservable(this, {\n cards: observable,\n fromStore: action,\n upsertCard: action,\n removeCard: action,\n moveCard: action,\n });\n }\n\n fromStore(data: Partial<DashboardPreferencesModel>): void {\n this.cards = sanitizeDashboardCards(data?.cards);\n }\n\n upsertCard(card: DashboardCard): void {\n const normalized = sanitizeDashboardCards([card])[0];\n if (!normalized) return;\n const index = this.cards.findIndex((entry) => entry.id === normalized.id);\n if (index < 0) this.cards.push(normalized);\n else this.cards[index] = normalized;\n }\n\n removeCard(id: string): void {\n this.cards = this.cards.filter((card) => card.id !== id);\n }\n\n moveCard(id: string, targetIndex: number): void {\n const index = this.cards.findIndex((card) => card.id === id);\n if (index < 0 || !Number.isFinite(targetIndex)) return;\n const destination = Math.max(0, Math.min(this.cards.length - 1, Math.trunc(targetIndex)));\n if (index === destination) return;\n const [card] = this.cards.splice(index, 1);\n this.cards.splice(destination, 0, card);\n }\n\n toJSON(): DashboardPreferencesModel {\n return {\n cards: this.cards.map(({ id, title, url, size, autoRefresh, refreshEvery10Seconds, selector }) => ({\n id,\n title,\n url,\n size,\n autoRefresh: autoRefresh === true,\n ...(refreshEvery10Seconds === true ? { refreshEvery10Seconds: true } : {}),\n ...(selector ? { selector } : {}),\n })),\n };\n }\n}\n"],"mappings":";;;;AAQA,IAAa,4BAAb,cAA+C,mBAAA,OAAO,MAAM,eAA0C;CACpG,QAAyB,CAAC;CAE1B,cAAc;EACZ,MAAM;GAAE,YAAY;GAAyB,UAAU,EAAE,OAAO,CAAC,EAAE;EAAE,CAAC;EACtE,8BAAA,eAAe,MAAM;GACnB,OAAO,8BAAA;GACP,WAAW,8BAAA;GACX,YAAY,8BAAA;GACZ,YAAY,8BAAA;GACZ,UAAU,8BAAA;EACZ,CAAC;CACH;CAEA,UAAU,MAAgD;EACxD,KAAK,QAAQ,kBAAA,uBAAuB,MAAM,KAAK;CACjD;CAEA,WAAW,MAA2B;EACpC,MAAM,aAAa,kBAAA,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;EAClD,IAAI,CAAC,YAAY;EACjB,MAAM,QAAQ,KAAK,MAAM,WAAW,UAAU,MAAM,OAAO,WAAW,EAAE;EACxE,IAAI,QAAQ,GAAG,KAAK,MAAM,KAAK,UAAU;OACpC,KAAK,MAAM,SAAS;CAC3B;CAEA,WAAW,IAAkB;EAC3B,KAAK,QAAQ,KAAK,MAAM,QAAQ,SAAS,KAAK,OAAO,EAAE;CACzD;CAEA,SAAS,IAAY,aAA2B;EAC9C,MAAM,QAAQ,KAAK,MAAM,WAAW,SAAS,KAAK,OAAO,EAAE;EAC3D,IAAI,QAAQ,KAAK,CAAC,OAAO,SAAS,WAAW,GAAG;EAChD,MAAM,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,MAAM,SAAS,GAAG,KAAK,MAAM,WAAW,CAAC,CAAC;EACxF,IAAI,UAAU,aAAa;EAC3B,MAAM,CAAC,QAAQ,KAAK,MAAM,OAAO,OAAO,CAAC;EACzC,KAAK,MAAM,OAAO,aAAa,GAAG,IAAI;CACxC;CAEA,SAAoC;EAClC,OAAO,EACL,OAAO,KAAK,MAAM,KAAK,EAAE,IAAI,OAAO,KAAK,MAAM,aAAa,uBAAuB,gBAAgB;GACjG;GACA;GACA;GACA;GACA,aAAa,gBAAgB;GAC7B,GAAI,0BAA0B,OAAO,EAAE,uBAAuB,KAAK,IAAI,CAAC;GACxE,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;EACjC,EAAE,EACJ;CACF;AACF"}
@@ -4,6 +4,7 @@ const require_monitoring_history = require("../monitoring-history.js");
4
4
  //#region src/common/store/monitoring-preferences-store.ts
5
5
  var MonitoringPreferencesStore = class extends require_extensions.Common.Store.ExtensionStore {
6
6
  enabled = false;
7
+ diagnosticsVisible = true;
7
8
  historyEnabled = false;
8
9
  trackedHistory = [];
9
10
  constructor() {
@@ -11,12 +12,14 @@ var MonitoringPreferencesStore = class extends require_extensions.Common.Store.E
11
12
  configName: "monitoring-preferences",
12
13
  defaults: {
13
14
  enabled: false,
15
+ diagnosticsVisible: true,
14
16
  historyEnabled: false,
15
17
  trackedHistory: []
16
18
  }
17
19
  });
18
20
  require__global_external_mobx.makeObservable(this, {
19
21
  enabled: require__global_external_mobx.observable,
22
+ diagnosticsVisible: require__global_external_mobx.observable,
20
23
  historyEnabled: require__global_external_mobx.observable,
21
24
  trackedHistory: require__global_external_mobx.observable,
22
25
  fromStore: require__global_external_mobx.action
@@ -24,6 +27,7 @@ var MonitoringPreferencesStore = class extends require_extensions.Common.Store.E
24
27
  }
25
28
  fromStore(data) {
26
29
  this.enabled = data?.enabled === true;
30
+ this.diagnosticsVisible = data?.diagnosticsVisible !== false;
27
31
  this.historyEnabled = data?.historyEnabled === true;
28
32
  this.trackedHistory = Array.isArray(data?.trackedHistory) ? data.trackedHistory.filter(require_monitoring_history.validHistoryIdentity).slice(0, 100).map(({ clusterId, scope, uid }) => ({
29
33
  clusterId,
@@ -34,6 +38,7 @@ var MonitoringPreferencesStore = class extends require_extensions.Common.Store.E
34
38
  toJSON() {
35
39
  return {
36
40
  enabled: this.enabled,
41
+ diagnosticsVisible: this.diagnosticsVisible,
37
42
  historyEnabled: this.historyEnabled,
38
43
  trackedHistory: this.trackedHistory.map(({ clusterId, scope, uid }) => ({
39
44
  clusterId,