running-process 4.0.1__tar.gz → 4.0.3__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 (178) hide show
  1. {running_process-4.0.1 → running_process-4.0.3}/Cargo.lock +2 -2
  2. {running_process-4.0.1 → running_process-4.0.3}/Cargo.toml +1 -1
  3. {running_process-4.0.1 → running_process-4.0.3}/PKG-INFO +44 -7
  4. {running_process-4.0.1 → running_process-4.0.3}/README.md +43 -6
  5. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/Cargo.toml +4 -2
  6. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/proto/daemon.proto +124 -0
  7. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/client/mod.rs +6 -0
  8. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/client/pty_session.rs +58 -24
  9. running_process-4.0.3/crates/running-process/src/client/telemetry.rs +264 -0
  10. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/containment.rs +2 -0
  11. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/attach_stream.rs +75 -6
  12. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/handlers/mod.rs +4 -0
  13. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/handlers/pty_sessions_handlers.rs +21 -9
  14. running_process-4.0.3/crates/running-process/src/daemon/handlers/telemetry.rs +403 -0
  15. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/handlers_tests.rs +193 -2
  16. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/mod.rs +1 -0
  17. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/pipe_attach_stream.rs +67 -0
  18. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/pipe_sessions.rs +222 -0
  19. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/pty_sessions.rs +184 -2
  20. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/runtime_gc.rs +97 -0
  21. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/server.rs +12 -0
  22. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/shadow.rs +73 -0
  23. running_process-4.0.3/crates/running-process/src/daemon/telemetry.rs +937 -0
  24. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/lib.rs +86 -8
  25. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/pty/backend.rs +1 -0
  26. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/pty/conpty_passthrough/mod.rs +3 -3
  27. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/pty/mod.rs +1 -1
  28. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/pty/native_pty_process.rs +3 -1
  29. running_process-4.0.3/crates/running-process/src/terminal_graphics.rs +725 -0
  30. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/types.rs +10 -0
  31. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_non_tty_attach_test.rs +38 -2
  32. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_pipe_session_attach_test.rs +75 -0
  33. running_process-4.0.3/crates/running-process/tests/daemon_tee_ring_test.rs +337 -0
  34. running_process-4.0.3/crates/running-process/tests/interactive_pty_session_test.rs +171 -0
  35. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/originator_test.rs +9 -7
  36. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/process_core_test.rs +79 -2
  37. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/pty_master_public_api_test.rs +1 -1
  38. running_process-4.0.3/crates/running-process/tests/terminal_graphics_capabilities_test.rs +218 -0
  39. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/Cargo.toml +1 -1
  40. {running_process-4.0.1 → running_process-4.0.3}/pyproject.toml +1 -1
  41. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/__init__.py +1 -1
  42. {running_process-4.0.1 → running_process-4.0.3}/LICENSE +0 -0
  43. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/build.rs +0 -0
  44. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/bin/daemon.rs +0 -0
  45. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/bin/runpm.rs +0 -0
  46. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/bin/trampoline.rs +0 -0
  47. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/client/client.rs +0 -0
  48. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/client/paths.rs +0 -0
  49. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/client/pipe_session.rs +0 -0
  50. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/console_detect.rs +0 -0
  51. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/config.rs +0 -0
  52. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/handlers/core.rs +0 -0
  53. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/handlers/kill.rs +0 -0
  54. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/handlers/maintenance.rs +0 -0
  55. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/handlers/pipe_sessions_handlers.rs +0 -0
  56. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/handlers/process_tree.rs +0 -0
  57. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/handlers/registry_handlers.rs +0 -0
  58. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/handlers/services.rs +0 -0
  59. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/handlers/spawn.rs +0 -0
  60. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/handlers/util.rs +0 -0
  61. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/idle.rs +0 -0
  62. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/platform/mod.rs +0 -0
  63. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/platform/unix.rs +0 -0
  64. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/platform/windows.rs +0 -0
  65. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/reaper.rs +0 -0
  66. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/daemon/registry.rs +0 -0
  67. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/helpers.rs +0 -0
  68. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/originator.rs +0 -0
  69. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/pty/conpty_passthrough/child.rs +0 -0
  70. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/pty/conpty_passthrough/pipes.rs +0 -0
  71. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/pty/conpty_passthrough/proc_thread_attr.rs +0 -0
  72. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/pty/conpty_passthrough/pseudoconsole.rs +0 -0
  73. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/pty/pty_posix.rs +0 -0
  74. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/pty/pty_windows.rs +0 -0
  75. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/pty/terminal_input.rs +0 -0
  76. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/public_symbols.rs +0 -0
  77. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/rust_debug.rs +0 -0
  78. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/spawn.rs +0 -0
  79. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/spawn_imp_unix.rs +0 -0
  80. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/spawn_imp_windows.rs +0 -0
  81. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/tests.rs +0 -0
  82. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/unix.rs +0 -0
  83. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/src/windows.rs +0 -0
  84. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/containment_test.rs +0 -0
  85. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_autostart_test.rs +0 -0
  86. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_backlog_accumulation_test.rs +0 -0
  87. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_cross_process_pty_attach_test.rs +0 -0
  88. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_fast_ctrl_c_handoff_test.rs +0 -0
  89. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_integration/compiler_wrap_seam_test.rs +0 -0
  90. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_integration/env_replace_test.rs +0 -0
  91. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_integration/main.rs +0 -0
  92. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_integration/more_tests.rs +0 -0
  93. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_integration/stdout_seam_test.rs +0 -0
  94. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_pty_session_attach_test.rs +0 -0
  95. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_resize_rpc_test.rs +0 -0
  96. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_runpm_service_stubs.rs +0 -0
  97. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_sessions_bulk_ops_test.rs +0 -0
  98. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_sessions_log_test.rs +0 -0
  99. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_termination_outcome_test.rs +0 -0
  100. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_tree_kill_test.rs +0 -0
  101. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/daemon_tui_repaint_test.rs +0 -0
  102. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/fs_adversarial_test.rs +0 -0
  103. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/pty_conhost_job_test.rs +0 -0
  104. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process/tests/spawn_test.rs +0 -0
  105. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/containment.rs +0 -0
  106. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/daemon_client.rs +0 -0
  107. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/debug_traces.rs +0 -0
  108. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/helpers.rs +0 -0
  109. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/idle_detector.rs +0 -0
  110. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/lib.rs +0 -0
  111. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/metrics.rs +0 -0
  112. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/originator.rs +0 -0
  113. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/pid_tracking.rs +0 -0
  114. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/priority.rs +0 -0
  115. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/process.rs +0 -0
  116. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/process_tree.rs +0 -0
  117. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/pty_buffer.rs +0 -0
  118. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/pty_process.rs +0 -0
  119. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/public_symbols.rs +0 -0
  120. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/py_native_process.rs +0 -0
  121. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/registry.rs +0 -0
  122. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/signal_bool.rs +0 -0
  123. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/terminal_input.rs +0 -0
  124. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/tests/control_churn.rs +0 -0
  125. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/tests/expect_match.rs +0 -0
  126. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/tests/idle_detector.rs +0 -0
  127. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/tests/mod.rs +0 -0
  128. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/tests/parse_command.rs +0 -0
  129. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/tests/process_tree.rs +0 -0
  130. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/tests/pty_buffer.rs +0 -0
  131. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/tests/pty_process.rs +0 -0
  132. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/tests/registry.rs +0 -0
  133. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/tests/signal_bool.rs +0 -0
  134. {running_process-4.0.1 → running_process-4.0.3}/crates/running-process-py/src/tests/terminal_input.rs +0 -0
  135. {running_process-4.0.1 → running_process-4.0.3}/crates/test-watchdog/Cargo.toml +0 -0
  136. {running_process-4.0.1 → running_process-4.0.3}/crates/test-watchdog/src/lib.rs +0 -0
  137. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/assets/example.txt +0 -0
  138. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/cli.py +0 -0
  139. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/command_render.py +0 -0
  140. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/compat.py +0 -0
  141. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/console_encoding.py +0 -0
  142. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/daemon.py +0 -0
  143. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/dashboard.py +0 -0
  144. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/exit_status.py +0 -0
  145. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/expect.py +0 -0
  146. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/interrupt_handler.py +0 -0
  147. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/launch.py +0 -0
  148. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/line_iterator.py +0 -0
  149. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/output_formatter.py +0 -0
  150. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/priority.py +0 -0
  151. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/process_utils.py +0 -0
  152. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/processor_cli.py +0 -0
  153. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/__init__.py +0 -0
  154. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/_command.py +0 -0
  155. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/_console_io.py +0 -0
  156. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/_errors.py +0 -0
  157. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/_idle_helpers.py +0 -0
  158. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/_idle_state.py +0 -0
  159. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/_interactive.py +0 -0
  160. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/_process_helpers.py +0 -0
  161. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/_pseudo_terminal.py +0 -0
  162. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/_pty_expect.py +0 -0
  163. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/_pty_idle_waiter.py +0 -0
  164. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/_pty_input_relay.py +0 -0
  165. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/_pty_reader.py +0 -0
  166. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/_pty_wait_for.py +0 -0
  167. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/_terminal_strip.py +0 -0
  168. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/_types.py +0 -0
  169. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/pty/_wait_input.py +0 -0
  170. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/running_process/__init__.py +0 -0
  171. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/running_process/_classmethod_api.py +0 -0
  172. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/running_process/_core.py +0 -0
  173. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/running_process/_helpers.py +0 -0
  174. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/running_process/_iter.py +0 -0
  175. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/running_process/_subprocess.py +0 -0
  176. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/running_process/_types.py +0 -0
  177. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/running_process/_wait_methods.py +0 -0
  178. {running_process-4.0.1 → running_process-4.0.3}/src/running_process/running_process_manager.py +0 -0
