answer42 0.4.85__tar.gz → 0.4.87__tar.gz

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 (64) hide show
  1. {answer42-0.4.85 → answer42-0.4.87}/PKG-INFO +1 -1
  2. {answer42-0.4.85 → answer42-0.4.87}/docs/architecture.md +1 -1
  3. {answer42-0.4.85 → answer42-0.4.87}/pyproject.toml +1 -1
  4. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/rag/dump.py +2 -0
  5. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/server.py +56 -3
  6. {answer42-0.4.85 → answer42-0.4.87}/.gitignore +0 -0
  7. {answer42-0.4.85 → answer42-0.4.87}/LICENSE +0 -0
  8. {answer42-0.4.85 → answer42-0.4.87}/README.md +0 -0
  9. {answer42-0.4.85 → answer42-0.4.87}/credentials.example.json +0 -0
  10. {answer42-0.4.85 → answer42-0.4.87}/docs/agent-installation.md +0 -0
  11. {answer42-0.4.85 → answer42-0.4.87}/docs/assets/answer42-logo.png +0 -0
  12. {answer42-0.4.85 → answer42-0.4.87}/docs/assets/platform42-logo.svg +0 -0
  13. {answer42-0.4.85 → answer42-0.4.87}/docs/installation.md +0 -0
  14. {answer42-0.4.85 → answer42-0.4.87}/scripts/build_cf.py +0 -0
  15. {answer42-0.4.85 → answer42-0.4.87}/scripts/build_pages.py +0 -0
  16. {answer42-0.4.85 → answer42-0.4.87}/scripts/e2e_http_smoke.py +0 -0
  17. {answer42-0.4.85 → answer42-0.4.87}/scripts/e2e_stable.py +0 -0
  18. {answer42-0.4.85 → answer42-0.4.87}/scripts/openclaw_mcp_autoreload.py +0 -0
  19. {answer42-0.4.85 → answer42-0.4.87}/scripts/rag_cli.py +0 -0
  20. {answer42-0.4.85 → answer42-0.4.87}/src/cf/ConfigDumpInfo.xml +0 -0
  21. {answer42-0.4.85 → answer42-0.4.87}/src/cf/Configuration.xml +0 -0
  22. {answer42-0.4.85 → answer42-0.4.87}/src/cf/DataProcessors/MCPTestManager/Ext/ObjectModule.bsl +0 -0
  23. {answer42-0.4.85 → answer42-0.4.87}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260/Ext/Form/Module.bsl" +0 -0
  24. {answer42-0.4.85 → answer42-0.4.87}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260/Ext/Form.xml" +0 -0
  25. {answer42-0.4.85 → answer42-0.4.87}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260.xml" +0 -0
  26. {answer42-0.4.85 → answer42-0.4.87}/src/cf/DataProcessors/MCPTestManager.xml +0 -0
  27. {answer42-0.4.85 → answer42-0.4.87}/src/cf/Ext/ManagedApplicationModule.bsl +0 -0
  28. {answer42-0.4.85 → answer42-0.4.87}/src/cf/Languages//320/240/321/203/321/201/321/201/320/272/320/270/320/271.xml" +0 -0
  29. {answer42-0.4.85 → answer42-0.4.87}/src/client_cf/Catalogs//320/237/320/241_/320/222/320/273/320/260/320/264/320/265/320/273/320/265/321/206.xml" +0 -0
  30. {answer42-0.4.85 → answer42-0.4.87}/src/client_cf/Catalogs//320/237/320/241_/320/241/320/277/321/200/320/260/320/262/320/276/321/207/320/275/320/270/320/2721.xml" +0 -0
  31. {answer42-0.4.85 → answer42-0.4.87}/src/client_cf/ConfigDumpInfo.xml +0 -0
  32. {answer42-0.4.85 → answer42-0.4.87}/src/client_cf/Configuration.xml +0 -0
  33. {answer42-0.4.85 → answer42-0.4.87}/src/client_cf/Languages//320/240/321/203/321/201/321/201/320/272/320/270/320/271.xml" +0 -0
  34. {answer42-0.4.85 → answer42-0.4.87}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262/Ext/ManagerModule.bsl" +0 -0
  35. {answer42-0.4.85 → answer42-0.4.87}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262/Ext/ObjectModule.bsl" +0 -0
  36. {answer42-0.4.85 → answer42-0.4.87}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262/Templates//320/236/321/201/320/275/320/276/320/262/320/275/320/260/321/217/320/241/321/205/320/265/320/274/320/260/320/232/320/276/320/274/320/277/320/276/320/275/320/276/320/262/320/272/320/270/320/224/320/260/320/275/320/275/321/213/321/205/Ext/Template.xml" +0 -0
  37. {answer42-0.4.85 → answer42-0.4.87}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262/Templates//320/236/321/201/320/275/320/276/320/262/320/275/320/260/321/217/320/241/321/205/320/265/320/274/320/260/320/232/320/276/320/274/320/277/320/276/320/275/320/276/320/262/320/272/320/270/320/224/320/260/320/275/320/275/321/213/321/205.xml" +0 -0
  38. {answer42-0.4.85 → answer42-0.4.87}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262.xml" +0 -0
  39. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/__init__.py +0 -0
  40. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/assets/MCPTestClient.cf +0 -0
  41. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/assets/MCPTestManager.cf +0 -0
  42. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/assets/__init__.py +0 -0
  43. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/assets/skills/answer42/SKILL.md +0 -0
  44. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/assets/skills/answer42-rag/SKILL.md +0 -0
  45. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/assets/skills/answer42-universal-report/SKILL.md +0 -0
  46. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/auth.py +0 -0
  47. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/bridge.py +0 -0
  48. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/credentials.py +0 -0
  49. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/os_support.py +0 -0
  50. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/platform.py +0 -0
  51. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/protocol.py +0 -0
  52. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/rag/__init__.py +0 -0
  53. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/rag/detect.py +0 -0
  54. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/rag/model.py +0 -0
  55. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/rag/parsers.py +0 -0
  56. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/rag/service.py +0 -0
  57. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/rag/store.py +0 -0
  58. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/rag/summary_backend.py +0 -0
  59. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/rag/summary_vector.py +0 -0
  60. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/recorder.py +0 -0
  61. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/release_helper.py +0 -0
  62. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/runtime.py +0 -0
  63. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/skill_installer.py +0 -0
  64. {answer42-0.4.85 → answer42-0.4.87}/src/mcp_1c/window_control.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: answer42
