Skip to content

Creates AI Resource Page plugin#8

Draft
dawnkelly09 wants to merge 12 commits intostaging-ai-resources-pluginfrom
build-ai-resources-plugin
Draft

Creates AI Resource Page plugin#8
dawnkelly09 wants to merge 12 commits intostaging-ai-resources-pluginfrom
build-ai-resources-plugin

Conversation

@dawnkelly09
Copy link
Contributor

This pull request introduces a new "AI Resources Page" MkDocs plugin and a shared AI file utilities module, along with supporting documentation and configuration. The changes automate the creation of an AI-focused resources page, standardize AI artifact actions (like "View", "Copy", "Open in ChatGPT"), and provide clear developer documentation for both features.

Key changes include:

New AI Resources Page Plugin

  • Added the ai_resources_page plugin, which auto-generates an "AI Resources" documentation page based on llms_config.json, including an overview and a dynamic table of global and category AI artifact files with standardized action buttons. [1] [2] [3] [4] [5]

AI File Utilities Module

  • Introduced ai_file_utils.py, a shared utility class for defining and resolving standardized AI artifact actions (e.g., "View Markdown", "Open in ChatGPT") using a JSON schema and context interpolation.
  • Added ai_file_actions.json with a schema for common actions, supporting dynamic variables and prompt templates for LLM tools.
  • Provided developer documentation for the AI file utilities module, including usage, schema, and extensibility instructions.

Documentation

  • Added comprehensive documentation for both the new plugin (docs/ai-resources-page.md) and the AI file utilities module (docs/ai-file-utils.md). [1] [2]
  • Updated the main README.md to reference the new plugin and its usage. [1] [2]

These changes enable automated, consistent AI resource surfacing for documentation sites and provide a foundation for further AI/LLM integrations.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an MkDocs plugin that generates an “AI Resources” page from llms_config.json, plus a shared AIFileUtils module for generating standardized “View/Copy/Download/Open in LLM” actions, along with documentation and configuration updates.

Changes:

  • Added ai_resources_page MkDocs plugin to auto-generate ai-resources.md content from llms_config.json.
  • Added ai_file_utils module + ai_file_actions.json schema for resolving standardized action definitions.
  • Added documentation pages and updated README / MkDocs entry-point configuration.

Reviewed changes

Copilot reviewed 9 out of 11 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
plugins/ai_resources_page/plugin.py Implements the AI Resources page markdown generation and action rendering.
plugins/ai_resources_page/__init.py__ Adds package init file (currently misnamed).
plugins/ai_file_utils/ai_file_utils.py Implements schema loading + placeholder interpolation for actions.
plugins/ai_file_utils/ai_file_actions.json Defines default actions (View/Download/Copy/ChatGPT/Claude).
pyproject.toml Registers the new MkDocs plugin entry-point.
tests/ai_file_utils/test_ai_file_utils.py Adds tests for action resolution + schema error handling.
tests/ai_file_utils/test_plugin.py Duplicates the same AIFileUtils tests (appears redundant).
docs/ai-resources-page.md Documents configuration and behavior of the new plugin.
docs/ai-file-utils.md Documents AIFileUtils usage, schema, and extension patterns.
README.md References the new plugin and shows mkdocs.yml usage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

log = logging.getLogger("mkdocs.plugins.ai_resources_page")

class AiResourcesPagePlugin(BasePlugin):
def __init__(self):
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AiResourcesPagePlugin.__init__ doesn’t call super().__init__(). Other plugins in this repo (e.g. ResolveMDPlugin) call the base initializer; skipping it can leave BasePlugin state/config uninitialized and cause runtime issues.

Suggested change
def __init__(self):
def __init__(self):
super().__init__()

Copilot uses AI. Check for mistakes.
project_cfg = self.llms_config.get("project", {})
project_name = project_cfg.get("name")
if not project_name:
raise KeyError("[ai_resources_page] 'project.name' is missing in llms_config.json")
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The raise KeyError(...) line is over-indented compared to the surrounding block. While it may still run, it’s inconsistent with the repository’s formatting (Black) and risks introducing indentation-related errors if the block is edited later.

Suggested change
raise KeyError("[ai_resources_page] 'project.name' is missing in llms_config.json")
raise KeyError("[ai_resources_page] 'project.name' is missing in llms_config.json")

