ibm-watsonx-orchestrate 1.10.0b0__py3-none-any.whl → 1.10.0b1__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 (27) hide show
  1. ibm_watsonx_orchestrate/__init__.py +1 -1
  2. ibm_watsonx_orchestrate/agent_builder/connections/__init__.py +1 -1
  3. ibm_watsonx_orchestrate/agent_builder/connections/connections.py +1 -1
  4. ibm_watsonx_orchestrate/agent_builder/connections/types.py +16 -12
  5. ibm_watsonx_orchestrate/agent_builder/knowledge_bases/types.py +47 -3
  6. ibm_watsonx_orchestrate/agent_builder/toolkits/types.py +18 -15
  7. ibm_watsonx_orchestrate/agent_builder/tools/types.py +1 -1
  8. ibm_watsonx_orchestrate/cli/commands/connections/connections_command.py +7 -7
  9. ibm_watsonx_orchestrate/cli/commands/connections/connections_controller.py +36 -26
  10. ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_controller.py +32 -10
  11. ibm_watsonx_orchestrate/cli/commands/server/server_command.py +95 -14
  12. ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_command.py +43 -10
  13. ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_controller.py +52 -25
  14. ibm_watsonx_orchestrate/client/connections/connections_client.py +4 -3
  15. ibm_watsonx_orchestrate/client/knowledge_bases/knowledge_base_client.py +4 -4
  16. ibm_watsonx_orchestrate/docker/compose-lite.yml +48 -13
  17. ibm_watsonx_orchestrate/docker/default.env +18 -13
  18. ibm_watsonx_orchestrate/flow_builder/flows/__init__.py +2 -0
  19. ibm_watsonx_orchestrate/flow_builder/flows/flow.py +91 -12
  20. ibm_watsonx_orchestrate/flow_builder/node.py +39 -15
  21. ibm_watsonx_orchestrate/flow_builder/types.py +114 -25
  22. ibm_watsonx_orchestrate/run/connections.py +2 -2
  23. {ibm_watsonx_orchestrate-1.10.0b0.dist-info → ibm_watsonx_orchestrate-1.10.0b1.dist-info}/METADATA +1 -1
  24. {ibm_watsonx_orchestrate-1.10.0b0.dist-info → ibm_watsonx_orchestrate-1.10.0b1.dist-info}/RECORD +27 -27
  25. {ibm_watsonx_orchestrate-1.10.0b0.dist-info → ibm_watsonx_orchestrate-1.10.0b1.dist-info}/WHEEL +0 -0
  26. {ibm_watsonx_orchestrate-1.10.0b0.dist-info → ibm_watsonx_orchestrate-1.10.0b1.dist-info}/entry_points.txt +0 -0
  27. {ibm_watsonx_orchestrate-1.10.0b0.dist-info → ibm_watsonx_orchestrate-1.10.0b1.dist-info}/licenses/LICENSE +0 -0
@@ -332,7 +332,6 @@ def write_merged_env_file(merged_env: dict, target_path: str = None) -> Path:
332
332
  file.write(f"{key}={val}\n")
333
333
  return Path(file.name)
334
334
 
335
-
336
335
  def get_dbtag_from_architecture(merged_env_dict: dict) -> str:
337
336
  """Detects system architecture and returns the corresponding DBTAG."""
338
337
  arch = platform.machine()
@@ -375,7 +374,8 @@ def run_compose_lite(
375
374
  experimental_with_langfuse=False,
376
375
  experimental_with_ibm_telemetry=False,
377
376
  with_doc_processing=False,
378
- with_voice=False
377
+ with_voice=False,
378
+ experimental_with_langflow=False,
379
379
  ) -> None:
380
380
  compose_path = get_compose_file()
381
381
 
