Add `markitect helper <QUESTION>` CLI command that answers questions about markitect using its own documentation as LLM context. Uses OpenRouter with openrouter/aurora-alpha by default; model is configurable via --model flag or MARKITECT_HELPER_MODEL env var. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
100 lines
3.1 KiB
Python
100 lines
3.1 KiB
Python
"""
|
|
Knowledge loader for the markitect helper.
|
|
|
|
Reads markitect's own documentation files and returns them as a
|
|
concatenated string for use as LLM context.
|
|
"""
|
|
|
|
import importlib
|
|
from pathlib import Path
|
|
from typing import List
|
|
|
|
|
|
# Docs to load relative to the project root, in priority order.
|
|
_DOC_PATHS: List[str] = [
|
|
"INTRODUCTION.md",
|
|
"docs/CLI_TUTORIAL.md",
|
|
"docs/PROJECT_STRUCTURE.md",
|
|
"docs/SCHEMA_MANAGEMENT_GUIDE.md",
|
|
"docs/PLUGIN_SYSTEM.md",
|
|
"docs/ERROR_HANDLING_STRATEGY.md",
|
|
"docs/architecture/CAPABILITIES_ARCHITECTURE.md",
|
|
"docs/architecture/caching-system.md",
|
|
"docs/ASSET_MANAGEMENT_USER_GUIDE.md",
|
|
"docs/graphql_interface.md",
|
|
"examples/content-generator/TUTORIAL.md",
|
|
"examples/infospace-with-history/TUTORIAL.md",
|
|
]
|
|
|
|
# Glob patterns (relative to project root) for additional docs.
|
|
_DOC_GLOBS: List[str] = [
|
|
"docs/user-guides/*.md",
|
|
]
|
|
|
|
# Modules whose docstrings to include.
|
|
_MODULE_DOCSTRINGS: List[str] = [
|
|
"markitect.prompts",
|
|
"markitect.llm",
|
|
]
|
|
|
|
|
|
def _find_project_root() -> Path:
|
|
"""Return the markitect project root directory.
|
|
|
|
Walks up from this file (markitect/helper/knowledge.py) to find the
|
|
directory that contains ``markitect/`` as a package *and* has a
|
|
``pyproject.toml`` or ``INTRODUCTION.md``.
|
|
"""
|
|
candidate = Path(__file__).resolve().parent.parent.parent
|
|
# Verify we landed in the right place.
|
|
if (candidate / "pyproject.toml").exists() or (candidate / "INTRODUCTION.md").exists():
|
|
return candidate
|
|
# Fallback: try CWD.
|
|
cwd = Path.cwd()
|
|
if (cwd / "markitect").is_dir():
|
|
return cwd
|
|
return candidate
|
|
|
|
|
|
def collect_knowledge() -> str:
|
|
"""Load markitect documentation and return as a single string.
|
|
|
|
Reads documentation files from the project root, concatenates them
|
|
with section headers, and appends relevant module docstrings.
|
|
Missing files are silently skipped.
|
|
"""
|
|
root = _find_project_root()
|
|
sections: List[str] = []
|
|
|
|
# Fixed-path documents.
|
|
for rel_path in _DOC_PATHS:
|
|
filepath = root / rel_path
|
|
if filepath.is_file():
|
|
try:
|
|
content = filepath.read_text(encoding="utf-8")
|
|
sections.append(f"## {rel_path}\n\n{content}")
|
|
except OSError:
|
|
continue
|
|
|
|
# Glob-pattern documents.
|
|
for pattern in _DOC_GLOBS:
|
|
for filepath in sorted(root.glob(pattern)):
|
|
if filepath.is_file():
|
|
rel = filepath.relative_to(root)
|
|
try:
|
|
content = filepath.read_text(encoding="utf-8")
|
|
sections.append(f"## {rel}\n\n{content}")
|
|
except OSError:
|
|
continue
|
|
|
|
# Module docstrings.
|
|
for mod_name in _MODULE_DOCSTRINGS:
|
|
try:
|
|
mod = importlib.import_module(mod_name)
|
|
if mod.__doc__:
|
|
sections.append(f"## Module: {mod_name}\n\n{mod.__doc__.strip()}")
|
|
except ImportError:
|
|
continue
|
|
|
|
return "\n\n---\n\n".join(sections)
|