pylogue 0.2.0__tar.gz → 0.3__tar.gz

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.
Files changed (26) hide show
  1. {pylogue-0.2.0 → pylogue-0.3}/PKG-INFO +1 -1
  2. {pylogue-0.2.0 → pylogue-0.3}/README.md +6 -4
  3. {pylogue-0.2.0 → pylogue-0.3}/pyproject.toml +1 -1
  4. {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/__init__.py +2 -0
  5. {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/_modidx.py +1 -0
  6. {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/cards.py +27 -10
  7. {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/chatapp.py +15 -9
  8. {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/renderer.py +12 -1
  9. {pylogue-0.2.0 → pylogue-0.3}/src/pylogue.egg-info/PKG-INFO +1 -1
  10. {pylogue-0.2.0 → pylogue-0.3}/AUTHORS.md +0 -0
  11. {pylogue-0.2.0 → pylogue-0.3}/CONTRIBUTING.md +0 -0
  12. {pylogue-0.2.0 → pylogue-0.3}/LICENSE +0 -0
  13. {pylogue-0.2.0 → pylogue-0.3}/MANIFEST.in +0 -0
  14. {pylogue-0.2.0 → pylogue-0.3}/setup.cfg +0 -0
  15. {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/__pre_init__.py +0 -0
  16. {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/chat.py +0 -0
  17. {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/health.py +0 -0
  18. {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/service.py +0 -0
  19. {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/session.py +0 -0
  20. {pylogue-0.2.0 → pylogue-0.3}/src/pylogue.egg-info/SOURCES.txt +0 -0
  21. {pylogue-0.2.0 → pylogue-0.3}/src/pylogue.egg-info/dependency_links.txt +0 -0
  22. {pylogue-0.2.0 → pylogue-0.3}/src/pylogue.egg-info/entry_points.txt +0 -0
  23. {pylogue-0.2.0 → pylogue-0.3}/src/pylogue.egg-info/requires.txt +0 -0
  24. {pylogue-0.2.0 → pylogue-0.3}/src/pylogue.egg-info/top_level.txt +0 -0
  25. {pylogue-0.2.0 → pylogue-0.3}/tests/__init__.py +0 -0
  26. {pylogue-0.2.0 → pylogue-0.3}/tests/test_pylogue.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pylogue
3
- Version: 0.2.0
3
+ Version: 0.3
4
4
  Summary: A Chatbot UI built for AI agents
5
5
  Author-email: Yeshwanth Reddy <yyeshr@gmail.com>
6
6
  Maintainer-email: Yeshwanth Reddy <yyeshr@gmail.com>
@@ -20,7 +20,7 @@ app.run(port=5001)
20
20
  ### Custom Styling
21
21
 
22
22
  ``` python
23
- from pylogue.cards import ChatCard
23
+ from pylogue.card import ChatCard
24
24
  from pylogue.chatapp import create_default_chat_app, ChatAppConfig
25
25
 
26
26
  card = ChatCard(
@@ -51,7 +51,7 @@ from pylogue.chatapp import ChatApp, ChatAppConfig
51
51
  from pylogue.session import InMemorySessionManager
52
52
  from pylogue.service import ChatService
53
53
  from pylogue.renderer import ChatRenderer
54
- from pylogue.cards import ChatCard
54
+ from pylogue.card import ChatCard
55
55
 
56
56
  # 1. Configure components
57
57
  session_manager = InMemorySessionManager()
@@ -162,7 +162,7 @@ html = renderer.render_messages(messages)
162
162
 
163
163
  ## 📚 Examples
164
164
 
165
- See `5-Examples.ipynb` for complete working examples:
165
+ See `6-Examples.ipynb` for complete working examples:
166
166
 
167
167
  1. **Echo Bot** - Simplest possible implementation
168
168
  2. **Custom Styled Chat** - UI/UX customization
@@ -250,10 +250,12 @@ app = create_default_chat_app(responder=your_responder)
250
250
  - `3-Renderer.ipynb` - Explore presentation layer
251
251
  - `4-ChatApp.ipynb` - See full integration
252
252
  - `5-Examples.ipynb` - Working examples
253
+ - `6-JupyterExample.ipynb` - Jupyter integration
253
254
 
254
255
  2. Try the examples in `5-Examples.ipynb`
255
256
 
256
- 3. Build your own custom responder
257
+ 3. Build your own custom responder and test it out in
258
+ `6-JupyterExample.ipynb`
257
259
 
258
260
  4. Deploy to production with your preferred hosting
259
261
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pylogue"
7
- version = "0.2.0"
7
+ version = "0.3"
8
8
  description = "A Chatbot UI built for AI agents"
9
9
  readme = "README.rst"
10
10
  authors = [
@@ -14,3 +14,5 @@ __version__ = "0.1.0"
14
14
 
15
15
  from .__pre_init__ import cli
16
16
  from .health import *
17
+
18
+ from .chatapp import create_default_chat_app
@@ -11,6 +11,7 @@ d = { 'settings': { 'branch': 'main',
11
11
  'pylogue.cards.ChatCard._get_role_style': ('0-card.html#chatcard._get_role_style', 'pylogue/cards.py'),
12
12
  'pylogue.cards.ChatCard._get_style': ('0-card.html#chatcard._get_style', 'pylogue/cards.py'),
13
13
  'pylogue.cards.ChatCard._get_text_color': ('0-card.html#chatcard._get_text_color', 'pylogue/cards.py'),
14
+ 'pylogue.cards.ChatCard.get_mobile_styles': ('0-card.html#chatcard.get_mobile_styles', 'pylogue/cards.py'),
14
15
  'pylogue.cards.ChatCard.render': ('0-card.html#chatcard.render', 'pylogue/cards.py'),
15
16
  'pylogue.cards.mk_inp': ('0-card.html#mk_inp', 'pylogue/cards.py'),
16
17
  'pylogue.cards.render_chat_list': ('0-card.html#render_chat_list', 'pylogue/cards.py')},
@@ -14,18 +14,19 @@ class ChatCard:
14
14
  assistant_color: str = "#004539",
15
15
  user_emoji: str = "🗣️",
16
16
  assistant_emoji: str = "🕵️‍♂️",
17
- width: str = "60%",
17
+ max_width: str = "80%",
18
+ card_max_width: str = "60%",
18
19
  font_size: str = "1.5em",
20
+ mobile_font_size: str = "16px",
19
21
  padding: str = "1.25em",
20
- border_radius: str = "1em",
21
22
  user_align: str = "right",
22
23
  assistant_align: str = "left",
23
- user_self_align: str = "center",
24
- assistant_self_align: str = "center",
24
+ user_self_align: str = "flex-end",
25
+ assistant_self_align: str = "flex-start",
25
26
  role_font_weight: str = "bold",
26
27
  role_font_size: str = "1.1em",
27
28
  role_margin_bottom: str = "8px",
28
- content_white_space: str = "pre-wrap",
29
+ content_white_space: str = "normal",
29
30
  spinner_class: str = "spinner",
30
31
  ):
31
32
  self.colors = {
@@ -40,11 +41,14 @@ class ChatCard:
40
41
  "Assistant": {"text": assistant_align, "self": assistant_self_align},
41
42
  }
42
43
 
44
+ self.border_radii = {"User": "1em 1em 0em 1em", "Assistant": "1em 1em 1em 0em"}
45
+
43
46
  # Style configuration
44
- self.width = width
47
+ self.card_max_width = card_max_width
48
+ self.max_width = max_width
45
49
  self.font_size = font_size
50
+ self.mobile_font_size = mobile_font_size
46
51
  self.padding = padding
47
- self.border_radius = border_radius
48
52
  self.role_font_weight = role_font_weight
49
53
  self.role_font_size = role_font_size
50
54
  self.role_margin_bottom = role_margin_bottom
@@ -54,8 +58,8 @@ class ChatCard:
54
58
  # Build style template
55
59
  self.style_template = f"""
56
60
  background: {{bg}}; color: {{text_color}}; padding: 10px; font-size: {self.font_size};
57
- width: {self.width}; align-self: {{self_align}};
58
- text-align: {{text_align}}; border-radius: {self.border_radius};
61
+ max-width: min({self.card_max_width}, {self.max_width}); align-self: {{self_align}};
62
+ text-align: {{text_align}}; border-radius: {{border_radius}};
59
63
  padding: {self.padding}"""
60
64
 
61
65
  def _get_text_color(self, bg_color: str) -> str:
@@ -89,12 +93,23 @@ class ChatCard:
89
93
  text_color=self._get_text_color(bg_color),
90
94
  self_align=self.alignments[role]["self"],
91
95
  text_align=self.alignments[role]["text"],
96
+ border_radius=self.border_radii[role],
92
97
  )
93
98
 
94
99
  def _get_role_style(self) -> str:
95
100
  """Generate CSS style string for role labels."""
96
101
  return f"font-weight: {self.role_font_weight}; font-size: {self.role_font_size}; display: block; margin-bottom: {self.role_margin_bottom};"
97
102
 
103
+ def get_mobile_styles(self) -> str:
104
+ """Generate CSS media query for mobile devices."""
105
+ return f"""
106
+ @media (max-width: 768px) {{
107
+ .chat-card {{
108
+ font-size: {self.mobile_font_size} !important;
109
+ }}
110
+ }}
111
+ """
112
+
98
113
  def render(self, data: dict):
99
114
  """
100
115
  Render a chat card with the given data.
@@ -117,7 +132,7 @@ class ChatCard:
117
132
 
118
133
  if pending:
119
134
  spinner = Span(cls=self.spinner_class)
120
- return Div(f"{emoji} {role}: ", spinner, style=style)
135
+ return Div(f"{emoji} {role}: ", spinner, style=style, cls="chat-card")
121
136
 
122
137
  # Add 'marked' class to enable markdown rendering
123
138
  return Div(
@@ -129,6 +144,7 @@ class ChatCard:
129
144
  content, cls="marked", style=f"white-space: {self.content_white_space};"
130
145
  ),
131
146
  style=style,
147
+ cls="chat-card",
132
148
  )
133
149
 
134
150
  def __call__(self, data: dict):
@@ -141,6 +157,7 @@ CHAT_DIV_ID = "chat-cards"
141
157
 
142
158
  def render_chat_list(messages: List[Dict[str, str]], ChatCard: ChatCard):
143
159
  return Div(
160
+ Style(ChatCard.get_mobile_styles()),
144
161
  *[ChatCard(m) for m in messages],
145
162
  id=CHAT_DIV_ID,
146
163
  cls="chat-cards",
@@ -34,6 +34,7 @@ class ChatAppConfig:
34
34
 
35
35
  # WebSocket settings
36
36
  ws_endpoint: str = "/ws"
37
+ chat_endpoint: str = "/chat"
37
38
 
38
39
  # FastHTML extensions and headers
39
40
  markdown_enabled: bool = True
@@ -120,6 +121,9 @@ class ChatApp:
120
121
  # Add spinner styles
121
122
  headers.append(Style(self.config.get_spinner_style()))
122
123
 
124
+ # Add mobile responsive styles from ChatCard
125
+ headers.append(Style(self.renderer.card.get_mobile_styles()))
126
+
123
127
  return FastHTML(exts="ws", hdrs=tuple(headers))
124
128
 
125
129
  def _get_initial_messages(self) -> List[Message]:
@@ -131,23 +135,25 @@ class ChatApp:
131
135
  def _register_routes(self):
132
136
  """Register HTTP and WebSocket routes."""
133
137
 
134
- @self.app.route("/")
135
- def home():
138
+ @self.app.route(self.config.chat_endpoint)
139
+ def chat():
136
140
  """Main chat interface."""
137
141
  initial_messages = self._get_initial_messages()
138
142
 
139
143
  container_style = self.config.container_style or (
140
144
  f"font-family: monospace, sans-serif; margin: 0; padding: 0; "
141
- f"background: {self.config.bg_color}; min-height: 100vh;"
142
145
  )
143
146
 
144
147
  return (
145
148
  Title(self.config.page_title),
146
- Div(
147
- H1(self.config.app_title, style=self.config.header_style),
148
- self.renderer.render_messages(initial_messages),
149
- self.renderer.render_form(),
150
- style=container_style,
149
+ Body(
150
+ Div(
151
+ H1(self.config.app_title, style=self.config.header_style),
152
+ self.renderer.render_messages(initial_messages),
153
+ self.renderer.render_form(),
154
+ style=container_style,
155
+ ),
156
+ style="background-color: #000",
151
157
  ),
152
158
  )
153
159
 
@@ -210,7 +216,7 @@ class ChatApp:
210
216
  assistant_msg.id, content=full_response, pending=False
211
217
  )
212
218
  # Send updated message list to UI
213
- print(f"📤 Sending chunk #{chunk_count}: {repr(chunk)}") # Debug
219
+ # print(f"📤 Sending chunk #{chunk_count}: {repr(chunk)}") # Debug
214
220
  await send(self.renderer.render_messages(session.get_messages()))
215
221
 
216
222
  except Exception as e:
@@ -41,7 +41,7 @@ class ChatRenderer:
41
41
  "font-size: 1em; border-radius: 0.5em"
42
42
  )
43
43
  self.chat_container_style = chat_container_style or (
44
- "display: flex; flex-direction: column; gap: 10px;"
44
+ "display: flex; flex-direction: column; gap: 1em; margin: 3em;"
45
45
  )
46
46
 
47
47
  def render_message(self, message: Message) -> Any:
@@ -58,7 +58,18 @@ class ChatRenderer:
58
58
  Returns:
59
59
  FastHTML Div containing all rendered messages
60
60
  """
61
+ # Add mobile-responsive margin CSS
62
+ mobile_margin_css = """
63
+ @media (max-width: 768px) {
64
+ .chat-cards {
65
+ margin: 1em !important;
66
+ }
67
+ }
68
+ """
69
+
61
70
  return Div(
71
+ Style(self.card.get_mobile_styles()),
72
+ Style(mobile_margin_css),
62
73
  *[self.render_message(msg) for msg in messages],
63
74
  id=self.CHAT_DIV_ID,
64
75
  cls="chat-cards",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pylogue
3
- Version: 0.2.0
3
+ Version: 0.3
4
4
  Summary: A Chatbot UI built for AI agents
5
5
  Author-email: Yeshwanth Reddy <yyeshr@gmail.com>
6
6
  Maintainer-email: Yeshwanth Reddy <yyeshr@gmail.com>
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes