mirror of
https://github.com/usestrix/strix.git
synced 2026-08-28 05:25:00 +00:00
docs(shell): note the PTY layer's 30s yield ceiling
The SDK clamps every PTY yield to 30s and floors an empty poll at 5s. Record that where the defaults are set, and tell the agent a slower command still backgrounds so it harvests it with one poll per 30s instead of asking for an unreachable yield.
This commit is contained in:
parent
3fea23de7e
commit
7ef555ad19
3 changed files with 19 additions and 8 deletions
|
|
@ -188,9 +188,11 @@ EFFICIENCY TACTICS:
|
|||
the instant there is new output or the process exits, or give the original
|
||||
`exec_command` a bigger `yield_time_ms` up front so it doesn't background.
|
||||
- When you expect a command to take a while (a scan like `nmap`/`nuclei`/`ffuf`,
|
||||
a build, a long crawl), estimate its runtime and pass that as
|
||||
`yield_time_ms` on the first `exec_command` — one call that waits beats a
|
||||
backgrounded process you then poll for many turns. Default is 30s.
|
||||
a build, a long crawl), pass the time you expect to need as `yield_time_ms`
|
||||
on the first `exec_command` — one call that waits beats a backgrounded
|
||||
process you then poll for many turns. The shell yields at most 30s per call
|
||||
(the default), so anything slower than that still backgrounds: harvest it
|
||||
with one `write_stdin(chars="")` poll per 30s rather than many short ones.
|
||||
- Before importing a third-party Python library, make sure it is installed. The
|
||||
sandbox's `python3` runs inside a preconfigured virtualenv that ships
|
||||
`requests`, `httpx`, `beautifulsoup4` (bs4), `lxml`, `pyjwt`, and
|
||||
|
|
|
|||
|
|
@ -109,13 +109,18 @@ class ShellSettings(BaseSettings):
|
|||
after only 250ms on a ``write_stdin`` poll and 10s on ``exec_command``.
|
||||
Raising these defaults lets one call return a meaningful result instead of a
|
||||
no-op round-trip. An explicit ``yield_time_ms`` from the model always wins.
|
||||
|
||||
The SDK's PTY layer clamps every yield to 30s, so a larger value here would
|
||||
be silently ineffective; keep both yields at or below that ceiling.
|
||||
"""
|
||||
|
||||
model_config = _BASE_CONFIG
|
||||
|
||||
# Default yield for exec_command when the model omits yield_time_ms.
|
||||
# Default yield for exec_command when the model omits yield_time_ms. 30s is
|
||||
# the most the PTY layer honours, so this sits right at that ceiling.
|
||||
exec_yield_ms: int = Field(default=30_000, gt=0, alias="STRIX_SHELL_EXEC_YIELD_MS")
|
||||
# Default yield for an empty (polling) write_stdin call.
|
||||
# Default yield for an empty (polling) write_stdin call. The SDK already
|
||||
# floors an empty poll at 5s; this trades a little latency for far fewer turns.
|
||||
write_stdin_poll_yield_ms: int = Field(
|
||||
default=20_000, gt=0, alias="STRIX_SHELL_WRITE_STDIN_POLL_YIELD_MS"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -164,16 +164,20 @@ async def test_wrap_exec_command_default_does_not_depend_on_the_binary(cmd: str)
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_wrap_exec_command_preserves_long_explicit_yield() -> None:
|
||||
async def test_wrap_exec_command_preserves_longer_explicit_yield() -> None:
|
||||
"""A slow command gets the yield the agent asked for, not a guessed one.
|
||||
|
||||
The SDK's PTY layer clamps anything above 30s, so a longer wait than that
|
||||
cannot be bought with a bigger argument."""
|
||||
captured: dict[str, str] = {}
|
||||
wrapped = factory._wrap_exec_command(_capturing_exec_tool(captured))
|
||||
|
||||
await wrapped.on_invoke_tool(
|
||||
cast("Any", None),
|
||||
json.dumps({"cmd": "nmap -p- example.com", "yield_time_ms": 300_000}),
|
||||
json.dumps({"cmd": "nmap -p- example.com", "yield_time_ms": 25_000}),
|
||||
)
|
||||
|
||||
assert json.loads(captured["raw_input"])["yield_time_ms"] == 300_000
|
||||
assert json.loads(captured["raw_input"])["yield_time_ms"] == 25_000
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue