Commit Graph

55 Commits

Author SHA1 Message Date
Zoe Forbes
da2a360c56 feat: add headless runner entry points
New file: runner.py with three entry points for silorunner:
- dag_extract(input_path, output_path): extract feature DAG as JSON
- validate(input_path, output_path): rebuild features, report pass/fail
- export(input_path, output_path, format): export to STEP/IGES/STL/OBJ

Invoked via: create --console -e 'from runner import dag_extract; ...'

Closes kindred/create#217
2026-02-14 15:17:30 -06:00
Zoe Forbes
3dd0da3964 feat: push DAG on save and commit
Adds _push_dag_after_upload() helper that extracts the feature DAG
and pushes it to Silo after a successful file upload.

Hooked into both Silo_Save and Silo_Commit commands. DAG sync
failures are logged as warnings and never block the save/commit.

Closes kindred/create#216
2026-02-14 15:10:50 -06:00
Zoe Forbes
4921095296 feat: update silo-client — add DAG API methods
Points silo-client to feat/dag-api-methods with push_dag/get_dag.

Closes kindred/create#215
2026-02-14 15:06:31 -06:00
Zoe Forbes
3a9fe6aed8 feat: add DAG extraction engine
Implements extract_dag(), classify_type(), and compute_properties_hash()
for extracting feature trees from FreeCAD documents.

- classify_type: maps ~50 FreeCAD TypeIds to 8 DAG node types
- compute_properties_hash: SHA-256 of per-feature parametric inputs
- extract_dag: two-pass walk of doc.Objects producing nodes + edges

No GUI dependencies -- works in both desktop and headless mode.

