refactor(server): extract context.py into focused modules

Split the monolithic context.py (117 lines) into five purpose-specific
modules following single-responsibility principle:

- config.py: Server-level constants (DATA_DIR, SESSIONS_DIR, PORT,
  STALE_EVENT_AGE, _state_lock)
- agents.py: Agent-specific paths and caches (CLAUDE_PROJECTS_DIR,
  CODEX_SESSIONS_DIR, discovery caches)
- auth.py: Authentication token generation/validation for spawn endpoint
- spawn_config.py: Spawn feature configuration (PENDING_SPAWNS_DIR,
  rate limiting, projects watcher thread)
- zellij.py: Zellij binary resolution and session management constants

This refactoring improves:
- Code navigation: Find relevant constants by domain, not alphabetically
- Testing: Each module can be tested in isolation
- Import clarity: Mixins import only what they need
- Future maintenance: Changes to one domain don't risk breaking others

All mixins updated to import from new module locations. Tests updated
to use new import paths.

Includes PROPOSED_CODE_FILE_REORGANIZATION_PLAN.md documenting the
rationale and mapping from old to new locations.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
teernisse
2026-02-27 11:05:39 -05:00
parent 69175f08f9
commit 1fb4a82b39
20 changed files with 683 additions and 191 deletions

View File

@@ -37,7 +37,7 @@ class SkillsMixin:
Checks SKILL.md (canonical) first, then falls back to skill.md,
prompt.md, README.md for description extraction. Parses YAML
frontmatter if present to extract the description field.
frontmatter if present to extract name and description fields.
Returns:
List of {name: str, description: str} dicts.
@@ -53,35 +53,41 @@ class SkillsMixin:
if not skill_dir.is_dir() or skill_dir.name.startswith("."):
continue
description = ""
# Check files in priority order
meta = {"name": "", "description": ""}
# Check files in priority order, accumulating metadata
# (earlier files take precedence for each field)
for md_name in ["SKILL.md", "skill.md", "prompt.md", "README.md"]:
md_file = skill_dir / md_name
if md_file.exists():
try:
content = md_file.read_text()
description = self._extract_description(content)
if description:
parsed = self._parse_frontmatter(content)
if not meta["name"] and parsed["name"]:
meta["name"] = parsed["name"]
if not meta["description"] and parsed["description"]:
meta["description"] = parsed["description"]
if meta["description"]:
break
except OSError:
pass
skills.append({
"name": skill_dir.name,
"description": description or f"Skill: {skill_dir.name}",
"name": meta["name"] or skill_dir.name,
"description": meta["description"] or f"Skill: {skill_dir.name}",
})
return skills
def _extract_description(self, content: str) -> str:
"""Extract description from markdown content.
def _parse_frontmatter(self, content: str) -> dict:
"""Extract name and description from markdown YAML frontmatter.
Handles YAML frontmatter (looks for 'description:' field) and
falls back to first meaningful line after frontmatter.
Returns:
Dict with 'name' and 'description' keys (both str, may be empty).
"""
result = {"name": "", "description": ""}
lines = content.splitlines()
if not lines:
return ""
return result
# Check for YAML frontmatter
frontmatter_end = 0
@@ -91,33 +97,37 @@ class SkillsMixin:
if stripped == "---":
frontmatter_end = i + 1
break
# Look for description field in frontmatter
if stripped.startswith("description:"):
# Extract value after colon
desc = stripped[len("description:"):].strip()
# Remove quotes if present
if desc.startswith('"') and desc.endswith('"'):
desc = desc[1:-1]
elif desc.startswith("'") and desc.endswith("'"):
desc = desc[1:-1]
# Handle YAML multi-line indicators (>- or |-)
if desc in (">-", "|-", ">", "|", ""):
# Multi-line: read the next indented line
if i + 1 < len(lines):
next_line = lines[i + 1].strip()
if next_line and not next_line.startswith("---"):
return next_line[:100]
elif desc:
return desc[:100]
# Check each known frontmatter field
for field in ("name", "description"):
if stripped.startswith(f"{field}:"):
val = stripped[len(field) + 1:].strip()
# Remove quotes if present
if val.startswith('"') and val.endswith('"'):
val = val[1:-1]
elif val.startswith("'") and val.endswith("'"):
val = val[1:-1]
# Handle YAML multi-line indicators (>- or |-)
if val in (">-", "|-", ">", "|", ""):
if i + 1 < len(lines):
next_line = lines[i + 1].strip()
if next_line and not next_line.startswith("---"):
val = next_line
else:
val = ""
else:
val = ""
if val:
result[field] = val[:100]
# Fall back to first meaningful line after frontmatter
for line in lines[frontmatter_end:]:
stripped = line.strip()
# Skip empty lines, headers, comments, and frontmatter delimiters
if stripped and not stripped.startswith("#") and not stripped.startswith("<!--") and stripped != "---":
return stripped[:100]
# Fall back to first meaningful line for description
if not result["description"]:
for line in lines[frontmatter_end:]:
stripped = line.strip()
if stripped and not stripped.startswith("#") and not stripped.startswith("<!--") and stripped != "---":
result["description"] = stripped[:100]
break
return ""
return result
def _enumerate_codex_skills(self) -> list[dict]:
"""Enumerate Codex skills from cache and user directory.
@@ -161,19 +171,19 @@ class SkillsMixin:
if not skill_dir.is_dir() or skill_dir.name.startswith("."):
continue
description = ""
# Check SKILL.md for description
meta = {"name": "", "description": ""}
# Check SKILL.md for metadata
skill_md = skill_dir / "SKILL.md"
if skill_md.exists():
try:
content = skill_md.read_text()
description = self._extract_description(content)
meta = self._parse_frontmatter(content)
except OSError:
pass
skills.append({
"name": skill_dir.name,
"description": description or f"User skill: {skill_dir.name}",
"name": meta["name"] or skill_dir.name,
"description": meta["description"] or f"User skill: {skill_dir.name}",
})
return skills