diff --git a/CHANGELOG.md b/CHANGELOG.md index e0b5bf5f..db64339c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Added - **Chunk visualization for generated skills**: `visualize_chunk(chunk_id)` function exposed in generated skill packages, enabling callers to render visual grounding from chunk IDs in skill state +- **Configurable generated skills**: Generated skill `create_skill()` now accepts optional `db_path` and `config` parameters, enabling post-discovery reconfiguration via `skill.reconfigure()` (requires haiku.skills >= 0.11.0) ### Fixed diff --git a/haiku_rag_slim/haiku/rag/skill_generator/templates/__init__.py.j2 b/haiku_rag_slim/haiku/rag/skill_generator/templates/__init__.py.j2 index eaf36767..27c130af 100644 --- a/haiku_rag_slim/haiku/rag/skill_generator/templates/__init__.py.j2 +++ b/haiku_rag_slim/haiku/rag/skill_generator/templates/__init__.py.j2 @@ -2,6 +2,7 @@ from pathlib import Path from pydantic import BaseModel, Field +from haiku.rag.config.models import AppConfig from haiku.skills.models import Skill from haiku.skills.parser import parse_skill_md {% if "ask" in tool_names or "research" in tool_names %} @@ -62,12 +63,21 @@ def _get_config(): return get_config() -def create_skill() -> Skill: +def create_skill( + db_path: Path | None = None, + config: AppConfig | None = None, +) -> Skill: from haiku.rag.skills._tools import create_skill_tools metadata, instructions = parse_skill_md(Path(__file__).parent / "SKILL.md") - config = _get_config() - tools = create_skill_tools(_DB_PATH, config, SkillState, _TOOL_NAMES) + + if config is None: + config = _get_config() + + if db_path is None: + db_path = _DB_PATH + + tools = create_skill_tools(db_path, config, SkillState, _TOOL_NAMES) return Skill( metadata=metadata, instructions=instructions, diff --git a/haiku_rag_slim/haiku/rag/skill_generator/templates/pyproject.toml.j2 b/haiku_rag_slim/haiku/rag/skill_generator/templates/pyproject.toml.j2 index c571f03e..62d52c3d 100644 --- a/haiku_rag_slim/haiku/rag/skill_generator/templates/pyproject.toml.j2 +++ b/haiku_rag_slim/haiku/rag/skill_generator/templates/pyproject.toml.j2 @@ -10,7 +10,7 @@ readme = "README.md" requires-python = ">=3.12" dependencies = [ "haiku.rag-slim >= {{ rag_version }}", - "haiku-skills >= 0.10.0", + "haiku-skills >= 0.11.0", ] [project.entry-points."haiku.skills"] diff --git a/haiku_rag_slim/haiku/rag/skills/rag.py b/haiku_rag_slim/haiku/rag/skills/rag.py index da81680d..10270e2a 100644 --- a/haiku_rag_slim/haiku/rag/skills/rag.py +++ b/haiku_rag_slim/haiku/rag/skills/rag.py @@ -1,11 +1,11 @@ import os from functools import cache from pathlib import Path -from typing import Any from pydantic import BaseModel, Field from haiku.rag.agents.research.models import Citation +from haiku.rag.config.models import AppConfig from haiku.rag.skills._tools import ResearchEntry from haiku.rag.store.models.chunk import SearchResult from haiku.rag.tools.document import DocumentInfo @@ -61,7 +61,7 @@ def state_metadata() -> StateMetadata: def create_skill( db_path: Path | None = None, - config: Any = None, + config: AppConfig | None = None, ) -> Skill: """Create a RAG skill for searching and analyzing documents. diff --git a/haiku_rag_slim/haiku/rag/skills/rlm.py b/haiku_rag_slim/haiku/rag/skills/rlm.py index 463e524f..7b48bbad 100644 --- a/haiku_rag_slim/haiku/rag/skills/rlm.py +++ b/haiku_rag_slim/haiku/rag/skills/rlm.py @@ -1,10 +1,10 @@ import os from functools import cache from pathlib import Path -from typing import Any from pydantic import BaseModel +from haiku.rag.config.models import AppConfig from haiku.rag.skills._tools import AnalysisEntry from haiku.skills.models import Skill, SkillMetadata, SkillSource, StateMetadata from haiku.skills.parser import parse_skill_md @@ -42,7 +42,7 @@ def state_metadata() -> StateMetadata: def create_skill( db_path: Path | None = None, - config: Any = None, + config: AppConfig | None = None, ) -> Skill: """Create an RLM analysis skill for computational document analysis. diff --git a/haiku_rag_slim/pyproject.toml b/haiku_rag_slim/pyproject.toml index 3355972b..ba5f6052 100644 --- a/haiku_rag_slim/pyproject.toml +++ b/haiku_rag_slim/pyproject.toml @@ -24,7 +24,7 @@ classifiers = [ dependencies = [ "cachetools>=7.0.2", "docling-core>=2.70.2", - "haiku.skills>=0.10.0", + "haiku.skills>=0.11.0", "httpx>=0.28.1", "jinja2>=3.1.0", "jsonpatch>=1.33", diff --git a/tests/test_skill_generator.py b/tests/test_skill_generator.py index 37f3d06c..9025f84e 100644 --- a/tests/test_skill_generator.py +++ b/tests/test_skill_generator.py @@ -142,9 +142,7 @@ class TestRenderTemplates: ) init = tmp_path / "docs-skill" / "docs_skill" / "__init__.py" content = init.read_text() - assert ( - "create_skill_tools(_DB_PATH, config, SkillState, _TOOL_NAMES)" in content - ) + assert "create_skill_tools(db_path, config, SkillState, _TOOL_NAMES)" in content def test_tool_names_in_init(self, tmp_path): render_templates( @@ -273,6 +271,18 @@ class TestRenderTemplates: assert "skill_visualize_chunk" not in content assert "HaikuRAG" in content + def test_create_skill_accepts_optional_params(self, tmp_path): + render_templates( + output_dir=tmp_path, + name="docs", + description="A docs skill.", + tool_names=["search"], + ) + init = tmp_path / "docs-skill" / "docs_skill" / "__init__.py" + content = init.read_text() + assert "db_path: Path | None = None" in content + assert "config: AppConfig | None = None" in content + def test_generated_python_is_valid(self, tmp_path): render_templates( output_dir=tmp_path, diff --git a/uv.lock b/uv.lock index f2b686c2..a2d71aab 100644 --- a/uv.lock +++ b/uv.lock @@ -318,6 +318,7 @@ dependencies = [ { name = "jmespath" }, { name = "s3transfer" }, ] +sdist = { url = "https://files.pythonhosted.org/packages/74/ec/636ab2aa7ad9e6bf6e297240ac2d44dba63cc6611e2d5038db318436d449/boto3-1.42.74.tar.gz", hash = "sha256:dbacd808cf2a3dadbf35f3dbd8de97b94dc9f78b1ebd439f38f552e0f9753577", size = 112739, upload-time = "2026-03-23T19:34:09.815Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ad/16/a264b4da2af99f4a12609b93fea941cce5ec41da14b33ed3fef77a910f0c/boto3-1.42.74-py3-none-any.whl", hash = "sha256:4bf89c044d618fe4435af854ab820f09dd43569c0df15d7beb0398f50b9aa970", size = 140557, upload-time = "2026-03-23T19:34:07.084Z" }, ] @@ -1570,7 +1571,7 @@ requires-dist = [ { name = "cohere", marker = "extra == 'cohere'", specifier = ">=5.20.7" }, { name = "docling", marker = "extra == 'docling'", specifier = ">=2.81.0" }, { name = "docling-core", specifier = ">=2.70.2" }, - { name = "haiku-skills", specifier = ">=0.10.0" }, + { name = "haiku-skills", specifier = ">=0.11.0" }, { name = "httpx", specifier = ">=0.28.1" }, { name = "jinja2", specifier = ">=3.1.0" }, { name = "jsonpatch", specifier = ">=1.33" }, @@ -1603,7 +1604,7 @@ provides-extras = ["docling", "voyageai", "mxbai", "cohere", "zeroentropy", "jin [[package]] name = "haiku-skills" -version = "0.10.0" +version = "0.11.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "ag-ui-protocol" }, @@ -1613,9 +1614,9 @@ dependencies = [ { name = "pyyaml" }, { name = "skills-ref" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7a/f2/97cd4c9561c402f81b118051553a808daa173f945b72ff37781ba86aaed7/haiku_skills-0.10.0.tar.gz", hash = "sha256:f7933b729088faeaa0afcae00d301b28bbdb24092f8731dfd68410b94f47b769", size = 166398, upload-time = "2026-03-24T11:17:54.608Z" } +sdist = { url = "https://files.pythonhosted.org/packages/da/a7/4f8483ee3c8789cf5a2882c82545c93787cff343b78bb5a3da25f43f2bbf/haiku_skills-0.11.0.tar.gz", hash = "sha256:bb9117a3c1636ddafa4a4dda7abaed79da83c409c4428136393de0365ab4fa52", size = 166785, upload-time = "2026-03-26T11:44:38.651Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/0b/f2de3b43e53ccc567cde4287674c123a7f92e30862c541bcf28393e30a93/haiku_skills-0.10.0-py3-none-any.whl", hash = "sha256:5ff13d0a69bf6eecf6d6b15fbbed1176406109c626ef2e386bca4766e58b7557", size = 29445, upload-time = "2026-03-24T11:17:53.692Z" }, + { url = "https://files.pythonhosted.org/packages/7a/4a/3578dbbf251ec94b894163d4859c1dcdc271d5972fec2376c1a73978d45f/haiku_skills-0.11.0-py3-none-any.whl", hash = "sha256:19c76532c6228c7abb60f06cb666a023d67b9809dd2ef8597aa0347c471a4695", size = 29664, upload-time = "2026-03-26T11:44:37.479Z" }, ] [[package]]