redeploy 0.2.43__tar.gz → 0.2.44__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 (181) hide show
  1. {redeploy-0.2.43 → redeploy-0.2.44}/PKG-INFO +8 -6
  2. {redeploy-0.2.43 → redeploy-0.2.44}/README.md +5 -5
  3. {redeploy-0.2.43 → redeploy-0.2.44}/pyproject.toml +2 -1
  4. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/__init__.py +1 -1
  5. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/device_map.py +38 -3
  6. redeploy-0.2.44/redeploy/integrations/__init__.py +1 -0
  7. redeploy-0.2.44/redeploy/integrations/op3_bridge.py +74 -0
  8. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy.egg-info/PKG-INFO +8 -6
  9. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy.egg-info/SOURCES.txt +2 -0
  10. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy.egg-info/requires.txt +3 -0
  11. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/apply/__init__.py +0 -0
  12. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/apply/exceptions.py +0 -0
  13. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/apply/executor.py +0 -0
  14. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/apply/handlers.py +0 -0
  15. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/apply/progress.py +0 -0
  16. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/apply/rollback.py +0 -0
  17. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/apply/state.py +0 -0
  18. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/apply/state_apply.py +0 -0
  19. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/apply/utils/__init__.py +0 -0
  20. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/apply/utils/run_container_build.py +0 -0
  21. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/audit.py +0 -0
  22. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/blueprint/__init__.py +0 -0
  23. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/blueprint/extractor.py +0 -0
  24. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/blueprint/generators/__init__.py +0 -0
  25. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/blueprint/generators/docker_compose.py +0 -0
  26. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/blueprint/generators/migration.py +0 -0
  27. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/__init__.py +0 -0
  28. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/__init__.py +0 -0
  29. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/audit.py +0 -0
  30. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/blueprint.py +0 -0
  31. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/detect.py +0 -0
  32. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/devices.py +0 -0
  33. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/diagnose.py +0 -0
  34. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/diff.py +0 -0
  35. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/exec_.py +0 -0
  36. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/export.py +0 -0
  37. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/hardware.py +0 -0
  38. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/import_.py +0 -0
  39. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/init.py +0 -0
  40. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/inspect.py +0 -0
  41. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/patterns.py +0 -0
  42. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/plan_apply.py +0 -0
  43. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/plugin.py +0 -0
  44. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/probe.py +0 -0
  45. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/push.py +0 -0
  46. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/state.py +0 -0
  47. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/status.py +0 -0
  48. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/target.py +0 -0
  49. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/version/__init__.py +0 -0
  50. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/version/commands.py +0 -0
  51. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/version/helpers.py +0 -0
  52. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/version/monorepo.py +0 -0
  53. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/version/release.py +0 -0
  54. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/version/scanner.py +0 -0
  55. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/commands/workflow.py +0 -0
  56. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/core.py +0 -0
  57. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli/display.py +0 -0
  58. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/cli.py +0 -0
  59. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/data_sync.py +0 -0
  60. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/detect/__init__.py +0 -0
  61. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/detect/builtin/__init__.py +0 -0
  62. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/detect/detector.py +0 -0
  63. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/detect/hardware.py +0 -0
  64. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/detect/hardware_rules.py +0 -0
  65. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/detect/probes.py +0 -0
  66. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/detect/remote.py +0 -0
  67. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/detect/templates.py +0 -0
  68. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/detect/workflow.py +0 -0
  69. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/discovery.py +0 -0
  70. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/dsl/__init__.py +0 -0
  71. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/dsl/loader.py +0 -0
  72. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/dsl/parser.py +0 -0
  73. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/dsl_python/__init__.py +0 -0
  74. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/dsl_python/context.py +0 -0
  75. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/dsl_python/decorators.py +0 -0
  76. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/dsl_python/docker_steps.py +0 -0
  77. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/dsl_python/exceptions.py +0 -0
  78. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/dsl_python/runner.py +0 -0
  79. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/dsl_python/steps.py +0 -0
  80. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/fleet.py +0 -0
  81. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/hardware/__init__.py +0 -0
  82. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/hardware/config_txt.py +0 -0
  83. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/hardware/data/__init__.py +0 -0
  84. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/hardware/data/hyperpixel.py +0 -0
  85. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/hardware/data/official.py +0 -0
  86. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/hardware/data/waveshare.py +0 -0
  87. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/hardware/fixes.py +0 -0
  88. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/hardware/kiosk/__init__.py +0 -0
  89. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/hardware/kiosk/autostart.py +0 -0
  90. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/hardware/kiosk/browsers.py +0 -0
  91. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/hardware/kiosk/compositors.py +0 -0
  92. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/hardware/kiosk/output_profiles.py +0 -0
  93. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/hardware/panels.py +0 -0
  94. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/hardware/raspi_config.py +0 -0
  95. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/iac/__init__.py +0 -0
  96. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/iac/base.py +0 -0
  97. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/iac/docker_compose.py +0 -0
  98. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/iac/parsers/__init__.py +0 -0
  99. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/iac/parsers/compose.py +0 -0
  100. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/iac/registry.py +0 -0
  101. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/markpact/__init__.py +0 -0
  102. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/markpact/compiler.py +0 -0
  103. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/markpact/models.py +0 -0
  104. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/markpact/parser.py +0 -0
  105. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/models.py +0 -0
  106. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/observe.py +0 -0
  107. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/parse.py +0 -0
  108. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/patterns.py +0 -0
  109. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/plan/__init__.py +0 -0
  110. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/plan/planner.py +0 -0
  111. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/plugins/__init__.py +0 -0
  112. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/plugins/builtin/__init__.py +0 -0
  113. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/plugins/builtin/browser_reload.py +0 -0
  114. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/plugins/builtin/hardware_diagnostic.py +0 -0
  115. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/plugins/builtin/notify.py +0 -0
  116. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/plugins/builtin/process_control.py +0 -0
  117. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/plugins/builtin/systemd_reload.py +0 -0
  118. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/spec_loader.py +0 -0
  119. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/ssh.py +0 -0
  120. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/steps.py +0 -0
  121. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/__init__.py +0 -0
  122. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_audit.py +0 -0
  123. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_cli.py +0 -0
  124. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_data_sync.py +0 -0
  125. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_discovery.py +0 -0
  126. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_dsl.py +0 -0
  127. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_examples.py +0 -0
  128. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_executor.py +0 -0
  129. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_fleet.py +0 -0
  130. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_git_integration.py +0 -0
  131. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_iac.py +0 -0
  132. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_manifest.py +0 -0
  133. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_markpact_compiler.py +0 -0
  134. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_markpact_parser.py +0 -0
  135. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_models.py +0 -0
  136. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_observe.py +0 -0
  137. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_parse.py +0 -0
  138. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_patterns.py +0 -0
  139. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_planner_edge.py +0 -0
  140. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_plugins.py +0 -0
  141. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_probes.py +0 -0
  142. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_public_api.py +0 -0
  143. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_resume.py +0 -0
  144. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_spec_loader.py +0 -0
  145. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_ssh.py +0 -0
  146. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_templates.py +0 -0
  147. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_verify.py +0 -0
  148. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_version.py +0 -0
  149. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_version_changelog.py +0 -0
  150. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_version_cli.py +0 -0
  151. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_version_manifest.py +0 -0
  152. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_version_sources.py +0 -0
  153. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/tests/test_workflow.py +0 -0
  154. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/verify.py +0 -0
  155. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version/__init__.py +0 -0
  156. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version/bump.py +0 -0
  157. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version/changelog.py +0 -0
  158. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version/commits.py +0 -0
  159. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version/diff.py +0 -0
  160. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version/git_integration.py +0 -0
  161. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version/git_transaction.py +0 -0
  162. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version/manifest.py +0 -0
  163. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version/sources/__init__.py +0 -0
  164. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version/sources/base.py +0 -0
  165. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version/sources/json_.py +0 -0
  166. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version/sources/plain.py +0 -0
  167. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version/sources/regex.py +0 -0
  168. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version/sources/toml_.py +0 -0
  169. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version/sources/yaml_.py +0 -0
  170. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version/transaction.py +0 -0
  171. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy/version.py +0 -0
  172. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy.egg-info/dependency_links.txt +0 -0
  173. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy.egg-info/entry_points.txt +0 -0
  174. {redeploy-0.2.43 → redeploy-0.2.44}/redeploy.egg-info/top_level.txt +0 -0
  175. {redeploy-0.2.43 → redeploy-0.2.44}/setup.cfg +0 -0
  176. {redeploy-0.2.43 → redeploy-0.2.44}/tests/test_hardware_config.py +0 -0
  177. {redeploy-0.2.43 → redeploy-0.2.44}/tests/test_hardware_kiosk.py +0 -0
  178. {redeploy-0.2.43 → redeploy-0.2.44}/tests/test_hardware_rules.py +0 -0
  179. {redeploy-0.2.43 → redeploy-0.2.44}/tests/test_iac.py +0 -0
  180. {redeploy-0.2.43 → redeploy-0.2.44}/tests/test_parse.py +0 -0
  181. {redeploy-0.2.43 → redeploy-0.2.44}/tests/test_redeploy.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: redeploy
