botrun-flow-lang 5.11.11__py3-none-any.whl → 5.12.261__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.
- botrun_flow_lang/api/hatch_api.py +28 -1
- botrun_flow_lang/api/line_bot_api.py +181 -30
- botrun_flow_lang/langgraph_agents/agents/agent_runner.py +13 -9
- botrun_flow_lang/langgraph_agents/agents/langgraph_react_agent.py +31 -0
- botrun_flow_lang/langgraph_agents/agents/util/pdf_analyzer.py +368 -42
- botrun_flow_lang/langgraph_agents/agents/util/pdf_cache.py +250 -0
- botrun_flow_lang/langgraph_agents/agents/util/pdf_processor.py +204 -0
- botrun_flow_lang/mcp_server/default_mcp.py +17 -8
- botrun_flow_lang/services/hatch/hatch_fs_store.py +23 -8
- botrun_flow_lang/services/storage/storage_cs_store.py +5 -1
- {botrun_flow_lang-5.11.11.dist-info → botrun_flow_lang-5.12.261.dist-info}/METADATA +3 -2
- {botrun_flow_lang-5.11.11.dist-info → botrun_flow_lang-5.12.261.dist-info}/RECORD +13 -11
- {botrun_flow_lang-5.11.11.dist-info → botrun_flow_lang-5.12.261.dist-info}/WHEEL +1 -1
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"""
|
|
2
|
+
PDF 處理工具模組
|
|
3
|
+
|
|
4
|
+
提供 PDF 切割等功能,用於處理大型 PDF 檔案。
|
|
5
|
+
使用 pypdf(純 Python)實作,避免 C++ 庫的 segfault 問題。
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import io
|
|
9
|
+
from typing import List, Tuple
|
|
10
|
+
|
|
11
|
+
from pypdf import PdfReader, PdfWriter
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_pdf_size(pdf_content: bytes) -> int:
|
|
15
|
+
"""
|
|
16
|
+
取得 PDF 檔案大小(bytes)
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
pdf_content: PDF 檔案的二進位內容
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
int: 檔案大小(bytes)
|
|
23
|
+
"""
|
|
24
|
+
return len(pdf_content)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_pdf_size_mb(pdf_content: bytes) -> float:
|
|
28
|
+
"""
|
|
29
|
+
取得 PDF 檔案大小(MB)
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
pdf_content: PDF 檔案的二進位內容
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
float: 檔案大小(MB)
|
|
36
|
+
"""
|
|
37
|
+
return len(pdf_content) / (1024 * 1024)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_pdf_page_count(pdf_content: bytes) -> int:
|
|
41
|
+
"""
|
|
42
|
+
取得 PDF 總頁數
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
pdf_content: PDF 檔案的二進位內容
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
int: 總頁數
|
|
49
|
+
"""
|
|
50
|
+
try:
|
|
51
|
+
reader = PdfReader(io.BytesIO(pdf_content))
|
|
52
|
+
return len(reader.pages)
|
|
53
|
+
except Exception as e:
|
|
54
|
+
print(f"[get_pdf_page_count] 無法讀取 PDF 頁數: {e}")
|
|
55
|
+
return 0
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def split_pdf_by_pages(
|
|
59
|
+
pdf_content: bytes, pages_per_chunk: int = 15
|
|
60
|
+
) -> List[Tuple[bytes, str]]:
|
|
61
|
+
"""
|
|
62
|
+
按頁數切割 PDF
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
pdf_content: PDF 檔案的二進位內容
|
|
66
|
+
pages_per_chunk: 每個切片的頁數(預設 15 頁)
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
List[Tuple[bytes, str]]: 切片清單,每個元素為 (切片內容, 頁碼範圍字串)
|
|
70
|
+
例如: [(chunk_bytes, "page-001-015"), (chunk_bytes, "page-016-030"), ...]
|
|
71
|
+
"""
|
|
72
|
+
chunks = []
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
reader = PdfReader(io.BytesIO(pdf_content))
|
|
76
|
+
total_pages = len(reader.pages)
|
|
77
|
+
|
|
78
|
+
for start_idx in range(0, total_pages, pages_per_chunk):
|
|
79
|
+
end_idx = min(start_idx + pages_per_chunk, total_pages)
|
|
80
|
+
|
|
81
|
+
# 建立新的 PDF 並複製頁面
|
|
82
|
+
writer = PdfWriter()
|
|
83
|
+
for page_idx in range(start_idx, end_idx):
|
|
84
|
+
writer.add_page(reader.pages[page_idx])
|
|
85
|
+
|
|
86
|
+
# 輸出切片
|
|
87
|
+
output = io.BytesIO()
|
|
88
|
+
writer.write(output)
|
|
89
|
+
chunk_bytes = output.getvalue()
|
|
90
|
+
|
|
91
|
+
# 產生頁碼範圍字串(1-indexed)
|
|
92
|
+
page_range = f"page-{start_idx + 1:03d}-{end_idx:03d}"
|
|
93
|
+
|
|
94
|
+
chunks.append((chunk_bytes, page_range))
|
|
95
|
+
|
|
96
|
+
except Exception as e:
|
|
97
|
+
print(f"[split_pdf_by_pages] 切割 PDF 時發生錯誤: {e}")
|
|
98
|
+
# 如果切割失敗,回傳整個 PDF 作為單一切片
|
|
99
|
+
if pdf_content:
|
|
100
|
+
chunks.append((pdf_content, "page-001-all"))
|
|
101
|
+
|
|
102
|
+
return chunks
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def calculate_optimal_chunk_size(
|
|
106
|
+
pdf_content: bytes,
|
|
107
|
+
target_size_mb: float = 4.0,
|
|
108
|
+
min_pages: int = 5,
|
|
109
|
+
max_pages: int = 30,
|
|
110
|
+
) -> int:
|
|
111
|
+
"""
|
|
112
|
+
計算最佳切割頁數,確保每個切片小於目標大小
|
|
113
|
+
|
|
114
|
+
策略:
|
|
115
|
+
1. 先估算每頁平均大小
|
|
116
|
+
2. 計算達到目標大小需要的頁數
|
|
117
|
+
3. 限制在 min_pages 和 max_pages 之間
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
pdf_content: PDF 檔案的二進位內容
|
|
121
|
+
target_size_mb: 目標切片大小(MB),預設 4MB
|
|
122
|
+
min_pages: 最小頁數,預設 5 頁
|
|
123
|
+
max_pages: 最大頁數,預設 30 頁
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
int: 建議的每個切片頁數
|
|
127
|
+
"""
|
|
128
|
+
total_size_mb = get_pdf_size_mb(pdf_content)
|
|
129
|
+
total_pages = get_pdf_page_count(pdf_content)
|
|
130
|
+
|
|
131
|
+
if total_pages == 0:
|
|
132
|
+
return min_pages
|
|
133
|
+
|
|
134
|
+
# 估算每頁平均大小
|
|
135
|
+
avg_page_size_mb = total_size_mb / total_pages
|
|
136
|
+
|
|
137
|
+
# 計算達到目標大小需要的頁數
|
|
138
|
+
if avg_page_size_mb > 0:
|
|
139
|
+
optimal_pages = int(target_size_mb / avg_page_size_mb)
|
|
140
|
+
else:
|
|
141
|
+
optimal_pages = max_pages
|
|
142
|
+
|
|
143
|
+
# 限制在範圍內
|
|
144
|
+
optimal_pages = max(min_pages, min(optimal_pages, max_pages))
|
|
145
|
+
|
|
146
|
+
return optimal_pages
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def split_pdf_smart(
|
|
150
|
+
pdf_content: bytes, target_size_mb: float = 4.0
|
|
151
|
+
) -> List[Tuple[bytes, str]]:
|
|
152
|
+
"""
|
|
153
|
+
智慧切割 PDF
|
|
154
|
+
|
|
155
|
+
先計算最佳切割頁數,然後進行切割。
|
|
156
|
+
如果切割後某個切片仍超過目標大小,會進一步分割。
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
pdf_content: PDF 檔案的二進位內容
|
|
160
|
+
target_size_mb: 目標切片大小(MB),預設 4MB
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
List[Tuple[bytes, str]]: 切片清單,每個元素為 (切片內容, 頁碼範圍字串)
|
|
164
|
+
"""
|
|
165
|
+
# 計算最佳切割頁數
|
|
166
|
+
pages_per_chunk = calculate_optimal_chunk_size(pdf_content, target_size_mb)
|
|
167
|
+
print(f"[split_pdf_smart] 計算最佳切割頁數: {pages_per_chunk} 頁/切片")
|
|
168
|
+
|
|
169
|
+
# 進行初步切割
|
|
170
|
+
chunks = split_pdf_by_pages(pdf_content, pages_per_chunk)
|
|
171
|
+
|
|
172
|
+
# 檢查是否有切片超過目標大小,如果有則進一步分割
|
|
173
|
+
final_chunks = []
|
|
174
|
+
for chunk_bytes, page_range in chunks:
|
|
175
|
+
chunk_size_mb = get_pdf_size_mb(chunk_bytes)
|
|
176
|
+
|
|
177
|
+
if chunk_size_mb > target_size_mb and pages_per_chunk > 5:
|
|
178
|
+
# 這個切片太大,需要進一步分割
|
|
179
|
+
print(
|
|
180
|
+
f"[split_pdf_smart] 切片 {page_range} 大小 {chunk_size_mb:.2f}MB "
|
|
181
|
+
f"超過目標 {target_size_mb}MB,進一步分割"
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
# 取得這個切片的頁碼範圍
|
|
185
|
+
parts = page_range.replace("page-", "").split("-")
|
|
186
|
+
start_page = int(parts[0])
|
|
187
|
+
|
|
188
|
+
# 用更小的頁數重新切割
|
|
189
|
+
smaller_chunks = split_pdf_by_pages(chunk_bytes, pages_per_chunk // 2)
|
|
190
|
+
|
|
191
|
+
# 更新頁碼範圍
|
|
192
|
+
chunk_page_count = get_pdf_page_count(chunk_bytes)
|
|
193
|
+
for i, (sub_chunk, _) in enumerate(smaller_chunks):
|
|
194
|
+
sub_start = start_page + i * (pages_per_chunk // 2)
|
|
195
|
+
sub_end = min(
|
|
196
|
+
sub_start + (pages_per_chunk // 2) - 1,
|
|
197
|
+
start_page + chunk_page_count - 1,
|
|
198
|
+
)
|
|
199
|
+
sub_range = f"page-{sub_start:03d}-{sub_end:03d}"
|
|
200
|
+
final_chunks.append((sub_chunk, sub_range))
|
|
201
|
+
else:
|
|
202
|
+
final_chunks.append((chunk_bytes, page_range))
|
|
203
|
+
|
|
204
|
+
return final_chunks
|
|
@@ -15,7 +15,9 @@ from langchain_core.runnables import RunnableConfig
|
|
|
15
15
|
|
|
16
16
|
# Import necessary dependencies
|
|
17
17
|
from botrun_flow_lang.models.nodes.utils import scrape_single_url
|
|
18
|
-
from botrun_flow_lang.langgraph_agents.agents.util.pdf_analyzer import
|
|
18
|
+
from botrun_flow_lang.langgraph_agents.agents.util.pdf_analyzer import (
|
|
19
|
+
analyze_pdf_async,
|
|
20
|
+
)
|
|
19
21
|
from botrun_flow_lang.langgraph_agents.agents.util.img_util import analyze_imgs
|
|
20
22
|
from botrun_flow_lang.langgraph_agents.agents.util.local_files import (
|
|
21
23
|
upload_and_get_tmp_public_url,
|
|
@@ -76,6 +78,10 @@ async def chat_with_pdf(
|
|
|
76
78
|
"""
|
|
77
79
|
Analyze a PDF file and answer questions about its content.
|
|
78
80
|
|
|
81
|
+
Supports intelligent processing based on file size:
|
|
82
|
+
- Small files (< 5MB): Direct multimodal analysis
|
|
83
|
+
- Large files (>= 5MB): Compress -> Split -> Parallel multimodal Q&A -> Merge results
|
|
84
|
+
|
|
79
85
|
Args:
|
|
80
86
|
pdf_url: The URL to the PDF file (can be generated using generate_tmp_public_url for local files)
|
|
81
87
|
user_input: The user's question or instruction about the PDF content
|
|
@@ -91,7 +97,7 @@ async def chat_with_pdf(
|
|
|
91
97
|
if not pdf_url.startswith("http"):
|
|
92
98
|
pdf_url = upload_and_get_tmp_public_url(pdf_url, botrun_flow_lang_url, user_id)
|
|
93
99
|
|
|
94
|
-
return
|
|
100
|
+
return await analyze_pdf_async(pdf_url, user_input)
|
|
95
101
|
|
|
96
102
|
|
|
97
103
|
@mcp.tool()
|
|
@@ -175,10 +181,10 @@ async def generate_image(
|
|
|
175
181
|
# 驗證必要參數
|
|
176
182
|
if not user_id:
|
|
177
183
|
logger.error("User ID not available")
|
|
178
|
-
|
|
184
|
+
return "User ID not available"
|
|
179
185
|
if not botrun_flow_lang_url:
|
|
180
186
|
logger.error("botrun_flow_lang_url not available")
|
|
181
|
-
|
|
187
|
+
return "botrun_flow_lang_url not available"
|
|
182
188
|
|
|
183
189
|
# Check rate limit before generating image
|
|
184
190
|
rate_limit_client = RateLimitClient()
|
|
@@ -195,10 +201,12 @@ async def generate_image(
|
|
|
195
201
|
f"User {user_id} has reached daily limit of {daily_limit} image generations. "
|
|
196
202
|
f"Current usage: {current_usage}. Please try again tomorrow."
|
|
197
203
|
)
|
|
198
|
-
|
|
199
|
-
f"You have reached your daily limit of {daily_limit} image generations. "
|
|
204
|
+
return f"[Please tell user error] You have reached your daily limit of {daily_limit} image generations. " \
|
|
200
205
|
f"Current usage: {current_usage}. Please try again tomorrow."
|
|
201
|
-
|
|
206
|
+
# raise BotrunRateLimitException(
|
|
207
|
+
# f"You have reached your daily limit of {daily_limit} image generations. "
|
|
208
|
+
# f"Current usage: {current_usage}. Please try again tomorrow."
|
|
209
|
+
# )
|
|
202
210
|
|
|
203
211
|
# 2. 使用 DALL-E 生成圖片
|
|
204
212
|
dalle_wrapper = DallEAPIWrapper(
|
|
@@ -267,7 +275,8 @@ async def generate_tmp_public_url(
|
|
|
267
275
|
logger.info(f"generate_tmp_public_url file_path: {file_path}")
|
|
268
276
|
|
|
269
277
|
if not os.path.exists(file_path):
|
|
270
|
-
|
|
278
|
+
return f"File not found: {file_path}"
|
|
279
|
+
# raise FileNotFoundError(f"File not found: {file_path}")
|
|
271
280
|
|
|
272
281
|
return upload_and_get_tmp_public_url(file_path, botrun_flow_lang_url, user_id)
|
|
273
282
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from typing import Union, List, Tuple
|
|
3
|
+
from datetime import datetime, timezone
|
|
3
4
|
from google.cloud.exceptions import GoogleCloudError
|
|
4
5
|
from botrun_flow_lang.constants import HATCH_SHARING_STORE_NAME, HATCH_STORE_NAME
|
|
5
6
|
from botrun_flow_lang.services.base.firestore_base import FirestoreBase
|
|
@@ -27,6 +28,9 @@ class HatchFsStore(FirestoreBase):
|
|
|
27
28
|
|
|
28
29
|
async def set_hatch(self, item: Hatch):
|
|
29
30
|
try:
|
|
31
|
+
# Update updated_at timestamp with current UTC time
|
|
32
|
+
item.updated_at = datetime.now(timezone.utc).isoformat()
|
|
33
|
+
|
|
30
34
|
# Proceed with saving the hatch
|
|
31
35
|
doc_ref = self.collection.document(str(item.id))
|
|
32
36
|
doc_ref.set(item.model_dump())
|
|
@@ -49,18 +53,29 @@ class HatchFsStore(FirestoreBase):
|
|
|
49
53
|
return False
|
|
50
54
|
|
|
51
55
|
async def get_hatches(
|
|
52
|
-
self,
|
|
56
|
+
self,
|
|
57
|
+
user_id: str,
|
|
58
|
+
offset: int = 0,
|
|
59
|
+
limit: int = 20,
|
|
60
|
+
sort_by: str = "updated_at",
|
|
61
|
+
order: str = "desc",
|
|
53
62
|
) -> Tuple[List[Hatch], str]:
|
|
54
63
|
try:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
)
|
|
59
|
-
.order_by("name")
|
|
60
|
-
.offset(offset)
|
|
61
|
-
.limit(limit)
|
|
64
|
+
# Build base query
|
|
65
|
+
query = self.collection.where(
|
|
66
|
+
filter=firestore.FieldFilter("user_id", "==", user_id)
|
|
62
67
|
)
|
|
63
68
|
|
|
69
|
+
# Add sorting
|
|
70
|
+
# Firestore direction: DESCENDING or ASCENDING
|
|
71
|
+
direction = (
|
|
72
|
+
firestore.Query.DESCENDING if order == "desc" else firestore.Query.ASCENDING
|
|
73
|
+
)
|
|
74
|
+
query = query.order_by(sort_by, direction=direction)
|
|
75
|
+
|
|
76
|
+
# Add pagination
|
|
77
|
+
query = query.offset(offset).limit(limit)
|
|
78
|
+
|
|
64
79
|
docs = query.stream()
|
|
65
80
|
hatches = [Hatch(**doc.to_dict()) for doc in docs]
|
|
66
81
|
return hatches, ""
|
|
@@ -39,7 +39,11 @@ class StorageCsStore(StorageStore):
|
|
|
39
39
|
{
|
|
40
40
|
"action": {"type": "Delete"},
|
|
41
41
|
"condition": {"age": 365, "matchesPrefix": ["tmp/"]},
|
|
42
|
-
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"action": {"type": "Delete"},
|
|
45
|
+
"condition": {"age": 7, "matchesPrefix": ["pdf-cache/"]},
|
|
46
|
+
},
|
|
43
47
|
]
|
|
44
48
|
|
|
45
49
|
if not bucket.exists():
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: botrun-flow-lang
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.12.261
|
|
4
4
|
Summary: A flow language for botrun
|
|
5
5
|
Author-email: sebastian-hsu <sebastian.hsu@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -13,7 +13,7 @@ Requires-Python: <3.13,>=3.11
|
|
|
13
13
|
Requires-Dist: aiohttp>=3.10.8
|
|
14
14
|
Requires-Dist: anthropic>=0.61.0
|
|
15
15
|
Requires-Dist: boto3>=1.40.3
|
|
16
|
-
Requires-Dist: botrun-hatch>=5.
|
|
16
|
+
Requires-Dist: botrun-hatch>=5.12.261
|
|
17
17
|
Requires-Dist: botrun-log>=0.3.0
|
|
18
18
|
Requires-Dist: cachetools>=5.5.2
|
|
19
19
|
Requires-Dist: chardet>=5.2.0
|
|
@@ -47,6 +47,7 @@ Requires-Dist: pandas>=2.2.3
|
|
|
47
47
|
Requires-Dist: pdfminer-six==20250506
|
|
48
48
|
Requires-Dist: plotly>=6.0.0
|
|
49
49
|
Requires-Dist: pydantic-settings>=2.5.2
|
|
50
|
+
Requires-Dist: pypdf==6.4.2
|
|
50
51
|
Requires-Dist: python-multipart>=0.0.20
|
|
51
52
|
Requires-Dist: pytz>=2024.2
|
|
52
53
|
Requires-Dist: pyyaml>=6.0.2
|
|
@@ -8,9 +8,9 @@ botrun_flow_lang/api/auth_api.py,sha256=o_ThrZFcOMQieUcUJIF_B7rsyvbkCvOCjCjknl9G
|
|
|
8
8
|
botrun_flow_lang/api/auth_utils.py,sha256=qE7RIPDnX30FPmhlgmlQNoVNkLU028x4SldVl6VC4KQ,6455
|
|
9
9
|
botrun_flow_lang/api/botrun_back_api.py,sha256=mE2NSejaYIiE0L9GmNJbLc_FRWCy6BXlcqRwkB1kKmc,2397
|
|
10
10
|
botrun_flow_lang/api/flow_api.py,sha256=DcxuoGE1OcbTgLSYKZ2SO9IdcH3UB5Ik3cVmX3v3-Po,108
|
|
11
|
-
botrun_flow_lang/api/hatch_api.py,sha256=
|
|
11
|
+
botrun_flow_lang/api/hatch_api.py,sha256=trenrAJt95ufjpAzwuTvcCoJdMR2x4EZCuWBup9e4hA,16984
|
|
12
12
|
botrun_flow_lang/api/langgraph_api.py,sha256=zqu0xeTiy2Pr4UL6vvGqVVAy2KX3ZUn1uzcq-Tfb_aM,29291
|
|
13
|
-
botrun_flow_lang/api/line_bot_api.py,sha256=
|
|
13
|
+
botrun_flow_lang/api/line_bot_api.py,sha256=INTWnI09LhRhQ6NcetHrHAQZU86eyoJ2zZ6g-KtX8MM,55500
|
|
14
14
|
botrun_flow_lang/api/model_api.py,sha256=bXemey_XUUdylZwh7Z10eksoBWe9xSa8I9TEL7jIBtE,9483
|
|
15
15
|
botrun_flow_lang/api/rate_limit_api.py,sha256=SkpjfvShHRdP5XJzy3DdrH4jLtdYAEHROGBMBkC9OIY,948
|
|
16
16
|
botrun_flow_lang/api/routes.py,sha256=rd0IoMsteJT9BO3MQuyXirhPQbas6OeiKaEC8Yf2SZs,1570
|
|
@@ -23,8 +23,8 @@ botrun_flow_lang/api/version_api.py,sha256=Mcs7hKBP7T7nlHDaZS4U0dtOkNQqW0BtT62Iv
|
|
|
23
23
|
botrun_flow_lang/api/youtube_api.py,sha256=R384jNRheMKnDyzvlLnbzackipZhiLYTZl4w4hB6vtw,753
|
|
24
24
|
botrun_flow_lang/langgraph_agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
25
|
botrun_flow_lang/langgraph_agents/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
|
-
botrun_flow_lang/langgraph_agents/agents/agent_runner.py,sha256=
|
|
27
|
-
botrun_flow_lang/langgraph_agents/agents/langgraph_react_agent.py,sha256=
|
|
26
|
+
botrun_flow_lang/langgraph_agents/agents/agent_runner.py,sha256=1BRIbEi7_NoIx1BuVUPFA-fDHErm3nHpX65HsY7YpWU,6495
|
|
27
|
+
botrun_flow_lang/langgraph_agents/agents/langgraph_react_agent.py,sha256=4fK_hMoUAqcEYv7rrHbAx6PFsJ7UcvGI0G2OgWhVhnw,29972
|
|
28
28
|
botrun_flow_lang/langgraph_agents/agents/search_agent_graph.py,sha256=6fz-ewLQGacEx-uqGfF3-go9FdiioiMzW_sfANzYTcI,31182
|
|
29
29
|
botrun_flow_lang/langgraph_agents/agents/agent_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
30
|
botrun_flow_lang/langgraph_agents/agents/agent_tools/step_planner.py,sha256=CgEhfGR28Rq7ui9cKxj_DczfNfjJNXIP9DXQNIwBLv0,2350
|
|
@@ -44,7 +44,9 @@ botrun_flow_lang/langgraph_agents/agents/util/img_util.py,sha256=FF5XUFCtYBul6DZ
|
|
|
44
44
|
botrun_flow_lang/langgraph_agents/agents/util/local_files.py,sha256=ib3JVvuTgKhFj-D_8d5MH3vImFe6Fk1aMxyxNqjDWWc,13110
|
|
45
45
|
botrun_flow_lang/langgraph_agents/agents/util/mermaid_util.py,sha256=Aw_ufAEBAqSENOtueemYtapxPVvbQ6HScedeWUZ8lS4,2556
|
|
46
46
|
botrun_flow_lang/langgraph_agents/agents/util/model_utils.py,sha256=lCORhM77agNgmDxsA40XlUth-E8ThM5Kv-x0_DQnYrs,4811
|
|
47
|
-
botrun_flow_lang/langgraph_agents/agents/util/pdf_analyzer.py,sha256=
|
|
47
|
+
botrun_flow_lang/langgraph_agents/agents/util/pdf_analyzer.py,sha256=R50ttYF9uun9aawjFzyFlTrXbM03HNbc-yanILdyRtM,15691
|
|
48
|
+
botrun_flow_lang/langgraph_agents/agents/util/pdf_cache.py,sha256=ptWaNtu_ls1piiBqQG2ZISjxWJ4gxMbIs7hvBdeas5k,7125
|
|
49
|
+
botrun_flow_lang/langgraph_agents/agents/util/pdf_processor.py,sha256=OgaloAzjoMmdymM3O1EiES7Ji6qqZtZPQmDT6HwmnYM,6040
|
|
48
50
|
botrun_flow_lang/langgraph_agents/agents/util/perplexity_search.py,sha256=4ynmvT8yXbi4KFEVliXWffozB6fHd8jVueA3MmGKlD8,19073
|
|
49
51
|
botrun_flow_lang/langgraph_agents/agents/util/plotly_util.py,sha256=8xKoj9ABwqCA8dzWFmw-qXCXStgCx6hMc5mVBBJ3ZGw,1913
|
|
50
52
|
botrun_flow_lang/langgraph_agents/agents/util/tavily_search.py,sha256=hhiuxF6u92X8Mz1VLAreFrB-LyR-UOKR9Xxh1TBveTg,6623
|
|
@@ -56,7 +58,7 @@ botrun_flow_lang/llm_agent/llm_agent.py,sha256=Ae9YCK0R_zvSU38Oewo7_qbnBMYTaero6
|
|
|
56
58
|
botrun_flow_lang/llm_agent/llm_agent_util.py,sha256=1slGk7LIYUylRjHvw4d92VAxD16uwiK4Efy0m_7tCJs,3048
|
|
57
59
|
botrun_flow_lang/log/.gitignore,sha256=ZZ3Viy7hKc5dYybO_EM74DBeCqrwL7vmnECmsw--nVc,16
|
|
58
60
|
botrun_flow_lang/mcp_server/__init__.py,sha256=P02XN_G9ALIeNgPwIsLPdKjGO7lk_XYOxME6NFrBrzE,208
|
|
59
|
-
botrun_flow_lang/mcp_server/default_mcp.py,sha256=
|
|
61
|
+
botrun_flow_lang/mcp_server/default_mcp.py,sha256=P38E6p6s9yT2U33hxlOMXG0iioUQ-JgJze-9zmlu5mY,28490
|
|
60
62
|
botrun_flow_lang/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
61
63
|
botrun_flow_lang/models/token_usage.py,sha256=hwGYZzklnTrcDCjNqCn03kddzS3VH-i1l0d5WnF6iqA,842
|
|
62
64
|
botrun_flow_lang/models/nodes/utils.py,sha256=kN9RFOSHPvOZU7T4ZfVU6u2wkKgS03xtAKvjLOpryKM,6699
|
|
@@ -64,9 +66,9 @@ botrun_flow_lang/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
|
|
|
64
66
|
botrun_flow_lang/services/base/firestore_base.py,sha256=Z561TzGvYOUmGKc3IQh03nsK8XHCa96Nlx5m23TySks,1045
|
|
65
67
|
botrun_flow_lang/services/hatch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
66
68
|
botrun_flow_lang/services/hatch/hatch_factory.py,sha256=ObCcb_hTp8YFXRNXOsXtI_dND_dz7cusypF2tDnMqYY,271
|
|
67
|
-
botrun_flow_lang/services/hatch/hatch_fs_store.py,sha256=
|
|
69
|
+
botrun_flow_lang/services/hatch/hatch_fs_store.py,sha256=2wmRlFInjCD1RRRHVfX47xX74vih4zJBhfRcy5Uk7ew,13620
|
|
68
70
|
botrun_flow_lang/services/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
69
|
-
botrun_flow_lang/services/storage/storage_cs_store.py,sha256=
|
|
71
|
+
botrun_flow_lang/services/storage/storage_cs_store.py,sha256=5NQekxfzjH6420QHi6HxLFHM5qY9kfiYis-dmsyuHO4,7896
|
|
70
72
|
botrun_flow_lang/services/storage/storage_factory.py,sha256=Yn40nB79qoEvClksIRnRpQGojXT4J4q1ExBqb3ydets,354
|
|
71
73
|
botrun_flow_lang/services/storage/storage_store.py,sha256=cb31kDJHNqVA4HyiyJJ1Pnyqv1n5nOkHMpPpA8tvgXg,1905
|
|
72
74
|
botrun_flow_lang/services/user_setting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -95,6 +97,6 @@ botrun_flow_lang/utils/yaml_utils.py,sha256=1A6PSEE8TM0HSD_6l-fhUsjYnXJcrEKuPgot
|
|
|
95
97
|
botrun_flow_lang/utils/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
96
98
|
botrun_flow_lang/utils/clients/rate_limit_client.py,sha256=TRpA56OKrfYsoLoJ-TPYlC7Znp9s267-u6CX6BLyVko,8349
|
|
97
99
|
botrun_flow_lang/utils/clients/token_verify_client.py,sha256=BtrfLvMe-DtS8UKeDhaIkVKDZHphZVP7kyqXn9jhXEc,5740
|
|
98
|
-
botrun_flow_lang-5.
|
|
99
|
-
botrun_flow_lang-5.
|
|
100
|
-
botrun_flow_lang-5.
|
|
100
|
+
botrun_flow_lang-5.12.261.dist-info/METADATA,sha256=vtLwjT6C29pqio3IV9gFQeWSuVexlZuCs_bjkUmCw4s,6221
|
|
101
|
+
botrun_flow_lang-5.12.261.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
102
|
+
botrun_flow_lang-5.12.261.dist-info/RECORD,,
|