Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion host-setup/agent-safety/claude/model-tier-guard.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def names_model(text, model):
"""Whether a script text carries a `model: '<name>'` option naming `model`."""
# A JavaScript key may be bare or quoted, so `{"model": "x"}` is the same option as `{model: "x"}`.
# The value may be a full model id rather than the alias, so the alias is matched as a word inside it.
value = r"[^'\"`]*(?<![a-z0-9])(?i:" + re.escape(model) + r")(?![a-z0-9])[^'\"`]*"
value = r"[^'\"`]*(?<![A-Za-z0-9])(?i:" + re.escape(model) + r")(?![A-Za-z0-9])[^'\"`]*"
pattern = r"(?<![\w$])['\"]?model['\"]?\s*:\s*['\"`]" + value + r"['\"`]"
return re.search(pattern, text) is not None

Expand Down
10 changes: 10 additions & 0 deletions host-setup/agent-safety/claude/test_model_tier_guard.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ def test_a_workflow_script_naming_the_blocked_model_is_denied(self):
'agent("x", {"model": "fable"})',
"agent('x', {'model': 'fable'})",
"agent('x', { model: 'claude-fable-5-1' })",
"agent('x', { model: 'claude-Fable-5-1' })",
):
with self.subTest(script=script):
self.assertDenied(self.run_hook("Workflow", {"script": script}))
Expand All @@ -131,6 +132,15 @@ def test_a_script_file_is_read_even_beside_an_inline_script(self):
tool_input = {"script": "agent('x', { model: 'opus' })", "scriptPath": str(path)}
self.assertDenied(self.run_hook("Workflow", tool_input))

def test_a_workflow_model_merely_containing_the_blocked_alias_is_allowed(self):
for script in (
"agent('x', { model: 'fableX' })",
"agent('x', { model: 'Xfable' })",
"agent('x', { model: 'FABLEX' })",
):
with self.subTest(script=script):
self.assertIsNone(self.run_hook("Workflow", {"script": script}))

def test_a_workflow_at_another_model_or_saved_by_name_is_allowed(self):
self.assertIsNone(self.run_hook("Workflow", {"script": "agent('x', { model: 'opus' })"}))
self.assertIsNone(self.run_hook("Workflow", {"name": "saved-flow"}))
Expand Down
Loading