rf-mcp 0.34.0.dev1__tar.gz → 0.34.0.dev3__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.
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/PKG-INFO +1 -1
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/pyproject.toml +1 -1
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/platynui_focus.py +2 -2
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/suite_execution_service.py +69 -9
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/test_builder.py +51 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/library_checker.py +4 -1
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.gitignore +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/@msgpackr-extract/msgpackr-extract-linux-x64/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/@standard-schema/spec/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/@standard-schema/spec/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/cross-spawn/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/cross-spawn/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/detect-libc/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/detect-libc/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/effect/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/effect/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/fast-check/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/fast-check/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/find-my-way-ts/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/find-my-way-ts/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/ini/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/ini/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/isexe/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/isexe/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/kubernetes-types/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/msgpackr/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/msgpackr/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/msgpackr-extract/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/msgpackr-extract/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/multipasta/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/multipasta/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/node-gyp-build-optional-packages/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/node-gyp-build-optional-packages/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/pure-rand/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/pure-rand/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/toml/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/toml/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/uuid/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/which/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/which/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/yaml/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/yaml/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/zod/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/zod/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/LICENSE +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/README.md +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/adapters/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/adapters/adapter_factory.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/adapters/browser_adapter.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/adapters/page_state_adapter.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/adapters/playwright_adapter.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/adapters/recovery_adapter.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/adapters/selenium_adapter.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/attach/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/attach/mcp_attach.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/compat/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/compat/fastmcp_compat.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/browser/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/browser/browser_library_manager.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/desktop_display_safety.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/desktop_execution_signals.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/desktop_guidance.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/desktop_launch_env.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/execution_coordinator.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/external_rf_client.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/keyword_executor.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/locator_arg_introspection.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/locator_converter.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/mobile_capability_service.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/page_source_service.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/rf_native_context_manager.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/session_manager.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/ui_tree_service.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/keyword_matcher.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/library_recommender.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/nlp_processor.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/state_manager.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/variables/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/variables/variable_resolver.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/config/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/config/library_registry.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/container.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/core/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/core/dynamic_keyword_orchestrator.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/core/event_bus.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/core/keyword_discovery.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/core/library_manager.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/core/session_manager.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/artifact_output/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/artifact_output/aggregates.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/artifact_output/entities.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/artifact_output/events.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/artifact_output/services.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/artifact_output/value_objects.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/batch_execution/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/batch_execution/aggregates.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/batch_execution/entities.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/batch_execution/events.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/batch_execution/services.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/batch_execution/value_objects.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/instruction/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/instruction/adapters/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/instruction/adapters/fastmcp_adapter.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/instruction/aggregates.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/instruction/entities.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/instruction/events.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/instruction/repository.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/instruction/security.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/instruction/services.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/instruction/value_objects.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/intent/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/intent/adapters/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/intent/adapters/locator_normalizer_adapter.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/intent/adapters/mcp_tool.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/intent/adapters/session_lookup_adapter.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/intent/aggregates.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/intent/entities.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/intent/events.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/intent/services.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/intent/value_objects.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/keyword_resolution/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/keyword_resolution/aggregates.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/keyword_resolution/events.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/keyword_resolution/services.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/keyword_resolution/value_objects.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/memory/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/memory/adapters/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/memory/adapters/fastmcp_adapter.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/memory/adapters/sqlite_vec_adapter.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/memory/aggregates.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/memory/entities.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/memory/events.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/memory/repository.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/memory/services.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/memory/value_objects.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/recovery/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/recovery/aggregates.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/recovery/entities.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/recovery/events.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/recovery/services.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/recovery/value_objects.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/response_optimization/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/response_optimization/aggregates.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/response_optimization/events.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/response_optimization/repository.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/response_optimization/services.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/response_optimization/value_objects.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/shared/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/shared/kernel.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/snapshot/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/snapshot/aggregates.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/snapshot/delta_aggregates.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/snapshot/delta_entities.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/snapshot/delta_events.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/snapshot/delta_service.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/snapshot/delta_value_objects.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/snapshot/diff_service.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/snapshot/entities.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/snapshot/events.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/snapshot/list_folding.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/snapshot/models.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/snapshot/repository.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/snapshot/services.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/snapshot/value_objects.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/timeout/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/timeout/aggregates.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/timeout/entities.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/timeout/events.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/timeout/keyword_classifier.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/timeout/services.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/timeout/value_objects.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/token_accounting/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/token_accounting/aggregates.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/token_accounting/entities.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/token_accounting/events.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/token_accounting/repository.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/token_accounting/services.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/token_accounting/value_objects.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/tool_profile/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/tool_profile/adapters/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/tool_profile/adapters/fastmcp_adapter.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/tool_profile/aggregates.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/tool_profile/entities.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/tool_profile/events.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/tool_profile/repository.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/tool_profile/services.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/tool_profile/value_objects.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/entry.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/frontend/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/frontend/api.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/frontend/apps.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/frontend/asgi.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/frontend/bridge.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/frontend/config.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/frontend/controller.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/frontend/devserver.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/frontend/django_app.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/frontend/static/frontend/app.js +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/frontend/static/frontend/base.css +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/frontend/templates/frontend/index.html +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/frontend/templates/frontend/layout.html +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/frontend/urls.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/frontend/views.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/models/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/models/browser_models.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/models/config_models.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/models/execution_models.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/models/library_models.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/models/session_models.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/onboarding/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/onboarding/adapters.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/onboarding/cli.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/onboarding/codecs.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/onboarding/diagnostics.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/onboarding/installer.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/onboarding/manifest.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/optimization/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/optimization/collector.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/optimization/compression_learner.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/optimization/folding_learner.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/optimization/instruction_hooks.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/optimization/instruction_learner.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/optimization/page_analyzer.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/optimization/pattern_store.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/optimization/ref_learner.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/optimization/timeout_learner.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/plugins/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/plugins/base.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/plugins/builtin/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/plugins/builtin/browser_plugin.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/plugins/builtin/definitions.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/plugins/builtin/platynui_plugin.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/plugins/builtin/requests_plugin.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/plugins/builtin/selenium_plugin.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/plugins/contracts.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/plugins/discovery.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/plugins/manager.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/server.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/__init__.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/argument_processor.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/enhanced_response_serializer.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/enhanced_serialization_integration.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/hints.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/libdoc_argument_parser.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/library_detection.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/library_detector.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/library_loading_validator.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/logging_setup.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/requests_guidance.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/response_serializer.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/rf_libdoc_integration.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/rf_native_type_converter.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/rf_variables_compatibility.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/sampling.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/server_integration.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/session_resolution.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/token_efficient_output.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/validation.py +0 -0
- {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/utils/visual_guidance.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rf-mcp
|
|
3
|
-
Version: 0.34.0.
|
|
3
|
+
Version: 0.34.0.dev3
|
|
4
4
|
Summary: Robot Framework MCP Server - Natural Language Test Automation Bridge
|
|
5
5
|
Project-URL: Homepage, https://github.com/manykarim/rf-mcp
|
|
6
6
|
Project-URL: Repository, https://github.com/manykarim/rf-mcp
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rf-mcp"
|
|
7
|
-
version = "0.34.0.
|
|
7
|
+
version = "0.34.0.dev3"
|
|
8
8
|
description = "Robot Framework MCP Server - Natural Language Test Automation Bridge"
|
|
9
9
|
authors = [{ name = "Many Kasiriha" }]
|
|
10
10
|
license = { text = "Apache-2.0" }
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/platynui_focus.py
RENAMED
|
@@ -1052,7 +1052,7 @@ def x11_window_present(
|
|
|
1052
1052
|
try:
|
|
1053
1053
|
proc = subprocess.run(
|
|
1054
1054
|
[sys.executable, "-c", _X11_WINDOW_PROBE_SRC, *names],
|
|
1055
|
-
capture_output=True, text=True, timeout=5, env=env,
|
|
1055
|
+
capture_output=True, text=True, timeout=5, env=env, stdin=subprocess.DEVNULL,
|
|
1056
1056
|
)
|
|
1057
1057
|
out = (proc.stdout or "").strip()
|
|
1058
1058
|
return out if out in ("present", "absent", "unknown") else "unknown"
|
|
@@ -1143,7 +1143,7 @@ def x11_display_pids() -> Optional[frozenset]:
|
|
|
1143
1143
|
try:
|
|
1144
1144
|
proc = subprocess.run(
|
|
1145
1145
|
[sys.executable, "-c", _X11_PID_LIST_PROBE_SRC],
|
|
1146
|
-
capture_output=True, text=True, timeout=5, env=dict(os.environ),
|
|
1146
|
+
capture_output=True, text=True, timeout=5, env=dict(os.environ), stdin=subprocess.DEVNULL,
|
|
1147
1147
|
)
|
|
1148
1148
|
out = (proc.stdout or "").strip()
|
|
1149
1149
|
if not out or out == "unknown":
|
|
@@ -13,6 +13,7 @@ import json
|
|
|
13
13
|
import io
|
|
14
14
|
import subprocess
|
|
15
15
|
import sys
|
|
16
|
+
import signal
|
|
16
17
|
from contextlib import redirect_stdout, redirect_stderr
|
|
17
18
|
|
|
18
19
|
try:
|
|
@@ -31,6 +32,37 @@ from robotmcp.models.config_models import ExecutionConfig
|
|
|
31
32
|
logger = logging.getLogger(__name__)
|
|
32
33
|
|
|
33
34
|
|
|
35
|
+
def _kill_process_tree(proc: "subprocess.Popen") -> None:
|
|
36
|
+
"""Best-effort terminate a child process AND all of its descendants.
|
|
37
|
+
|
|
38
|
+
change: fix-mcp-subprocess-stdin-deadlock. A plain ``proc.kill()`` reaps only the
|
|
39
|
+
direct child; a surviving grandchild (e.g. the uv-trampoline launcher's real
|
|
40
|
+
interpreter) keeps the captured stdout/stderr pipes open and hangs the post-kill
|
|
41
|
+
``communicate()``. On Windows we ``taskkill /F /T`` the PID tree; on POSIX we
|
|
42
|
+
``killpg`` (the child is spawned with ``start_new_session=True``). Never raises.
|
|
43
|
+
"""
|
|
44
|
+
pid = getattr(proc, "pid", None)
|
|
45
|
+
if pid is not None:
|
|
46
|
+
try:
|
|
47
|
+
if os.name == "nt":
|
|
48
|
+
subprocess.run(
|
|
49
|
+
["taskkill", "/F", "/T", "/PID", str(pid)],
|
|
50
|
+
stdin=subprocess.DEVNULL,
|
|
51
|
+
stdout=subprocess.DEVNULL,
|
|
52
|
+
stderr=subprocess.DEVNULL,
|
|
53
|
+
timeout=10,
|
|
54
|
+
)
|
|
55
|
+
else:
|
|
56
|
+
os.killpg(os.getpgid(pid), signal.SIGKILL)
|
|
57
|
+
except Exception:
|
|
58
|
+
pass # missing taskkill / already-dead / permission — fall through
|
|
59
|
+
# Ensure the direct child is gone regardless.
|
|
60
|
+
try:
|
|
61
|
+
proc.kill()
|
|
62
|
+
except Exception:
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
|
|
34
66
|
class SuiteExecutionService:
|
|
35
67
|
"""Service for executing Robot Framework test suites in dry run and normal modes."""
|
|
36
68
|
|
|
@@ -297,6 +329,12 @@ class SuiteExecutionService:
|
|
|
297
329
|
start_time = datetime.now()
|
|
298
330
|
|
|
299
331
|
# Prepare Robot Framework options
|
|
332
|
+
# NOTE: do NOT add --console none here. The dry-run captures RF's console output
|
|
333
|
+
# via a PIPE and the validation parser reads it (there is no output.xml —
|
|
334
|
+
# --output NONE), so suppressing the console would blank suite_info/test_count.
|
|
335
|
+
# The stdin=DEVNULL isolation below (change: fix-mcp-subprocess-stdin-deadlock)
|
|
336
|
+
# is what fixes the Windows deadlock; the captured stdout is a pipe, not an
|
|
337
|
+
# inherited handle, so there is nothing to defend against with --console none.
|
|
300
338
|
rf_options = ["--dryrun", "--output", "NONE", "--report", "NONE", "--log", "NONE"]
|
|
301
339
|
|
|
302
340
|
# Add validation level options (execution_options may override loglevel)
|
|
@@ -325,20 +363,42 @@ class SuiteExecutionService:
|
|
|
325
363
|
# write to the underlying stdout fd and bypass contextlib.redirect_stdout).
|
|
326
364
|
def run_robot_dry():
|
|
327
365
|
cmd = [sys.executable, "-m", "robot", *rf_options]
|
|
366
|
+
# stdin=DEVNULL: the dry-run child MUST NOT inherit the MCP server's stdin
|
|
367
|
+
# (its JSON-RPC read channel). On Windows an inherited synchronous stdin
|
|
368
|
+
# pipe deadlocks the child's C-runtime stdio init behind the server's
|
|
369
|
+
# pending read → the dry-run hangs the full timeout (change:
|
|
370
|
+
# fix-mcp-subprocess-stdin-deadlock). Popen (not subprocess.run) so a
|
|
371
|
+
# timeout can reap the whole tree BEFORE draining the pipes.
|
|
372
|
+
popen_kwargs = dict(
|
|
373
|
+
stdin=subprocess.DEVNULL,
|
|
374
|
+
stdout=subprocess.PIPE,
|
|
375
|
+
stderr=subprocess.PIPE,
|
|
376
|
+
text=True,
|
|
377
|
+
encoding="utf-8",
|
|
378
|
+
errors="replace",
|
|
379
|
+
)
|
|
380
|
+
if os.name != "nt":
|
|
381
|
+
popen_kwargs["start_new_session"] = True # own group for killpg
|
|
328
382
|
try:
|
|
329
|
-
proc = subprocess.
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
)
|
|
337
|
-
return proc.returncode, proc.stdout or "", proc.stderr or ""
|
|
383
|
+
proc = subprocess.Popen(cmd, **popen_kwargs)
|
|
384
|
+
except Exception as e:
|
|
385
|
+
logger.error(f"Robot Framework dry run error: {e}")
|
|
386
|
+
return 252, "", str(e)
|
|
387
|
+
try:
|
|
388
|
+
stdout, stderr = proc.communicate(timeout=timeout_s)
|
|
389
|
+
return proc.returncode, stdout or "", stderr or ""
|
|
338
390
|
except subprocess.TimeoutExpired:
|
|
391
|
+
# Reap the whole tree so an orphaned grandchild cannot keep the
|
|
392
|
+
# capture pipes open and hang the drain below.
|
|
393
|
+
_kill_process_tree(proc)
|
|
394
|
+
try:
|
|
395
|
+
proc.communicate(timeout=5)
|
|
396
|
+
except Exception:
|
|
397
|
+
pass
|
|
339
398
|
raise
|
|
340
399
|
except Exception as e:
|
|
341
400
|
logger.error(f"Robot Framework dry run error: {e}")
|
|
401
|
+
_kill_process_tree(proc)
|
|
342
402
|
return 252, "", str(e)
|
|
343
403
|
|
|
344
404
|
loop = asyncio.get_event_loop()
|
|
@@ -110,6 +110,39 @@ class GeneratedTestSuite:
|
|
|
110
110
|
column_headers: Optional[List[str]] = None
|
|
111
111
|
|
|
112
112
|
|
|
113
|
+
# change: fix-suite-arg-escape-roundtrip. RF recognizes only \n \r \t (+ \xHH \uHHHH
|
|
114
|
+
# \UHHHHHHHH) as escapes and drops the backslash for anything else. Preserve those and the
|
|
115
|
+
# syntax escapes rf-mcp/agents rely on; double every other literal backslash so RF's parser
|
|
116
|
+
# recovers the value. Idempotent: an already-doubled \\ is kept as a pair.
|
|
117
|
+
_RF_ESCAPE_PRESERVE_NEXT = frozenset("nrtxuU=#$@&%{} ")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _escape_aware_backslashes(s: str) -> str:
|
|
121
|
+
"""Double literal backslashes that RF would drop, preserving real/intended escapes."""
|
|
122
|
+
if "\\" not in s:
|
|
123
|
+
return s
|
|
124
|
+
out: List[str] = []
|
|
125
|
+
i, n = 0, len(s)
|
|
126
|
+
while i < n:
|
|
127
|
+
c = s[i]
|
|
128
|
+
if c == "\\":
|
|
129
|
+
nxt = s[i + 1] if i + 1 < n else ""
|
|
130
|
+
if nxt == "\\":
|
|
131
|
+
out.append("\\\\") # keep an existing \\ pair verbatim (idempotent)
|
|
132
|
+
i += 2
|
|
133
|
+
continue
|
|
134
|
+
if nxt in _RF_ESCAPE_PRESERVE_NEXT:
|
|
135
|
+
out.append("\\") # recognized/intended escape — do not double
|
|
136
|
+
i += 1
|
|
137
|
+
continue
|
|
138
|
+
out.append("\\\\") # unrecognized escape / trailing lone \ — double it
|
|
139
|
+
i += 1
|
|
140
|
+
continue
|
|
141
|
+
out.append(c)
|
|
142
|
+
i += 1
|
|
143
|
+
return "".join(out)
|
|
144
|
+
|
|
145
|
+
|
|
113
146
|
class TestBuilder:
|
|
114
147
|
"""Builds Robot Framework test suites from successful execution steps."""
|
|
115
148
|
|
|
@@ -4098,6 +4131,24 @@ class TestBuilder:
|
|
|
4098
4131
|
# Fix malformed evaluation namespace expressions first
|
|
4099
4132
|
arg = self._fix_malformed_evaluation_namespace(arg)
|
|
4100
4133
|
|
|
4134
|
+
# Platform-independent path form (change: fix-suite-path-escaping): a Windows
|
|
4135
|
+
# DRIVE-LETTER path is rewritten to forward slashes — valid for Start Process/
|
|
4136
|
+
# subprocess and the OperatingSystem keywords on BOTH Windows and POSIX, and
|
|
4137
|
+
# RF-escape-safe. Without this, RF's escape processing corrupts a literal
|
|
4138
|
+
# backslash path (C:\WINDOWS -> C:WINDOWS; C:\name -> embedded newline).
|
|
4139
|
+
# Only the unambiguous drive-letter shape is touched; flags (/w), URLs
|
|
4140
|
+
# (https://…) and variable references do NOT match and are left unchanged.
|
|
4141
|
+
if re.match(r"^[A-Za-z]:[\\/]", arg):
|
|
4142
|
+
arg = arg.replace("\\", "/")
|
|
4143
|
+
|
|
4144
|
+
# Escape-aware backslash round-trip (change: fix-suite-arg-escape-roundtrip). RF
|
|
4145
|
+
# drops the backslash for every escape it does not recognize (\d -> d, \W -> W), so
|
|
4146
|
+
# a literal backslash (regex, relative Windows path) is corrupted on parse. Double
|
|
4147
|
+
# a backslash ONLY where RF would drop it; PRESERVE RF's real escapes (\n \r \t,
|
|
4148
|
+
# \x \u \U), an already-doubled \\, and the intended syntax escapes (\= \# \$ \{ \}
|
|
4149
|
+
# \@ \& \% \<space>). Idempotent, and leaves ${..} references (no backslash) intact.
|
|
4150
|
+
arg = _escape_aware_backslashes(arg)
|
|
4151
|
+
|
|
4101
4152
|
# Escape literal newlines/tabs so they don't break the .robot line structure.
|
|
4102
4153
|
# RF uses \n / \t as escape sequences, so we emit \\n / \\t in the text
|
|
4103
4154
|
# which RF interprets back as the literal characters at runtime.
|
|
@@ -97,9 +97,12 @@ class LibraryAvailabilityChecker:
|
|
|
97
97
|
def check_pip_package_installed(self, package_name: str) -> bool:
|
|
98
98
|
"""Check if a pip package is installed using pip list."""
|
|
99
99
|
try:
|
|
100
|
+
# stdin=DEVNULL: never inherit the MCP server's stdin — an inherited
|
|
101
|
+
# synchronous stdin pipe deadlocks this child on Windows behind the server's
|
|
102
|
+
# pending JSON-RPC read (change: fix-mcp-subprocess-stdin-deadlock).
|
|
100
103
|
result = subprocess.run([
|
|
101
104
|
sys.executable, '-m', 'pip', 'list', '--format=freeze'
|
|
102
|
-
], capture_output=True, text=True, timeout=10)
|
|
105
|
+
], capture_output=True, text=True, timeout=10, stdin=subprocess.DEVNULL)
|
|
103
106
|
|
|
104
107
|
if result.returncode == 0:
|
|
105
108
|
installed_packages = result.stdout.lower()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/.kilo/node_modules/@standard-schema/spec/README.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/browser/browser_library_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/desktop_guidance.py
RENAMED
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/desktop_launch_env.py
RENAMED
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/execution_coordinator.py
RENAMED
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/external_rf_client.py
RENAMED
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/keyword_executor.py
RENAMED
|
File without changes
|
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/locator_converter.py
RENAMED
|
File without changes
|
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/page_source_service.py
RENAMED
|
File without changes
|
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/session_manager.py
RENAMED
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/execution/ui_tree_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/components/variables/variable_resolver.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/artifact_output/aggregates.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/artifact_output/value_objects.py
RENAMED
|
File without changes
|
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/batch_execution/aggregates.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/batch_execution/value_objects.py
RENAMED
|
File without changes
|
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/instruction/adapters/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/keyword_resolution/__init__.py
RENAMED
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/keyword_resolution/aggregates.py
RENAMED
|
File without changes
|
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/keyword_resolution/services.py
RENAMED
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/keyword_resolution/value_objects.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/memory/adapters/fastmcp_adapter.py
RENAMED
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/memory/adapters/sqlite_vec_adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/response_optimization/__init__.py
RENAMED
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/response_optimization/aggregates.py
RENAMED
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/response_optimization/events.py
RENAMED
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/response_optimization/repository.py
RENAMED
|
File without changes
|
{rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev3}/src/robotmcp/domains/response_optimization/services.py
RENAMED
|
File without changes
|
|
File without changes
|