Skip to content

Changelog

All notable changes to this project will be documented here.


[0.7.3] — 2026-08-10

✨ Added

  • Variable Names Introspection: PromptNode.variable_names returns the sorted names of a prompt's variables, and PromptNamespace.variable_names returns the union of variable names across every prompt in a namespace (including nested sub-namespaces). Makes it easy to discover what variables a prompt or a whole folder of prompts expects.

[0.7.2] — 2026-08-10

🐛 Fixed

  • Dotted Filename Namespaces: Markdown files whose names contain dots (e.g. main.sub_agents_instructions.md) are no longer mangled into underscores (main_sub_agents_instructions). Dotted filenames now express namespaces exactly like dotted TOML headers, so dp.main.sub_agents_instructions works and auto_export round-trips without producing duplicate mangled prompts.

[0.7.0] — 2026-08-10

🐛 Fixed

  • Nested TOML Namespaces: A single nested TOML prompt (e.g. [default.main.system_prompt]) loaded from a directory is no longer renamed to the file stem — the main.system_prompt namespace is preserved.

🔧 Changed

  • Examples Updated: examples/run_all.py now references the actual gemini/analyzer.md path and renders with the AnalysisSchema dictionary.

[0.6.0] — 2026-08-01

✨ Added

  • Inner Folder Prompt Resolution: Prompts in nested folders (e.g. gemini/analyzer.md) are now accessible as namespaces (prompts.gemini.analyzer) and can be referenced from within other prompts using the namespace-prefixed name.
  • Unusual Variable Name Rendering: Non-identifier variable names (e.g. app:access_policy, hello world) in templates now render correctly. Invalid or unusual Jinja tags are preserved as-is instead of raising a syntax error.

🐛 Fixed

  • Caller File Exclusion: The frame-skipping logic used to prevent self-loading/infinite loops was simplified to check the whole dynaprompt package directory instead of a fixed internal-file list.

[0.5.0] — 2026-07-18

✨ Added

  • Automatic Cache Cleanup: DynaPrompt now tracks every __pycache__ directory created when loading external .py schema/variable files via importlib. These are removed automatically when cleanup() is called.
  • .dynaprompt Folder Cleanup: Any .dynaprompt directory found inside a scanned settings root is removed during cleanup, preventing stale artefacts from accumulating across runs.
  • cleanup() Method: Explicit cleanup API — call prompts.cleanup() at any point to remove all ephemeral cache directories created since the last load.
  • Context-Manager Support: DynaPrompt now implements __enter__ / __exit__, so cleanup runs automatically when used as a context manager:
    with DynaPrompt(settings_files=["prompts/"]) as p:
        result = p.my_prompt.render()
    # __pycache__ and .dynaprompt dirs deleted here
    
  • reload() now cleans up first: Calling reload() triggers cleanup() before resetting the internal state, ensuring no stale cache directories linger between reloads.

[0.4.0] — 2026-05-22

✨ Added

  • Nested Prompt Support: Prompts can now be included inside other prompts using the {{prompt_name}} syntax.
  • Recursion Protection: Implemented a render stack to prevent circular references between prompts (e.g., A includes B, B includes A). Detected loops are replaced with a safe warning message instead of a RecursionError.
  • Enhanced Variable Registry: The directory scanner now skips internal and hidden directories (like .venv, .git, __pycache__) by default to prevent self-loading or ImportError.

🐛 Fixed

  • Synchronous Rendering Compatibility: Fixed a bug where enable_async=True in Jinja2 was causing synchronous render() calls to return coroutines instead of text. Sync and Async rendering now utilize separate pre-compiled templates.
  • Auto-Render Lifecycle: Refactored auto_render to use a "silent" internal render. This ensures variables and schemas are rendered during initialization without triggering lifecycle hooks twice.
  • Schema Context Injection: Global schemas (from shared .py or .json files) are now automatically injected into all prompt contexts, including nested prompts.

[0.3.6] — 2026-05-11

✨ Added

  • Dot-Notation Variables: Variables in PromptNode can now be accessed directly using dot notation (e.g., node.variables.MyVariable).
  • Pydantic Auto-Detection: DynaPrompt now automatically detects if a Pydantic schema is passed in the variables and referenced in the template. If so, it automatically assigns it as the response_schema for the prompt, eliminating the need to explicitly define it in the markdown frontmatter in most cases.

[0.3.5] — 2026-05-11

🐛 Fixed

  • Python Variable Stability: Fixed a crash (TypeError: cannot pickle 'module' object) when loading Python files that contain standard imports (e.g. import math). Modules are now automatically excluded from the variable registry.

[0.3.4] — 2026-05-11

✨ Added

  • template Property Alias: PromptNode now supports .template as a more intuitive alias for the raw .text attribute.

🐛 Fixed

  • Auto-Render Locking: Fixed a regression where enabling auto_render would "lock" the template and prevent subsequent overrides in .render() calls.

[0.3.3] — 2026-05-11

🐛 Fixed

  • Infinite Loop Protection: Automatically detects and excludes the caller script from the scanning process, preventing infinite recursion when using . as a settings directory.
  • Python Module Loading: Directory scanning now automatically skips __init__.py files to avoid relative import errors in package-style prompt directories.

✨ Added

  • Introspection Methods: keys(), __iter__, and .prompts property on DynaPrompt for easier exploration of loaded prompts.

[0.3.0] — 2026-05-10

✨ Added

  • Async Rendering: async_render() and async_rerender() on PromptNode for non-blocking I/O in FastAPI and async agents.
  • Async Hooks: @async_hookable decorator for asynchronous lifecycle hooks.
  • Prompt Hashing: Every RenderedPrompt now includes a prompt_hash (SHA-256) for audit logs and LangSmith observability.
  • Debug Trace: prompts.debug_trace("key") to visualize the full merge hierarchy and identify which environment/file provided specific values.
  • Python Variable Templates: Templates can be extracted from Python files using the template = "file.py:variable" syntax.

🐛 Fixed

  • Dotted TOML Headers: Nested TOML headers like [default.gemini.analyzer] were parsed as nested dicts instead of flat prompt namespaces.
  • Missing File Alerts: Explicit UserWarning when a requested settings file doesn't exist.

📝 Changed

  • README Overhaul: Completely redesigned with side-by-side "before/after" comparisons, YAML frontmatter guides, and advanced examples.
  • Jinja2 Environment: Enabled enable_async=True globally for transparent sync/async rendering.

[0.2.0] — 2026-05-08

✨ Added

  • structure_mode Parameter: Enables building nested namespaces from directory structures (e.g., prompts.folder.file). Defaults to True.
  • auto_export Visibility: Improved documentation for the auto_export feature which mirrors the prompt tree to pyprompts.toml.
  • Enhanced Metadata: Expanded PyPI keywords and Trove classifiers for better discoverability.

📝 Changed

  • auto_render Default: Now True by default. Variables within templates are automatically rendered during initialization.
  • Modernized Test Suite: Refactored legacy test scripts into a clean pytest suite using tmp_path fixtures.

🐛 Fixed

  • CI Workflow: Fixed an "Invalid action input" error in GitHub Actions by updating Codecov to v5.

[0.1.3] — 2026-05-04

  • 🎉 Initial public release with lazy-loading, environment support, and Pydantic schema integration.