ibm-watsonx-orchestrate 1.12.0b0__py3-none-any.whl → 1.13.0b0__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.
Files changed (66) hide show
  1. ibm_watsonx_orchestrate/__init__.py +2 -1
  2. ibm_watsonx_orchestrate/agent_builder/agents/types.py +5 -5
  3. ibm_watsonx_orchestrate/agent_builder/connections/types.py +34 -3
  4. ibm_watsonx_orchestrate/agent_builder/knowledge_bases/types.py +11 -2
  5. ibm_watsonx_orchestrate/agent_builder/models/types.py +18 -1
  6. ibm_watsonx_orchestrate/agent_builder/toolkits/base_toolkit.py +1 -1
  7. ibm_watsonx_orchestrate/agent_builder/toolkits/types.py +14 -2
  8. ibm_watsonx_orchestrate/agent_builder/tools/__init__.py +1 -1
  9. ibm_watsonx_orchestrate/agent_builder/tools/base_tool.py +1 -1
  10. ibm_watsonx_orchestrate/agent_builder/tools/langflow_tool.py +61 -1
  11. ibm_watsonx_orchestrate/agent_builder/tools/openapi_tool.py +6 -0
  12. ibm_watsonx_orchestrate/agent_builder/tools/types.py +21 -3
  13. ibm_watsonx_orchestrate/agent_builder/voice_configurations/__init__.py +1 -1
  14. ibm_watsonx_orchestrate/agent_builder/voice_configurations/types.py +11 -0
  15. ibm_watsonx_orchestrate/cli/commands/agents/agents_controller.py +29 -53
  16. ibm_watsonx_orchestrate/cli/commands/connections/connections_command.py +2 -2
  17. ibm_watsonx_orchestrate/cli/commands/connections/connections_controller.py +56 -30
  18. ibm_watsonx_orchestrate/cli/commands/copilot/copilot_command.py +25 -2
  19. ibm_watsonx_orchestrate/cli/commands/copilot/copilot_controller.py +249 -14
  20. ibm_watsonx_orchestrate/cli/commands/copilot/copilot_server_controller.py +4 -4
  21. ibm_watsonx_orchestrate/cli/commands/environment/environment_command.py +5 -1
  22. ibm_watsonx_orchestrate/cli/commands/environment/environment_controller.py +6 -3
  23. ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_command.py +3 -2
  24. ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_controller.py +1 -1
  25. ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_controller.py +45 -16
  26. ibm_watsonx_orchestrate/cli/commands/models/model_provider_mapper.py +23 -4
  27. ibm_watsonx_orchestrate/cli/commands/models/models_command.py +2 -2
  28. ibm_watsonx_orchestrate/cli/commands/models/models_controller.py +29 -10
  29. ibm_watsonx_orchestrate/cli/commands/partners/offering/partners_offering_controller.py +21 -4
  30. ibm_watsonx_orchestrate/cli/commands/partners/offering/types.py +7 -15
  31. ibm_watsonx_orchestrate/cli/commands/partners/partners_command.py +1 -1
  32. ibm_watsonx_orchestrate/cli/commands/server/server_command.py +30 -20
  33. ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_command.py +2 -2
  34. ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_controller.py +139 -27
  35. ibm_watsonx_orchestrate/cli/commands/tools/tools_command.py +2 -2
  36. ibm_watsonx_orchestrate/cli/commands/tools/tools_controller.py +79 -36
  37. ibm_watsonx_orchestrate/cli/commands/voice_configurations/voice_configurations_controller.py +23 -11
  38. ibm_watsonx_orchestrate/cli/common.py +26 -0
  39. ibm_watsonx_orchestrate/cli/config.py +33 -2
  40. ibm_watsonx_orchestrate/client/connections/connections_client.py +1 -14
  41. ibm_watsonx_orchestrate/client/copilot/cpe/copilot_cpe_client.py +34 -1
  42. ibm_watsonx_orchestrate/client/knowledge_bases/knowledge_base_client.py +6 -2
  43. ibm_watsonx_orchestrate/client/model_policies/model_policies_client.py +1 -1
  44. ibm_watsonx_orchestrate/client/models/models_client.py +1 -1
  45. ibm_watsonx_orchestrate/client/threads/threads_client.py +34 -0
  46. ibm_watsonx_orchestrate/client/utils.py +29 -7
  47. ibm_watsonx_orchestrate/docker/compose-lite.yml +58 -8
  48. ibm_watsonx_orchestrate/docker/default.env +26 -17
  49. ibm_watsonx_orchestrate/flow_builder/flows/decorators.py +10 -2
  50. ibm_watsonx_orchestrate/flow_builder/flows/flow.py +90 -16
  51. ibm_watsonx_orchestrate/flow_builder/node.py +14 -2
  52. ibm_watsonx_orchestrate/flow_builder/types.py +57 -3
  53. ibm_watsonx_orchestrate/langflow/__init__.py +0 -0
  54. ibm_watsonx_orchestrate/langflow/langflow_utils.py +195 -0
  55. ibm_watsonx_orchestrate/langflow/lfx_deps.py +84 -0
  56. ibm_watsonx_orchestrate/utils/async_helpers.py +31 -0
  57. ibm_watsonx_orchestrate/utils/docker_utils.py +1177 -33
  58. ibm_watsonx_orchestrate/utils/environment.py +165 -20
  59. ibm_watsonx_orchestrate/utils/exceptions.py +1 -1
  60. ibm_watsonx_orchestrate/utils/tokens.py +51 -0
  61. ibm_watsonx_orchestrate/utils/utils.py +63 -4
  62. {ibm_watsonx_orchestrate-1.12.0b0.dist-info → ibm_watsonx_orchestrate-1.13.0b0.dist-info}/METADATA +2 -2
  63. {ibm_watsonx_orchestrate-1.12.0b0.dist-info → ibm_watsonx_orchestrate-1.13.0b0.dist-info}/RECORD +66 -59
  64. {ibm_watsonx_orchestrate-1.12.0b0.dist-info → ibm_watsonx_orchestrate-1.13.0b0.dist-info}/WHEEL +0 -0
  65. {ibm_watsonx_orchestrate-1.12.0b0.dist-info → ibm_watsonx_orchestrate-1.13.0b0.dist-info}/entry_points.txt +0 -0
  66. {ibm_watsonx_orchestrate-1.12.0b0.dist-info → ibm_watsonx_orchestrate-1.13.0b0.dist-info}/licenses/LICENSE +0 -0
