Add skill enable controls and data factory SQL skill
This commit is contained in:
@@ -40,6 +40,25 @@ class AgentPromptingTests(unittest.TestCase):
|
||||
self.assertIn('__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__', prompt)
|
||||
self.assertIn('主工作目录:', prompt)
|
||||
|
||||
def test_prompt_builder_respects_enabled_skill_names(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
runtime_config = AgentRuntimeConfig(
|
||||
cwd=Path(tmp_dir),
|
||||
enabled_skill_names=('verify',),
|
||||
)
|
||||
model_config = ModelConfig(model='Qwen/Qwen3-Coder-30B-A3B-Instruct')
|
||||
prompt_context = build_prompt_context(runtime_config, model_config)
|
||||
parts = build_system_prompt_parts(
|
||||
prompt_context=prompt_context,
|
||||
runtime_config=runtime_config,
|
||||
tools=default_tool_registry(),
|
||||
)
|
||||
|
||||
prompt = render_system_prompt(parts)
|
||||
self.assertIn('verify', prompt)
|
||||
self.assertNotIn('product-data', prompt)
|
||||
self.assertNotIn('online-mining', prompt)
|
||||
|
||||
def test_session_state_exports_messages_in_order(self) -> None:
|
||||
state = AgentSessionState.create(['sys one', 'sys two'], 'hello')
|
||||
state.append_assistant('working', ())
|
||||
|
||||
@@ -66,6 +66,14 @@ class BundledSkillsTests(unittest.TestCase):
|
||||
self.assertIn('verify', rendered)
|
||||
self.assertIn('update-config', rendered)
|
||||
|
||||
def test_skills_prompt_respects_enabled_skill_filter(self) -> None:
|
||||
rendered = format_skills_for_system_prompt(
|
||||
enabled_skill_names=('verify', 'product-data')
|
||||
)
|
||||
self.assertIn('verify', rendered)
|
||||
self.assertIn('product-data', rendered)
|
||||
self.assertNotIn('online-mining', rendered)
|
||||
|
||||
def test_project_skills_are_loaded_from_workspace_skills_directory(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
workspace = Path(tmp_dir)
|
||||
|
||||
@@ -149,13 +149,59 @@ class GuiServerTests(unittest.TestCase):
|
||||
|
||||
def test_skills_listed(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
client, _ = _build_client(Path(d))
|
||||
root = Path(d)
|
||||
skill_dir = root / 'skills' / 'project-skill'
|
||||
skill_dir.mkdir(parents=True)
|
||||
(skill_dir / 'SKILL.md').write_text(
|
||||
(
|
||||
'---\n'
|
||||
'name: project-skill\n'
|
||||
'description: Project skill.\n'
|
||||
'---\n'
|
||||
'Project skill body.\n'
|
||||
),
|
||||
encoding='utf-8',
|
||||
)
|
||||
client, _ = _build_client(root)
|
||||
response = client.get('/api/skills')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
skills = response.json()
|
||||
self.assertTrue(skills)
|
||||
names = {entry['name'] for entry in skills}
|
||||
self.assertIn('simplify', names)
|
||||
by_name = {entry['name']: entry for entry in skills}
|
||||
self.assertIn('project-skill', by_name)
|
||||
self.assertTrue(by_name['project-skill']['enabled'])
|
||||
self.assertTrue(by_name['project-skill']['configurable'])
|
||||
self.assertNotIn('simplify', by_name)
|
||||
|
||||
def test_skill_preference_toggle_updates_prompt_filter(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
root = Path(d)
|
||||
skill_dir = root / 'skills' / 'project-skill'
|
||||
skill_dir.mkdir(parents=True)
|
||||
(skill_dir / 'SKILL.md').write_text(
|
||||
(
|
||||
'---\n'
|
||||
'name: project-skill\n'
|
||||
'description: Project skill.\n'
|
||||
'---\n'
|
||||
'Project skill body.\n'
|
||||
),
|
||||
encoding='utf-8',
|
||||
)
|
||||
client, state = _build_client(root)
|
||||
|
||||
response = client.patch(
|
||||
'/api/skills',
|
||||
json={'skill': 'project-skill', 'enabled': False},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
skill = {
|
||||
entry['name']: entry
|
||||
for entry in response.json()
|
||||
}['project-skill']
|
||||
self.assertFalse(skill['enabled'])
|
||||
self.assertNotIn('project-skill', state.agent_for().runtime_config.enabled_skill_names)
|
||||
self.assertIn('verify', state.agent_for().runtime_config.enabled_skill_names)
|
||||
|
||||
def test_chat_runs_local_slash_command(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
|
||||
@@ -313,6 +313,7 @@ class TestRuntimeConfigSerialization(unittest.TestCase):
|
||||
session_directory=Path('/sessions'),
|
||||
scratchpad_root=Path('/scratch'),
|
||||
python_env_dir=Path('/python/.venv'),
|
||||
enabled_skill_names=('verify', 'product-data'),
|
||||
)
|
||||
payload = serialize_runtime_config(config)
|
||||
restored = deserialize_runtime_config(payload)
|
||||
@@ -346,6 +347,7 @@ class TestRuntimeConfigSerialization(unittest.TestCase):
|
||||
self.assertEqual(restored.output_schema.schema, config.output_schema.schema)
|
||||
self.assertTrue(restored.output_schema.strict)
|
||||
self.assertEqual(restored.python_env_dir, Path('/python/.venv'))
|
||||
self.assertEqual(restored.enabled_skill_names, ('verify', 'product-data'))
|
||||
|
||||
def test_round_trip_none_output_schema(self) -> None:
|
||||
config = AgentRuntimeConfig(
|
||||
@@ -374,6 +376,7 @@ class TestRuntimeConfigSerialization(unittest.TestCase):
|
||||
self.assertFalse(config.disable_claude_md_discovery)
|
||||
self.assertIsNone(config.budget_config.max_total_tokens)
|
||||
self.assertIsNone(config.output_schema)
|
||||
self.assertIsNone(config.enabled_skill_names)
|
||||
|
||||
def test_deserialize_non_dict_permissions(self) -> None:
|
||||
payload = {'cwd': '/home', 'permissions': 'invalid'}
|
||||
|
||||
Reference in New Issue
Block a user