c47e6445d0
CI / quality (pull_request) Successful in 19s
CI / lint (pull_request) Successful in 22s
CI / benchmark-publish (pull_request) Has been skipped
CI / security (pull_request) Successful in 33s
CI / build (pull_request) Successful in 26s
CI / typecheck (pull_request) Successful in 1m0s
CI / integration_tests (pull_request) Successful in 4m56s
CI / unit_tests (pull_request) Successful in 15m11s
CI / docker (pull_request) Successful in 1m33s
CI / benchmark-regression (pull_request) Successful in 20m55s
CI / coverage (pull_request) Successful in 33m42s
CI / lint (push) Successful in 13s
CI / build (push) Successful in 15s
CI / quality (push) Successful in 17s
CI / security (push) Successful in 28s
CI / typecheck (push) Successful in 32s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 3m3s
CI / benchmark-publish (push) Successful in 10m8s
CI / unit_tests (push) Successful in 12m42s
CI / docker (push) Successful in 39s
CI / coverage (push) Has been cancelled
Add ActorCompiler module that translates GRAPH-type ActorConfigSchema definitions into LangGraph NodeConfig/Edge structures with LSP binding metadata. Includes subgraph resolution with cross-actor cycle detection, entry/exit validation, and CompilationMetadata for diagnostics. New files: - src/cleveragents/actor/compiler.py: Core compiler with compile_actor() - features/actor_compiler.feature: 13 Behave scenarios - features/steps/actor_compiler_steps.py: Step definitions - robot/actor_compiler.robot: 4 Robot smoke tests - benchmarks/actor_compiler_bench.py: ASV performance benchmarks - docs/reference/actor_compiler.md: Compilation pipeline reference Modified: - src/cleveragents/actor/__init__.py: Export compiler types - vulture_whitelist.py: Whitelist new public API ISSUES CLOSED: #158
177 lines
7.5 KiB
Gherkin
177 lines
7.5 KiB
Gherkin
Feature: Agent Skills Discovery
|
|
As a developer using CleverAgents
|
|
I want to discover Agent Skills from configured filesystem paths
|
|
So that external tool bundles are automatically registered in the ToolRegistry
|
|
|
|
Background:
|
|
Given the agent skills discovery module is available
|
|
|
|
# --- Config key ---
|
|
|
|
Scenario: Config key skills.agent_skills_paths is registered
|
|
When I check the config registry for "skills.agent_skills_paths"
|
|
Then the config entry should exist
|
|
And the config entry type should be "str"
|
|
And the config entry env var should be "CLEVERAGENTS_SKILLS_AGENT_SKILLS_PATHS"
|
|
|
|
# --- Path parsing ---
|
|
|
|
Scenario: Parse single agent skills path
|
|
When I parse agent skills paths "~/.cleveragents/agent_skills"
|
|
Then the result should contain 1 path
|
|
|
|
Scenario: Parse multiple comma-separated paths
|
|
When I parse agent skills paths "/opt/skills,/home/user/skills"
|
|
Then the result should contain 2 paths
|
|
|
|
Scenario: Parse empty agent skills paths
|
|
When I parse an empty agent skills path string
|
|
Then the result should contain 0 paths
|
|
|
|
Scenario: Parse paths with whitespace around commas
|
|
When I parse agent skills paths "/opt/skills , /home/user/skills"
|
|
Then the result should contain 2 paths
|
|
|
|
# --- Discovery ---
|
|
|
|
Scenario: Discover agent skills from directory with SKILL.md
|
|
Given a temporary directory with agent skill folders
|
|
| folder_name | skill_name | description |
|
|
| my-tool | my-tool | A test agent skill |
|
|
When I scan the directory for agent skills
|
|
Then I should discover 1 agent skill
|
|
And the discovered skill "my-tool" should have description "A test agent skill"
|
|
|
|
Scenario: Discover multiple agent skills
|
|
Given a temporary directory with agent skill folders
|
|
| folder_name | skill_name | description |
|
|
| tool-a | tool-a | First tool |
|
|
| tool-b | tool-b | Second tool |
|
|
| tool-c | tool-c | Third tool |
|
|
When I scan the directory for agent skills
|
|
Then I should discover 3 agent skills
|
|
|
|
Scenario: Skip directories without SKILL.md
|
|
Given a temporary directory with some folders missing SKILL.md
|
|
When I scan the directory for agent skills
|
|
Then I should discover 0 agent skills
|
|
|
|
Scenario: Handle non-existent directory gracefully
|
|
When I run discovery on a non-existent directory
|
|
Then the discovery result should have 0 discovered skills
|
|
And the discovery result should have errors mentioning "does not exist"
|
|
|
|
Scenario: Handle SKILL.md without front-matter
|
|
Given a temporary directory with a SKILL.md that has no front-matter
|
|
When I scan the directory for agent skills
|
|
Then I should discover 0 agent skills
|
|
|
|
Scenario: Fall back to folder name when SKILL.md has no name field
|
|
Given a temporary directory with agent skill folders
|
|
| folder_name | skill_name | description |
|
|
| fallback-tool | _none_ | Some description |
|
|
When I scan the directory for agent skills
|
|
Then I should discover 1 agent skill
|
|
And the discovered skill should use folder name as name
|
|
|
|
# --- ToolSpec building ---
|
|
|
|
Scenario: Build ToolSpec from discovered agent skill
|
|
Given a discovered agent skill named "my-tool" at "/opt/skills/my-tool"
|
|
When I build a ToolSpec from the discovered skill
|
|
Then the ToolSpec name should be "agent_skills/my-tool"
|
|
And the ToolSpec source should be "agent_skills"
|
|
And the ToolSpec source_metadata should contain path "/opt/skills/my-tool"
|
|
|
|
# --- Registration ---
|
|
|
|
Scenario: Register discovered agent skills in ToolRegistry
|
|
Given a ToolRegistry with no existing tools
|
|
And a list of 2 discovered agent skills
|
|
When I register discovered skills with "skip" conflict strategy
|
|
Then 2 tools should be registered in the ToolRegistry
|
|
And 0 conflicts should be reported
|
|
|
|
Scenario: Skip registration on name collision with skip strategy
|
|
Given a ToolRegistry with an existing tool "agent_skills/collider"
|
|
And a discovered agent skill named "collider"
|
|
When I register discovered skills with "skip" conflict strategy
|
|
Then 0 tools should be registered in the ToolRegistry
|
|
And 1 conflict should be reported with tool name "agent_skills/collider"
|
|
|
|
Scenario: Error on name collision with error strategy
|
|
Given a ToolRegistry with an existing tool "agent_skills/collider"
|
|
And a discovered agent skill named "collider"
|
|
When I register discovered skills with "error" conflict strategy
|
|
Then a discovery ValueError should be raised mentioning "name collision"
|
|
|
|
Scenario: Replace existing tool on collision with replace strategy
|
|
Given a ToolRegistry with an existing tool "agent_skills/collider"
|
|
And a discovered agent skill named "collider"
|
|
When I register discovered skills with "replace" conflict strategy
|
|
Then 1 tool should be registered in the ToolRegistry
|
|
And the tool "agent_skills/collider" should have source "agent_skills"
|
|
|
|
# --- Refresh ---
|
|
|
|
Scenario: Refresh removes old agent skills and re-discovers
|
|
Given a SkillRegistryService with a ToolRegistry
|
|
And agent skills paths pointing to a directory with 2 skills
|
|
When I call discover_and_register
|
|
Then 2 agent skills should be registered
|
|
When the directory now has 3 skills and I call refresh_agent_skills
|
|
Then 3 agent skills should be registered
|
|
|
|
# --- Edge cases ---
|
|
|
|
Scenario: Register empty discovered list returns empty
|
|
Given a ToolRegistry with no existing tools
|
|
When I register an empty discovered skills list
|
|
Then the registration should return 0 specs and 0 conflicts
|
|
|
|
Scenario: Scan non-directory path returns empty
|
|
When I scan a non-directory path for agent skills
|
|
Then I should discover 0 agent skills
|
|
|
|
Scenario: Discover with path that is a file not a directory
|
|
When I run discovery on a path that is a file
|
|
Then the discovery result should have 0 discovered skills
|
|
And the discovery result should have errors mentioning "not a directory"
|
|
|
|
Scenario: SKILL.md with invalid YAML front-matter
|
|
Given a temporary directory with a SKILL.md that has invalid YAML
|
|
When I scan the directory for agent skills
|
|
Then I should discover 0 agent skills
|
|
|
|
Scenario: SKILL.md with empty YAML block
|
|
Given a temporary directory with a SKILL.md that has empty front-matter
|
|
When I scan the directory for agent skills
|
|
Then I should discover 0 agent skills
|
|
|
|
Scenario: SKILL.md with non-dict YAML
|
|
Given a temporary directory with a SKILL.md that has non-dict YAML
|
|
When I scan the directory for agent skills
|
|
Then I should discover 0 agent skills
|
|
|
|
Scenario: Skill with non-string description in front-matter
|
|
Given a temporary directory with a SKILL.md that has numeric description
|
|
When I scan the directory for agent skills
|
|
Then I should discover 1 agent skill
|
|
|
|
Scenario: Skill with empty description falls back to default
|
|
Given a temporary directory with a SKILL.md that has empty description
|
|
When I scan the directory for agent skills
|
|
Then I should discover 1 agent skill
|
|
And the first discovered skill description should contain "Agent skill from"
|
|
|
|
Scenario: Noop handler returns expected placeholder
|
|
When I call the noop handler
|
|
Then the noop handler should return status "agent_skill_placeholder"
|
|
|
|
# --- Source metadata ---
|
|
|
|
Scenario: Source metadata is included when resolving skill tools
|
|
Given a registered skill "local/test-skill" with an agent_skill source
|
|
When I resolve tools for "local/test-skill"
|
|
Then the resolved tools should include agent_skill source entries
|