@@ -6,16 +6,32 @@ import subprocess
6
6
  import sys
7
7
  import tempfile
8
8
  from pathlib import Path
9
+ from typing import Tuple, OrderedDict
9
10
  from urllib.parse import urlparse
11
+ from enum import Enum
10
12
 
11
13
  from dotenv import dotenv_values
12
14
 
15
+ from ibm_watsonx_orchestrate.cli.commands.environment.types import EnvironmentAuthType
13
16
  from ibm_watsonx_orchestrate.cli.commands.server.types import WatsonXAIEnvConfig, ModelGatewayEnvConfig
14
17
  from ibm_watsonx_orchestrate.cli.config import USER_ENV_CACHE_HEADER, Config
15
18
  from ibm_watsonx_orchestrate.client.utils import is_arm_architecture
19
+ from ibm_watsonx_orchestrate.utils.utils import parse_bool_safe, parse_int_safe, parse_bool_safe_and_get_raw_val
20
+
16
21
 
17
22
  logger = logging.getLogger(__name__)
18
23
 
24
+ class DeveloperEditionSources(str, Enum):
25
+ MYIBM = "myibm"
26
+ ORCHESTRATE = "orchestrate"
27
+ INTERNAL = "internal"
28
+ CUSTOM = "custom"
29
+
30
+ def __str__(self):
31
+ return self.value
32
+
33
+ def __repr__(self):
34
+ return self.value
19
35
 
20
36
  class EnvService:
21
37
 
@@ -65,8 +81,8 @@ class EnvService:
65
81
  return env_file
66
82
 
67
83
  @staticmethod
