alita-sdk 0.3.554__py3-none-any.whl → 0.3.603__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.
Potentially problematic release.
This version of alita-sdk might be problematic. Click here for more details.
- alita_sdk/cli/agent_executor.py +2 -1
- alita_sdk/cli/agent_loader.py +34 -4
- alita_sdk/cli/agents.py +433 -203
- alita_sdk/configurations/openapi.py +227 -15
- alita_sdk/runtime/clients/client.py +4 -2
- alita_sdk/runtime/langchain/_constants_bkup.py +1318 -0
- alita_sdk/runtime/langchain/assistant.py +61 -11
- alita_sdk/runtime/langchain/constants.py +419 -171
- alita_sdk/runtime/langchain/document_loaders/AlitaJSONLoader.py +4 -2
- alita_sdk/runtime/langchain/document_loaders/AlitaTextLoader.py +5 -2
- alita_sdk/runtime/langchain/langraph_agent.py +106 -21
- alita_sdk/runtime/langchain/utils.py +30 -14
- alita_sdk/runtime/toolkits/__init__.py +3 -0
- alita_sdk/runtime/toolkits/artifact.py +2 -1
- alita_sdk/runtime/toolkits/mcp.py +6 -3
- alita_sdk/runtime/toolkits/mcp_config.py +1048 -0
- alita_sdk/runtime/toolkits/skill_router.py +2 -2
- alita_sdk/runtime/toolkits/tools.py +64 -2
- alita_sdk/runtime/toolkits/vectorstore.py +1 -1
- alita_sdk/runtime/tools/artifact.py +15 -0
- alita_sdk/runtime/tools/data_analysis.py +183 -0
- alita_sdk/runtime/tools/llm.py +30 -11
- alita_sdk/runtime/tools/mcp_server_tool.py +6 -3
- alita_sdk/runtime/tools/router.py +2 -4
- alita_sdk/runtime/tools/sandbox.py +9 -6
- alita_sdk/runtime/utils/constants.py +5 -1
- alita_sdk/runtime/utils/mcp_client.py +1 -1
- alita_sdk/runtime/utils/mcp_sse_client.py +1 -1
- alita_sdk/runtime/utils/toolkit_utils.py +2 -0
- alita_sdk/tools/__init__.py +3 -1
- alita_sdk/tools/ado/repos/__init__.py +26 -8
- alita_sdk/tools/ado/repos/repos_wrapper.py +78 -52
- alita_sdk/tools/ado/test_plan/__init__.py +3 -2
- alita_sdk/tools/ado/test_plan/test_plan_wrapper.py +23 -1
- alita_sdk/tools/ado/utils.py +1 -18
- alita_sdk/tools/ado/wiki/__init__.py +2 -1
- alita_sdk/tools/ado/wiki/ado_wrapper.py +23 -1
- alita_sdk/tools/ado/work_item/__init__.py +3 -2
- alita_sdk/tools/ado/work_item/ado_wrapper.py +23 -1
- alita_sdk/tools/advanced_jira_mining/__init__.py +2 -1
- alita_sdk/tools/aws/delta_lake/__init__.py +2 -1
- alita_sdk/tools/azure_ai/search/__init__.py +2 -1
- alita_sdk/tools/azure_ai/search/api_wrapper.py +1 -1
- alita_sdk/tools/base_indexer_toolkit.py +15 -6
- alita_sdk/tools/bitbucket/__init__.py +2 -1
- alita_sdk/tools/bitbucket/api_wrapper.py +1 -1
- alita_sdk/tools/bitbucket/cloud_api_wrapper.py +3 -3
- alita_sdk/tools/browser/__init__.py +1 -1
- alita_sdk/tools/carrier/__init__.py +1 -1
- alita_sdk/tools/chunkers/code/treesitter/treesitter.py +37 -13
- alita_sdk/tools/cloud/aws/__init__.py +2 -1
- alita_sdk/tools/cloud/azure/__init__.py +2 -1
- alita_sdk/tools/cloud/gcp/__init__.py +2 -1
- alita_sdk/tools/cloud/k8s/__init__.py +2 -1
- alita_sdk/tools/code/linter/__init__.py +2 -1
- alita_sdk/tools/code/sonar/__init__.py +2 -1
- alita_sdk/tools/code_indexer_toolkit.py +19 -2
- alita_sdk/tools/confluence/__init__.py +7 -6
- alita_sdk/tools/confluence/api_wrapper.py +2 -2
- alita_sdk/tools/custom_open_api/__init__.py +2 -1
- alita_sdk/tools/elastic/__init__.py +2 -1
- alita_sdk/tools/elitea_base.py +28 -9
- alita_sdk/tools/figma/__init__.py +52 -6
- alita_sdk/tools/figma/api_wrapper.py +1158 -123
- alita_sdk/tools/figma/figma_client.py +73 -0
- alita_sdk/tools/figma/toon_tools.py +2748 -0
- alita_sdk/tools/github/__init__.py +2 -1
- alita_sdk/tools/github/github_client.py +69 -97
- alita_sdk/tools/github/schemas.py +4 -4
- alita_sdk/tools/gitlab/__init__.py +2 -1
- alita_sdk/tools/gitlab/api_wrapper.py +118 -38
- alita_sdk/tools/gitlab_org/__init__.py +2 -1
- alita_sdk/tools/gitlab_org/api_wrapper.py +60 -62
- alita_sdk/tools/google/bigquery/__init__.py +2 -1
- alita_sdk/tools/google_places/__init__.py +2 -1
- alita_sdk/tools/jira/__init__.py +2 -1
- alita_sdk/tools/keycloak/__init__.py +2 -1
- alita_sdk/tools/localgit/__init__.py +2 -1
- alita_sdk/tools/memory/__init__.py +1 -1
- alita_sdk/tools/ocr/__init__.py +2 -1
- alita_sdk/tools/openapi/__init__.py +227 -15
- alita_sdk/tools/openapi/api_wrapper.py +1287 -802
- alita_sdk/tools/pandas/__init__.py +11 -5
- alita_sdk/tools/pandas/api_wrapper.py +38 -25
- alita_sdk/tools/postman/__init__.py +2 -1
- alita_sdk/tools/pptx/__init__.py +2 -1
- alita_sdk/tools/qtest/__init__.py +21 -2
- alita_sdk/tools/qtest/api_wrapper.py +430 -13
- alita_sdk/tools/rally/__init__.py +2 -1
- alita_sdk/tools/rally/api_wrapper.py +1 -1
- alita_sdk/tools/report_portal/__init__.py +2 -1
- alita_sdk/tools/salesforce/__init__.py +2 -1
- alita_sdk/tools/servicenow/__init__.py +2 -1
- alita_sdk/tools/sharepoint/__init__.py +2 -1
- alita_sdk/tools/sharepoint/api_wrapper.py +2 -2
- alita_sdk/tools/slack/__init__.py +3 -2
- alita_sdk/tools/slack/api_wrapper.py +2 -2
- alita_sdk/tools/sql/__init__.py +3 -2
- alita_sdk/tools/testio/__init__.py +2 -1
- alita_sdk/tools/testrail/__init__.py +2 -1
- alita_sdk/tools/utils/content_parser.py +77 -3
- alita_sdk/tools/utils/text_operations.py +163 -71
- alita_sdk/tools/xray/__init__.py +3 -2
- alita_sdk/tools/yagmail/__init__.py +2 -1
- alita_sdk/tools/zephyr/__init__.py +2 -1
- alita_sdk/tools/zephyr_enterprise/__init__.py +2 -1
- alita_sdk/tools/zephyr_essential/__init__.py +2 -1
- alita_sdk/tools/zephyr_scale/__init__.py +3 -2
- alita_sdk/tools/zephyr_scale/api_wrapper.py +2 -2
- alita_sdk/tools/zephyr_squad/__init__.py +2 -1
- {alita_sdk-0.3.554.dist-info → alita_sdk-0.3.603.dist-info}/METADATA +7 -6
- {alita_sdk-0.3.554.dist-info → alita_sdk-0.3.603.dist-info}/RECORD +116 -111
- {alita_sdk-0.3.554.dist-info → alita_sdk-0.3.603.dist-info}/WHEEL +0 -0
- {alita_sdk-0.3.554.dist-info → alita_sdk-0.3.603.dist-info}/entry_points.txt +0 -0
- {alita_sdk-0.3.554.dist-info → alita_sdk-0.3.603.dist-info}/licenses/LICENSE +0 -0
- {alita_sdk-0.3.554.dist-info → alita_sdk-0.3.603.dist-info}/top_level.txt +0 -0
|
@@ -23,6 +23,7 @@ from langgraph.store.base import BaseStore
|
|
|
23
23
|
from .constants import PRINTER_NODE_RS, PRINTER, PRINTER_COMPLETED_STATE
|
|
24
24
|
from .mixedAgentRenderes import convert_message_to_json
|
|
25
25
|
from .utils import create_state, propagate_the_input_mapping, safe_format
|
|
26
|
+
from ..utils.constants import TOOLKIT_NAME_META, TOOL_NAME_META
|
|
26
27
|
from ..tools.function import FunctionTool
|
|
27
28
|
from ..tools.indexer_tool import IndexerNode
|
|
28
29
|
from ..tools.llm import LLMNode
|
|
@@ -188,7 +189,7 @@ Answer only with step name, no need to add descrip in case none of the steps are
|
|
|
188
189
|
decision_input = state.get('messages', [])[:]
|
|
189
190
|
else:
|
|
190
191
|
if len(additional_info) == 0:
|
|
191
|
-
additional_info = """###
|
|
192
|
+
additional_info = """### Additional info: """
|
|
192
193
|
additional_info += "{field}: {value}\n".format(field=field, value=state.get(field, ""))
|
|
193
194
|
decision_input.append(HumanMessage(
|
|
194
195
|
self.prompt.format(steps=self.steps, description=safe_format(self.description, state), additional_info=additional_info)))
|
|
@@ -447,6 +448,50 @@ def prepare_output_schema(lg_builder, memory, store, debug=False, interrupt_befo
|
|
|
447
448
|
return compiled
|
|
448
449
|
|
|
449
450
|
|
|
451
|
+
def find_tool_by_name_or_metadata(tools: list, tool_name: str, toolkit_name: Optional[str] = None) -> Optional[BaseTool]:
|
|
452
|
+
"""
|
|
453
|
+
Find a tool by name or by matching metadata (toolkit_name + tool_name).
|
|
454
|
+
|
|
455
|
+
For toolkit nodes with toolkit_name specified, this function checks:
|
|
456
|
+
1. Metadata match first (toolkit_name + tool_name) - PRIORITY when toolkit_name is provided
|
|
457
|
+
2. Direct tool name match (backward compatibility fallback)
|
|
458
|
+
|
|
459
|
+
For toolkit nodes without toolkit_name, or other node types:
|
|
460
|
+
1. Direct tool name match
|
|
461
|
+
|
|
462
|
+
Args:
|
|
463
|
+
tools: List of available tools
|
|
464
|
+
tool_name: The tool name to search for
|
|
465
|
+
toolkit_name: Optional toolkit name for metadata matching
|
|
466
|
+
|
|
467
|
+
Returns:
|
|
468
|
+
The matching tool or None if not found
|
|
469
|
+
"""
|
|
470
|
+
# When toolkit_name is specified, prioritize metadata matching
|
|
471
|
+
if toolkit_name:
|
|
472
|
+
for tool in tools:
|
|
473
|
+
# Check metadata match first
|
|
474
|
+
if hasattr(tool, 'metadata') and tool.metadata:
|
|
475
|
+
metadata_toolkit_name = tool.metadata.get(TOOLKIT_NAME_META)
|
|
476
|
+
metadata_tool_name = tool.metadata.get(TOOL_NAME_META)
|
|
477
|
+
|
|
478
|
+
# Match if both toolkit_name and tool_name in metadata match
|
|
479
|
+
if metadata_toolkit_name == toolkit_name and metadata_tool_name == tool_name:
|
|
480
|
+
return tool
|
|
481
|
+
|
|
482
|
+
# Fallback to direct name match for backward compatibility
|
|
483
|
+
for tool in tools:
|
|
484
|
+
if tool.name == tool_name:
|
|
485
|
+
return tool
|
|
486
|
+
else:
|
|
487
|
+
# No toolkit_name specified, use direct name match only
|
|
488
|
+
for tool in tools:
|
|
489
|
+
if tool.name == tool_name:
|
|
490
|
+
return tool
|
|
491
|
+
|
|
492
|
+
return None
|
|
493
|
+
|
|
494
|
+
|
|
450
495
|
def create_graph(
|
|
451
496
|
client: Any,
|
|
452
497
|
yaml_schema: str,
|
|
@@ -482,19 +527,37 @@ def create_graph(
|
|
|
482
527
|
node_type = node.get('type', 'function')
|
|
483
528
|
node_id = clean_string(node['id'])
|
|
484
529
|
toolkit_name = node.get('toolkit_name')
|
|
485
|
-
tool_name = clean_string(node.get('tool',
|
|
530
|
+
tool_name = clean_string(node.get('tool', ''))
|
|
486
531
|
# Tool names are now clean (no prefix needed)
|
|
487
532
|
logger.info(f"Node: {node_id} : {node_type} - {tool_name}")
|
|
488
533
|
if node_type in ['function', 'toolkit', 'mcp', 'tool', 'loop', 'loop_from_tool', 'indexer', 'subgraph', 'pipeline', 'agent']:
|
|
489
|
-
if node_type
|
|
490
|
-
#
|
|
491
|
-
raise ToolException(f"
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
534
|
+
if node_type in ['mcp', 'toolkit', 'agent'] and not tool_name:
|
|
535
|
+
# tool is not specified
|
|
536
|
+
raise ToolException(f"Tool name is required for {node_type} node with id '{node_id}'")
|
|
537
|
+
|
|
538
|
+
# Unified validation and tool finding for toolkit, mcp, and agent node types
|
|
539
|
+
matching_tool = None
|
|
540
|
+
if node_type in ['toolkit', 'mcp', 'agent']:
|
|
541
|
+
# Use enhanced validation that checks both direct name and metadata
|
|
542
|
+
matching_tool = find_tool_by_name_or_metadata(tools, tool_name, toolkit_name)
|
|
543
|
+
if not matching_tool:
|
|
544
|
+
# tool is not found in the provided tools
|
|
545
|
+
error_msg = f"Node `{node_id}` with type `{node_type}` has tool '{tool_name}'"
|
|
546
|
+
if toolkit_name:
|
|
547
|
+
error_msg += f" (toolkit: '{toolkit_name}')"
|
|
548
|
+
error_msg += f" which is not found in the provided tools. Make sure it is connected properly. Available tools: {format_tools(tools)}"
|
|
549
|
+
raise ToolException(error_msg)
|
|
550
|
+
else:
|
|
551
|
+
# For other node types, find tool by direct name match
|
|
552
|
+
for tool in tools:
|
|
553
|
+
if tool.name == tool_name:
|
|
554
|
+
matching_tool = tool
|
|
555
|
+
break
|
|
556
|
+
|
|
557
|
+
if matching_tool:
|
|
495
558
|
if node_type in ['function', 'toolkit', 'mcp']:
|
|
496
559
|
lg_builder.add_node(node_id, FunctionTool(
|
|
497
|
-
tool=
|
|
560
|
+
tool=matching_tool, name=node_id, return_type='dict',
|
|
498
561
|
output_variables=node.get('output', []),
|
|
499
562
|
input_mapping=node.get('input_mapping',
|
|
500
563
|
{'messages': {'type': 'variable', 'value': 'messages'}}),
|
|
@@ -505,7 +568,7 @@ def create_graph(
|
|
|
505
568
|
{'messages': {'type': 'variable', 'value': 'messages'}})
|
|
506
569
|
output_vars = node.get('output', [])
|
|
507
570
|
lg_builder.add_node(node_id, FunctionTool(
|
|
508
|
-
client=client, tool=
|
|
571
|
+
client=client, tool=matching_tool,
|
|
509
572
|
name=node_id, return_type='str',
|
|
510
573
|
output_variables=output_vars + ['messages'] if 'messages' not in output_vars else output_vars,
|
|
511
574
|
input_variables=input_params,
|
|
@@ -513,15 +576,15 @@ def create_graph(
|
|
|
513
576
|
))
|
|
514
577
|
elif node_type == 'subgraph' or node_type == 'pipeline':
|
|
515
578
|
# assign parent memory/store
|
|
516
|
-
#
|
|
517
|
-
#
|
|
579
|
+
# matching_tool.checkpointer = memory
|
|
580
|
+
# matching_tool.store = store
|
|
518
581
|
# wrap with mappings
|
|
519
582
|
pipeline_name = node.get('tool', None)
|
|
520
583
|
if not pipeline_name:
|
|
521
584
|
raise ValueError(
|
|
522
585
|
"Subgraph must have a 'tool' node: add required tool to the subgraph node")
|
|
523
586
|
node_fn = SubgraphRunnable(
|
|
524
|
-
inner=
|
|
587
|
+
inner=matching_tool.graph,
|
|
525
588
|
name=pipeline_name,
|
|
526
589
|
input_mapping=node.get('input_mapping', {}),
|
|
527
590
|
output_mapping=node.get('output_mapping', {}),
|
|
@@ -530,7 +593,7 @@ def create_graph(
|
|
|
530
593
|
break # skip legacy handling
|
|
531
594
|
elif node_type == 'tool':
|
|
532
595
|
lg_builder.add_node(node_id, ToolNode(
|
|
533
|
-
client=client, tool=
|
|
596
|
+
client=client, tool=matching_tool,
|
|
534
597
|
name=node_id, return_type='dict',
|
|
535
598
|
output_variables=node.get('output', []),
|
|
536
599
|
input_variables=node.get('input', ['messages']),
|
|
@@ -539,7 +602,7 @@ def create_graph(
|
|
|
539
602
|
))
|
|
540
603
|
elif node_type == 'loop':
|
|
541
604
|
lg_builder.add_node(node_id, LoopNode(
|
|
542
|
-
client=client, tool=
|
|
605
|
+
client=client, tool=matching_tool,
|
|
543
606
|
name=node_id, return_type='dict',
|
|
544
607
|
output_variables=node.get('output', []),
|
|
545
608
|
input_variables=node.get('input', ['messages']),
|
|
@@ -557,7 +620,7 @@ def create_graph(
|
|
|
557
620
|
lg_builder.add_node(node_id, LoopToolNode(
|
|
558
621
|
client=client,
|
|
559
622
|
name=node_id, return_type='dict',
|
|
560
|
-
tool=
|
|
623
|
+
tool=matching_tool, loop_tool=t,
|
|
561
624
|
variables_mapping=node.get('variables_mapping', {}),
|
|
562
625
|
output_variables=node.get('output', []),
|
|
563
626
|
input_variables=node.get('input', ['messages']),
|
|
@@ -573,7 +636,7 @@ def create_graph(
|
|
|
573
636
|
indexer_tool = t
|
|
574
637
|
logger.info(f"Indexer tool: {indexer_tool}")
|
|
575
638
|
lg_builder.add_node(node_id, IndexerNode(
|
|
576
|
-
client=client, tool=
|
|
639
|
+
client=client, tool=matching_tool,
|
|
577
640
|
index_tool=indexer_tool,
|
|
578
641
|
input_mapping=node.get('input_mapping', {}),
|
|
579
642
|
name=node_id, return_type='dict',
|
|
@@ -582,7 +645,6 @@ def create_graph(
|
|
|
582
645
|
output_variables=node.get('output', []),
|
|
583
646
|
input_variables=node.get('input', ['messages']),
|
|
584
647
|
structured_output=node.get('structured_output', False)))
|
|
585
|
-
break
|
|
586
648
|
elif node_type == 'code':
|
|
587
649
|
from ..tools.sandbox import create_sandbox_tool
|
|
588
650
|
sandbox_tool = create_sandbox_tool(stateful=False, allow_net=True,
|
|
@@ -651,10 +713,13 @@ def create_graph(
|
|
|
651
713
|
))
|
|
652
714
|
elif node_type == 'decision':
|
|
653
715
|
logger.info(f'Adding decision: {node["nodes"]}')
|
|
716
|
+
# fallback to old-style decision node
|
|
717
|
+
decisional_inputs = node.get('decisional_inputs')
|
|
718
|
+
decisional_inputs = node.get('input', ['messages']) if not decisional_inputs else decisional_inputs
|
|
654
719
|
lg_builder.add_node(node_id, DecisionEdge(
|
|
655
720
|
client, node['nodes'],
|
|
656
721
|
node.get('description', ""),
|
|
657
|
-
decisional_inputs=
|
|
722
|
+
decisional_inputs=decisional_inputs,
|
|
658
723
|
default_output=node.get('default_output', 'END'),
|
|
659
724
|
is_node=True
|
|
660
725
|
))
|
|
@@ -749,8 +814,20 @@ def create_graph(
|
|
|
749
814
|
debug=debug,
|
|
750
815
|
)
|
|
751
816
|
except ValueError as e:
|
|
752
|
-
|
|
753
|
-
|
|
817
|
+
# Build a clearer debug message without complex f-string expressions
|
|
818
|
+
debug_nodes = "\n*".join(lg_builder.nodes.keys()) if lg_builder and lg_builder.nodes else ""
|
|
819
|
+
debug_message = (
|
|
820
|
+
"Validation of the schema failed. {err}\n\n"
|
|
821
|
+
"DEBUG INFO:**Schema Nodes:**\n\n*{nodes}\n\n"
|
|
822
|
+
"**Schema Edges:**\n\n{edges}\n\n"
|
|
823
|
+
"**Tools Available:**\n\n{tools}"
|
|
824
|
+
).format(
|
|
825
|
+
err=e,
|
|
826
|
+
nodes=debug_nodes,
|
|
827
|
+
edges=lg_builder.edges if lg_builder else {},
|
|
828
|
+
tools=format_tools(tools),
|
|
829
|
+
)
|
|
830
|
+
raise ValueError(debug_message)
|
|
754
831
|
# If building a nested subgraph, return the raw CompiledStateGraph
|
|
755
832
|
if for_subgraph:
|
|
756
833
|
return graph
|
|
@@ -764,6 +841,14 @@ def create_graph(
|
|
|
764
841
|
)
|
|
765
842
|
return compiled.validate()
|
|
766
843
|
|
|
844
|
+
def format_tools(tools_list: list) -> str:
|
|
845
|
+
"""Format a list of tool names into a comma-separated string."""
|
|
846
|
+
try:
|
|
847
|
+
return ', '.join([tool.name for tool in tools_list])
|
|
848
|
+
except Exception as e:
|
|
849
|
+
logger.warning(f"Failed to format tools list: {e}")
|
|
850
|
+
return str(tools_list)
|
|
851
|
+
|
|
767
852
|
def set_defaults(d):
|
|
768
853
|
"""Set default values for dictionary entries based on their type."""
|
|
769
854
|
type_defaults = {
|
|
@@ -2,7 +2,7 @@ import builtins
|
|
|
2
2
|
import json
|
|
3
3
|
import logging
|
|
4
4
|
import re
|
|
5
|
-
from pydantic import create_model, Field,
|
|
5
|
+
from pydantic import create_model, Field, JsonValue
|
|
6
6
|
from typing import Tuple, TypedDict, Any, Optional, Annotated
|
|
7
7
|
from langchain_core.messages import AnyMessage
|
|
8
8
|
from langgraph.graph import add_messages
|
|
@@ -263,17 +263,33 @@ def create_pydantic_model(model_name: str, variables: dict[str, dict]):
|
|
|
263
263
|
return create_model(model_name, **fields)
|
|
264
264
|
|
|
265
265
|
def parse_pydantic_type(type_name: str):
|
|
266
|
-
""
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
266
|
+
t = (type_name or "any").strip().lower()
|
|
267
|
+
|
|
268
|
+
base = {
|
|
269
|
+
"str": str,
|
|
270
|
+
"int": int,
|
|
271
|
+
"float": float,
|
|
272
|
+
"bool": bool,
|
|
273
|
+
# "dict" means JSON object
|
|
274
|
+
"dict": dict[str, JsonValue],
|
|
275
|
+
# "list" means array of JSON values (or pick str if you want)
|
|
276
|
+
"list": list[JsonValue],
|
|
277
|
+
# IMPORTANT: don't return bare Any -> it produces {} schema
|
|
278
|
+
"any": JsonValue,
|
|
278
279
|
}
|
|
279
|
-
|
|
280
|
+
if t in base:
|
|
281
|
+
return base[t]
|
|
282
|
+
|
|
283
|
+
m = re.fullmatch(r"list\[(.+)\]", t)
|
|
284
|
+
if m:
|
|
285
|
+
return list[parse_pydantic_type(m.group(1))]
|
|
286
|
+
|
|
287
|
+
m = re.fullmatch(r"dict\[(.+?),(.+)\]", t)
|
|
288
|
+
if m:
|
|
289
|
+
k = parse_pydantic_type(m.group(1))
|
|
290
|
+
v = parse_pydantic_type(m.group(2))
|
|
291
|
+
# restrict keys to str for JSON objects
|
|
292
|
+
return dict[str, v] if k is not str else dict[str, v]
|
|
293
|
+
|
|
294
|
+
# fallback: avoid Any
|
|
295
|
+
return JsonValue
|
|
@@ -11,6 +11,7 @@ from .prompt import PromptToolkit
|
|
|
11
11
|
from .subgraph import SubgraphToolkit
|
|
12
12
|
from .vectorstore import VectorStoreToolkit
|
|
13
13
|
from .mcp import McpToolkit
|
|
14
|
+
from .mcp_config import McpConfigToolkit, get_session_manager as get_mcp_session_manager
|
|
14
15
|
from .skill_router import SkillRouterToolkit
|
|
15
16
|
from ...tools.memory import MemoryToolkit
|
|
16
17
|
|
|
@@ -23,6 +24,8 @@ __all__ = [
|
|
|
23
24
|
"SubgraphToolkit",
|
|
24
25
|
"VectorStoreToolkit",
|
|
25
26
|
"McpToolkit",
|
|
27
|
+
"McpConfigToolkit",
|
|
28
|
+
"get_mcp_session_manager",
|
|
26
29
|
"SkillRouterToolkit",
|
|
27
30
|
"MemoryToolkit"
|
|
28
31
|
]
|
|
@@ -7,6 +7,7 @@ from langchain_core.tools import BaseTool
|
|
|
7
7
|
from pydantic import create_model, BaseModel, ConfigDict, Field
|
|
8
8
|
from pydantic.fields import FieldInfo
|
|
9
9
|
from ..tools.artifact import ArtifactWrapper
|
|
10
|
+
from ..utils.constants import TOOLKIT_NAME_META, TOOLKIT_TYPE_META, TOOL_NAME_META
|
|
10
11
|
from ...tools.base.tool import BaseAction
|
|
11
12
|
from ...configurations.pgvector import PgVectorConfiguration
|
|
12
13
|
|
|
@@ -68,7 +69,7 @@ class ArtifactToolkit(BaseToolkit):
|
|
|
68
69
|
name=tool["name"],
|
|
69
70
|
description=description,
|
|
70
71
|
args_schema=tool["args_schema"],
|
|
71
|
-
metadata={
|
|
72
|
+
metadata={TOOLKIT_NAME_META: toolkit_name, TOOLKIT_TYPE_META: "artifact", TOOL_NAME_META: tool['name']} if toolkit_name else {}
|
|
72
73
|
))
|
|
73
74
|
return cls(tools=tools)
|
|
74
75
|
|
|
@@ -516,7 +516,8 @@ class McpToolkit(BaseToolkit):
|
|
|
516
516
|
is_prompt=is_prompt,
|
|
517
517
|
prompt_name=tool_dict.get("_mcp_prompt_name") if is_prompt else None,
|
|
518
518
|
original_tool_name=tool_name, # Store original name for MCP server invocation
|
|
519
|
-
session_id=session_id # Pass session ID for stateful SSE servers
|
|
519
|
+
session_id=session_id, # Pass session ID for stateful SSE servers
|
|
520
|
+
metadata={"toolkit_name": toolkit_name, "toolkit_type": "mcp"}
|
|
520
521
|
)
|
|
521
522
|
except Exception as e:
|
|
522
523
|
logger.error(f"Failed to create MCP tool '{tool_name}' from toolkit '{toolkit_name}': {e}")
|
|
@@ -615,7 +616,8 @@ class McpToolkit(BaseToolkit):
|
|
|
615
616
|
args_schema=McpServerTool.create_pydantic_model_from_schema(tool_metadata.input_schema),
|
|
616
617
|
client=client,
|
|
617
618
|
server=tool_metadata.server,
|
|
618
|
-
tool_timeout_sec=timeout
|
|
619
|
+
tool_timeout_sec=timeout,
|
|
620
|
+
metadata={"toolkit_name": toolkit_name, "toolkit_type": name}
|
|
619
621
|
)
|
|
620
622
|
except Exception as e:
|
|
621
623
|
logger.error(f"Failed to create MCP tool '{tool_name}' from server '{tool_metadata.server}': {e}")
|
|
@@ -649,7 +651,8 @@ class McpToolkit(BaseToolkit):
|
|
|
649
651
|
),
|
|
650
652
|
client=client,
|
|
651
653
|
server=toolkit_name,
|
|
652
|
-
tool_timeout_sec=timeout
|
|
654
|
+
tool_timeout_sec=timeout,
|
|
655
|
+
metadata={"toolkit_name": toolkit_name, "toolkit_type": name}
|
|
653
656
|
)
|
|
654
657
|
except Exception as e:
|
|
655
658
|
logger.error(f"Failed to create MCP tool '{tool_name}' from toolkit '{toolkit_name}': {e}")
|