Add skill enable controls and data factory SQL skill

This commit is contained in:
武阳
2026-05-08 14:56:32 +08:00
parent 046b0eeab0
commit bd2f260b9f
16 changed files with 1167 additions and 25 deletions
+19
View File
@@ -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', ())
+8
View File
@@ -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)
+49 -3
View File
@@ -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:
+3
View File
@@ -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'}