68
- def read_env_file (env_path: Path | str) -> dict:
69
- return dotenv_values(str(env_path))
84
+ def read_env_file (env_path: Path | str) -> OrderedDict:
85
+ return dotenv_values(env_path)
70
86
 
71
87
  def get_user_env (self, user_env_file: Path | str, fallback_to_persisted_env: bool = True) -> dict:
72
88
  if user_env_file is not None and isinstance(user_env_file, str):
@@ -80,19 +96,19 @@ class EnvService:
80
96
  return user_env
81
97
 
82
98
  @staticmethod
83
- def get_dev_edition_source_core(env_dict: dict | None) -> str:
99
+ def get_dev_edition_source_core(env_dict: dict | None) -> DeveloperEditionSources | str:
84
100
  if not env_dict:
85
- return "myibm"
101
+ return DeveloperEditionSources.MYIBM
86
102
 
87
103
  source = env_dict.get("WO_DEVELOPER_EDITION_SOURCE")
88
104
 
89
105
  if source:
90
106
  return source
91
107
  if env_dict.get("WO_INSTANCE"):
92
- return "orchestrate"
93
- return "myibm"
108
+ return DeveloperEditionSources.ORCHESTRATE
109
+ return DeveloperEditionSources.MYIBM
94
110
 
95
- def get_dev_edition_source(self, user_env_file: str):
111
+ def get_dev_edition_source(self, user_env_file: str) -> DeveloperEditionSources | str:
96
112
  return self.get_dev_edition_source_core(self.get_user_env(user_env_file))
97
113
 
98
114
  @staticmethod
@@ -105,17 +121,35 @@ class EnvService:
105
121
 
106
122
  return merged
107
123
 
124
+ @staticmethod
125
+ def resolve_auth_type (env_dict: dict) -> str | None:
126
+ auth_type = env_dict.get("WO_AUTH_TYPE")
127
+
128
+ # Try infer the auth type if not provided
129
+ if not auth_type:
130
+ instance_url = env_dict.get("WO_INSTANCE")
131
+ if instance_url:
132
+ if ".cloud.ibm.com" in instance_url:
133
+ auth_type = EnvironmentAuthType.IBM_CLOUD_IAM.value
134
+ elif ".ibm.com" in instance_url:
135
+ auth_type = EnvironmentAuthType.MCSP.value
136
+ elif "https://cpd" in instance_url:
137
+ auth_type = EnvironmentAuthType.CPD.value
138
+
139
+ return auth_type
140
+
108
141
  @staticmethod
109
142
  def __get_default_registry_env_vars_by_dev_edition_source (default_env: dict, user_env: dict, source: str) -> dict[str, str]:
110
143
  component_registry_var_names = {key for key in default_env if key.endswith("_REGISTRY")} | {'REGISTRY_URL'}
111
144
 
112
145
  registry_url = user_env.get("REGISTRY_URL", None)
146
+ user_env["HAS_USER_PROVIDED_REGISTRY_URL"] = registry_url is not None
113
147
  if not registry_url:
114
- if source == "internal":
148
+ if source == DeveloperEditionSources.INTERNAL:
115
149
  registry_url = "us.icr.io/watson-orchestrate-private"
116
- elif source == "myibm":
150
+ elif source == DeveloperEditionSources.MYIBM:
117
151
  registry_url = "cp.icr.io/cp/wxo-lite"
118
- elif source == "orchestrate":
152
+ elif source == DeveloperEditionSources.ORCHESTRATE:
119
153
  # extract the hostname from the WO_INSTANCE URL, and replace the "api." prefix with "registry." to construct the registry URL per region
120
154
  wo_url = user_env.get("WO_INSTANCE")
121
155
 
@@ -123,15 +157,34 @@ class EnvService:
123
157
  raise ValueError(
124
158
  "WO_INSTANCE is required in the environment file if the developer edition source is set to 'orchestrate'.")
125
159
 
126
- parsed = urlparse(wo_url)
127
- hostname = parsed.hostname
160
+ wo_auth_type = EnvService.resolve_auth_type(user_env)
161
+
162
+ if wo_auth_type == EnvironmentAuthType.CPD.value:
163
+ registry_url = "cpd/cp/wxo-lite"
128
164
 
