@64mb/freelens-power 1.0.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -4
- package/THIRD_PARTY_LICENSES +1707 -0
- package/out/main/ai.js +63 -23
- package/out/main/ai.js.map +1 -1
- package/out/main/cluster-icons-catalog.js +28 -0
- package/out/main/cluster-icons-catalog.js.map +1 -0
- package/out/main/cluster-icons.js +125 -0
- package/out/main/cluster-icons.js.map +1 -0
- package/out/main/common/ai-terminal-context.js +51 -0
- package/out/main/common/ai-terminal-context.js.map +1 -0
- package/out/main/common/ai.js.map +1 -1
- package/out/main/common/cluster-icon-ipc.js +6 -0
- package/out/main/common/cluster-icon-ipc.js.map +1 -0
- package/out/main/common/cluster-icons.js +121 -0
- package/out/main/common/cluster-icons.js.map +1 -0
- package/out/main/common/dashboard.js +1 -1
- package/out/main/common/dashboard.js.map +1 -1
- package/out/main/common/monitoring-history.js +52 -0
- package/out/main/common/monitoring-history.js.map +1 -0
- package/out/main/common/settings-export.js +3 -1
- package/out/main/common/settings-export.js.map +1 -1
- package/out/main/common/store/cluster-icons-store.js +32 -0
- package/out/main/common/store/cluster-icons-store.js.map +1 -0
- package/out/main/common/store/monitoring-preferences-store.js +30 -2
- package/out/main/common/store/monitoring-preferences-store.js.map +1 -1
- package/out/main/dashboard-views.js +132 -28
- package/out/main/dashboard-views.js.map +1 -1
- package/out/main/diagnostics-menu-order.js +57 -0
- package/out/main/diagnostics-menu-order.js.map +1 -0
- package/out/main/index.js +11 -1
- package/out/main/index.js.map +1 -1
- package/out/main/monitoring-history-database.js +103 -0
- package/out/main/monitoring-history-database.js.map +1 -0
- package/out/main/monitoring-history-worker.js +61 -0
- package/out/main/monitoring-history-worker.js.map +1 -0
- package/out/main/monitoring-history.js +110 -0
- package/out/main/monitoring-history.js.map +1 -0
- package/out/renderer/_virtual/_global-external_mobx.js +2 -1
- package/out/renderer/_virtual/_global-external_react-dom.js +2 -1
- package/out/renderer/_virtual/_global-external_react.js +10 -5
- package/out/renderer/_virtual/_rolldown/runtime.js +22 -0
- package/out/renderer/ai-terminal-context.js +200 -0
- package/out/renderer/ai-terminal-context.js.map +1 -0
- package/out/renderer/ai.js +90 -9
- package/out/renderer/ai.js.map +1 -1
- package/out/renderer/appearance.js +1 -0
- package/out/renderer/appearance.js.map +1 -1
- package/out/renderer/cluster-icon-colors.js +188 -0
- package/out/renderer/cluster-icon-colors.js.map +1 -0
- package/out/renderer/cluster-icons.js +304 -0
- package/out/renderer/cluster-icons.js.map +1 -0
- package/out/renderer/dashboard.js +8 -5
- package/out/renderer/dashboard.js.map +1 -1
- package/out/renderer/details/secret-certificate-details.js +9 -2
- package/out/renderer/details/secret-certificate-details.js.map +1 -1
- package/out/renderer/diagnostics.css.js +39 -0
- package/out/renderer/diagnostics.css.js.map +1 -0
- package/out/renderer/diagnostics.js +1100 -0
- package/out/renderer/diagnostics.js.map +1 -0
- package/out/renderer/index.js +32 -0
- package/out/renderer/index.js.map +1 -1
- package/out/renderer/monitoring-collector.js +202 -0
- package/out/renderer/monitoring-collector.js.map +1 -0
- package/out/renderer/monitoring-details-chart.js +42 -0
- package/out/renderer/monitoring-details-chart.js.map +1 -0
- package/out/renderer/monitoring-history-collection.js +168 -0
- package/out/renderer/monitoring-history-collection.js.map +1 -0
- package/out/renderer/monitoring-history-view.js +227 -0
- package/out/renderer/monitoring-history-view.js.map +1 -0
- package/out/renderer/monitoring-history.js +19 -0
- package/out/renderer/monitoring-history.js.map +1 -0
- package/out/renderer/monitoring.js +153 -139
- package/out/renderer/monitoring.js.map +1 -1
- package/out/renderer/node-monitoring.js +127 -0
- package/out/renderer/node-monitoring.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js +10 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js +8 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js +9 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js +9 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/classCallCheck.js +8 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/classCallCheck.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/createClass.js +15 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/createClass.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/createSuper.js +19 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/createSuper.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/defineProperty.js +14 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/defineProperty.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/extends.js +19 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/extends.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js +15 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/inherits.js +14 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/inherits.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/isNativeReflectConstruct.js +18 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/isNativeReflectConstruct.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/iterableToArray.js +8 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/iterableToArray.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js +26 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/nonIterableRest.js +8 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/nonIterableRest.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js +8 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectSpread2.js +27 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectSpread2.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js +15 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js +14 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/possibleConstructorReturn.js +12 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/possibleConstructorReturn.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js +15 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/slicedToArray.js +12 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/slicedToArray.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/taggedTemplateLiteral.js +8 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/taggedTemplateLiteral.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toConsumableArray.js +12 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toConsumableArray.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toPrimitive.js +16 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toPrimitive.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toPropertyKey.js +11 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toPropertyKey.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/typeof.js +18 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/typeof.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js +13 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@emotion_cache@11.14.0/node_modules/@emotion/cache/dist/emotion-cache.browser.esm.js +237 -0
- package/out/renderer/node_modules/.pnpm/@emotion_cache@11.14.0/node_modules/@emotion/cache/dist/emotion-cache.browser.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@emotion_hash@0.9.2/node_modules/@emotion/hash/dist/emotion-hash.esm.js +25 -0
- package/out/renderer/node_modules/.pnpm/@emotion_hash@0.9.2/node_modules/@emotion/hash/dist/emotion-hash.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@emotion_memoize@0.9.0/node_modules/@emotion/memoize/dist/emotion-memoize.esm.js +12 -0
- package/out/renderer/node_modules/.pnpm/@emotion_memoize@0.9.0/node_modules/@emotion/memoize/dist/emotion-memoize.esm.js.map +1 -0
- 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
- 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
- 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
- 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
- package/out/renderer/node_modules/.pnpm/@emotion_serialize@1.3.3/node_modules/@emotion/serialize/dist/emotion-serialize.esm.js +133 -0
- package/out/renderer/node_modules/.pnpm/@emotion_serialize@1.3.3/node_modules/@emotion/serialize/dist/emotion-serialize.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@emotion_sheet@1.4.0/node_modules/@emotion/sheet/dist/emotion-sheet.esm.js +65 -0
- package/out/renderer/node_modules/.pnpm/@emotion_sheet@1.4.0/node_modules/@emotion/sheet/dist/emotion-sheet.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@emotion_unitless@0.10.0/node_modules/@emotion/unitless/dist/emotion-unitless.esm.js +54 -0
- package/out/renderer/node_modules/.pnpm/@emotion_unitless@0.10.0/node_modules/@emotion/unitless/dist/emotion-unitless.esm.js.map +1 -0
- 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
- 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
- package/out/renderer/node_modules/.pnpm/@emotion_utils@1.4.2/node_modules/@emotion/utils/dist/emotion-utils.browser.esm.js +30 -0
- package/out/renderer/node_modules/.pnpm/@emotion_utils@1.4.2/node_modules/@emotion/utils/dist/emotion-utils.browser.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@floating-ui_dom@1.7.2/node_modules/@floating-ui/dom/dist/floating-ui.dom.js +211 -0
- 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
- 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
- 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
- package/out/renderer/node_modules/.pnpm/@floating-ui_utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.js +31 -0
- 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
- 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
- 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
- package/out/renderer/node_modules/.pnpm/memoize-one@6.0.0/node_modules/memoize-one/dist/memoize-one.esm.js +38 -0
- package/out/renderer/node_modules/.pnpm/memoize-one@6.0.0/node_modules/memoize-one/dist/memoize-one.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.development.js +159 -0
- package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.development.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.production.min.js +103 -0
- package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.production.min.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/index.js +18 -0
- package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/index.js.map +1 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Enum.js +22 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Enum.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Middleware.js +30 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Middleware.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Parser.js +164 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Parser.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Serializer.js +37 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Serializer.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Tokenizer.js +245 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Tokenizer.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Utility.js +120 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Utility.js.map +1 -0
- 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
- 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
- package/out/renderer/pod-monitoring.js +38 -11
- package/out/renderer/pod-monitoring.js.map +1 -1
- package/out/renderer/preferences/ai-shortcuts-preferences.js +12 -4
- package/out/renderer/preferences/ai-shortcuts-preferences.js.map +1 -1
- package/out/renderer/preferences/dashboard-preferences.js +20 -4
- package/out/renderer/preferences/dashboard-preferences.js.map +1 -1
- package/out/renderer/preferences/monitoring-preferences.js +141 -9
- package/out/renderer/preferences/monitoring-preferences.js.map +1 -1
- package/out/renderer/preferences/preferences.js +31 -7
- package/out/renderer/preferences/preferences.js.map +1 -1
- package/out/renderer/read-only.js +2 -2
- package/out/renderer/read-only.js.map +1 -1
- package/out/renderer/src/common/ai-terminal-context.js +51 -0
- package/out/renderer/src/common/ai-terminal-context.js.map +1 -0
- package/out/renderer/src/common/ai.js.map +1 -1
- package/out/renderer/src/common/cluster-icon-ipc.js +6 -0
- package/out/renderer/src/common/cluster-icon-ipc.js.map +1 -0
- package/out/renderer/src/common/cluster-icons.js +133 -0
- package/out/renderer/src/common/cluster-icons.js.map +1 -0
- package/out/renderer/src/common/dashboard.js +1 -1
- package/out/renderer/src/common/dashboard.js.map +1 -1
- package/out/renderer/src/common/date-time.js +11 -0
- package/out/renderer/src/common/date-time.js.map +1 -0
- package/out/renderer/src/common/monitoring-history.js +17 -0
- package/out/renderer/src/common/monitoring-history.js.map +1 -0
- package/out/renderer/src/common/monitoring-math.js +98 -0
- package/out/renderer/src/common/monitoring-math.js.map +1 -0
- package/out/renderer/src/common/resource-diagnostics.js +227 -0
- package/out/renderer/src/common/resource-diagnostics.js.map +1 -0
- package/out/renderer/src/common/settings-export.js.map +1 -1
- package/out/renderer/src/common/store/monitoring-preferences-store.js +30 -2
- package/out/renderer/src/common/store/monitoring-preferences-store.js.map +1 -1
- package/out/renderer/welcome.js +31 -7
- package/out/renderer/welcome.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
const require_monitoring_math = require("./monitoring-math.js");
|
|
2
|
+
//#region src/common/resource-diagnostics.ts
|
|
3
|
+
function effectivePodResource(pod, metric, kind = "requests") {
|
|
4
|
+
return require_monitoring_math.effectivePodResource(pod, metric, kind);
|
|
5
|
+
}
|
|
6
|
+
function buildConsumerGroups(pods, owners, usage = []) {
|
|
7
|
+
const objects = new Map(owners.filter((o) => o.metadata.uid).map((o) => [o.metadata.uid, o]));
|
|
8
|
+
const metrics = new Map(usage.map((u) => [u.uid, u]));
|
|
9
|
+
const groups = /* @__PURE__ */ new Map();
|
|
10
|
+
for (const [index, pod] of pods.entries()) {
|
|
11
|
+
if (pod.status?.phase === "Succeeded" || pod.status?.phase === "Failed") continue;
|
|
12
|
+
let owner = pod;
|
|
13
|
+
let resolved = true;
|
|
14
|
+
const visited = /* @__PURE__ */ new Set();
|
|
15
|
+
let unresolved;
|
|
16
|
+
while (true) {
|
|
17
|
+
const references = owner.metadata.ownerReferences ?? [];
|
|
18
|
+
const reference = references.find((r) => r.controller) ?? (references.length === 1 ? references[0] : void 0);
|
|
19
|
+
if (!reference) break;
|
|
20
|
+
if (visited.has(reference.uid)) {
|
|
21
|
+
resolved = false;
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
visited.add(reference.uid);
|
|
25
|
+
const next = objects.get(reference.uid);
|
|
26
|
+
if (!next || next.metadata.namespace !== pod.metadata.namespace) {
|
|
27
|
+
unresolved = reference;
|
|
28
|
+
resolved = false;
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
owner = next;
|
|
32
|
+
}
|
|
33
|
+
const namespace = pod.metadata.namespace ?? "default";
|
|
34
|
+
const identity = unresolved?.uid ?? owner.metadata.uid ?? `unidentified-pod-${index}`;
|
|
35
|
+
const key = `${namespace}/${identity}`;
|
|
36
|
+
let group = groups.get(key);
|
|
37
|
+
if (!group) {
|
|
38
|
+
const summary = () => ({
|
|
39
|
+
requests: 0,
|
|
40
|
+
scheduledRequests: 0,
|
|
41
|
+
unscheduledRequests: 0,
|
|
42
|
+
coveredPods: 0,
|
|
43
|
+
totalPods: 0,
|
|
44
|
+
unknownRequestPods: 0
|
|
45
|
+
});
|
|
46
|
+
group = {
|
|
47
|
+
namespace,
|
|
48
|
+
identity,
|
|
49
|
+
kind: unresolved?.kind ?? owner.kind ?? "Pod",
|
|
50
|
+
name: unresolved?.name ?? owner.metadata.name ?? "Unknown",
|
|
51
|
+
ownerResolved: resolved,
|
|
52
|
+
pods: [],
|
|
53
|
+
cpu: summary(),
|
|
54
|
+
memory: summary()
|
|
55
|
+
};
|
|
56
|
+
groups.set(key, group);
|
|
57
|
+
}
|
|
58
|
+
group.pods.push(pod);
|
|
59
|
+
for (const metric of ["cpu", "memory"]) {
|
|
60
|
+
const summary = group[metric];
|
|
61
|
+
summary.totalPods++;
|
|
62
|
+
try {
|
|
63
|
+
const request = effectivePodResource(pod, metric);
|
|
64
|
+
summary.requests += request;
|
|
65
|
+
summary[pod.spec?.nodeName ? "scheduledRequests" : "unscheduledRequests"] += request;
|
|
66
|
+
} catch {
|
|
67
|
+
summary.unknownRequestPods++;
|
|
68
|
+
}
|
|
69
|
+
const value = pod.metadata.uid ? metrics.get(pod.metadata.uid)?.[metric] : void 0;
|
|
70
|
+
if (value !== void 0 && Number.isFinite(value) && value >= 0) {
|
|
71
|
+
summary.coveredPods++;
|
|
72
|
+
summary.usage = (summary.usage ?? 0) + value;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return [...groups.values()];
|
|
77
|
+
}
|
|
78
|
+
var validTime = (value) => value && Number.isFinite(Date.parse(value)) ? value : void 0;
|
|
79
|
+
function normalizeEvents(events) {
|
|
80
|
+
return events.map((event, index) => ({
|
|
81
|
+
id: event.metadata?.uid ?? `event-${index}`,
|
|
82
|
+
reason: event.reason ?? "Event",
|
|
83
|
+
message: event.message ?? event.note ?? "",
|
|
84
|
+
time: validTime(event.series?.lastObservedTime) ?? validTime(event.lastTimestamp) ?? validTime(event.eventTime) ?? validTime(event.metadata?.creationTimestamp),
|
|
85
|
+
firstTime: validTime(event.firstTimestamp) ?? validTime(event.eventTime),
|
|
86
|
+
count: event.series?.count ?? event.count ?? 1,
|
|
87
|
+
certainty: "reported",
|
|
88
|
+
objectUid: event.involvedObject?.uid ?? event.regarding?.uid
|
|
89
|
+
})).map((entry) => ({
|
|
90
|
+
...entry,
|
|
91
|
+
certainty: entry.time ? entry.certainty : "unknown"
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
function diagnosePendingPod(pod, nodes, events = [], pvcs) {
|
|
95
|
+
const state = pod.status?.phase !== "Pending" ? "not-pending" : pod.spec?.nodeName ? "assigned-waiting" : "unscheduled";
|
|
96
|
+
const evidence = events.filter((event) => !!pod.metadata.uid && (event.involvedObject?.uid ?? event.regarding?.uid) === pod.metadata.uid).map((event) => ({
|
|
97
|
+
source: "event",
|
|
98
|
+
message: `${event.reason ?? "Event"}: ${event.message ?? event.note ?? ""}`
|
|
99
|
+
}));
|
|
100
|
+
const limitations = ["Local checks do not establish exact schedulability or available node capacity"];
|
|
101
|
+
if (state !== "unscheduled") return {
|
|
102
|
+
state,
|
|
103
|
+
evidence,
|
|
104
|
+
limitations
|
|
105
|
+
};
|
|
106
|
+
const spec = pod.spec;
|
|
107
|
+
if (!nodes.length) limitations.push("Node data unavailable");
|
|
108
|
+
if (spec?.schedulerName && spec.schedulerName !== "default-scheduler") limitations.push("Custom scheduler profile is unknown");
|
|
109
|
+
if (spec?.affinity?.podAffinity || spec?.affinity?.podAntiAffinity || spec?.topologySpreadConstraints?.length) limitations.push("Pod affinity and topology constraints are not evaluated");
|
|
110
|
+
for (const node of nodes) {
|
|
111
|
+
const reject = (message) => evidence.push({
|
|
112
|
+
source: "constraint",
|
|
113
|
+
node: node.metadata.name,
|
|
114
|
+
message
|
|
115
|
+
});
|
|
116
|
+
if (node.spec?.unschedulable) reject("Node is cordoned");
|
|
117
|
+
if (Object.entries(spec?.nodeSelector ?? {}).some(([key, value]) => node.metadata.labels?.[key] !== value)) reject("Node selector does not match");
|
|
118
|
+
for (const taint of node.spec?.taints ?? []) {
|
|
119
|
+
if (!["NoSchedule", "NoExecute"].includes(taint.effect)) continue;
|
|
120
|
+
if (!(spec?.tolerations ?? []).some((t) => (!t.effect || t.effect === taint.effect) && (t.operator === "Exists" ? !t.key || t.key === taint.key : t.key === taint.key && (t.value ?? "") === (taint.value ?? "")))) reject(`Untolerated taint ${taint.key} (${taint.effect})`);
|
|
121
|
+
}
|
|
122
|
+
const required = spec?.affinity?.nodeAffinity?.requiredDuringSchedulingIgnoredDuringExecution;
|
|
123
|
+
const terms = required && typeof required === "object" && "nodeSelectorTerms" in required && Array.isArray(required.nodeSelectorTerms) ? required.nodeSelectorTerms : void 0;
|
|
124
|
+
if (required && !terms) limitations.push("Required node affinity data is unsupported");
|
|
125
|
+
if (terms) {
|
|
126
|
+
if (terms.some((term) => term.matchFields?.length || term.matchExpressions?.some((e) => ![
|
|
127
|
+
"In",
|
|
128
|
+
"NotIn",
|
|
129
|
+
"Exists",
|
|
130
|
+
"DoesNotExist",
|
|
131
|
+
"Gt",
|
|
132
|
+
"Lt"
|
|
133
|
+
].includes(e.operator)))) {
|
|
134
|
+
if (!limitations.includes("Required node affinity contains unsupported expressions")) limitations.push("Required node affinity contains unsupported expressions");
|
|
135
|
+
} else if (!terms.some((term) => !!term.matchExpressions?.length && term.matchExpressions.every((e) => {
|
|
136
|
+
const value = node.metadata.labels?.[e.key];
|
|
137
|
+
if (e.operator === "Exists") return value !== void 0;
|
|
138
|
+
if (e.operator === "DoesNotExist") return value === void 0;
|
|
139
|
+
if (e.operator === "In") return value !== void 0 && !!e.values?.includes(value);
|
|
140
|
+
if (e.operator === "NotIn") return value === void 0 || !e.values?.includes(value);
|
|
141
|
+
return value !== void 0 && !!e.values?.length && Number.isFinite(Number(value)) && (e.operator === "Gt" ? Number(value) > Number(e.values[0]) : Number(value) < Number(e.values[0]));
|
|
142
|
+
}))) reject("Required node affinity does not match");
|
|
143
|
+
}
|
|
144
|
+
for (const metric of ["cpu", "memory"]) try {
|
|
145
|
+
if (node.status?.allocatable?.[metric] !== void 0 && effectivePodResource(pod, metric) > require_monitoring_math.parseQuantity(node.status.allocatable[metric], metric === "memory")) reject(`Pod ${metric} request exceeds node allocatable`);
|
|
146
|
+
} catch {
|
|
147
|
+
limitations.push(`Invalid or unavailable ${metric} resource data`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
for (const volume of spec?.volumes ?? []) {
|
|
151
|
+
const claim = volume.persistentVolumeClaim?.claimName;
|
|
152
|
+
if (!claim) continue;
|
|
153
|
+
const pvc = pvcs?.find((item) => item.metadata.name === claim && item.metadata.namespace === pod.metadata.namespace);
|
|
154
|
+
if (!pvc) limitations.push(`PVC ${claim} data unavailable`);
|
|
155
|
+
else if (pvc.status?.phase !== "Bound") limitations.push(`PVC ${claim} is not bound; delayed binding and storage topology require scheduler evidence`);
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
state,
|
|
159
|
+
evidence,
|
|
160
|
+
limitations: [...new Set(limitations)]
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function observePodChanges(previous, current, observedAt) {
|
|
164
|
+
const entries = [];
|
|
165
|
+
const prior = new Map(previous.filter((pod) => pod.metadata.uid).map((pod) => [pod.metadata.uid, pod]));
|
|
166
|
+
for (const pod of current) {
|
|
167
|
+
const old = pod.metadata.uid ? prior.get(pod.metadata.uid) : void 0;
|
|
168
|
+
const add = (reason, message) => entries.push({
|
|
169
|
+
id: `${pod.metadata.uid ?? pod.metadata.name}/${reason}/${observedAt}`,
|
|
170
|
+
reason,
|
|
171
|
+
message,
|
|
172
|
+
time: validTime(observedAt),
|
|
173
|
+
count: 1,
|
|
174
|
+
certainty: validTime(observedAt) ? "observed" : "unknown",
|
|
175
|
+
objectUid: pod.metadata.uid,
|
|
176
|
+
gap: "Change occurred between snapshots; exact transition time is unknown"
|
|
177
|
+
});
|
|
178
|
+
if (!old) {
|
|
179
|
+
add("FirstObserved", `${pod.metadata.name ?? "Pod"} first observed; creation or rollout time is unknown`);
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
if (old.status?.phase !== pod.status?.phase) add("PhaseChanged", `${old.status?.phase ?? "Unknown"} → ${pod.status?.phase ?? "Unknown"}`);
|
|
183
|
+
for (const status of pod.status?.containerStatuses ?? []) {
|
|
184
|
+
const before = old.status?.containerStatuses?.find((item) => item.name === status.name);
|
|
185
|
+
if (before && status.restartCount !== before.restartCount) add(`Restarts/${status.name}`, `${status.name}: restart count ${before.restartCount} → ${status.restartCount}`);
|
|
186
|
+
if (before && status.ready !== before.ready) add(`Readiness/${status.name}`, `${status.name}: ready ${String(before.ready)} → ${String(status.ready)}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return entries;
|
|
190
|
+
}
|
|
191
|
+
function observeResourceChanges(previous, current, observedAt) {
|
|
192
|
+
const entries = observePodChanges(previous, current.filter((object) => object.kind === "Pod" || !!object.spec?.containers), observedAt);
|
|
193
|
+
const prior = new Map(previous.filter((object) => object.metadata.uid).map((object) => [object.metadata.uid, object]));
|
|
194
|
+
for (const object of current) {
|
|
195
|
+
if (object.kind === "Pod" || object.spec?.containers) continue;
|
|
196
|
+
const old = object.metadata.uid ? prior.get(object.metadata.uid) : void 0;
|
|
197
|
+
if (!old) continue;
|
|
198
|
+
const changes = [
|
|
199
|
+
"readyReplicas",
|
|
200
|
+
"updatedReplicas",
|
|
201
|
+
"observedGeneration"
|
|
202
|
+
].filter((key) => old.status?.[key] !== object.status?.[key]).map((key) => `${key}: ${old.status?.[key] ?? "unknown"} → ${object.status?.[key] ?? "unknown"}`);
|
|
203
|
+
if (old.metadata.generation !== object.metadata.generation) changes.push(`generation: ${old.metadata.generation ?? "unknown"} → ${object.metadata.generation ?? "unknown"}`);
|
|
204
|
+
const revisionKey = "deployment.kubernetes.io/revision";
|
|
205
|
+
if (old.metadata.annotations?.[revisionKey] !== object.metadata.annotations?.[revisionKey]) changes.push(`revision: ${old.metadata.annotations?.[revisionKey] ?? "unknown"} → ${object.metadata.annotations?.[revisionKey] ?? "unknown"}`);
|
|
206
|
+
if (changes.length) entries.push({
|
|
207
|
+
id: `${object.metadata.uid}/rollout/${observedAt}`,
|
|
208
|
+
reason: "RolloutObserved",
|
|
209
|
+
message: `${object.metadata.name ?? "Workload"}: ${changes.join(", ")}`,
|
|
210
|
+
time: validTime(observedAt),
|
|
211
|
+
count: 1,
|
|
212
|
+
certainty: validTime(observedAt) ? "observed" : "unknown",
|
|
213
|
+
objectUid: object.metadata.uid,
|
|
214
|
+
gap: "Change occurred between snapshots; exact transition time is unknown"
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
return entries;
|
|
218
|
+
}
|
|
219
|
+
//#endregion
|
|
220
|
+
exports.buildConsumerGroups = buildConsumerGroups;
|
|
221
|
+
exports.diagnosePendingPod = diagnosePendingPod;
|
|
222
|
+
exports.effectivePodResource = effectivePodResource;
|
|
223
|
+
exports.normalizeEvents = normalizeEvents;
|
|
224
|
+
exports.observePodChanges = observePodChanges;
|
|
225
|
+
exports.observeResourceChanges = observeResourceChanges;
|
|
226
|
+
|
|
227
|
+
//# sourceMappingURL=resource-diagnostics.js.map
|
|
@@ -0,0 +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; 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":"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"}
|
|
@@ -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.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,23 +1,51 @@
|
|
|
1
1
|
const require_extensions = require("../../../_virtual/_global-external_@freelensapp/extensions.js");
|
|
2
2
|
const require__global_external_mobx = require("../../../_virtual/_global-external_mobx.js");
|
|
3
|
+
const require_monitoring_history = require("../monitoring-history.js");
|
|
3
4
|
//#region src/common/store/monitoring-preferences-store.ts
|
|
4
5
|
var MonitoringPreferencesStore = class extends require_extensions.Common.Store.ExtensionStore {
|
|
5
6
|
enabled = false;
|
|
7
|
+
diagnosticsVisible = true;
|
|
8
|
+
historyEnabled = false;
|
|
9
|
+
trackedHistory = [];
|
|
6
10
|
constructor() {
|
|
7
11
|
super({
|
|
8
12
|
configName: "monitoring-preferences",
|
|
9
|
-
defaults: {
|
|
13
|
+
defaults: {
|
|
14
|
+
enabled: false,
|
|
15
|
+
diagnosticsVisible: true,
|
|
16
|
+
historyEnabled: false,
|
|
17
|
+
trackedHistory: []
|
|
18
|
+
}
|
|
10
19
|
});
|
|
11
20
|
require__global_external_mobx.makeObservable(this, {
|
|
12
21
|
enabled: require__global_external_mobx.observable,
|
|
22
|
+
diagnosticsVisible: require__global_external_mobx.observable,
|
|
23
|
+
historyEnabled: require__global_external_mobx.observable,
|
|
24
|
+
trackedHistory: require__global_external_mobx.observable,
|
|
13
25
|
fromStore: require__global_external_mobx.action
|
|
14
26
|
});
|
|
15
27
|
}
|
|
16
28
|
fromStore(data) {
|
|
17
29
|
this.enabled = data?.enabled === true;
|
|
30
|
+
this.diagnosticsVisible = data?.diagnosticsVisible !== false;
|
|
31
|
+
this.historyEnabled = data?.historyEnabled === true;
|
|
32
|
+
this.trackedHistory = Array.isArray(data?.trackedHistory) ? data.trackedHistory.filter(require_monitoring_history.validHistoryIdentity).slice(0, 100).map(({ clusterId, scope, uid }) => ({
|
|
33
|
+
clusterId,
|
|
34
|
+
scope,
|
|
35
|
+
uid
|
|
36
|
+
})) : [];
|
|
18
37
|
}
|
|
19
38
|
toJSON() {
|
|
20
|
-
return {
|
|
39
|
+
return {
|
|
40
|
+
enabled: this.enabled,
|
|
41
|
+
diagnosticsVisible: this.diagnosticsVisible,
|
|
42
|
+
historyEnabled: this.historyEnabled,
|
|
43
|
+
trackedHistory: this.trackedHistory.map(({ clusterId, scope, uid }) => ({
|
|
44
|
+
clusterId,
|
|
45
|
+
scope,
|
|
46
|
+
uid
|
|
47
|
+
}))
|
|
48
|
+
};
|
|
21
49
|
}
|
|
22
50
|
};
|
|
23
51
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitoring-preferences-store.js","names":[],"sources":["../../../../../src/common/store/monitoring-preferences-store.ts"],"sourcesContent":["import { Common } from \"@freelensapp/extensions\";\nimport { action, makeObservable, observable } from \"mobx\";\n\nexport class MonitoringPreferencesStore extends Common.Store.ExtensionStore<{
|
|
1
|
+
{"version":3,"file":"monitoring-preferences-store.js","names":[],"sources":["../../../../../src/common/store/monitoring-preferences-store.ts"],"sourcesContent":["import { Common } from \"@freelensapp/extensions\";\nimport { action, makeObservable, observable } from \"mobx\";\nimport { type HistoryIdentity, validHistoryIdentity } from \"../monitoring-history\";\n\nexport class MonitoringPreferencesStore extends Common.Store.ExtensionStore<{\n enabled: boolean;\n diagnosticsVisible: boolean;\n historyEnabled: boolean;\n trackedHistory: HistoryIdentity[];\n}> {\n enabled = false;\n diagnosticsVisible = true;\n historyEnabled = false;\n trackedHistory: HistoryIdentity[] = [];\n\n constructor() {\n super({\n configName: \"monitoring-preferences\",\n defaults: { enabled: false, diagnosticsVisible: true, historyEnabled: false, trackedHistory: [] },\n });\n makeObservable(this, {\n enabled: observable,\n diagnosticsVisible: observable,\n historyEnabled: observable,\n trackedHistory: observable,\n fromStore: action,\n });\n }\n\n fromStore(data: {\n enabled?: boolean;\n diagnosticsVisible?: boolean;\n historyEnabled?: boolean;\n trackedHistory?: HistoryIdentity[];\n }): void {\n this.enabled = data?.enabled === true;\n this.diagnosticsVisible = data?.diagnosticsVisible !== false;\n this.historyEnabled = data?.historyEnabled === true;\n this.trackedHistory = Array.isArray(data?.trackedHistory)\n ? data.trackedHistory\n .filter(validHistoryIdentity)\n .slice(0, 100)\n .map(({ clusterId, scope, uid }) => ({ clusterId, scope, uid }))\n : [];\n }\n\n toJSON(): {\n enabled: boolean;\n diagnosticsVisible: boolean;\n historyEnabled: boolean;\n trackedHistory: HistoryIdentity[];\n } {\n return {\n enabled: this.enabled,\n diagnosticsVisible: this.diagnosticsVisible,\n historyEnabled: this.historyEnabled,\n trackedHistory: this.trackedHistory.map(({ clusterId, scope, uid }) => ({ clusterId, scope, uid })),\n };\n }\n}\n"],"mappings":";;;;AAIA,IAAa,6BAAb,cAAgD,mBAAA,OAAO,MAAM,eAK1D;CACD,UAAU;CACV,qBAAqB;CACrB,iBAAiB;CACjB,iBAAoC,CAAC;CAErC,cAAc;EACZ,MAAM;GACJ,YAAY;GACZ,UAAU;IAAE,SAAS;IAAO,oBAAoB;IAAM,gBAAgB;IAAO,gBAAgB,CAAC;GAAE;EAClG,CAAC;EACD,8BAAA,eAAe,MAAM;GACnB,SAAS,8BAAA;GACT,oBAAoB,8BAAA;GACpB,gBAAgB,8BAAA;GAChB,gBAAgB,8BAAA;GAChB,WAAW,8BAAA;EACb,CAAC;CACH;CAEA,UAAU,MAKD;EACP,KAAK,UAAU,MAAM,YAAY;EACjC,KAAK,qBAAqB,MAAM,uBAAuB;EACvD,KAAK,iBAAiB,MAAM,mBAAmB;EAC/C,KAAK,iBAAiB,MAAM,QAAQ,MAAM,cAAc,IACpD,KAAK,eACF,OAAO,2BAAA,oBAAoB,CAAC,CAC5B,MAAM,GAAG,GAAG,CAAC,CACb,KAAK,EAAE,WAAW,OAAO,WAAW;GAAE;GAAW;GAAO;EAAI,EAAE,IACjE,CAAC;CACP;CAEA,SAKE;EACA,OAAO;GACL,SAAS,KAAK;GACd,oBAAoB,KAAK;GACzB,gBAAgB,KAAK;GACrB,gBAAgB,KAAK,eAAe,KAAK,EAAE,WAAW,OAAO,WAAW;IAAE;IAAW;IAAO;GAAI,EAAE;EACpG;CACF;AACF"}
|
package/out/renderer/welcome.js
CHANGED
|
@@ -14,17 +14,30 @@ function createWelcomeContent() {
|
|
|
14
14
|
const features = document.createElement("ul");
|
|
15
15
|
features.className = "freelens-power-features";
|
|
16
16
|
features.setAttribute("role", "list");
|
|
17
|
-
|
|
17
|
+
const labels = [
|
|
18
|
+
"🔐 Secure Node Shell with IPv6 and Colima",
|
|
19
|
+
"📜 Certificate details in Secrets",
|
|
20
|
+
"🎨 Themes and cluster icon studio",
|
|
21
|
+
"🔗 Website cards with pinning and refresh",
|
|
22
|
+
"📈 CPU/RAM metrics with local history",
|
|
23
|
+
"🔎 Resource usage, timelines and Pending",
|
|
24
|
+
"🤖 AI chat with context and read-only tools",
|
|
25
|
+
"🔒 Read-only controls for Kubernetes"
|
|
26
|
+
];
|
|
27
|
+
for (const [index, text] of [
|
|
18
28
|
"🔐 Secure Node Shell with custom commands, IPv6 and automatic Colima support",
|
|
19
29
|
"📜 Certificate details in Secrets",
|
|
20
|
-
"🎨 Accent themes
|
|
21
|
-
"🔗 Website dashboards with flexible cards and background refresh",
|
|
30
|
+
"🎨 Accent themes and matching custom cluster icons",
|
|
31
|
+
"🔗 Website dashboards with flexible cards, pinned windows and background refresh",
|
|
32
|
+
"📈 Cluster, node and pod metrics with optional local history",
|
|
33
|
+
"🔎 Resource consumers, application timelines and Pending diagnostics",
|
|
22
34
|
"🤖 Context-aware AI chat with read-only tools and prompt shortcuts",
|
|
23
35
|
"🔒 Read-only UI controls for safer browsing"
|
|
24
|
-
]) {
|
|
36
|
+
].entries()) {
|
|
25
37
|
const feature = document.createElement("li");
|
|
26
38
|
feature.setAttribute("role", "listitem");
|
|
27
|
-
feature.textContent =
|
|
39
|
+
feature.textContent = labels[index];
|
|
40
|
+
feature.title = text;
|
|
28
41
|
features.append(feature);
|
|
29
42
|
}
|
|
30
43
|
content.append(features);
|
|
@@ -47,8 +60,19 @@ function startWelcomeOverride() {
|
|
|
47
60
|
.Welcome [${HOST_ATTRIBUTE}] > p { display: none; }
|
|
48
61
|
.Welcome [${CONTENT_ATTRIBUTE}] { color: var(--textColorSecondary); }
|
|
49
62
|
.Welcome [${CONTENT_ATTRIBUTE}] h2 { color: var(--textColorPrimary); margin: 15px 0 16px; }
|
|
50
|
-
.Welcome [${CONTENT_ATTRIBUTE}] .freelens-power-features { display:
|
|
51
|
-
.Welcome [${CONTENT_ATTRIBUTE}] .freelens-power-features > li, .Welcome [${CONTENT_ATTRIBUTE}] .freelens-power-features > li:hover { margin: 0; padding: 0; background: none; border: 0; border-radius: 0; box-shadow: none; cursor: default; color: inherit; text-decoration: none; transform: none; transition: none; }
|
|
63
|
+
.Welcome [${CONTENT_ATTRIBUTE}] .freelens-power-features { display: grid; grid-template-columns: repeat(2, minmax(0, max-content)); justify-content: center; gap: 14px 48px; list-style: none; padding: 16px 0; margin: 16px 0; border-top: 1px solid var(--borderColor); border-bottom: 1px solid var(--borderColor); text-align: left; line-height: 1.5; }
|
|
64
|
+
.Welcome [${CONTENT_ATTRIBUTE}] .freelens-power-features > li, .Welcome [${CONTENT_ATTRIBUTE}] .freelens-power-features > li:hover { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin: 0; padding: 0; background: none; border: 0; border-radius: 0; box-shadow: none; cursor: default; color: inherit; text-decoration: none; transform: none; transition: none; }
|
|
65
|
+
.Welcome [data-testid="welcome-banner-container"]:has([${HOST_ATTRIBUTE}]) { width: min(960px, calc(100% - 48px)) !important; }
|
|
66
|
+
.Welcome [${HOST_ATTRIBUTE}] { width: 100% !important; max-width: 100%; }
|
|
67
|
+
.Welcome [data-testid="no-welcome-banners-icon"] { display: inline-flex; width: 120px; height: 120px; }
|
|
68
|
+
.Welcome [data-testid="no-welcome-banners-icon"] svg { width: 100%; height: 100%; }
|
|
69
|
+
.Welcome [${HOST_ATTRIBUTE}] [data-testid="welcome-menu-container"] { width: fit-content !important; margin-inline: auto; max-width: 100%; }
|
|
70
|
+
.Welcome [${HOST_ATTRIBUTE}] [data-testid="welcome-menu-container"] > li { display: flex; align-items: center; gap: 8px; padding: 8px 12px; }
|
|
71
|
+
.Welcome [${HOST_ATTRIBUTE}] [data-testid="welcome-menu-container"] .box { flex: 0 0 auto; width: auto; padding: 0; }
|
|
72
|
+
.Welcome [${HOST_ATTRIBUTE}] [data-testid="welcome-menu-container"] a { margin-left: 0; }
|
|
73
|
+
@media (max-width: 640px) {
|
|
74
|
+
.Welcome [${CONTENT_ATTRIBUTE}] .freelens-power-features { grid-template-columns: 1fr; }
|
|
75
|
+
}
|
|
52
76
|
.Welcome [${CONTENT_ATTRIBUTE}] p { margin-top: 14px; }
|
|
53
77
|
`;
|
|
54
78
|
document.head.append(style);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"welcome.js","names":[],"sources":["../../src/renderer/welcome.ts"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\nconst WELCOME_SELECTOR = '.Welcome [data-testid=\"welcome-text-container\"]';\nconst HOST_ATTRIBUTE = \"data-freelens-power-welcome\";\nconst CONTENT_ATTRIBUTE = \"data-freelens-power-welcome-content\";\n\nfunction createWelcomeContent(): HTMLDivElement {\n const content = document.createElement(\"div\");\n content.setAttribute(CONTENT_ATTRIBUTE, \"\");\n\n const heading = document.createElement(\"h2\");\n heading.textContent = \"🔋 Freelens Power\";\n content.append(heading);\n\n const introduction = document.createElement(\"p\");\n introduction.textContent = \"Make Freelens your own with practical tools for everyday Kubernetes work.\";\n content.append(introduction);\n\n const features = document.createElement(\"ul\");\n features.className = \"freelens-power-features\";\n features.setAttribute(\"role\", \"list\");\n\n for (const text of [\n \"🔐 Secure Node Shell with custom commands, IPv6 and automatic Colima support\",\n \"📜 Certificate details in Secrets\",\n \"🎨 Accent themes
|
|
1
|
+
{"version":3,"file":"welcome.js","names":[],"sources":["../../src/renderer/welcome.ts"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\nconst WELCOME_SELECTOR = '.Welcome [data-testid=\"welcome-text-container\"]';\nconst HOST_ATTRIBUTE = \"data-freelens-power-welcome\";\nconst CONTENT_ATTRIBUTE = \"data-freelens-power-welcome-content\";\n\nfunction createWelcomeContent(): HTMLDivElement {\n const content = document.createElement(\"div\");\n content.setAttribute(CONTENT_ATTRIBUTE, \"\");\n\n const heading = document.createElement(\"h2\");\n heading.textContent = \"🔋 Freelens Power\";\n content.append(heading);\n\n const introduction = document.createElement(\"p\");\n introduction.textContent = \"Make Freelens your own with practical tools for everyday Kubernetes work.\";\n content.append(introduction);\n\n const features = document.createElement(\"ul\");\n features.className = \"freelens-power-features\";\n features.setAttribute(\"role\", \"list\");\n\n const labels = [\n \"🔐 Secure Node Shell with IPv6 and Colima\",\n \"📜 Certificate details in Secrets\",\n \"🎨 Themes and cluster icon studio\",\n \"🔗 Website cards with pinning and refresh\",\n \"📈 CPU/RAM metrics with local history\",\n \"🔎 Resource usage, timelines and Pending\",\n \"🤖 AI chat with context and read-only tools\",\n \"🔒 Read-only controls for Kubernetes\",\n ];\n for (const [index, text] of [\n \"🔐 Secure Node Shell with custom commands, IPv6 and automatic Colima support\",\n \"📜 Certificate details in Secrets\",\n \"🎨 Accent themes and matching custom cluster icons\",\n \"🔗 Website dashboards with flexible cards, pinned windows and background refresh\",\n \"📈 Cluster, node and pod metrics with optional local history\",\n \"🔎 Resource consumers, application timelines and Pending diagnostics\",\n \"🤖 Context-aware AI chat with read-only tools and prompt shortcuts\",\n \"🔒 Read-only UI controls for safer browsing\",\n ].entries()) {\n const feature = document.createElement(\"li\");\n feature.setAttribute(\"role\", \"listitem\");\n feature.textContent = labels[index];\n feature.title = text;\n features.append(feature);\n }\n\n content.append(features);\n\n const paragraph = document.createElement(\"p\");\n const link = document.createElement(\"a\");\n link.className = \"link\";\n link.href = \"https://github.com/64mb/freelens-power\";\n link.target = \"_blank\";\n link.rel = \"noopener noreferrer\";\n link.textContent = \"Freelens Power on GitHub\";\n paragraph.append(link);\n content.append(paragraph);\n\n return content;\n}\n\nexport function startWelcomeOverride(): () => void {\n const style = document.createElement(\"style\");\n style.setAttribute(\"data-freelens-power\", \"welcome\");\n style.textContent = `\n .Welcome [${HOST_ATTRIBUTE}] > h2,\n .Welcome [${HOST_ATTRIBUTE}] > p { display: none; }\n .Welcome [${CONTENT_ATTRIBUTE}] { color: var(--textColorSecondary); }\n .Welcome [${CONTENT_ATTRIBUTE}] h2 { color: var(--textColorPrimary); margin: 15px 0 16px; }\n .Welcome [${CONTENT_ATTRIBUTE}] .freelens-power-features { display: grid; grid-template-columns: repeat(2, minmax(0, max-content)); justify-content: center; gap: 14px 48px; list-style: none; padding: 16px 0; margin: 16px 0; border-top: 1px solid var(--borderColor); border-bottom: 1px solid var(--borderColor); text-align: left; line-height: 1.5; }\n .Welcome [${CONTENT_ATTRIBUTE}] .freelens-power-features > li, .Welcome [${CONTENT_ATTRIBUTE}] .freelens-power-features > li:hover { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin: 0; padding: 0; background: none; border: 0; border-radius: 0; box-shadow: none; cursor: default; color: inherit; text-decoration: none; transform: none; transition: none; }\n .Welcome [data-testid=\"welcome-banner-container\"]:has([${HOST_ATTRIBUTE}]) { width: min(960px, calc(100% - 48px)) !important; }\n .Welcome [${HOST_ATTRIBUTE}] { width: 100% !important; max-width: 100%; }\n .Welcome [data-testid=\"no-welcome-banners-icon\"] { display: inline-flex; width: 120px; height: 120px; }\n .Welcome [data-testid=\"no-welcome-banners-icon\"] svg { width: 100%; height: 100%; }\n .Welcome [${HOST_ATTRIBUTE}] [data-testid=\"welcome-menu-container\"] { width: fit-content !important; margin-inline: auto; max-width: 100%; }\n .Welcome [${HOST_ATTRIBUTE}] [data-testid=\"welcome-menu-container\"] > li { display: flex; align-items: center; gap: 8px; padding: 8px 12px; }\n .Welcome [${HOST_ATTRIBUTE}] [data-testid=\"welcome-menu-container\"] .box { flex: 0 0 auto; width: auto; padding: 0; }\n .Welcome [${HOST_ATTRIBUTE}] [data-testid=\"welcome-menu-container\"] a { margin-left: 0; }\n @media (max-width: 640px) {\n .Welcome [${CONTENT_ATTRIBUTE}] .freelens-power-features { grid-template-columns: 1fr; }\n }\n .Welcome [${CONTENT_ATTRIBUTE}] p { margin-top: 14px; }\n `;\n document.head.append(style);\n\n const hosts = new Map<Element, { content: HTMLDivElement; previousAttribute: string | null }>();\n\n const restore = (host: Element) => {\n const entry = hosts.get(host);\n if (!entry) return;\n\n entry.content.remove();\n if (entry.previousAttribute === null) {\n host.removeAttribute(HOST_ATTRIBUTE);\n } else {\n host.setAttribute(HOST_ATTRIBUTE, entry.previousAttribute);\n }\n hosts.delete(host);\n };\n\n const attach = (host: Element) => {\n if (hosts.has(host)) return;\n\n const content = createWelcomeContent();\n hosts.set(host, { content, previousAttribute: host.getAttribute(HOST_ATTRIBUTE) });\n host.setAttribute(HOST_ATTRIBUTE, \"\");\n host.prepend(content);\n };\n\n const scan = (node: Element) => {\n if (node.matches(WELCOME_SELECTOR)) attach(node);\n for (const host of node.querySelectorAll(WELCOME_SELECTOR)) attach(host);\n };\n\n scan(document.body);\n\n const observer = new MutationObserver((mutations) => {\n for (const host of hosts.keys()) {\n if (!host.isConnected) restore(host);\n }\n\n for (const mutation of mutations) {\n for (const node of mutation.addedNodes) {\n if (node instanceof Element && node.isConnected) scan(node);\n }\n }\n });\n observer.observe(document.body, { childList: true, subtree: true });\n\n return () => {\n observer.disconnect();\n for (const host of hosts.keys()) restore(host);\n style.remove();\n };\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@64mb/freelens-power",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Power tools for Freelens Kubernetes IDE",
|
|
5
5
|
"main": "out/main/index.js",
|
|
6
6
|
"renderer": "out/renderer/index.js",
|
|
@@ -46,7 +46,8 @@
|
|
|
46
46
|
"freelens"
|
|
47
47
|
],
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"markdown-it": "15.0.2"
|
|
49
|
+
"markdown-it": "15.0.2",
|
|
50
|
+
"react-select": "5.10.2"
|
|
50
51
|
},
|
|
51
52
|
"repository": {
|
|
52
53
|
"type": "git",
|