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,282 @@
1
+ """Docs context fetching and RAG ingestion for the Prefab CAD dashboard.
2
+
3
+ Responsibilities (Single Responsibility principle):
4
+ - Fetch and filter docs from the MCP docs endpoint (``fetch_docs_context``).
5
+ - Ingest local files or URLs into the simple retrieval index (``ingest_reference_source``).
6
+
7
+ Does NOT own: LLM calls, preview export, session state mutation beyond metadata merges.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import json
13
+ from pathlib import Path
14
+ from typing import Any
15
+ from urllib.parse import urlparse
16
+ from urllib.request import Request, urlopen
17
+
18
+ from loguru import logger
19
+
20
+ from ...agents.history_db import insert_evidence_link, insert_tool_call_record
21
+ from ...agents.retrieval_index import _chunk_text
22
+ from ._utils import (
23
+ DEFAULT_API_ORIGIN,
24
+ DEFAULT_RAG_DIR,
25
+ HTMLTextExtractor,
26
+ filter_docs_text,
27
+ is_url_reference,
28
+ merge_metadata,
29
+ persist_ui_action,
30
+ read_reference_source,
31
+ read_reference_url,
32
+ sanitize_ui_text,
33
+ )
34
+
35
+ # ---------------------------------------------------------------------------
36
+ # Public API
37
+ # ---------------------------------------------------------------------------
38
+
39
+
40
+ def fetch_docs_context(
41
+ session_id: str,
42
+ *,
43
+ docs_query: str = "",
44
+ db_path: Path | None = None,
45
+ api_origin: str = DEFAULT_API_ORIGIN,
46
+ ) -> dict[str, Any]:
47
+ """Fetch docs text from the ``/docs`` endpoint and store a filtered context snippet.
48
+
49
+ Args:
50
+ session_id: Dashboard session identifier.
51
+ docs_query: Keyword(s) to filter the docs text by.
52
+ db_path: Optional override for the SQLite database path.
53
+ api_origin: Base URL of the running FastAPI server.
54
+
55
+ Returns:
56
+ Full dashboard state payload.
57
+ """
58
+ from .session_service import ( # noqa: PLC0415
59
+ build_dashboard_state,
60
+ ensure_dashboard_session,
61
+ )
62
+
63
+ ensure_dashboard_session(session_id, db_path=db_path)
64
+ docs_url = f"{api_origin}/docs"
65
+ query_text = sanitize_ui_text(docs_query, "solidworks workflow")
66
+ if urlparse(docs_url).scheme not in {"http", "https"}:
67
+ raise ValueError(f"Disallowed URL scheme in docs endpoint: {docs_url!r}")
68
+ try:
69
+ request = Request(docs_url, headers={"User-Agent": "solidworks-mcp-ui/1.0"})
70
+ with urlopen(request, timeout=8) as response: # nosec B310
71
+ html = response.read().decode("utf-8", errors="ignore")
72
+ extractor = HTMLTextExtractor()
73
+ extractor.feed(html)
74
+ snippet = filter_docs_text(extractor.text(), query_text)
75
+ persist_ui_action(
76
+ session_id,
77
+ tool_name="ui.docs.fetch",
78
+ db_path=db_path,
79
+ metadata_updates={
80
+ "docs_query": query_text,
81
+ "docs_context_text": snippet,
82
+ "latest_message": "Docs context updated from MCP docs endpoint.",
83
+ "latest_error_text": "",
84
+ "remediation_hint": "",
85
+ },
86
+ input_payload={"query": query_text, "url": docs_url},
87
+ output_payload={"chars": len(snippet)},
88
+ )
89
+ except Exception as exc:
90
+ logger.exception("[ui.fetch_docs_context] failed session_id={}", session_id)
91
+ merge_metadata(
92
+ session_id,
93
+ db_path=db_path,
94
+ docs_query=query_text,
95
+ docs_context_text="",
96
+ latest_error_text=str(exc),
97
+ remediation_hint="Verify the /docs endpoint is reachable, then retry docs refresh.",
98
+ )
99
+ return build_dashboard_state(session_id, db_path=db_path, api_origin=api_origin)
100
+
101
+
102
+ def ingest_reference_source(
103
+ session_id: str,
104
+ *,
105
+ source_path: str,
106
+ namespace: str,
107
+ chunk_size: int = 1200,
108
+ overlap: int = 200,
109
+ db_path: Path | None = None,
110
+ ) -> dict[str, Any]:
111
+ """Ingest a local file or URL into the simple local retrieval index.
112
+
113
+ Args:
114
+ session_id: Dashboard session identifier.
115
+ source_path: Absolute file path or http/https URL.
116
+ namespace: Namespace key that isolates this index from others.
117
+ chunk_size: Maximum characters per chunk.
118
+ overlap: Overlapping characters between adjacent chunks.
119
+ db_path: Optional override for the SQLite database path.
120
+
121
+ Returns:
122
+ Full dashboard state payload.
123
+ """
124
+ from .session_service import ( # noqa: PLC0415
125
+ build_dashboard_state,
126
+ ensure_dashboard_session,
127
+ )
128
+
129
+ ensure_dashboard_session(session_id, db_path=db_path)
130
+ source_reference = (source_path or "").strip()
131
+ resolved_namespace = (
132
+ namespace or "engineering-reference"
133
+ ).strip() or "engineering-reference"
134
+
135
+ try:
136
+ if is_url_reference(source_reference):
137
+ source_identifier = source_reference
138
+ source_text, source_label = read_reference_url(source_reference)
139
+ else:
140
+ resolved_source = Path(source_reference).expanduser()
141
+ if not resolved_source.exists():
142
+ merge_metadata(
143
+ session_id,
144
+ db_path=db_path,
145
+ rag_source_path=str(resolved_source),
146
+ rag_namespace=resolved_namespace,
147
+ rag_status="Reference source path was not found.",
148
+ latest_error_text=f"Missing reference source: {resolved_source}",
149
+ remediation_hint=(
150
+ "Provide an absolute path or an http/https URL for a PDF, "
151
+ "markdown, text, or HTML source."
152
+ ),
153
+ )
154
+ return build_dashboard_state(session_id, db_path=db_path)
155
+ source_identifier = str(resolved_source.resolve())
156
+ source_label = resolved_source.name
157
+ source_text = read_reference_source(resolved_source)
158
+
159
+ chunks = _chunk_text(source_text, chunk_size=chunk_size, overlap=overlap)
160
+ output_path = DEFAULT_RAG_DIR / f"{resolved_namespace}.json"
161
+ output_path.parent.mkdir(parents=True, exist_ok=True)
162
+ payload: dict[str, Any] = {
163
+ "version": "1.0",
164
+ "namespace": resolved_namespace,
165
+ "source_location": source_identifier,
166
+ "chunk_count": len(chunks),
167
+ "chunks": [
168
+ {
169
+ "id": f"{resolved_namespace}-{index}",
170
+ "source": source_identifier,
171
+ "text": chunk,
172
+ }
173
+ for index, chunk in enumerate(chunks, start=1)
174
+ ],
175
+ }
176
+ output_path.write_text(
177
+ json.dumps(payload, indent=2, ensure_ascii=True), encoding="utf-8"
178
+ )
179
+
180
+ # --- FAISS vector index (best-effort; skipped if optional deps missing) ---
181
+ try:
182
+ from ...agents.vector_rag import VectorRAGIndex # noqa: PLC0415
183
+
184
+ idx = VectorRAGIndex.load(
185
+ namespace=resolved_namespace, rag_dir=DEFAULT_RAG_DIR
186
+ )
187
+ for chunk in payload["chunks"]:
188
+ idx.ingest_text(
189
+ chunk["text"], source=source_identifier, tags=[resolved_namespace]
190
+ )
191
+ idx.save()
192
+ logger.info(
193
+ "[ui.ingest_reference_source] FAISS index updated namespace={} chunks={}",
194
+ resolved_namespace,
195
+ len(chunks),
196
+ )
197
+ except ImportError:
198
+ logger.debug(
199
+ "[ui.ingest_reference_source] FAISS not available; skipping vector index"
200
+ )
201
+ except Exception as faiss_exc:
202
+ logger.warning(
203
+ "[ui.ingest_reference_source] FAISS indexing failed (non-fatal): {}",
204
+ faiss_exc,
205
+ )
206
+
207
+ insert_evidence_link(
208
+ session_id=session_id,
209
+ source_type="rag_ingest",
210
+ source_id=source_identifier,
211
+ relevance_score=0.88,
212
+ rationale=f"Ingested {len(chunks)} chunk(s) into namespace '{resolved_namespace}'.",
213
+ payload_json=json.dumps(
214
+ {
215
+ "namespace": resolved_namespace,
216
+ "index_path": str(output_path.resolve()),
217
+ "chunk_count": len(chunks),
218
+ },
219
+ ensure_ascii=True,
220
+ ),
221
+ db_path=db_path,
222
+ )
223
+ merge_metadata(
224
+ session_id,
225
+ db_path=db_path,
226
+ rag_source_path=source_identifier,
227
+ rag_namespace=resolved_namespace,
228
+ rag_status=f"Ingested {len(chunks)} chunk(s) from {source_label}.",
229
+ rag_index_path=str(output_path.resolve()),
230
+ rag_chunk_count=len(chunks),
231
+ rag_provenance_text=(
232
+ f"Namespace {resolved_namespace} | source {source_label} | chunks {len(chunks)}"
233
+ ),
234
+ latest_message=f"Reference source {source_label} ingested for retrieval.",
235
+ latest_error_text="",
236
+ remediation_hint="",
237
+ )
238
+ insert_tool_call_record(
239
+ session_id=session_id,
240
+ tool_name="ui.ingest_reference_source",
241
+ input_json=json.dumps(
242
+ {
243
+ "source_path": source_identifier,
244
+ "namespace": resolved_namespace,
245
+ "chunk_size": chunk_size,
246
+ "overlap": overlap,
247
+ },
248
+ ensure_ascii=True,
249
+ ),
250
+ output_json=json.dumps(
251
+ {"index_path": str(output_path.resolve()), "chunk_count": len(chunks)},
252
+ ensure_ascii=True,
253
+ ),
254
+ success=True,
255
+ db_path=db_path,
256
+ )
257
+ except Exception as exc:
258
+ merge_metadata(
259
+ session_id,
260
+ db_path=db_path,
261
+ rag_source_path=source_reference,
262
+ rag_namespace=resolved_namespace,
263
+ rag_status="Reference ingestion failed.",
264
+ latest_error_text=str(exc),
265
+ remediation_hint=(
266
+ "Use a readable local file or http/https URL and ensure optional "
267
+ "PDF dependencies are installed."
268
+ ),
269
+ )
270
+ insert_tool_call_record(
271
+ session_id=session_id,
272
+ tool_name="ui.ingest_reference_source",
273
+ input_json=json.dumps(
274
+ {"source_path": source_reference, "namespace": resolved_namespace},
275
+ ensure_ascii=True,
276
+ ),
277
+ output_json=json.dumps({"error": str(exc)}, ensure_ascii=True),
278
+ success=False,
279
+ db_path=db_path,
280
+ )
281
+
282
+ return build_dashboard_state(session_id, db_path=db_path)