alita-sdk 0.3.206__py3-none-any.whl → 0.3.207__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.
- alita_sdk/runtime/clients/client.py +269 -6
- alita_sdk/runtime/langchain/langraph_agent.py +6 -1
- alita_sdk/runtime/langchain/store_manager.py +4 -4
- alita_sdk/runtime/toolkits/tools.py +11 -20
- alita_sdk/runtime/utils/streamlit.py +472 -192
- alita_sdk/runtime/utils/toolkit_runtime.py +147 -0
- alita_sdk/runtime/utils/toolkit_utils.py +157 -0
- alita_sdk/tools/memory/__init__.py +54 -10
- {alita_sdk-0.3.206.dist-info → alita_sdk-0.3.207.dist-info}/METADATA +1 -1
- {alita_sdk-0.3.206.dist-info → alita_sdk-0.3.207.dist-info}/RECORD +13 -20
- alita_sdk/community/analysis/__init__.py +0 -0
- alita_sdk/community/analysis/ado_analyse/__init__.py +0 -103
- alita_sdk/community/analysis/ado_analyse/api_wrapper.py +0 -261
- alita_sdk/community/analysis/github_analyse/__init__.py +0 -98
- alita_sdk/community/analysis/github_analyse/api_wrapper.py +0 -166
- alita_sdk/community/analysis/gitlab_analyse/__init__.py +0 -110
- alita_sdk/community/analysis/gitlab_analyse/api_wrapper.py +0 -172
- alita_sdk/community/analysis/jira_analyse/__init__.py +0 -141
- alita_sdk/community/analysis/jira_analyse/api_wrapper.py +0 -252
- {alita_sdk-0.3.206.dist-info → alita_sdk-0.3.207.dist-info}/WHEEL +0 -0
- {alita_sdk-0.3.206.dist-info → alita_sdk-0.3.207.dist-info}/licenses/LICENSE +0 -0
- {alita_sdk-0.3.206.dist-info → alita_sdk-0.3.207.dist-info}/top_level.txt +0 -0
@@ -256,45 +256,55 @@ def run_streamlit(st, ai_icon=None, user_icon=None):
|
|
256
256
|
|
257
257
|
return config
|
258
258
|
|
259
|
-
def instantiate_toolkit(
|
260
|
-
"""
|
259
|
+
def instantiate_toolkit(toolkit_config):
|
260
|
+
"""
|
261
|
+
Helper function to instantiate a toolkit based on its configuration.
|
262
|
+
This function now delegates to the toolkit_utils module for the actual implementation.
|
263
|
+
"""
|
261
264
|
try:
|
262
|
-
|
263
|
-
logger.info(f"Instantiating toolkit {toolkit_name} with config: {json.dumps(toolkit_config, indent=2)}")
|
265
|
+
from .toolkit_utils import instantiate_toolkit_with_client
|
264
266
|
|
265
|
-
#
|
266
|
-
|
267
|
-
|
267
|
+
# Extract toolkit name and settings from the old format
|
268
|
+
toolkit_name = toolkit_config.get('toolkit_name')
|
269
|
+
settings = toolkit_config.get('settings', {})
|
268
270
|
|
269
|
-
#
|
270
|
-
|
271
|
-
for config in st.session_state.tooklit_configs:
|
272
|
-
if config['title'] == toolkit_name:
|
273
|
-
toolkit_schema = config
|
274
|
-
break
|
275
|
-
|
276
|
-
if not toolkit_schema:
|
277
|
-
raise ValueError(f"Toolkit {toolkit_name} not found")
|
271
|
+
# Inject project secrets into configuration
|
272
|
+
enhanced_settings = inject_project_secrets(settings)
|
278
273
|
|
279
|
-
#
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
# Create a tool configuration dict with required ID field
|
284
|
-
tool_config = {
|
285
|
-
'id': random.randint(1, 1000000), # Required random integer ID
|
286
|
-
'type': toolkit_name.lower(),
|
287
|
-
'settings': enhanced_config,
|
288
|
-
'toolkit_name': toolkit_name
|
274
|
+
# Create the new format configuration
|
275
|
+
new_config = {
|
276
|
+
'toolkit_name': toolkit_name,
|
277
|
+
'settings': enhanced_settings
|
289
278
|
}
|
290
279
|
|
291
|
-
#
|
292
|
-
|
280
|
+
# Create a basic LLM client for toolkit instantiation
|
281
|
+
try:
|
282
|
+
if not st.session_state.client:
|
283
|
+
raise ValueError("Alita client not available")
|
284
|
+
|
285
|
+
llm_client = st.session_state.client.get_llm(
|
286
|
+
model_name="gpt-4o-mini",
|
287
|
+
model_config={
|
288
|
+
"temperature": 0.1,
|
289
|
+
"max_tokens": 1000,
|
290
|
+
"top_p": 1.0
|
291
|
+
}
|
292
|
+
)
|
293
|
+
except Exception as e:
|
294
|
+
logger.warning(f"Failed to create LLM client: {str(e)}. Falling back to basic toolkit instantiation.")
|
295
|
+
# Fallback to basic instantiation
|
296
|
+
from .toolkit_utils import instantiate_toolkit as fallback_instantiate
|
297
|
+
return fallback_instantiate(new_config)
|
293
298
|
|
294
|
-
|
299
|
+
# Use the enhanced implementation with client support
|
300
|
+
return instantiate_toolkit_with_client(
|
301
|
+
new_config,
|
302
|
+
llm_client,
|
303
|
+
st.session_state.client
|
304
|
+
)
|
295
305
|
|
296
306
|
except Exception as e:
|
297
|
-
logger.error(f"Error instantiating toolkit {toolkit_name}: {str(e)}")
|
307
|
+
logger.error(f"Error instantiating toolkit {toolkit_config.get('toolkit_name')}: {str(e)}")
|
298
308
|
raise
|
299
309
|
|
300
310
|
st.set_page_config(
|
@@ -905,12 +915,61 @@ def run_streamlit(st, ai_icon=None, user_icon=None):
|
|
905
915
|
elif default_value:
|
906
916
|
array_value = str(default_value)
|
907
917
|
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
918
|
+
# Auto-populate selected_tools with all available tools
|
919
|
+
if field_name == 'selected_tools':
|
920
|
+
# Get available tools from the schema's json_schema_extra
|
921
|
+
args_schemas = field_schema.get('json_schema_extra', {}).get('args_schemas', {})
|
922
|
+
if args_schemas:
|
923
|
+
available_tools = list(args_schemas.keys())
|
924
|
+
|
925
|
+
# Create a session state key for this toolkit's auto-population
|
926
|
+
auto_populate_key = f"auto_populate_tools_{toolkit_schema['title']}_{selected_toolkit_idx}"
|
927
|
+
|
928
|
+
# Auto-populate if field is empty and not already auto-populated
|
929
|
+
if not array_value and auto_populate_key not in st.session_state:
|
930
|
+
array_value = '\n'.join(available_tools)
|
931
|
+
st.session_state[auto_populate_key] = True
|
932
|
+
st.success(f"🔧 **Auto-populated {len(available_tools)} tools:** {', '.join(available_tools)}")
|
933
|
+
elif array_value and auto_populate_key in st.session_state:
|
934
|
+
# Show info about existing auto-population
|
935
|
+
current_tools = [line.strip() for line in array_value.split('\n') if line.strip()]
|
936
|
+
st.info(f"📋 **{len(current_tools)} tools configured** (auto-populated: {len(available_tools)} available)")
|
937
|
+
|
938
|
+
# Add a button to reset to all tools
|
939
|
+
col1, col2 = st.columns([3, 1])
|
940
|
+
with col2:
|
941
|
+
if st.button("📋 Load All Tools", help="Auto-populate with all available tools", key=f"load_all_tools_{selected_toolkit_idx}"):
|
942
|
+
# Update the session state to trigger rerun with populated tools
|
943
|
+
st.session_state[f"tools_loaded_{selected_toolkit_idx}"] = '\n'.join(available_tools)
|
944
|
+
st.success(f"✅ Loaded {len(available_tools)} tools")
|
945
|
+
st.rerun()
|
946
|
+
|
947
|
+
# Check if tools were just loaded via button
|
948
|
+
if f"tools_loaded_{selected_toolkit_idx}" in st.session_state:
|
949
|
+
array_value = st.session_state[f"tools_loaded_{selected_toolkit_idx}"]
|
950
|
+
del st.session_state[f"tools_loaded_{selected_toolkit_idx}"] # Clean up
|
951
|
+
|
952
|
+
with col1:
|
953
|
+
array_input = st.text_area(
|
954
|
+
f"{label} (one per line)",
|
955
|
+
value=array_value,
|
956
|
+
help=f"{field_description} - Enter one item per line. Available tools: {', '.join(available_tools)}",
|
957
|
+
key=f"config_{field_name}_{selected_toolkit_idx}"
|
958
|
+
)
|
959
|
+
else:
|
960
|
+
array_input = st.text_area(
|
961
|
+
f"{label} (one per line)",
|
962
|
+
value=array_value,
|
963
|
+
help=f"{field_description} - Enter one item per line",
|
964
|
+
key=f"config_{field_name}_{selected_toolkit_idx}"
|
965
|
+
)
|
966
|
+
else:
|
967
|
+
array_input = st.text_area(
|
968
|
+
f"{label} (one per line)",
|
969
|
+
value=array_value,
|
970
|
+
help=f"{field_description} - Enter one item per line",
|
971
|
+
key=f"config_{field_name}_{selected_toolkit_idx}"
|
972
|
+
)
|
914
973
|
toolkit_config_values[field_name] = [line.strip() for line in array_input.split('\n') if line.strip()]
|
915
974
|
else:
|
916
975
|
st.info("This toolkit doesn't require additional configuration.")
|
@@ -988,7 +1047,11 @@ def run_streamlit(st, ai_icon=None, user_icon=None):
|
|
988
1047
|
toolkit_name = toolkit_schema['title']
|
989
1048
|
|
990
1049
|
# Test with current config
|
991
|
-
|
1050
|
+
toolkit_test_config = {
|
1051
|
+
'toolkit_name': toolkit_name,
|
1052
|
+
'settings': toolkit_config_values
|
1053
|
+
}
|
1054
|
+
tools = instantiate_toolkit(toolkit_test_config)
|
992
1055
|
st.success("✅ Connection test successful!")
|
993
1056
|
|
994
1057
|
except Exception as e:
|
@@ -1050,6 +1113,41 @@ def run_streamlit(st, ai_icon=None, user_icon=None):
|
|
1050
1113
|
# Toolkit Testing Main View
|
1051
1114
|
st.title("🚀 Toolkit Testing Interface")
|
1052
1115
|
|
1116
|
+
# Add info about the new testing capabilities
|
1117
|
+
st.info("""
|
1118
|
+
🔥 **Enhanced Testing Features:**
|
1119
|
+
- **Event Tracking**: Monitor custom events dispatched during tool execution
|
1120
|
+
- **Callback Support**: Full runtime callback support for real-time monitoring
|
1121
|
+
- **Error Handling**: Detailed error reporting with execution context
|
1122
|
+
- **Client Integration**: Uses the same method available in the API client
|
1123
|
+
""")
|
1124
|
+
|
1125
|
+
# Sidebar with testing information
|
1126
|
+
with st.sidebar:
|
1127
|
+
st.markdown("### 🔧 Testing Information")
|
1128
|
+
st.markdown("""
|
1129
|
+
**Current Method**: `client.test_toolkit_tool()`
|
1130
|
+
|
1131
|
+
**Features**:
|
1132
|
+
- ✅ Runtime callbacks
|
1133
|
+
- ✅ Event dispatching
|
1134
|
+
- ✅ Error handling
|
1135
|
+
- ✅ Configuration validation
|
1136
|
+
|
1137
|
+
**API Usage**:
|
1138
|
+
```python
|
1139
|
+
result = client.test_toolkit_tool(
|
1140
|
+
toolkit_config={
|
1141
|
+
'toolkit_name': 'github',
|
1142
|
+
'settings': {'token': '...'}
|
1143
|
+
},
|
1144
|
+
tool_name='get_repo',
|
1145
|
+
tool_params={'repo': 'alita'},
|
1146
|
+
runtime_config={'callbacks': [cb]}
|
1147
|
+
)
|
1148
|
+
```
|
1149
|
+
""")
|
1150
|
+
|
1053
1151
|
toolkit_config = st.session_state.configured_toolkit
|
1054
1152
|
|
1055
1153
|
# Header with toolkit info and navigation
|
@@ -1091,185 +1189,367 @@ def run_streamlit(st, ai_icon=None, user_icon=None):
|
|
1091
1189
|
st.write("**Original Agent Configuration:**")
|
1092
1190
|
st.json(agent_context['original_agent_config'])
|
1093
1191
|
|
1094
|
-
# Test mode selection in main view
|
1192
|
+
# Test mode selection in main view - simplified to function mode only
|
1095
1193
|
st.markdown("---")
|
1096
|
-
st.subheader("📋 Step 2:
|
1194
|
+
st.subheader("📋 Step 2: Function Testing Mode")
|
1097
1195
|
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
help="Tool Mode: Let AI decide which functions to call. Function Mode: Call specific functions directly.",
|
1102
|
-
horizontal=True
|
1103
|
-
)
|
1196
|
+
# Force to function mode only to avoid client dependency issues
|
1197
|
+
test_mode = "⚡ Without LLM (Function Mode)"
|
1198
|
+
st.info("🔧 **Function Mode:** Call specific toolkit functions directly with custom parameters.")
|
1104
1199
|
|
1105
1200
|
st.markdown("---")
|
1106
1201
|
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
)
|
1117
|
-
|
1118
|
-
col1, col2 = st.columns([3, 1])
|
1119
|
-
with col1:
|
1120
|
-
run_llm = st.button("🚀 Run with LLM", type="primary", key="run_llm_main")
|
1121
|
-
with col2:
|
1122
|
-
clear_prompt = st.button("🗑️ Clear", key="clear_llm_main")
|
1123
|
-
if clear_prompt:
|
1124
|
-
st.rerun()
|
1125
|
-
|
1126
|
-
if run_llm:
|
1127
|
-
if not test_prompt.strip():
|
1128
|
-
st.warning("⚠️ Please enter a test prompt.")
|
1129
|
-
else:
|
1130
|
-
with st.spinner("🔄 AI is working with your toolkit..."):
|
1131
|
-
try:
|
1132
|
-
tools = instantiate_toolkit(
|
1133
|
-
toolkit_config['name'],
|
1134
|
-
toolkit_config['config'],
|
1135
|
-
st.session_state.llm
|
1136
|
-
)
|
1137
|
-
|
1138
|
-
# Create a simple agent with the tools
|
1139
|
-
try:
|
1140
|
-
# Try to use OpenAI functions agent if available
|
1141
|
-
from langchain.agents import create_openai_functions_agent, AgentExecutor
|
1142
|
-
from langchain.prompts import ChatPromptTemplate
|
1143
|
-
|
1144
|
-
# Create a prompt for the toolkit testing
|
1145
|
-
prompt = ChatPromptTemplate.from_messages([
|
1146
|
-
("system", f"You are a helpful assistant with access to {toolkit_config['name']} toolkit functions. Use the available tools to help the user accomplish their task. Always explain what you're doing and provide clear results."),
|
1147
|
-
("human", "{input}"),
|
1148
|
-
("placeholder", "{agent_scratchpad}"),
|
1149
|
-
])
|
1150
|
-
|
1151
|
-
agent = create_openai_functions_agent(st.session_state.llm, tools, prompt)
|
1152
|
-
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
|
1153
|
-
|
1154
|
-
result = agent_executor.invoke({"input": test_prompt})
|
1155
|
-
|
1156
|
-
except ImportError:
|
1157
|
-
# Fallback to direct LLM invocation with tool descriptions
|
1158
|
-
tool_descriptions = "\n".join([f"- {tool.name}: {tool.description}" for tool in tools])
|
1159
|
-
enhanced_prompt = f"""You have access to the following {toolkit_config['name']} toolkit functions:
|
1160
|
-
{tool_descriptions}
|
1161
|
-
|
1162
|
-
User request: {test_prompt}
|
1163
|
-
|
1164
|
-
Please explain how you would use these tools to help the user, even though I cannot directly execute them in this fallback mode."""
|
1165
|
-
|
1166
|
-
result = {"output": st.session_state.llm.invoke(enhanced_prompt).content}
|
1167
|
-
|
1168
|
-
st.markdown("### 🎯 AI Response:")
|
1169
|
-
st.success(result["output"])
|
1170
|
-
|
1171
|
-
# Show tool usage details if available
|
1172
|
-
if "intermediate_steps" in result:
|
1173
|
-
with st.expander("📋 Execution Details"):
|
1174
|
-
st.json(result)
|
1175
|
-
|
1176
|
-
except Exception as e:
|
1177
|
-
st.error(f"❌ Error running toolkit with LLM: {str(e)}")
|
1178
|
-
with st.expander("🔍 Error Details"):
|
1179
|
-
st.code(str(e))
|
1202
|
+
# Directly proceed to Function Mode (no LLM option)
|
1203
|
+
st.markdown("### ⚡ Direct Function Testing")
|
1204
|
+
|
1205
|
+
# Information about the new testing method
|
1206
|
+
col1, col2 = st.columns([3, 1])
|
1207
|
+
with col1:
|
1208
|
+
st.info("💡 **Enhanced Testing:** Using `AlitaClient.test_toolkit_tool()` method with event capture and runtime callbacks.")
|
1209
|
+
with col2:
|
1210
|
+
st.markdown("**🔧 Method:** `test_toolkit_tool`")
|
1180
1211
|
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1212
|
+
# Show available functions
|
1213
|
+
try:
|
1214
|
+
# Use the client to get toolkit tools for display
|
1215
|
+
# We'll call the toolkit utilities directly to get tools
|
1216
|
+
from .toolkit_utils import instantiate_toolkit_with_client
|
1184
1217
|
|
1185
|
-
#
|
1218
|
+
# Create a simple LLM client for tool instantiation
|
1186
1219
|
try:
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1220
|
+
if not st.session_state.client:
|
1221
|
+
raise ValueError("Alita client not available")
|
1222
|
+
|
1223
|
+
llm_client = st.session_state.client.get_llm(
|
1224
|
+
model_name="gpt-4o-mini",
|
1225
|
+
model_config={
|
1226
|
+
"temperature": 0.1,
|
1227
|
+
"max_tokens": 1000,
|
1228
|
+
"top_p": 1.0
|
1229
|
+
}
|
1191
1230
|
)
|
1231
|
+
except Exception as e:
|
1232
|
+
logger.warning(f"Failed to create LLM client for toolkit instantiation: {str(e)}. Falling back to basic mode.")
|
1233
|
+
# Fallback to basic instantiation
|
1234
|
+
from .toolkit_utils import instantiate_toolkit as fallback_instantiate
|
1235
|
+
toolkit_test_config = {
|
1236
|
+
'toolkit_name': toolkit_config['name'],
|
1237
|
+
'settings': toolkit_config['config']
|
1238
|
+
}
|
1239
|
+
tools = fallback_instantiate(toolkit_test_config)
|
1240
|
+
else:
|
1241
|
+
toolkit_test_config = {
|
1242
|
+
'toolkit_name': toolkit_config['name'],
|
1243
|
+
'settings': toolkit_config['config']
|
1244
|
+
}
|
1245
|
+
tools = instantiate_toolkit_with_client(
|
1246
|
+
toolkit_test_config,
|
1247
|
+
llm_client,
|
1248
|
+
st.session_state.client
|
1249
|
+
)
|
1250
|
+
|
1251
|
+
if tools:
|
1252
|
+
st.markdown("### 📚 Available Functions:")
|
1253
|
+
st.info("🔧 **Auto-Population Enabled:** All available tools are automatically selected when you configure a toolkit. You can modify the selection below.")
|
1254
|
+
function_names = [tool.name for tool in tools]
|
1192
1255
|
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1256
|
+
# Auto-populate selected tools with all available tools
|
1257
|
+
if f"selected_tools_{toolkit_config['name']}" not in st.session_state:
|
1258
|
+
st.session_state[f"selected_tools_{toolkit_config['name']}"] = function_names
|
1259
|
+
|
1260
|
+
# Add controls for tool selection
|
1261
|
+
col1, col2, col3 = st.columns([3, 1, 1])
|
1262
|
+
with col1:
|
1263
|
+
st.markdown("**Tool Selection:**")
|
1264
|
+
with col2:
|
1265
|
+
if st.button("✅ Select All", help="Select all available tools", key=f"select_all_{toolkit_config['name']}"):
|
1266
|
+
st.session_state[f"selected_tools_{toolkit_config['name']}"] = function_names
|
1267
|
+
st.rerun()
|
1268
|
+
with col3:
|
1269
|
+
if st.button("❌ Clear All", help="Clear all selected tools", key=f"clear_all_{toolkit_config['name']}"):
|
1270
|
+
st.session_state[f"selected_tools_{toolkit_config['name']}"] = []
|
1271
|
+
st.rerun()
|
1272
|
+
|
1273
|
+
# Create multi-select for tools with auto-population
|
1274
|
+
selected_tools = st.multiselect(
|
1275
|
+
"Select tools to test:",
|
1276
|
+
function_names,
|
1277
|
+
default=st.session_state[f"selected_tools_{toolkit_config['name']}"],
|
1278
|
+
help="Choose the tools you want to test. All tools are selected by default.",
|
1279
|
+
key=f"tools_multiselect_{toolkit_config['name']}"
|
1280
|
+
)
|
1281
|
+
|
1282
|
+
# Update session state when selection changes
|
1283
|
+
st.session_state[f"selected_tools_{toolkit_config['name']}"] = selected_tools
|
1284
|
+
|
1285
|
+
# Show selection summary
|
1286
|
+
if selected_tools:
|
1287
|
+
st.success(f"✅ **{len(selected_tools)} of {len(function_names)} tools selected**")
|
1288
|
+
else:
|
1289
|
+
st.warning("⚠️ **No tools selected** - Please select at least one tool to proceed.")
|
1290
|
+
|
1291
|
+
# Create function selection dropdown from selected tools
|
1292
|
+
if selected_tools:
|
1198
1293
|
selected_function = st.selectbox(
|
1199
|
-
"Select a function:",
|
1200
|
-
|
1201
|
-
help="Choose the function you want to
|
1294
|
+
"Select a function to configure and run:",
|
1295
|
+
selected_tools,
|
1296
|
+
help="Choose the specific function you want to configure and execute",
|
1202
1297
|
key="function_selector_main"
|
1203
1298
|
)
|
1299
|
+
else:
|
1300
|
+
st.warning("Please select at least one tool to proceed.")
|
1301
|
+
selected_function = None
|
1302
|
+
|
1303
|
+
if selected_function:
|
1304
|
+
selected_tool = next(tool for tool in tools if tool.name == selected_function)
|
1305
|
+
|
1306
|
+
# Function details
|
1307
|
+
col1, col2 = st.columns([2, 1])
|
1308
|
+
with col1:
|
1309
|
+
st.markdown(f"**📖 Description:** {selected_tool.description}")
|
1310
|
+
with col2:
|
1311
|
+
st.markdown(f"**🏷️ Function:** `{selected_function}`")
|
1312
|
+
|
1313
|
+
# Show function schema if available
|
1314
|
+
if hasattr(selected_tool, 'args_schema') and selected_tool.args_schema:
|
1315
|
+
with st.expander("📋 Function Schema", expanded=False):
|
1316
|
+
try:
|
1317
|
+
schema = selected_tool.args_schema.schema()
|
1318
|
+
st.json(schema)
|
1319
|
+
except:
|
1320
|
+
st.write("Schema not available")
|
1204
1321
|
|
1205
|
-
|
1206
|
-
|
1322
|
+
# Function parameter form (instead of JSON input)
|
1323
|
+
st.markdown("---")
|
1324
|
+
with st.form("function_params_form", clear_on_submit=False):
|
1325
|
+
parameters = render_function_parameters_form(selected_tool, f"func_{selected_function}")
|
1207
1326
|
|
1208
|
-
#
|
1209
|
-
|
1327
|
+
# LLM Configuration Section
|
1328
|
+
st.markdown("### 🤖 LLM Configuration")
|
1329
|
+
st.markdown("Configure the LLM settings for tools that require AI capabilities:")
|
1330
|
+
|
1331
|
+
col1, col2 = st.columns(2)
|
1210
1332
|
with col1:
|
1211
|
-
st.
|
1333
|
+
llm_model = st.selectbox(
|
1334
|
+
"LLM Model:",
|
1335
|
+
options=['gpt-4o-mini', 'gpt-4o', 'gpt-4', 'gpt-3.5-turbo', 'claude-3-haiku', 'claude-3-sonnet'],
|
1336
|
+
index=0,
|
1337
|
+
help="Select the LLM model to use for tools that require AI capabilities"
|
1338
|
+
)
|
1339
|
+
|
1340
|
+
temperature = st.slider(
|
1341
|
+
"Temperature:",
|
1342
|
+
min_value=0.0,
|
1343
|
+
max_value=1.0,
|
1344
|
+
value=0.1,
|
1345
|
+
step=0.1,
|
1346
|
+
help="Controls randomness in AI responses. Lower values are more deterministic."
|
1347
|
+
)
|
1348
|
+
|
1212
1349
|
with col2:
|
1213
|
-
st.
|
1350
|
+
max_tokens = st.number_input(
|
1351
|
+
"Max Tokens:",
|
1352
|
+
min_value=100,
|
1353
|
+
max_value=4000,
|
1354
|
+
value=1000,
|
1355
|
+
step=100,
|
1356
|
+
help="Maximum number of tokens in the AI response"
|
1357
|
+
)
|
1358
|
+
|
1359
|
+
top_p = st.slider(
|
1360
|
+
"Top-p:",
|
1361
|
+
min_value=0.1,
|
1362
|
+
max_value=1.0,
|
1363
|
+
value=1.0,
|
1364
|
+
step=0.1,
|
1365
|
+
help="Controls diversity via nucleus sampling"
|
1366
|
+
)
|
1214
1367
|
|
1215
|
-
#
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
except:
|
1222
|
-
st.write("Schema not available")
|
1368
|
+
# Create LLM config
|
1369
|
+
llm_config = {
|
1370
|
+
'max_tokens': max_tokens,
|
1371
|
+
'temperature': temperature,
|
1372
|
+
'top_p': top_p
|
1373
|
+
}
|
1223
1374
|
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1375
|
+
col1, col2 = st.columns([3, 1])
|
1376
|
+
with col1:
|
1377
|
+
run_function = st.form_submit_button("⚡ Run Function", type="primary")
|
1378
|
+
with col2:
|
1379
|
+
clear_params = st.form_submit_button("🗑️ Clear Form")
|
1380
|
+
if clear_params:
|
1381
|
+
st.rerun()
|
1382
|
+
|
1383
|
+
if run_function and parameters is not None:
|
1384
|
+
with st.spinner("⚡ Executing function..."):
|
1385
|
+
try:
|
1386
|
+
# Use the client's test_toolkit_tool method
|
1387
|
+
# Create callback to capture events
|
1388
|
+
from langchain_core.callbacks import BaseCallbackHandler
|
1389
|
+
|
1390
|
+
class StreamlitEventCallback(BaseCallbackHandler):
|
1391
|
+
"""Callback handler for capturing custom events in Streamlit."""
|
1392
|
+
def __init__(self):
|
1393
|
+
self.events = []
|
1394
|
+
self.steps = []
|
1395
|
+
|
1396
|
+
def on_custom_event(self, name, data, **kwargs):
|
1397
|
+
"""Handle custom events dispatched by tools."""
|
1398
|
+
import datetime
|
1399
|
+
event = {
|
1400
|
+
'name': name,
|
1401
|
+
'data': data,
|
1402
|
+
'timestamp': datetime.datetime.now().isoformat(),
|
1403
|
+
**kwargs
|
1404
|
+
}
|
1405
|
+
self.events.append(event)
|
1406
|
+
|
1407
|
+
# Update progress in real-time for certain events
|
1408
|
+
if name == "progress" and isinstance(data, dict):
|
1409
|
+
message = data.get('message', 'Processing...')
|
1410
|
+
step = data.get('step', None)
|
1411
|
+
total_steps = data.get('total_steps', None)
|
1412
|
+
|
1413
|
+
if step and total_steps:
|
1414
|
+
progress = step / total_steps
|
1415
|
+
st.progress(progress, text=f"{message} ({step}/{total_steps})")
|
1416
|
+
else:
|
1417
|
+
st.info(f"📊 {message}")
|
1418
|
+
|
1419
|
+
callback = StreamlitEventCallback()
|
1420
|
+
runtime_config = {
|
1421
|
+
'callbacks': [callback],
|
1422
|
+
'configurable': {'streamlit_session': True},
|
1423
|
+
'tags': ['streamlit_testing', toolkit_config['name']]
|
1424
|
+
}
|
1425
|
+
|
1426
|
+
# Call the client's test method with LLM configuration
|
1427
|
+
result = st.session_state.client.test_toolkit_tool(
|
1428
|
+
toolkit_config={
|
1429
|
+
'toolkit_name': toolkit_config['name'],
|
1430
|
+
'settings': toolkit_config['config']
|
1431
|
+
},
|
1432
|
+
tool_name=selected_function,
|
1433
|
+
tool_params=parameters,
|
1434
|
+
runtime_config=runtime_config,
|
1435
|
+
llm_model=llm_model,
|
1436
|
+
llm_config=llm_config
|
1437
|
+
)
|
1438
|
+
|
1439
|
+
st.markdown("### 🎯 Function Result:")
|
1440
|
+
|
1441
|
+
if result['success']:
|
1442
|
+
execution_time = result.get('execution_time_seconds', 0.0)
|
1443
|
+
# Display success status with timing and LLM info
|
1444
|
+
col1, col2, col3, col4 = st.columns([2, 1, 1, 1])
|
1445
|
+
with col1:
|
1446
|
+
st.success("✅ Function executed successfully!")
|
1447
|
+
with col2:
|
1448
|
+
st.metric("⏱️ Time", f"{execution_time:.3f}s")
|
1449
|
+
with col3:
|
1450
|
+
st.metric("📡 Events", len(result.get('events_dispatched', [])))
|
1451
|
+
with col4:
|
1452
|
+
st.metric("🔧 Tool", result['tool_name'])
|
1453
|
+
llm_used = result.get('llm_model', 'N/A')
|
1454
|
+
st.metric("LLM", llm_used)
|
1243
1455
|
|
1244
|
-
#
|
1245
|
-
|
1246
|
-
st.
|
1247
|
-
|
1248
|
-
if
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1456
|
+
# Display the actual result
|
1457
|
+
with st.container():
|
1458
|
+
st.markdown("**📊 Function Output:**")
|
1459
|
+
tool_result = result['result']
|
1460
|
+
if isinstance(tool_result, (dict, list)):
|
1461
|
+
st.json(tool_result)
|
1462
|
+
elif isinstance(tool_result, str):
|
1463
|
+
if tool_result.startswith('{') or tool_result.startswith('['):
|
1464
|
+
try:
|
1465
|
+
parsed_result = json.loads(tool_result)
|
1466
|
+
st.json(parsed_result)
|
1467
|
+
except:
|
1468
|
+
st.code(tool_result, language="text")
|
1469
|
+
else:
|
1470
|
+
if len(tool_result) > 1000:
|
1471
|
+
with st.expander("📄 View Full Output", expanded=False):
|
1472
|
+
st.code(tool_result, language="text")
|
1473
|
+
st.info(f"Output truncated. Full length: {len(tool_result)} characters.")
|
1474
|
+
else:
|
1475
|
+
st.code(tool_result, language="text")
|
1254
1476
|
else:
|
1255
|
-
st.code(
|
1256
|
-
else:
|
1257
|
-
st.code(str(result))
|
1477
|
+
st.code(str(tool_result), language="text")
|
1258
1478
|
|
1259
|
-
#
|
1260
|
-
|
1479
|
+
# Show events if any were dispatched with better formatting
|
1480
|
+
events = result.get('events_dispatched', [])
|
1481
|
+
if events:
|
1482
|
+
with st.expander(f"📡 Events Dispatched ({len(events)})", expanded=True):
|
1483
|
+
for i, event in enumerate(events):
|
1484
|
+
with st.container():
|
1485
|
+
col1, col2 = st.columns([1, 4])
|
1486
|
+
with col1:
|
1487
|
+
event_type = event.get('name', 'unknown')
|
1488
|
+
if event_type == 'progress':
|
1489
|
+
st.markdown("🔄 **Progress**")
|
1490
|
+
elif event_type == 'info':
|
1491
|
+
st.markdown("ℹ️ **Info**")
|
1492
|
+
elif event_type == 'warning':
|
1493
|
+
st.markdown("⚠️ **Warning**")
|
1494
|
+
elif event_type == 'error':
|
1495
|
+
st.markdown("❌ **Error**")
|
1496
|
+
else:
|
1497
|
+
st.markdown(f"📋 **{event_type.title()}**")
|
1498
|
+
with col2:
|
1499
|
+
event_data = event.get('data', {})
|
1500
|
+
if isinstance(event_data, dict) and 'message' in event_data:
|
1501
|
+
st.write(event_data['message'])
|
1502
|
+
if len(event_data) > 1:
|
1503
|
+
with st.expander("Event Details"):
|
1504
|
+
st.json({k: v for k, v in event_data.items() if k != 'message'})
|
1505
|
+
else:
|
1506
|
+
st.json(event_data)
|
1507
|
+
if i < len(events) - 1:
|
1508
|
+
st.divider()
|
1261
1509
|
|
1262
|
-
|
1263
|
-
st.
|
1510
|
+
# Show execution metadata
|
1511
|
+
with st.expander("🔍 Execution Details", expanded=False):
|
1512
|
+
execution_time = result.get('execution_time_seconds', 0.0)
|
1513
|
+
metadata = {
|
1514
|
+
'tool_name': result['tool_name'],
|
1515
|
+
'toolkit_name': result['toolkit_config'].get('toolkit_name'),
|
1516
|
+
'llm_model': result.get('llm_model'),
|
1517
|
+
'llm_config': llm_config,
|
1518
|
+
'success': result['success'],
|
1519
|
+
'execution_time_seconds': execution_time,
|
1520
|
+
'execution_time_formatted': f"{execution_time:.3f}s",
|
1521
|
+
'events_count': len(result.get('events_dispatched', [])),
|
1522
|
+
'parameters_used': parameters
|
1523
|
+
}
|
1524
|
+
st.json(metadata)
|
1525
|
+
else:
|
1526
|
+
# Display error from the client method
|
1527
|
+
execution_time = result.get('execution_time_seconds', 0.0)
|
1528
|
+
st.error(f"❌ {result['error']} (after {execution_time:.3f}s)")
|
1264
1529
|
with st.expander("🔍 Error Details"):
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1530
|
+
error_details = {
|
1531
|
+
'error': result['error'],
|
1532
|
+
'tool_name': result['tool_name'],
|
1533
|
+
'toolkit_config': result['toolkit_config'],
|
1534
|
+
'llm_model': result.get('llm_model'),
|
1535
|
+
'llm_config': llm_config,
|
1536
|
+
'execution_time_seconds': execution_time,
|
1537
|
+
'execution_time_formatted': f"{execution_time:.3f}s",
|
1538
|
+
'events_dispatched': result.get('events_dispatched', [])
|
1539
|
+
}
|
1540
|
+
st.json(error_details)
|
1541
|
+
|
1542
|
+
except Exception as e:
|
1543
|
+
st.error(f"❌ Error executing function: {str(e)}")
|
1544
|
+
with st.expander("🔍 Error Details"):
|
1545
|
+
st.code(str(e))
|
1546
|
+
else:
|
1547
|
+
st.warning("⚠️ No functions available in this toolkit.")
|
1548
|
+
|
1549
|
+
except Exception as e:
|
1550
|
+
st.error(f"❌ Error loading toolkit functions: {str(e)}")
|
1551
|
+
with st.expander("🔍 Error Details"):
|
1552
|
+
st.code(str(e))
|
1273
1553
|
|
1274
1554
|
# Display current configuration
|
1275
1555
|
st.markdown("---")
|