ibm-watsonx-orchestrate 1.12.0b1__py3-none-any.whl → 1.12.1__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.
- ibm_watsonx_orchestrate/__init__.py +2 -1
- ibm_watsonx_orchestrate/agent_builder/tools/langflow_tool.py +61 -1
- ibm_watsonx_orchestrate/cli/commands/environment/environment_command.py +5 -1
- ibm_watsonx_orchestrate/cli/commands/environment/environment_controller.py +6 -3
- ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_command.py +3 -2
- ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_controller.py +1 -1
- ibm_watsonx_orchestrate/cli/commands/partners/offering/partners_offering_controller.py +21 -4
- ibm_watsonx_orchestrate/cli/commands/partners/offering/types.py +7 -15
- ibm_watsonx_orchestrate/cli/commands/tools/tools_controller.py +37 -8
- ibm_watsonx_orchestrate/cli/config.py +3 -1
- ibm_watsonx_orchestrate/docker/default.env +8 -8
- ibm_watsonx_orchestrate/flow_builder/flows/decorators.py +2 -0
- ibm_watsonx_orchestrate/flow_builder/flows/flow.py +40 -2
- ibm_watsonx_orchestrate/flow_builder/node.py +13 -1
- ibm_watsonx_orchestrate/flow_builder/types.py +18 -0
- ibm_watsonx_orchestrate/langflow/__init__.py +0 -0
- ibm_watsonx_orchestrate/langflow/langflow_utils.py +195 -0
- ibm_watsonx_orchestrate/langflow/lfx_deps.py +84 -0
- ibm_watsonx_orchestrate/utils/utils.py +6 -2
- {ibm_watsonx_orchestrate-1.12.0b1.dist-info → ibm_watsonx_orchestrate-1.12.1.dist-info}/METADATA +2 -2
- {ibm_watsonx_orchestrate-1.12.0b1.dist-info → ibm_watsonx_orchestrate-1.12.1.dist-info}/RECORD +24 -21
- {ibm_watsonx_orchestrate-1.12.0b1.dist-info → ibm_watsonx_orchestrate-1.12.1.dist-info}/WHEEL +0 -0
- {ibm_watsonx_orchestrate-1.12.0b1.dist-info → ibm_watsonx_orchestrate-1.12.1.dist-info}/entry_points.txt +0 -0
- {ibm_watsonx_orchestrate-1.12.0b1.dist-info → ibm_watsonx_orchestrate-1.12.1.dist-info}/licenses/LICENSE +0 -0
@@ -2,8 +2,10 @@ import json
|
|
2
2
|
import re
|
3
3
|
|
4
4
|
from pydantic import BaseModel
|
5
|
+
import rich
|
5
6
|
|
6
7
|
from ibm_watsonx_orchestrate.agent_builder.connections.types import ConnectionSecurityScheme
|
8
|
+
from ibm_watsonx_orchestrate.langflow.langflow_utils import parse_langflow_model
|
7
9
|
from .base_tool import BaseTool
|
8
10
|
from .types import LangflowToolBinding, ToolBinding, ToolPermission, ToolRequestBody, ToolResponseBody, ToolSpec
|
9
11
|
from ibm_watsonx_orchestrate.utils.exceptions import BadRequest
|
@@ -14,6 +16,9 @@ LANGFLOW_CHAT_OUTPUT_LABEL = "ChatOutput"
|
|
14
16
|
VALID_NAME_PATTERN = re.compile("^[a-zA-Z](\\w|_)+$")
|
15
17
|
|
16
18
|
class LangflowTool(BaseTool):
|
19
|
+
# additional python module requirements for langflow based tools
|
20
|
+
requirements: list[str] = []
|
21
|
+
|
17
22
|
def __init__(self,spec: ToolSpec):
|
18
23
|
BaseTool.__init__(self,spec=spec)
|
19
24
|
|
@@ -103,6 +108,59 @@ def create_langflow_tool(
|
|
103
108
|
if not validate_langflow_version(langflow_version):
|
104
109
|
raise ValueError(f"Langflow version is below minimum requirements, found '{langflow_version}', miniumum required version '{'.'.join(map(str,MIN_LANGFLOW_VERSION))}'")
|
105
110
|
|
111
|
+
# find all the component in Langflow and display its credential
|
112
|
+
langflow_spec = parse_langflow_model(tool_definition)
|
113
|
+
if langflow_spec:
|
114
|
+
rich.print(f"[bold white]Langflow version used: {langflow_version}[/bold white]")
|
115
|
+
rich.print("Please ensure this flow is compatible with the Langflow version bundled in ADK.")
|
116
|
+
rich.print("\nLangflow components:")
|
117
|
+
|
118
|
+
table = rich.table.Table(show_header=True, header_style="bold white", show_lines=True)
|
119
|
+
column_args = {
|
120
|
+
"ID": {},
|
121
|
+
"Name": {},
|
122
|
+
"Credentials": {},
|
123
|
+
"Requirements": {}
|
124
|
+
}
|
125
|
+
for column in column_args:
|
126
|
+
table.add_column(column,**column_args[column])
|
127
|
+
|
128
|
+
requirements = set()
|
129
|
+
api_key_not_set = False
|
130
|
+
for component in langflow_spec.components:
|
131
|
+
if component.credentials and len(component.credentials) > 0:
|
132
|
+
# create a command separated list with newline
|
133
|
+
component_creds = None
|
134
|
+
for k, v in component.credentials.items():
|
135
|
+
if v is None or v == "":
|
136
|
+
v = 'NOT SET'
|
137
|
+
api_key_not_set = True
|
138
|
+
if component_creds is None:
|
139
|
+
component_creds = f"{k} {v}"
|
140
|
+
else:
|
141
|
+
component_creds += "\n" + f"{k} {v}"
|
142
|
+
else:
|
143
|
+
component_creds = "N/A"
|
144
|
+
|
145
|
+
if component.requirements and len(component.requirements) > 0:
|
146
|
+
# create a command separated list with newline
|
147
|
+
component_req = "\n".join([f"{k}" for k in component.requirements])
|
148
|
+
for r in component.requirements:
|
149
|
+
requirements.add(r)
|
150
|
+
else:
|
151
|
+
component_req = "N/A"
|
152
|
+
table.add_row(component.id,component.name,component_creds,component_req)
|
153
|
+
rich.print(table)
|
154
|
+
|
155
|
+
rich.print("[bold yellow]Tip:[/bold yellow] Langflow tool might require additional python modules. Identified requirements will be added.")
|
156
|
+
rich.print("[bold yellow]Tip:[/bold yellow] Avoid hardcoding sensitive values. Use Orchestrate connections to manage secrets securely.")
|
157
|
+
if api_key_not_set:
|
158
|
+
rich.print("[bold yellow]Warning:[/bold yellow] Some required api key(s) were not set in the flow. Please adjust the flow to include them.")
|
159
|
+
rich.print("Ensure each credential follows the <app-id>_<variable> naming convention within the Langflow model.")
|
160
|
+
|
161
|
+
for connection in connections:
|
162
|
+
rich.print(f"* Connection: {connection} → Suggested naming: {connection}_<variable>")
|
163
|
+
|
106
164
|
spec = ToolSpec(
|
107
165
|
name=name,
|
108
166
|
description=description,
|
@@ -121,4 +179,6 @@ def create_langflow_tool(
|
|
121
179
|
)
|
122
180
|
)
|
123
181
|
|
124
|
-
|
182
|
+
tool = LangflowTool(spec=spec)
|
183
|
+
tool.requirements = requirements
|
184
|
+
return tool
|
@@ -43,9 +43,13 @@ def activate_env(
|
|
43
43
|
test_package_version_override: Annotated[
|
44
44
|
str,
|
45
45
|
typer.Option("--test-package-version-override", help="Which prereleased package version to reference when using --registry testpypi", hidden=True),
|
46
|
+
] = None,
|
47
|
+
skip_version_check: Annotated[
|
48
|
+
bool,
|
49
|
+
typer.Option('--skip-version-check/--enable-version-check', help='Use this flag to skip validating that adk version in use exists in pypi (for clients who mirror the ADK to a local registry and do not have local access to pypi).')
|
46
50
|
] = None
|
47
51
|
):
|
48
|
-
environment_controller.activate(name=name, apikey=apikey,username=username, password=password, registry=registry, test_package_version_override=test_package_version_override)
|
52
|
+
environment_controller.activate(name=name, apikey=apikey, username=username, password=password, registry=registry, test_package_version_override=test_package_version_override, skip_version_check=skip_version_check)
|
49
53
|
|
50
54
|
|
51
55
|
@environment_app.command(name="add")
|
@@ -18,8 +18,9 @@ from ibm_watsonx_orchestrate.cli.config import (
|
|
18
18
|
ENV_IAM_URL_OPT,
|
19
19
|
ENVIRONMENTS_SECTION_HEADER,
|
20
20
|
PROTECTED_ENV_NAME,
|
21
|
-
ENV_AUTH_TYPE, PYTHON_REGISTRY_HEADER, PYTHON_REGISTRY_TYPE_OPT, PYTHON_REGISTRY_TEST_PACKAGE_VERSION_OVERRIDE_OPT,
|
22
|
-
|
21
|
+
ENV_AUTH_TYPE, PYTHON_REGISTRY_HEADER, PYTHON_REGISTRY_TYPE_OPT, PYTHON_REGISTRY_TEST_PACKAGE_VERSION_OVERRIDE_OPT,
|
22
|
+
BYPASS_SSL, VERIFY,
|
23
|
+
DEFAULT_CONFIG_FILE_CONTENT, PYTHON_REGISTRY_SKIP_VERSION_CHECK_OPT
|
23
24
|
)
|
24
25
|
from ibm_watsonx_orchestrate.client.client import Client
|
25
26
|
from ibm_watsonx_orchestrate.client.client_errors import ClientError
|
@@ -131,7 +132,7 @@ def _login(name: str, apikey: str = None, username: str = None, password: str =
|
|
131
132
|
except ClientError as e:
|
132
133
|
raise ClientError(e)
|
133
134
|
|
134
|
-
def activate(name: str, apikey: str=None, username: str=None, password: str=None, registry: RegistryType=None, test_package_version_override=None) -> None:
|
135
|
+
def activate(name: str, apikey: str=None, username: str=None, password: str=None, registry: RegistryType=None, test_package_version_override=None, skip_version_check=None) -> None:
|
135
136
|
cfg = Config()
|
136
137
|
auth_cfg = Config(AUTH_CONFIG_FILE_FOLDER, AUTH_CONFIG_FILE)
|
137
138
|
env_cfg = cfg.read(ENVIRONMENTS_SECTION_HEADER, name)
|
@@ -159,6 +160,8 @@ def activate(name: str, apikey: str=None, username: str=None, password: str=None
|
|
159
160
|
elif cfg.read(PYTHON_REGISTRY_HEADER, PYTHON_REGISTRY_TYPE_OPT) is None:
|
160
161
|
cfg.write(PYTHON_REGISTRY_HEADER, PYTHON_REGISTRY_TYPE_OPT, DEFAULT_CONFIG_FILE_CONTENT[PYTHON_REGISTRY_HEADER][PYTHON_REGISTRY_TYPE_OPT])
|
161
162
|
cfg.write(PYTHON_REGISTRY_HEADER, PYTHON_REGISTRY_TEST_PACKAGE_VERSION_OVERRIDE_OPT, test_package_version_override)
|
163
|
+
if skip_version_check is not None:
|
164
|
+
cfg.write(PYTHON_REGISTRY_HEADER, PYTHON_REGISTRY_SKIP_VERSION_CHECK_OPT, skip_version_check)
|
162
165
|
|
163
166
|
logger.info(f"Environment '{name}' is now active")
|
164
167
|
is_cpd = is_cpd_env(url)
|
@@ -54,7 +54,8 @@ def read_env_file(env_path: Path|str) -> dict:
|
|
54
54
|
def validate_watsonx_credentials(user_env_file: str) -> bool:
|
55
55
|
required_sets = [
|
56
56
|
["WATSONX_SPACE_ID", "WATSONX_APIKEY"],
|
57
|
-
["WO_INSTANCE", "WO_API_KEY"]
|
57
|
+
["WO_INSTANCE", "WO_API_KEY"],
|
58
|
+
["WO_INSTANCE", "WO_PASSWORD", "WO_USERNAME"]
|
58
59
|
]
|
59
60
|
|
60
61
|
def has_valid_keys(env: dict) -> bool:
|
@@ -75,7 +76,7 @@ def validate_watsonx_credentials(user_env_file: str) -> bool:
|
|
75
76
|
user_env = read_env_file(user_env_file)
|
76
77
|
|
77
78
|
if not has_valid_keys(user_env):
|
78
|
-
logger.error("Error: The environment file does not contain the required keys: either WATSONX_SPACE_ID and WATSONX_APIKEY or WO_INSTANCE and WO_API_KEY.")
|
79
|
+
logger.error("Error: The environment file does not contain the required keys: either WATSONX_SPACE_ID and WATSONX_APIKEY or WO_INSTANCE and WO_API_KEY or WO_INSTANCE and WO_USERNAME and WO_PASSWORD.")
|
79
80
|
sys.exit(1)
|
80
81
|
|
81
82
|
# Update os.environ with whichever set is present
|
@@ -52,7 +52,7 @@ class EvaluationsController:
|
|
52
52
|
|
53
53
|
if "WATSONX_SPACE_ID" in os.environ and "WATSONX_APIKEY" in os.environ:
|
54
54
|
provider = "watsonx"
|
55
|
-
elif "WO_INSTANCE" in os.environ and "WO_API_KEY" in os.environ:
|
55
|
+
elif "WO_INSTANCE" in os.environ and ("WO_API_KEY" in os.environ or "WO_PASSWORD" in os.environ):
|
56
56
|
provider = "model_proxy"
|
57
57
|
else:
|
58
58
|
logger.error(
|
@@ -23,6 +23,7 @@ from ibm_watsonx_orchestrate.client.connections import get_connections_client
|
|
23
23
|
from ibm_watsonx_orchestrate.agent_builder.connections.types import ConnectionEnvironment
|
24
24
|
from ibm_watsonx_orchestrate.cli.commands.connections.connections_controller import export_connection
|
25
25
|
from ibm_watsonx_orchestrate.cli.commands.tools.tools_controller import ToolsController
|
26
|
+
from ibm_watsonx_orchestrate.utils.utils import sanitize_catalog_label
|
26
27
|
from .types import *
|
27
28
|
|
28
29
|
APPLICATIONS_FILE_VERSION = '1.16.0'
|
@@ -54,7 +55,7 @@ def get_tool_bindings(tool_names: list[str]) -> dict[str, dict]:
|
|
54
55
|
|
55
56
|
return results
|
56
57
|
|
57
|
-
def _patch_agent_yamls(project_root: Path, publisher_name: str):
|
58
|
+
def _patch_agent_yamls(project_root: Path, publisher_name: str, parent_agent_name: str):
|
58
59
|
agents_dir = project_root / "agents"
|
59
60
|
if not agents_dir.exists():
|
60
61
|
return
|
@@ -70,15 +71,18 @@ def _patch_agent_yamls(project_root: Path, publisher_name: str):
|
|
70
71
|
if "language_support" not in agent_data:
|
71
72
|
agent_data["language_support"] = ["English"]
|
72
73
|
if "icon" not in agent_data:
|
73
|
-
agent_data["icon"] =
|
74
|
+
agent_data["icon"] = AGENT_CATALOG_ONLY_PLACEHOLDERS['icon']
|
74
75
|
if "category" not in agent_data:
|
75
76
|
agent_data["category"] = "agent"
|
76
77
|
if "supported_apps" not in agent_data:
|
77
78
|
agent_data["supported_apps"] = []
|
79
|
+
if "agent_role" not in agent_data:
|
80
|
+
agent_data["agent_role"] = "manager" if agent_data.get("name") == parent_agent_name else "collaborator"
|
78
81
|
|
79
82
|
with open(agent_yaml, "w") as f:
|
80
83
|
yaml.safe_dump(agent_data, f, sort_keys=False)
|
81
84
|
|
85
|
+
|
82
86
|
def _create_applications_entry(connection_config: dict) -> dict:
|
83
87
|
return {
|
84
88
|
'app_id': connection_config.get('app_id'),
|
@@ -116,6 +120,15 @@ class PartnersOfferingController:
|
|
116
120
|
sys.exit(1)
|
117
121
|
|
118
122
|
def create(self, offering: str, publisher_name: str, agent_type: str, agent_name: str):
|
123
|
+
|
124
|
+
# Sanitize offering name
|
125
|
+
original_offering = offering
|
126
|
+
offering = sanitize_catalog_label(offering)
|
127
|
+
|
128
|
+
if offering != original_offering:
|
129
|
+
logger.warning("Offering name must contain only alpahnumeric characters or underscore")
|
130
|
+
logger.info(f"Offering '{original_offering}' has been updated to '{offering}'")
|
131
|
+
|
119
132
|
# Create parent project folder
|
120
133
|
project_root = self.root / offering
|
121
134
|
|
@@ -179,7 +192,7 @@ class PartnersOfferingController:
|
|
179
192
|
output_zip.unlink(missing_ok=True)
|
180
193
|
|
181
194
|
# Patch the agent yamls with publisher, tags, icon, etc.
|
182
|
-
_patch_agent_yamls(project_root, publisher_name)
|
195
|
+
_patch_agent_yamls(project_root=project_root, publisher_name=publisher_name, parent_agent_name=agent_name)
|
183
196
|
|
184
197
|
|
185
198
|
# Create offering.yaml file -------------------------------------------------------
|
@@ -337,12 +350,16 @@ class PartnersOfferingController:
|
|
337
350
|
**agent_data
|
338
351
|
)
|
339
352
|
agent = Agent.model_validate(agent_details)
|
340
|
-
AgentsController().persist_record(agent=agent)
|
341
353
|
case AgentKind.EXTERNAL:
|
342
354
|
agent_details = parse_create_external_args(
|
343
355
|
**agent_data
|
344
356
|
)
|
345
357
|
agent = ExternalAgent.model_validate(agent_details)
|
358
|
+
|
359
|
+
# Placeholder detection
|
360
|
+
for label,placeholder in AGENT_CATALOG_ONLY_PLACEHOLDERS.items():
|
361
|
+
if agent_data.get(label) == placeholder:
|
362
|
+
logger.warning(f"Placeholder '{label}' detected for agent '{agent_name}', please ensure '{label}' is correct before packaging.")
|
346
363
|
|
347
364
|
agent_json_path = f"{top_level_folder}/agents/{agent_name}/config.json"
|
348
365
|
zf.writestr(agent_json_path, json.dumps(agent_data, indent=2))
|
@@ -24,6 +24,10 @@ CATALOG_ONLY_FIELDS = [
|
|
24
24
|
'supported_apps'
|
25
25
|
]
|
26
26
|
|
27
|
+
AGENT_CATALOG_ONLY_PLACEHOLDERS = {
|
28
|
+
'icon': "inline-svg-of-icon",
|
29
|
+
}
|
30
|
+
|
27
31
|
class AgentKind(str, Enum):
|
28
32
|
NATIVE = "native"
|
29
33
|
EXTERNAL = "external"
|
@@ -87,21 +91,9 @@ class Offering(BaseModel):
|
|
87
91
|
return values
|
88
92
|
|
89
93
|
def validate_ready_for_packaging(self):
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
placholders = False
|
94
|
-
# part numbers
|
95
|
-
if not self.part_number:
|
96
|
-
raise ValueError(f"Offering '{self.name}' does not have valid part numbers")
|
97
|
-
|
98
|
-
for (k,v) in self.part_number.model_dump().items():
|
99
|
-
if v == CATALOG_PLACEHOLDERS['part_number']:
|
100
|
-
logger.warning(f"Placeholder part number detected for platform '{k}', please ensure valid part numbers are entered before packaging.")
|
101
|
-
placholders = True
|
102
|
-
|
103
|
-
if placholders:
|
104
|
-
raise ValueError(f"Offering '{self.name}' cannot be packaged with placeholder values")
|
94
|
+
# Leaving this fn here in case we want to reintroduce validation
|
95
|
+
pass
|
96
|
+
|
105
97
|
|
106
98
|
|
107
99
|
|
@@ -11,7 +11,7 @@ import zipfile
|
|
11
11
|
from enum import Enum
|
12
12
|
from os import path
|
13
13
|
from pathlib import Path
|
14
|
-
from typing import Iterable, List
|
14
|
+
from typing import Iterable, List, cast
|
15
15
|
import rich
|
16
16
|
import json
|
17
17
|
from rich.json import JSON
|
@@ -25,7 +25,7 @@ from rich.panel import Panel
|
|
25
25
|
|
26
26
|
from ibm_watsonx_orchestrate.agent_builder.tools import BaseTool, ToolSpec
|
27
27
|
from ibm_watsonx_orchestrate.agent_builder.tools.flow_tool import create_flow_json_tool
|
28
|
-
from ibm_watsonx_orchestrate.agent_builder.tools.langflow_tool import create_langflow_tool
|
28
|
+
from ibm_watsonx_orchestrate.agent_builder.tools.langflow_tool import LangflowTool, create_langflow_tool
|
29
29
|
from ibm_watsonx_orchestrate.agent_builder.tools.openapi_tool import create_openapi_json_tools_from_uri,create_openapi_json_tools_from_content
|
30
30
|
from ibm_watsonx_orchestrate.cli.commands.models.models_controller import ModelHighlighter
|
31
31
|
from ibm_watsonx_orchestrate.cli.commands.tools.types import RegistryType
|
@@ -33,7 +33,7 @@ from ibm_watsonx_orchestrate.cli.commands.connections.connections_controller imp
|
|
33
33
|
from ibm_watsonx_orchestrate.agent_builder.connections.types import ConnectionType, ConnectionEnvironment, ConnectionPreference
|
34
34
|
from ibm_watsonx_orchestrate.cli.config import Config, CONTEXT_SECTION_HEADER, CONTEXT_ACTIVE_ENV_OPT, \
|
35
35
|
PYTHON_REGISTRY_HEADER, PYTHON_REGISTRY_TYPE_OPT, PYTHON_REGISTRY_TEST_PACKAGE_VERSION_OVERRIDE_OPT, \
|
36
|
-
DEFAULT_CONFIG_FILE_CONTENT
|
36
|
+
DEFAULT_CONFIG_FILE_CONTENT, PYTHON_REGISTRY_SKIP_VERSION_CHECK_OPT
|
37
37
|
from ibm_watsonx_orchestrate.agent_builder.connections import ConnectionSecurityScheme, ExpectedCredentials
|
38
38
|
from ibm_watsonx_orchestrate.flow_builder.flows.decorators import FlowWrapper
|
39
39
|
from ibm_watsonx_orchestrate.client.tools.tool_client import ToolClient
|
@@ -56,6 +56,11 @@ DEFAULT_LANGFLOW_TOOL_REQUIREMENTS = [
|
|
56
56
|
"lfx==0.1.8"
|
57
57
|
]
|
58
58
|
|
59
|
+
DEFAULT_LANGFLOW_RUNNER_MODULES = [
|
60
|
+
"lfx",
|
61
|
+
"lfx-nightly"
|
62
|
+
]
|
63
|
+
|
59
64
|
class ToolKind(str, Enum):
|
60
65
|
openapi = "openapi"
|
61
66
|
python = "python"
|
@@ -851,15 +856,18 @@ class ToolsController:
|
|
851
856
|
|
852
857
|
cfg = Config()
|
853
858
|
registry_type = cfg.read(PYTHON_REGISTRY_HEADER, PYTHON_REGISTRY_TYPE_OPT) or DEFAULT_CONFIG_FILE_CONTENT[PYTHON_REGISTRY_HEADER][PYTHON_REGISTRY_TYPE_OPT]
|
859
|
+
skip_version_check = cfg.read(PYTHON_REGISTRY_HEADER, PYTHON_REGISTRY_SKIP_VERSION_CHECK_OPT) or DEFAULT_CONFIG_FILE_CONTENT[PYTHON_REGISTRY_HEADER][PYTHON_REGISTRY_SKIP_VERSION_CHECK_OPT]
|
854
860
|
|
855
861
|
version = __version__
|
856
862
|
if registry_type == RegistryType.LOCAL:
|
863
|
+
logger.warning(f"Using a local registry which is for development purposes only")
|
857
864
|
requirements.append(f"/packages/ibm_watsonx_orchestrate-0.6.0-py3-none-any.whl\n")
|
858
865
|
elif registry_type == RegistryType.PYPI:
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
866
|
+
if not skip_version_check:
|
867
|
+
wheel_file = get_whl_in_registry(registry_url='https://pypi.org/simple/ibm-watsonx-orchestrate', version=version)
|
868
|
+
if not wheel_file:
|
869
|
+
logger.error(f"Could not find ibm-watsonx-orchestrate@{version} on https://pypi.org/project/ibm-watsonx-orchestrate")
|
870
|
+
exit(1)
|
863
871
|
requirements.append(f"ibm-watsonx-orchestrate=={version}\n")
|
864
872
|
elif registry_type == RegistryType.TESTPYPI:
|
865
873
|
override_version = cfg.get(PYTHON_REGISTRY_HEADER, PYTHON_REGISTRY_TEST_PACKAGE_VERSION_OVERRIDE_OPT) or version
|
@@ -890,13 +898,34 @@ class ToolsController:
|
|
890
898
|
tool_path = Path(self.file)
|
891
899
|
zip_tool_artifacts.write(tool_path, arcname=f"{tool_path.stem}.json")
|
892
900
|
|
893
|
-
requirements =
|
901
|
+
requirements = []
|
894
902
|
|
895
903
|
if self.requirements_file:
|
896
904
|
requirements_file_path = Path(self.requirements_file)
|
897
905
|
requirements.extend(
|
898
906
|
get_requirement_lines(requirements_file=requirements_file_path, remove_trailing_newlines=False)
|
899
907
|
)
|
908
|
+
|
909
|
+
langflowTool = cast(LangflowTool, tool)
|
910
|
+
# if there are additional requriements from the langflow model, we should add it to the requirement set
|
911
|
+
if langflowTool.requirements and len(langflowTool.requirements) > 0:
|
912
|
+
requirements.extend(langflowTool.requirements)
|
913
|
+
|
914
|
+
# now check if the requirements contain modules listed in DEFAULT_LANGFLOW_RUNNER_MODULES
|
915
|
+
# if it is needed, we are assuming the user wants to override the default langflow module
|
916
|
+
# with a specific version
|
917
|
+
runner_overridden = False
|
918
|
+
for r in requirements:
|
919
|
+
# get the module name from the requirements
|
920
|
+
module_name = r.strip().split('==')[0].split('=')[0].split('>=')[0].split('<=')[0].split('~=')[0].lower()
|
921
|
+
if not module_name.startswith('#'):
|
922
|
+
if module_name in DEFAULT_LANGFLOW_RUNNER_MODULES:
|
923
|
+
runner_overridden = True
|
924
|
+
|
925
|
+
if not runner_overridden:
|
926
|
+
# add the default runner to the top of requirement list
|
927
|
+
requirements = DEFAULT_LANGFLOW_TOOL_REQUIREMENTS + list(requirements)
|
928
|
+
|
900
929
|
requirements_content = '\n'.join(requirements) + '\n'
|
901
930
|
zip_tool_artifacts.writestr("requirements.txt",requirements_content)
|
902
931
|
zip_tool_artifacts.writestr("bundle-format", "2.0.0\n")
|
@@ -22,6 +22,7 @@ AUTH_MCSP_TOKEN_OPT = "wxo_mcsp_token"
|
|
22
22
|
AUTH_MCSP_TOKEN_EXPIRY_OPT = "wxo_mcsp_token_expiry"
|
23
23
|
CONTEXT_ACTIVE_ENV_OPT = "active_environment"
|
24
24
|
PYTHON_REGISTRY_TYPE_OPT = "type"
|
25
|
+
PYTHON_REGISTRY_SKIP_VERSION_CHECK_OPT = "skip_version_check"
|
25
26
|
PYTHON_REGISTRY_TEST_PACKAGE_VERSION_OVERRIDE_OPT = "test_package_version_override"
|
26
27
|
ENV_WXO_URL_OPT = "wxo_url"
|
27
28
|
ENV_IAM_URL_OPT = "iam_url"
|
@@ -40,7 +41,8 @@ DEFAULT_CONFIG_FILE_CONTENT = {
|
|
40
41
|
CONTEXT_SECTION_HEADER: {CONTEXT_ACTIVE_ENV_OPT: None},
|
41
42
|
PYTHON_REGISTRY_HEADER: {
|
42
43
|
PYTHON_REGISTRY_TYPE_OPT: str(RegistryType.PYPI),
|
43
|
-
PYTHON_REGISTRY_TEST_PACKAGE_VERSION_OVERRIDE_OPT: None
|
44
|
+
PYTHON_REGISTRY_TEST_PACKAGE_VERSION_OVERRIDE_OPT: None,
|
45
|
+
PYTHON_REGISTRY_SKIP_VERSION_CHECK_OPT: False
|
44
46
|
},
|
45
47
|
ENVIRONMENTS_SECTION_HEADER: {
|
46
48
|
PROTECTED_ENV_NAME: {
|
@@ -58,16 +58,16 @@ REGISTRY_URL=
|
|
58
58
|
|
59
59
|
|
60
60
|
|
61
|
-
SERVER_TAG=
|
61
|
+
SERVER_TAG=24-09-2025-17d7c67
|
62
62
|
SERVER_REGISTRY=
|
63
63
|
|
64
|
-
WORKER_TAG=
|
64
|
+
WORKER_TAG=24-09-2025-17d7c67
|
65
65
|
WORKER_REGISTRY=
|
66
66
|
|
67
67
|
AI_GATEWAY_TAG=20-08-2025-9ed6d40
|
68
68
|
AI_GATEWAY_REGISTRY=
|
69
69
|
|
70
|
-
AGENT_GATEWAY_TAG=
|
70
|
+
AGENT_GATEWAY_TAG=19-10-2025-e48ad3a
|
71
71
|
AGENT_GATEWAY_REGISTRY=
|
72
72
|
|
73
73
|
DB_REGISTRY=
|
@@ -78,7 +78,7 @@ AMDDBTAG=17-09-2025-8a9aff2
|
|
78
78
|
ARM64DBTAG=17-09-2025-8a9aff2
|
79
79
|
|
80
80
|
UI_REGISTRY=
|
81
|
-
UITAG=
|
81
|
+
UITAG=22-09-2025-e35f498
|
82
82
|
|
83
83
|
CM_REGISTRY=
|
84
84
|
CM_TAG=16-09-2025-e33b344
|
@@ -86,16 +86,16 @@ CM_TAG=16-09-2025-e33b344
|
|
86
86
|
CONNECTIONS_UI_REGISTRY=
|
87
87
|
CONNECTIONS_UI_TAG=15-09-2025-98aa9da
|
88
88
|
|
89
|
-
TRM_TAG=
|
89
|
+
TRM_TAG=16-09-2025-cb6b9df
|
90
90
|
TRM_REGISTRY=
|
91
91
|
|
92
|
-
TR_TAG=
|
92
|
+
TR_TAG=24-09-2025-a515038
|
93
93
|
TR_REGISTRY=
|
94
94
|
|
95
|
-
BUILDER_TAG=
|
95
|
+
BUILDER_TAG=24-09-2025-f9b68d8
|
96
96
|
BUILDER_REGISTRY=
|
97
97
|
|
98
|
-
FLOW_RUNTIME_TAG=
|
98
|
+
FLOW_RUNTIME_TAG=22-09-2025-0bd3f58
|
99
99
|
FLOW_RUMTIME_REGISTRY=
|
100
100
|
|
101
101
|
|
@@ -35,6 +35,7 @@ def flow(*args,
|
|
35
35
|
description: str|None=None,
|
36
36
|
input_schema: type[BaseModel] | None = None,
|
37
37
|
output_schema: type[BaseModel] | None = None,
|
38
|
+
private_schema: type[BaseModel] | None = None,
|
38
39
|
initiators: Sequence[str] = (),
|
39
40
|
schedulable: bool = False,
|
40
41
|
llm_model: str|ListVirtualModel|None=None,
|
@@ -63,6 +64,7 @@ def flow(*args,
|
|
63
64
|
description = node_spec.description,
|
64
65
|
input_schema = input_schema,
|
65
66
|
output_schema = output_schema,
|
67
|
+
private_schema = private_schema,
|
66
68
|
initiators = initiators,
|
67
69
|
schedulable = schedulable,
|
68
70
|
llm_model = llm_model,
|
@@ -26,13 +26,13 @@ from ibm_watsonx_orchestrate.client.tools.tool_client import ToolClient
|
|
26
26
|
from ibm_watsonx_orchestrate.client.tools.tempus_client import TempusClient
|
27
27
|
from ibm_watsonx_orchestrate.client.utils import instantiate_client
|
28
28
|
from ..types import (
|
29
|
-
DocProcKVPSchema, Assignment, Conditions, EndNodeSpec, Expression, ForeachPolicy, ForeachSpec, LoopSpec, BranchNodeSpec, MatchPolicy, NodeIdCondition, PlainTextReadingOrder, PromptExample, PromptLLMParameters, PromptNodeSpec, TimerNodeSpec,
|
29
|
+
DocProcKVPSchema, Assignment, Conditions, EndNodeSpec, Expression, ForeachPolicy, ForeachSpec, LoopSpec, BranchNodeSpec, MatchPolicy, NodeIdCondition, PlainTextReadingOrder, PromptExample, PromptLLMParameters, PromptNodeSpec, ScriptNodeSpec, TimerNodeSpec,
|
30
30
|
StartNodeSpec, ToolSpec, JsonSchemaObject, ToolRequestBody, ToolResponseBody, UserFieldKind, UserFieldOption, UserFlowSpec, UserNodeSpec, WaitPolicy,
|
31
31
|
DocProcSpec, TextExtractionResponse, DocProcInput, DecisionsNodeSpec, DecisionsRule, DocExtSpec, File, DocumentClassificationResponse, DocClassifierSpec, DocumentProcessingCommonInput
|
32
32
|
)
|
33
33
|
from .constants import CURRENT_USER, START, END, ANY_USER
|
34
34
|
from ..node import (
|
35
|
-
EndNode, Node, PromptNode, StartNode, UserNode, AgentNode, DataMap, ToolNode, DocProcNode, DecisionsNode, DocExtNode, DocClassifierNode
|
35
|
+
EndNode, Node, PromptNode, ScriptNode, StartNode, UserNode, AgentNode, DataMap, ToolNode, DocProcNode, DecisionsNode, DocExtNode, DocClassifierNode
|
36
36
|
)
|
37
37
|
from ..types import (
|
38
38
|
AgentNodeSpec, extract_node_spec, FlowContext, FlowEventType, FlowEvent, FlowSpec,
|
@@ -357,6 +357,41 @@ class Flow(Node):
|
|
357
357
|
|
358
358
|
node = self._add_node(node)
|
359
359
|
return cast(ToolNode, node)
|
360
|
+
|
361
|
+
|
362
|
+
def script(
|
363
|
+
self,
|
364
|
+
script: str | None = "",
|
365
|
+
name: str | None = None,
|
366
|
+
display_name: str | None = None,
|
367
|
+
description: str | None = None,
|
368
|
+
input_schema: type[BaseModel] | None = None,
|
369
|
+
output_schema: type[BaseModel] | None = None,
|
370
|
+
input_map: DataMap = None
|
371
|
+
) -> ScriptNode:
|
372
|
+
'''create a script node in the flow'''
|
373
|
+
name = name if name is not None and name != "" else ""
|
374
|
+
|
375
|
+
input_schema_obj = _get_json_schema_obj("input", input_schema)
|
376
|
+
output_schema_obj = _get_json_schema_obj("output", output_schema)
|
377
|
+
|
378
|
+
script_node_spec = ScriptNodeSpec(
|
379
|
+
name = name,
|
380
|
+
display_name = display_name,
|
381
|
+
description = description,
|
382
|
+
input_schema= _get_tool_request_body(input_schema_obj),
|
383
|
+
output_schema= _get_tool_response_body(output_schema_obj),
|
384
|
+
output_schema_object = output_schema_obj,
|
385
|
+
fn = script)
|
386
|
+
|
387
|
+
node = ScriptNode(spec=script_node_spec)
|
388
|
+
|
389
|
+
# setup input and output map
|
390
|
+
if input_map:
|
391
|
+
node.input_map = self._get_data_map(input_map)
|
392
|
+
|
393
|
+
node = self._add_node(node)
|
394
|
+
return cast(ScriptNode, node)
|
360
395
|
|
361
396
|
|
362
397
|
def _add_node(self, node: Node) -> Node:
|
@@ -1245,6 +1280,7 @@ class FlowFactory(BaseModel):
|
|
1245
1280
|
initiators: Sequence[str]|None=None,
|
1246
1281
|
input_schema: type[BaseModel]|None=None,
|
1247
1282
|
output_schema: type[BaseModel]|None=None,
|
1283
|
+
private_schema: type[BaseModel]|None=None,
|
1248
1284
|
schedulable: bool=False,
|
1249
1285
|
llm_model: str|ListVirtualModel|None=None,
|
1250
1286
|
agent_conversation_memory_turns_limit: int|None = None) -> Flow:
|
@@ -1257,6 +1293,7 @@ class FlowFactory(BaseModel):
|
|
1257
1293
|
input_schema_obj = _get_json_schema_obj(parameter_name = "input", type_def = input_schema)
|
1258
1294
|
# create input spec
|
1259
1295
|
output_schema_obj = _get_json_schema_obj("output", output_schema)
|
1296
|
+
private_schema_obj = _get_json_schema_obj("private", private_schema)
|
1260
1297
|
if initiators is None:
|
1261
1298
|
initiators = []
|
1262
1299
|
|
@@ -1268,6 +1305,7 @@ class FlowFactory(BaseModel):
|
|
1268
1305
|
initiators=initiators,
|
1269
1306
|
input_schema=_get_tool_request_body(input_schema_obj),
|
1270
1307
|
output_schema=_get_tool_response_body(output_schema_obj),
|
1308
|
+
private_schema = private_schema_obj,
|
1271
1309
|
output_schema_object = output_schema_obj,
|
1272
1310
|
schedulable=schedulable,
|
1273
1311
|
)
|
@@ -6,7 +6,7 @@ import yaml
|
|
6
6
|
from pydantic import BaseModel, Field, SerializeAsAny, create_model
|
7
7
|
from enum import Enum
|
8
8
|
|
9
|
-
from .types import Assignment, DocExtConfigField, EndNodeSpec, NodeSpec, AgentNodeSpec, PromptNodeSpec, TimerNodeSpec, StartNodeSpec, ToolNodeSpec, UserFieldKind, UserFieldOption, UserNodeSpec, DocProcSpec, \
|
9
|
+
from .types import Assignment, DocExtConfigField, EndNodeSpec, NodeSpec, AgentNodeSpec, PromptNodeSpec, ScriptNodeSpec, TimerNodeSpec, StartNodeSpec, ToolNodeSpec, UserFieldKind, UserFieldOption, UserNodeSpec, DocProcSpec, \
|
10
10
|
DocExtSpec, DocExtConfig, DocClassifierSpec, DecisionsNodeSpec, DocClassifierConfig
|
11
11
|
|
12
12
|
from .data_map import DataMap
|
@@ -132,6 +132,18 @@ class ToolNode(Node):
|
|
132
132
|
|
133
133
|
def get_spec(self) -> ToolNodeSpec:
|
134
134
|
return cast(ToolNodeSpec, self.spec)
|
135
|
+
|
136
|
+
|
137
|
+
class ScriptNode(Node):
|
138
|
+
def __repr__(self):
|
139
|
+
return f"ScriptNode(name='{self.spec.name}', description='{self.spec.description}')"
|
140
|
+
|
141
|
+
def get_spec(self) -> ScriptNodeSpec:
|
142
|
+
return cast(ScriptNodeSpec, self.spec)
|
143
|
+
|
144
|
+
def updateScript(self, script: str):
|
145
|
+
'''Update the script of a script node'''
|
146
|
+
self.spec.fn = script
|
135
147
|
|
136
148
|
class UserNode(Node):
|
137
149
|
def __repr__(self):
|
@@ -389,6 +389,19 @@ class ToolNodeSpec(NodeSpec):
|
|
389
389
|
else:
|
390
390
|
model_spec["tool"] = self.tool
|
391
391
|
return model_spec
|
392
|
+
|
393
|
+
class ScriptNodeSpec(NodeSpec):
|
394
|
+
fn: str = Field(default = None, description="the script to execute")
|
395
|
+
|
396
|
+
def __init__(self, **data):
|
397
|
+
super().__init__(**data)
|
398
|
+
self.kind = "script"
|
399
|
+
|
400
|
+
def to_json(self) -> dict[str, Any]:
|
401
|
+
model_spec = super().to_json()
|
402
|
+
if self.fn:
|
403
|
+
model_spec["fn"] = self.fn
|
404
|
+
return model_spec
|
392
405
|
|
393
406
|
|
394
407
|
class UserFieldValue(BaseModel):
|
@@ -871,6 +884,9 @@ class FlowSpec(NodeSpec):
|
|
871
884
|
initiators: Sequence[str] = [ANY_USER]
|
872
885
|
schedulable: bool = False
|
873
886
|
|
887
|
+
# flow can have private schema
|
888
|
+
private_schema: JsonSchemaObject | SchemaRef | None = None
|
889
|
+
|
874
890
|
def __init__(self, **kwargs):
|
875
891
|
super().__init__(**kwargs)
|
876
892
|
self.kind = "flow"
|
@@ -879,6 +895,8 @@ class FlowSpec(NodeSpec):
|
|
879
895
|
model_spec = super().to_json()
|
880
896
|
if self.initiators:
|
881
897
|
model_spec["initiators"] = self.initiators
|
898
|
+
if self.private_schema:
|
899
|
+
model_spec["private_schema"] = _to_json_from_json_schema(self.private_schema)
|
882
900
|
|
883
901
|
model_spec["schedulable"] = self.schedulable
|
884
902
|
|
File without changes
|
@@ -0,0 +1,195 @@
|
|
1
|
+
import logging
|
2
|
+
import ast
|
3
|
+
import sys
|
4
|
+
from pathlib import Path
|
5
|
+
import importlib.util
|
6
|
+
|
7
|
+
from pydantic import BaseModel
|
8
|
+
|
9
|
+
from .lfx_deps import LFX_DEPENDENCIES
|
10
|
+
|
11
|
+
logger = logging.getLogger(__name__)
|
12
|
+
|
13
|
+
class LangflowComponent(BaseModel):
|
14
|
+
id: str
|
15
|
+
name: str
|
16
|
+
credentials: dict
|
17
|
+
requirements: list[str] = []
|
18
|
+
|
19
|
+
class LangflowModelSpec(BaseModel):
|
20
|
+
version: str
|
21
|
+
components: list[LangflowComponent]
|
22
|
+
|
23
|
+
_MODULE_MAP = {
|
24
|
+
"mem0":"mem0ai",
|
25
|
+
}
|
26
|
+
|
27
|
+
import math
|
28
|
+
from collections import Counter
|
29
|
+
|
30
|
+
def _calculate_entropy(s):
|
31
|
+
"""
|
32
|
+
Calculates the Shannon entropy of a string.
|
33
|
+
|
34
|
+
Parameters:
|
35
|
+
s (str): Input string.
|
36
|
+
|
37
|
+
Returns:
|
38
|
+
float: Shannon entropy value.
|
39
|
+
"""
|
40
|
+
if not s:
|
41
|
+
return 0.0
|
42
|
+
|
43
|
+
freq = Counter(s)
|
44
|
+
length = len(s)
|
45
|
+
|
46
|
+
entropy = -sum((count / length) * math.log2(count / length) for count in freq.values())
|
47
|
+
return entropy
|
48
|
+
|
49
|
+
def _mask_api_key(key):
|
50
|
+
"""
|
51
|
+
Masks an API key by keeping the first 5 characters visible,
|
52
|
+
masking the rest with asterisks, and truncating the result to a maximum of 25 characters.
|
53
|
+
|
54
|
+
Parameters:
|
55
|
+
key (str): The API key string.
|
56
|
+
|
57
|
+
Returns:
|
58
|
+
str: Masked and truncated API key.
|
59
|
+
"""
|
60
|
+
if not isinstance(key, str):
|
61
|
+
return key
|
62
|
+
|
63
|
+
# if this is a potential real API key -- mask it
|
64
|
+
if _calculate_entropy(key) > 4.1:
|
65
|
+
visible_part = key[:5]
|
66
|
+
masked_part = '*' * (len(key) - 5)
|
67
|
+
masked_key = visible_part + masked_part
|
68
|
+
|
69
|
+
return masked_key[:25]
|
70
|
+
elif len(key) > 25:
|
71
|
+
# if the key is longer than 25 characters, truncates it anyway
|
72
|
+
return key[:22] + '...'
|
73
|
+
|
74
|
+
return key
|
75
|
+
|
76
|
+
def _extract_imports(source_code) -> list[str]:
|
77
|
+
tree = ast.parse(source_code)
|
78
|
+
imports = set()
|
79
|
+
for node in ast.walk(tree):
|
80
|
+
if isinstance(node, ast.Import):
|
81
|
+
for alias in node.names:
|
82
|
+
# we only need the module name, not sub-module
|
83
|
+
imports.add(alias.name.split('.')[0])
|
84
|
+
elif isinstance(node, ast.ImportFrom):
|
85
|
+
if node.module:
|
86
|
+
# we only need the module name, not sub-module
|
87
|
+
imports.add(node.module.split('.')[0])
|
88
|
+
return sorted(imports)
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
def _is_builtin_module(module_name: str) -> bool:
|
93
|
+
underscore_module_name = f"_{module_name}"
|
94
|
+
|
95
|
+
# Check against the list of standard modules
|
96
|
+
if module_name in sys.stdlib_module_names:
|
97
|
+
return True
|
98
|
+
|
99
|
+
if underscore_module_name in sys.stdlib_module_names:
|
100
|
+
return True
|
101
|
+
|
102
|
+
# Check against the list of built-in module names
|
103
|
+
if module_name in sys.builtin_module_names:
|
104
|
+
return True
|
105
|
+
|
106
|
+
if underscore_module_name in sys.builtin_module_names:
|
107
|
+
return True
|
108
|
+
|
109
|
+
# Use importlib to find the module spec
|
110
|
+
spec = importlib.util.find_spec(module_name)
|
111
|
+
if spec is None:
|
112
|
+
return False # Module not found
|
113
|
+
|
114
|
+
# Check if the loader is a BuiltinImporter
|
115
|
+
return isinstance(spec.loader, importlib.machinery.BuiltinImporter)
|
116
|
+
|
117
|
+
|
118
|
+
def _find_missing_requirements(imported_modules, requirements_modules: list[str]) -> list[str]:
|
119
|
+
"""
|
120
|
+
Compare imported modules with requirements.txt and return missing ones.
|
121
|
+
|
122
|
+
Parameters:
|
123
|
+
imported_modules (list): List of module names used in the code.
|
124
|
+
requirements_file_path (str): Path to the requirements.txt file.
|
125
|
+
|
126
|
+
Returns:
|
127
|
+
list: Modules that are imported but not listed in requirements.txt.
|
128
|
+
"""
|
129
|
+
def normalize_module_name(name):
|
130
|
+
module_name = name.split('.')[0].lower()
|
131
|
+
# sometimes the module name in pipy is different than the real name
|
132
|
+
if module_name in _MODULE_MAP:
|
133
|
+
module_name = _MODULE_MAP[module_name]
|
134
|
+
return module_name
|
135
|
+
|
136
|
+
# Normalize imported module names
|
137
|
+
normalized_imports = [normalize_module_name(mod) for mod in imported_modules]
|
138
|
+
|
139
|
+
# filter out all built-ins
|
140
|
+
filtered_imports = [
|
141
|
+
module for module in normalized_imports
|
142
|
+
if _is_builtin_module(module) is False
|
143
|
+
]
|
144
|
+
|
145
|
+
# Compare and find missing modules
|
146
|
+
missing_modules = [
|
147
|
+
module for module in filtered_imports
|
148
|
+
if module not in requirements_modules
|
149
|
+
]
|
150
|
+
|
151
|
+
return missing_modules
|
152
|
+
|
153
|
+
|
154
|
+
|
155
|
+
def parse_langflow_model(model) -> LangflowModelSpec:
|
156
|
+
"""
|
157
|
+
Extracts component details and Langflow version from a Langflow JSON object.
|
158
|
+
|
159
|
+
Parameters:
|
160
|
+
model (dict): The Langflow JSON object.
|
161
|
+
|
162
|
+
Returns:
|
163
|
+
LangflowModelSpec: A LangflowModelSpec object containing the extracted version and component information.
|
164
|
+
"""
|
165
|
+
version = model.get("last_tested_version", "Unknown")
|
166
|
+
components = []
|
167
|
+
data = model.get('data', {} )
|
168
|
+
|
169
|
+
# get the list of available modules
|
170
|
+
requirements_modules = LFX_DEPENDENCIES
|
171
|
+
|
172
|
+
for node in data.get("nodes", []):
|
173
|
+
node_data = node.get("data", {})
|
174
|
+
node_info = node_data.get("node", {})
|
175
|
+
template = node_info.get("template", {})
|
176
|
+
code = template.get("code")
|
177
|
+
credentials = {}
|
178
|
+
|
179
|
+
missing_imports = []
|
180
|
+
for field_name, field_info in template.items():
|
181
|
+
if isinstance(field_info, dict) and field_info.get("password", False) == True:
|
182
|
+
credentials[field_name] = _mask_api_key(field_info.get("value"))
|
183
|
+
|
184
|
+
if code and code.get("value") != None:
|
185
|
+
imports = _extract_imports(code.get("value"))
|
186
|
+
if len(imports) > 0:
|
187
|
+
missing_imports = _find_missing_requirements(imports, requirements_modules)
|
188
|
+
|
189
|
+
component_info = LangflowComponent(name=node_info.get("display_name", "Unknown"), id=node_data.get("id", "Unknown"),
|
190
|
+
credentials=credentials, requirements=missing_imports)
|
191
|
+
|
192
|
+
components.append(component_info)
|
193
|
+
|
194
|
+
return LangflowModelSpec(version=version, components=components)
|
195
|
+
|
@@ -0,0 +1,84 @@
|
|
1
|
+
LFX_DEPENDENCIES = [
|
2
|
+
"aiofile",
|
3
|
+
"aiofiles",
|
4
|
+
"annotated-types",
|
5
|
+
"anyio",
|
6
|
+
"asyncer",
|
7
|
+
"cachetools",
|
8
|
+
"caio",
|
9
|
+
"certifi",
|
10
|
+
"chardet",
|
11
|
+
"charset-normalizer",
|
12
|
+
"click",
|
13
|
+
"defusedxml",
|
14
|
+
"docstring_parser",
|
15
|
+
"emoji",
|
16
|
+
"fastapi",
|
17
|
+
"h11",
|
18
|
+
"h2",
|
19
|
+
"hpack",
|
20
|
+
"httpcore",
|
21
|
+
"httpx",
|
22
|
+
"hyperframe",
|
23
|
+
"idna",
|
24
|
+
"json_repair",
|
25
|
+
"jsonpatch",
|
26
|
+
"jsonpointer",
|
27
|
+
"langchain",
|
28
|
+
"langchain-core",
|
29
|
+
"langchain-text-splitters",
|
30
|
+
"langsmith",
|
31
|
+
"lfx-nightly",
|
32
|
+
"loguru",
|
33
|
+
"markdown-it-py",
|
34
|
+
"mdurl",
|
35
|
+
"nanoid",
|
36
|
+
"networkx",
|
37
|
+
"numpy",
|
38
|
+
"orjson",
|
39
|
+
"packaging",
|
40
|
+
"pandas",
|
41
|
+
"passlib",
|
42
|
+
"pillow",
|
43
|
+
"platformdirs",
|
44
|
+
"pydantic",
|
45
|
+
"pydantic-settings",
|
46
|
+
"pydantic_core",
|
47
|
+
"Pygments",
|
48
|
+
"python-dateutil",
|
49
|
+
"python-dotenv",
|
50
|
+
"pytz",
|
51
|
+
"PyYAML",
|
52
|
+
"requests",
|
53
|
+
"requests-toolbelt",
|
54
|
+
"rich",
|
55
|
+
"shellingham",
|
56
|
+
"six",
|
57
|
+
"sniffio",
|
58
|
+
"SQLAlchemy",
|
59
|
+
"starlette",
|
60
|
+
"structlog",
|
61
|
+
"tenacity",
|
62
|
+
"tomli",
|
63
|
+
"typer",
|
64
|
+
"typing-inspection",
|
65
|
+
"typing_extensions",
|
66
|
+
"tzdata",
|
67
|
+
"urllib3",
|
68
|
+
"uvicorn",
|
69
|
+
"validators",
|
70
|
+
"zstandard",
|
71
|
+
"langflow",
|
72
|
+
"langchain_openai",
|
73
|
+
"langchain_core",
|
74
|
+
"langchain_text_splitters",
|
75
|
+
"collections",
|
76
|
+
"typing",
|
77
|
+
"datetime",
|
78
|
+
"zoneinfo",
|
79
|
+
"or",
|
80
|
+
"re",
|
81
|
+
"os",
|
82
|
+
"copy",
|
83
|
+
"json"
|
84
|
+
]
|
@@ -11,8 +11,12 @@ def yaml_safe_load(file : BinaryIO) -> dict:
|
|
11
11
|
return yaml.safe_load(file)
|
12
12
|
|
13
13
|
def sanitize_app_id(app_id: str) -> str:
|
14
|
-
|
15
|
-
return re.sub(
|
14
|
+
sanitize_pattern = re.compile(r"[^a-zA-Z0-9]+")
|
15
|
+
return re.sub(sanitize_pattern,'_', app_id)
|
16
|
+
|
17
|
+
def sanitize_catalog_label(label: str) -> str:
|
18
|
+
sanitize_pattern = re.compile(r"[^a-zA-Z0-9]+")
|
19
|
+
return re.sub(sanitize_pattern,'_', label)
|
16
20
|
|
17
21
|
def check_file_in_zip(file_path: str, zip_file: zipfile.ZipFile) -> bool:
|
18
22
|
return any(x.startswith("%s/" % file_path.rstrip("/")) for x in zip_file.namelist())
|
{ibm_watsonx_orchestrate-1.12.0b1.dist-info → ibm_watsonx_orchestrate-1.12.1.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ibm-watsonx-orchestrate
|
3
|
-
Version: 1.12.
|
3
|
+
Version: 1.12.1
|
4
4
|
Summary: IBM watsonx.orchestrate SDK
|
5
5
|
Author-email: IBM <support@ibm.com>
|
6
6
|
License: MIT License
|
@@ -11,7 +11,7 @@ Requires-Dist: click<8.2.0,>=8.0.0
|
|
11
11
|
Requires-Dist: docstring-parser<1.0,>=0.16
|
12
12
|
Requires-Dist: httpx<1.0.0,>=0.28.1
|
13
13
|
Requires-Dist: ibm-cloud-sdk-core>=3.24.2
|
14
|
-
Requires-Dist: ibm-watsonx-orchestrate-evaluation-framework==1.1.
|
14
|
+
Requires-Dist: ibm-watsonx-orchestrate-evaluation-framework==1.1.3
|
15
15
|
Requires-Dist: jsonref==1.1.0
|
16
16
|
Requires-Dist: langchain-core<=0.3.63
|
17
17
|
Requires-Dist: langsmith<=0.3.45
|
{ibm_watsonx_orchestrate-1.12.0b1.dist-info → ibm_watsonx_orchestrate-1.12.1.dist-info}/RECORD
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
ibm_watsonx_orchestrate/__init__.py,sha256=
|
1
|
+
ibm_watsonx_orchestrate/__init__.py,sha256=f3ba5wWbOhu85odqw41PZ_43Yy6-yhTc1WglmHJGkLU,426
|
2
2
|
ibm_watsonx_orchestrate/agent_builder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
3
|
ibm_watsonx_orchestrate/agent_builder/agents/__init__.py,sha256=lmZwaiWXD4Ea19nrMwZXaqCxFMG29xNS8vUoZtK3yI4,392
|
4
4
|
ibm_watsonx_orchestrate/agent_builder/agents/agent.py,sha256=W0uya81fQPrYZFaO_tlsxBL56Bfpw0xrqdxQJhAZ6XI,983
|
@@ -23,7 +23,7 @@ ibm_watsonx_orchestrate/agent_builder/toolkits/types.py,sha256=RGkS01_fqbs-7YFFZ
|
|
23
23
|
ibm_watsonx_orchestrate/agent_builder/tools/__init__.py,sha256=R07j4zERCBX22ILsGBl3qRw0poaVSONPnMZ_69bAFDw,519
|
24
24
|
ibm_watsonx_orchestrate/agent_builder/tools/base_tool.py,sha256=qiVHqLN-S9AuJlsvVaV_kNN5oNi4kk6177Hi9KpEdaI,1240
|
25
25
|
ibm_watsonx_orchestrate/agent_builder/tools/flow_tool.py,sha256=DJWYVmIjw1O_cbzPpwU0a_vIZGvo0mj8UsjW9zkKMlA,2589
|
26
|
-
ibm_watsonx_orchestrate/agent_builder/tools/langflow_tool.py,sha256=
|
26
|
+
ibm_watsonx_orchestrate/agent_builder/tools/langflow_tool.py,sha256=beozS44KQkjy3hjUn17Sy1xoPZyviu7o3_ez4KGtJgU,6843
|
27
27
|
ibm_watsonx_orchestrate/agent_builder/tools/openapi_tool.py,sha256=haAN5t4YMGrVM788UdMxfMWUctOe6_3szGxsRF3KPr8,19730
|
28
28
|
ibm_watsonx_orchestrate/agent_builder/tools/python_tool.py,sha256=cdgu-v1oRR9RUbMNKEklOzO1z3nNZpDZPSMwnJEvuIY,12533
|
29
29
|
ibm_watsonx_orchestrate/agent_builder/tools/types.py,sha256=8Esn77LZSBNTiKOpvRXF35LUFnfydyvZ-oxAQJyt1wE,8931
|
@@ -31,7 +31,7 @@ ibm_watsonx_orchestrate/agent_builder/utils/__init__.py,sha256=47DEQpj8HBSa-_TIm
|
|
31
31
|
ibm_watsonx_orchestrate/agent_builder/voice_configurations/__init__.py,sha256=W3-T8PH_KuONsCQPILQAvW2Nz25p7dp9AZbWHWGJXhA,37
|
32
32
|
ibm_watsonx_orchestrate/agent_builder/voice_configurations/types.py,sha256=lSS1yiDzVAMkEdOwcI4_1DUuRnu_6oc8XupQtoE4Fvs,3989
|
33
33
|
ibm_watsonx_orchestrate/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
34
|
-
ibm_watsonx_orchestrate/cli/config.py,sha256=
|
34
|
+
ibm_watsonx_orchestrate/cli/config.py,sha256=ZcuOhd-zXZQ6N0yMM3DLpz9SKHywiB1djk6SrAqGDOk,8435
|
35
35
|
ibm_watsonx_orchestrate/cli/init_helper.py,sha256=qxnKdFcPtGsV_6RqP_IuLshRxgB004SxzDAkBTExA-4,1675
|
36
36
|
ibm_watsonx_orchestrate/cli/main.py,sha256=5AuoVVDHzgNZ6Y2ZR4bSF1cs7AhQRyd8n7S41o8lK4w,3618
|
37
37
|
ibm_watsonx_orchestrate/cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -48,11 +48,11 @@ ibm_watsonx_orchestrate/cli/commands/connections/connections_controller.py,sha25
|
|
48
48
|
ibm_watsonx_orchestrate/cli/commands/copilot/copilot_command.py,sha256=IxasApIyQYWRMKPXKa38ZPVkUvOc4chggSmSGjgQGXc,2345
|
49
49
|
ibm_watsonx_orchestrate/cli/commands/copilot/copilot_controller.py,sha256=SC2Tjq6r-tHIiyPBMajsxdMIY3BQpRWpkYGZS2XbJyU,18981
|
50
50
|
ibm_watsonx_orchestrate/cli/commands/copilot/copilot_server_controller.py,sha256=9MXS5uE3esKp3IYILVty7COFcr9iJ90axkAqPVaJ1NE,3874
|
51
|
-
ibm_watsonx_orchestrate/cli/commands/environment/environment_command.py,sha256=
|
52
|
-
ibm_watsonx_orchestrate/cli/commands/environment/environment_controller.py,sha256=
|
51
|
+
ibm_watsonx_orchestrate/cli/commands/environment/environment_command.py,sha256=1CO0UfxSem0NafNGNCBXswC-P93MVYIA-YJewjKgdNc,4186
|
52
|
+
ibm_watsonx_orchestrate/cli/commands/environment/environment_controller.py,sha256=z3m4khZfHNpv1dRsDfRW0cteLvhAeDEbxh-fOZduSpQ,10479
|
53
53
|
ibm_watsonx_orchestrate/cli/commands/environment/types.py,sha256=X6jEnyBdxakromA7FhQ5btZMj9kwGcwRSFz8vpD65jA,224
|
54
|
-
ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_command.py,sha256=
|
55
|
-
ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_controller.py,sha256=
|
54
|
+
ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_command.py,sha256=0ET6tXMkeupT8K5hNGQBgLOhlV8YAshqH3bp9A8vgDk,21930
|
55
|
+
ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_controller.py,sha256=avA5Guyyhqw9x0IAp-I9vVyEaS3X5U77Ag4xBw1k8l0,11348
|
56
56
|
ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_command.py,sha256=hOzRcGVoqq7dTc4bSregKxH-kYbrVqaFdhBLawqnRNo,2668
|
57
57
|
ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_controller.py,sha256=d9RSBy2S2nn8vWrghovGb1owe7Zu8LywOm0nIdzlXiU,11567
|
58
58
|
ibm_watsonx_orchestrate/cli/commands/login/login_command.py,sha256=xArMiojoozg7Exn6HTpbTcjDO2idZRA-y0WV-_Ic1Sk,651
|
@@ -62,8 +62,8 @@ ibm_watsonx_orchestrate/cli/commands/models/models_controller.py,sha256=wcy16LPZ
|
|
62
62
|
ibm_watsonx_orchestrate/cli/commands/partners/partners_command.py,sha256=YpTlKKinQw1QdM4yXYjSrMtoAcwc1b9GoO6Wv1NmgKc,385
|
63
63
|
ibm_watsonx_orchestrate/cli/commands/partners/partners_controller.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
64
64
|
ibm_watsonx_orchestrate/cli/commands/partners/offering/partners_offering_command.py,sha256=X6u5zGwKYY1Uc2szaVHCIyMlFJBzp8o8JgVZUxcZPd8,1727
|
65
|
-
ibm_watsonx_orchestrate/cli/commands/partners/offering/partners_offering_controller.py,sha256=
|
66
|
-
ibm_watsonx_orchestrate/cli/commands/partners/offering/types.py,sha256=
|
65
|
+
ibm_watsonx_orchestrate/cli/commands/partners/offering/partners_offering_controller.py,sha256=4qIaMwUHcSsPDDqXHS0vuwktyFD18sQyFabbBhr8vjY,19229
|
66
|
+
ibm_watsonx_orchestrate/cli/commands/partners/offering/types.py,sha256=Wc7YyY3dQobx5P5-as45WmTiZiuiSzvSSSDZP-5vj-g,2804
|
67
67
|
ibm_watsonx_orchestrate/cli/commands/server/server_command.py,sha256=cMjaAXEPMN-OkenqIbckPisPV093rabOxkLKmNiyxTc,28956
|
68
68
|
ibm_watsonx_orchestrate/cli/commands/server/types.py,sha256=DGLopPbLFf5yH5-hzsFf5Uaw158QHwkTAcwydbUmZ3Q,4416
|
69
69
|
ibm_watsonx_orchestrate/cli/commands/settings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -75,7 +75,7 @@ ibm_watsonx_orchestrate/cli/commands/settings/observability/langfuse/langfuse_co
|
|
75
75
|
ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_command.py,sha256=dgmfI3PA04By3W526BEOZp0jJE5eVoxEUMbPG0JxUlE,5653
|
76
76
|
ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_controller.py,sha256=lo9xahKQiPhm4xh97O_twkzLO0GhXDzAi1rZT0ybQpA,13027
|
77
77
|
ibm_watsonx_orchestrate/cli/commands/tools/tools_command.py,sha256=1RXndNL8Ztl6YEVl4rW6sg0m0hE9d0RhT2Oac45ui2M,3945
|
78
|
-
ibm_watsonx_orchestrate/cli/commands/tools/tools_controller.py,sha256=
|
78
|
+
ibm_watsonx_orchestrate/cli/commands/tools/tools_controller.py,sha256=nq-cmGfwqscOwtaUlm1feI-eUp1kIDG96XcABX1a3QU,49492
|
79
79
|
ibm_watsonx_orchestrate/cli/commands/tools/types.py,sha256=_md0GEa_cTH17NO_moWDY_LNdFvyEFQ1UVB9_FltYiA,173
|
80
80
|
ibm_watsonx_orchestrate/cli/commands/voice_configurations/voice_configurations_command.py,sha256=q4KHWQ-LZbp31e2ytihX1OuyAPS4-nRinmc-eMXC0l0,1783
|
81
81
|
ibm_watsonx_orchestrate/cli/commands/voice_configurations/voice_configurations_controller.py,sha256=JbAc_CY0woHY8u7qrnOcb9O2FgECzkzeMirxFhRoep8,5884
|
@@ -108,7 +108,7 @@ ibm_watsonx_orchestrate/client/tools/tempus_client.py,sha256=iD7Hkzn_LdnFivAzGSV
|
|
108
108
|
ibm_watsonx_orchestrate/client/tools/tool_client.py,sha256=kYwQp-ym9dYQDOFSTnXNyeh8wzl39LpBJqHSNT9EKT0,2113
|
109
109
|
ibm_watsonx_orchestrate/client/voice_configurations/voice_configurations_client.py,sha256=M5xIPLiVNpP-zxQw8CTNT9AiBjeXXmJiNaE142e2A3E,2682
|
110
110
|
ibm_watsonx_orchestrate/docker/compose-lite.yml,sha256=niF_ir68D_YdjrZWGUOy8eNLV-K5PX_xVWhdZEC2Crk,48041
|
111
|
-
ibm_watsonx_orchestrate/docker/default.env,sha256=
|
111
|
+
ibm_watsonx_orchestrate/docker/default.env,sha256=eR-j22xztFZV4pEpXFupbNTUXd4nv2z8B6rKbAUkR50,6372
|
112
112
|
ibm_watsonx_orchestrate/docker/proxy-config-single.yaml,sha256=WEbK4ENFuTCYhzRu_QblWp1_GMARgZnx5vReQafkIG8,308
|
113
113
|
ibm_watsonx_orchestrate/docker/start-up.sh,sha256=LTtwHp0AidVgjohis2LXGvZnkFQStOiUAxgGABOyeUI,1811
|
114
114
|
ibm_watsonx_orchestrate/docker/sdk/ibm_watsonx_orchestrate-0.6.0-py3-none-any.whl,sha256=Hi3-owh5OM0Jz2ihX9nLoojnr7Ky1TV-GelyqLcewLE,2047417
|
@@ -116,26 +116,29 @@ ibm_watsonx_orchestrate/docker/sdk/ibm_watsonx_orchestrate-0.6.0.tar.gz,sha256=e
|
|
116
116
|
ibm_watsonx_orchestrate/docker/tempus/common-config.yaml,sha256=Zo3F36F5DV4VO_vUg1RG-r4WhcukVh79J2fXhGl6j0A,22
|
117
117
|
ibm_watsonx_orchestrate/flow_builder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
118
118
|
ibm_watsonx_orchestrate/flow_builder/data_map.py,sha256=LinePFgb5mBnrvNmPkFe3rq5oYJZSjcgmaEGpE6dVwc,586
|
119
|
-
ibm_watsonx_orchestrate/flow_builder/node.py,sha256=
|
120
|
-
ibm_watsonx_orchestrate/flow_builder/types.py,sha256=
|
119
|
+
ibm_watsonx_orchestrate/flow_builder/node.py,sha256=Y5hzVkbWNWaYp6zSbLW4Qbg4r1deLAs-X3HEFoZ9vzk,10338
|
120
|
+
ibm_watsonx_orchestrate/flow_builder/types.py,sha256=3mpLKOVgQBwWBVJAfF7GQF2wPZKYwDniJCUnaJypYTA,70606
|
121
121
|
ibm_watsonx_orchestrate/flow_builder/utils.py,sha256=8q1jr5i_TzoJpoQxmLiO0g5Uv03BLbTUaRfw8_0VWIY,11931
|
122
122
|
ibm_watsonx_orchestrate/flow_builder/flows/__init__.py,sha256=iRYV0_eXgBBGhuNnvg-mUyPUyCIw5BiallPOp27bzYM,1083
|
123
123
|
ibm_watsonx_orchestrate/flow_builder/flows/constants.py,sha256=-TGneZyjA4YiAtJJK7OmmjDHYQC4mw2e98MPAZqiB50,324
|
124
|
-
ibm_watsonx_orchestrate/flow_builder/flows/decorators.py,sha256=
|
124
|
+
ibm_watsonx_orchestrate/flow_builder/flows/decorators.py,sha256=07yaaDXLrwmj0v9lhZli8UmnKVpIuF6x1t3JbPVj0F8,3247
|
125
125
|
ibm_watsonx_orchestrate/flow_builder/flows/events.py,sha256=VyaBm0sADwr15LWfKbcBQS1M80NKqzYDj3UlW3OpOf4,2984
|
126
|
-
ibm_watsonx_orchestrate/flow_builder/flows/flow.py,sha256=
|
126
|
+
ibm_watsonx_orchestrate/flow_builder/flows/flow.py,sha256=wPCpDT-RFJZsiDYNPLteWQRpSQl86urEbCi6UurCqfg,67946
|
127
|
+
ibm_watsonx_orchestrate/langflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
128
|
+
ibm_watsonx_orchestrate/langflow/langflow_utils.py,sha256=UIWN28WvaYNhV-Ph_x0HSqV7jbL8lQlaUBdYeELqXJo,5765
|
129
|
+
ibm_watsonx_orchestrate/langflow/lfx_deps.py,sha256=Bgbo8IQEX_TblGLmw1tnA0DP7Xm4SFRncPp4TGbqY1o,1396
|
127
130
|
ibm_watsonx_orchestrate/run/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
128
131
|
ibm_watsonx_orchestrate/run/connections.py,sha256=9twXkNeUx83fP_qYUbJRtumE-wzPPNN2v-IY_8hGndM,1820
|
129
132
|
ibm_watsonx_orchestrate/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
130
133
|
ibm_watsonx_orchestrate/utils/docker_utils.py,sha256=yDaeMToD7PSptuzCguEN8zPDyvPlwDR3ORutffldbuM,11355
|
131
134
|
ibm_watsonx_orchestrate/utils/environment.py,sha256=MBNhZsGuhL7-9HL-0ln6RwgiqfXXZqvSCyHcIQypuc8,14549
|
132
135
|
ibm_watsonx_orchestrate/utils/exceptions.py,sha256=MjpoGuk7lMziPT2Zo7X-jgGlm0M22mTZF4Y8EHb3KPM,631
|
133
|
-
ibm_watsonx_orchestrate/utils/utils.py,sha256=
|
136
|
+
ibm_watsonx_orchestrate/utils/utils.py,sha256=X7kV4VgLEA82IdD5QNY90gdk_BZ6WcxqLLe6X8Q6DQU,868
|
134
137
|
ibm_watsonx_orchestrate/utils/logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
135
138
|
ibm_watsonx_orchestrate/utils/logging/logger.py,sha256=FzeGnidXAjC7yHrvIaj4KZPeaBBSCniZFlwgr5yV3oA,1037
|
136
139
|
ibm_watsonx_orchestrate/utils/logging/logging.yaml,sha256=9_TKfuFr1barnOKP0fZT5D6MhddiwsXVTFjtRbcOO5w,314
|
137
|
-
ibm_watsonx_orchestrate-1.12.
|
138
|
-
ibm_watsonx_orchestrate-1.12.
|
139
|
-
ibm_watsonx_orchestrate-1.12.
|
140
|
-
ibm_watsonx_orchestrate-1.12.
|
141
|
-
ibm_watsonx_orchestrate-1.12.
|
140
|
+
ibm_watsonx_orchestrate-1.12.1.dist-info/METADATA,sha256=JuOchl70FsR2MBshmh_rutVDS8lEs9kkChhMXInbgso,1361
|
141
|
+
ibm_watsonx_orchestrate-1.12.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
142
|
+
ibm_watsonx_orchestrate-1.12.1.dist-info/entry_points.txt,sha256=SfIT02-Jen5e99OcLhzbcM9Bdyf8SGVOCtnSplgZdQI,69
|
143
|
+
ibm_watsonx_orchestrate-1.12.1.dist-info/licenses/LICENSE,sha256=Shgxx7hTdCOkiVRmfGgp_1ISISrwQD7m2f0y8Hsapl4,1083
|
144
|
+
ibm_watsonx_orchestrate-1.12.1.dist-info/RECORD,,
|
{ibm_watsonx_orchestrate-1.12.0b1.dist-info → ibm_watsonx_orchestrate-1.12.1.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|
File without changes
|