feat: forward agent style via native CLI config and terminal title
Replace prompt-injection for display identity with native UI wiring: - Claude: writes a statusline shell script + custom theme JSON, wired up via settings.json so label/color show in the status bar and theme - Codex: writes [tui] block into codex-config.toml (status_line, terminal_title, dark-ansi theme) - Both backends set the terminal title via ANSI OSC 0 escape before exec-ing the agent when a label is present Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -62,7 +62,7 @@ class TestAgentProviderRuntime(unittest.TestCase):
|
||||
config = Path(tmp, "codex-config.toml").read_text()
|
||||
self.assertIn('[projects."/home/node/workspace"]', config)
|
||||
|
||||
def test_codex_injects_name_and_color_into_prompt(self):
|
||||
def test_codex_writes_tui_settings_without_mutating_prompt(self):
|
||||
with tempfile.TemporaryDirectory(prefix="bb-provider.") as tmp:
|
||||
prompt_file = Path(tmp) / "prompt.txt"
|
||||
prompt_file.write_text("Existing instructions.\n")
|
||||
@@ -76,11 +76,12 @@ class TestAgentProviderRuntime(unittest.TestCase):
|
||||
color="bright-cyan",
|
||||
)
|
||||
prompt = prompt_file.read_text()
|
||||
config = Path(tmp, "codex-config.toml").read_text()
|
||||
self.assertTrue(plan.has_prompt)
|
||||
self.assertIn("Bot-bottle agent display identity:", prompt)
|
||||
self.assertIn("Name: review-api", prompt)
|
||||
self.assertIn("Color: bright-cyan", prompt)
|
||||
self.assertTrue(prompt.endswith("Existing instructions.\n"))
|
||||
self.assertEqual("Existing instructions.\n", prompt)
|
||||
self.assertIn("[tui]", config)
|
||||
self.assertIn('status_line = ["model", "cwd"]', config)
|
||||
self.assertIn('terminal_title = ["spinner", "project"]', config)
|
||||
|
||||
def test_codex_forward_host_credentials_adds_auth_and_verify(self):
|
||||
with tempfile.TemporaryDirectory(prefix="bb-provider.") as tmp:
|
||||
@@ -146,7 +147,7 @@ class TestAgentProviderRuntime(unittest.TestCase):
|
||||
self.assertIn("/home/node", config["projects"])
|
||||
self.assertIn("/home/node/workspace", config["projects"])
|
||||
|
||||
def test_claude_injects_name_and_color_into_prompt(self):
|
||||
def test_claude_writes_statusline_and_theme_without_mutating_prompt(self):
|
||||
with tempfile.TemporaryDirectory(prefix="bb-provider.") as tmp:
|
||||
prompt_file = Path(tmp) / "prompt.txt"
|
||||
prompt_file.write_text("Existing instructions.\n")
|
||||
@@ -160,11 +161,11 @@ class TestAgentProviderRuntime(unittest.TestCase):
|
||||
color="green",
|
||||
)
|
||||
prompt = prompt_file.read_text()
|
||||
settings = json.loads(Path(tmp, "claude-settings.json").read_text())
|
||||
self.assertTrue(plan.has_prompt)
|
||||
self.assertIn("Bot-bottle agent display identity:", prompt)
|
||||
self.assertIn("Name: research-ui", prompt)
|
||||
self.assertIn("Color: green", prompt)
|
||||
self.assertTrue(prompt.endswith("Existing instructions.\n"))
|
||||
self.assertEqual("Existing instructions.\n", prompt)
|
||||
self.assertEqual("~/.claude/statusline.sh", settings["statusLine"]["command"])
|
||||
self.assertEqual("custom:bot-bottle-research-ui", settings["theme"])
|
||||
|
||||
def test_codex_forward_host_credentials_populates_egress_routes(self):
|
||||
with tempfile.TemporaryDirectory(prefix="bb-provider.") as tmp:
|
||||
|
||||
@@ -8,6 +8,8 @@ either side are expected to diverge the implementations."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock, patch
|
||||
@@ -127,7 +129,7 @@ class TestClaudeProvisionPrompt(unittest.TestCase):
|
||||
self.assertIsNone(r)
|
||||
bottle.cp_in.assert_called_once()
|
||||
|
||||
def test_returns_path_when_provider_prompt_has_identity(self):
|
||||
def test_returns_path_when_provider_prompt_exists(self):
|
||||
bottle = _make_bottle()
|
||||
provision = AgentProvisionPlan(
|
||||
template="claude", command="claude", prompt_mode="append_file",
|
||||
@@ -261,6 +263,35 @@ class TestClaudeProvision(unittest.TestCase):
|
||||
_plan(agent_provision=provision), bottle,
|
||||
)
|
||||
|
||||
|
||||
class TestClaudeUiProvision(unittest.TestCase):
|
||||
def test_writes_statusline_and_custom_theme_files(self):
|
||||
with tempfile.TemporaryDirectory(prefix="bb-claude-ui.") as tmp:
|
||||
state_dir = Path(tmp)
|
||||
prompt_file = state_dir / "prompt.txt"
|
||||
prompt_file.write_text("Existing instructions.\n")
|
||||
plan = ClaudeAgentProvider().provision_plan(
|
||||
dockerfile="",
|
||||
state_dir=state_dir,
|
||||
instance_name="bot-bottle-demo-abc12",
|
||||
prompt_file=prompt_file,
|
||||
label="research-ui",
|
||||
color="bright-cyan",
|
||||
)
|
||||
settings = json.loads((state_dir / "claude-settings.json").read_text())
|
||||
statusline = (state_dir / "claude-statusline.sh").read_text()
|
||||
theme = json.loads((state_dir / "bot-bottle-research-ui.json").read_text())
|
||||
prompt_text = prompt_file.read_text()
|
||||
self.assertTrue(plan.has_prompt)
|
||||
self.assertEqual("Existing instructions.\n", prompt_text)
|
||||
self.assertEqual("command", settings["statusLine"]["type"])
|
||||
self.assertEqual("~/.claude/statusline.sh", settings["statusLine"]["command"])
|
||||
self.assertEqual("custom:bot-bottle-research-ui", settings["theme"])
|
||||
self.assertIn("research-ui", statusline)
|
||||
self.assertIn("\x1b[96m", statusline)
|
||||
self.assertEqual("dark", theme["base"])
|
||||
self.assertEqual("ansi:cyanBright", theme["overrides"]["claude"])
|
||||
|
||||
def test_runs_verify_commands(self):
|
||||
provision = AgentProvisionPlan(
|
||||
template="claude", command="claude", prompt_mode="append_file",
|
||||
|
||||
@@ -9,6 +9,7 @@ no claude equivalent."""
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
@@ -130,7 +131,7 @@ class TestCodexProvisionPrompt(unittest.TestCase):
|
||||
self.assertIsNone(r)
|
||||
bottle.cp_in.assert_called_once()
|
||||
|
||||
def test_returns_path_when_provider_prompt_has_identity(self):
|
||||
def test_returns_path_when_provider_prompt_exists(self):
|
||||
bottle = _make_bottle()
|
||||
provision = AgentProvisionPlan(
|
||||
template="codex", command="codex",
|
||||
@@ -146,6 +147,28 @@ class TestCodexProvisionPrompt(unittest.TestCase):
|
||||
)
|
||||
self.assertEqual("/home/node/.bot-bottle-prompt.txt", r)
|
||||
|
||||
def test_writes_tui_settings_into_codex_config(self):
|
||||
with tempfile.TemporaryDirectory(prefix="bb-codex-ui.") as tmp:
|
||||
state_dir = Path(tmp)
|
||||
prompt_file = state_dir / "prompt.txt"
|
||||
prompt_file.write_text("Existing instructions.\n")
|
||||
plan = CodexAgentProvider().provision_plan(
|
||||
dockerfile="",
|
||||
state_dir=state_dir,
|
||||
instance_name="bot-bottle-demo-abc12",
|
||||
prompt_file=prompt_file,
|
||||
label="research-ui",
|
||||
color="bright-cyan",
|
||||
)
|
||||
config = (state_dir / "codex-config.toml").read_text()
|
||||
prompt_text = prompt_file.read_text()
|
||||
self.assertTrue(plan.has_prompt)
|
||||
self.assertEqual("Existing instructions.\n", prompt_text)
|
||||
self.assertIn("[tui]", config)
|
||||
self.assertIn('status_line = ["model", "cwd"]', config)
|
||||
self.assertIn('terminal_title = ["spinner", "project"]', config)
|
||||
self.assertIn('theme = "dark-ansi"', config)
|
||||
|
||||
|
||||
class TestCodexProvisionSkills(unittest.TestCase):
|
||||
def test_noop_when_agent_has_no_skills(self):
|
||||
|
||||
Reference in New Issue
Block a user