Implemented the next missing parity slice around the /skills slash command listing.
/skills now enumerates bundled_skills.BUNDLED_SKILLS (matching the npm SkillsMenu component, which lists skills — not slash commands). Previously it mislabeled the slash-command catalog as "Available Skills". Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -359,7 +359,7 @@ Missing npm slash commands (from `src/commands/` — 80+ commands total):
|
||||
- [x] `/resume`, `/continue` — Resume a previous conversation
|
||||
- [x] `/rewind`, `/checkpoint` — Restore code/conversation to a previous point
|
||||
- [x] `/sandbox-toggle` — Toggle sandbox mode (alias `/sandbox`)
|
||||
- [x] `/skills` — List available skills
|
||||
- [x] `/skills` — List available bundled skills (mirrors `commands/skills/SkillsMenu.tsx`; lists `bundled_skills.BUNDLED_SKILLS`, not slash commands)
|
||||
- [x] `/stats` — Usage statistics and activity
|
||||
- [x] `/stickers` — Order stickers
|
||||
- [x] `/tag` — Toggle a searchable tag on the session
|
||||
|
||||
@@ -1667,11 +1667,19 @@ def _handle_add_dir(agent: 'LocalCodingAgent', args: str, input_text: str) -> Sl
|
||||
|
||||
|
||||
def _handle_skills(agent: 'LocalCodingAgent', _args: str, input_text: str) -> SlashCommandResult:
|
||||
"""List available skills."""
|
||||
"""List bundled skills (mirrors npm `/skills` SkillsMenu listing)."""
|
||||
from .bundled_skills import get_bundled_skills
|
||||
|
||||
lines = ['## Available Skills', '']
|
||||
for spec in get_slash_command_specs():
|
||||
primary = f'/{spec.names[0]}'
|
||||
lines.append(f'- `{primary}`: {spec.description}')
|
||||
for skill in get_bundled_skills():
|
||||
if not skill.user_invocable:
|
||||
continue
|
||||
header = f'- `{skill.name}`'
|
||||
if skill.aliases:
|
||||
header += f' (aliases: {", ".join(skill.aliases)})'
|
||||
lines.append(f'{header}: {skill.description}')
|
||||
if skill.when_to_use:
|
||||
lines.append(f' - When to use: {skill.when_to_use}')
|
||||
lines.extend(['', 'Use the Skill tool to invoke skills programmatically.'])
|
||||
return _local_result(input_text, '\n'.join(lines))
|
||||
|
||||
|
||||
@@ -318,6 +318,25 @@ class AgentRuntimeTests(unittest.TestCase):
|
||||
self.assertEqual(result.tool_calls, 0)
|
||||
self.assertIn('# Permissions', result.final_output)
|
||||
|
||||
def test_slash_skills_lists_bundled_skills(self) -> None:
|
||||
from src.bundled_skills import get_bundled_skills
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
agent = LocalCodingAgent(
|
||||
model_config=ModelConfig(model='Qwen/Qwen3-Coder-30B-A3B-Instruct'),
|
||||
runtime_config=AgentRuntimeConfig(cwd=Path(tmp_dir)),
|
||||
)
|
||||
result = agent.run('/skills')
|
||||
self.assertEqual(result.turns, 0)
|
||||
self.assertEqual(result.tool_calls, 0)
|
||||
self.assertIn('Available Skills', result.final_output)
|
||||
for skill in get_bundled_skills():
|
||||
if skill.user_invocable:
|
||||
self.assertIn(skill.name, result.final_output)
|
||||
# Slash command names (e.g. 'permissions') must NOT appear — that was
|
||||
# the old buggy behavior the upstream `/skills` command never did.
|
||||
self.assertNotIn('/permissions', result.final_output)
|
||||
|
||||
def test_clear_runtime_state_drops_session_env_vars(self) -> None:
|
||||
from src.session_env_vars import (
|
||||
clear_session_env_vars,
|
||||
|
||||
Reference in New Issue
Block a user