3
- Version: 0.2.43
3
+ Version: 0.2.44
4
4
  Summary: Infrastructure migration toolkit: detect → plan → apply
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -22,23 +22,25 @@ Requires-Dist: ruff>=0.4; extra == "dev"
22
22
  Requires-Dist: goal>=2.1.0; extra == "dev"
23
23
  Requires-Dist: costs>=0.1.20; extra == "dev"
24
24
  Requires-Dist: pfix>=0.1.60; extra == "dev"
25
+ Provides-Extra: op3
26
+ Requires-Dist: op3>=0.1.4; extra == "op3"
25
27
 
26
28
  # redeploy
27
29
 
28
30
 
29
31
  ## AI Cost Tracking
30
32
 
31
- ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.2.43-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
32
- ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-21.0h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
33
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.2.44-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
34
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-21.4h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
33
35
 
34
- - 🤖 **LLM usage:** $7.5000 (64 commits)
35
- - 👤 **Human dev:** ~$2099 (21.0h @ $100/h, 30min dedup)
36
+ - 🤖 **LLM usage:** $7.5000 (65 commits)
37
+ - 👤 **Human dev:** ~$2136 (21.4h @ $100/h, 30min dedup)
36
38
 
37
39
  Generated on 2026-04-21 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
38
40
 