129
- registry_url = f"registry.{hostname[4:]}/cp/wxo-lite"
165
+ else:
166
+ parsed = urlparse(wo_url)
167
+ hostname = parsed.hostname
168
+
169
+ registry_url = f"registry.{hostname[4:]}/cp/wxo-lite"
170
+ elif source == DeveloperEditionSources.CUSTOM:
171
+ registry_url = user_env.get("CUSTOM_REGISTRY_URL")
172
+ if not registry_url:
173
+ raise ValueError(
174
+ f"REGISTRY_URL is required in the environment file when the developer edition source is set to 'custom'."
175
+ )
130
176
  else:
131
177
  raise ValueError(
132
- f"Unknown value for developer edition source: {source}. Must be one of ['internal', 'myibm', 'orchestrate']."
178
+ f"Unknown value for developer edition source: {source}. Must be one of {list(map(str, DeveloperEditionSources))}."
133
179
  )
134
-
180
+
181
+ # For non-custom use cases remove etcd and elastic search as they have different default registries
182
+ if source != DeveloperEditionSources.CUSTOM:
183
+ component_registry_var_names -= {"ETCD_REGISTRY", "ELASTICSEARCH_REGISTRY"}
184
+ # In the custom case default the OPENSOURCE_REGISTRY_PROXY to also be the REGISTRY_URL
185
+ else:
186
+ component_registry_var_names.add("OPENSOURCE_REGISTRY_PROXY")
187
+
135
188
  result = {name: registry_url for name in component_registry_var_names}
136
189
  return result
137
190
 
@@ -145,21 +198,28 @@ class EnvService:
145
198
 
146
199
  @staticmethod
147
200
  def write_merged_env_file (merged_env: dict, target_path: str = None) -> Path:
201
+ target_file = None
148
202
  if target_path:
149
- file = open(target_path, "w")
203
+ target_file = target_path
204
+
150
205
  else:
151
- file = tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".env")
206
+ with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".env") as ntf:
207
+ target_file = ntf.name
152
208
 
153
- with file:
209
+ with open(target_file, "w") as file:
154
210
  for key, val in merged_env.items():
155
211
  file.write(f"{key}={val}\n")
156
- return Path(file.name)
157
212
 
158
- def persist_user_env (self, env: dict, include_secrets: bool = False) -> None:
213
+ return Path(target_file)
214
+
215
+ def persist_user_env (self, env: dict, include_secrets: bool = False, source: DeveloperEditionSources| str | None = None) -> None:
159
216
  if include_secrets:
160
217
  persistable_env = env
161
218
  else:
162
219
  persistable_env = {k: env[k] for k in EnvService.__NON_SECRET_ENV_ITEMS if k in env}
220
+
221
+ if source == DeveloperEditionSources.CUSTOM and "REGISTRY_URL" in env:
222
+ persistable_env["CUSTOM_REGISTRY_URL"] = env.get("REGISTRY_URL")
163
223
 
