mirror of
https://github.com/turnstonelabs/turnstone.git
synced 2026-08-12 23:12:23 -06:00
fix(session): record operator skill changes
Operator-driven /skill changes were only shown in the UI, leaving no trajectory marker for the model. Persist a system turn for named skill changes and clears, with regression coverage for both paths.
This commit is contained in:
committed by
Patrick Buckley
parent
8240d2c00d
commit
a64cd25807
@@ -213,6 +213,46 @@ def _run_exec_search(session, capture_return):
|
||||
return output
|
||||
|
||||
|
||||
class TestSkillCommand:
|
||||
@pytest.mark.parametrize(
|
||||
("command", "skill", "expected_name", "expected_target"),
|
||||
[
|
||||
("/skill beta", {"name": "beta"}, "beta", "beta"),
|
||||
("/skill clear", None, None, "defaults"),
|
||||
],
|
||||
)
|
||||
def test_operator_change_is_recorded_in_trajectory(
|
||||
self, command, skill, expected_name, expected_target
|
||||
):
|
||||
session = ChatSession.__new__(ChatSession)
|
||||
session._skill_name = "alpha"
|
||||
session.messages = [turn_from_dict({"role": "user", "content": "prior work"})]
|
||||
session._msg_tokens = [2]
|
||||
session._chars_per_token = 4.0
|
||||
session._ws_id = "test-workstream"
|
||||
session.ui = MagicMock()
|
||||
session.ui.on_system_turn.return_value = None
|
||||
session._ui_event_id = MagicMock(return_value=None)
|
||||
session.set_skill = MagicMock(
|
||||
side_effect=lambda name: setattr(session, "_skill_name", name)
|
||||
)
|
||||
|
||||
with (
|
||||
patch("turnstone.core.session.get_skill_by_name", return_value=skill),
|
||||
patch("turnstone.core.session.save_message") as save_message,
|
||||
):
|
||||
session.handle_command(command)
|
||||
|
||||
session.set_skill.assert_called_once_with(expected_name)
|
||||
marker = turn_to_dict(session.messages[-1])
|
||||
assert marker["role"] == "system"
|
||||
assert marker["_source"] == "skill_hint"
|
||||
assert marker["content"] == (
|
||||
f"Operator changed the active skill from alpha to {expected_target}."
|
||||
)
|
||||
save_message.assert_called_once()
|
||||
|
||||
|
||||
class TestChatSessionConstruction:
|
||||
def test_system_messages_created(self, tmp_db):
|
||||
session = _make_session()
|
||||
|
||||
@@ -16919,6 +16919,7 @@ class ChatSession:
|
||||
self.ui.on_info("Instructions updated.")
|
||||
|
||||
elif cmd == "/skill":
|
||||
previous_skill = self._skill_name or "defaults"
|
||||
if not arg:
|
||||
if self._skill_name:
|
||||
self.ui.on_info(f"Active skill: {self._skill_name}")
|
||||
@@ -16926,11 +16927,19 @@ class ChatSession:
|
||||
self.ui.on_info("Using defaults. Usage: /skill <name> or /skill clear")
|
||||
elif arg.strip().lower() == "clear":
|
||||
self.set_skill(None)
|
||||
self._append_system_turn(
|
||||
"skill_hint",
|
||||
f"Operator changed the active skill from {previous_skill} to defaults.",
|
||||
)
|
||||
self.ui.on_info("Skill cleared; using defaults.")
|
||||
else:
|
||||
tpl = get_skill_by_name(arg.strip())
|
||||
if tpl:
|
||||
self.set_skill(tpl["name"])
|
||||
self._append_system_turn(
|
||||
"skill_hint",
|
||||
f"Operator changed the active skill from {previous_skill} to {tpl['name']}.",
|
||||
)
|
||||
self.ui.on_info(f"Skill set: {tpl['name']}")
|
||||
else:
|
||||
self.ui.on_error(f"Skill not found: {arg.strip()}")
|
||||
|
||||
Reference in New Issue
Block a user