Closes kindred/create#214
2026-02-14 14:41:35 -06:00
Zoe Forbes
9e99b83091 fix: default cert browser to home dir instead of /etc/ssl/certs (#203)
The CA certificate file browser hardcoded /etc/ssl/certs as fallback,
which confused users when the dialog opened to a system directory.
Default to the user's home directory instead.
2026-02-14 12:50:01 -06:00
Zoe Forbes
fed72676bc feat: use .kc extension for new files, find both .kc and .FCStd
- get_cad_file_path() now generates .kc paths instead of .FCStd
- find_file_by_part_number() searches .kc first, falls back to .FCStd
- search_local_files() lists both .kc and .FCStd files
2026-02-13 13:39:22 -06:00
91f539a18a Merge pull request 'feat(open): replace modal open dialog with MDI tab' (#20) from feat/open-item-mdi-tab into main
Reviewed-on: #20
2026-02-12 17:47:09 +00:00
2ddfea083a Merge branch 'main' into feat/open-item-mdi-tab 2026-02-12 17:46:57 +00:00
be8783bf0a feat(open): replace modal open dialog with MDI tab
Extract search-and-open UI into OpenItemWidget (open_search.py), a
plain QWidget with item_selected/cancelled signals.  Silo_Open now
adds this widget as an MDI subwindow instead of running a blocking
QDialog, matching the Silo_New tab pattern.

Improvements over the old dialog:
- Non-blocking: multiple search tabs can be open simultaneously
- 500 ms debounce on search input reduces API load
- Filter checkbox changes trigger immediate re-search
2026-02-12 10:22:42 -06:00
972dc07157 feat(silo): replace modal new-item dialog with MDI pre-document tab
Extract SchemaFormWidget from SchemaFormDialog so the creation form
can be embedded as a plain QWidget in an MDI subwindow tab.  Each
Ctrl+N invocation opens a new tab alongside document tabs.  On
successful creation the pre-document tab closes and the real document
opens in its place.

- SchemaFormWidget emits item_created/cancelled signals
- SchemaFormDialog preserved as thin modal wrapper for backward compat
- Inline error display replaces modal QMessageBox
- Live tab title updates from part number preview
2026-02-11 15:14:38 -06:00
069bb7a552 Merge pull request 'fix: pull assembly dependencies recursively before opening' (#19) from fix/pull-assembly-dependencies into main
Reviewed-on: #19
2026-02-11 19:12:22 +00:00
201e0af450 feat: register Silo overlay context for EditingContextResolver
Add 'Silo Origin' toolbar (Commit/Pull/Push/Info/BOM) registered with
Unavailable visibility. Register a Silo overlay via
FreeCADGui.registerEditingOverlay() that appends this toolbar to any
active editing context when the current document is Silo-tracked
(ownsDocument() returns True).

Consolidate PySide.QtCore imports.
2026-02-11 13:11:47 -06:00
8a6e5cdffa fix: pull assembly dependencies recursively before opening
When pulling an assembly from Silo, the linked component files were not
downloaded, causing FreeCAD to report 'Link not restored' errors for
every external reference.

Add _pull_dependencies() that queries the BOM API to discover child
part numbers, then downloads the latest file revision for each child
that doesn't already exist locally. Recurses into sub-assemblies.

Silo_Pull.Activated() now calls _pull_dependencies() after downloading
the assembly file and before opening it, so all PropertyXLink paths
resolve correctly.
2026-02-11 13:09:59 -06:00
95c56fa29a Merge pull request 'feat/schema-driven-new-item-form' (#18) from feat/schema-driven-new-item-form into main
Reviewed-on: #18
2026-02-11 16:19:05 +00:00
33d5eeb76c Merge branch 'main' into feat/schema-driven-new-item-form 2026-02-11 16:18:55 +00:00
9e83982c78 feat: schema-driven Qt form for new item creation
Replace the 3-dialog chain (category → description → projects) with a
single SchemaFormDialog that fetches schema data from the Silo REST API
and builds the UI dynamically at runtime.

New dialog features:
- Two-stage category picker (domain combo → subcategory combo)
- Dynamic property fields grouped by domain and common defaults
- Collapsible form sections (Identity, Sourcing, Details, Properties)
- Live part number preview via POST /api/generate-part-number
- Item type selection (part, assembly, consumable, tool)
- Sourcing fields (type, cost, URL)
- Project tagging via multi-select list
- Widget factory: string→QLineEdit, number→QDoubleSpinBox+unit,
  boolean→QCheckBox

The form mirrors the React CreateItemPane.tsx layout and uses the same
API endpoints:
- GET /api/schemas/kindred-rd (category enum values)
- GET /api/schemas/kindred-rd/properties?category={code}
- GET /api/projects
- POST /api/items (via _client.create_item)
2026-02-11 08:42:18 -06:00
e83769090b fix: use Qt enum for setWindowModality instead of raw integer
PySide6 requires the proper enum type QtCore.Qt.WindowModal, not the
raw integer 2. The integer form was accepted by PySide2/Qt5 but raises
TypeError in PySide6.
2026-02-11 07:40:05 -06:00
52fc9cdd3a Merge pull request 'fix: save Modified attribute and SSE retry reset' (#17) from fix/silo-sse-and-save into main
Reviewed-on: #17
2026-02-11 01:15:53 +00:00
ae132948d1 Merge branch 'main' into fix/silo-sse-and-save 2026-02-11 01:15:39 +00:00
Zoe Forbes
ab801601c9 fix: save Modified attribute and SSE retry reset
- silo_origin.py: use Gui.Document.Modified instead of App.Document.Modified
  (re-applies fix from #13 that was lost in rebase)
- silo_origin.py: add traceback logging to saveDocument error handler
- silo_commands.py: reset SSE retry counter after connections lasting >30s
  so transient disconnects don't permanently kill the listener
2026-02-10 19:00:13 -06:00
32d5f1ea1b Merge pull request 'fix: use FreeCADGui.Document.Modified instead of App.Document.IsModified()' (#16) from fix/pull-is-modified-bug into main
Reviewed-on: #16
2026-02-10 16:41:23 +00:00
de80e392f5 Merge branch 'main' into fix/pull-is-modified-bug 2026-02-10 16:41:15 +00:00
ba42343577 Merge pull request 'feat: native Qt start panel with Silo API + kindred:// URL scheme' (#15) from feat/native-start-panel-167 into main
Reviewed-on: #15
2026-02-10 16:40:58 +00:00
af7eab3a70 Merge branch 'main' into feat/native-start-panel-167 2026-02-10 16:40:49 +00:00
6c9789fdf3 fix: use FreeCADGui.Document.Modified instead of App.Document.IsModified()
App.Document has no IsModified() method, causing Silo_Pull to crash with
AttributeError. The correct API is to get the Gui document and check its
Modified property, consistent with the pattern used elsewhere in this file
(lines 891, 913).
2026-02-10 10:39:13 -06:00
85bfb17854 feat: native Qt start panel with Silo API + kindred:// URL scheme
Replace QWebEngineView-based start page with a rich native Qt panel that
fetches items directly from the Silo REST API. QWebEngineView is not
available on conda-forge for Qt6.

Start panel features:
- Database Items list with search (from SiloClient.list_items)
- Recent Files list from FreeCAD preferences
- Real-time Activity Feed via SSE (SiloEventListener)
- Context menu: Open in Create, Open in Browser, Copy Part Number
- Open in Browser button (QDesktopServices)
- Catppuccin Mocha dark theme styling

URL scheme support:
- handle_kindred_url() function for kindred://item/{part_number} URLs
- Startup hook in InitGui.py for cold-start URL arguments

Closes #167
2026-02-10 10:30:12 -06:00
6d231e80dd Merge pull request 'fix: use Gui.Document.Modified instead of App.Document.Modified' (#14) from fix/save-modified-attribute into main
Reviewed-on: #14
2026-02-10 12:57:29 +00:00
a7ef5f195b Merge branch 'main' into fix/save-modified-attribute 2026-02-10 12:57:16 +00:00
Zoe Forbes
7cf5867a7a fix: use Gui.Document.Modified instead of App.Document.Modified (#13)
App.Document has no 'Modified' attribute — it only exists on
Gui.Document. This caused every Silo save to fail with:
  Silo save failed: 'App.Document' object has no attribute 'Modified'

The save itself succeeded but the modified flag was never cleared,
so the document always appeared unsaved.
2026-02-09 18:40:42 -06:00
Zoe Forbes
9a6d1dfbd2 fix: use Gui.Document.Modified instead of App.Document.Modified (#13)
App.Document has no 'Modified' attribute — it only exists on
Gui.Document. This caused every Silo save to fail with:
  Silo save failed: 'App.Document' object has no attribute 'Modified'

The save itself succeeded but the modified flag was never cleared,
so the document always appeared unsaved.
2026-02-09 18:40:18 -06:00
8937cb5e8b Merge pull request 'feat(freecad): add Silo-aware start page with webview and offline fallback' (#12) from feat/silo-start-page into main 2026-02-09 17:28:34 +00:00
a53cd52c73 feat(freecad): add Silo-aware start page with webview and offline fallback
Replaces the default FreeCAD Start page with a dual-mode view:
- Online: QWebEngineView loading the Silo web app
- Offline: native Qt fallback with recent files and connectivity status

The command override is registered at InitGui.py load time, before
the C++ StartLauncher fires.
2026-02-09 11:28:16 -06:00
Zoe Forbes
c6e187a75c Merge fix/sse-url-and-origin-open 2026-02-08 22:54:37 -06:00
Zoe Forbes
2e9bf52082 fix: SSE URL double /api/ and SiloOrigin command invocation (#84)
- Fix SSE listener URL: _listen() used '/api/events' but _get_api_url()
  already returns a URL ending in '/api', producing '/api/api/events'.
  Changed to '/events' to match _test_sse().
- Replace all Command.get().Activated() calls in silo_origin.py with
  FreeCADGui.runCommand(). The C++ Gui::Command wrapper returned by
  Command.get() does not expose .Activated() to Python.
2026-02-08 22:54:28 -06:00
Zoe Forbes
383eefce9c fix(UX): offer registration when BOM opened on untracked document (#56)
Replace the dead-end warning in Silo_BOM with a question dialog that
offers to register the document via Silo_New. If the user accepts and
registration succeeds, the BOM dialog opens seamlessly.
2026-02-08 18:46:22 -06:00
Zoe Forbes
1676b3e1a0 art: add missing icons for TagProjects, Rollback, SetStatus (#60)
Create silo-tag.svg, silo-rollback.svg, and silo-status.svg in the
Catppuccin Mocha style matching existing silo icons. These were
referenced by _icon() but did not exist, causing the commands to
render without toolbar icons.
2026-02-08 18:36:22 -06:00
Zoe Forbes
06cd30e88d fix: update silo-client — consistent error handling in delete_bom_entry (#59) 2026-02-08 18:29:31 -06:00
f9924d35f7 Merge pull request 'feat: enhance Database Activity pane with comments, interaction, and badges' (#11) from feature/activity-pane-enhancements into main
Reviewed-on: #11
2026-02-08 22:23:50 +00:00
373f3aaa79 Merge branch 'main' into feature/activity-pane-enhancements 2026-02-08 22:23:40 +00:00
66b2baf510 Merge pull request 'fix: SSE reconnect with exponential backoff and terminal state' (#7) from fix/sse-reconnect into main
Reviewed-on: #7
2026-02-08 22:23:23 +00:00
35f33f2079 Merge branch 'main' into fix/sse-reconnect 2026-02-08 22:23:16 +00:00
Zoe Forbes
d26bb6da2d feat: enhance Database Activity pane with comments, interaction, and badges
Enhance the Database Activity panel in SiloAuthDockWidget:

- Show latest revision number and comment inline per activity entry
- Truncate long descriptions with ellipsis, full text in tooltip
- Mark locally checked-out items with green color and "local" badge
- Double-click opens local file or triggers checkout from server
- Right-click context menu: Open in Create, Open in Browser,
  Copy Part Number, View Revisions

Closes #9
2026-02-08 16:23:06 -06:00
Zoe Forbes
e5126c913d fix: SSE reconnect with exponential backoff and terminal state
Replace the infinite fixed-delay retry loop with exponential backoff
(1s, 2s, 4s, ... capped at 60s) and a max retry limit of 10.

Changes to SiloEventListener:
- Expand connection_status signal to (status, retry_count, error_message)
- Add exponential backoff: min(BASE_DELAY * 2^retries, MAX_DELAY)
- Add terminal "gave_up" state after MAX_RETRIES exhausted
- Capture and forward error messages from failed connection attempts

Changes to SiloAuthDockWidget._on_sse_status:
- Show retry count: "Reconnecting (3/10)..."
- Show "Disconnected" (red) on gave_up state
- Log each attempt to FreeCAD console (PrintWarning/PrintError)
- Set tooltip with last error message on the status label

Closes #2
2026-02-08 16:22:55 -06:00
76973aaae0 Merge pull request 'feat: add Silo_Diag connection diagnostics command' (#6) from feature/silo-diag into main
Reviewed-on: #6
2026-02-08 22:22:51 +00:00
Zoe Forbes
4ddbf26af7 feat: add Silo_Diag connection diagnostics command
Add a diagnostics command that sequentially tests:
- DNS resolution of the server hostname
- Health endpoint (/health)
- Readiness endpoint (/ready)
- Auth endpoint (/auth/me) with token
- SSE event stream (/events)

Results are printed to the FreeCAD console with PASS/FAIL status.

Closes #3
2026-02-08 16:22:25 -06:00
516116ae9d Merge pull request 'feat: add silo-aware start panel' (#10) from feature/start-panel into main
Reviewed-on: #10
2026-02-08 22:11:55 +00:00
Zoe Forbes
6fa60af5e0 feat: add silo-aware start panel
Add a SiloStartPanel dock widget that shows connection status, local
checkouts, recent silo activity, and local recent files. Automatically
shown when the Silo workbench is activated.

Sections:
- Connection status badge (green/gray dot with hostname)
- My Checkouts: scans local projects dir for .FCStd files, shows part
  number and description, double-click to open
- Recent Silo Activity: fetches from server, badges items present
  locally, double-click to open or checkout
- Local Recent Files: reads FreeCAD MRU list, double-click to open

Auto-refreshes every 60 seconds. Panel is reused if already open.

Closes #5
2026-02-08 16:11:33 -06:00
fd3c97ff97 Merge pull request 'feat: reflect server mode in client UI' (#8) from feature/server-mode-ui into main
Reviewed-on: #8
2026-02-08 22:10:22 +00:00
fb9e1d3188 Merge branch 'main' into feature/server-mode-ui 2026-02-08 22:10:14 +00:00
Zoe Forbes
026ed0cb8a feat: reflect server mode in client UI
Add server mode awareness to the FreeCAD client. The mode (normal,
read-only, degraded, offline) is fetched from the /ready endpoint on
each status refresh and updated in real-time via SSE server.state events.

Changes:
- Add _server_mode global and _fetch_server_mode() helper that queries
  /ready and maps response status to mode string
- Add server_mode_changed signal to SiloEventListener, handle
  server.state SSE events in _dispatch()
- Add mode banner to SiloAuthDockWidget: colored bar shown when server
  is not in normal mode (yellow=read-only, orange=degraded, red=offline)
- Update _refresh_status() to fetch mode and update banner
- Disable write commands (New, Save, Commit, Push) when server is not
  in normal mode via IsActive() checks

Closes #4
2026-02-08 16:06:48 -06:00