3
- Version: 0.4.85
3
+ Version: 0.4.87
4
4
  Summary: Answer42 — The Answer to Life, Universe, and 1C — UI Driver. MCP-powered 1C:Enterprise UI automation: click, fill, navigate, test, and introspect managed forms through the test-client API
5
5
  Author: Marvin (AI Assistant), 42Clouds, and contributors
6
6
  Author-email: "Kosolapov Stanislav (proDOOMman)" <prodoomman@gmail.com>
@@ -233,7 +233,7 @@ large remote infobases.
233
233
  | `ONEC_MCP_WS_HOST` | WebSocket host | `127.0.0.1` |
234
234
  | `ONEC_MCP_WS_PORT` | WebSocket port | `8765` |
235
235
  | `ONEC_MCP_REQUEST_TIMEOUT` | Таймаут запроса, сек | `60` |
236
- | `ONEC_MCP_DATA_DIR` | Рабочая директория | `/tmp/answer42` |
236
+ | `ONEC_MCP_DATA_DIR` | Рабочая директория | OS tempdir + `answer42` (`/tmp/answer42` on Linux, `%TEMP%\answer42` on Windows) |
237
237
  | `MCP_1C_RAG_DB` | Путь к RAG SQLite | `build/rag/onec-rag.sqlite` |
238
238
  | `ONEC_MCP_DISABLE_RAG` | Отключить встроенный RAG (`1/true/yes/on`) | пусто |
239
239
  | `ONEC_MCP_RAG_SOURCE_DIRS` | `:`/`;`-separated directories for startup RAG discovery/watch | пусто |
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "answer42"
3
- version = "0.4.85"
3
+ version = "0.4.87"
4
4
  description = "Answer42 — The Answer to Life, Universe, and 1C — UI Driver. MCP-powered 1C:Enterprise UI automation: click, fill, navigate, test, and introspect managed forms through the test-client API"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -31,6 +31,8 @@ def _run_designer(argv: list[str], *, timeout: float = 600, display: str = "") -
31
31
 
32
32
 
33
33
  def _find_free_display() -> str:
34
+ if os_support.IS_WINDOWS:
35
+ return ""
34
36
  return _platform.find_free_display(99)
35
37
 
36
38
 
@@ -678,15 +678,68 @@ class SessionState:
678
678
  _SESSIONS: dict[str, SessionState] = {}
679
679
 
680
680
 