39
41
  ---
40
42
 
41
- ![PyPI](https://img.shields.io/badge/pypi-redeploy-blue) ![Version](https://img.shields.io/badge/version-0.2.43-blue) ![Python](https://img.shields.io/badge/python-3.10+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
43
+ ![PyPI](https://img.shields.io/badge/pypi-redeploy-blue) ![Version](https://img.shields.io/badge/version-0.2.44-blue) ![Python](https://img.shields.io/badge/python-3.10+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
42
44
 
43
45
  Infrastructure migration and device deploy toolkit — VPS, Raspberry Pi kiosk, Podman Quadlet, k3s.
44
46
 
@@ -3,17 +3,17 @@
3
3
 
4
4
  ## AI Cost Tracking
5
5
 
6
- ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.2.43-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
7
- ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-21.0h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
6
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.2.44-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
7
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-21.4h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
8
8
 
9
- - 🤖 **LLM usage:** $7.5000 (64 commits)
10
- - 👤 **Human dev:** ~$2099 (21.0h @ $100/h, 30min dedup)
9
+ - 🤖 **LLM usage:** $7.5000 (65 commits)
10
+ - 👤 **Human dev:** ~$2136 (21.4h @ $100/h, 30min dedup)
11
11
 
12
12
  Generated on 2026-04-21 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
13
13
 
14
14
  ---
15
15
 
16
- ![PyPI](https://img.shields.io/badge/pypi-redeploy-blue) ![Version](https://img.shields.io/badge/version-0.2.43-blue) ![Python](https://img.shields.io/badge/python-3.10+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
16
+ ![PyPI](https://img.shields.io/badge/pypi-redeploy-blue) ![Version](https://img.shields.io/badge/version-0.2.44-blue) ![Python](https://img.shields.io/badge/python-3.10+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
17
17
 
18
18
  Infrastructure migration and device deploy toolkit — VPS, Raspberry Pi kiosk, Podman Quadlet, k3s.
19
19
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "redeploy"
7
- version = "0.2.43"
7
+ version = "0.2.44"
8
8
  description = "Infrastructure migration toolkit: detect → plan → apply"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -32,6 +32,7 @@ dev = ["pytest>=8.0", "ruff>=0.4",
32
32
  "costs>=0.1.20",
33
33
  "pfix>=0.1.60",
34
34
  ]
35
+ op3 = ["op3>=0.1.4"]
35
36
 
36
37
  [tool.ruff]
37
38
  line-length = 100
@@ -7,7 +7,7 @@ Public API (stable from 0.2.0, semver guaranteed)::
7
7
 
8
8
  Everything not listed in ``__all__`` is internal and may change without notice.
9
9
  """
10
- __version__ = "0.2.43"
10
+ __version__ = "0.2.44"
11
11
 
12
12
  # ── Core models ───────────────────────────────────────────────────────────────
13
13
  from .models import ( # noqa: F401
@@ -50,10 +50,16 @@ from rich.table import Table
50
50
  @click.option("--apply-config", "apply_config", default=None,
51
51
  type=click.Path(exists=True, dir_okay=False),
52
52
  help="Apply hardware/infra settings from YAML config file to the remote host")
53
+ @click.option(
54
+ "--query", "query_expr",
55
+ default=None,
56
+ metavar="EXPR",
57
+ help="Extract specific values using JMESPath query (e.g. 'hardware.drm_outputs[0].transform', 'host')",
58
+ )
53
59
  @click.option("--ssh-key", default=None, type=click.Path(), help="SSH private key path")
54
60
  def device_map_cmd(
55
61
  host, name, tags, save, out_path, output_fmt,
56
- no_infra, list_saved, show_file, diff_files, ssh_key, apply_config,
62
+ no_infra, list_saved, show_file, diff_files, ssh_key, apply_config, query_expr,
57
63
  ):
58
64
  """Generate a full standardized device snapshot (hardware + infra + diagnostics).
59
65
 
@@ -105,6 +111,11 @@ def device_map_cmd(
105
111
  console.print("[red]✗ HOST required (or use --list / --show / --diff)[/red]")
106
112
  sys.exit(1)
107
113
 
114
+ # ── --apply-config ─────────────────────────────────────────────────────────
115
+ if apply_config:
116
+ _apply_config_from_file(console, apply_config, ssh_key)
117
+ return
118
+
108
119
  # ── probe ─────────────────────────────────────────────────────────────────
109
120
  from ...detect.hardware import probe_hardware
110
121
  from ...detect.remote import RemoteProbe
@@ -195,7 +206,7 @@ def _apply_config_from_file(console, config_path, ssh_key):
195
206
  import yaml
196
207
  import json as _json
197
208
 
198
- from ...remote import Remote
209
+ from ...detect.remote import RemoteProbe
199
210
 
200
211
  with open(config_path) as f:
201
212
  raw = f.read()
@@ -214,7 +225,7 @@ def _apply_config_from_file(console, config_path, ssh_key):
214
225
  console.print(f"[cyan]→ Applying config from {config_path} to {host}[/cyan]")
215
226
 
216
227
  # Connect to remote
217
- p = Remote(host, ssh_key=ssh_key)
228
+ p = RemoteProbe(host, ssh_key=ssh_key)
218
229
 
219
230
  applied = 0
220
231
 
@@ -321,6 +332,30 @@ def _update_kanshi_from_cfg(console, p, dsi_outputs: list):
321
332
  p.run("pkill -SIGUSR1 kanshi 2>/dev/null || true")
322
333
 
323
334
 
335
+ def _execute_query_device_map(console, dm, query_expr, output_fmt):
336
+ """Execute JMESPath query on DeviceMap model and output result."""
337
+ import jmespath
338
+ import json as _json
339
+
340
+ data = dm.model_dump(mode="json")
341
+
342
+ try:
343
+ result = jmespath.search(query_expr, data)
344
+ except jmespath.exceptions.JMESPathError as e:
345
+ console.print(f"[red]✗ JMESPath error:[/red] {e}")
346
+ sys.exit(1)
347
+
348
+ if result is None:
349
+ console.print("[dim]No match found for query[/dim]")
350
+ return
351
+
352
+ if output_fmt == "json":
353
+ click.echo(_json.dumps(result, indent=2, default=str))
354
+ else:
355
+ import yaml
356
+ click.echo(yaml.safe_dump(result, sort_keys=False, default_flow_style=False))
357
+
358
+
324
359
  # ── rendering helpers ─────────────────────────────────────────────────────────
325
360
 
326
361
 
@@ -0,0 +1 @@
1
+ """Redeploy integrations."""
@@ -0,0 +1,74 @@
1
+ """Bridge between redeploy and op3.
2
+
3
+ All adapters go through here. This module isolates op3 usage so that redeploy
4
+ remains runnable when op3 is not installed.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import os
9
+ from typing import TYPE_CHECKING
10
+
11
+ if TYPE_CHECKING:
12
+ from opstree.probes.context import SSHContext
13
+ from opstree.snapshot.model import Snapshot
14
+ from redeploy.models import InfraState, HardwareInfo
15
+
16
+ OP3_ENABLED_ENV = "REDEPLOY_USE_OP3"
17
+
18
+
19
+ def op3_enabled() -> bool:
20
+ """Check whether the user wants to use op3."""
21
+ return os.environ.get(OP3_ENABLED_ENV, "0").lower() in ("1", "true", "yes")
22
+
23
+
24
+ def op3_available() -> bool:
25
+ """Check whether op3 is installed."""
26
+ try:
27
+ import opstree # noqa: F401
28
+ return True
29
+ except ImportError:
30
+ return False
31
+
32
+
33
+ def should_use_op3() -> bool:
34
+ """Use op3 only when both flag is on and library is available."""
35
+ return op3_enabled() and op3_available()
36
+
37
+
38
+ def make_op3_context_from_ssh_client(ssh_client) -> "SSHContext":
39
+ """Convert redeploy.SshClient -> opstree.SSHContext."""
40
+ from opstree.probes.context import SSHContext
41
+
42
+ return SSHContext(
43
+ target=ssh_client.target,
44
+ host=ssh_client.host,
45
+ user=ssh_client.user,
46
+ ssh_key=ssh_client.ssh_key,
47
+ )
48
+
49
+
50
+ def snapshot_to_infra_state(snapshot: "Snapshot") -> "InfraState":
51
+ """Convert opstree.Snapshot -> redeploy.InfraState (backward compat)."""
52
+ from redeploy.models import InfraState
53
+
54
+ runtime_data = snapshot.layer("runtime.container")
55
+ service_data = snapshot.layer("service.containers")
56
+ endpoint_data = snapshot.layer("endpoint.http")
57
+
58
+ # TODO: full mapping once layer schemas stabilise
59
+ return InfraState(
60
+ runtime=runtime_data.data if runtime_data else {},
61
+ services=service_data.data if service_data else {},
62
+ endpoints=endpoint_data.data if endpoint_data else {},
63
+ )
64
+
65
+
66
+ def snapshot_to_hardware_info(snapshot: "Snapshot") -> "HardwareInfo":
67
+ """Convert opstree.Snapshot -> redeploy.HardwareInfo."""
68
+ from redeploy.models import HardwareInfo
69
+
70
+ physical = snapshot.layer("physical.display")
71
+ # TODO: expand mapping as op3 layer schema grows
72
+ return HardwareInfo(
73
+ device_model=physical.data.get("model") if physical else None,
74
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: redeploy
3
- Version: 0.2.43
3
+ Version: 0.2.44
4
4
  Summary: Infrastructure migration toolkit: detect → plan → apply
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -22,23 +22,25 @@ Requires-Dist: ruff>=0.4; extra == "dev"
22
22
  Requires-Dist: goal>=2.1.0; extra == "dev"
23
23
  Requires-Dist: costs>=0.1.20; extra == "dev"
24
24
  Requires-Dist: pfix>=0.1.60; extra == "dev"
25
+ Provides-Extra: op3
26
+ Requires-Dist: op3>=0.1.4; extra == "op3"
25
27
 
26
28
  # redeploy
27
29
 
28
30
 
29
31
  ## AI Cost Tracking
30
32
 
31
- ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.2.43-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
32
- ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-21.0h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
33
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.2.44-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
34
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-21.4h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
33
35
 
34
- - 🤖 **LLM usage:** $7.5000 (64 commits)
35
- - 👤 **Human dev:** ~$2099 (21.0h @ $100/h, 30min dedup)
36
+ - 🤖 **LLM usage:** $7.5000 (65 commits)
37
+ - 👤 **Human dev:** ~$2136 (21.4h @ $100/h, 30min dedup)
36
38
 
37
39
  Generated on 2026-04-21 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
38
40
 
39
41
  ---
40
42
 
41
- ![PyPI](https://img.shields.io/badge/pypi-redeploy-blue) ![Version](https://img.shields.io/badge/version-0.2.43-blue) ![Python](https://img.shields.io/badge/python-3.10+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
43
+ ![PyPI](https://img.shields.io/badge/pypi-redeploy-blue) ![Version](https://img.shields.io/badge/version-0.2.44-blue) ![Python](https://img.shields.io/badge/python-3.10+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
42
44
 
43
45
  Infrastructure migration and device deploy toolkit — VPS, Raspberry Pi kiosk, Podman Quadlet, k3s.
44
46
 
@@ -107,6 +107,8 @@ redeploy/iac/docker_compose.py
107
107
  redeploy/iac/registry.py
108
108
  redeploy/iac/parsers/__init__.py
109
109
  redeploy/iac/parsers/compose.py
110
+ redeploy/integrations/__init__.py
111
+ redeploy/integrations/op3_bridge.py
110
112
  redeploy/markpact/__init__.py
111
113
  redeploy/markpact/compiler.py
112
114
  redeploy/markpact/models.py
@@ -17,3 +17,6 @@ ruff>=0.4
17
17
  goal>=2.1.0
18
18
  costs>=0.1.20
19
19
  pfix>=0.1.60
20
+
21
+ [op3]
22
+ op3>=0.1.4
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