diff --git a/package.json b/package.json index 8e93d25..9bc71a4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codesys-mcp-sp21-plus", - "version": "0.6.3", + "version": "0.6.4", "description": "Codesys-MCP-SP21+ -- fork of luke-harriman/Codesys-MCP carrying CODESYS V3.5 SP22 Patch 1 fixes (and forward-compat with later SPs): script-engine API drift, online/runtime tool auto-login, dual-SHA release classifier, set_pou_code omitted-decl wipe fix, add_library managed-overload, etc. MCP server for CODESYS with persistent UI instance and file-based IPC.", "main": "dist/server.js", "bin": { diff --git a/src/scripts/compile_project.py b/src/scripts/compile_project.py index bf115cb..65c504a 100644 --- a/src/scripts/compile_project.py +++ b/src/scripts/compile_project.py @@ -106,36 +106,43 @@ def _build_message_entry(msg, category_name=None): def _enumerate_categories(script_engine_arg): + """Returns a list of (label, category_guid_or_None) tuples for every + message category the IDE exposes plus a (None, None) sentinel for the + no-filter call. + + Discovery path: script_engine.system.get_message_categories() (the + METHOD) returns the live List[Guid] of category IDs registered in + this IDE session. script_engine.system.get_message_category_description(guid) + gives the human-readable label per category ('Build', 'Application + Composer', 'SVN', 'Script Messages', 'Additional code checks', etc.). + + History: pre-0.6.4 the function looked at `system.message_categories` + (a property) which doesn't exist, then fell back to a hardcoded list + of GUIDs that happened to NOT include the actual Build category + (97f48d64-a2a3-4856-b640-75c046e37ea9). Result: compile errors were + invisible. Verified by diagnostic probe with intentional syntax-error + injection on 2026-04-29.""" cats = [('', None)] + se_sys = getattr(script_engine_arg, 'system', None) + if se_sys is None or not hasattr(se_sys, 'get_message_categories'): + return cats try: - se_sys = getattr(script_engine_arg, 'system', None) - if se_sys is not None: - mc = getattr(se_sys, 'message_categories', None) - if mc is not None: - try: - for c in mc: - try: - label = ( - _coerce_str(getattr(c, 'name', None)) - or _coerce_str(getattr(c, 'guid', None)) - or _coerce_str(c) - or '' - ) - cats.append((label, c)) - except Exception: - continue - except Exception: - pass - except Exception: - pass - well_known = [ - ('Compile (well-known GUID)', '90F1B997-7AB7-4B11-B637-D55D71BC4F2A'), - ('Build (well-known GUID)', '7390398F-1B2F-4B30-B6E2-37F2BB7B57E0'), - ('Online (well-known GUID)', '15F65557-DC73-4193-B7F2-EFF5A2A6C10C'), - ('LibMan (well-known GUID)', '0B8D54FB-C68A-43F9-9B4D-79DBE1F8DF44'), - ] - for lbl, g in well_known: - cats.append((lbl, g)) + guids = se_sys.get_message_categories() + except Exception as e: + print("DEBUG: get_message_categories() raised: %s" % e) + return cats + if guids is None: + return cats + for g in guids: + label = None + try: + if hasattr(se_sys, 'get_message_category_description'): + label = _coerce_str(se_sys.get_message_category_description(g)) + except Exception: + label = None + if not label: + label = _coerce_str(g) or '' + cats.append((label, g)) return cats diff --git a/src/scripts/get_compile_messages.py b/src/scripts/get_compile_messages.py index 0835b4f..e40f2e6 100644 --- a/src/scripts/get_compile_messages.py +++ b/src/scripts/get_compile_messages.py @@ -106,39 +106,35 @@ def _build_message_entry(msg, category_name=None): def _enumerate_categories(script_engine_arg): - """Returns a list of (label, category_obj_or_guid_or_None). Always - includes a (None, None) sentinel for the no-filter call.""" + """Returns a list of (label, category_guid_or_None) tuples for every + message category the IDE exposes plus a (None, None) sentinel for the + no-filter call. + + Discovery path: script_engine.system.get_message_categories() (the + METHOD) returns the live List[Guid]. script_engine.system.get_message_category_description(guid) + gives the human-readable label per category. See compile_project.py + for the verified-on-SP22 history note.""" cats = [('', None)] + se_sys = getattr(script_engine_arg, 'system', None) + if se_sys is None or not hasattr(se_sys, 'get_message_categories'): + return cats try: - se_sys = getattr(script_engine_arg, 'system', None) - if se_sys is not None: - mc = getattr(se_sys, 'message_categories', None) - if mc is not None: - try: - for c in mc: - try: - label = ( - _coerce_str(getattr(c, 'name', None)) - or _coerce_str(getattr(c, 'guid', None)) - or _coerce_str(c) - or '' - ) - cats.append((label, c)) - except Exception: - continue - except Exception: - pass - except Exception: - pass - # Well-known V3.5 category GUIDs (probed as fallback strings). - well_known = [ - ('Compile (well-known GUID)', '90F1B997-7AB7-4B11-B637-D55D71BC4F2A'), - ('Build (well-known GUID)', '7390398F-1B2F-4B30-B6E2-37F2BB7B57E0'), - ('Online (well-known GUID)', '15F65557-DC73-4193-B7F2-EFF5A2A6C10C'), - ('LibMan (well-known GUID)', '0B8D54FB-C68A-43F9-9B4D-79DBE1F8DF44'), - ] - for lbl, g in well_known: - cats.append((lbl, g)) + guids = se_sys.get_message_categories() + except Exception as e: + print("DEBUG: get_message_categories() raised: %s" % e) + return cats + if guids is None: + return cats + for g in guids: + label = None + try: + if hasattr(se_sys, 'get_message_category_description'): + label = _coerce_str(se_sys.get_message_category_description(g)) + except Exception: + label = None + if not label: + label = _coerce_str(g) or '' + cats.append((label, g)) return cats