-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Expand file tree
/
Copy pathai_builder.py
More file actions
192 lines (170 loc) ยท 7.24 KB
/
Copy pathai_builder.py
File metadata and controls
192 lines (170 loc) ยท 7.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
import os
import frontmatter
import reflex as rx
import reflex_components_internal as ui
from reflex_site_shared.components.marquee import marquee
from reflex_site_shared.constants import REFLEX_ASSETS_CDN
from reflex_site_shared.integrations import get_integration_logo_url
from reflex_docs.pages.docs import ai_builder as ai_builder_pages
def get_integration_path() -> list:
from integrations_docs import DOCS_DIR
base_dir = str(DOCS_DIR)
web_path_prefix = "/ai/integrations"
result = []
exclude_files = [
"mcp_installation",
"mcp_overview",
"overview",
"skills",
"snowflake",
] # without .md extension
for filename in os.listdir(base_dir):
if filename.endswith(".md"):
name_without_ext = filename[:-3]
if name_without_ext in exclude_files:
continue
key = name_without_ext.lower()
slug = key.replace("_", "-")
file_path = os.path.join(base_dir, filename)
with open(file_path, "r", encoding="utf-8") as f:
post = frontmatter.load(f)
# Handle tags as a string (get first tag, or empty)
raw_tags = post.get("tags", [])
if isinstance(raw_tags, list) and raw_tags:
tag = raw_tags[0]
elif isinstance(raw_tags, str):
tag = raw_tags
else:
tag = ""
description = post.get("description", "").strip()
title = key.replace("_", " ").title()
if title == "Open Ai":
title = "Open AI"
result.append({
key: {
"path": f"{web_path_prefix}/{slug}",
"tags": tag,
"description": description,
"name": key,
"title": title,
}
})
return result
def card(
title: str, description: str, content: str, href: str, enteprise_only: bool = False
) -> rx.Component:
return rx.el.div(
rx.el.span(
"Enterprise-only",
class_name="text-secondary-12 text-xs font-medium bg-secondary-1 px-2.5 h-7 absolute top-0 right-0 border-b border-l rounded-bl-lg border-secondary-4 flex justify-center items-center",
)
if enteprise_only
else None,
rx.el.div(
rx.el.span(
title,
class_name="text-secondary-12 text-xl font-[575]",
),
rx.el.span(
description,
class_name="text-secondary-11 text-sm font-[475]",
),
class_name="flex flex-col gap-2 p-8",
),
content,
rx.el.a(href=href, aria_label=title, class_name="absolute inset-0"),
class_name="flex flex-col bg-secondary-1/96 backdrop-blur-[16px] rounded-xl relative cursor-pointer transition-colors overflow-hidden shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_12px_24px_0_rgba(0,0,0,0.08),0_1px_1px_0_rgba(0,0,0,0.01),0_4px_8px_0_rgba(0,0,0,0.03)] dark:shadow-none dark:border dark:border-secondary-4",
)
def integration_icon_marquee(integration_name: str) -> rx.Component:
return ui.avatar.root(
ui.avatar.image(
src=rx.color_mode_cond(
get_integration_logo_url(integration_name, "light"),
get_integration_logo_url(integration_name, "dark"),
),
alt=f"{integration_name} logo",
unstyled=True,
class_name="size-full",
),
ui.avatar.fallback(
integration_name[0],
class_name="text-secondary-12 text-base font-semibold uppercase size-full",
unstyled=True,
),
unstyled=True,
class_name="size-6.5 flex items-center justify-center mx-3",
)
@rx.memo
def integrations_marquee() -> rx.Component:
integration_names = [
next(iter(item.values()))["name"] for item in get_integration_path()
]
return rx.el.div(
marquee(
*[integration_icon_marquee(name) for name in reversed(integration_names)],
direction="left",
gradient_color="light-dark(rgba(255, 255, 255, 0.96), var(--secondary-1))",
class_name="h-auto w-full overflow-hidden",
gradient_width=65,
speed=25,
pause_on_hover=False,
),
marquee(
*[integration_icon_marquee(name) for name in integration_names],
direction="right",
gradient_color="light-dark(rgba(255, 255, 255, 0.96), var(--secondary-1))",
class_name="h-auto w-full overflow-hidden",
gradient_width=65,
speed=25,
pause_on_hover=False,
),
class_name="flex flex-col gap-6.5 px-8 max-lg:pb-6",
)
def ai_builder_section() -> rx.Component:
return rx.el.section(
rx.el.div(
rx.el.div(
rx.el.h2(
"AI Builder",
class_name="text-secondary-12 text-3xl font-[575]",
),
rx.el.p(
"Learn how to build applications with Reflex AI.",
class_name="text-secondary-11 text-sm font-[475]",
),
class_name="flex flex-col gap-4",
),
rx.el.div(
card(
title="Getting Started",
description="A comprehensive guide to working effectively with AI Builder. The key to success is clarity, structure, and iteration.",
content=rx.image(
src=f"{REFLEX_ASSETS_CDN}docs/{rx.color_mode_cond('light', 'dark')}/getting_started_1.svg",
alt="AI Builder getting started guide",
class_name="w-full h-auto pb-8",
),
href=ai_builder_pages.overview.best_practices.path,
),
card(
title="Integrations",
description="Easily connect with the tools your team already uses or extend your app with any Python SDK, library, or API.",
content=integrations_marquee(),
href=ai_builder_pages.integrations.overview.path,
),
card(
title="MCP",
description="The Reflex Model Context Protocol (MCP) provides AI assistants and coding tools with structured access to Reflex documentation and component information.",
content=rx.image(
src=f"{REFLEX_ASSETS_CDN}docs/{rx.color_mode_cond('light', 'dark')}/mcp_1.svg",
alt="Reflex MCP integration illustration",
class_name="w-full h-auto -mt-4",
),
href=ai_builder_pages.integrations.mcp_overview.path,
enteprise_only=True,
),
class_name="grid grid-cols-1 lg:grid-cols-3 gap-12",
),
class_name="flex flex-col gap-10 max-lg:text-center relative max-w-(--landing-layout-max-width) mx-auto",
),
class_name="bg-gradient-to-b from-secondary-2 to-secondary-1 w-full lg:pt-24 lg:pb-24 pb-10 max-xl:px-6 max-lg:pt-10",
)