164
224
  self.__config.save(
165
225
  {
@@ -367,3 +427,88 @@ class EnvService:
367
427
 
368
428
  def define_saas_wdu_runtime (self, value: str = "none") -> None:
369
429
  self.__config.write(USER_ENV_CACHE_HEADER, "SAAS_WDU_RUNTIME", value)
430
+
431
+ @staticmethod
432
+ def did_user_provide_registry_url (env_dict: dict) -> bool:
433
+ has_user_provided_registry_url = parse_bool_safe(env_dict.get("HAS_USER_PROVIDED_REGISTRY_URL"), fallback=None)
434
+
435
+ if has_user_provided_registry_url is None:
436
+ raise Exception("Unable to determine if user has provided REGISTRY_URL.")
437
+
438
+ return has_user_provided_registry_url
439
+
440
+
441
+ class EnvSettingsService:
442
+
443
+ @staticmethod
444
+ def __get_string_safe(value) -> str | None:
445
+ if value is not None and isinstance(value, str):
446
+ value = value.strip()
447
+
448
+ if value == "":
449
+ value = None
450
+
451
+ return value
452
+
453
+ return None
454
+
455
+ def __init__(self, env_file: Path | str) -> None:
456
+ self.__env_dict = dotenv_values(str(env_file))
457
+
458
+ def get_env(self) -> dict:
459
+ return self.__env_dict
460
+
461
+ def get_user_provided_docker_os_type(self) -> str | None:
462
+ return self.__get_string_safe(self.__env_dict.get("DOCKER_IMAGE_OS_TYPE"))
463
+
464
+ def get_user_provided_docker_arch_type(self) -> str | None:
465
+ return self.__get_string_safe(self.__env_dict.get("DOCKER_IMAGE_ARCH_TYPE"))
466
+
467
+ def get_wo_instance_url(self) -> str:
468
+ return self.__env_dict["WO_INSTANCE"]
469
+
470
+ def get_parsed_wo_instance_details(self) -> Tuple[str, str, str, str]:
471
+ instance_url = self.get_wo_instance_url()
472
+ parsed = urlparse(instance_url)
473
+ route_parts = parsed.path.split("/")
474
+
475
+ orchestrate_namespace = route_parts[2] # this is usually "cpd-instance-1"
476
+ wxo_tenant_id = route_parts[4]
477
+
478
+ return parsed.scheme, parsed.netloc, orchestrate_namespace, wxo_tenant_id
479
+
480
+ def get_wo_username(self) -> str:
481
+ return self.__env_dict.get("WO_USERNAME")
482
+
483
+ def get_wo_password(self) -> str:
484
+ return self.__env_dict.get("WO_PASSWORD")
485
+
486
+ def get_wo_api_key(self) -> str:
487
+ return self.__env_dict.get("WO_API_KEY")
488
+
489
+ def use_parallel_docker_image_layer_pulls(self):
490
+ return parse_bool_safe(value=self.__env_dict.get("DOCKER_IMAGE_PULL_LAYERS_PARALLELISM"), fallback=True)
491
+
492
+ def get_docker_pull_parallel_worker_count(self):
493
+ fallback = 7
494
+ parsed = parse_int_safe(value=self.__env_dict.get("DOCKER_IMAGE_PULL_PARALLEL_WORKERS_COUNT"),
495
+ fallback=fallback)
496
+
497
+ if parsed < 1:
498
+ parsed = fallback
499
+
500
+ return parsed
501
+
502
+ def use_ranged_requests_during_docker_pulls(self):
503
+ return parse_bool_safe(value=self.__env_dict.get("USE_RANGE_REQUESTS_IN_DOCKER_IMAGE_PULLS"), fallback=True)
504
+
505
+ def get_wo_instance_ssl_verify(self) -> bool | str:
506
+ ssl_verify, path = parse_bool_safe_and_get_raw_val(value=self.__env_dict.get("WO_VERIFY_SSL"), fallback=True)
507
+ if ssl_verify is True and path is not None and isinstance(path, str):
508
+ if not os.path.exists(path) or not os.path.isfile(path):
509
+ logger.error(f"WO SSL verification certificate path not found or could not be accessed: {str(path)}")
510
+ sys.exit(1)
511
+
512
+ return str(path)
513
+
514
+ return ssl_verify
@@ -20,4 +20,4 @@ class BadRequest(Exception):
20
20
  return "PYTEST_CURRENT_TEST" in os.environ
21
21
 
22
22
  def __str__(self):
23
- return self.message
23
+ return self.message
@@ -0,0 +1,51 @@
1
+ from datetime import timezone, datetime
2
+ from urllib.parse import urlparse
3
+
4
+ import jwt
5
+
6
+ from ibm_watsonx_orchestrate.cli.commands.environment.types import EnvironmentAuthType
7
+ from ibm_watsonx_orchestrate.client.client import Client
8
+ from ibm_watsonx_orchestrate.client.client_errors import ClientError
9
+ from ibm_watsonx_orchestrate.client.credentials import Credentials
10
+ from ibm_watsonx_orchestrate.utils.environment import EnvSettingsService
11
+
12
+
13
+ class CpdWxOTokenService:
14
+
15
+ def __init__ (self, env_settings: EnvSettingsService):
16
+ self.__token = None
17
+ self.__token_exp_at = None
18
+ self.__env_settings = env_settings
19
+
20
+ def get_token (self) -> str:
21
+ if self.__token is None or self.__has_token_expired():
22
+ self.__refresh_token()
23
+
24
+ return self.__token
25
+
26
+ def __has_token_expired (self) -> bool:
27
+ return self.__token is None or self.__token_exp_at is None or datetime.now(
28
+ timezone.utc).timestamp() >= self.__token_exp_at
29
+
30
+ def __refresh_token (self) -> None:
31
+ try:
32
+ self.__token = None
33
+ self.__token_exp_at = None
34
+
35
+ creds = Credentials(
36
+ url=self.__env_settings.get_wo_instance_url(),
37
+ api_key=self.__env_settings.get_wo_api_key(),
38
+ username=self.__env_settings.get_wo_username(),
39
+ password=self.__env_settings.get_wo_password(),
40
+ iam_url=None,
41
+ auth_type=EnvironmentAuthType.CPD
42
+ )
43
+
44
+ client = Client(creds)
45
+ self.__token = client.token
46
+
47
+ decoded_token = jwt.decode(self.__token, options={"verify_signature": False})
48
+ self.__token_exp_at = decoded_token.get("exp")
49
+
50
+ except ClientError as ex:
51
+ raise ClientError(ex)
@@ -1,7 +1,7 @@
1
1
  import re
2
2
  import zipfile
3
3
  import yaml
4
- from typing import BinaryIO
4
+ from typing import BinaryIO, Any, Tuple
5
5
 
6
6
  # disables the automatic conversion of date-time objects to datetime objects and leaves them as strings
7
7
  yaml.constructor.SafeConstructor.yaml_constructors[u'tag:yaml.org,2002:timestamp'] = \
@@ -11,8 +11,67 @@ 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
- sanatize_pattern = re.compile(r"[^a-zA-Z0-9]+")
15
- return re.sub(sanatize_pattern,'_', app_id)
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
- return any(x.startswith("%s/" % file_path.rstrip("/")) for x in zip_file.namelist())
22
+ return any(x.startswith("%s/" % file_path.rstrip("/")) for x in zip_file.namelist())
23
+
24
+ def parse_bool_safe (value, fallback = False) -> bool:
25
+ if value is not None:
26
+ if isinstance(value, bool):
27
+ return value
28
+
29
+ elif isinstance(value, str):
30
+ value = value.lower().strip()
31
+ if value in ("yes", "true", "t", "1"):
32
+ return True
33
+
34
+ elif value in ("no", "false", "f", "0"):
35
+ return False
36
+
37
+ elif value in (0, 1):
38
+ return parse_bool_safe(str(value), fallback)
39
+
40
+ return fallback
41
+
42
+ def parse_bool_safe_and_get_raw_val (value, fallback: bool = False) -> Tuple[bool, Any | None]:
43
+ if value is not None:
44
+ if isinstance(value, bool):
45
+ return value, None
46
+
47
+ elif isinstance(value, str):
48
+ value_str = value.lower().strip()
49
+ if value_str in ("yes", "true", "t", "1"):
50
+ return True, None
51
+
52
+ elif value_str in ("no", "false", "f", "0"):
53
+ return False, None
54
+
55
+ elif value in (0, 1):
56
+ return parse_bool_safe_and_get_raw_val(str(value), fallback)
57
+
58
+ return fallback, value
59
+
60
+ def parse_int_safe (value, base: int = 10, fallback: int | None = None) -> int:
61
+ if value is not None:
62
+ if isinstance(value, int):
63
+ return value
64
+
65
+ elif isinstance(value, float):
66
+ return int(value)
67
+
68
+ elif isinstance(value, str):
69
+ value = value.strip()
70
+
71
+ try:
72
+ return int(value, base)
73
+
74
+ except ValueError as ex:
75
+ pass
76
+
77
+ return fallback
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ibm-watsonx-orchestrate
3
- Version: 1.12.0b0
3
+ Version: 1.13.0b0
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.2
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