forked from github/copilot-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_skills.py
More file actions
101 lines (72 loc) · 3.66 KB
/
Copy pathtest_skills.py
File metadata and controls
101 lines (72 loc) · 3.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
"""
Tests for skills configuration functionality
"""
import os
import pytest
from .testharness import E2ETestContext
pytestmark = pytest.mark.asyncio(loop_scope="module")
SKILL_MARKER = "PINEAPPLE_COCONUT_42"
_skill_dir_counter = 0
def create_skill_dir(work_dir: str) -> str:
"""Create a skills directory in the working directory"""
global _skill_dir_counter
_skill_dir_counter += 1
skills_dir = os.path.join(work_dir, ".test_skills", f"copilot-skills-test-{_skill_dir_counter}")
os.makedirs(skills_dir, exist_ok=True)
# Create a skill subdirectory with SKILL.md
skill_subdir = os.path.join(skills_dir, "test-skill")
os.makedirs(skill_subdir, exist_ok=True)
# Create a skill that instructs the model to include a specific marker in responses
skill_content = f"""---
name: test-skill
description: A test skill that adds a marker to responses
---
# Test Skill Instructions
IMPORTANT: You MUST include the exact text "{SKILL_MARKER}" somewhere in EVERY response you give.
This is a mandatory requirement. Include it naturally in your response.
"""
with open(os.path.join(skill_subdir, "SKILL.md"), "w") as f:
f.write(skill_content)
return skills_dir
@pytest.mark.skip(reason="Skills tests temporarily skipped")
class TestSkillBehavior:
async def test_load_and_apply_skill_from_skill_directories(self, ctx: E2ETestContext):
"""Test that skills are loaded and applied from skillDirectories"""
skills_dir = create_skill_dir(ctx.work_dir)
session = await ctx.client.create_session({"skill_directories": [skills_dir]})
assert session.session_id is not None
# The skill instructs the model to include a marker - verify it appears
message = await session.send_and_wait({"prompt": "Say hello briefly using the test skill."})
assert message is not None
assert SKILL_MARKER in message.data.content
await session.destroy()
async def test_not_apply_skill_when_disabled_via_disabled_skills(self, ctx: E2ETestContext):
"""Test that disabledSkills prevents skill from being applied"""
skills_dir = create_skill_dir(ctx.work_dir)
session = await ctx.client.create_session(
{"skill_directories": [skills_dir], "disabled_skills": ["test-skill"]}
)
assert session.session_id is not None
# The skill is disabled, so the marker should NOT appear
message = await session.send_and_wait({"prompt": "Say hello briefly using the test skill."})
assert message is not None
assert SKILL_MARKER not in message.data.content
await session.destroy()
async def test_apply_skill_on_session_resume_with_skill_directories(self, ctx: E2ETestContext):
"""Test that skills are applied when added on session resume"""
skills_dir = create_skill_dir(ctx.work_dir)
# Create a session without skills first
session1 = await ctx.client.create_session()
session_id = session1.session_id
# First message without skill - marker should not appear
message1 = await session1.send_and_wait({"prompt": "Say hi."})
assert message1 is not None
assert SKILL_MARKER not in message1.data.content
# Resume with skillDirectories - skill should now be active
session2 = await ctx.client.resume_session(session_id, {"skill_directories": [skills_dir]})
assert session2.session_id == session_id
# Now the skill should be applied
message2 = await session2.send_and_wait({"prompt": "Say hello again using the test skill."})
assert message2 is not None
assert SKILL_MARKER in message2.data.content
await session2.destroy()