Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 48fd8579c5 | |||
| 62bf372e1d | |||
| 3a4654141f | |||
| 967dcfcb37 | |||
| d7faf186f8 | |||
| f819aa68d5 | |||
| 975ad20d5a | |||
| a94106ae61 | |||
| 777e830aec | |||
| bbf2dc903a | |||
| 8fb05858c8 | |||
| d0d0f30d64 | |||
| 04185f9a31 | |||
| 5227a1370c | |||
| c33f306944 | |||
| 3306780507 | |||
| 84d7b60cd2 | |||
| 0d435a5d4a | |||
| 4994543d56 | |||
| 026ceab2ef | |||
| c92bf504fb | |||
| a7eac42c9d | |||
| f20550d5f6 | |||
| 742b08c86d | |||
| a85ddcd6c1 | |||
| 758ac4ab62 | |||
| 56e5d7ff54 | |||
| 596a8ba21d | |||
| 19b67b3c8a | |||
| eaa97ce301 | |||
| a05d16a789 | |||
| f11aa77e3a | |||
| 1bbcf60e58 | |||
| c90ee58bc0 | |||
| 2983e20695 | |||
| 4e7570cb26 | |||
| 7987b61345 | |||
| 6fbd47ed8a | |||
| bada4ef524 | |||
| 8918d37bb6 | |||
| b0d94a3594 | |||
| 1291204d2b | |||
| 804f201589 | |||
| 65779b1eb6 | |||
| 7eac978950 | |||
| b1d0cfa2e7 | |||
| 282b1c2b0a | |||
| b4b0d4cd7e | |||
| 6a66ee75ac | |||
| 45dcdcccbb | |||
| 5d47f1dfca | |||
| 1e07e5f17b | |||
| 8adb1b9730 | |||
| 9d3720b6a1 | |||
| 6496601e4e | |||
| b96df3b501 | |||
| 489460f509 | |||
| 192870d658 | |||
| bed4b5ee49 | |||
| f0eb402100 | |||
| e73486904b | |||
| 1119a45e93 |
@@ -67,9 +67,9 @@ def fetch_all_records(url: str, *, expand: str | None = None, per_page: int = 50
|
|||||||
return items
|
return items
|
||||||
|
|
||||||
|
|
||||||
def normalize_os_variants(install_methods_json: list[dict[str, Any]]) -> list[str]:
|
def normalize_os_variants(install_methods: list[dict[str, Any]]) -> list[str]:
|
||||||
os_values: list[str] = []
|
os_values: list[str] = []
|
||||||
for item in install_methods_json:
|
for item in install_methods:
|
||||||
if not isinstance(item, dict):
|
if not isinstance(item, dict):
|
||||||
continue
|
continue
|
||||||
resources = item.get("resources", {})
|
resources = item.get("resources", {})
|
||||||
@@ -83,6 +83,31 @@ def normalize_os_variants(install_methods_json: list[dict[str, Any]]) -> list[st
|
|||||||
return os_values
|
return os_values
|
||||||
|
|
||||||
|
|
||||||
|
def split_notes(notes_raw: list[dict[str, Any]]) -> tuple[list[str], list[str]]:
|
||||||
|
"""Split PocketBase notes into (info_notes, warnings).
|
||||||
|
|
||||||
|
Each entry has shape ``{"text": str, "type": "warning"|...}``. Anything
|
||||||
|
flagged ``type == "warning"`` lands in the warnings list so the bash
|
||||||
|
menu can render those in red with a dedicated WARNINGS header. Other
|
||||||
|
notes go to the regular notes list.
|
||||||
|
"""
|
||||||
|
info: list[str] = []
|
||||||
|
warns: list[str] = []
|
||||||
|
for note in notes_raw or []:
|
||||||
|
if not isinstance(note, dict):
|
||||||
|
continue
|
||||||
|
text = note.get("text")
|
||||||
|
if not isinstance(text, str) or not text.strip():
|
||||||
|
continue
|
||||||
|
text = text.strip()
|
||||||
|
ntype = (note.get("type") or "").strip().lower()
|
||||||
|
if ntype == "warning":
|
||||||
|
warns.append(text)
|
||||||
|
else:
|
||||||
|
info.append(text)
|
||||||
|
return info, warns
|
||||||
|
|
||||||
|
|
||||||
def build_script_path(type_name: str, slug: str) -> str:
|
def build_script_path(type_name: str, slug: str) -> str:
|
||||||
type_name = (type_name or "").strip().lower()
|
type_name = (type_name or "").strip().lower()
|
||||||
slug = (slug or "").strip()
|
slug = (slug or "").strip()
|
||||||
@@ -138,19 +163,19 @@ def main() -> int:
|
|||||||
full_script_url = f"{SCRIPT_BASE}/{script_path}"
|
full_script_url = f"{SCRIPT_BASE}/{script_path}"
|
||||||
script_url_mirror = to_mirror_url(full_script_url)
|
script_url_mirror = to_mirror_url(full_script_url)
|
||||||
|
|
||||||
install_methods_json = raw.get("install_methods_json", [])
|
# Sprint 11.7: PocketBase exposes these as `install_methods` and
|
||||||
if not isinstance(install_methods_json, list):
|
# `notes`, not `install_methods_json` / `notes_json`. The legacy field
|
||||||
install_methods_json = []
|
# names silently returned [] for every entry, which is why the cache
|
||||||
|
# had empty notes and missing OS variants for every script.
|
||||||
|
install_methods = raw.get("install_methods", [])
|
||||||
|
if not isinstance(install_methods, list):
|
||||||
|
install_methods = []
|
||||||
|
|
||||||
notes_json = raw.get("notes_json", [])
|
notes_raw = raw.get("notes", [])
|
||||||
if not isinstance(notes_json, list):
|
if not isinstance(notes_raw, list):
|
||||||
notes_json = []
|
notes_raw = []
|
||||||
|
|
||||||
notes = [
|
notes, warnings = split_notes(notes_raw)
|
||||||
note.get("text", "")
|
|
||||||
for note in notes_json
|
|
||||||
if isinstance(note, dict) and isinstance(note.get("text"), str) and note.get("text", "").strip()
|
|
||||||
]
|
|
||||||
|
|
||||||
category_ids = raw.get("categories", [])
|
category_ids = raw.get("categories", [])
|
||||||
if not isinstance(category_ids, list):
|
if not isinstance(category_ids, list):
|
||||||
@@ -193,6 +218,7 @@ def main() -> int:
|
|||||||
"categories": category_ids,
|
"categories": category_ids,
|
||||||
"category_names": category_names,
|
"category_names": category_names,
|
||||||
"notes": notes,
|
"notes": notes,
|
||||||
|
"warnings": warnings,
|
||||||
"port": raw.get("port", 0),
|
"port": raw.get("port", 0),
|
||||||
"website": raw.get("website", ""),
|
"website": raw.get("website", ""),
|
||||||
"documentation": raw.get("documentation", ""),
|
"documentation": raw.get("documentation", ""),
|
||||||
@@ -210,7 +236,7 @@ def main() -> int:
|
|||||||
# Emit one entry per install method so the menu shell can offer an
|
# Emit one entry per install method so the menu shell can offer an
|
||||||
# explicit OS choice. When there is only one method (or none), a
|
# explicit OS choice. When there is only one method (or none), a
|
||||||
# single entry is emitted with os="" (script decides at runtime).
|
# single entry is emitted with os="" (script decides at runtime).
|
||||||
os_variants = normalize_os_variants(install_methods_json)
|
os_variants = normalize_os_variants(install_methods)
|
||||||
|
|
||||||
if len(os_variants) > 1:
|
if len(os_variants) > 1:
|
||||||
for os_name in os_variants:
|
for os_name in os_variants:
|
||||||
@@ -228,11 +254,12 @@ def main() -> int:
|
|||||||
with OUTPUT_FILE.open("w", encoding="utf-8") as f:
|
with OUTPUT_FILE.open("w", encoding="utf-8") as f:
|
||||||
json.dump(cache, f, ensure_ascii=False, indent=2)
|
json.dump(cache, f, ensure_ascii=False, indent=2)
|
||||||
|
|
||||||
|
total_notes = sum(len(e.get("notes", [])) for e in cache)
|
||||||
|
total_warns = sum(len(e.get("warnings", [])) for e in cache)
|
||||||
print(f"\n✅ helpers_cache.json → {OUTPUT_FILE}")
|
print(f"\n✅ helpers_cache.json → {OUTPUT_FILE}")
|
||||||
print(f" Guardados: {len(cache)}")
|
print(f" Guardados: {len(cache)} entries, {total_notes} notes, {total_warns} warnings")
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
|||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
0024ebd5201dc3b504aaa760b18ff6651338e3cae21e26e3cb8f4cc8b613b04a ProxMenux-1.2.0.AppImage
|
db5bc199adba9c231f344428ac902a0cbf7473778e8a79a4535263599d975449 ProxMenux-1.2.0.AppImage
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
### New version ProxMenux v1.2.1 — *SR-IOV Awareness & GPU Passthrough Hardening*
|
### New version ProxMenux v1.2.1 — *SR-IOV Awareness & GPU Passthrough Hardening*
|
||||||
|
|
||||||
Targeted release on top of **v1.2.0** addressing three community-reported areas that needed fixing before the next stable cycle: full SR-IOV awareness across the GPU/PCI subsystem, robust handling of GPU + audio companions during passthrough attach and detach (Intel iGPU with chipset audio, discrete cards with HDMI audio, mixed-GPU VMs), and compatibility fixes for the AI notification providers (OpenAI-compatible custom endpoints such as LiteLLM/MLX/LM Studio, OpenAI reasoning models, and Gemini 2.5+/3.x thinking models). Also bundles quality-of-life fixes in the NVIDIA installer, the disk health monitor, and the LXC lifecycle helpers used by the passthrough wizards.
|
Targeted release on top of **v1.2.0** addressing three community-reported areas: complete SR-IOV awareness across the GPU/PCI subsystem, robust handling of GPU + audio companions during passthrough attach and detach (Intel iGPU with chipset audio, discrete cards with HDMI audio, mixed-GPU VMs), and compatibility fixes for AI notification providers (OpenAI-compatible custom endpoints such as LiteLLM/MLX/LM Studio, OpenAI reasoning models, and Gemini 2.5+/3.x thinking models). Also includes quality-of-life improvements in the NVIDIA installer, the disk health monitor, and the LXC lifecycle helpers used by the passthrough wizards.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -1062,4 +1062,4 @@ Disks now display tags like ⚠ In use, ⚠ RAID, ⚠ LVM, or ⚠ ZFS, making it
|
|||||||
## [1.0.0] - 2024-12-18
|
## [1.0.0] - 2024-12-18
|
||||||
### Added
|
### Added
|
||||||
- Initial release of **ProxMenux**.
|
- Initial release of **ProxMenux**.
|
||||||
- Created a script to add **Coral TPU drivers** to Proxmox.
|
- Created a script to add **Coral TPU drivers** to Proxmox.
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
Under this license:
|
Under this license:
|
||||||
1. Attribution: You must give appropriate credit to the original author (MacRimi).
|
1. Attribution: You must give appropriate credit to the original author (MacRimi)
|
||||||
|
and to all contributors involved in the development of the project.
|
||||||
2. Copyleft: If you remix, transform, or build upon ProxMenux, you must
|
2. Copyleft: If you remix, transform, or build upon ProxMenux, you must
|
||||||
distribute your contributions under the same GPL-3.0 license.
|
distribute your contributions under the same GPL-3.0 license.
|
||||||
3. Source Code: Anyone distributing a modified version must make the
|
3. Source Code: Anyone distributing a modified version must make the
|
||||||
@@ -34,4 +35,4 @@ FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
|||||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING
|
||||||
FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
DEALINGS IN THE SOFTWARE.
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
|||||||
+4783
-1150
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user