Source code for veupath_chatbot.ai.tools.planner.artifact_tools

"""Tools for planning artifacts, conversation titles, and reasoning.

Provides :class:`ArtifactToolsMixin` with tools for saving planning
artifacts, setting conversation titles, and reporting reasoning.
"""

from typing import Annotated, cast

from kani import AIParam, ai_function

from veupath_chatbot.platform.types import JSONArray, JSONObject


[docs] class ArtifactToolsMixin: """Kani tool mixin for planning artifact management."""
[docs] @ai_function() async def save_planning_artifact( self, title: Annotated[str, AIParam(desc="Short title for the plan")], summary_markdown: Annotated[ str, AIParam(desc="Main planning output in markdown (actionable, structured)"), ], assumptions: Annotated[ list[str] | None, AIParam(desc="Optional list of assumptions/constraints") ] = None, parameters: Annotated[ JSONObject | None, AIParam(desc="Chosen/considered parameters (free-form JSON)"), ] = None, proposed_strategy_plan: Annotated[ JSONObject | None, AIParam( desc=( "Optional proposed strategy plan payload that can be " "applied during execution." ) ), ] = None, ) -> JSONObject: """Publish a reusable planning artifact (persisted to the conversation).""" from datetime import UTC, datetime from uuid import uuid4 artifact: JSONObject = { "id": f"plan_{uuid4().hex[:12]}", "title": (title or "").strip() or "New Conversation", "summaryMarkdown": summary_markdown or "", "assumptions": cast(JSONArray, assumptions or []), "parameters": cast(JSONObject, parameters or {}), "proposedStrategyPlan": proposed_strategy_plan, "createdAt": datetime.now(UTC).isoformat(), } return {"planningArtifact": artifact}
[docs] @ai_function() async def set_conversation_title( self, title: Annotated[str, AIParam(desc="Short conversation title")], ) -> JSONObject: """Update the conversation title.""" t = (title or "").strip() if not t: return {"error": "title_required"} return {"conversationTitle": t}
[docs] @ai_function() async def report_reasoning( self, reasoning: Annotated[ str, AIParam(desc="Model reasoning text to show in Thinking tab") ], ) -> JSONObject: """Publish reasoning text to the Thinking tab.""" r = (reasoning or "").strip() if not r: return {"error": "reasoning_required"} return {"reasoning": r}