@@ -404,7 +404,11 @@ def run_compose_lite(
404
404
  logger.info("Database container started successfully. Now starting other services...")
405
405
 
406
406
 
407
- # Step 2: Start all remaining services (except DB)
407
+ # Step 2: Create Langflow DB (if enabled)
408
+ if experimental_with_langflow:
409
+ create_langflow_db()
410
+
411
+ # Step 3: Start all remaining services (except DB)
408
412
  profiles = []
409
413
  if experimental_with_langfuse:
410
414
  profiles.append("langfuse")
@@ -414,6 +418,8 @@ def run_compose_lite(
414
418
  profiles.append("docproc")
415
419
  if with_voice:
416
420
  profiles.append("voice")
421
+ if experimental_with_langflow:
422
+ profiles.append("langflow")
417
423
 
418
424
  command = compose_command[:]
419
425
  for profile in profiles:
@@ -665,7 +671,6 @@ def run_compose_lite_down(final_env_file: Path, is_reset: bool = False) -> None:
665
671
  )
666
672
  sys.exit(1)
667
673
 
668
-
669
674
  def run_compose_lite_logs(final_env_file: Path, is_reset: bool = False) -> None:
670
675
  compose_path = get_compose_file()
671
676
  compose_command = ensure_docker_compose_installed()
@@ -866,6 +871,12 @@ def server_start(
866
871
  '--with-voice', '-v',
867
872
  help='Enable voice controller to interact with the chat via voice channels'
868
873
  ),
874
+ experimental_with_langflow: bool = typer.Option(
875
+ False,
876
+ '--experimental-with-langflow',
877
+ help='(Experimental) Enable Langflow UI, available at http://localhost:7861',
878
+ hidden=True
879
+ ),
869
880
  ):
870
881
  confirm_accepts_license_agreement(accept_terms_and_conditions)
871
882
 
@@ -907,6 +918,9 @@ def server_start(
907
918
  if experimental_with_ibm_telemetry:
908
919
  merged_env_dict['USE_IBM_TELEMETRY'] = 'true'
909
920
 
921
+ if experimental_with_langflow:
922
+ merged_env_dict['LANGFLOW_ENABLED'] = 'true'
923
+
910
924
 
911
925
  try:
912
926
  dev_edition_source = get_dev_edition_source(merged_env_dict)
@@ -921,7 +935,8 @@ def server_start(
921
935
  experimental_with_langfuse=experimental_with_langfuse,
922
936
  experimental_with_ibm_telemetry=experimental_with_ibm_telemetry,
923
937
  with_doc_processing=with_doc_processing,
924
- with_voice=with_voice)
938
+ with_voice=with_voice,
939
+ experimental_with_langflow=experimental_with_langflow)
925
940
 
926
941
  run_db_migration()
927
942
 
