solidworks-mcp-python 1.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. solidworks_mcp/__init__.py +57 -0
  2. solidworks_mcp/adapters/__init__.py +40 -0
  3. solidworks_mcp/adapters/base.py +1882 -0
  4. solidworks_mcp/adapters/circuit_breaker.py +2052 -0
  5. solidworks_mcp/adapters/com_executor.py +252 -0
  6. solidworks_mcp/adapters/complexity_analyzer.py +272 -0
  7. solidworks_mcp/adapters/connection_pool.py +1884 -0
  8. solidworks_mcp/adapters/factory.py +366 -0
  9. solidworks_mcp/adapters/intelligent_router.py +218 -0
  10. solidworks_mcp/adapters/mock_adapter.py +4016 -0
  11. solidworks_mcp/adapters/pywin32_adapter.py +2842 -0
  12. solidworks_mcp/adapters/solidworks/__init__.py +17 -0
  13. solidworks_mcp/adapters/solidworks/bitmap.py +180 -0
  14. solidworks_mcp/adapters/solidworks/com_utils.py +56 -0
  15. solidworks_mcp/adapters/solidworks/dimension_layout.py +753 -0
  16. solidworks_mcp/adapters/solidworks/documentation.py +1476 -0
  17. solidworks_mcp/adapters/solidworks/drawing_standard.py +1993 -0
  18. solidworks_mcp/adapters/solidworks/face_selection.py +392 -0
  19. solidworks_mcp/adapters/solidworks/features.py +3362 -0
  20. solidworks_mcp/adapters/solidworks/io.py +3649 -0
  21. solidworks_mcp/adapters/solidworks/rebuild_diagnostics.py +269 -0
  22. solidworks_mcp/adapters/solidworks/rebuild_inspector.py +146 -0
  23. solidworks_mcp/adapters/solidworks/selection.py +308 -0
  24. solidworks_mcp/adapters/solidworks/sketch.py +2545 -0
  25. solidworks_mcp/adapters/sw_feature_errors.py +66 -0
  26. solidworks_mcp/adapters/sw_type_info.py +317 -0
  27. solidworks_mcp/adapters/vba_adapter.py +318 -0
  28. solidworks_mcp/adapters/vba_macro_executor.py +215 -0
  29. solidworks_mcp/agents/__init__.py +68 -0
  30. solidworks_mcp/agents/design_knowledge/assembly_patterns.md +127 -0
  31. solidworks_mcp/agents/design_knowledge/hinges.md +118 -0
  32. solidworks_mcp/agents/design_knowledge/snap_fits.md +93 -0
  33. solidworks_mcp/agents/design_knowledge/solidworks_basics.md +3 -0
  34. solidworks_mcp/agents/design_knowledge/tolerancing.md +128 -0
  35. solidworks_mcp/agents/harness.py +216 -0
  36. solidworks_mcp/agents/history_db.py +1508 -0
  37. solidworks_mcp/agents/retrieval_index.py +164 -0
  38. solidworks_mcp/agents/schemas.py +165 -0
  39. solidworks_mcp/agents/smoke_test.py +285 -0
  40. solidworks_mcp/agents/soc_exporter.py +650 -0
  41. solidworks_mcp/agents/soc_pickup.py +332 -0
  42. solidworks_mcp/agents/soc_rewind.py +221 -0
  43. solidworks_mcp/agents/vector_rag.py +665 -0
  44. solidworks_mcp/cache/__init__.py +5 -0
  45. solidworks_mcp/cache/response_cache.py +164 -0
  46. solidworks_mcp/config.py +729 -0
  47. solidworks_mcp/exceptions.py +37 -0
  48. solidworks_mcp/security/__init__.py +68 -0
  49. solidworks_mcp/security/auth.py +128 -0
  50. solidworks_mcp/security/cors.py +27 -0
  51. solidworks_mcp/security/rate_limiting.py +90 -0
  52. solidworks_mcp/security/runtime.py +155 -0
  53. solidworks_mcp/server.py +777 -0
  54. solidworks_mcp/server_cli_fixed.py +120 -0
  55. solidworks_mcp/setup/__init__.py +1 -0
  56. solidworks_mcp/setup/cli.py +399 -0
  57. solidworks_mcp/setup/clients.py +157 -0
  58. solidworks_mcp/setup/config_file.py +230 -0
  59. solidworks_mcp/setup/handshake.py +202 -0
  60. solidworks_mcp/setup/launcher.py +102 -0
  61. solidworks_mcp/setup/legacy.py +100 -0
  62. solidworks_mcp/setup/registration.py +193 -0
  63. solidworks_mcp/setup/solidworks.py +49 -0
  64. solidworks_mcp/tools/__init__.py +64 -0
  65. solidworks_mcp/tools/analysis.py +723 -0
  66. solidworks_mcp/tools/automation.py +578 -0
  67. solidworks_mcp/tools/docs_discovery.py +1476 -0
  68. solidworks_mcp/tools/drawing.py +1015 -0
  69. solidworks_mcp/tools/drawing_analysis.py +456 -0
  70. solidworks_mcp/tools/drawing_automation.py +627 -0
  71. solidworks_mcp/tools/engineering_data.py +466 -0
  72. solidworks_mcp/tools/error_classifier.py +232 -0
  73. solidworks_mcp/tools/export.py +833 -0
  74. solidworks_mcp/tools/file_facts.py +40 -0
  75. solidworks_mcp/tools/file_management.py +1473 -0
  76. solidworks_mcp/tools/input_compat.py +17 -0
  77. solidworks_mcp/tools/macro_recording.py +464 -0
  78. solidworks_mcp/tools/modeling.py +2360 -0
  79. solidworks_mcp/tools/sketching.py +1422 -0
  80. solidworks_mcp/tools/template_management.py +367 -0
  81. solidworks_mcp/tools/tool_boundary.py +280 -0
  82. solidworks_mcp/tools/vba_generation.py +1145 -0
  83. solidworks_mcp/ui/__init__.py +9 -0
  84. solidworks_mcp/ui/local_llm.py +725 -0
  85. solidworks_mcp/ui/routers/__init__.py +10 -0
  86. solidworks_mcp/ui/routers/checkpoint.py +24 -0
  87. solidworks_mcp/ui/routers/docs.py +47 -0
  88. solidworks_mcp/ui/routers/llm.py +83 -0
  89. solidworks_mcp/ui/routers/local_model.py +69 -0
  90. solidworks_mcp/ui/routers/model.py +75 -0
  91. solidworks_mcp/ui/routers/preview.py +38 -0
  92. solidworks_mcp/ui/routers/session.py +161 -0
  93. solidworks_mcp/ui/routers/viewer.py +154 -0
  94. solidworks_mcp/ui/schemas.py +502 -0
  95. solidworks_mcp/ui/server.py +298 -0
  96. solidworks_mcp/ui/service.py +481 -0
  97. solidworks_mcp/ui/services/__init__.py +136 -0
  98. solidworks_mcp/ui/services/_utils.py +958 -0
  99. solidworks_mcp/ui/services/checkpoint_service.py +1110 -0
  100. solidworks_mcp/ui/services/docs_service.py +282 -0
  101. solidworks_mcp/ui/services/llm_service.py +956 -0
  102. solidworks_mcp/ui/services/model_service.py +459 -0
  103. solidworks_mcp/ui/services/parameter_repair_service.py +314 -0
  104. solidworks_mcp/ui/services/preview_service.py +489 -0
  105. solidworks_mcp/ui/services/session_service.py +1389 -0
  106. solidworks_mcp/utils/__init__.py +9 -0
  107. solidworks_mcp/utils/feature_tree_classifier.py +342 -0
  108. solidworks_mcp/utils/logging.py +76 -0
  109. solidworks_mcp/utils/validation.py +77 -0
  110. solidworks_mcp/version.py +8 -0
  111. solidworks_mcp_python-1.5.0.dist-info/METADATA +410 -0
  112. solidworks_mcp_python-1.5.0.dist-info/RECORD +115 -0
  113. solidworks_mcp_python-1.5.0.dist-info/WHEEL +4 -0
  114. solidworks_mcp_python-1.5.0.dist-info/entry_points.txt +3 -0
  115. solidworks_mcp_python-1.5.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,481 @@
