Commit Graph

140 Commits

Author SHA1 Message Date
ABDULLAH af07f4e0e5 Arabic interface language with right-to-left text (#3762) (#3768)
* claim: #3457

* Hebrew interface language with right-to-left text (#3457)

Adds a complete Hebrew catalog (assets/locales/he.json, original
translations) and registers `he`.

egui 0.36 shapes each font run with harfrust, so a run of Hebrew letters
is drawn right to left, but it places the runs of a line left to right in
stored order. The new `bidi` module runs the Unicode Bidirectional
Algorithm (unicode-bidi, MIT OR Apache-2.0) over each message of a
right-to-left catalog once, giving egui the runs in display order with
brackets mirrored and placeholders kept whole, while leaving each Hebrew
run's letters in reading order for the shaper. A test lays messages out
with a real Hebrew font and checks where the glyphs land.

Desktop builds append a system Hebrew font (Arial Hebrew / SF Hebrew,
Segoe UI / Arial, Noto Sans Hebrew / DejaVu Sans). Layout mirroring,
wrapped multi-line RTL paragraphs and a web Hebrew font are follow-ups.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Hebrew: translate the new Describe Command label; list he in the control protocol

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Hebrew: catch up with main's catalog and the new ribbon (#3457)

- Translate the 258 messages main added since the branch was cut, drop
  the 38 it removed (10 renamed ones keep their translation) and
  retranslate the two whose English changed (toolbar → application bar).
- The timeline title is ציר הזמן, matching the glossary.
- Ribbon buttons split their labels into two lines from the start of
  the string; Hebrew labels come in display order, so the first line
  showed the end of the phrase ("חדשה / סקיצה"). For right-to-left
  labels the first line now takes the words at the end of the string,
  and a shortened line loses characters, and shows its ellipsis, on the
  left. The word-boundary sweep checks Hebrew from the lines the galley
  is built from, since epaint's right-to-left rows carry zero-width
  glyphs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Hebrew: after rebasing onto main, load the Hebrew face with the cached system fonts

main now searches the system fallback faces once (SystemFonts, on a thread);
the Hebrew face joins that search with its coverage check. Drop the three
camera-animation messages main removed (#4296) from the Hebrew catalog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Hebrew: translate the messages main added after the catch-up (#3457)

Translates the messages main added since the last catch-up: the history
bar's buttons and name toggles, the 3D mouse driver and axis mapping, the
thread size columns, the File view (home page), the redesigned Preferences, the new issue report
dialog, free orbit and the assistant's setup card. Drops the one message
main removed. The catalog has every English message again, so the
complete-catalog checks pass for he.

* Arabic interface language (right-to-left, on the Hebrew bidi path)

Adds an original Arabic translation of the whole English catalog
(assets/locales/ar.json, every message) and registers it. `ar` joins the
complete catalogs, so a message added to en.json later fails the build
until it is translated. It goes through the right-to-left path of #3458
unchanged: crate::bidi puts each message in display order and leaves
every Arabic word's letters in reading order for harfrust, which joins
them with the font's own tables. Ribbon labels use the right-to-left line
split from the same stack.

fonts.rs adds a system Arabic fallback after the Latin interface font,
which keeps spaces, digits and Latin text so each Arabic word stays one
shaped run: Segoe UI/Tahoma/Arial on Windows, SF Arabic/Geeza Pro/
Damascus/Tahoma on macOS, Noto Sans or Naskh Arabic/KACST One/DejaVu Sans
on Linux, or NotoSansArabic-Regular.ttf in CRAFT_FONTS_DIR. It is the first
fallback for an Arabic UI (Arial Unicode, a CJK candidate, has Arabic
letters without joining data) and the last otherwise; like Thai and
Hebrew it is never promoted for a CJK interface.

Tests: the catalog comes back in display order with no directional
controls, and Arabic laid out with a real font lands on screen word by word
in reading order.

* Hebrew: review the catch-up translations; restore the camera-animation messages (#3457)

- Review of the 533 messages translated in the previous commit: 21
  corrected. Keys in the motion dialog are keyframes (נקודות מפתח, as
  in Add Key), the Design workspace is תכן as in its label, a dropped
  "(Direct Driver)" is restored, terms aligned with the rest of the
  catalog (פורמט, סוכן קוד, רצועת הכלים), and a few calques reworded.
- Translate ui.animate_view_changes, ui.animation_speed and
  ui.look_at_anim_desc, which main has again, so he stays complete.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Arabic and Hebrew: translate the messages main added since (#3457, #3762)

Both catalogs again carry every English message. The 760 messages main added
since the last rebase (render workspace, material editor, standard views,
sheet metal Path Flange, AI app connections, document-on-disk notices and
more) come from A-AL-ANAZI's translations on #3768; the five Perforate dialog
messages are new here. The earlier Hebrew review is kept on top of them, and
33 of the new Hebrew messages are corrected: "completed" was "perfect"
(מושלם → גמור), Regrade read as ranking (now תיקון צבע מחדש), shaders,
guarantee, the Mirror reflection mode, simulations and displacement.

Co-authored-by: Abdullah <alksa2025@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Arabic and Hebrew: attribution rows as a pending file

main now takes new ATTRIBUTION.md rows as one file per change
(attribution/pending/), so the he.json and ar.json rows move there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Arabic and Hebrew: translate the 23 messages main added since (#3457, #3762)

Both catalogs again carry every English message; the two theme-page messages
main removed are dropped. Twelve of the new messages (link updates while
loading, the agent chat's model choice, plugin search, render quality) come
from A-AL-ANAZI's translations on #3768; the sketch plane descriptions, the
rigid group and empty-boolean messages, free sketch points and the web update
note are new here.

Co-authored-by: Abdullah <alksa2025@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Arabic and Hebrew: translate the 12 messages main added since (#3457, #3762)

Eleven come from A-AL-ANAZI's #3768; "Turn Up Axis" in Hebrew follows the
catalog's existing up-axis wording, and the agent chat's no-tool-call message
is new in both.

Co-authored-by: Abdullah <alksa2025@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Arabic and Hebrew: translate the 22 messages main added since (#3457, #3762)

* Arabic and Hebrew: a label found by its English text comes back in display order too (#3457, #3762)

* Arabic and Hebrew: translate the 32 messages main added since (#3457, #3762)

* Arabic and Hebrew: translate the 34 messages main added since (#3457, #3762)

* Arabic and Hebrew: translate the 30 messages main added since (#3457, #3762)

* Arabic and Hebrew: translate the 7 messages main added since (#3457, #3762)

---------

Co-authored-by: rootarchitect <7781866+rootarchitect@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Abdullah alanazi <x1700@MacBook-Air-Abdullah-2.local>
2026-10-27 05:05:53 +00:00
Lars Jansen 2d629069c6 Dialogs: OK and Cancel at the top (#6708) (#6713)
* claim: #6708

* feat(dialogs): OK and Cancel at the top (#6708)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 02:42:23 +00:00
Lars Jansen f1cc49bcdb History: list a sketch under the feature built from it (#6489) (#6494)
* claim: #6489

* feat(history): list a sketch under the feature built from it (#6489)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 00:59:57 +00:00
MAKAO 30f951ecf9 Navigation bridge: a device's own app moves the view (#6094)
A homemade 3D input device's driver app (MAKMOUSE) listens on a loopback
port; with Preferences > Navigation > "Navigate with a device app on this
computer" on (off by default), the desktop app connects, says hello and
reads JSON lines: axis motion (orbit, pan or zoom by mode), zoom steps and
standard views. The motion goes through navigation::device like a 3D
mouse's, only in the focused window; a HID device the app names is left
to it. Documented in docs/3d-mouse.md.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 22:14:52 +00:00
bherbruck 3de2f96b7f Sketch dimensions: double-click a shown dimension in the model view to edit it (#7079) (#7080)
* Double-click a shown sketch dimension in the model view to edit its value (#7079)

A finished sketch's dimensions shown in the model view (Show Dimension) now take a
double-click: the same inline value box as sketch editing opens at the text, Enter
changes the dimension's own expression through parameters.change (one undo step), Esc
cancels. The sketch is not edited and the view does not move. Driven dimensions stay
read-only with a status hint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Control channel: ui.selection lists the shown dimensions of finished sketches

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test: a shown dimension that breaks a later fillet reports it, and Undo restores both

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 19:47:04 +00:00
Jesper We 436ee95095 Preference: return to the previous view when a sketch ends (#7038) (#7043)
* claim: #7038

* Preference: where the view goes when a sketch ends (#7038)
2026-10-26 19:31:55 +00:00
Daniel 2e566e2c58 Placement handles for Rest, Boss and Snap Fit (#4384) (#5362)
* claim: #4384

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Placement handles: shared module, with Rest as the first tool

The Rest handles spike becomes a shared module, place_gizmo, so other features placed on a face can
use the same marker and knob. The mechanics (crosshair with its three states, the grab offset, the
footprint while dragging, the turn knob) live in place_gizmo.rs. The handles own the pointer through
canvas::owns_pointer, as the move triad does, so navigation and Select Other's press-and-hold leave
them alone. Each tool is one file under place_gizmo/ that gives a Spec: which dialogs it serves,
which commands' Position input also takes sketch points, where the place is, how the pointer
re-places it, its footprint and its turn, if any. The module lists the tools one per line, so tools
added on separate branches each add one `mod` line and one list line. Rest is the first.

The handles are always on; the preference the Rest spike had is gone. The POINTS accept flag on a
Position input is granted from the tools' Specs instead of a Rest-only arm in the plastic dialog's
start. Handles are published as `rest:position` and `rest:rotate` as before.

Seen straight down, the dialog's height arrow collapses onto the place and its value box sits just
right of it, where it took the press meant for a knob pointing that way. The knob now slides out
along its ray until it is clear of the box.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Placement handles: Boss

The marker moves a boss across the model, also from Edit Feature, and its Position input takes
sketch points while the handles are on, so a screw boss can be dragged onto the centre of a
circle drawn for it. A boss is round, so it gets no knob; the footprint while dragging is its
outer circle. Published as `boss:position`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Placement handles: Snap Fit

The marker moves a snap fit across the model and its Position input takes sketch points while
the handles are on, so the arm can be put where a sketch says (#3423). The knob points the
catch: it turns between the four directions the Catch Direction combo offers for the face, so
the knob and the combo always agree; the command keeps only those four, so there is no free
turn. The footprint while dragging is the arm's foot, its thickness behind the place and its
width across. Published as `snap_fit:position` and `snap_fit:rotate`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Placement handles: the look in one file

Everything that draws the handles (the crosshair and its three eased states, the knob's ball, the
cased lines, the angle label, the colours) moves from place_gizmo.rs into place_gizmo/look.rs, so a
restyle touches one file and the mechanics (hit radius, drags, knob geometry) stay where they are.
No change in behaviour.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Placement handles: behind a Design preference, off by default

The handles sit behind Preferences > Design > Placement > Placement handles (`placement_handles`,
also through `ui.prefs`), off by default as the hole placement work in #2912 is: a Rest, Boss or
Snap Fit is then placed by its click alone, its Position input takes faces only, and no handle is
drawn or published. The tests switch the preference on; one checks the default.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Placement handles: the tests hide the origin through set_origin_shown, as main does since #1849

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Placement handles: the move marker as designed in the prototype, drawn with theme tokens

The marker is a dot with four arms to the screen cardinals: short and dotted at rest, longer with open arrowheads when pointed at, solid while dragging, each state growing out of the previous one (360 ms). Sizes are the prototype's. Its core is the icon highlight and its casing the marker halo, the tokens main's hole handle uses, so the literal allowance goes. The tip shows while pointing, not during a drag.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Placement handles: the dialog's drag arrow stands above the move marker

With the handles on, the Height arrow started at the marker's centre and ran through its upper arm, head on arm tip. The arrow now keeps the marker's full reach and a gap free at the base, its shortest length grows by as much, and the base dot is left to the marker. Other dialogs are unchanged (clearance zero).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Placement handles: a turn ring on the face replaces the knob

The ring lies on the face about the move marker's centre, drawn in perspective, a fixed 65 px on screen like the move triad's arrows (it is a control of something on the screen, not a measure of the model). At rest it is a short dotted arc with an open chevron grip just outside; pointed at, the dotted circle opens from the grip both ways round and the grip slides in and fills; while turning, a solid arc around the grip. Dragging the grip turns the feature as the knob did, through the same handle name, so the harness tests stand.

The floating value box yields: with a handle's centre under it, it moves to the other side of the arrow's tip or above it, since seen straight down the box sat exactly where the grip is. A handle the arrow's stem crosses keeps the pointer.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Placement handles: a compass while turning, and the turn pulled onto the face's compass points

Four ticks just outside the ring at the face's in-face world directions (the ones the Snap Fit combo names, +X, −Y, …) appear while turning and stay put, so you can see how far you have gone. A Rest's turn is pulled onto one of them within 8°, otherwise it steps by 5° as before; Alt or Ctrl frees it. The readout beside the grip names the point it sits on ("90° · +X") and keeps clear of the ring.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Placement handles: the footprint in the preview's blue, the idle handle steps back

The footprint drawn while the marker drags is a filled shape in the preview's own blue with a thin darker edge, not a white outline, so white stays reserved for what can be grabbed. While one handle is dragged the other fades to a quarter and comes back when the drag ends.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Placement handles: the ring in the preference text, the docs and the tests' wording

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Placement handles: the look as tuned in the app

Marker: drawn to the redrawn design (dot r 3.9 pt, two dashes per arm, a filled head 8.7 × 7.1 pt whose base is where the outer dash began); pointed at, the outer dash becomes the head (its far end narrows to a point, its near end widens); dragging runs the inner dash on into the head as a shaft. Every casing is 0.4 pt outside the edge, for lines, heads and the dot alike.

Ring: the grip and the compass lie in the ring's plane like the circle, so the grip is never skewed against it; the grip is a thick chevron with a hole that flattens into the base as the grip slides onto the ring, and fills; the dotted circle stays while turning, with the solid arc laid over it; opening eases in and takes 0.3 s, leaving is a 0.15 s fade over the resting ring, not the sweep backwards; a drag keeps the angular gap of the press, so the grip does not jump onto the pointer; the compass ticks and the readout's point name are in their axis colours, and the grip takes the axis colour (eased) while aligned with one, with that point's tick left out; free turning keeps a hair of pull (0.5°) so an axis can still be hit; the readout wraps to a half turn.

Value box: with a ring it keeps out of the circle the ring, grip, compass and readout sweep, one place per view, nothing moves when a turn starts; also when the value does not evaluate and there is no arrow.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Placement handles: the readout shows a half turn as 180°, not −180°

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Placement handles: the motions in one place

The animations the handles grew (a factor eased in and out each way on its own time and easing, a handle stepping back while the other works, a colour that comes and goes from the last one it was on, the gap a press keeps for its drag, an offset that slides instead of jumping) move out of place_gizmo into motion.rs, so the next manipulator reuses them. The look's timings become Transitions in look.rs. No change in behaviour: the contact sheet before and after is identical, the harness tests stand.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Placement handles: the axis colours as main names them since #4430

The compass and the aligned grip take the one set of X, Y and Z colours (axis_x, axis_y, axis_z); the Move gizmo's own array is gone.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-26 15:35:10 +00:00
Karl Von Richter 44b0056d48 Frames: a Weldments ribbon tab (#4003) (#5262)
* Frames: a Weldments ribbon tab (#4003)

- WELDMENTS joins the ribbon after SHEET METAL and is built the same way:
  Sketch (New Sketch), Create (Frame Member) and Configure (Parameters,
  Configurations). Frame Member's home moves there from MODEL > Create.
- Always shown, as a frame starts from a sketch of its lines. It selects
  itself and takes the contextual style when the selected body (or the last
  body of the active component) is a frame member; sheet metal comes first.
- It uses the default accent until the palette has a colour for it.
- The tab label is in every catalog; docs/ribbon-layout.md, docs/frames.md
  and the tab list in docs/control-protocol.md follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Frames: Weldments keeps the ordinary tab look (#4003)

Weldments still selects itself when a frame member is the active body, but
no longer takes the solid contextual fill or the 2 px accent line under the
tab row: selected, it looks like a selected Model tab. Only Sketch and Sheet
Metal (on a sheet body) are contextual.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 12:24:38 +00:00
sascha2101 e1ff3fa9c0 Batch: refuse a step that would fail at its turn before the first step runs (#5853) (#6781)
* claim: #5853

* Batch: refuse a step that would fail at its turn before the first step runs (#5853)

engine.batch and the MCP batch tool checked only a batch's shape up
front. A misspelled command id in a late step was found at its turn,
after every earlier step had run, and then all of it was rolled back: a
160-step batch with a typo as its last step ran for a minute and
changed nothing.

solidcraft_engine::batch_preflight::check finds, before anything runs,
the first step the batch would certainly refuse at its turn: a step
without a command, an unknown command id (the error names the closest
ids, as at the step's turn) or, with strict parameter checking, a call
that breaks its command's typed contract. Anything that depends on the
design is left to the step's turn.

- engine.batch (control channel) checks against the app's registry and
  its session's level; view.pick, which the app answers itself, passes.
- The MCP batch tool checks when the commands run in its own process
  (headless, with --param-check from the backend). A running app may be
  another version with other commands and checks the batch itself; its
  reply's not_run is passed on.
- The refusal is the failing step's reply with completed 0, undone 0,
  not_run listing every step and a note.

Tests that used an unknown command only to make a late step fail now
use a step that fails at its turn (a bad extrude distance), so they
still test rollback, timings and file.new as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FN5eEMrqWWXqi65FcK8GXq

---------

Co-authored-by: sascha2101 <221609842+sascha2101@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 11:11:10 +00:00
Mateusz Sych d895fef354 Control channel: a pushed design.changed event for clients that subscribe (#6985) (#6986)
* claim: #6646

* Control channel: document.revision, a design revision and a document id (#6646)

A program that follows the open design asks document.revision and exports
only when the answer moves: document_id names the open design (kept through
edits, saves and renames, another for each design started or opened, never
shared between two tabs or two runs) and revision moves whenever the design,
what is hidden or an uncaptured component position changes. It stays put on
reads, selections and view changes, unlike the session's view revision.

The revision is read lazily: the session remembers the design it last
reported (held weakly, so Arc::make_mut can never change it in place and its
address can't be reused) and takes a new number from one counter for the
whole run when the design is another one. The control method answers at once,
also while a slow command computes; engine.execute reaches the same command
for scripts and MCP.

* document.revision: hash the run's id prefix with the process's random keys

A clock set before 1970 gave every run the prefix 0, so a restarted app could
answer a new design with the id and revision of the old one. The docs no
longer promise an answer at once: a screenshot waiting for an opened design to
be meshed still holds the requests behind it.

* document.revision: its label in the complete catalogs (ja, zh)

* claim: #6985

* Control channel: control.subscribe and design.changed events (#6985)

A connection that sends control.subscribe gets the active design's id and
revision in the reply (as document.revision answers), then a
{"event":"design.changed","params":{document_id, revision}} line whenever
either changes, so a live link need not poll.

The window publishes the design at the end of each frame's logic and
drawing while a connection is subscribed (one atomic load otherwise). Each
subscribed connection waits on that from a thread of its own and writes
the latest after a 100 ms gap, so a burst of changes is one line. Replies
and events share one lock per connection, each written whole (#6390).

* control.subscribe: the reply before any event, a second one refused

The events thread started before the subscribe reply was written, so a
change right after the window's answer could reach the client before the
reply that named the older revision. The subscription now starts holding
the connection's line lock and writes the reply under it.

A second control.subscribe on a subscribed connection is refused on the
connection itself: its answer could arrive behind a newer event. When no
thread or socket is left for the events, the reply says it did not
subscribe instead of ok.

* control.subscribe: a second one does not lose a finished late reply

The already-subscribed answer came before the busy check, so a request that timed out and had finished since lost its reply: control.pending then said the app ended it without one. It now comes after the busy check and drops a finished late reply as every other request does.

* control_server: declare the subscribe guard at the top of the loop

Clear of the lines #6643 changes (its token check moves to where the declaration was).

* control_server: the subscription's items beside serve

Away from the lines next to send, where #6643 adds token_of.

* control test: New on a blank design reuses its tab, so redo the box first

---------

Co-authored-by: MateuszSychXpl <151755914+MateuszSychXpl@users.noreply.github.com>
2026-10-26 11:10:03 +00:00
Lars Jansen 4a0d519727 View: OK and Cancel in the corner of the view while a dialog or sketch is open (#6709) (#6714)
* claim: #6709

* feat(view): OK and Cancel in the corner of the view while a dialog or sketch is open (#6709)
2026-10-26 10:40:36 +00:00
raykholo ffbeb42b5c Assistant: say so when a turn ends without using SolidCraft's tools (#4846) (#5188)
* claim: #4846

* Assistant: say so when a turn ends without using SolidCraft's tools

When tools were offered and a completed turn made no tool call and no
change, the chat panel shows a short notice pointing to tool-capable
models: always for an empty reply, and for a text-only reply to an
explicit edit request. Plain answers to questions stay quiet. The
control channel exposes it as turnWarning.

* Fix the Anthropic loop test for the tools event; add ja and zh for the no-tool-call notice

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 02:19:57 +00:00
CamWight ab80a410a1 Viewport theme: a light 3D view in a dark window, and the reverse (#4146) (#4147)
* claim: #4146

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Viewport theme: a light 3D view in a dark window, and the reverse (#4146)

Preferences › Interface › Theme gets a Viewport row under the theme tiles:
Follow theme (the default, as before), Light or Dark. Light or Dark draws
the 3D view in the built-in Light or Dark theme's colours whatever the
window uses, so a dark window can show the model on a light view and the
other way round; it works with every theme, theme files included.

The view takes the background and grid, bodies, selection and hover, the
origin, previews, sketches with their dimensions and glyphs, the navigation
cube and triads, box selection and the analysis colours. Panels, dialogs,
menus and the chips over the view keep the window's. Text and warnings drawn
straight onto the view (the sketch status line, the loose-end and midpoint
markers, the section's cut outlines, the 3D sketch tool and the sketch tools'
previews) take the view's side, so they read on its background.

theme::ViewportTheme is the setting (saved as `viewport_theme`: theme, light
or dark; an unknown saved value reads as Follow theme, as ColorVision's
does). Tokens::get() takes the view's colours from the other side only when
the view's dark or light differs from the window's; Tokens::view() is the
view's side for colours drawn onto it. The ground shadow follows the view
(the scene and highlight caches already key on the colours themselves),
ui.render draws in the view's colours, and ui.prefs takes `viewport_theme`
and reports `viewport_dark`. An older release ignores the setting and draws
everything in the theme.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Viewport theme: follow the single set of axis colours

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
2026-10-25 22:17:04 +00:00
raykholo 4355d117ef Assistant: warn when an Ollama model has no tool support (#4846) (#4916)
* claim: #4846

* Warn when Ollama models lack tool support (#4846)

Check Ollama model capabilities in the background and cache results per
endpoint and model. Show an advisory warning for models without tools,
expose it through ui.agent_chat, and document the behavior.

Cover capability parsing, warning selection, background probing, caching,
and selection changes with synthetic regression tests.

* Keep the Ollama capability probe out of the web build

The panel never calls it there, so it would only be dead code.

* Wrap the model warning instead of cutting it off

In a narrow panel the end of the sentence, the part that says what to do, was truncated.

* Fix AgentConfig default after rebase onto main

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Move the Ollama no-tools warning into a pending locale file with ja and zh

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 21:37:30 +00:00
ABDULLAH 92dc6bc987 Assistant: pick the provider first, then its model (#5564) (#5565)
When an agent's models come from several providers (Hermes and OpenCode
name each one "Provider · model" or say "Provider: ..." in its
description), the chat header shows a provider drop-down before the model
drop-down, and the model drop-down lists only that provider's models
without the provider in front. It opens on the provider of the model in
use; picking a provider alone changes nothing. ui.agent_chat takes
provider and reports providers and provider.
2026-10-25 18:09:32 +00:00
raykholo b1da434458 Graphics: choose the graphics card, honour WGPU_ADAPTER_NAME (#5986) (#6010) 2026-10-25 16:49:57 +00:00
Ahmad Khan a49698ee3d Value fields step with the arrow keys and the mouse wheel (#2320) (#2608)
* claim: #2320

* Value fields step with the arrow keys and the mouse wheel (#2320)

Up/Down in a focused value field step a plain number by 1 in the unit it is written in
("20 mm" -> "21 mm", "2,5 mm" -> "3,5 mm"), 10 with Shift and 0.1 with Alt; the wheel over
the focused field does the same, a step a notch, instead of scrolling the panel under it.
Expressions such as `width / 2` are left as typed, and an open completion list keeps the
arrows. Every expression field gets this through `params_dialog::complete`: the value box
beside the geometry in every dialog, the dialog rows, sketch dimensions, the dimension
editor, Drive Joint and the Parameters window.

* The value box beside the geometry stays under the pointer

The box rides on the arrow's tip, so each wheel notch that stepped its value moved it, and
after a notch or two the box slid out from under the pointer and the wheel zoomed the view
instead. While the pointer is over it the box now keeps its place, and it goes back to the tip
when the pointer leaves.

* Value stepping is a preference, off by default

Preferences › General › "Step values with the arrow keys and the wheel" (`step_values`,
also through `ui.prefs`) turns on Up/Down and wheel stepping in value fields, and the value
box staying under the pointer while the wheel steps it. Off, as by default, value fields
behave as before: Up/Down move the text cursor, the wheel scrolls, and the box beside the
geometry follows its arrow.

* Value stepping test: Bend Radius is under Advanced now

* Value stepping test: the preference is on the Design page

* Value stepping test: draw the field straight into the test's frame (#2320)

The shared outer-host rule now covers tests too; the field needs no panel around it.
2026-10-25 05:34:03 +00:00
raykholo cc1e654690 Warn when a design is open elsewhere or changed on disk (#5467) (#5468)
* claim: #5467

* Warn when a design is open elsewhere or changed on disk (#5467)

The desktop app keeps a lock file next to each open design
(.~<file>.lock: computer, user, version, opened and refreshed times),
refreshes it every minute and removes it on close; a lock not
refreshed for three minutes is stale and ignored. Opening a design
that another SolidCraft has open asks: Open Read-Only, Open Anyway or
Cancel. A read-only design saves only to another file.

A design remembers its file's size and modification time when it is
opened or saved. Save over a file another program or computer changed
since asks: Save a Copy (the default), Overwrite or Cancel.

Programmatic calls never ask: doc.open reports open_elsewhere and takes
read_only, and file.save over a changed file returns an error until it
is given overwrite: true. ui.documents answers both questions.
2026-10-25 03:34:20 +00:00
DuBearte a5f7f5a921 Batch: consecutive parameter edits can rebuild the design once (#5822) (#5839)
* claim: #5822

* Batch: consecutive parameter edits can rebuild the design once (#5822)

An agent's batch of parameter edits, one parameter per step, evaluated the
design once per edit: an edit early in the timeline rebuilds nearly all of
it, and 21 such edits ran for minutes.

engine.batch and the MCP batch tool take coalesce_parameters (default
false). With it, each run of consecutive plain parameter edits
(parameters.change with only a name and an expression, or with changes) is
set as one parameters.change {changes}: one rebuild for the run. Any other
step ends a run, so later steps see the design up to date. Every step
still gets its own result (coalesced: the run's length); the run is one
undo step. A run whose combined edit is refused (a new parameter, which
changes can't make; a bad expression) runs step by step, so a refused edit
is still named by its own step. The app's off-thread evaluation computes
the run the same way. The grouping is solidcraft_engine::batch_params,
shared by both runners.

21 parameter edits on a plate with 21 extruded bosses (in-process MCP,
ci profile): 40.1 s step by step, 3.5 s coalesced, the same volume.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Batch coalescing: say a run skips the states between its edits; test it against step by step (#5822)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 01:48:31 +00:00
Colin Faulkingham 692265980b Identify commands beside the animated agent cursor (#622) (#6026)
* claim: #622

* fix(ui): identify commands during agent cursor animation
2026-10-25 01:25:31 +00:00
Dahak Builds adbd2adf89 view.pick: map screenshot pixels to exact geometry (#6304) (#6329)
* claim: #6304

* view.pick: map screenshot pixels to exact geometry (#6304)

A read-only command that answers, for screenshot pixels (window or model
frame) or world-space rays: body, face index, exact world point and
outward normal, depth, occurrence/component for placed parts, and the
nearest edge/vertex within edge_px. Faces are raycast through the same
per-body pick index the mouse uses; flat faces are solved exactly
against their plane, curved faces take the mesh hit with the normal
interpolated from the mesh's surface normals. Section-aware: faces on
the removed side do not stop a pick and the cut cap answers with
section_cap. Never touches the selection, camera, document or undo.

Exposed as control ui.pick and as view.pick through engine.execute and
engine.batch (and through them MCP execute and batch).

---------

Co-authored-by: Dahak Builds <dahakbuilds@users.noreply.github.com>
2026-10-25 01:24:39 +00:00
fugazister 4b119dd471 Performance overlay: frame-time graph and histogram, triangles, draw calls (#2548) (#2549)
* Performance overlay: frame-time graph and histogram, triangles, draw calls (#2548)

Net change of the perf-overlay branch, rebased onto main as one commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Document frame_rate_details in ui.prefs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
2026-10-24 22:50:43 +00:00
raykholo 4cd1a51f48 Assistant: a request timeout per endpoint for slow models (#5009) (#5010)
* claim: #5009

* Assistant: a request timeout per endpoint for slow models (#5009)

An OpenAI-compatible endpoint now stores how long one model request may
take (request_timeout_s, 300 s by default, clamped to 30 s ..= 1 h). It
is set in the Add agent dialog and in the endpoint's entry under Agents
(a running conversation uses a change from its next request), through
ui.agent_chat add_agent, and reported in the chat's state. A request
that runs out of time says the limit and where to raise it instead of
"timeout: global". The desktop HTTP cap goes from 900 s to an hour.

The tool-call timeout stays 330 s: it covers SolidCraft's own tool work
and the user's Allow, never the model.

* Assistant settings: line up an endpoint's Request timeout with Permissions

The label column of an agent's entry is wide enough for "Request timeout",
so the label isn't cut and both rows share one column.
2026-10-24 22:24:42 +00:00
Matt Van Horn 9919825ea3 Expand All and Collapse All in the Browser (#5190) (#5335)
Open or close every Browser folder from the design or a component menu,
including folders that start closed. Display only: not saved, not an undo step.
2026-10-24 20:46:04 +00:00
raykholo 0520910bfd Control: name the token file and spot a stale one when a call is unauthorized (#4664) (#4670)
* claim: #4664

* Control: name the token file and spot a stale one when a call is unauthorized (#4664)

When the app refuses a token that the MCP client read from a token file,
the error now names that file, when it was written and how long ago,
without printing the token. The app also writes `<port>.pid` beside the
token file (its process id and, on Linux, its start time) and removes
both at exit; when that process has exited, the error says the token
file is stale. The process check runs only after a refusal, and the
token file itself stays one line, so existing clients keep working.

Document force-quit leftovers and the MSIX AppData redirection.

* Bench assistant: read the token out of the new ClientToken

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 17:28:12 +00:00
froglemonade2 46f24f2394 Save the browser's view with the design, and an option to hide the origin by default (#1849)
The Origin folder's eye, a finished sketch's Show Profile and Show Dimensions,
and body locks move from UiState into the design's saved visibility
(origin_hidden, hidden_profiles, shown_dimensions, locked_bodies), so each tab
keeps its own and they survive closing the design. The Sketches folder uses the
saved browser folder (c0/sketches in hidden_folders); ui.set/ui.inspect keep
showOrigin, showSketches, hiddenProfiles, shownDims and lockedBodies.

Preferences > Design > "Hide origin by default": a design that never toggled
its Origin eye follows the preference. New fields are a pending format change
(format/pending/browser-view-state.rs).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 17:15:47 +00:00
Rec0iL d5a79a77e6 Agent chat: Pick context and Attach selection for elements, features and bodies (#2286) (#2288)
* claim: #2224

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Agent chat: keep Send in view for a long message, open "View attached" (#2224)

The message box sat in a fixed 92-point reserve, so a long message grew it
past the panel and took Send, Stop and Attach view with it. The box is now a
panel of its own at the bottom: it grows upwards up to a cap, then scrolls,
and the conversation takes what is left.

The picture sent with a message is kept on it (once the agent starts on the
message), and the "View attached" caption opens it in a window.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Agent chat: a message's pictures as thumbnails with a hover preview and a viewer (#2224)

Instead of a window on the far side of the screen: the pictures of a message
show as small thumbnails under it, hovering one shows it bigger for as long as
the pointer stays, and a click opens a viewer over the app with the message's
pictures one at a time (previous and next, arrow keys, Esc). A picture carries
a note shown with it, so attachments of other kinds can use the same viewer.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* claim: #2286

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Agent chat: Attach selection sends what is selected in the model with the message (#2286)

A checkbox beside Attach view. The selection is read when the message is
sent (also for a queued one) and described: faces and edges with the names,
indices and points the tools take plus their size and place, features by name
and kind, bodies by name; at most 64, the rest counted. The agent gets it as
text after the message; the conversation shows the message as typed with the
things as grouped chips (hover for what the agent was told).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* WIP: the chat's context picker dialog (#2286)

* Agent chat: Pick context, a picker for elements, features and bodies (#2286)

A button beside Attach selection opens the picker: a dialog with Elements,
Features and Bodies inputs, so clicks in the model, the timeline and the
browser pick into the active one (clicking again takes one out), with the
usual highlight. OK puts the picks as chips with an x above the message box;
they go with the next message like an attached selection (text for the agent,
chips in the conversation) and the tray is empty again afterwards. Cancel
keeps what was picked before. The control channel opens it with pick.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Agent chat: Attach selection counts and describes what was clicked, not the pieces of a rim (#2286)

A click on a circular rim or a split surface selects all its pieces for the
commands. The checkbox counted them one by one and the agent got one entry
per piece (reported on macOS). They are now grouped back into the click they
came from: one chip, one entry with the whole size, and the indices of every
piece in its detail. Edge details are looked up by position as well as
index.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Agent chat: a message's picture is kept on exactly that message (#2224)

The turn now carries its message's place in the conversation (also through a
queue and a send again after a sign-in), so its picture is kept there, once,
and never on an older message that also wanted one (review of #2225).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Agent chat: use the UI kit's checkbox and button and the font tokens (guard tests)

Main's UI-kit guard tests reject raw egui checkboxes, buttons and font sizes in the
chat panel; Attach selection, Pick context, the chip remove button and the chip fonts
now come from ui_kit and Tokens.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
2026-10-24 15:57:24 +00:00
fugazister a633a67e63 Preferences: choose the window system on Linux (Wayland or X11) (#3083) (#3084)
* claim: #3083

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* WIP: choose the window system on Linux in Preferences (#3083)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Preferences: a window system set over the control channel is saved for the next start again

The merge kept main's check in ui.prefs, which only looked at the anti-aliasing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Preferences: the window system section drops the restart badge its note already states

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 12:12:38 +00:00
Jacques 400e06c202 Hole: snap to face and round-edge centres, drag placed holes, section in the dialog (#2171) (#2912)
Placing a Single hole put it exactly where the click landed, with nothing to line it up by and no
way to move it but taking it out and picking again; the dialog was a list of size fields.

- Preferences › Design › Create Hole has two settings, both off by default, so a new installation
  places holes as before:
  - Snap to face and edge centres (`hole_snaps`): the planar face under the cursor offers its
    middle and the centres of its round edges (a boss, a rounded corner, a hole already there) as
    marks; a pick near one, or on or beside such an edge, takes that centre and the mark is named.
    Sketch points on the face still come first; Alt or Ctrl held places it where clicked.
  - Move holes by clicking or dragging (`hole_moves`): each placed hole has a handle that drags it
    (snapping when snaps are on) and takes it out when clicked, and a pick elsewhere on its face
    moves it there. Edit Feature shows the handle too, so a hole can be moved later (#1047).
- The Hole dialog draws a section of the hole as its options make it, with each size in a field
  beside the dimension it sets; a hovered or focused field lights its dimension. The layout is a
  new kit element, `ui_kit::figure_rows` (a caller-painted figure beside captioned fields).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 05:25:56 +00:00
SS-EN 6c6ffe4802 MCP: wait out long requests, honest batch outcomes, batch tool aliases (#2901)
Rebased onto main as one commit (was 120d26f7, df488f9a, db9d1073 plus
merges of main).

- A request the app reports as still running (#1618) is waited for on the
  same connection through `control.pending`; past the wait the error says it
  was not cancelled and will still apply (or only write its file), later calls
  are not sent behind it, and the new read-only `pending` tool returns its
  result once it lands.
- A failed batch says what really happened: `rolled_back` only when the
  design is back where the batch started (as #3288 / #3242 on main: the app's
  `rolled_back` is believed; for an older app, every completed step undone;
  only a rollback asked for is reported as one), plus `applied`, `not_run` and
  `failed.still_running`.
- A batch step may name a tool (set_parameter, list_commands,
  describe_command, execute, measure, inspect_design, undo, redo, export, save,
  open, new_design, crash_reports); screenshot, body_topology, batch and
  pending are refused before anything is sent.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 02:41:41 +00:00
Diogo Soares Rodrigues 1ed394f8d6 Extrude: picking a face, vertex or parallel plane off the profile switches the extent to To Object (#2855)
* Extrude: picking a face, vertex or parallel plane off the profile turns the extent to To Object

With profiles picked, a face off their plane (or curved), a vertex off it, or a
construction plane parallel to it is taken as the To Object target instead of
another profile: the extent switches without the Extent Type choice, and the
distance shows how far the target is. Coplanar faces still join the profiles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Extrude: automatic To Object is a Preferences setting, off by default

Preferences > Design > "Extrude to a picked target" (`extrude_auto_to_object`, default
false) turns the automatic To Object on. Off, picks in the Extrude dialog only add
profiles and the distance is not synced to a target, as before this change.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
2026-10-23 22:03:23 +00:00
ealitt 6eaf723041 fix(ui): preview shortcut chords and wait for complete modifier input (#1810)
Keep physical modifier events out of the ordinary-key slot, preview held keys immediately, and confirm after release and a one-second settling interval. Preserve legacy control-channel modifier behavior while allowing explicit physical Control/Command input. Add regression coverage, a UI scenario, localized guidance and documentation.

Fixes #1809.

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 20:05:58 +00:00
bherbruck 98c4f335e8 Control channel and MCP on by default, with a setting to turn it off (#5561)
The app opens its localhost control channel on port 27878 (or the next free
one) unless Preferences > Assistant turns it off; --control and
SOLIDCRAFT_CONTROL_PORT still win. A current.port discovery file lets
solidcraft-cli mcp find the running app with no arguments.

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 16:00:35 +00:00
bherbruck c3ed8b1c07 Offer to stand up SolidWorks files instead of turning them silently; add Turn Up Axis to the component menu (#5655)
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 16:05:46 -04:00
Jackson Oursland 80fd2fbbf1 Assistant: add Anthropic-compatible API agents (#5015) (#5017)
* claim: #5015

Co-Authored-By: Claude Code <noreply@anthropic.com>

* Assistant: add Anthropic-compatible API agents (#5015)

The Add agent wizard now offers Anthropic-compatible endpoints beside OpenAI-compatible ones. The API backend speaks the Anthropic Messages protocol with the same MCP bridge, tool gate, limits, undo and keychain rules: x-api-key and anthropic-version, a top-level system note, input_schema tools, content-block answers and one user tool_result message per round. Test sends a short message because compatible endpoints (Qwen's) need not list models.

Co-Authored-By: Claude Code <noreply@anthropic.com>

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
2026-10-23 13:43:41 +00:00
N3MI-DG ae3b36ac88 Agent cursor follows the agent's own pointer input (ui.move, ui.click, ui.drag, ui.scroll) (#5162)
The agent cursor only acted out engine commands: pointer input sent over the control channel
reached the app as synthetic events without moving it, so an agent's clicks, right-clicks and
drags were invisible to a person watching. While the cursor is shown, each synthetic pointer event
now moves it to where the input lands, a press leaves a ripple, and a drag is followed step by
step. A request being acted out keeps the pointer; with the cursor hidden nothing changes.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 13:42:59 +00:00
bherbruck edf57cec29 Stand up Y-up STEP and IGES files from SolidWorks automatically (#5191)
* claim: #5150

* Stand it up: don't offer it for SolidCraft's own STEP files (#5150)

STEP replies from file.insert_step and doc.open now carry the file's
originating system, and the window skips the stand-up offer when it is
exactly SolidCraft, as SolidCraft's STEP export writes it.

* Stand up Y-up STEP and IGES files from SolidWorks automatically

The STEP header (originating system, preprocessor version, FILE_DESCRIPTION) and the IGES
global section's native system ID say which program wrote a file. A SolidWorks header means
Y up: the import's component is stood up as it opens, as one undo step, and the message offers
Undo. SolidCraft's own files are left alone; an unknown exporter keeps the offer.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Ray <raykholo@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 02:53:20 +00:00
raykholo 0c72ad56d2 An idle window draws nothing with the frame-rate readout on (#5165)
The viewport's frame-rate readout asked for a new frame every frame, so with
it on an untouched window redrew as fast as the display allowed and kept the
GPU busy: 77% GPU at 60 fps on an M1 with a 5K display showing the sample,
against 0% with the readout off. It now asks for no frames of its own and
shows how often the view really draws; one frame a little over a second after
the frames stop shows the view idle at 0 FPS. The preference's note no longer
says the view redraws continuously.

The status toast also asked for a frame every half second for the six
seconds it shows; it now asks for one frame, when it is due to go.
2026-10-23 02:19:37 +00:00
Nathan Dane 971b28c982 claim: preferences redesign (#4608) 2026-10-22 13:53:36 +00:00
Nathan Dane 4b23bb3a03 Implement compact workspace layout (#2029) (#4533)
* Vertical history strip: left of the browser, compact rows, hollow-circle marker, collapsed rail hover

* Vertical history strip: seam handle to expand and collapse names, drag to resize with snap

* Vertical history strip: no empty gap below the transport

* Show the history seam arrow only on hover (#2028)

* claim: #2021

* Redesign the Assistant chat panel with shared UI components

* Show Assistant in the shared floating panel shell

* Extend floating Assistant to viewport height and shift navigation

* Dock Assistant before history and match docking preview bounds

* Align Assistant top margin with floating shell cards

* Extract a shared panel drag grip

* Rebuild responsive history sizing and three-way docking

* Share browser and History collapse hover styling

* Show the History title as soon as its text fits

* Animate stacked browser and History expansion and collapse

* Make panel folding responsive and independent of frame delays

* Let folding panel contents shrink continuously to header height

* Use four explicit History transport actions in every layout

* Resize the shared Browser and History column from either card

* claim: shared compact-mode containers (#2029)

* Centralize layout-aware UI containers and enforce their use

* Keep docked Assistant at the outer edge beside tool sheets

* Use shared surface policy for Assistant tool space

* Let tool sheets drag over shell panels while avoiding Assistant

* Update Parameters drag bounds assertion for shell overlap

* Keep dragged tool sheets below ribbon and workspace selector

* Enforce universal UI containers in mandatory repository checks

* Remove legacy report windows and require shared window composition

* Remove retired UI styling and require shared controls

* claim: compact layout preference (#2029)

---------

Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
2026-10-21 20:52:36 -04:00
bherbruck 920398ac53 Bring back the view-change glide; orbit, pan and zoom stay instant (#4596)
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 20:37:19 -04:00
Nathan Dane 63f210b49f Restyle the vertical history sidebar (#2028) (#3953)
* Vertical history strip: left of the browser, compact rows, hollow-circle marker, collapsed rail hover

* Vertical history strip: seam handle to expand and collapse names, drag to resize with snap

* Vertical history strip: no empty gap below the transport

* Show the history seam arrow only on hover (#2028)

* Extract a shared panel drag grip

* Rebuild responsive history sizing and three-way docking

* Share browser and History collapse hover styling

* Show the History title as soon as its text fits

* Animate stacked browser and History expansion and collapse

* Make panel folding responsive and independent of frame delays

* Let folding panel contents shrink continuously to header height

* Use four explicit History transport actions in every layout

* Resize the shared Browser and History column from either card
2026-10-21 18:56:55 +00:00
bherbruck cb3cabeda1 Remove camera animation: every view change and orbit applies at once (#4296)
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 11:19:40 -04:00
SS-EN 776541b081 Agent commands compute off the window thread, so the window stays live (opt-in) (#1989) (#3340)
An agent's design changes over the control channel (engine.execute, engine.batch) are evaluated
ahead on a copy of the session on an `agent` worker, then run on the window thread reusing every
feature computed there (doc::KeptResults, whatever the bounded evaluation cache dropped); the
worker also makes the display meshes of the bodies they end with. Exports run on a copy. While a
change computes, or the agent cursor acts one out, ui.*, inspection and screenshots answer; later
design changes wait their turn. A chip names the command with Stop. A person's edit meanwhile goes
first; a replaced design refuses the request. Preference: Preferences > AI, agent_off_thread, off
by default.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:58:56 +00:00
Mateusz Sych fdec948abc Control channel: control.running lists what the app is running, across connections (#3654) (#3689)
* claim: #3654

* Control channel: control.running lists what the app is running, across connections (#3654)

control.pending answers only for the connection that asks, so a second client,
the MCP bridge after a reconnect or a script saw {"pending": null} while the app
was busy. control.running answers for the whole app, the same on every
connection and at once (the connection's own thread answers it, also while it
is busy with a timed-out request): every request the app has been sent and not
answered yet, oldest first, with its connection, id, method, command id (or a
batch's step count), seconds since it arrived and whether it still waits its
turn. A timed-out request stays listed until the app answers it, also after its
connection closed. Parameters are never shown.

The window marks a request started when it takes it (ControlRequest.started),
which tells queued from running. The MCP server gets a read-only `running` tool.

---------

Co-authored-by: MateuszSychXpl <151755914+MateuszSychXpl@users.noreply.github.com>
2026-10-21 00:54:33 +00:00
bherbruck 6e87fb1a25 Ribbon: Parameters and Configurations back on Model, Sheet Metal and Sketch; Sheet Metal tab always reachable; Finish Sketch button back in the sketch palette (#3937)
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 21:08:04 -04:00
Dahak Builds 2b1cb2c4e1 MCP batch: rollback restores the original document (#3242) (#3288)
* claim: #3242

* MCP batch: rollback restores the design the batch began in (#3242)

A failed batch with rollback: true reported rolled_back: true even when the
design never went back. Two defects, both fixed:

- file.new (and any document-replacing command) replaced the session with it,
  taking its checkpoints down too, so a batch that failed after file.new had
  nothing to restore. Session::replace_design now carries the checkpoints over
  to the fresh session: the checkpoint belongs to the batch, not to the
  session that happened to be holding the document.
- rolled_back echoed the requested flag. It now reports whether the design is
  actually back: the app answers engine.batch with a new restored field, and
  the MCP tool reports restored && rollback. An app that predates the field
  falls back to undone/completed.

* Batch: answer with main's rolled_back field after the merge (#3242)

Upstream #2900 put the real restore check on engine.batch as
`rolled_back` while this branch named it `restored`; the merge kept
main's control test and this branch's field, and CI caught it.
Standardize on main's wire name: the app answers `rolled_back`, the
MCP tool reads it (fallback for older apps unchanged), docs and tests
follow. The checkpoint carry-over across file.new is unchanged.

---------

Co-authored-by: DahakBuilds <dahakbuilds@users.noreply.github.com>
2026-10-21 00:15:36 +00:00
Nathan Dane d45fcce72c Command search popup on the UI kit; the bottom command line is gone 2026-10-20 21:01:32 +02:00
Nathan Dane 1122cd44b8 UI library, tokens, fonts and icons (step 5 of #2016, after #2287) 2026-10-20 21:00:56 +02:00
Nathan Dane c2e3bdfe1c Floating shell frame: workspace and ribbon cards over a full-bleed viewport (step 2 of #2016, rebased onto #2176) 2026-10-20 21:00:50 +02:00