681
+ def _runtime_output_file(prefix: str, session_id: str, suffix: str) -> Path:
682
+ """Return a writable cross-platform runtime output path for 1C file saves."""
683
+ safe_prefix = re.sub(r"[^A-Za-z0-9_.-]+", "-", str(prefix or "answer42")).strip(".-") or "answer42"
684
+ safe_session = re.sub(r"[^A-Za-z0-9_.-]+", "-", str(session_id or DEFAULT_SESSION)).strip(".-") or DEFAULT_SESSION
685
+ safe_suffix = suffix if suffix.startswith(".") else f".{suffix}"
686
+ output_dir = os_support.default_data_dir() / "exports"
687
+ output_dir.mkdir(parents=True, exist_ok=True)
688
+ return output_dir / f"{safe_prefix}_{safe_session}_{uuid.uuid4().hex}{safe_suffix}"
689
+
690
+
681
691
  def _pid_is_running(pid: int) -> bool:
682
692
  if pid <= 0:
683
693
  return False
694
+ if os_support.IS_WINDOWS:
695
+ # ``os.kill(pid, 0)`` is a POSIX liveness probe. On Windows CPython
696
+ # delegates to TerminateProcess even for signal 0 and may raise
697
+ # unrelated OSError values such as WinError 11 instead of answering
698
+ # whether the process exists. Use the native process handle API there.
699
+ try:
700
+ import ctypes
701
+ from ctypes import wintypes
702
+
703
+ kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
704
+ open_process = kernel32.OpenProcess
705
+ open_process.argtypes = [wintypes.DWORD, wintypes.BOOL, wintypes.DWORD]
706
+ open_process.restype = wintypes.HANDLE
707
+ close_handle = kernel32.CloseHandle
708
+ close_handle.argtypes = [wintypes.HANDLE]
709
+ close_handle.restype = wintypes.BOOL
710
+ get_exit_code_process = kernel32.GetExitCodeProcess
711
+ get_exit_code_process.argtypes = [wintypes.HANDLE, ctypes.POINTER(wintypes.DWORD)]
712
+ get_exit_code_process.restype = wintypes.BOOL
713
+
714
+ PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
715
+ ERROR_ACCESS_DENIED = 5
716
+ ERROR_INVALID_PARAMETER = 87
717
+ STILL_ACTIVE = 259
718
+ handle = open_process(PROCESS_QUERY_LIMITED_INFORMATION, False, int(pid))
719
+ if not handle:
720
+ error = ctypes.get_last_error()
721
+ if error == ERROR_ACCESS_DENIED:
722
+ return True
723
+ if error == ERROR_INVALID_PARAMETER:
724
+ return False
725
+ return False
726
+ try:
727
+ exit_code = wintypes.DWORD()
728
+ if not get_exit_code_process(handle, ctypes.byref(exit_code)):
729
+ return True
730
+ return int(exit_code.value) == STILL_ACTIVE
731
+ finally:
732
+ close_handle(handle)
733
+ except Exception:
734
+ return False
684
735
  try:
685
736
  os.kill(pid, 0)
686
737
  except ProcessLookupError:
687
738
  return False
688
739
  except PermissionError:
689
740
  return True
741
+ except OSError:
742
+ return False
690
743
  return True
691
744
 
692
745
 
@@ -8385,7 +8438,7 @@ async def _metadata_rows_from_universal_report(
8385
8438
  read_warnings: list[str] = []
8386
8439
  last_saved_path = ""
8387
8440
  save_diagnostics: Any = {}
8388
- mxl_path = Path("/tmp/answer42") / f"metadata_objects_{session_id}_{uuid.uuid4().hex}.mxl"
8441
+ mxl_path = _runtime_output_file("metadata_objects", session_id, ".mxl")
8389
8442
  try:
8390
8443
  selected_result = await _tabular_document_save_filter_by_filter(
8391
8444
  session_id,
@@ -8428,7 +8481,7 @@ async def _metadata_rows_from_universal_report(
8428
8481
  )
8429
8482
  return rows[:max_rows], warnings
8430
8483
 
8431
- report_path = Path("/tmp/answer42") / f"metadata_objects_{session_id}_{uuid.uuid4().hex}.xlsx"
8484
+ report_path = _runtime_output_file("metadata_objects", session_id, ".xlsx")
8432
8485
  try:
8433
8486
  selected_result = await _tabular_document_save_filter_by_filter(
8434
8487
  session_id,
@@ -9113,7 +9166,7 @@ async def _save_output_tabular_document_to_mxl(
9113
9166
  if not doc_name:
9114
9167
  warnings.append("List output did not return a tabular document name for MXL save")
9115
9168
  return []
9116
- mxl_path = Path("/tmp/answer42") / f"{path_prefix}_{session_id}_{uuid.uuid4().hex}.mxl"
9169
+ mxl_path = _runtime_output_file(path_prefix, session_id, ".mxl")
9117
9170
  try:
9118
9171
  selected_result = await _tabular_document_save_filter_by_filter(
9119
9172
  session_id,
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes