同步执行命令,支持超时 — 源码 bash.rs:102-165 超时控制的关键: - Rust 用 tokio::time::timeout 包装 command.output() - Python 用 subprocess.run(timeout=...) - 超时后返回 interrupted=True + 特定错误消息 - 超时不会 kill 进程!只是放弃等待。 (Rust 的 tokio 版本在 drop future 时会清理子进程)
(
inp: BashCommandInput,
sandbox_status: SandboxStatus,
cwd: Path,
)
| 502 | |
| 503 | |
| 504 | def _execute_bash_sync( |
| 505 | inp: BashCommandInput, |
| 506 | sandbox_status: SandboxStatus, |
| 507 | cwd: Path, |
| 508 | ) -> BashCommandOutput: |
| 509 | """同步执行命令,支持超时 — 源码 bash.rs:102-165 |
| 510 | |
| 511 | 超时控制的关键: |
| 512 | - Rust 用 tokio::time::timeout 包装 command.output() |
| 513 | - Python 用 subprocess.run(timeout=...) |
| 514 | - 超时后返回 interrupted=True + 特定错误消息 |
| 515 | - 超时不会 kill 进程!只是放弃等待。 |
| 516 | (Rust 的 tokio 版本在 drop future 时会清理子进程) |
| 517 | """ |
| 518 | cmd_args, env = prepare_command(inp.command, cwd, sandbox_status) |
| 519 | |
| 520 | timeout_seconds = inp.timeout / 1000.0 if inp.timeout else None |
| 521 | |
| 522 | try: |
| 523 | result = subprocess.run( |
| 524 | cmd_args, |
| 525 | capture_output=True, |
| 526 | cwd=str(cwd), |
| 527 | env=env, |
| 528 | timeout=timeout_seconds, |
| 529 | ) |
| 530 | stdout = result.stdout.decode("utf-8", errors="replace") |
| 531 | stderr = result.stderr.decode("utf-8", errors="replace") |
| 532 | |
| 533 | # 解释返回码 — 源码 bash.rs:140-146 |
| 534 | return_code_interpretation = None |
| 535 | if result.returncode != 0: |
| 536 | return_code_interpretation = f"exit_code:{result.returncode}" |
| 537 | |
| 538 | return BashCommandOutput( |
| 539 | stdout=stdout, |
| 540 | stderr=stderr, |
| 541 | interrupted=False, |
| 542 | sandbox_status=sandbox_status, |
| 543 | return_code_interpretation=return_code_interpretation, |
| 544 | no_output_expected=(not stdout.strip() and not stderr.strip()), |
| 545 | ) |
| 546 | |
| 547 | except subprocess.TimeoutExpired: |
| 548 | # 超时处理 — 源码 bash.rs:112-130 |
| 549 | # 注意: 返回的消息格式是固定的,模型会解析这个消息 |
| 550 | return BashCommandOutput( |
| 551 | stderr=f"Command exceeded timeout of {inp.timeout} ms", |
| 552 | interrupted=True, |
| 553 | sandbox_status=sandbox_status, |
| 554 | return_code_interpretation="timeout", |
| 555 | no_output_expected=True, |
| 556 | ) |
| 557 | |
| 558 | |
| 559 | # ============================================================ |
no test coverage detected