Calls primary_project.get_compilerversion() (ScriptEngine 4.2.0.0+) and
emits the result through the JSON payload. Renders as:
- library.md: a 'Project compiler version' row in the Versions table
- list_project_libraries chat output: a 'Compiler version: X.Y.Z.W'
line in the header section
Motivation: changing the project's compiler version (Project > Project
Settings > Compiler version, or set_compilerversion_to_newest()) only
touched the .project binary -- mirror_export couldn't see it, so the
release classifier had to fall back to SHA comparison and emitted the
generic 'device-tree / library refs / task config / visu / Save() touch'
classification. Compiler-version changes now leave a textual diff in
mcp-mirror/library.md, letting the classifier issue an honest revision
bump instead of the bare build-bump SHA fallback.
Defensive: get_compilerversion() is wrapped in try/except so older
ScriptEngines (< 4.2.0.0) that lack the method don't crash the tool;
they just emit compiler_version=null and the field is omitted from
output.
Enriches the tool's output with project-level metadata that previously
lived only in hand-edited library.md headers:
Project info:
Version: 1.0.0.0 (Project Information.version)
Title: ... (Project Information.title)
Company: ... (Project Information.company)
Author: ... (Project Information.author)
IDE: CODESYS V3.5 SP22 Patch 1, ScriptEngine.plugin 4.2.0.0
Devices (N):
MainPLC [4096 / 1006 120D / 6.2.0.1]
MainPLC/Kbus [32778 / Wago 750-Series Local Bus Interface / 2.1.0.1]
...
Implementation:
- collect_project_info() reads .version / .title / .company / .author
on the Project Information node (first child of project root). Each
field is read defensively (try/except) since some installs leave
them unset; missing fields are dropped from the output.
- collect_devices() walks the tree depth-first for nodes where
is_device is True, captures get_device_identification() into a
type/id/version triple. The triple is the offline target id the
IDE uses to pick a compiler + runtime when building -- not the
live firmware reported by a connected PLC over a runtime
connection (the latter would require an online connect).
- sys.version inside IronPython under CODESYS reports the IDE
version directly (same string we see in ready.signal).
server.ts renders these as a Header block above the existing
library-by-container tables. Hand-edited X33/library.md "Versions"
section is now redundant -- next regeneration will produce the
header automatically.
Verified via the local SP22 install + the live X33 watcher: pi.version
read-back works after bump_project_version sets it, devices walk
returns 13 entries on X33 (MainPLC + 11 Kbus modules + the network
adapter).
RTFM. Per the helpme-codesys.com Library Manager scripting page and
the local SP22 stub Stubs/scriptengine/ScriptLibManObject.pyi:
- ScriptLibManObjectContainer is added to BOTH the project AND every
Application object. It exposes:
has_library_manager -- @property (NOT a method) returning bool
get_library_manager() -- method returning the LibMan ScriptObject
- ScriptLibManObject (the libman itself) exposes:
.references -- @property, ScriptLibraryReferences (list-
like) of ScriptLibraryReference objects
with structured fields (name, namespace,
is_placeholder, is_managed, system_library,
effective_resolution, ...)
get_libraries(recursive=False) -- list[str], names only
- ScriptLibManObjectMarker.is_libman is the universal marker, useful
as a fallback when walking the tree.
The previous implementation searched the project tree by NAME for an
object literally called "Library Manager" via primary_project.find()
and a children name probe. That never matches because the libman's
actual name is generated, not "Library Manager." On the X33 project
(MRCodesysX33_0021) it returned empty -- false negative on a project
that obviously has dozens of system + application libraries. This
also took add_library down with it (same wrong axis), and the smoke
test from earlier in the fork's history flagged the inconsistency
without identifying the cause.
Fixed:
- Walk the tree depth-first, accept any node where has_library_manager
is True (depth-limited at 8 to be safe).
- For each, call get_library_manager() and iterate .references for
structured data; fall back to get_libraries() name-only enumeration
if .references is unavailable on the SP.
- Capture every documented ScriptLibraryReference field defensively
(each access wrapped in try/except since some fields raise on
placeholders / unmanaged / SP-version skew).
- Return a structured JSON shape grouped by container so the TS side
can show which Application owns which libraries.
server.ts:
- Updated the result-parsing block to handle the new structured shape.
- Distinguishes "no library managers found" (suspicious, libman
discovery probably broken) from "found managers, all empty" (just
empty applications).
- Renders flags ([system, placeholder, managed, optional, redirected])
+ namespace + effective_resolution per reference.
- Tool description rewritten to advertise the actual mechanism and
cite the doc + local stub source.
add_library is NOT fixed in this commit -- it has the same wrong-axis
bug but landing the lookup-only fix first to verify the API contract.
add_library will land separately once we know list_project_libraries
sees the right libman in production (X33 smoke test).