vyasa 0.3.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vyasa/__init__.py +5 -0
- vyasa/agent.py +116 -0
- vyasa/build.py +660 -0
- vyasa/config.py +224 -0
- vyasa/core.py +2825 -0
- vyasa/helpers.py +349 -0
- vyasa/layout_helpers.py +40 -0
- vyasa/main.py +108 -0
- vyasa/static/scripts.js +1202 -0
- vyasa/static/sidenote.css +21 -0
- vyasa-0.3.6.dist-info/METADATA +227 -0
- vyasa-0.3.6.dist-info/RECORD +16 -0
- vyasa-0.3.6.dist-info/WHEEL +5 -0
- vyasa-0.3.6.dist-info/entry_points.txt +2 -0
- vyasa-0.3.6.dist-info/licenses/LICENSE +201 -0
- vyasa-0.3.6.dist-info/top_level.txt +1 -0
vyasa/__init__.py
ADDED
vyasa/agent.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# fasthtml solveit
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import re
|
|
5
|
+
from urllib.parse import quote
|
|
6
|
+
from pydantic_ai import Agent, RunContext
|
|
7
|
+
from .config import get_config
|
|
8
|
+
from .helpers import list_vyasa_entries
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
from dotenv import load_dotenv
|
|
12
|
+
|
|
13
|
+
load_dotenv(override=True)
|
|
14
|
+
except Exception:
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
import logfire
|
|
19
|
+
|
|
20
|
+
logfire.configure(
|
|
21
|
+
environment="development",
|
|
22
|
+
service_name="vyasa",
|
|
23
|
+
)
|
|
24
|
+
logfire.instrument_pydantic_ai()
|
|
25
|
+
except Exception:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class VyasaDeps:
|
|
31
|
+
root: Path
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
system_prompt = """
|
|
35
|
+
You talk only as much as needed and not a word more.
|
|
36
|
+
|
|
37
|
+
You are a helpful AI assistant that helps people find answers from a blog.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
vyasa_agent = Agent(
|
|
41
|
+
"openai:gpt-5-mini",
|
|
42
|
+
deps_type=VyasaDeps,
|
|
43
|
+
system_prompt=system_prompt,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@vyasa_agent.tool
|
|
48
|
+
def list_vyasa_posts_tool(
|
|
49
|
+
ctx: RunContext[VyasaDeps],
|
|
50
|
+
path: str = ".",
|
|
51
|
+
include_hidden: bool = False,
|
|
52
|
+
) -> dict:
|
|
53
|
+
"""List immediate folders and posts under a path (Use this tool for progressive disclosure)."""
|
|
54
|
+
return list_vyasa_entries(ctx.deps.root, relative=path, include_hidden=include_hidden)
|
|
55
|
+
|
|
56
|
+
@vyasa_agent.tool
|
|
57
|
+
def get_vyasa_post_content_tool(
|
|
58
|
+
ctx: RunContext[VyasaDeps],
|
|
59
|
+
relative_path: str,
|
|
60
|
+
) -> str:
|
|
61
|
+
"""Get the content of a blog post given its relative path from the blog root.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
relative_path: Relative path to the blog post from the blog root.
|
|
65
|
+
"""
|
|
66
|
+
root = ctx.deps.root.resolve()
|
|
67
|
+
post_path = (root / relative_path).resolve()
|
|
68
|
+
try:
|
|
69
|
+
if not post_path.is_file() or not str(post_path).startswith(str(root)):
|
|
70
|
+
return "Error: Invalid post path."
|
|
71
|
+
|
|
72
|
+
with open(post_path, "r", encoding="utf-8") as f:
|
|
73
|
+
content = f.read()
|
|
74
|
+
return content
|
|
75
|
+
except Exception as e:
|
|
76
|
+
return f"Error: Could not read post content. Error: {e}"
|
|
77
|
+
|
|
78
|
+
class PydanticAIStreamingResponder:
|
|
79
|
+
"""Streaming responder using Pydantic AI's run_stream."""
|
|
80
|
+
|
|
81
|
+
def __init__(self, agent=None, agent_deps=None):
|
|
82
|
+
self.agent = agent if agent is not None else vyasa_agent
|
|
83
|
+
if agent_deps is None:
|
|
84
|
+
config = get_config()
|
|
85
|
+
agent_deps = VyasaDeps(root=config.get_root_folder())
|
|
86
|
+
self.agent_deps = agent_deps
|
|
87
|
+
self.message_history = None
|
|
88
|
+
|
|
89
|
+
async def __call__(self, text: str, context=None):
|
|
90
|
+
import asyncio
|
|
91
|
+
|
|
92
|
+
if self.agent is None:
|
|
93
|
+
self.agent = vyasa_agent
|
|
94
|
+
if self.agent is None:
|
|
95
|
+
raise RuntimeError("PydanticAI agent is not initialized")
|
|
96
|
+
|
|
97
|
+
async with self.agent.run_stream(
|
|
98
|
+
text,
|
|
99
|
+
message_history=self.message_history,
|
|
100
|
+
deps=self.agent_deps,
|
|
101
|
+
) as response:
|
|
102
|
+
async for token in response.stream_text(delta=True):
|
|
103
|
+
yield token
|
|
104
|
+
await asyncio.sleep(0)
|
|
105
|
+
|
|
106
|
+
self.message_history = response.all_messages()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def app_factory():
|
|
110
|
+
responder = PydanticAIStreamingResponder(agent=vyasa_agent)
|
|
111
|
+
return create_core_app(
|
|
112
|
+
responder=responder,
|
|
113
|
+
tag_line="PYDANTIC AI",
|
|
114
|
+
title="Pydantic AI Chat",
|
|
115
|
+
subtitle="Streaming tokens from PydanticAI over WebSockets.",
|
|
116
|
+
)
|