Copilot uses AI. Check for mistakes.
Comment on lines +54 to +64
# This would be the structure consumed by the UI generator
print("\n--- Resolved Actions Example ---")
for action in actions:
print(f"Action ID: {action['id']}")
print(f" Type: {action['type']}")
print(f" Label: {action['label']}")
if "href" in action:
print(f" Href: {action['href'][:50]}...") # Truncated for display
if "clipboardContent" in action:
print(f" Clipboard: {action['clipboardContent'][:20]}...")

Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test contains multiple print(...) statements, which will spam CI output and aren’t needed for assertions. Prefer removing them or using pytest’s captured output only when explicitly debugging (or gating behind a verbose flag).

Suggested change
# This would be the structure consumed by the UI generator
print("\n--- Resolved Actions Example ---")
for action in actions:
print(f"Action ID: {action['id']}")
print(f" Type: {action['type']}")
print(f" Label: {action['label']}")
if "href" in action:
print(f" Href: {action['href'][:50]}...") # Truncated for display
if "clipboardContent" in action:
print(f" Clipboard: {action['clipboardContent'][:20]}...")

Copilot uses AI. Check for mistakes.
Comment on lines +65 to +76
def test_missing_schema_file(self, tmp_path, caplog):
"""Test behavior when schema file is missing."""
utils = AIFileUtils()
# Override path to non-existent file
utils._actions_config_path = tmp_path / "non_existent.json"

# Should return empty list, not crash. Logs warning internally.
actions = utils.resolve_actions("url", "file", "content")

# Verify warning log
assert "Actions schema file not found" in caplog.text
assert actions == []
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

caplog assertions may be flaky here because the test never sets the capture level and logger name. Since AIFileUtils logs via mkdocs.utils.log, explicitly set caplog.set_level(...) (and, if needed, the logger=) before calling resolve_actions to ensure the message is captured reliably.

Copilot uses AI. Check for mistakes.
Comment on lines +57 to +60
if "ai-resources.md" not in page.file.src_path:
return markdown

log.info(f"[ai_resources_page] Generating content for {page.file.src_path}")
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Page targeting uses a substring check ("ai-resources.md" in page.file.src_path). This will also match paths like some-ai-resources.md or ai-resources.md.bak. Use an exact filename/endswith("/ai-resources.md") style check to avoid generating content on the wrong page.

Suggested change
if "ai-resources.md" not in page.file.src_path:
return markdown
log.info(f"[ai_resources_page] Generating content for {page.file.src_path}")
src_path = page.file.src_path
if Path(src_path).name != "ai-resources.md":
return markdown
log.info(f"[ai_resources_page] Generating content for {src_path}")

Copilot uses AI. Check for mistakes.
Comment on lines +131 to +137

filename = f"{slug}.md"
url = f"{public_root_stripped}/categories/{filename}"

actions = self.generate_actions_html(url, filename)

row = f"| {cat} | {description} | <code style=\"white-space: nowrap;\">{filename}</code> | {actions} |"
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Category names/descriptions are inserted into a markdown table row without escaping. If cat or description contains | or newlines (valid in JSON), it will break the table rendering. Consider sanitizing/escaping table cell content before formatting the row.

Suggested change
filename = f"{slug}.md"
url = f"{public_root_stripped}/categories/{filename}"
actions = self.generate_actions_html(url, filename)
row = f"| {cat} | {description} | <code style=\"white-space: nowrap;\">{filename}</code> | {actions} |"
# Sanitize category name and description for markdown table cells
cat_cell = re.sub(r"[\r\n]+", " ", str(cat)).replace("|", "\\|")
description_cell = re.sub(r"[\r\n]+", " ", str(description)).replace("|", "\\|")
filename = f"{slug}.md"
url = f"{public_root_stripped}/categories/{filename}"
actions = self.generate_actions_html(url, filename)
row = f"| {cat_cell} | {description_cell} | <code style=\"white-space: nowrap;\">{filename}</code> | {actions} |"

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +18
def __init__(self):
self._actions_schema = None
self._actions_config_path = Path(__file__).parent / "ai_file_actions.json"

Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AIFileUtils loads ai_file_actions.json from the package directory at runtime, but the repo doesn’t appear to configure setuptools to include JSON files in the built wheel/sdist. In an installed package, this file may be missing, causing all actions to resolve as empty. Add package-data configuration (e.g. tool.setuptools.package-data / MANIFEST.in) or embed defaults in Python.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +4
import pytest
from plugins.ai_file_utils.ai_file_utils import AIFileUtils

class TestAIFileUtils:
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two test modules are identical (test_plugin.py and test_ai_file_utils.py), so the same tests will run twice. This adds noise and maintenance overhead; remove one file or split them so each file tests distinct behavior.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,120 @@
import pytest
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'pytest' is not used.

Suggested change
import pytest

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,120 @@
import pytest
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'pytest' is not used.

Suggested change
import pytest

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant