mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-18 03:54:17 +02:00
fix/skip-objects
10
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
fdd6ec416f |
fix(slicer): classify filament profiles by their real printer scope, not just their name (#2628 follow-up)
Slicing for a P2S failed with "filament preset Bambu PLA Basic @BBL X1C 0.2 nozzle (slot 1) is not compatible with printer Bambu Lab P2S 0.4 nozzle" — naming a profile shown nowhere in the dialog. The picked profile was "Overture PLA Matte @0.2", whose inheritance chain roots in that X1C profile. The dialog classifies a profile by its compatible_printers list and falls back to reading the printer out of its name. That name carries no model, and the list — present on the imported copy — is not shipped by every source: Bambu Cloud omits it deliberately (rate limits), and Orca Cloud shipped it but Bambuddy only mined filament type and colour from the same content. Orca Cloud entries now carry their own compatible_printers, and the existing same-name enrichment bridge carries the list onto entries that lack one, in both directions between the cloud tiers. A bare "@<size>" name tag is read as a nozzle size as a last resort: it can rule a printer out but never rules one in, and implausible values are ignored rather than guessed at. |
||
|
|
1c42a9f1fd |
remove(slicer): drop bundle import; fix cloud preset type/from for CLI (#1712)
Bundle import never delivered what it implied: BambuStudio's .bbscfg export
strips system processes/filaments, so importing a bundle left users without
process presets and slicing fell back to embedded settings on STL. Bundle
mode also hid the standard tier behind a constrained dropdown, the actual
trap reported here.
Removed end-to-end:
- backend: POST/GET/DELETE /slicer/bundles*, SliceRequest.bundle,
SliceBundleSpec, dispatch fork in library.py, bundle-context params on
the filament-requirements endpoints, bundle-fingerprint cache key in
slice_preview.py, SlicerApiService.{import,list,get,delete}_bundle and
slice_with_bundle, BundleSummary / BundleNotFoundError.
- frontend: BundlePicker + BundleStringDropdown, isBundleMode + every
branch, bundle state/queries/dispatch in SliceModal.tsx, SlicerBundle /
SliceBundleSpec types, three bundle API methods. buildCompatibilityIndex
loses its bundle path; presetCompatibility keeps compatible_printers
plus the @BBL fallback.
- SlicerBundlesPanel turns into a permanent static notice explaining the
removal, alternative import paths, and the new slice-time lookup order
(Imported > Orca Cloud > Bambu Cloud > Standard sidecar fallback).
- i18n: slicerBundlesRemoved.{title,description,alternatives,lookupOrder}
translated across all 11 locales; slice.bundle*, slicerBundles.* keys
removed.
Fixed (surfaced by removing bundle mode):
- _resolve_cloud and _resolve_orca_cloud now force type per slot and pin
from: "system" on the payload before json.dumps. Bambu Cloud ships
type as "printer"/"print" and routinely empty `from`; the BS CLI's
--load-settings parser rejects both with return -5 / "input preset
file invalid". Standard tier already did this; cloud paths now match.
|
||
|
|
d459b6eabb |
fix(slicer): preset visibility + lookup precedence + signed-out banner + AMS slot badges (#1712)
Four #1712 issues from the 2026-06-04 Orca Cloud integration: (1) Tier order put Orca Cloud above everything across SliceModal, auto-pick scoring, dropdown groups, the AMS slot picker, and the backend precedence. Bambu-Cloud-only users saw their profiles deprioritised behind an empty Orca tier. (2) Cross-tier dedup hid a same-named preset in all but the highest- priority tier. A user with both a local-imported and an Orca-synced "Bambu PLA Basic" couldn't see the Orca copy as a picker option. (3) CloudStatusBanner nagged signed-out users with a permanent "Sign in to Orca Cloud" line at the top of every slice -- even after explicit logout. Bambu Cloud had the symmetric problem. (4) ConfigureAmsSlotModal source badges were inconsistent: Orca rows showed only "Custom" (no source identity), Bambu Cloud built-in rows had no badge at all, and the orthogonal isUser-driven "Custom" badge collided with the source badge for cloud user presets. Order is local > orca_cloud > cloud > standard everywhere it lives (SliceModal SLICE_MODAL_TIER_ORDER + TIER_BONUS + dropdown tier list, ConfigureAmsSlotModal sourceOrder, and backend precedence). The order drives auto-pick + visual group rendering; it does NOT hide profiles. _dedupe_by_name replaced with _enrich_cloud_metadata: every tier returns its full list across all three slots (printer / process / filament). The function still backfills Bambu Cloud filament metadata from same-named local / orca_cloud / standard entries so cloud filaments score in pickFilamentForSlot. CloudStatusBanner silently no-ops on not_authenticated for both clouds; expired / unreachable still surface. The not_authenticated i18n keys stay in the locale files dormant. ConfigureAmsSlotModal: one source badge per row, one colour per source (green Local / purple Orca Cloud / bambu-blue Bambu Cloud / amber Built-in). The legacy isUser-driven "Custom" badge is gone; every row identifies its tier consistently. |
||
|
|
18d534c945 |
feat(orca-cloud): integrate Orca Cloud profile sync across UI, slicer and SpoolBuddy
Reads, lists, and slices with profiles from a user's Orca Cloud account (OrcaSlicer 2.4.0-alpha's Supabase-backed sync) alongside the existing Bambu Cloud integration. Four sign-in providers (Google / Apple / GitHub / email+password); password defaults. Paste-flow PKCE because Orca's Supabase project only allowlists localhost redirect_to — open feature request at OrcaSlicer/OrcaSlicer#14028. Surfaces: - Profiles tab: new "Orca Cloud" tab next to "Bambu Cloud" with the same rich layout (search + 5 filter dropdowns + 3-column grouped grid + read-only detail modal) - SliceModal: 4-tier preset picker (orca_cloud > local > bambu cloud > standard); separate status banner per cloud; metadata-aware pre-pick scores Orca filaments above local (Orca's sync_pull returns full content inline so filament_type / filament_colour come for free, no per-setting fetch rate-limit dance) - ConfigureAmsSlotModal: orca_cloud as a new preset source (prefixed orca_<UUID> to match local_/builtin_); generic Bambu filament-ID derivation from parsed material (printer firmware can't grok Orca UUIDs); slot mapping persists preset_source='orca_cloud' - SpoolForm / SpoolBuddyWriteTagPage: Orca filaments merge into the cloud preset list via Promise.allSettled (OrcaProfileMeta is structurally identical to SlicerSetting) Backend: - services/orca_cloud.py: OrcaCloudService with PKCE / token exchange / single-use refresh rotation / get_user_info / list_profiles via the bare /sync/pull bootstrap path - routes/orca_cloud.py: 7 endpoints (auth/start, auth/finish, auth/password, status, logout, profiles, profiles/{id}); router-level _cloud_api_key_gate + per-route cloud_caller() so API-keyed callers (SpoolBuddy kiosk) properly resolve their owner User; just-in-time refresh with atomic persist-before-API-call - routes/slicer_presets.py: _fetch_orca_cloud_presets mirrors the Bambu Cloud fetcher (status vocabulary, 5min cache, permission shortcut); _dedupe_by_name extended to 4 tiers; UnifiedPresetsResponse gains orca_cloud + orca_cloud_status - services/preset_resolver.py: PresetRef.source extended with "orca_cloud"; _resolve_orca_cloud walks list + filters - 8 columns on users table for tokens (5 persistent) + transient PKCE handshake state with 10-min TTL (3); dialect-branched DATETIME / TIMESTAMP; auth-disabled mode falls back to Settings table - orca_cloud:auth permission folded into can_access_cloud API-key scope (same trust dimension) |
||
|
|
171848a0fc |
fix(slicer-presets): #1581 SliceModal refresh + invalidate on local-profile delete/import
Two-part fix for the reporter's "removed profiles still show on the slice
menu" symptom.
Local half (real bug). LocalProfilesView's import and delete mutations
invalidated ['localPresets'] (the management view's own query) but not
['slicerPresets'] (the SliceModal's unified preset query, staleTime 60s).
A freshly-deleted preset kept rendering in the slice dropdown until that
staleTime elapsed plus a refocus/remount. Both mutations now also call
queryClient.invalidateQueries({queryKey: ['slicerPresets']}).
Cloud half (opt-in cache bypass). _fetch_cloud_presets keeps a 5-minute
per-(user, token) in-process cache (slicer_presets.py:69, balances
"users see freshly-saved presets quickly" against "busy install doesn't
hit Bambu Cloud once per modal open"). Users delete cloud presets in
Bambu Studio / Bambu Handy, not in Bambuddy, so there's no event hook
to invalidate on. Rather than shorten the TTL globally, the listing
endpoint gains an opt-in ?refresh=true query param that bypasses both
the cloud cache AND the 1-hour bundled-preset cache for that one call;
the fresh result is still written back so subsequent normal callers
keep hitting the cache.
New SliceModal "Refresh" button. Lives in the preset section header
next to the cloud-status banner. Calls getSlicerPresets({refresh: true})
and writes the fresh slots into the ['slicerPresets'] cache via
queryClient.setQueryData so the spinner stops immediately rather than
triggering a second refetch. RefreshCw icon spins while in-flight;
disabled during slice enqueue to prevent double-fire.
|
||
|
|
3058c5789b |
fix(slice): @BBL name fallback for users without slicer bundles (#1325 follow-up)
The first cut of #1325 swapped a stale hardcoded model table for bundle-based compatibility matching: a cloud / standard process or filament preset was classified by consulting the user's uploaded Slicer Bundles (.bbscfg). That works perfectly when bundles cover every printer in the user's cloud catalogue, and silently no-ops otherwise - every cloud preset resolves to 'unknown', nothing moves into "Other printers", and the dropdowns look identical to the pre-fix state. The reporter saw exactly this on a clean install with no bundles uploaded. Restored BambuStudio's `@BBL <token>` name convention as a third tier below the bundle path, but driven by the canonical backend PRINTER_MODEL_MAP - exposed via a new GET /slicer/printer-models route - rather than a manually-maintained frontend table. The matcher inverts the registry into short-code -> printer-fragment ("X1C" -> "X1 Carbon"), normalises whitespace + case so "A1 mini" and "A1 Mini" compare equal, and falls back to raw-token compare for models not yet in the registry (so a future "Q1" matches without a code change). Adding a new Bambu model still touches exactly the one backend file already listed in the Bambu Model Codes registry. Tests: 2 new in test_slicer_presets.py (route returns the full PRINTER_MODEL_MAP, route returns a copy not the live dict); 11 new in slicerPrinterMatch.test.ts covering registry-driven X1C vs X1 Carbon, A1 vs A1 mini, H2D vs H2D Pro, P2S / H2C / H2S / X2D (which the original hardcoded list was missing), raw-token fallback, registry-not-loaded-yet degradation, and the precedence rules between compatible_printers / bundle / @BBL name. 38 slicer-presets + 36 slicerPrinterMatch + 34 SliceModal tests green; backend ruff clean; frontend build clean. |
||
|
|
7eba29624b |
feat(slicer): filter process & filament profiles by selected printer (issue #1325)
The Slice dialog listed every process / filament preset regardless of the chosen printer (#1325). Picking a printer profile now filters both dropdowns to compatible presets; presets resolving to a different Bambu model move into a trailing "Other printers" group. Matching uses the slicer's own compatible_printers list for imported (local) presets, and falls back to the "@BBL <model>" name suffix for cloud / standard presets where no compatibility metadata is available, so all three tiers are covered. Compatibility-unknown presets (custom or untagged) are never hidden. The pre-pick and printer-switch paths follow the same rule. - UnifiedPreset gains compatible_printers, exposed for the local tier - new frontend util slicerPrinterMatch.ts with the matching logic - slice.otherPrinters added across all 9 locales |
||
|
|
9cde2e37fd |
feat(slicer): log sidecar reject reason on bundle import failure (#1312)
The route mapped sidecar 4xx/5xx to HTTPException with detail but never logged it. Reporters seeing a 400 toast were giving us only the status code, not the reason, and the access-log line was all that landed in support bundles. Add WARNING-level logs on each error branch (400 SlicerInputError, 503 SlicerApiUnavailableError, 502 SlicerApiError) with the sidecar's own message + the filename / byte count / configured URL. Next reporter on this code path produces a support bundle that contains the answer. |
||
|
|
060ba509da |
feat(slicer): add /slicer/bundles routes for .bbscfg import + bundle slicing
Wires Bambuddy to the orca-slicer-api fork's bundle endpoints (shipped
in bambuddy/bundle-import). Users will eventually upload a BambuStudio
"Printer Preset Bundle" (.bbscfg) once per printer; subsequent slices
pick from the bundle by preset name instead of re-uploading the JSON
triplet every time.
Service layer:
- BundleSummary / BundleNotFoundError types
- import_bundle / list_bundles / get_bundle / delete_bundle methods
- slice_with_bundle: POST /slice with bundle id + per-category names
instead of attached profile JSONs
Routes (LIBRARY_UPLOAD perm gate):
- POST /api/v1/slicer/bundles
- GET /api/v1/slicer/bundles
- GET /api/v1/slicer/bundles/:id
- DELETE /api/v1/slicer/bundles/:id
All routes proxy via _resolve_slicer_api_url so they follow the user's
preferred_slicer setting (bambu_studio vs orcaslicer). Status-code
mapping treats sidecar 4xx as 400, BundleNotFoundError as 404,
unreachable as 503, and sidecar 5xx as 502.
|
||
|
|
61c15aac03 |
feat(slicer): unified Cloud/local/standard presets + harden 3MF profile path
UNIFIED PRESET LISTING (the main feature)
The initial slicer integration only saw DB-backed local imports — users
without imported profiles got an empty Slice modal even when their
Bambu Cloud account or the slicer sidecar carried perfectly usable
presets. The Slice modal now pulls from three tiers in priority order:
- cloud: user's own Bambu Cloud presets, fetched live.
- local: DB-backed imports.
- standard: slicer-bundled stock profiles via the sidecar's new
GET /profiles/bundled endpoint.
Listing endpoint: GET /api/v1/slicer/presets
- Name-based dedup, cloud > local > standard, within-tier order
preserved exactly. A preset that exists in multiple tiers only
renders in the highest-priority one.
- cloud_status (ok / not_authenticated / expired / unreachable)
drives a precise modal banner instead of an unexplained empty
list.
- Cloud branch: per-user cache, 5 min TTL, key
(user_id, sha256(token)[:16]) so logout/login or token rotation
auto-invalidates without callback wiring from the cloud-auth
routes.
- Bundled branch: global cache, 1 h TTL.
- Bundled URL respects preferred_slicer (bambu_studio vs orcaslicer)
so BambuStudio installs see the bambu sidecar's bundled list, not
OrcaSlicer's.
Slicing endpoint: POST /library/files/{id}/slice + /archives/{id}/slice
- Body now accepts source-aware {source, id} triplets per slot:
printer_preset: PresetRef
process_preset: PresetRef
filament_preset: PresetRef
- Legacy *_preset_id integer fields kept for backwards-compat. The
schema validator normalises bare ints into
PresetRef(source='local', id=str(int)) so the route handler only
deals with one shape.
New preset_resolver service fetches the JSON content per source:
- cloud: BambuCloudService.get_setting_detail(id), unwraps the
`setting` envelope (falls back to top-level for minor
shape variants).
- local: DB read with preset_type slot validation (existing path,
factored into the new helper).
- standard: minimal {name, inherits, from: "system"} stub — the
sidecar's profile-resolver flattens it against
BUNDLED_PROFILES_PATH/<category>/<name>.json with no
preset-content round-trip from Bambuddy.
PERMISSIONS
- Listing route gate: LIBRARY_UPLOAD (matches the slice action — any
user who can slice can populate the dropdowns).
- Cloud branch in BOTH the listing helper and the resolver checks
CLOUD_AUTH independently — a user with LIBRARY_UPLOAD but not
CLOUD_AUTH doesn't see the cloud tier (returns 403 if they try
to slice with a cloud preset) even if a leftover User.cloud_token
survived a permission revocation. Cloud listing path
short-circuits the token lookup entirely on the gate-fail branch.
FRONTEND — SliceModal
- Calls api.getSlicerPresets() instead of api.getLocalPresets().
- Dropdowns render <optgroup> per tier with localised section
labels (Cloud / Imported / Standard).
- Default selection follows cloud > local > standard priority on
first load (auto-pick fires once when the data arrives, manual
choices stick after that).
- Cloud-status banner renders three variants
(sign-in / expired / unreachable) only when status != 'ok'.
- Slice button submits source-aware refs; legacy integer payload
is preserved server-side for older clients.
3MF PROFILE-PATH HARDENING (shipped together because they touch the
same code paths)
(1) Strip widened. _strip_3mf_embedded_settings only removed
Metadata/project_settings.config. Real-world Bambu Studio /
OrcaSlicer 3MFs also carry model_settings.config, slice_info.config,
and cut_information.xml — any single leftover trips the CLI's
input validation and the slice falls back to embedded settings,
making the SliceModal's profile picker theatrical for 3MF inputs.
Now removes all four configs via a centralised
_STRIPPABLE_3MF_CONFIGS frozenset with per-file rationale;
geometry (3D/3dmodel.model), thumbnails, multi-part data
preserved.
(2) Sidecar 5xx error capture. slicer_api.py was reading only
`message` from sidecar 5xx responses and dropping `details`, so
every CLI failure surfaced as the unhelpful generic
"Failed to slice the model". New _format_sidecar_error helper
combines both fields, falls back to plain-text body for
non-JSON 5xx (nginx 502s, gateway timeouts), replaces the four
duplicated extraction blocks. Pairs with the orca-slicer-api
fork's bambuddy/profile-resolver branch which now emits
`details` on AppError responses (d9c6121) and captures CLI
stderr in the failure path (fb928c8).
CARE TAKEN — additive on existing surfaces
- main.py: +1 import, +1 router register
- slicer_api.py: +list_bundled_profiles, +_format_sidecar_error
(dedupes the 4 message-extraction blocks);
no existing method behaviour changed
- library.py: resolver swap inside _run_slicer_with_fallback,
user_id threaded through two callers,
strip widened
- schemas/slicer.py: PresetRef added, *_preset fields added,
legacy *_preset_id kept; validator normalises
- 4 new files: schema, route, resolver, tests
- No existing route URL changed, no existing field removed, no
behaviour change for clients still sending bare integer ids.
TESTS
- 17 unit tests for the listing endpoint helpers
- 11 unit tests for the source-aware resolver
- 6 schema tests for SliceRequest legacy + new shapes
- 3 unit tests for the new sidecar error-detail capture
- Strip integration test extended to assert all 4 configs go and
geometry stays
- 12 frontend tests for SliceModal covering tier-priority
auto-selection, <optgroup> grouping, fallback paths, source-aware
payload on submit, manual override across tiers, archive vs
library routing, error display, all three banner variants
Verified: 3394 backend + 1531 frontend tests pass, ruff clean,
frontend production build clean.
Pairs with three already-pushed commits on the orca-slicer-api fork's
bambuddy/profile-resolver branch:
- 5fd6bc6 feat(profiles): add GET /profiles/bundled
- d9c6121 fix(error): include causeMessage in JSON response as `details`
- fb928c8 fix(slicing): include CLI stdout/stderr in failure causeMessage
|