1
+ """Compatibility shim for legacy imports from solidworks_mcp.ui.service.
2
+
3
+ The UI backend was split into focused modules under solidworks_mcp.ui.services.
4
+ This module preserves historical import paths used by tests and external callers.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import os as os # re-exported: tests read service.os
10
+ from contextlib import contextmanager
11
+ from io import BytesIO
12
+ from pathlib import Path
13
+ from typing import Any
14
+ from urllib.parse import urlparse
15
+ from urllib.request import Request, urlopen
16
+
17
+ from ..adapters import create_adapter
18
+
19
+ # Re-exported (``name as name``) for the legacy ``ui.service.<name>`` imports.
20
+ from ..agents.history_db import (
21
+ get_design_session as get_design_session,
22
+ )
23
+ from ..agents.history_db import (
24
+ insert_model_state_snapshot as insert_model_state_snapshot,
25
+ )
26
+ from ..agents.history_db import (
27
+ list_plan_checkpoints,
28
+ )
29
+ from ..agents.history_db import (
30
+ upsert_design_session as upsert_design_session,
31
+ )
32
+ from ..agents.retrieval_index import _chunk_text
33
+ from ..agents.schemas import RecoverableFailure as _AgentRecoverableFailure
34
+ from ..config import load_config
35
+ from .services import * # noqa: F401,F403,F405
36
+ from .services import _utils as _utils_service
37
+ from .services import checkpoint_service as _checkpoint_service
38
+ from .services import docs_service as _docs_service
39
+ from .services import llm_service as _llm_service
40
+ from .services import model_service as _model_service
41
+ from .services import preview_service as _preview_service
42
+ from .services import session_service as _session_service
43
+ from .services._utils import DEFAULT_API_ORIGIN, DEFAULT_PREVIEW_ORIENTATION
44
+ from .services._utils import (
45
+ context_file_path as _context_file_path_impl,
46
+ )
47
+ from .services._utils import (
48
+ materialize_uploaded_model as _materialize_uploaded_model_impl,
49
+ )
50
+ from .services._utils import (
51
+ merge_metadata as _merge_metadata,
52
+ )
53
+ from .services._utils import (
54
+ normalize_feature_targets as _normalize_feature_targets,
55
+ )
56
+ from .services._utils import (
57
+ safe_context_name as _safe_context_name,
58
+ )
59
+ from .services._utils import (
60
+ sanitize_model_path_text as _sanitize_model_path_text,
61
+ )
62
+ from .services._utils import (
63
+ sanitize_preview_viewer_url as _sanitize_preview_viewer_url,
64
+ )
65
+ from .services.llm_service import (
66
+ Agent,
67
+ OpenAIChatModel,
68
+ OpenAIProvider,
69
+ _ensure_provider_credentials,
70
+ )
71
+
72
+ _ORIG_BUILD_AGENT_MODEL = _llm_service._build_agent_model
73
+ _ORIG_RUN_STRUCTURED_AGENT = _llm_service._run_structured_agent
74
+
75
+ # Keep compatibility with tests importing this symbol from agents.schemas.
76
+ RecoverableFailure = _AgentRecoverableFailure
77
+
78
+ # Legacy constants expected by helper tests.
79
+ DEFAULT_CONTEXT_DIR = _utils_service._DEFAULT_CONTEXT_DIR
80
+ DEFAULT_UPLOADED_MODEL_DIR = _utils_service._DEFAULT_UPLOADED_MODEL_DIR
81
+
82
+ # Keep this symbol available for tests that monkeypatch PDF ingestion behavior.
83
+ try:
84
+ from pypdf import PdfReader # type: ignore
85
+ except Exception:
86
+ PdfReader = None
87
+
88
+
89
+ # Legacy helper retained for test compatibility.
90
+ def _default_model_for_profile(provider: str, profile: str) -> str:
91
+ if provider == "local":
92
+ profile_models = {
93
+ "small": "local:gemma4:e2b",
94
+ "balanced": "local:gemma4:e4b",
95
+ "large": "local:gemma4:26b",
96
+ }
97
+ return profile_models.get(
98
+ (profile or "balanced").lower(), profile_models["balanced"]
99
+ )
100
+
101
+ profile_models = {
102
+ "small": "github:openai/gpt-4.1-mini",
103
+ "balanced": "github:openai/gpt-4.1",
104
+ "large": "github:openai/gpt-4.1",
105
+ }
106
+ return profile_models.get(
107
+ (profile or "balanced").lower(), profile_models["balanced"]
108
+ )
109
+
110
+
111
+ @contextmanager
112
+ def _temporary_module_bindings(module: Any, **bindings: Any):
113
+ original: dict[str, Any] = {}
114
+ for name, value in bindings.items():
115
+ if hasattr(module, name):
116
+ original[name] = getattr(module, name)
117
+ setattr(module, name, value)
118
+ try:
119
+ yield
120
+ finally:
121
+ for name in bindings:
122
+ if name in original:
123
+ setattr(module, name, original[name])
124
+
125
+
126
+ def _read_reference_source(source_path: Path) -> str:
127
+ return _utils_service.read_reference_source(source_path)
128
+
129
+
130
+ def _read_reference_url(source_url: str) -> tuple[str, str]:
131
+ parsed = urlparse(source_url)
132
+ if parsed.scheme not in {"http", "https"}:
133
+ raise ValueError(f"Disallowed URL scheme: {parsed.scheme!r}")
134
+ request = Request(source_url, headers={"User-Agent": "SolidWorksMCP/1.0"})
135
+ with urlopen(request, timeout=20) as response: # nosec B310
136
+ content_type = response.headers.get_content_type()
137
+ charset = response.headers.get_content_charset() or "utf-8"
138
+ raw_bytes = response.read()
139
+ label = Path(parsed.path).name or parsed.netloc or source_url
140
+ suffix = Path(parsed.path).suffix.lower()
141
+
142
+ if content_type == "application/pdf" or suffix == ".pdf":
143
+ if PdfReader is None:
144
+ raise RuntimeError(
145
+ "Install pypdf to ingest PDF sources, or provide a text, markdown, or HTML source instead."
146
+ )
147
+ reader = PdfReader(BytesIO(raw_bytes))
148
+ text = "\n\n".join((page.extract_text() or "") for page in reader.pages).strip()
149
+ return text, label
150
+
151
+ decoded = raw_bytes.decode(charset, errors="ignore")
152
+ if "html" in content_type or suffix in {".html", ".htm"}:
153
+ parser = _utils_service.HTMLTextExtractor()
154
+ parser.feed(decoded)
155
+ return parser.text().strip(), label
156
+
157
+ return decoded.strip(), label
158
+
159
+
160
+ def _build_agent_model(model_name: str, local_endpoint: str | None = None):
161
+ with _temporary_module_bindings(
162
+ _llm_service,
163
+ OpenAIProvider=OpenAIProvider,
164
+ OpenAIChatModel=OpenAIChatModel,
165
+ ):
166
+ return _ORIG_BUILD_AGENT_MODEL(model_name, local_endpoint)
167
+
168
+
169
+ async def _run_structured_agent(*args: Any, **kwargs: Any):
170
+ with _temporary_module_bindings(
171
+ _llm_service,
172
+ Agent=Agent,
173
+ RecoverableFailure=RecoverableFailure,
174
+ _ensure_provider_credentials=_ensure_provider_credentials,
175
+ _build_agent_model=_build_agent_model,
176
+ ):
177
+ result = await _ORIG_RUN_STRUCTURED_AGENT(*args, **kwargs)
178
+ if isinstance(result, RecoverableFailure):
179
+ return result
180
+ if all(
181
+ hasattr(result, name)
182
+ for name in (
183
+ "explanation",
184
+ "remediation_steps",
185
+ "retry_focus",
186
+ "should_retry",
187
+ )
188
+ ):
189
+ return RecoverableFailure(
190
+ explanation=str(getattr(result, "explanation", "")),
191
+ remediation_steps=list(getattr(result, "remediation_steps", []) or []),
192
+ retry_focus=str(getattr(result, "retry_focus", "")) or None,
193
+ should_retry=bool(getattr(result, "should_retry", False)),
194
+ )
195
+ return result
196
+
197
+
198
+ def ensure_uploaded_model_dir(upload_dir: Path | None = None) -> Path:
199
+ return _utils_service.ensure_uploaded_model_dir(
200
+ upload_dir or DEFAULT_UPLOADED_MODEL_DIR
201
+ )
202
+
203
+
204
+ def ensure_context_dir(context_dir: Path | None = None) -> Path:
205
+ return _utils_service.ensure_context_dir(context_dir or DEFAULT_CONTEXT_DIR)
206
+
207
+
208
+ def _materialize_uploaded_model(
209
+ session_id: str,
210
+ uploaded_files: list[dict[str, Any]] | None,
211
+ *,
212
+ upload_dir: Path | None = None,
213
+ ) -> Path:
214
+ return _materialize_uploaded_model_impl(
215
+ session_id,
216
+ uploaded_files,
217
+ upload_dir=upload_dir or DEFAULT_UPLOADED_MODEL_DIR,
218
+ )
219
+
220
+
221
+ def _context_file_path(
222
+ session_id: str,
223
+ *,
224
+ context_name: str | None = None,
225
+ context_dir: Path | None = None,
226
+ ) -> Path:
227
+ return _context_file_path_impl(
228
+ session_id,
229
+ context_name=context_name,
230
+ context_dir=context_dir or DEFAULT_CONTEXT_DIR,
231
+ )
232
+
233
+
234
+ async def _run_checkpoint_tools(planned: dict[str, Any]) -> dict[str, Any]:
235
+ with _temporary_module_bindings(
236
+ _checkpoint_service,
237
+ create_adapter=create_adapter,
238
+ load_config=load_config,
239
+ ):
240
+ return await _checkpoint_service._run_checkpoint_tools(planned)
241
+
242
+
243
+ async def open_target_model(
244
+ session_id: str,
245
+ *,
246
+ model_path: str | None = None,
247
+ uploaded_files: list[dict[str, Any]] | None = None,
248
+ feature_target_text: str = "",
249
+ db_path: Path | None = None,
250
+ api_origin: str = DEFAULT_API_ORIGIN,
251
+ ) -> dict[str, Any]:
252
+ with _temporary_module_bindings(
253
+ _model_service,
254
+ create_adapter=create_adapter,
255
+ load_config=load_config,
256
+ ):
257
+ return await _model_service.open_target_model(
258
+ session_id,
259
+ model_path=model_path,
260
+ uploaded_files=uploaded_files,
261
+ feature_target_text=feature_target_text,
262
+ db_path=db_path,
263
+ api_origin=api_origin,
264
+ )
265
+
266
+
267
+ def fetch_docs_context(
268
+ session_id: str,
269
+ *,
270
+ docs_query: str = "",
271
+ db_path: Path | None = None,
272
+ api_origin: str = DEFAULT_API_ORIGIN,
273
+ ) -> dict[str, Any]:
274
+ with _temporary_module_bindings(
275
+ _docs_service,
276
+ urlopen=urlopen,
277
+ ):
278
+ return _docs_service.fetch_docs_context(
279
+ session_id,
280
+ docs_query=docs_query,
281
+ db_path=db_path,
282
+ api_origin=api_origin,
283
+ )
284
+
285
+
286
+ async def execute_next_checkpoint(
287
+ session_id: str,
288
+ *,
289
+ db_path: Path | None = None,
290
+ ) -> dict[str, Any]:
291
+ with (
292
+ _temporary_module_bindings(
293
+ _session_service,
294
+ ensure_dashboard_session=ensure_dashboard_session, # noqa: F405
295
+ build_dashboard_state=build_dashboard_state, # noqa: F405
296
+ ),
297
+ _temporary_module_bindings(
298
+ _checkpoint_service,
299
+ list_plan_checkpoints=list_plan_checkpoints,
300
+ merge_metadata=_merge_metadata,
301
+ ),
302
+ ):
303
+ return await _checkpoint_service.execute_next_checkpoint(
304
+ session_id, db_path=db_path
305
+ )
306
+
307
+
308
+ async def refresh_preview(
309
+ session_id: str,
310
+ *,
311
+ orientation: str = DEFAULT_PREVIEW_ORIENTATION,
312
+ db_path: Path | None = None,
313
+ preview_dir: Path | None = None,
314
+ api_origin: str = DEFAULT_API_ORIGIN,
315
+ ) -> dict[str, Any]:
316
+ with _temporary_module_bindings(
317
+ _preview_service,
318
+ create_adapter=create_adapter,
319
+ load_config=load_config,
320
+ ):
321
+ return await _preview_service.refresh_preview(
322
+ session_id,
323
+ orientation=orientation,
324
+ db_path=db_path,
325
+ preview_dir=preview_dir,
326
+ api_origin=api_origin,
327
+ )
328
+
329
+
330
+ async def connect_target_model(
331
+ session_id: str,
332
+ *,
333
+ model_path: str | None = None,
334
+ uploaded_files: list[dict[str, Any]] | None = None,
335
+ feature_target_text: str = "",
336
+ db_path: Path | None = None,
337
+ api_origin: str = DEFAULT_API_ORIGIN,
338
+ ) -> dict[str, Any]:
339
+ with (
340
+ _temporary_module_bindings(
341
+ _model_service,
342
+ create_adapter=create_adapter,
343
+ load_config=load_config,
344
+ refresh_preview=refresh_preview,
345
+ ),
346
+ _temporary_module_bindings(
347
+ _preview_service,
348
+ create_adapter=create_adapter,
349
+ load_config=load_config,
350
+ ),
351
+ ):
352
+ return await _model_service.connect_target_model(
353
+ session_id,
354
+ model_path=model_path,
355
+ uploaded_files=uploaded_files,
356
+ feature_target_text=feature_target_text,
357
+ db_path=db_path,
358
+ api_origin=api_origin,
359
+ )
360
+
361
+
362
+ def ingest_reference_source(
363
+ session_id: str,
364
+ *,
365
+ source_path: str,
366
+ namespace: str,
367
+ chunk_size: int = 1200,
368
+ overlap: int = 200,
369
+ db_path: Path | None = None,
370
+ ) -> dict[str, Any]:
371
+ with _temporary_module_bindings(
372
+ _docs_service,
373
+ _chunk_text=_chunk_text,
374
+ read_reference_url=_read_reference_url,
375
+ read_reference_source=_read_reference_source,
376
+ ):
377
+ return _docs_service.ingest_reference_source(
378
+ session_id,
379
+ source_path=source_path,
380
+ namespace=namespace,
381
+ chunk_size=chunk_size,
382
+ overlap=overlap,
383
+ db_path=db_path,
384
+ )
385
+
386
+
387
+ async def _compat_run_structured_agent(*args: Any, **kwargs: Any) -> Any:
388
+ """Run the structured agent and normalise any failure to the LLM service's type.
389
+
390
+ Callers may receive this module's ``RecoverableFailure`` or any object with
391
+ the same four fields; the LLM service only understands its own class.
392
+ """
393
+ result = await _run_structured_agent(*args, **kwargs)
394
+ if isinstance(result, RecoverableFailure):
395
+ return _llm_service.RecoverableFailure(
396
+ explanation=str(getattr(result, "explanation", "")),
397
+ remediation_steps=list(getattr(result, "remediation_steps", []) or []),
398
+ retry_focus=str(getattr(result, "retry_focus", "")) or "",
399
+ should_retry=bool(getattr(result, "should_retry", False)),
400
+ )
401
+ if all(
402
+ hasattr(result, name)
403
+ for name in (
404
+ "explanation",
405
+ "remediation_steps",
406
+ "retry_focus",
407
+ "should_retry",
408
+ )
409
+ ):
410
+ return _llm_service.RecoverableFailure(
411
+ explanation=str(getattr(result, "explanation", "")),
412
+ remediation_steps=list(getattr(result, "remediation_steps", []) or []),
413
+ retry_focus=str(getattr(result, "retry_focus", "")),
414
+ should_retry=bool(getattr(result, "should_retry", False)),
415
+ )
416
+ return result
417
+
418
+
419
+ async def request_clarifications(
420
+ session_id: str,
421
+ user_goal: str,
422
+ *,
423
+ user_answer: str = "",
424
+ model_name: str | None = None,
425
+ db_path: Path | None = None,
426
+ ) -> dict[str, Any]:
427
+ with _temporary_module_bindings(
428
+ _llm_service, _run_structured_agent=_compat_run_structured_agent
429
+ ):
430
+ return await _llm_service.request_clarifications(
431
+ session_id,
432
+ user_goal,
433
+ user_answer=user_answer,
434
+ model_name=model_name,
435
+ db_path=db_path,
436
+ )
437
+
438
+
439
+ async def inspect_family(
440
+ session_id: str,
441
+ user_goal: str,
442
+ *,
443
+ model_name: str | None = None,
444
+ db_path: Path | None = None,
445
+ ) -> dict[str, Any]:
446
+ with _temporary_module_bindings(
447
+ _llm_service, _run_structured_agent=_compat_run_structured_agent
448
+ ):
449
+ return await _llm_service.inspect_family(
450
+ session_id,
451
+ user_goal,
452
+ model_name=model_name,
453
+ db_path=db_path,
454
+ )
455
+
456
+
457
+ # Legacy private helper aliases expected by compatibility tests.
458
+ _sanitize_model_path_text = _sanitize_model_path_text
459
+ _safe_context_name = _safe_context_name
460
+ _normalize_feature_targets = _normalize_feature_targets
461
+ _sanitize_preview_viewer_url = _sanitize_preview_viewer_url
462
+ _sanitize_ui_text = _utils_service.sanitize_ui_text
463
+ _provider_from_model_name = _utils_service.provider_from_model_name
464
+ _workflow_copy = _utils_service.workflow_copy
465
+ _filter_docs_text = _utils_service.filter_docs_text
466
+ _feature_target_status = _utils_service.feature_target_status
467
+ _feature_grounding_warning_text = _utils_service.feature_grounding_warning_text
468
+ _parse_json_blob = _utils_service.parse_json_blob
469
+ _trace_json_default = _utils_service._trace_json_default
470
+ _looks_like_path_token = _utils_service._looks_like_path_token
471
+ _normalize_model_name_for_provider = _utils_service.normalize_model_name_for_provider
472
+ _provider_has_credentials = _utils_service.provider_has_credentials
473
+ _trace_json = _utils_service.trace_json
474
+ _trace_session_row = _utils_service.trace_session_row
475
+ _trace_tool_records = _utils_service.trace_tool_records
476
+
477
+
478
+ __all__ = [
479
+ # core shimmed services
480
+ *[name for name in globals() if not name.startswith("__")],
481
+ ]
@@ -0,0 +1,136 @@
1
+ """Public re-exports for the ``solidworks_mcp.ui.services`` package.
2
+
3
+ Import all public service functions from this package to maintain backward
4
+ compatibility with code that previously imported directly from
5
+ ``solidworks_mcp.ui.service``.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from ._utils import (
11
+ DEFAULT_API_ORIGIN,
12
+ DEFAULT_PREVIEW_ORIENTATION,
13
+ DEFAULT_RAG_DIR,
14
+ DEFAULT_SESSION_ID,
15
+ DEFAULT_SOURCE_MODE,
16
+ DEFAULT_USER_GOAL,
17
+ DEFAULT_WORKFLOW_MODE,
18
+ SUPPORTED_MODEL_UPLOAD_SUFFIXES,
19
+ ensure_context_dir,
20
+ ensure_preview_dir,
21
+ ensure_uploaded_model_dir,
22
+ feature_grounding_warning_text,
23
+ feature_target_status,
24
+ filter_docs_text,
25
+ is_url_reference,
26
+ materialize_uploaded_model,
27
+ merge_metadata,
28
+ normalize_feature_targets,
29
+ normalize_workflow_mode,
30
+ parse_json_blob,
31
+ persist_ui_action,
32
+ provider_from_model_name,
33
+ provider_has_credentials,
34
+ read_reference_source,
35
+ read_reference_url,
36
+ safe_context_name,
37
+ sanitize_model_path_text,
38
+ sanitize_preview_viewer_url,
39
+ sanitize_ui_text,
40
+ trace_json,
41
+ trace_session_row,
42
+ trace_tool_records,
43
+ workflow_copy,
44
+ )
45
+ from .checkpoint_service import execute_next_checkpoint
46
+ from .docs_service import fetch_docs_context, ingest_reference_source
47
+ from .llm_service import (
48
+ CheckpointCandidate,
49
+ ClarificationResponse,
50
+ FamilyInspection,
51
+ inspect_family,
52
+ request_clarifications,
53
+ run_go_orchestration,
54
+ )
55
+ from .model_service import connect_target_model, open_target_model
56
+ from .preview_service import highlight_feature, refresh_preview
57
+ from .session_service import (
58
+ accept_family_choice,
59
+ approve_design_brief,
60
+ build_dashboard_state,
61
+ build_dashboard_trace_payload,
62
+ ensure_dashboard_session,
63
+ load_session_context,
64
+ reconcile_manual_edits,
65
+ save_session_context,
66
+ select_workflow_mode,
67
+ update_session_notes,
68
+ update_ui_preferences,
69
+ )
70
+
71
+ __all__ = [
72
+ # utils
73
+ "DEFAULT_API_ORIGIN",
74
+ "DEFAULT_PREVIEW_ORIENTATION",
75
+ "DEFAULT_RAG_DIR",
76
+ "DEFAULT_SESSION_ID",
77
+ "DEFAULT_SOURCE_MODE",
78
+ "DEFAULT_USER_GOAL",
79
+ "DEFAULT_WORKFLOW_MODE",
80
+ "SUPPORTED_MODEL_UPLOAD_SUFFIXES",
81
+ "ensure_context_dir",
82
+ "ensure_preview_dir",
83
+ "ensure_uploaded_model_dir",
84
+ "feature_grounding_warning_text",
85
+ "feature_target_status",
86
+ "filter_docs_text",
87
+ "is_url_reference",
88
+ "materialize_uploaded_model",
89
+ "merge_metadata",
90
+ "normalize_feature_targets",
91
+ "normalize_workflow_mode",
92
+ "parse_json_blob",
93
+ "persist_ui_action",
94
+ "provider_from_model_name",
95
+ "provider_has_credentials",
96
+ "read_reference_source",
97
+ "read_reference_url",
98
+ "safe_context_name",
99
+ "sanitize_model_path_text",
100
+ "sanitize_preview_viewer_url",
101
+ "sanitize_ui_text",
102
+ "trace_json",
103
+ "trace_session_row",
104
+ "trace_tool_records",
105
+ "workflow_copy",
106
+ # session
107
+ "accept_family_choice",
108
+ "approve_design_brief",
109
+ "build_dashboard_state",
110
+ "build_dashboard_trace_payload",
111
+ "ensure_dashboard_session",
112
+ "load_session_context",
113
+ "reconcile_manual_edits",
114
+ "save_session_context",
115
+ "select_workflow_mode",
116
+ "update_session_notes",
117
+ "update_ui_preferences",
118
+ # llm
119
+ "ClarificationResponse",
120
+ "CheckpointCandidate",
121
+ "FamilyInspection",
122
+ "inspect_family",
123
+ "request_clarifications",
124
+ "run_go_orchestration",
125
+ # checkpoint
126
+ "execute_next_checkpoint",
127
+ # docs
128
+ "fetch_docs_context",
129
+ "ingest_reference_source",
130
+ # model
131
+ "connect_target_model",
132
+ "open_target_model",
133
+ # preview
134
+ "highlight_feature",
135
+ "refresh_preview",
136
+ ]