@@ -1026,7 +1026,7 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
1026
1026
 
1027
1027
  [[package]]
1028
1028
  name = "running-process"
1029
- version = "4.0.1"
1029
+ version = "4.0.3"
1030
1030
  dependencies = [
1031
1031
  "anyhow",
1032
1032
  "bytes",
@@ -1058,7 +1058,7 @@ dependencies = [
1058
1058
 
1059
1059
  [[package]]
1060
1060
  name = "running-process-py"
1061
- version = "4.0.1"
1061
+ version = "4.0.3"
1062
1062
  dependencies = [
1063
1063
  "interprocess",
1064
1064
  "libc",
@@ -3,7 +3,7 @@ resolver = "2"
3
3
  members = ["crates/running-process", "crates/running-process-py", "crates/test-watchdog"]
4
4
 
5
5
  [workspace.package]
6
- version = "4.0.1"
6
+ version = "4.0.3"
7
7
  edition = "2021"
8
8
  rust-version = "1.85"
9
9
  license = "BSD-3-Clause"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: running_process
3
- Version: 4.0.1
3
+ Version: 4.0.3
4
4
  License-File: LICENSE
5
5
  Summary: A Rust-backed subprocess wrapper with split stdout/stderr streaming
6
6
  Home-Page: https://github.com/zackees/running-process
@@ -47,6 +47,22 @@ On those platforms, `RunningProcess.pseudo_terminal(...)`, `wait_for_expect(...)
47
47
 
48
48
  `Pty.is_available()` remains as a compatibility shim and only reports `False` on unsupported platforms.
49
49
 
50
+ ## Terminal Graphics Capabilities
51
+
52
+ Rust callers can inspect terminal graphics support with
53
+ `running_process::current_terminal_capabilities()` or the pure
54
+ `running_process::detect_terminal_capabilities(...)` helper. The result reports
55
+ Sixel, Kitty graphics, and iTerm2 `File=` image support as structured
56
+ capability records with `status`, `evidence`, `source`, and `risks` metadata.
57
+
58
+ The detector intentionally distinguishes terminal hosts from shells. `cmd.exe`,
59
+ PowerShell, Git Bash, bash, zsh, and fish are command interpreters; they do not
60
+ prove graphics support. The terminal host or multiplexer does: Windows
61
+ Terminal, xterm, foot, Konsole, WezTerm, Kitty, iTerm2, tmux, GNU screen, and
62
+ similar programs provide the relevant evidence. Weak aliases such as
63
+ `TERM=xterm-256color` are reported as unknown unless a live probe or stronger
64
+ host signal confirms support.
65
+
50
66
  ## CLI Helpers
51
67
 
52
68
  The package installs a `running-process` wrapper CLI for supervised command execution:
@@ -200,6 +216,11 @@ PTY behavior:
200
216
 
201
217
  There is also a compatibility alias: `RunningProcess.psuedo_terminal(...)`.
202
218
 
219
+ Rust consumers should make the same transport choice explicitly: use
220
+ `NativeProcess` for one-shot noninteractive work and
221
+ `InteractivePtySession` / `NativePtyProcess` only for real terminal sessions.
222
+ See [Rust PTY guidance](docs/RUST_PTY.md).
223
+
203
224
  You can also inspect the intended interactive launch semantics without launching a child:
204
225
 
205
226
  ```python
@@ -283,7 +304,7 @@ PTY mode is intentionally more conservative:
283
304
  ./test
284
305
  ```
285
306
 
286
- `./install` bootstraps `rustup` into the shared user locations (`~/.cargo` and `~/.rustup`, or `CARGO_HOME` / `RUSTUP_HOME` if you override them), then installs the exact toolchain pinned in `rust-toolchain.toml`. Toolchain installs are serialized with a lock so concurrent repo bootstraps do not race the same shared version.
307
+ `./install` bootstraps `rustup` into the shared user locations (`~/.cargo` and `~/.rustup`, or `CARGO_HOME` / `RUSTUP_HOME` if you override them), then installs the exact toolchain pinned in `rust-toolchain.toml`. Toolchain installs are serialized with a lock so concurrent repo bootstraps do not race the same shared version. Rust build commands run through `uvx soldr`, so there is no separate `soldr` install step to maintain.
287
308
 
288
309
  `./lint` applies `cargo fmt` and Ruff autofixes before running the remaining lint checks, so fixable issues are rewritten in place.
289
310
 
@@ -291,16 +312,32 @@ PTY mode is intentionally more conservative:
291
312
 
292
313
  On local developer machines, `./test` also runs the Linux Docker preflight so Windows and macOS development catches Linux wheel, lint, and non-live pytest regressions before push. GitHub-hosted Actions skip that Docker-only preflight and run the native platform suite directly.
293
314
 
294
- If you want to invoke pytest directly, set `RUNNING_PROCESS_LIVE_TESTS=1` and run `uv run pytest -m live`.
315
+ For a live-only test run with the timeout crash watchdog and automatic thread
316
+ dumps still enabled, use:
317
+
318
+ ```bash
319
+ uv run -m ci.test --live-only
320
+ ```
321
+
322
+ For a narrower live-only selection, pass pytest targets and selectors through
323
+ the same entrypoint:
324
+
325
+ ```bash
326
+ uv run -m ci.test --live-only tests/test_pty_support.py interrupt
327
+ ```
295
328
 
296
- For direct Rust commands, prefer the repo trampolines, which prepend the shared `rustup` proxy location:
329
+ For direct Cargo build commands, use `uvx soldr` directly:
297
330
 
298
331
  ```bash
299
- ./_cargo check --workspace
300
- ./_cargo fmt --all --check
301
- ./_cargo clippy --workspace --all-targets -- -D warnings
332
+ uvx soldr cargo check --workspace
333
+ uvx soldr cargo test --workspace
334
+ uvx soldr cargo package -p running-process --no-verify
302
335
  ```
303
336
 
337
+ Keep `maturin`, `cargo fmt`, and `cargo clippy` on their normal entrypoints.
338
+ This repo's high-level scripts already choose the compatible path for those
339
+ tools.
340
+
304
341
  On Windows, native rebuilds that compile bundled C code should run from a Visual Studio developer shell. When the environment is ambiguous, point `maturin` at the MSVC toolchain binaries directly rather than relying on the generic cargo proxy.
305
342
 
306
343
  For local extension rebuilds, prefer:
@@ -33,6 +33,22 @@ On those platforms, `RunningProcess.pseudo_terminal(...)`, `wait_for_expect(...)
33
33
 
34
34
  `Pty.is_available()` remains as a compatibility shim and only reports `False` on unsupported platforms.
35
35
 
36
+ ## Terminal Graphics Capabilities
37
+
38
+ Rust callers can inspect terminal graphics support with
39
+ `running_process::current_terminal_capabilities()` or the pure
40
+ `running_process::detect_terminal_capabilities(...)` helper. The result reports
41
+ Sixel, Kitty graphics, and iTerm2 `File=` image support as structured
42
+ capability records with `status`, `evidence`, `source`, and `risks` metadata.
43
+
44
+ The detector intentionally distinguishes terminal hosts from shells. `cmd.exe`,
45
+ PowerShell, Git Bash, bash, zsh, and fish are command interpreters; they do not
46
+ prove graphics support. The terminal host or multiplexer does: Windows
47
+ Terminal, xterm, foot, Konsole, WezTerm, Kitty, iTerm2, tmux, GNU screen, and
48
+ similar programs provide the relevant evidence. Weak aliases such as
49
+ `TERM=xterm-256color` are reported as unknown unless a live probe or stronger
50
+ host signal confirms support.
51
+
36
52
  ## CLI Helpers
37
53
 
38
54
  The package installs a `running-process` wrapper CLI for supervised command execution:
@@ -186,6 +202,11 @@ PTY behavior:
186
202
 
187
203
  There is also a compatibility alias: `RunningProcess.psuedo_terminal(...)`.
188
204
 
205
+ Rust consumers should make the same transport choice explicitly: use
206
+ `NativeProcess` for one-shot noninteractive work and
207
+ `InteractivePtySession` / `NativePtyProcess` only for real terminal sessions.
208
+ See [Rust PTY guidance](docs/RUST_PTY.md).
209
+
189
210
  You can also inspect the intended interactive launch semantics without launching a child:
190
211
 
191
212
  ```python
@@ -269,7 +290,7 @@ PTY mode is intentionally more conservative:
269
290
  ./test
270
291
  ```
271
292
 
272
- `./install` bootstraps `rustup` into the shared user locations (`~/.cargo` and `~/.rustup`, or `CARGO_HOME` / `RUSTUP_HOME` if you override them), then installs the exact toolchain pinned in `rust-toolchain.toml`. Toolchain installs are serialized with a lock so concurrent repo bootstraps do not race the same shared version.
293
+ `./install` bootstraps `rustup` into the shared user locations (`~/.cargo` and `~/.rustup`, or `CARGO_HOME` / `RUSTUP_HOME` if you override them), then installs the exact toolchain pinned in `rust-toolchain.toml`. Toolchain installs are serialized with a lock so concurrent repo bootstraps do not race the same shared version. Rust build commands run through `uvx soldr`, so there is no separate `soldr` install step to maintain.
273
294
 
274
295
  `./lint` applies `cargo fmt` and Ruff autofixes before running the remaining lint checks, so fixable issues are rewritten in place.
275
296
 
@@ -277,16 +298,32 @@ PTY mode is intentionally more conservative:
277
298
 
278
299
  On local developer machines, `./test` also runs the Linux Docker preflight so Windows and macOS development catches Linux wheel, lint, and non-live pytest regressions before push. GitHub-hosted Actions skip that Docker-only preflight and run the native platform suite directly.
279
300
 
280
- If you want to invoke pytest directly, set `RUNNING_PROCESS_LIVE_TESTS=1` and run `uv run pytest -m live`.
301
+ For a live-only test run with the timeout crash watchdog and automatic thread
302
+ dumps still enabled, use:
303
+
304
+ ```bash
305
+ uv run -m ci.test --live-only
306
+ ```
307
+
308
+ For a narrower live-only selection, pass pytest targets and selectors through
309
+ the same entrypoint:
281
310
 
282
- For direct Rust commands, prefer the repo trampolines, which prepend the shared `rustup` proxy location:
311
+ ```bash
312
+ uv run -m ci.test --live-only tests/test_pty_support.py interrupt
313
+ ```
314
+
315
+ For direct Cargo build commands, use `uvx soldr` directly:
283
316
 
284
317
  ```bash
285
- ./_cargo check --workspace
286
- ./_cargo fmt --all --check
287
- ./_cargo clippy --workspace --all-targets -- -D warnings
318
+ uvx soldr cargo check --workspace
319
+ uvx soldr cargo test --workspace
320
+ uvx soldr cargo package -p running-process --no-verify
288
321
  ```
289
322
 
323
+ Keep `maturin`, `cargo fmt`, and `cargo clippy` on their normal entrypoints.
324
+ This repo's high-level scripts already choose the compatible path for those
325
+ tools.
326
+
290
327
  On Windows, native rebuilds that compile bundled C code should run from a Visual Studio developer shell. When the environment is ambiguous, point `maturin` at the MSVC toolchain binaries directly rather than relying on the generic cargo proxy.
291
328
 
292
329
  For local extension rebuilds, prefer:
@@ -35,13 +35,15 @@ path = "src/bin/trampoline.rs"
35
35
  # Final feature scheme per #165:
36
36
  # * `core` — always-available API (spawn / pty / containment).
37
37
  # * `client` — adds proto types + IPC client (prost, interprocess, dirs).
38
- # * `daemon` — superset of client; adds the full daemon runtime
39
- # (tokio, rusqlite, tracing, etc.).
38
+ # * `telemetry` — tee sink primitives without the full daemon runtime.
39
+ # * `daemon` — superset of client; adds the full daemon runtime
40
+ # (tokio, rusqlite, tracing, etc.).
40
41
  # Default ships `client` so `cargo install running-process` installs
41
42
  # the `runpm` binary out of the box (per Q1 resolution in #165:
42
43
  # `required-features` are not auto-activated by cargo install).
43
44
  default = ["client"]
44
45
  core = []
46
+ telemetry = []
45
47
  client = ["dep:prost", "dep:prost-types", "dep:interprocess", "dep:dirs", "dep:anyhow", "dep:clap"]
46
48
  daemon = [
47
49
  "client",
@@ -63,6 +63,10 @@ enum RequestType {
63
63
  REQUEST_TYPE_BULK_TERMINATE_SESSIONS = 73;
64
64
  // Resize a PTY session without attaching (#130 M5 follow-up).
65
65
  REQUEST_TYPE_RESIZE_PTY_SESSION = 74;
66
+ // Optional daemon-owned tee telemetry (#131).
67
+ REQUEST_TYPE_REGISTER_SESSION_TEE = 75;
68
+ REQUEST_TYPE_UNREGISTER_SESSION_TEE = 76;
69
+ REQUEST_TYPE_GET_SESSION_TEE_STATUS = 77;
66
70
  }
67
71
 
68
72
  enum StatusCode {
@@ -86,6 +90,30 @@ enum ProcessState {
86
90
  PROCESS_STATE_ZOMBIE = 3;
87
91
  }
88
92
 
93
+ enum GraphicsProtocol {
94
+ GRAPHICS_PROTOCOL_UNSPECIFIED = 0;
95
+ GRAPHICS_PROTOCOL_SIXEL = 1;
96
+ GRAPHICS_PROTOCOL_KITTY = 2;
97
+ GRAPHICS_PROTOCOL_ITERM2_FILE = 3;
98
+ }
99
+
100
+ enum CapabilityStatus {
101
+ CAPABILITY_STATUS_UNSPECIFIED = 0;
102
+ CAPABILITY_STATUS_SUPPORTED = 1;
103
+ CAPABILITY_STATUS_UNSUPPORTED = 2;
104
+ CAPABILITY_STATUS_UNKNOWN = 3;
105
+ CAPABILITY_STATUS_BLOCKED = 4;
106
+ }
107
+
108
+ enum EvidenceStrength {
109
+ EVIDENCE_STRENGTH_UNSPECIFIED = 0;
110
+ EVIDENCE_STRENGTH_PROBE = 1;
111
+ EVIDENCE_STRENGTH_STRONG_HOST_SIGNAL = 2;
112
+ EVIDENCE_STRENGTH_TERMINFO = 3;
113
+ EVIDENCE_STRENGTH_WEAK_ENV = 4;
114
+ EVIDENCE_STRENGTH_USER_OVERRIDE = 5;
115
+ }
116
+
89
117
  // ---------------------------------------------------------------------------
90
118
  // Envelope messages
91
119
  // ---------------------------------------------------------------------------
@@ -133,6 +161,9 @@ message DaemonRequest {
133
161
  PurgeExitedSessionsRequest purge_exited_sessions = 72;
134
162
  BulkTerminateSessionsRequest bulk_terminate_sessions = 73;
135
163
  ResizePtySessionRequest resize_pty_session = 74;
164
+ RegisterSessionTeeRequest register_session_tee = 75;
165
+ UnregisterSessionTeeRequest unregister_session_tee = 76;
166
+ GetSessionTeeStatusRequest get_session_tee_status = 77;
136
167
  }
137
168
 
138
169
  message DaemonResponse {
@@ -177,6 +208,9 @@ message DaemonResponse {
177
208
  PurgeExitedSessionsResponse purge_exited_sessions = 72;
178
209
  BulkTerminateSessionsResponse bulk_terminate_sessions = 73;
179
210
  ResizePtySessionResponse resize_pty_session = 74;
211
+ RegisterSessionTeeResponse register_session_tee = 75;
212
+ UnregisterSessionTeeResponse unregister_session_tee = 76;
213
+ GetSessionTeeStatusResponse get_session_tee_status = 77;
180
214
  }
181
215
 
182
216
  // ---------------------------------------------------------------------------
@@ -191,6 +225,19 @@ message KeyValue {
191
225
  string value = 2;
192
226
  }
193
227
 
228
+ message TerminalGraphicsCapability {
229
+ GraphicsProtocol protocol = 1;
230
+ CapabilityStatus status = 2;
231
+ EvidenceStrength evidence = 3;
232
+ string source = 4;
233
+ repeated string risks = 5;
234
+ }
235
+
236
+ message TerminalGraphicsCapabilities {
237
+ repeated TerminalGraphicsCapability protocols = 1;
238
+ GraphicsProtocol preferred = 2;
239
+ }
240
+
194
241
  message RegisterRequest {
195
242
  uint32 pid = 1;
196
243
  double created_at = 2;
@@ -484,6 +531,7 @@ message AttachPtySessionRequest {
484
531
  // Terminal capabilities for renegotiation; informational only for now.
485
532
  string term = 5;
486
533
  bool is_tty = 6;
534
+ TerminalGraphicsCapabilities graphics_capabilities = 7;
487
535
  }
488
536
 
489
537
  message AttachPtySessionResponse {
@@ -542,6 +590,9 @@ message PtySessionInfo {
542
590
  // child's environment (you cannot change a live child's TERM).
543
591
  // Empty when no client is attached.
544
592
  string attached_term = 15;
593
+ // Graphics capability metadata supplied by the currently attached
594
+ // client. Missing metadata from older clients is treated as unknown.
595
+ TerminalGraphicsCapabilities attached_graphics_capabilities = 16;
545
596
  }
546
597
 
547
598
  message TerminatePtySessionRequest {
@@ -763,6 +814,79 @@ message ResizePtySessionRequest {
763
814
  }
764
815
  message ResizePtySessionResponse {}
765
816
 
817
+ // ---------------------------------------------------------------------------
818
+ // Optional session tee telemetry (#131).
819
+ // ---------------------------------------------------------------------------
820
+
821
+ enum TeeSessionKind {
822
+ TEE_SESSION_KIND_UNSPECIFIED = 0;
823
+ TEE_SESSION_KIND_PTY = 1;
824
+ TEE_SESSION_KIND_PIPE = 2;
825
+ }
826
+
827
+ enum TeeStreamKind {
828
+ TEE_STREAM_KIND_UNSPECIFIED = 0;
829
+ TEE_STREAM_KIND_PTY_OUTPUT = 1;
830
+ TEE_STREAM_KIND_STDOUT = 2;
831
+ TEE_STREAM_KIND_STDERR = 3;
832
+ TEE_STREAM_KIND_STDIN = 4;
833
+ }
834
+
835
+ enum TeeSinkKind {
836
+ TEE_SINK_KIND_UNSPECIFIED = 0;
837
+ // Daemon opens the path and owns the file descriptor until the tee is
838
+ // removed or the session ends. Path bytes are OS-native, not UTF-8.
839
+ TEE_SINK_KIND_FILE = 1;
840
+ }
841
+
842
+ enum TeeFileMode {
843
+ TEE_FILE_MODE_APPEND = 0;
844
+ TEE_FILE_MODE_TRUNCATE = 1;
845
+ }
846
+
847
+ enum TeeBackpressure {
848
+ TEE_BACKPRESSURE_DROP_OLDEST = 0;
849
+ TEE_BACKPRESSURE_BLOCK = 1;
850
+ }
851
+
852
+ message RegisterSessionTeeRequest {
853
+ string session_id = 1;
854
+ TeeSessionKind session_kind = 2;
855
+ TeeStreamKind stream = 3;
856
+ TeeSinkKind sink_kind = 4;
857
+ // OS-native path bytes: Unix = OsStr bytes; Windows = little-endian UTF-16.
858
+ bytes file_path = 5;
859
+ TeeFileMode file_mode = 6;
860
+ // 0 means use the daemon default.
861
+ uint32 queue_capacity = 7;
862
+ // false means write missed-byte markers, matching the Rust default.
863
+ bool suppress_missed_markers = 8;
864
+ TeeBackpressure backpressure = 9;
865
+ }
866
+
867
+ message RegisterSessionTeeResponse {
868
+ uint64 tee_handle = 1;
869
+ }
870
+
871
+ message UnregisterSessionTeeRequest {
872
+ string session_id = 1;
873
+ TeeSessionKind session_kind = 2;
874
+ uint64 tee_handle = 3;
875
+ }
876
+ message UnregisterSessionTeeResponse {}
877
+
878
+ message GetSessionTeeStatusRequest {
879
+ string session_id = 1;
880
+ TeeSessionKind session_kind = 2;
881
+ uint64 tee_handle = 3;
882
+ }
883
+
884
+ message GetSessionTeeStatusResponse {
885
+ TeeStreamKind stream = 1;
886
+ uint64 missed_bytes = 2;
887
+ bool disconnected = 3;
888
+ }
889
+
766
890
  // Daemon -> client stream frame for an attached stdout/stderr.
767
891
  message PipeStreamFrame {
768
892
  oneof frame {
@@ -5,10 +5,12 @@
5
5
  //! previously imported from `running_process_client::*` keeps working
6
6
  //! when it switches to `running_process::client::*`.
7
7
 
8
+ #[allow(clippy::module_inception)]
8
9
  pub mod client;
9
10
  pub mod paths;
10
11
  pub mod pipe_session;
11
12
  pub mod pty_session;
13
+ pub mod telemetry;
12
14
 
13
15
  pub use client::{
14
16
  connect_or_start, daemonize_command, launch_detached, ClientError, DaemonClient,
@@ -16,3 +18,7 @@ pub use client::{
16
18
  };
17
19
  pub use pipe_session::{PipeSpawnRequest, PipeStreamAttachment, SpawnedPipeSession};
18
20
  pub use pty_session::{AttachError, PtyAttachment, PtySpawnRequest, SpawnedPtySession};
21
+ pub use telemetry::{
22
+ SessionTeeBackpressure, SessionTeeFileMode, SessionTeeFileRequest, SessionTeeKind,
23
+ SessionTeeStatus, SessionTeeStream,
24
+ };
@@ -10,17 +10,21 @@
10
10
  //! send/receive helpers suitable for tests and small clients. Async
11
11
  //! clients can build on top of [`DaemonClient::attach_pty_session_raw`].
12
12
 
13
- use crate::client::{ClientError, DaemonClient};
14
13
  use crate::client::paths;
15
- use interprocess::local_socket::Stream;
16
- use interprocess::TryClone;
17
- use prost::Message;
14
+ use crate::client::{ClientError, DaemonClient};
18
15
  use crate::proto::daemon::{
19
16
  pty_input_frame::Frame as InputOneof, AttachPtySessionRequest, AttachPtySessionResponse,
20
17
  DaemonRequest, DaemonResponse, DetachPtySessionRequest, KeyValue, ListPtySessionsRequest,
21
18
  ListPtySessionsResponse, PtyInputFrame, PtyResize, PtySessionInfo, PtyStreamFrame, RequestType,
22
19
  SpawnPtySessionRequest, SpawnPtySessionResponse, StatusCode, TerminatePtySessionRequest,
23
20
  };
21
+ use crate::terminal_graphics::{
22
+ current_terminal_capabilities, terminal_graphics_capabilities_to_proto, TerminalCapabilities,
23
+ TerminalGraphicsCapabilities,
24
+ };
25
+ use interprocess::local_socket::Stream;
26
+ use interprocess::TryClone;
27
+ use prost::Message;
24
28
  use std::io::{BufReader, BufWriter, Read, Write};
25
29
  use std::path::PathBuf;
26
30
  use std::time::Duration;
@@ -76,10 +80,7 @@ impl PtySpawnRequest {
76
80
  K: Into<String>,
77
81
  V: Into<String>,
78
82
  {
79
- self.env = env
80
- .into_iter()
81
- .map(|(k, v)| (k.into(), v.into()))
82
- .collect();
83
+ self.env = env.into_iter().map(|(k, v)| (k.into(), v.into())).collect();
83
84
  self
84
85
  }
85
86
  }
@@ -131,10 +132,12 @@ impl DaemonClient {
131
132
  let response = self.send_request(daemon_request)?;
132
133
  ensure_ok(&response)?;
133
134
  let payload: SpawnPtySessionResponse =
134
- response.spawn_pty_session.ok_or_else(|| ClientError::Server {
135
- code: StatusCode::Internal,
136
- message: "spawn_pty_session response missing payload".into(),
137
- })?;
135
+ response
136
+ .spawn_pty_session
137
+ .ok_or_else(|| ClientError::Server {
138
+ code: StatusCode::Internal,
139
+ message: "spawn_pty_session response missing payload".into(),
140
+ })?;
138
141
  Ok(SpawnedPtySession {
139
142
  session_id: payload.session_id,
140
143
  pid: payload.pid,
@@ -160,12 +163,13 @@ impl DaemonClient {
160
163
  };
161
164
  let response = self.send_request(req)?;
162
165
  ensure_ok(&response)?;
163
- let payload: ListPtySessionsResponse = response
164
- .list_pty_sessions
165
- .ok_or_else(|| ClientError::Server {
166
- code: StatusCode::Internal,
167
- message: "list_pty_sessions response missing payload".into(),
168
- })?;
166
+ let payload: ListPtySessionsResponse =
167
+ response
168
+ .list_pty_sessions
169
+ .ok_or_else(|| ClientError::Server {
170
+ code: StatusCode::Internal,
171
+ message: "list_pty_sessions response missing payload".into(),
172
+ })?;
169
173
  Ok(payload.sessions)
170
174
  }
171
175
 
@@ -210,7 +214,6 @@ impl DaemonClient {
210
214
  ensure_ok(&response)?;
211
215
  Ok(())
212
216
  }
213
-
214
217
  }
215
218
 
216
219
  fn ensure_ok(response: &DaemonResponse) -> Result<(), ClientError> {
@@ -249,7 +252,10 @@ pub enum AttachError {
249
252
  Connect(std::io::Error),
250
253
  Io(std::io::Error),
251
254
  Decode(prost::DecodeError),
252
- Server { code: StatusCode, message: String },
255
+ Server {
256
+ code: StatusCode,
257
+ message: String,
258
+ },
253
259
  /// The daemon never sent an AttachPtySessionResponse payload.
254
260
  MissingPayload,
255
261
  }
@@ -290,6 +296,32 @@ impl PtyAttachment {
290
296
  rows: u16,
291
297
  cols: u16,
292
298
  steal: bool,
299
+ ) -> Result<Self, AttachError> {
300
+ let mut terminal_capabilities = current_terminal_capabilities();
301
+ if !terminal_capabilities.is_tty {
302
+ terminal_capabilities.is_tty = true;
303
+ terminal_capabilities.graphics = TerminalGraphicsCapabilities::unknown();
304
+ }
305
+ Self::attach_to_with_terminal_capabilities(
306
+ socket_path,
307
+ session_id,
308
+ rows,
309
+ cols,
310
+ steal,
311
+ terminal_capabilities,
312
+ )
313
+ }
314
+
315
+ /// Attach with explicit terminal metadata. This is useful for tests,
316
+ /// non-interactive attach clients, and callers that already performed
317
+ /// capability probing before opening the daemon socket.
318
+ pub fn attach_to_with_terminal_capabilities(
319
+ socket_path: &str,
320
+ session_id: &str,
321
+ rows: u16,
322
+ cols: u16,
323
+ steal: bool,
324
+ terminal_capabilities: TerminalCapabilities,
293
325
  ) -> Result<Self, AttachError> {
294
326
  let name = paths::make_socket_name(socket_path).map_err(AttachError::Connect)?;
295
327
  use interprocess::local_socket::traits::Stream as _;
@@ -309,8 +341,11 @@ impl PtyAttachment {
309
341
  rows: rows as u32,
310
342
  cols: cols as u32,
311
343
  steal,
312
- term: std::env::var("TERM").unwrap_or_default(),
313
- is_tty: true,
344
+ term: terminal_capabilities.term.unwrap_or_default(),
345
+ is_tty: terminal_capabilities.is_tty,
346
+ graphics_capabilities: Some(terminal_graphics_capabilities_to_proto(
347
+ &terminal_capabilities.graphics,
348
+ )),
314
349
  }),
315
350
  ..Default::default()
316
351
  };
@@ -319,8 +354,7 @@ impl PtyAttachment {
319
354
 
320
355
  // Read the initial response.
321
356
  let response_bytes = read_length_prefixed(&mut reader).map_err(AttachError::Io)?;
322
- let response =
323
- DaemonResponse::decode(&response_bytes[..]).map_err(AttachError::Decode)?;
357
+ let response = DaemonResponse::decode(&response_bytes[..]).map_err(AttachError::Decode)?;
324
358
  if response.code != StatusCode::Ok as i32 {
325
359
  let code = StatusCode::try_from(response.code).unwrap_or(StatusCode::UnknownRequest);
326
360
  return Err(AttachError::Server {