Skip to content

Commit d162136

Browse files
committed
feat(sandbox): add terminal settings support for create_session API
refs alibaba/ROcks#540
1 parent e8e04a2 commit d162136

File tree

3 files changed

+133
-0
lines changed

3 files changed

+133
-0
lines changed

rock/actions/sandbox/request.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@ class CreateBashSessionRequest(BaseModel):
2525
env: dict[str, str] | None = Field(default=None)
2626
remote_user: str | None = Field(default=None)
2727

28+
# Terminal settings
29+
term: str = Field(default="dumb")
30+
"""Terminal type (TERM environment variable)."""
31+
32+
columns: int = Field(default=80, ge=1)
33+
"""Terminal width in columns. Must be positive."""
34+
35+
lines: int = Field(default=24, ge=1)
36+
"""Terminal height in lines. Must be positive."""
37+
38+
lang: str = Field(default="en_US.UTF-8")
39+
"""Language and encoding (LANG environment variable)."""
40+
2841

2942
CreateSessionRequest = Annotated[CreateBashSessionRequest, Field(discriminator="session_type")]
3043
"""Union type for all create session requests. Do not use this directly."""

rock/rocklet/local_sandbox.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,13 @@ async def start(self) -> CreateBashSessionResponse:
177177
else:
178178
env = {}
179179
env.update({"PS1": self._ps1, "PS2": "", "PS0": ""})
180+
181+
# Set terminal environment variables
182+
env["TERM"] = self.request.term
183+
env["COLUMNS"] = str(self.request.columns)
184+
env["LINES"] = str(self.request.lines)
185+
env["LANG"] = self.request.lang
186+
180187
if self.request.env is not None:
181188
env.update(self.request.env)
182189
logger.info(f"env:{env}")
@@ -190,6 +197,7 @@ async def start(self) -> CreateBashSessionResponse:
190197
echo=False,
191198
env=env, # type: ignore
192199
maxread=self.request.max_read_size,
200+
dimensions=(self.request.lines, self.request.columns),
193201
)
194202
time.sleep(0.3)
195203
cmds = []

tests/unit/rocklet/test_local_sandbox_runtime.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,115 @@ async def test_prompt_command(local_runtime: LocalSandboxRuntime):
7979
with_prompt_command = await local_runtime.run_in_session(BashAction(command="echo hello", action_type="bash"))
8080
assert with_prompt_command.output.__contains__("ROCK")
8181
await local_runtime.close_session(CloseBashSessionRequest(session_type="bash"))
82+
83+
84+
# ========== Terminal Settings Tests ==========
85+
86+
87+
@pytest.mark.asyncio
88+
async def test_default_terminal_settings(local_runtime: LocalSandboxRuntime):
89+
"""Test that default terminal settings are applied correctly."""
90+
import uuid
91+
session_name = f"term_default_{uuid.uuid4().hex[:8]}"
92+
await local_runtime.create_session(
93+
CreateBashSessionRequest(session_type="bash", session=session_name, startup_timeout=5.0)
94+
)
95+
96+
# Check TERM (default is dumb)
97+
obs = await local_runtime.run_in_session(
98+
BashAction(command="echo $TERM", action_type="bash", session=session_name, timeout=10)
99+
)
100+
assert "dumb" in obs.output
101+
102+
# Check LANG
103+
obs = await local_runtime.run_in_session(
104+
BashAction(command="echo $LANG", action_type="bash", session=session_name, timeout=10)
105+
)
106+
assert "en_US.UTF-8" in obs.output
107+
108+
await local_runtime.close_session(CloseBashSessionRequest(session_type="bash", session=session_name))
109+
110+
111+
@pytest.mark.asyncio
112+
async def test_custom_terminal_settings(local_runtime: LocalSandboxRuntime):
113+
"""Test that custom terminal settings are applied correctly."""
114+
import uuid
115+
session_name = f"term_custom_{uuid.uuid4().hex[:8]}"
116+
await local_runtime.create_session(
117+
CreateBashSessionRequest(
118+
session_type="bash",
119+
session=session_name,
120+
startup_timeout=5.0,
121+
term="screen",
122+
columns=120,
123+
lines=40,
124+
lang="zh_CN.UTF-8",
125+
)
126+
)
127+
128+
# Check TERM
129+
obs = await local_runtime.run_in_session(
130+
BashAction(command="echo $TERM", action_type="bash", session=session_name, timeout=10)
131+
)
132+
assert "screen" in obs.output
133+
134+
# Check LANG
135+
obs = await local_runtime.run_in_session(
136+
BashAction(command="echo $LANG", action_type="bash", session=session_name, timeout=10)
137+
)
138+
assert "zh_CN.UTF-8" in obs.output
139+
140+
await local_runtime.close_session(CloseBashSessionRequest(session_type="bash", session=session_name))
141+
142+
143+
@pytest.mark.asyncio
144+
async def test_terminal_size_stty(local_runtime: LocalSandboxRuntime):
145+
"""Test that terminal size is correctly set via stty size."""
146+
import uuid
147+
session_name = f"term_stty_{uuid.uuid4().hex[:8]}"
148+
await local_runtime.create_session(
149+
CreateBashSessionRequest(
150+
session_type="bash",
151+
session=session_name,
152+
startup_timeout=5.0,
153+
columns=100,
154+
lines=30,
155+
)
156+
)
157+
158+
# stty size outputs "lines columns"
159+
obs = await local_runtime.run_in_session(
160+
BashAction(command="stty size", action_type="bash", session=session_name, timeout=10)
161+
)
162+
assert "30 100" in obs.output
163+
164+
await local_runtime.close_session(CloseBashSessionRequest(session_type="bash", session=session_name))
165+
166+
167+
@pytest.mark.asyncio
168+
async def test_env_overrides_terminal_params(local_runtime: LocalSandboxRuntime):
169+
"""Test that env parameter takes priority over terminal params."""
170+
import uuid
171+
session_name = f"term_override_{uuid.uuid4().hex[:8]}"
172+
await local_runtime.create_session(
173+
CreateBashSessionRequest(
174+
session_type="bash",
175+
session=session_name,
176+
startup_timeout=5.0,
177+
term="xterm",
178+
env={"TERM": "vt100", "LANG": "C"},
179+
)
180+
)
181+
182+
# env should override term param
183+
obs = await local_runtime.run_in_session(
184+
BashAction(command="echo $TERM", action_type="bash", session=session_name, timeout=10)
185+
)
186+
assert "vt100" in obs.output
187+
188+
obs = await local_runtime.run_in_session(
189+
BashAction(command="echo $LANG", action_type="bash", session=session_name, timeout=10)
190+
)
191+
assert "C" in obs.output
192+
193+
await local_runtime.close_session(CloseBashSessionRequest(session_type="bash", session=session_name))

0 commit comments

Comments
 (0)