@@ -951,6 +966,8 @@ def server_start(
951
966
  logger.info(f"You can access the observability platform Langfuse at http://localhost:3010, username: orchestrate@ibm.com, password: orchestrate")
952
967
  if with_doc_processing:
953
968
  logger.info(f"Document processing in Flows (Public Preview) has been enabled.")
969
+ if experimental_with_langflow:
970
+ logger.info("Langflow has been enabled, the Langflow UI is available at http://localhost:7861")
954
971
 
955
972
  @server_app.command(name="stop")
956
973
  def server_stop(
@@ -1031,15 +1048,11 @@ def run_db_migration() -> None:
1031
1048
  merged_env_dict['ROUTING_LLM_API_KEY'] = ''
1032
1049
  merged_env_dict['ASSISTANT_LLM_API_KEY'] = ''
1033
1050
  final_env_file = write_merged_env_file(merged_env_dict)
1051
+
1034
1052
 
1035
- command = compose_command + [
1036
- "-f", str(compose_path),
1037
- "--env-file", str(final_env_file),
1038
- "exec",
1039
- "wxo-server-db",
1040
- "bash",
1041
- "-c",
1042
- '''
1053
+ pg_user = merged_env_dict.get("POSTGRES_USER","postgres")
1054
+
1055
+ migration_command = f'''
1043
1056
  APPLIED_MIGRATIONS_FILE="/var/lib/postgresql/applied_migrations/applied_migrations.txt"
1044
1057
  touch "$APPLIED_MIGRATIONS_FILE"
1045
1058
 
@@ -1050,7 +1063,7 @@ def run_db_migration() -> None:
1050
1063
  echo "Skipping already applied migration: $filename"
1051
1064
  else
1052
1065
  echo "Applying migration: $filename"
1053
- if psql -U postgres -d postgres -q -f "$file" > /dev/null 2>&1; then
1066
+ if psql -U {pg_user} -d postgres -q -f "$file" > /dev/null 2>&1; then
1054
1067
  echo "$filename" >> "$APPLIED_MIGRATIONS_FILE"
1055
1068
  else
1056
1069
  echo "Error applying $filename. Stopping migrations."
@@ -1059,6 +1072,15 @@ def run_db_migration() -> None:
1059
1072
  fi
1060
1073
  done
1061
1074
  '''
1075
+
1076
+ command = compose_command + [
1077
+ "-f", str(compose_path),
1078
+ "--env-file", str(final_env_file),
1079
+ "exec",
1080
+ "wxo-server-db",
1081
+ "bash",
1082
+ "-c",
1083
+ migration_command
1062
1084
  ]
1063
1085
 
1064
1086
  logger.info("Running Database Migration...")
@@ -1073,6 +1095,65 @@ def run_db_migration() -> None:
1073
1095
  )
1074
1096
  sys.exit(1)
1075
1097
 
1098
+ def create_langflow_db() -> None:
1099
+ compose_path = get_compose_file()
1100
+ compose_command = ensure_docker_compose_installed()
1101
+ default_env_path = get_default_env_file()
1102
+ merged_env_dict = merge_env(default_env_path, user_env_path=None)
1103
+ merged_env_dict['WATSONX_SPACE_ID']='X'
1104
+ merged_env_dict['WATSONX_APIKEY']='X'
1105
+ merged_env_dict['WXAI_API_KEY'] = ''
1106
+ merged_env_dict['ASSISTANT_EMBEDDINGS_API_KEY'] = ''
1107
+ merged_env_dict['ASSISTANT_LLM_SPACE_ID'] = ''
1108
+ merged_env_dict['ROUTING_LLM_SPACE_ID'] = ''
1109
+ merged_env_dict['USE_SAAS_ML_TOOLS_RUNTIME'] = ''
1110
+ merged_env_dict['BAM_API_KEY'] = ''
1111
+ merged_env_dict['ASSISTANT_EMBEDDINGS_SPACE_ID'] = ''
1112
+ merged_env_dict['ROUTING_LLM_API_KEY'] = ''
1113
+ merged_env_dict['ASSISTANT_LLM_API_KEY'] = ''
1114
+ final_env_file = write_merged_env_file(merged_env_dict)
1115
+
1116
+ pg_timeout = merged_env_dict.get('POSTGRES_READY_TIMEOUT','10')
1117
+
1118
+ pg_user = merged_env_dict.get("POSTGRES_USER","postgres")
1119
+
1120
+ creation_command = f"""
1121
+ echo 'Waiting for pg to initialize...'
1122
+
1123
+ timeout={pg_timeout}
1124
+ while [[ -z `pg_isready | grep 'accepting connections'` ]] && (( timeout > 0 )); do
1125
+ ((timeout-=1)) && sleep 1;
1126
+ done
1127
+
1128
+ if psql -U {pg_user} -lqt | cut -d \\| -f 1 | grep -qw langflow; then
1129
+ echo 'Existing Langflow DB found'
1130
+ else
1131
+ echo 'Creating Langflow DB'
1132
+ createdb -U "{pg_user}" -O "{pg_user}" langflow;
1133
+ psql -U {pg_user} -q -d postgres -c "GRANT CONNECT ON DATABASE langflow TO {pg_user}";
1134
+ fi
1135
+ """
1136
+ command = compose_command + [
1137
+ "-f", str(compose_path),
1138
+ "--env-file", str(final_env_file),
1139
+ "exec",
1140
+ "wxo-server-db",
1141
+ "bash",
1142
+ "-c",
1143
+ creation_command
1144
+ ]
1145
+
1146
+ logger.info("Preparing Langflow resources...")
1147
+ result = subprocess.run(command, capture_output=False)
1148
+
1149
+ if result.returncode == 0:
1150
+ logger.info("Langflow resources sucessfully created")
1151
+ else:
1152
+ error_message = result.stderr.decode('utf-8') if result.stderr else "Error occurred."
1153
+ logger.error(
1154
+ f"Failed to create Langflow resources\n{error_message}"
1155
+ )
1156
+ sys.exit(1)
1076
1157
 
1077
1158
  def bump_file_iteration(filename: str) -> str:
1078
1159
  regex = re.compile(f"^(?P<name>[^\\(\\s\\.\\)]+)(\\((?P<num>\\d+)\\))?(?P<type>\\.(?:{'|'.join(_EXPORT_FILE_TYPES)}))?$")
@@ -1,7 +1,7 @@
1
1
  import typer
2
2
  from typing import List
3
3
  from typing_extensions import Annotated, Optional
4
- from ibm_watsonx_orchestrate.agent_builder.toolkits.types import ToolkitKind, Language
4
+ from ibm_watsonx_orchestrate.agent_builder.toolkits.types import ToolkitKind, Language, ToolkitTransportKind
5
5
  from ibm_watsonx_orchestrate.cli.commands.toolkit.toolkit_controller import ToolkitController
6
6
  import logging
7
7
  import sys
@@ -45,6 +45,14 @@ def import_toolkit(
45
45
  "The first argument will be used as the executable, the rest as its arguments."
46
46
  ),
47
47
  ] = None,
48
+ url: Annotated[
49
+ Optional[str],
50
+ typer.Option("--url", "-u", help="The URL of the remote MCP server", hidden=True),
51
+ ] = None,
52
+ transport: Annotated[
53
+ ToolkitTransportKind,
54
+ typer.Option("--transport", help="The communication protocol to use for the remote MCP server. Only \"sse\" or \"streamable_http\" supported", hidden=True),
55
+ ] = None,
48
56
  tools: Annotated[
49
57
  Optional[str],
50
58
  typer.Option("--tools", "-t", help="Comma-separated list of tools to import. Or you can use \"*\" to use all tools"),
@@ -64,18 +72,41 @@ def import_toolkit(
64
72
  else:
65
73
  tool_list = None
66
74
 
67
- if not package and not package_root and not command:
68
- logger.error("You must provide either '--package', '--package-root' or '--command'.")
69
- sys.exit(1)
75
+ if not url and not transport:
76
+ if not package and not package_root and not command:
77
+ logger.error("You must provide either '--package', '--package-root' or '--command'.")
78
+ sys.exit(1)
70
79
 
71
- if package_root and not command:
72
- logger.error("Error: '--command' flag must be provided when '--package-root' is specified.")
73
- sys.exit(1)
74
-
75
- if package_root and package:
76
- logger.error("Please choose either '--package-root' or '--package' but not both.")
80
+ if package_root and not command:
81
+ logger.error("Error: '--command' flag must be provided when '--package-root' is specified.")
82
+ sys.exit(1)
83
+
84
+ if package_root and package:
85
+ logger.error("Please choose either '--package-root' or '--package' but not both.")
86
+ sys.exit(1)
87
+
88
+ if (url and not transport) or (transport and not url):
89
+ logger.error("Both '--url' and '--transport' must be provided together for remote MCP.")
77
90
  sys.exit(1)
78
91
 
92
+ if url and transport:
93
+ forbidden_local_opts = []
94
+ if package:
95
+ forbidden_local_opts.append("--package")
96
+ if package_root:
97
+ forbidden_local_opts.append("--package-root")
98
+ if language:
99
+ forbidden_local_opts.append("--language")
100
+ if command:
101
+ forbidden_local_opts.append("--command")
102
+
103
+ if forbidden_local_opts:
104
+ logger.error(
105
+ f"When using '--url' and '--transport' for a remote MCP, you cannot specify: "
106
+ f"{', '.join(forbidden_local_opts)}"
107
+ )
108
+ sys.exit(1)
109
+
79
110
  if package and not package_root:
80
111
  if not command:
81
112
  if language == Language.NODE:
@@ -97,6 +128,8 @@ def import_toolkit(
97
128
  package_root=package_root,
98
129
  language=language,
99
130
  command=command,
131
+ url=url,
132
+ transport=transport
100
133
  )
101
134
  toolkit_controller.import_toolkit(tools=tool_list, app_id=app_id)
102
135
 
@@ -10,7 +10,7 @@ import requests
10
10
  from ibm_watsonx_orchestrate.client.toolkit.toolkit_client import ToolKitClient
11
11
  from ibm_watsonx_orchestrate.client.tools.tool_client import ToolClient
12
12
  from ibm_watsonx_orchestrate.agent_builder.toolkits.base_toolkit import BaseToolkit, ToolkitSpec
13
- from ibm_watsonx_orchestrate.agent_builder.toolkits.types import ToolkitKind, Language, ToolkitSource
13
+ from ibm_watsonx_orchestrate.agent_builder.toolkits.types import ToolkitKind, Language, ToolkitSource, ToolkitTransportKind
14
14
  from ibm_watsonx_orchestrate.client.utils import instantiate_client
15
15
  from ibm_watsonx_orchestrate.utils.utils import sanatize_app_id
16
16
  from ibm_watsonx_orchestrate.client.connections import get_connections_client
@@ -26,15 +26,16 @@ import json
26
26
 
27
27
  logger = logging.getLogger(__name__)
28
28
 
29
- def get_connection_id(app_id: str) -> str:
29
+ def get_connection_id(app_id: str, is_local_mcp: bool) -> str:
30
30
  connections_client = get_connections_client()
31
31
  existing_draft_configuration = connections_client.get_config(app_id=app_id, env='draft')
32
32
  existing_live_configuration = connections_client.get_config(app_id=app_id, env='live')
33
33
 
34
34
  for config in [existing_draft_configuration, existing_live_configuration]:
35
- if config and config.security_scheme != 'key_value_creds':
36
- logger.error("Only key_value credentials are currently supported")
37
- exit(1)
35
+ if is_local_mcp is True:
36
+ if config and config.security_scheme != 'key_value_creds':
37
+ logger.error("Only key_value credentials are currently supported for local MCP")
38
+ exit(1)
38
39
  connection_id = None
39
40
  if app_id is not None:
40
41
  connection = connections_client.get(app_id=app_id)
@@ -59,6 +60,8 @@ class ToolkitController:
59
60
  package_root: str = None,
60
61
  language: Language = None,
61
62
  command: str = None,
63
+ url: str = None,
64
+ transport: ToolkitTransportKind = None
62
65
  ):
63
66
  self.kind = kind
64
67
  self.name = name
@@ -68,6 +71,8 @@ class ToolkitController:
68
71
  self.language = language
69
72
  self.command = command
70
73
  self.client = None
74
+ self.url = url
75
+ self.transport = transport
71
76
 
72
77
  self.source: ToolkitSource = (
73
78
  ToolkitSource.FILES if package_root else ToolkitSource.PUBLIC_REGISTRY
@@ -95,15 +100,23 @@ class ToolkitController:
95
100
  logger.error(f"Existing toolkit found with name '{self.name}'. Failed to create toolkit.")
96
101
  sys.exit(1)
97
102
 
98
- try:
99
- command_parts = json.loads(self.command)
100
- if not isinstance(command_parts, list):
101
- raise ValueError("JSON command must be a list of strings")
102
- except (json.JSONDecodeError, ValueError):
103
- command_parts = self.command.split()
103
+ if not self.command:
104
+ command_parts = []
105
+ else:
106
+ try:
107
+ command_parts = json.loads(self.command)
108
+ if not isinstance(command_parts, list):
109
+ raise ValueError("JSON command must be a list of strings")
110
+ except (json.JSONDecodeError, ValueError):
111
+ command_parts = self.command.split()
112
+
113
+ if command_parts:
114
+ command = command_parts[0]
115
+ args = command_parts[1:]
116
+ else:
117
+ command = None
118
+ args = []
104
119
 
105
- command = command_parts[0]
106
- args = command_parts[1:]
107
120
 
108
121
  if self.package_root:
109
122
  is_folder = os.path.isdir(self.package_root)
@@ -150,18 +163,31 @@ class ToolkitController:
150
163
  console.print(f" • {tool}")
151
164
 
152
165
  # Create toolkit metadata
153
- payload = {
154
- "name": self.name,
155
- "description": self.description,
156
- "mcp": {
157
- "source": self.source.value,
158
- "command": command,
159
- "args": args,
160
- "tools": tools,
161
- "connections": remapped_connections,
166
+ payload = {}
167
+
168
+ if self.transport is not None and self.url is not None:
169
+ payload = {
170
+ "name": self.name,
171
+ "description": self.description,
172
+ "mcp": {
173
+ "server_url": self.url,
174
+ "transport": self.transport.value,
175
+ "tools": tools,
176
+ "connections": remapped_connections,
177
+ }
178
+ }
179
+ else:
180
+ payload = {
181
+ "name": self.name,
182
+ "description": self.description,
183
+ "mcp": {
184
+ "source": self.source.value,
185
+ "command": command,
186
+ "args": args,
187
+ "tools": tools,
188
+ "connections": remapped_connections,
189
+ }
162
190
  }
163
- }
164
-
165
191
 
166
192
  with Progress(
167
193
  SpinnerColumn(spinner_name="dots"),
@@ -215,7 +241,8 @@ class ToolkitController:
215
241
  raise typer.BadParameter(f"The provided --app-id '{app_id}' is not valid. --app-id cannot be empty or whitespace")
216
242
 
217
243
  runtime_id = sanatize_app_id(runtime_id)
218
- app_id_dict[runtime_id] = get_connection_id(local_id)
244
+ is_local_mcp = self.package is not None or self.package_root is not None
245
+ app_id_dict[runtime_id] = get_connection_id(local_id, is_local_mcp)
219
246
 
220
247
  return app_id_dict
221
248
 
@@ -19,7 +19,7 @@ class FetchConfigAuthTypes(str, Enum):
19
19
  API_KEY_AUTH = ConnectionType.API_KEY_AUTH.value
20
20
  OAUTH2_AUTH_CODE = ConnectionType.OAUTH2_AUTH_CODE.value
21
21
  OAUTH2_IMPLICIT = 'oauth2_implicit'
22
- OAUTH2_PASSWORD = 'oauth2_password'
22
+ OAUTH2_PASSWORD = ConnectionType.OAUTH2_PASSWORD.value
23
23
  OAUTH2_CLIENT_CREDS = ConnectionType.OAUTH2_CLIENT_CREDS.value
24
24
  OAUTH_ON_BEHALF_OF_FLOW = ConnectionType.OAUTH_ON_BEHALF_OF_FLOW.value
25
25
  KEY_VALUE = ConnectionType.KEY_VALUE.value
@@ -50,7 +50,7 @@ class GetConfigResponse(BaseModel):
50
50
  class GetConnectionResponse(BaseModel):
51
51
  connection_id: str = None
52
52
  app_id: str = None
53
- tenant_id: str = None
53
+ tenant_id: Optional[str] = None
54
54
 
55
55
 
56
56
 
@@ -141,7 +141,8 @@ class ConnectionsClient(BaseAPIClient):
141
141
  else:
142
142
  return self._get(f"/connections/applications/runtime_credentials?app_id={app_id}&env={env}")
143
143
  except ClientAPIException as e:
144
- if e.response.status_code == 404:
144
+ # Returns 400 when app creds exist but runtime cred don't yet exist
145
+ if e.response.status_code == 404 or e.response.status_code == 400:
145
146
  return None
146
147
  raise e
147
148
 
@@ -15,10 +15,10 @@ class KnowledgeBaseClient(BaseAPIClient):
15
15
  self.base_endpoint = "/orchestrate/knowledge-bases" if is_local_dev(self.base_url) else "/knowledge-bases"
16
16
 
17
17
  def create(self, payload: dict) -> dict:
18
- return self._post_form_data(f"{self.base_endpoint}/documents", data={ "knowledge_base" : json.dumps(payload) })
18
+ return self._post_form_data(f"{self.base_endpoint}/documents", data=payload)
19
19
 
20
20
  def create_built_in(self, payload: dict, files: list) -> dict:
21
- return self._post_form_data(f"{self.base_endpoint}/documents", data={ "knowledge_base" : json.dumps(payload) }, files=files)
21
+ return self._post_form_data(f"{self.base_endpoint}/documents", data=payload, files=files)
22
22
 
23
23
  def get(self) -> dict:
24
24
  return self._get(self.base_endpoint)
@@ -38,10 +38,10 @@ class KnowledgeBaseClient(BaseAPIClient):
38
38
  return self._get(f"{self.base_endpoint}/{knowledge_base_id}/status")
39
39
 
40
40
  def update(self, knowledge_base_id: str, payload: dict) -> dict:
41
- return self._patch_form_data(f"{self.base_endpoint}/{knowledge_base_id}/documents", data={ "knowledge_base" : json.dumps(payload) })
41
+ return self._patch_form_data(f"{self.base_endpoint}/{knowledge_base_id}/documents", data=payload)
42
42
 
43
43
  def update_with_documents(self, knowledge_base_id: str, payload: dict, files: list) -> dict:
44
- return self._patch_form_data(f"{self.base_endpoint}/{knowledge_base_id}/documents", data={ "knowledge_base" : json.dumps(payload) }, files=files)
44
+ return self._patch_form_data(f"{self.base_endpoint}/{knowledge_base_id}/documents", data=payload, files=files)
45
45
 
46
46
  def delete(self, knowledge_base_id: str,) -> dict:
47
47
  return self._delete(f"{self.base_endpoint}/{knowledge_base_id}")
@@ -32,6 +32,7 @@ services:
32
32
  - wxo-applied-migrations:/var/lib/postgresql/applied_migrations
33
33
  command: -c shared_preload_libraries=pgsodium
34
34
 
35
+
35
36
  wxo-server-connection-manager:
36
37
  image: ${CM_REGISTRY:-us.icr.io/watson-orchestrate-private}/wxo-connections:${CM_TAG:-latest}
37
38
  platform: linux/amd64
@@ -128,8 +129,11 @@ services:
128
129
  IBM_DPS_CACHE_SERVICE: https://wxo-doc-processing-cache:8080
129
130
  DOCPROC_BASE_URL: http://wxo-doc-processing-infra-standalone:9080
130
131
  BUILDER_ASYNC_CALLBACK_ENDPOINT: http://wxo-builder:4025
132
+ DOCPROC_ENABLED: ${DOCPROC_ENABLED:-false}
131
133
  IS_OBSERVABILITY_FEATURE_ENABLED: "true"
132
134
  ALLOW_INSECURE_TLS: "true"
135
+ ENABLE_EDIT_PROMPTS: "true"
136
+ LANGFLOW_ENABLED: ${LANGFLOW_ENABLED:-false}
133
137
  command: 'npm start'
134
138
  ports:
135
139
  - "4025:4025"
@@ -261,6 +265,7 @@ services:
261
265
  - default
262
266
  - jaeger-network
263
267
  environment:
268
+ DEFAULT_AGENT_ENABLED: "true"
264
269
  RUNTIME_MANAGER_API_KEY: ${RUNTIME_MANAGER_API_KEY:-testapikey}
265
270
  PIP_NO_CACHE_DIR:
266
271
  JWT_SECRET: ${JWT_SECRET}
@@ -344,6 +349,7 @@ services:
344
349
  AGENTOPS_API_KEY: ${AGENTOPS_API_KEY}
345
350
  ES_HOST: http://elasticsearch:9200
346
351
  ORIGIN_HEADER: "internal"
352
+ LANGFLOW_ENABLED: ${LANGFLOW_ENABLED:-false}
347
353
 
348
354
  wxo-server-worker:
349
355
  image: ${WORKER_REGISTRY:-us.icr.io/watson-orchestrate-private}/wxo-server-conversation_controller:${WORKER_TAG:-latest}
@@ -441,6 +447,7 @@ services:
441
447
  USE_IBM_TELEMETRY: ${USE_IBM_TELEMETRY:-false}
442
448
  WXO_DEPLOYMENT_PLATFORM: saas
443
449
  CALLBACK_HOST_URL: ${CALLBACK_HOST_URL:-http://wxo-server:4321}
450
+ LANGFLOW_ENABLED: ${LANGFLOW_ENABLED:-false}
444
451
 
445
452
  tools-runtime-manager:
446
453
  image: ${TRM_REGISTRY:-us.icr.io/watson-orchestrate-private}/tools-runtime-manager:${TRM_TAG:-latest}
@@ -482,7 +489,8 @@ services:
482
489
  STORAGE_S3_REGION: us-east-1
483
490
  AWS_ACCESS_KEY_ID: ${MINIO_ROOT_USER:-minioadmin}
484
491
  AWS_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD:-watsonxorchestrate}
485
- TEMPUS_HOST_NAME: http://wxo-tempus-runtime:9044
492
+ TEMPUS_HOST_NAME: http://wxo-tempus-runtime:9044
493
+ LANGFLOW_ENABLED: ${LANGFLOW_ENABLED:-false}
486
494
  extra_hosts:
487
495
  - "host.docker.internal:host-gateway"
488
496
 
@@ -514,6 +522,7 @@ services:
514
522
  STORAGE_S3_REGION: us-east-1
515
523
  AWS_ACCESS_KEY_ID: ${MINIO_ROOT_USER:-minioadmin}
516
524
  AWS_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD:-watsonxorchestrate}
525
+ LANGFLOW_ENABLED: ${LANGFLOW_ENABLED:-false}
517
526
 
518
527
  ########################
519
528
  # IBM AGENT-OPS
@@ -792,6 +801,7 @@ services:
792
801
  LOG_LEVEL: info
793
802
  DOCPROC_ENABLED: ${DOCPROC_ENABLED:-false}
794
803
  DOCPROC_BASE_URL: http://wxo-doc-processing-infra-standalone:9080
804
+ DOCPROC_OUTPUT_FILE_SERVER_URL: ${DOCPROC_OUTPUT_FILE_SERVER_URL:-http://wxo-server:4321}
795
805
  WO_API_KEY: ${WO_API_KEY}
796
806
  WO_INSTANCE: ${WO_INSTANCE}
797
807
  AUTHORIZATION_URL: ${AUTHORIZATION_URL}
@@ -872,6 +882,19 @@ services:
872
882
  PREFLIGHT_MAX_SIZE: 10Mb
873
883
  PREFLIGHT_MAX_PAGES: 600
874
884
  RUNTIME_LIBRARY: "watson_doc_understanding"
885
+ WXAI_API_KEY: ${WXAI_API_KEY:-}
886
+ WXAI_IMAGE_DESCRIPTION_MODEL_ID: ${WXAI_IMAGE_DESCRIPTION_MODEL_ID:-mistralai/pixtral-12b}
887
+ WXAI_IMAGE_DESCRIPTION_PROJECT_ID: ${WXAI_IMAGE_DESCRIPTION_PROJECT_ID:-}
888
+ WXAI_KVP_MODEL_ID: ${WXAI_KVP_MODEL_ID:-}
889
+ WXAI_KVP_PROJECT_ID: ${WXAI_KVP_PROJECT_ID:-}
890
+ WXAI_SEMANTIC_KVP_PROJECT_ID: ${WXAI_SEMANTIC_KVP_PROJECT_ID:-}
891
+ WXAI_SEMANTIC_KVP_MODEL_ID: ${WXAI_SEMANTIC_KVP_MODEL_ID:-mistralai/pixtral-12b}
892
+ WXAI_SEMANTIC_KVP_SPACE_ID: ${WXAI_SEMANTIC_KVP_SPACE_ID:-}
893
+ WXAI_URL: ${WXAI_URL:-}
894
+ WXAI_USERNAME: ${WXAI_USERNAME:-}
895
+ WXAI_INSTANCE_ID: ${WXAI_INSTANCE_ID:-}
896
+ WXAI_VERSION: ${WXAI_VERSION:-5.1}
897
+
875
898
  profiles:
876
899
  - docproc
877
900
  ports:
@@ -1000,9 +1023,7 @@ services:
1000
1023
  SERVICE_NAME: wxo-doc-processing-llm-service
1001
1024
  LOG_LEVEL: info
1002
1025
  WATSONX_API_ENDPOINT: ${WATSONX_URL:-https://us-south.ml.cloud.ibm.com}
1003
- WATSONX_API_KEY: ${WATSONX_APIKEY}
1004
- WATSONX_PROJECT_ID: ${WATSONX_PROJECT_ID}
1005
- WATSONX_SPACE_ID: ${WATSONX_SPACE_ID}
1026
+ WXO_SERVER_BASE_URL : http://wxo-server:4321
1006
1027
  IBM_DPS_CACHE_SERVICE: 'wxo-doc-processing-cache:8080'
1007
1028
  profiles:
1008
1029
  - docproc
@@ -1096,15 +1117,28 @@ services:
1096
1117
  "
1097
1118
 
1098
1119
  wxo-server-voice:
1099
- image: ${VOICE_CONTROLLER_REGISTRY:-us.icr.io/watson-orchestrate-private}/wxo-server-voice:${VOICE_CONTROLLER_TAG:-latest}
1100
- profiles: [voice]
1101
- restart: unless-stopped
1102
- ports:
1103
- - 9876:8765
1104
- environment:
1105
- WXO_BASE_DOMAIN_URL: "http://wxo-server:4321"
1106
- AI_GATEWAY_URL: "http://ai-gateway:8787"
1107
- WXO_ORIGIN_HEADER: "internal"
1120
+ image: ${VOICE_CONTROLLER_REGISTRY:-us.icr.io/watson-orchestrate-private}/wxo-server-voice:${VOICE_CONTROLLER_TAG:-latest}
1121
+ profiles: [voice]
1122
+ restart: unless-stopped
1123
+ ports:
1124
+ - 9876:8765
1125
+ environment:
1126
+ WXO_BASE_DOMAIN_URL: "http://wxo-server:4321"
1127
+ AI_GATEWAY_URL: "http://ai-gateway:8787"
1128
+ WXO_ORIGIN_HEADER: "internal"
1129
+
1130
+ langflow:
1131
+ image: ${OPENSOURCE_REGISTRY_PROXY:-docker.io}/langflowai/${LANGFLOW_IMAGE:-langflow}:${LANGFLOW_TAG:-latest}
1132
+ profiles: [langflow]
1133
+ ports:
1134
+ - 7861:7861
1135
+ environment:
1136
+ LANGFLOW_PORT: 7861
1137
+ LANGFLOW_DATABASE_URL: postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@wxo-server-db:5432/langflow
1138
+ LANGFLOW_CONFIG_DIR: app/langflow
1139
+ volumes:
1140
+ - langflow-data:/app/langflow
1141
+
1108
1142
 
1109
1143
  volumes:
1110
1144
  tools:
@@ -1138,6 +1172,7 @@ volumes:
1138
1172
  wdu-models:
1139
1173
  driver: local
1140
1174
  es_data:
1175
+ langflow-data:
1141
1176
 
1142
1177
  networks:
1143
1178
  default: