mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-10 15:56:03 +00:00
chore(skill): prune dead local-filesystem helpers left over from Box migration
Follow-up to the Box-only refactor. The previous commit removed the
local-fallback BRANCHES from every public method; this one removes the
HELPERS those branches called, which are now unreachable.
SkillService (service/skill.py): 787 → 449 lines
Removed: scan_directory (sync), _read_skill_package, _write_skill_md,
_resolve_create_field, _managed_skill_path,
_managed_install_root_for_package, _normalize_package_root,
_resolve_skill_path, _find_skill_entry, _discover_skill_directories,
_safe_extract_zip, _extract_uploaded_skill_to_temp,
_download_github_skill_to_temp, _resolve_github_source_root,
_build_preview_target_dir, _preview_skill_candidates,
_select_preview_candidates, _install_preview_candidates,
_preview_source_root, _resolve_installed_skills, plus the
module-level _FRONTMATTER_FIELDS and _build_skill_md.
Kept (still needed by the surviving GitHub-import path):
_download_github_asset, _download_github_skill_directory_as_zip,
_find_github_skill_archive_entry, _copy_github_skill_directory_to_zip,
_is_github_skill_md_url, _parse_github_skill_md_url,
_resolve_github_skill_md_package_name, _validate_github_asset_url,
_uploaded_skill_target_stem, _validate_skill_name.
Imports dropped: shutil, tempfile, yaml, ....utils.paths.
SkillManager (skill/manager.py): 187 → 88 lines
Removed: get_managed_skills_root, _discover_skill_directories,
_find_skill_entry, _load_skill_file, _normalize_package_root.
Imports dropped: datetime, parse_frontmatter, paths.
Tests:
- test_skill_service.py: drop the 3 sync scan_directory tests +
skill_service fixture + _create_skill_file helper
- test_skill_tools.py: drop test_load_skill_file_success; rename
TestSkillManagerPackageLoading → TestSkillManagerCache
Full unit suite: 277 passed, 1 skipped. ``ruff check`` clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -35,24 +35,10 @@ def _make_skill_data(
|
||||
}
|
||||
|
||||
|
||||
class TestSkillManagerPackageLoading:
|
||||
def test_load_skill_file_success(self):
|
||||
from langbot.pkg.skill.manager import SkillManager
|
||||
|
||||
ap = _make_ap()
|
||||
mgr = SkillManager(ap)
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
skill_md = os.path.join(tmpdir, 'SKILL.md')
|
||||
with open(skill_md, 'w', encoding='utf-8') as f:
|
||||
f.write('---\ndescription: Test skill\n---\n\n# Test Skill\nDo things.')
|
||||
|
||||
skill_data = _make_skill_data(package_root=tmpdir)
|
||||
result = mgr._load_skill_file(skill_data)
|
||||
|
||||
assert result is True
|
||||
assert skill_data['instructions'] == '# Test Skill\nDo things.'
|
||||
assert skill_data['description'] == 'Test skill'
|
||||
class TestSkillManagerCache:
|
||||
"""The Box runtime is the only source of truth — SkillManager just holds
|
||||
an in-memory cache populated by ``reload_skills``. There is no local
|
||||
filesystem reader anymore."""
|
||||
|
||||
def test_refresh_skill_from_disk_reports_cache_presence(self):
|
||||
"""Box is the only source of truth for skill content. refresh_skill_from_disk
|
||||
|
||||
@@ -6,69 +6,6 @@ import pytest
|
||||
from langbot.pkg.api.http.service.skill import SkillService
|
||||
|
||||
|
||||
def _create_skill_file(
|
||||
path,
|
||||
*,
|
||||
name: str = 'imported-skill',
|
||||
display_name: str = '',
|
||||
description: str = 'Imported from local directory',
|
||||
body: str = 'Skill instructions',
|
||||
) -> None:
|
||||
frontmatter = ['name: ' + name, 'description: ' + description]
|
||||
if display_name:
|
||||
frontmatter.insert(1, 'display_name: ' + display_name)
|
||||
|
||||
path.write_text(
|
||||
'---\n' + '\n'.join(frontmatter) + f'\n---\n\n{body}\n',
|
||||
encoding='utf-8',
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def skill_service():
|
||||
app = SimpleNamespace(
|
||||
skill_mgr=SimpleNamespace(
|
||||
refresh_skill_from_disk=lambda *_args, **_kwargs: True,
|
||||
reload_skills=AsyncMock(),
|
||||
)
|
||||
)
|
||||
return SkillService(app)
|
||||
|
||||
|
||||
def test_scan_directory_supports_nested_skill_within_two_levels(skill_service, tmp_path):
|
||||
nested_dir = tmp_path / 'downloaded' / 'self-improving-agent'
|
||||
nested_dir.mkdir(parents=True)
|
||||
_create_skill_file(nested_dir / 'SKILL.md')
|
||||
|
||||
result = skill_service.scan_directory(str(tmp_path))
|
||||
|
||||
assert result['package_root'] == str(nested_dir.resolve())
|
||||
assert result['entry_file'] == 'SKILL.md'
|
||||
assert result['name'] == 'imported-skill'
|
||||
assert result['instructions'] == 'Skill instructions'
|
||||
|
||||
|
||||
def test_scan_directory_rejects_ambiguous_nested_skill_directories(skill_service, tmp_path):
|
||||
first_dir = tmp_path / 'skills' / 'alpha'
|
||||
second_dir = tmp_path / 'skills' / 'beta'
|
||||
first_dir.mkdir(parents=True)
|
||||
second_dir.mkdir(parents=True)
|
||||
_create_skill_file(first_dir / 'SKILL.md', body='alpha instructions')
|
||||
_create_skill_file(second_dir / 'SKILL.md', body='beta instructions')
|
||||
|
||||
with pytest.raises(ValueError, match='Multiple skill directories found'):
|
||||
skill_service.scan_directory(str(tmp_path))
|
||||
|
||||
|
||||
def test_scan_directory_errors_when_skill_is_deeper_than_two_levels(skill_service, tmp_path):
|
||||
deep_dir = tmp_path / 'a' / 'b' / 'c'
|
||||
deep_dir.mkdir(parents=True)
|
||||
_create_skill_file(deep_dir / 'SKILL.md')
|
||||
|
||||
with pytest.raises(ValueError, match='max depth: 2'):
|
||||
skill_service.scan_directory(str(tmp_path))
|
||||
|
||||
|
||||
class TestRequireBoxForWrite:
|
||||
"""Box is the only source of truth for skills — there is no local
|
||||
filesystem fallback. Every write and (most) read methods refuse cleanly
|
||||
|
||||
Reference in New Issue
Block a user