* fix: login crash when network plugin is unavailable
* fix: directly use !config_version.empty() for the control block
* Use if/else for the empty plug-in version check
* Fix multi-device task list using a deleted network agent after plug-in reload
---------
Co-authored-by: SoftFever <103989404+SoftFever@users.noreply.github.com>
Co-authored-by: SoftFever <softfeverever@gmail.com>
* fix: hide symbols of the bundled static openssl
* fix: hide the bundled static OpenSSL symbols on Linux
* fix: relink _ssl/_hashlib when OpenSSL recipe changes
## Summary
Fixes#15944.
The plugin audit deny-list matched `secret`, `cert`, and
`conf` as substrings of every path component. This blocked
valid imports during plugin capability execution, for example
`numpy/__config__.py`, because `conf` appeared inside the
module filename.
This PR changes deny keyword matching to use whole path
components instead of substring matches. It keeps the
intended protections for sensitive locations and config
files, while allowing dependency and stdlib modules whose
names merely contain those strings.
## Changes
- Match denied path keywords as whole components instead of
substrings.
- Keep denying sensitive directory names such as:
- `secret`
- `secrets`
- `cert`
- `certs`
- `certificate`
- `certificates`
- `conf`
- `config`
- Keep denying config files by extension:
- `.conf`
- `.ini`
- Allow legitimate Python module/package paths such as:
- `numpy/__config__.py`
- `numpy/_core/_ufunc_config.py`
- `configparser.py`
- `sysconfig.py`
- `logging/config.py`
- `certifi/cacert.pem`
- Include the denied target and reason in `PermissionError`
messages when the audit hook blocks an operation.
- Remove an unused `<memory>` include from
`PluginAuditManager.hpp`.
## Why
The previous substring matching caused false positives for
common dependency and standard-library paths. It also made
failures hard to diagnose because the Python exception did
not include the refused path.
The new behavior is narrower: it blocks sensitive path
components and config file extensions without treating
unrelated names like `__config__.py`, `configparser.py`,
`Conference`, or `Concert` as secrets.
## Testing
- Added/updated unit coverage in
`tests/slic3rutils/test_plugin_audit.cpp` for:
- whole-component keyword matches
- `.conf` / `.ini` blocking
- case-insensitive matching
- false-positive paths from #15944
Plugin used for testing:
[orca_audit_numpy_config_repro.py](https://github.com/user-attachments/files/33143848/orca_audit_numpy_config_repro.py)
# Description
The default Orca Cloud API URL omits its scheme, so libcurl interprets
it as HTTP and follows the server redirect to HTTPS. Recent libcurl
versions intentionally do not forward the `Authorization` header across
protocol/port-changing redirects, causing Orca Cloud profile sync to
receive HTTP 401 `missing_authorization` responses and eventually log
the user out.
Use the HTTPS API URL directly. Besides restoring sync with current
libcurl versions, this improves security by preventing the bearer access
token from being sent in the initial unencrypted HTTP request.
# Screenshots/Recordings/Graphs
N/A — no UI changes.
## Tests
- `git diff --check`
- Confirmed with current libcurl that the scheme-less URL redirects and
loses the authorization header, while the direct HTTPS URL retains it
Merged by /bot merge on behalf of @peachismomo (id 52488812).
Grants: resources/profiles/OrcaFilamentLibrary/filament/Elegoo, resources/profiles/OrcaFilamentLibrary.json, resources/profiles/Elegoo, resources/profiles/Elegoo.json
Head: 00276bf8ee
* fix: include bundled UV binary for arm64
* fix: update unit test CI
* Install unit-test numpy only with the bundled uv
* Simplify the unit-test script's uv lookup
---------
Co-authored-by: SoftFever <103989404+SoftFever@users.noreply.github.com>
Co-authored-by: SoftFever <softfeverever@gmail.com>
* Add developer flag for printer agents
* Parse user print info on the UI thread to prevent heap corruption (#119)
get_user_print_info()'s HTTP fetch can run on a worker thread (e.g. BindJob),
but parse_user_print_info() mutates userMachineList (insert/erase/delete
MachineObject). on_machine_alive (SSDP) mutates the same maps on the UI thread
without locking, so parsing off-thread races the map and frees MachineObjects
out from under it -> heap corruption.
Keep all device-list mutation on the UI thread: parse inline when already on
the main thread, otherwise marshal via CallAfter so it stays serialized with
on_machine_alive.
* Prevent loss of user access code on LAN reselect
Keep user access code intact to maintain access rights even if
device slot is unpopulated, ensuring continuous connection
and status message reception.
* Harden send flow and separate upload failure recovery (#111)
* fix(send): harden FT send path + IP pre-flight UX
* Remove early returns
* Working Moonraker and Qidi printer agent transport (#104)
Folds the Qidi AMS box-mapping print
overrides (apply_box_mapping +
start_* wrappers) that the transport
fix builds on.
* Add support for runtime error status in plugins
Distinguish a loaded plugin whose
capability errored (RuntimeError,
warn-styled, stays checked) from a
load-time Error. Status now derives
via resolve_plugin_status(); enum
ordinal keeps dialog sort priority.
Unloading clears stale errors.
* Resolve duplicate agent ID conflicts
Reject a printer-agent capability
whose agent ID is already owned by
another capability or built-in:
flag the plugin error, disable the
capability, and warn the user
instead of silently ignoring it.
* fix: checkbox should depend on plugin is_loaded status
* Replace fake-enum printer agent dropdown (#121)
A dedicated PrinterAgentChoice field
reads rows straight from the live
agent registry and stores the agent
id string, replacing the fake-coEnum
index mapping. The field moves to
TabPrinter and registers with the
searcher so UnsavedChanges renders
it; the PhysicalPrinterDialog copy
and its update hook are removed
(#125). switch_printer_agent now
resolves ids via
resolve_printer_agent_id.
* Reset device selection on agent swap or unload (#124)
set_live_printer_agent centralizes
the swap: deselect the machine,
clear stale sidebar state and the
previous agent's Other Devices, then
install the new agent (or null when
its provider vanished). Plugin
load/unload callbacks refresh the
dropdown and re-run agent selection.
load_last_machine no longer falls
back to the first available machine.
* Gate agent mode behind use_printer_agents toggle
Replace per-printer auto-activation
(is_current_printer_agent_plugin)
with a global experimental AppConfig
toggle, default off: legacy
print-host behavior is unchanged
until the user opts in. The toggle
drives device-tab routing, print
button defaults, connect-button
visibility and sidebar layout, and
dedups machine-select dialog opens.
* Track BBLPrinterAgentPlugin.py
* Add printer-agent and plugin status tests
Ports the agent lifecycle, duplicate
agent-id, built-in-id clash and
status-resolution tests. The loader
runs on a detached worker thread, so
the lifecycle tests live in their own
executable. Tests install the
production unload-side registry
wiring themselves (no GUI in the
test binary) and register agents
manually so concurrent loads stay
deterministic.
* fix: pin HTTP to prevent connection refusal
Set `use_ssl` to false to ensure Moonraker
connectivity, as the service uses HTTP rather
than HTTPS, preventing connection issues. Initialize
device info early for reliable name resolution.
* Bring Moonraker device panel to feature parity
The monitor panel showed wrong or missing
data for Moonraker printers, and its
controls did nothing.
Push payload now carries layer number and
total layers. Remaining time replaces the
wrong total_duration - print_duration
formula. The chamber light toggle maps to
Klipper SET_PIN / SET_LED, and pause,
resume and stop post to
/printer/print/{action}. Task thumbnails
resolve via /server/files/thumbnails onto
a new MachineObject thumbnail url.
Filament sync switches to pull mode so the
agent is queried on demand.
Not compiled or run.
* Stop blocking print on unreported nozzle data
* fix: make Klipper macro lamp control reliable
* Surface Moonraker webcams and gate unrunnable controls
* Keep Bambu AMS dialect out of the agent waist
M620 is Bambu firmware dialect, not a
neutral command. Composing it in
MachineObject let non-Bambu agents
(Moonraker/Klipper) forward it and
report success on firmware that
cannot run it.
Agents now own the dialect: the
default refusal on IPrinterAgent
returns not-supported so the UI
can say so; BBLPrinterAgent keeps
the byte-identical composition.
* Fix multi-color filament logic
Reuse color decoding across functions to improve
code readability and maintain consistency in
multi-color filament handling.
* Move Moonraker commands off the UI thread
Pause/resume/stop, g-code sends, temps, and
light ran synchronous HTTP on the UI thread,
freezing the app up to 10s per click on slow
or unreachable printers.
Run them on a single agent-owned FIFO worker
so g-code ordering is preserved, while command
translation stays synchronous so unsupported-
command dialogs still work.
Add a pending-disabled state to the pause,
resume, and abort buttons for Moonraker-family
printers: the icon only flips once the
WebSocket reports the real state, which also
rules out double-click races.
* Show Snapmaker U1 camera in Device tab
The U1 exposes no /server/webcams/list entry;
its camera only captures after an explicit
camera.start_monitor RPC, which the Moonraker
websocket executes unauthenticated but only
answers over MQTT - so the call is fire and
forget.
Start the camera when the camera view is
shown and renew every 300 s: the printer
retires the capture task at ~362 s and
stop_monitor is accepted but ineffective,
so teardown is simply to stop renewing.
Frames land in monitor.jpg as still JPEGs
(~2 fps at interval 0), so the webview loads
a local HTML wrapper that repolls with a
cache buster.
* fix: start stream when camera URL changes
* fix: stop Qidi slot parse throwing on null
* Keep printer-agent progress in sync
Keep the shared task progress aligned with agent
reports that lack Bambu cloud task identity.
Release the lazily allocated task during reset to
avoid leaks when machine objects reconnect.
* docs: document the printer-agent subsystem
* fix: merge access codes into one
* Reconcile implementation split with PR tip
* feat: abstract remaining gcode commands in devicemanager
* refactor: abstract bambu specific protocol to printer agent
* refactor: push bbl workflows to bbl printer agent
* remove unused
* fix: default impl
* fix callback error
* fix: remove redundant cache
* specify api for getting file transfer url
* revert file transfer abstraction
* fix: ams filament mapping workflow
* feat: update qidi to use subscription based filament sync mode
* fix: resolve stubgen byte header conflict
* fix: ams sync info and periodic ams sync via subscription workflow
* fix: skip filament sync dialog if filamentSyncMode is none
* feat: parse nozzle information for qidi and moonraker printer agents
* fix: extend access code requirements t 0, 8 or more characters.
* remove irrelevant docs
* fix: remove heavy includes from IPrinterAgent
* fix: defer filesystem and camera abstractions
* fix: remote do_fetch_filament_info from tests
* cleanup moonraker and snapmaker printer agents
* fix: access codes regression
* fix: tests
* fix: printer agent switching on preset change
* fix: remove unused variable
* fix: snapmaker U1 SelectMachineDialog blocking print
* fix: merge artifact
* fix: clear up some unrelated changes
* feat: connect to cloud printer and monitor
* feat: connect to cloud printer and monitor
* feat: generic camera stream support for http snapshot and rtsp
* fix: build & access code UI
* feat: generic camera stream support for http snapshot and rtsp
* fix: build & access code UI
* feat: connect to cloud printer and monitor
* feat: connect to cloud printer and monitor
* fix: build errors
* feat: camera via webrtc
* fix: build
* fix: cmake
* feat: remove frame assembler and change config to set protocol
* fix: orcaprinteragent refactor
* fix: LAN paths and camera stream
* feat: use ffmpeg to render http camera stream
* fix: make model_id/dev_type optional instead of blocking
* fix: connect via ip dialog
* feat: LAN impl for Orca Printer Agent
* fix: model_id resolution method for non bambu printers
* fix: ffmpeg http camera stream jittering due to incomplete frames
* fix: revert sdcard check
* feat: check printer storage status before sending
* fix: moonraker printer agent hang on printer power cut
* fix: shim layer for any compatibiliity changes
* fix: cloud printers were using the wrong MQTT endpoint
* feat: cloud download via HTTP
* temp: doc for intended change
* fix: warnings
* fix: warnings
* fix: camera auto-play on startup
* fix: split infra from impl
* fix: uninitialized ams state blocking print
* Fixes nullptr deref
* Log first before std::move
* fix: printer agent virutal optional functions
* fix: parameterize orcaslicer_copy_test_dlls() for printer_agent_plugin_tests
* Revert "fix: parameterize orcaslicer_copy_test_dlls() for printer_agent_plugin_tests"
This reverts commit 2f566e3779.
* Guard libdatachannel. Remove unused code
* fix: unit tests & unused variables
* fix(ci): deps build order for datachannel
* Resolve printer agent first before getting cloud printer agent
* fix(ci): set depends openssl
* fix: re-include apply header guarded by ifdef __APPLE__
* fix(ci): add libdatachannel to flatpak manifest
* fix: add internal_developer_mode chekc back to MediaPlayCtrl::load()
* fix: invoke js clearInterval on WebMediaController::stop
* fix: change rtc log level
* fix: inject provider, agent id and generation to get_user_print_info to ensure correct metadata
* fix: revert moonraker specific behavior
* fix: remove stale comment
* fix: use ORCA_CLOUD_PROVIDER instead of hardcoded string
* fix: remove hardcoded ICE servers
* feat: enable https camera stream mode
* fix: move non-mandatory printer agent function stubs to IPrinterAgent
* fix: dedupe compatible printer type check
* fix: stop the correct media controller
* fix: scope get_my_machine_list to printers listed under the current printer agent
* fix: move printer agent plugin tests into test_plugin_lifecycle.cpp
* fix: always build bundled DataChannel dep
* fix: disable unused DataChannel media support
* revert: filament sync work
* fix: wrap command_* with small wrapper
* fix: regression bug, connecting to bambu needs bblp username
* fix: default impl for vendor agnostic gcode commansd
* refactor: media controller playback routing and ownership
* fix: bump libdatachannel ver & update flatpak to use tar instead
* fix: stop flatpak DataChannel build from re-cloning over the sandboxed network
* fix: update windows ffmpeg prebuild
* fix: update printer agent plugin API
* fix: shift camera signaling channel to network agent
* fix: follow external-packages for flatpak libdatachannel deps & add flatpak path to use source_dir
* feat: add printer-agent.md doc to HLSD
* fix: guard DeviceManager command dispatch when no printer agent is bound
* fix: port BBL implementations from #15711
* refactor: connect_printer api and dialog
* fix(tests): make omitted printer agent operations answer like a missing agent
* fix: preserve printer agent defaults in PrinterAgentPluginCapabilityTrampoline
* test: cover printer agent default command dispatch
* fix: validate windows FFmpeg avformat library
* feat: extend optional printer model warnings to calibration & ams workflows
* fix: handle malformed printer progress values safely
* fix: clear webview document on stop
* chore: reduce diagnostic logging level to trace
* refactor: centralize printer compatibility checks
* tests: add device manager integration coverage
* tests: cover WebMediaController lifecycle with wxWebView stub
* fix: make integration tests headless
* refactor: collapse command_ams_refresh_rfid and command_ams_refresh_rfid2
* refactor: make printer connection SSL agent-specific
* fix: persist input printer host and port
* fix: use correct device id for Moonraker connections
* fix: make moonraker gcode commands asynchronous
* fix: preserve moonraker device names
* fix: add include for non BBL_RELEASE_TO_PUBLIC path in BBLPrinterAgent
---------
Co-authored-by: Andrew <159703254+andrewsoonqn@users.noreply.github.com>
Co-authored-by: SoftFever <softfeverever@gmail.com>
Co-authored-by: Lam Wei Lun <weilun.lam@gmail.com>
Merged by /bot merge on behalf of @peachismomo (id 52488812).
Grants: resources/profiles/OrcaFilamentLibrary/filament/Elegoo, resources/profiles/OrcaFilamentLibrary.json, resources/profiles/Elegoo, resources/profiles/Elegoo.json
Head: ff6a2f2056
# Description
<!--
> Please provide a summary of the changes made in this PR. Include
details such as:
> * What issue does this PR address or fix?
> * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be
considered?
-->
This PR re-orders the OFL OTA auto-publish workflow by using successful
cron runs as checkpoints, marking and waiting for every dispatched
profile publisher to finish, and clearing the pending queue once
centrally only after all publishers succeed.
# Screenshots/Recordings/Graphs
<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->
## Tests
<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
Merged by /bot merge on behalf of @peachismomo (id 52488812).
Grants: resources/profiles/OrcaFilamentLibrary/filament/Elegoo, resources/profiles/OrcaFilamentLibrary.json, resources/profiles/Elegoo, resources/profiles/Elegoo.json
Head: d4a18c633e
# Description
<!--
> Please provide a summary of the changes made in this PR. Include
details such as:
> * What issue does this PR address or fix?
> * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be
considered?
-->
Avoid calling Print::output_filename() when a slice is canceled or
fails, since unresolved filename placeholders can throw before G-code
export completes.
Instead, we should use the model name in ctx.name and the stable model
ID in ctx.id, consistently across slice and G-code export events.
# Screenshots/Recordings/Graphs
<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->
## Tests
<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
Fix#15885
# Description
<!--
> Please provide a summary of the changes made in this PR. Include
details such as:
> * What issue does this PR address or fix?
> * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be
considered?
-->
The OFL OTA workflow sent an ISO-8601 timestamp to the pending-clear
endpoint, which only accepts Unix epoch seconds. This caused the
scheduled workflow to fail with HTTP 400.
Use `data -u +%s` so that request matches the endpoint contract.
# Screenshots/Recordings/Graphs
<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->
## Tests
<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
# Description
<!--
> Please provide a summary of the changes made in this PR. Include
details such as:
> * What issue does this PR address or fix?
> * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be
considered?
-->
The previous implementation checks against the last successful
`post_merge_profiles` which can trigger when a normal OTA update for
non-OFL profiles are made. This causes the check to fail when OFL
changes are made before other regular profile changes are made in
`resources/profiles/<vendor>`
# Screenshots/Recordings/Graphs
<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->
## Tests
<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
Merged by /bot merge on behalf of @peachismomo (id 52488812).
Grants: resources/profiles/OrcaFilamentLibrary/filament/Elegoo, resources/profiles/OrcaFilamentLibrary.json, resources/profiles/Elegoo, resources/profiles/Elegoo.json
Head: b73e9df4f4
# Description
<!--
> Please provide a summary of the changes made in this PR. Include
details such as:
> * What issue does this PR address or fix?
> * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be
considered?
-->
- `OrcaFilamentLibrary` (OFL) has no `FOLDER_MERGERS` delegation and
changes far more often than other vendors, so it can't go through the
existing merge-triggered, human-published OTA flow.
`post_merge_profiles.yml` gains an explicit `vendor` + `auto_publish`
`workflow_dispatch` path that bypasses the `FOLDER_MERGERS` check and
calls the OTA auto-publish API directly, making the update live with no
human step.
- `ofl-ota-cronjob.yml` drives that path daily across `main` and every
`release/vX.Y.Z` branch, checkpointed against
`post_merge_profiles.yml`'s own per-branch run history so a failed
publish is retried rather than silently dropped.
- Fixes a pre-existing bug in `post_merge_profiles.yml`: a single vendor
with no `FOLDER_MERGERS` grant in a push used to zero out the *entire*
vendor batch, silently dropping other, properly-authorized vendors'
publishes too. It now drops only the ungranted vendor, with a warning.
## Notes
Once v2.5.0 stable is released, we need to remove branch checking
against main in both these workflows.
# Screenshots/Recordings/Graphs
<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->
## Tests
<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
# Description
This PR introduces lifecycle events to the plugin API.
For all plugin capabilities, you can define a `on_lifecycle_event`
function in the plugin that takes in a event enum and a small payload
for some generic information on the lifecycle event.
The idea is to keep the payload generic and small, and if you want to
get more information, you should invoke other more targeted APIs to get
more information.
For example, lets say you are keeping track of the the `ObjectAdded*`
event hook for model transformation, addition or deletion. The payload
would tell you the name of the model, and you should use a targeted API
such as `orca.host.plater().model()` to get more information on the
model. This is the overall design principle of the API.
Currently the lifecycle events are the following:
```cpp
enum class LifecycleEvent {
// Project (3mf)
NewProject,
ProjectOpened,
ProjectBeforeSave,
ProjectAfterSave,
ProjectClosed,
ProjectDirtyChanged,
// Slicing pipeline
SliceStarted,
SliceGeometryFinished,
GCodeExportStarted,
GCodeExportFinished,
SlicingJobComplete,
// Plate/model editing
ObjectAdded,
ObjectDeleted,
ObjectTransformed,
ObjectChanged,
ObjectRenamed,
PlateCreated,
PlateDeleted,
PlateSelected,
PlateRenamed,
// Preset
PresetSelected,
PresetSaved,
// Printer/device
PrintStateChanged,
DeviceOnlineChanged,
DeviceDiscovered,
DeviceSelected,
DeviceConnected,
DeviceDisconnected,
UploadStarted,
UploadFinished,
// Print/send jobs
PrintJobStarted,
PrintJobFinished,
SendJobStarted,
SendJobFinished,
};
```
This is an initial draft and lifecycle events can be included later on.
[orca_telegram_notifier_plugin_any.py](https://github.com/user-attachments/files/31220973/orca_telegram_notifier_plugin_any.py)
If you're familiar with telegram bots, after you install the telegram
bot, in the config of this plugin, you can enter the Bot ID and the Chat
ID with said bot.
# Screenshots/Recordings/Graphs
<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->
## Tests
<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->
For this plugin, I am testing it with a telegram bot that sends me a
message on lifecycle event.
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
# Description
<!--
> Please provide a summary of the changes made in this PR. Include
details such as:
> * What issue does this PR address or fix?
> * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be
considered?
-->
A Python printer agent plugin could take the host down, and one of its
operations could never report its result. This PR fixes both in
`PrinterAgentPluginCapabilityTrampoline.hpp`.
## Changes
### A faulty printer agent no longer throws into the GUI
`IPrinterAgent` reports failure through return values, and none of its
callers catch. A Python `raise`, a missing override or a wrongly typed
return from a printer agent plugin therefore escaped the trampoline as a
C++ exception.
Every trampoline operation now catches, logs `Printer agent plugin
'<key>': <operation> failed: <error>`, and answers with what
`NetworkAgent` returns when no printer agent is set. `BBLPrinterAgent`
returns the same values when the Bambu plug-in is unavailable:
- `-1` for every `int` status code
- `false` for `start_discovery` and `fetch_filament_info`
- `""` for `get_user_selected_machine`
- an empty `AgentInfo` for `get_agent_info` (registration already
rejects an empty agent ID)
- `FilamentSyncMode::none` for `get_filament_sync_mode`
`ORCA_PY_AGENT_OVERRIDE(ret, name, ...)` derives the fallback from the
return type through `printer_agent_failure<ret>()`, so the call sites
carry no fallback values of their own.
An exception is the safety net for plugin bugs, not an error channel. A
plugin reports an expected failure by returning a code, as the Bambu
plug-in does. A raise is logged as a failure and collapses to the
generic `-1`, so the GUI shows the generic message instead of the
specific one (`-18` cancelled, `-4020` FTP upload failed, …).
### `bind_detect` results now reach the host
`detect` is an out-parameter (`detectResult&`). pybind11 casts a
reference argument to an override with a copy, so a plugin that filled
in `detect` wrote to a throwaway object and the host always saw an empty
`detectResult`. It is now passed so that Python edits the caller's
struct. Plugins see the same `DetectResult` argument as before.
## TODO
- Expose the `BAMBU_NETWORK_*` return codes to Python (the
`orca.printer_agent` binding and the generated stub from
`scripts/generate_orca_python_stubs.py`). Plugins can already return
them, but only as hard-coded numbers.
# Screenshots/Recordings/Graphs
<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->
## Tests
<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->
- New `tests/slic3rutils/test_plugin_printer_agent.cpp`: an agent whose
operations raise, one that omits them, and one that returns the wrong
type all answer like a missing agent, and the interpreter stays usable.
A working agent's answers reach the host unchanged, including
`request_bind_ticket`'s out-param and the fields a plugin writes into
`bind_detect`'s `detect`.
- The `bind_detect` check failed before the fix (`"" == "192.168.0.2"`)
and passes after.
- `slic3rutils` passes under `ctest` (144/144); full Release build clean
on Linux.
- End to end on Linux with a test plugin whose chosen operations raise
(`start_discovery`, `get_filament_sync_mode`, `disconnect_printer`):
selecting the plugin's agent in the printer preset and switching back
logged each raise as a `Printer agent plugin '…': <operation> failed`
line, and the app kept running and closed cleanly (exit 0). Without the
guard, the first raise (`start_discovery`, on selecting the agent) ended
the app with `Uncaught exception` and SIGABRT (exit 134); that run used
a build whose printer-agent files are identical to `main`.
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
# Description
<!--
> Please provide a summary of the changes made in this PR. Include
details such as:
> * What issue does this PR address or fix?
> * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be
considered?
-->
When a PR is merged using the bot with `/bot merge`, it doesn't invoke
`post_merge_profiles.yml` because post_merge_profiles.yml only starts on
a push or manual dispatch.
# Screenshots/Recordings/Graphs
<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->
## Tests
<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
# Description
<!--
> Please provide a summary of the changes made in this PR. Include
details such as:
> * What issue does this PR address or fix?
> * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be
considered?
-->
On windows, after installing and loading a plugin, if you try to
unsubscribe from a loaded plugin, and on refresh, it will be an orphaned
plugin.
# Screenshots/Recordings/Graphs
<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->
On unsubscribing from a loaded cloud plugin
<img width="1418" height="862" alt="image"
src="https://github.com/user-attachments/assets/9ba8353c-1645-4b21-86ff-2ed235f4d259"
/>
On plugin refresh
<img width="1418" height="862" alt="image"
src="https://github.com/user-attachments/assets/fd58c144-7970-4448-ba3b-e72e52980467"
/>
## Tests
<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
# Description
Adds the CI half of the profile OTA pipeline: a push-triggered workflow
that
rebuilds a vendor's binary preset cache (`<vendor>.opc`) whenever its
profile
changes on `main` / `release/*`, and publishes it as a versioned release
asset
for OrcaCloud's OTA Manager to pick up.
### `.github/workflows/post_merge_profiles.yml` (new)
Push-triggered counterpart to `check_profiles.yml` (which only gates
PRs):
- Diffs the push to find which vendors under `resources/profiles/**`
changed.
- Reads the Orca version from `version.inc` and each vendor's 4-part
`version`
from `resources/profiles/<vendor>.json` (fails the run if it isn't
`A.B.C.D`).
- Downloads the prebuilt `generate_system_cache` from this repo's
`nightly-builds` release and builds one `<vendor>.opc` per changed
vendor.
- Packages each as
`<orca_ver>_<vendor>_<profile_version>_<UTCyyyymmddHHMM>.zip` (zip root
`<vendor>.opc`) — the asset-name contract OrcaCloud's release scanner
expects.
- Uploads them to a per-Orca-version release on the profiles repo via a
scoped
GitHub App token.
It stops there: no changelog, no R2, no OTA webhook — a maintainer still
publishes from the OTA Manager. Job is guarded to
`OrcaSlicer/OrcaSlicer`;
workflow permissions are `contents: read` (the cross-repo write uses the
App
token only).
### `.github/workflows/build_orca.yml`
Two steps on the Linux leg: upload `generate_system_cache` as a CI
artifact,
and (on `main`) deploy it to the `nightly-builds` release as
`generate_system_cache_Linux_Ubuntu2404_nightly` so the workflow above
has a
tool to download. `.opc` is 64-bit little-endian and
platform-independent, so
only the Linux binary is shipped.
### `src/dev-utils/generate_system_cache.cpp`
New `-v` / `--vendor` option to generate the cache for a single vendor
(plus the
always-loaded Orca filament library) instead of all vendors, and an
error if the
named vendor produced no `.opc` (catches typos). Reuses
`PresetBundle::set_vendor_to_validate()` from #14217.
## Operational prerequisites
- Repo secrets `PROFILES_APP_ID` / `PROFILES_APP_PRIVATE_KEY` for a
GitHub App
with `contents: write` on the target profiles repo.
- `env.PROFILES_OWNER` / `env.PROFILES_REPO` in
`post_merge_profiles.yml` must
point at the production profiles repo OrcaCloud reads.
- `generate_system_cache_Linux_Ubuntu2404_nightly` only appears after
the first
post-merge nightly `build_orca` run; a profile-only push before then
fails at
the download step.
## Screenshots/Recordings/Graphs
n/a — CI only.
## Tests
Exercised end-to-end in a staging environment: per-vendor `.opc` zips
published
in the expected `<orca_ver>_<vendor>_<profile_version>_<timestamp>.zip`
layout,
and `generate_system_cache -v <vendor>` confirmed to emit only that
vendor's
`.opc`.
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
# Description
<!--
> Please provide a summary of the changes made in this PR. Include
details such as:
> * What issue does this PR address or fix?
> * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be
considered?
-->
Adds a really basic API to push notifications to the plater.
Plugin used in demo:
[plater_notification.py](https://github.com/user-attachments/files/31293074/plater_notification.py)
# Screenshots/Recordings/Graphs
<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->
<img width="2172" height="1241" alt="image"
src="https://github.com/user-attachments/assets/540319ca-a11a-4b48-9b80-82fb6b0849d9"
/>
## Tests
<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
# Description
<!--
> Please provide a summary of the changes made in this PR. Include
details such as:
> * What issue does this PR address or fix?
> * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be
considered?
-->
#15416 introduced a bug that caused system profiles to be copied over to
the system folder in the roaming folder on every startup.
# Screenshots/Recordings/Graphs
<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->
## Tests
<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
# Description
<!--
> Please provide a summary of the changes made in this PR. Include
details such as:
> * What issue does this PR address or fix?
> * What new features or enhancements does this PR introduce?
> * Are there any breaking changes or dependencies that need to be
considered?
-->
Addition to #14217 to support OTA updates when the zip content is an OPC
file.
# Screenshots/Recordings/Graphs
<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->
## Tests
<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
# Description
Under `core.autocrlf=input`, a Windows dependency build fails while
building CPython:
```
The system cannot find the batch label specified - begin_search
Cannot locate python.exe on PATH or as PYTHON variable
error MSB8066: ... exited with code 3
```
`git apply` inherits the caller's git configuration, so it rewrites the
patched `PCbuild/find_python.bat` to LF, and `cmd.exe` cannot resolve
`goto` labels in an LF batch file. `git init` already runs in the
extracted source, so setting `core.autocrlf` on that repository fixes it
and leaves the shared `PATCH_CMD` alone.
Only python3 is affected, its patch being the only one under `deps/`
that touches a `.bat`. `core.autocrlf=true` (the Git for Windows
default) and `false`/unset were never affected.
If a dependency build later fails with `patch does not apply`, delete
`deps/build` and rebuild. `git apply` is not idempotent, and that is
independent of this change.
## Tests
Visual Studio 2026 (18.6.3), `core.autocrlf=input`, built from an empty
`deps/build-dbg`:
| `deps debug` on | `find_python.bat` | CPython |
|---|---|---|
| `upstream/main` | 0 CRLF / 95 LF | fails at `begin_search` |
| this branch | 94 CRLF / 1 LF | builds |
It then stops at the debug staging step, a separate bug fixed by #15353;
with both applied it installs `libpython`. I hit this on a debug build,
but the patch step has no Debug/Release conditional.
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
# Description
This is an initial draft of the plugin audit workflow.
It focuses on the user experience and developer-facing permission
workflow. It does not yet include the complete implementation of every
operation that should be audited, such as the full filesystem,
networking, and process-spawning event coverage.
## User workflow
When a plugin is loaded:
1. The plugin’s register_capabilities() function is executed.
2. The plugin declares the permissions it requires.
3. OrcaSlicer displays a permission dialog listing the requested
resources.
4. If the user grants access:
- The permission is persisted in the plugin’s .install_state.json.
- Capability registration continues.
- The plugin is materialized and loaded.
5. If the user denies access:
- Plugin loading fails before capabilities are materialized.
- on_load() is not called.
- The plugin’s install state is marked with "enabled": false to prevent
repeated automatic load attempts.
At runtime, if a plugin accesses a resource that was not approved during
loading, the audit hook displays another permission dialog. For
filesystem requests, the dialog identifies the requested filepath.
- Granting access persists the permission and allows the operation.
- Denying access raises a Python PermissionError.
- The error propagates to the host, which records the failure and
unloads the plugin.
Host-side traceback logging is performed outside the plugin audit
context so that logging does not generate additional permission dialogs.
## Developer-facing API
Plugins can declare filesystem read permissions through the new API:
```python
import orca
AUDIT_PATH = __file__
@orca.plugin
class ExamplePackage(orca.base):
def register_capabilities(self):
orca.request_permissions(
fs_read=[AUDIT_PATH],
)
orca.register_capability(ExampleCapability)
```
orca.request_permissions() must be called from register_capabilities()
while the plugin is being loaded.
Currently supported permission:
orca.request_permissions(fs_read=[...])
The paths should be explicit filesystem paths that the plugin intends to
read. The host deduplicates repeated paths, presents the request after
registration completes, and persists granted paths in the plugin
install-state sidecar. This API is still experimental, and is by no
means the final implementation.
Support for additional permission categories, including filesystem write
access, networking, and process spawning, is reserved for subsequent
work.
# Screenshots/Recordings/Graphs
<!--
> Please attach relevant screenshots to showcase the UI changes.
> Please attach images that can help explain the changes.
-->
<img width="869" height="799" alt="image"
src="https://github.com/user-attachments/assets/8a5903cc-0cbb-45a8-b88a-706d6cba790f"
/>
## Tests
<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)