ibm-watsonx-orchestrate 1.9.0b0__py3-none-any.whl → 1.9.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 (20) hide show
  1. ibm_watsonx_orchestrate/__init__.py +1 -1
  2. ibm_watsonx_orchestrate/cli/commands/agents/agents_controller.py +15 -3
  3. ibm_watsonx_orchestrate/cli/commands/connections/connections_controller.py +1 -1
  4. ibm_watsonx_orchestrate/cli/commands/copilot/copilot_controller.py +0 -3
  5. ibm_watsonx_orchestrate/cli/commands/server/server_command.py +146 -36
  6. ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_command.py +4 -2
  7. ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_controller.py +9 -1
  8. ibm_watsonx_orchestrate/docker/compose-lite.yml +115 -8
  9. ibm_watsonx_orchestrate/docker/default.env +16 -12
  10. ibm_watsonx_orchestrate/flow_builder/flows/constants.py +2 -0
  11. ibm_watsonx_orchestrate/flow_builder/flows/flow.py +48 -6
  12. ibm_watsonx_orchestrate/flow_builder/node.py +34 -3
  13. ibm_watsonx_orchestrate/flow_builder/types.py +38 -12
  14. ibm_watsonx_orchestrate/flow_builder/utils.py +0 -2
  15. {ibm_watsonx_orchestrate-1.9.0b0.dist-info → ibm_watsonx_orchestrate-1.9.0b1.dist-info}/METADATA +1 -3
  16. {ibm_watsonx_orchestrate-1.9.0b0.dist-info → ibm_watsonx_orchestrate-1.9.0b1.dist-info}/RECORD +19 -20
  17. ibm_watsonx_orchestrate/agent_builder/utils/pydantic_utils.py +0 -149
  18. {ibm_watsonx_orchestrate-1.9.0b0.dist-info → ibm_watsonx_orchestrate-1.9.0b1.dist-info}/WHEEL +0 -0
  19. {ibm_watsonx_orchestrate-1.9.0b0.dist-info → ibm_watsonx_orchestrate-1.9.0b1.dist-info}/entry_points.txt +0 -0
  20. {ibm_watsonx_orchestrate-1.9.0b0.dist-info → ibm_watsonx_orchestrate-1.9.0b1.dist-info}/licenses/LICENSE +0 -0
@@ -5,7 +5,7 @@
5
5
 
6
6
  pkg_name = "ibm-watsonx-orchestrate"
7
7
 
8
- __version__ = "1.9.0b0"
8
+ __version__ = "1.9.0b1"
9
9
 
10
10
 
11
11
 
@@ -750,6 +750,13 @@ class AgentsController:
750
750
  def list_agents(self, kind: AgentKind=None, verbose: bool=False):
751
751
  parse_errors = []
752
752
 
753
+ if verbose:
754
+ verbose_output_dictionary = {
755
+ "native":[],
756
+ "assistant":[],
757
+ "external":[]
758
+ }
759
+
753
760
  if kind == AgentKind.NATIVE or kind is None:
754
761
  response = self.get_native_client().get()
755
762
  native_agents = []
@@ -769,7 +776,7 @@ class AgentsController:
769
776
  for agent in native_agents:
770
777
  agents_list.append(json.loads(agent.dumps_spec()))
771
778
 
772
- rich.print_json(json.dumps(agents_list, indent=4))
779
+ verbose_output_dictionary["native"] = agents_list
773
780
  else:
774
781
  native_table = rich.table.Table(
775
782
  show_header=True,
@@ -832,7 +839,7 @@ class AgentsController:
832
839
  if verbose:
833
840
  for agent in external_agents:
834
841
  external_agents_list.append(json.loads(agent.dumps_spec()))
835
- rich.print_json(json.dumps(external_agents_list, indent=4))
842
+ verbose_output_dictionary["external"] = external_agents_list
836
843
  else:
837
844
  external_table = rich.table.Table(
838
845
  show_header=True,
@@ -899,8 +906,10 @@ class AgentsController:
899
906
  assistant_agent.config.authorization_url = response_data.get("authorization_url", assistant_agent.config.authorization_url)
900
907
 
901
908
  if verbose:
909
+ assistant_agent_specs = []
902
910
  for agent in assistant_agents:
903
- rich.print_json(agent.dumps_spec())
911
+ assistant_agent_specs.append(json.loads(agent.dumps_spec()))
912
+ verbose_output_dictionary["assistant"] = assistant_agent_specs
904
913
  else:
905
914
  assistants_table = rich.table.Table(
906
915
  show_header=True,
@@ -938,6 +947,9 @@ class AgentsController:
938
947
  )
939
948
  rich.print(assistants_table)
940
949
 
950
+ if verbose:
951
+ rich.print_json(data=verbose_output_dictionary)
952
+
941
953
  for error in parse_errors:
942
954
  for l in error:
943
955
  logger.error(l)
@@ -169,7 +169,7 @@ def _validate_connection_params(type: ConnectionType, **args) -> None:
169
169
 
170
170
 
171
171
  def _parse_entry(entry: str) -> dict[str,str]:
172
- split_entry = entry.split('=')
172
+ split_entry = entry.split('=', 1)
173
173
  if len(split_entry) != 2:
174
174
  message = f"The entry '{entry}' is not in the expected form '<key>=<value>'"
175
175
  logger.error(message)
@@ -137,9 +137,6 @@ def gather_utterances(max: int) -> list[str]:
137
137
  while count < max:
138
138
  utterance = Prompt.ask(" [green]>[/green]").strip()
139
139
 
140
- if utterance.lower() == 'q':
141
- break
142
-
143
140
  if utterance:
144
141
  utterances.append(utterance)
145
142
  count += 1
@@ -4,11 +4,13 @@ import os
4
4
  import platform
5
5
  import subprocess
6
6
  import sys
7
+ import shutil
7
8
  import tempfile
8
9
  import time
9
10
  from pathlib import Path
10
11
  from urllib.parse import urlparse
11
12
 
13
+ import re
12
14
  import jwt
13
15
  import requests
14
16
  import typer
@@ -32,6 +34,13 @@ logger = logging.getLogger(__name__)
32
34
 
33
35
  server_app = typer.Typer(no_args_is_help=True)
34
36
 
37
+ _EXPORT_FILE_TYPES: set[str] = {
38
+ 'py',
39
+ 'yaml',
40
+ 'yml',
41
+ 'json',
42
+ 'env'
43
+ }
35
44
 
36
45
  _ALWAYS_UNSET: set[str] = {
37
46
  "WO_API_KEY",
@@ -43,11 +52,34 @@ _ALWAYS_UNSET: set[str] = {
43
52
  "WO_USERNAME",
44
53
  "WO_PASSWORD",
45
54
  }
55
+
56
+ NON_SECRET_ENV_ITEMS: set[str] = {
57
+ "WO_DEVELOPER_EDITION_SOURCE",
58
+ "WO_INSTANCE",
59
+ "USE_SAAS_ML_TOOLS_RUNTIME",
60
+ "AUTHORIZATION_URL",
61
+ "OPENSOURCE_REGISTRY_PROXY",
62
+ "SAAS_WDU_RUNTIME",
63
+ "LATEST_ENV_FILE",
64
+ }
46
65
 
47
66
  def define_saas_wdu_runtime(value: str = "none") -> None:
48
67
  cfg = Config()
49
68
  cfg.write(USER_ENV_CACHE_HEADER,"SAAS_WDU_RUNTIME",value)
50
69
 
70
+ def set_compose_file_path_in_env(path: str = None) -> None:
71
+ Config().save(
72
+ {
73
+ USER_ENV_CACHE_HEADER: {
74
+ "DOCKER_COMPOSE_FILE_PATH" : path
75
+ }
76
+ }
77
+ )
78
+
79
+ def get_compose_file_path_from_env() -> str:
80
+ return Config().read(USER_ENV_CACHE_HEADER,"DOCKER_COMPOSE_FILE_PATH")
81
+
82
+
51
83
  def ensure_docker_installed() -> None:
52
84
  try:
53
85
  subprocess.run(["docker", "--version"], check=True, capture_output=True)
@@ -106,6 +138,11 @@ def docker_login_by_dev_edition_source(env_dict: dict, source: str) -> None:
106
138
 
107
139
 
108
140
  def get_compose_file() -> Path:
141
+ custom_compose_path = get_compose_file_path_from_env()
142
+ return Path(custom_compose_path) if custom_compose_path else get_default_compose_file()
143
+
144
+
145
+ def get_default_compose_file() -> Path:
109
146
  with resources.as_file(
110
147
  resources.files("ibm_watsonx_orchestrate.docker").joinpath("compose-lite.yml")
111
148
  ) as compose_file:
@@ -283,12 +320,17 @@ def _prepare_clean_env(env_file: Path) -> None:
283
320
  for key in keys_to_unset:
284
321
  os.environ.pop(key, None)
285
322
 
286
- def write_merged_env_file(merged_env: dict) -> Path:
287
- tmp = tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".env")
288
- with tmp:
323
+ def write_merged_env_file(merged_env: dict, target_path: str = None) -> Path:
324
+
325
+ if target_path:
326
+ file = open(target_path,"w")
327
+ else:
328
+ file = tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".env")
329
+
330
+ with file:
289
331
  for key, val in merged_env.items():
290
- tmp.write(f"{key}={val}\n")
291
- return Path(tmp.name)
332
+ file.write(f"{key}={val}\n")
333
+ return Path(file.name)
292
334
 
293
335
 
294
336
  def get_dbtag_from_architecture(merged_env_dict: dict) -> str:
@@ -310,14 +352,6 @@ def refresh_local_credentials() -> None:
310
352
  clear_protected_env_credentials_token()
311
353
  _login(name=PROTECTED_ENV_NAME, apikey=None)
312
354
 
313
- NON_SECRET_ENV_ITEMS = {
314
- "WO_DEVELOPER_EDITION_SOURCE",
315
- "WO_INSTANCE",
316
- "USE_SAAS_ML_TOOLS_RUNTIME",
317
- "AUTHORIZATION_URL",
318
- "OPENSOURCE_REGISTRY_PROXY",
319
- "SAAS_WDU_RUNTIME"
320
- }
321
355
  def persist_user_env(env: dict, include_secrets: bool = False) -> None:
322
356
  if include_secrets:
323
357
  persistable_env = env
@@ -337,7 +371,10 @@ def get_persisted_user_env() -> dict | None:
337
371
  return user_env
338
372
 
339
373
  def run_compose_lite(final_env_file: Path, experimental_with_langfuse=False, experimental_with_ibm_telemetry=False, with_doc_processing=False) -> None:
374
+
375
+
340
376
  compose_path = get_compose_file()
377
+
341
378
  compose_command = ensure_docker_compose_installed()
342
379
  _prepare_clean_env(final_env_file)
343
380
  db_tag = read_env_file(final_env_file).get('DBTAG', None)
@@ -754,6 +791,32 @@ def auto_configure_callback_ip(merged_env_dict: dict) -> dict:
754
791
 
755
792
  return merged_env_dict
756
793
 
794
+ def prepare_server_env_vars(user_env: dict = {}):
795
+
796
+ default_env = read_env_file(get_default_env_file())
797
+ dev_edition_source = get_dev_edition_source(user_env)
798
+ default_registry_vars = get_default_registry_env_vars_by_dev_edition_source(default_env, user_env, source=dev_edition_source)
799
+
800
+ # Update the default environment with the default registry variables only if they are not already set
801
+ for key in default_registry_vars:
802
+ if key not in default_env or not default_env[key]:
803
+ default_env[key] = default_registry_vars[key]
804
+
805
+ # Merge the default environment with the user environment
806
+ merged_env_dict = {
807
+ **default_env,
808
+ **user_env,
809
+ }
810
+
811
+ merged_env_dict = apply_server_env_dict_defaults(merged_env_dict)
812
+
813
+ # Auto-configure callback IP for async tools
814
+ merged_env_dict = auto_configure_callback_ip(merged_env_dict)
815
+
816
+ apply_llm_api_key_defaults(merged_env_dict)
817
+
818
+ return merged_env_dict
819
+
757
820
  @server_app.command(name="start")
758
821
  def server_start(
759
822
  user_env_file: str = typer.Option(
@@ -787,38 +850,37 @@ def server_start(
787
850
  '--with-doc-processing', '-d',
788
851
  help='Enable IBM Document Processing to extract information from your business documents. Enabling this activates the Watson Document Understanding service.'
789
852
  ),
853
+ custom_compose_file: str = typer.Option(
854
+ None,
855
+ '--compose-file', '-f',
856
+ help='Provide the path to a custom docker-compose file to use instead of the default compose file'
857
+ ),
790
858
  ):
791
859
  confirm_accepts_license_agreement(accept_terms_and_conditions)
792
860
 
793
861
  define_saas_wdu_runtime()
794
862
 
863
+ ensure_docker_installed()
864
+
795
865
  if user_env_file and not Path(user_env_file).exists():
796
- logger.error(f"Error: The specified environment file '{user_env_file}' does not exist.")
866
+ logger.error(f"The specified environment file '{user_env_file}' does not exist.")
797
867
  sys.exit(1)
798
- ensure_docker_installed()
799
868
 
800
- default_env = read_env_file(get_default_env_file())
869
+ if custom_compose_file:
870
+ if Path(custom_compose_file).exists():
871
+ logger.warning("You are using a custom docker compose file, official support will not be available for this configuration")
872
+ else:
873
+ logger.error(f"The specified docker-compose file '{custom_compose_file}' does not exist.")
874
+ sys.exit(1)
875
+
876
+ #Run regardless, to allow this to set compose as 'None' when not in use
877
+ set_compose_file_path_in_env(custom_compose_file)
878
+
801
879
  user_env = read_env_file(user_env_file) if user_env_file else {}
802
880
  persist_user_env(user_env, include_secrets=persist_env_secrets)
803
881
 
804
- dev_edition_source = get_dev_edition_source(user_env)
805
- default_registry_vars = get_default_registry_env_vars_by_dev_edition_source(default_env, user_env, source=dev_edition_source)
806
-
807
- # Update the default environment with the default registry variables only if they are not already set
808
- for key in default_registry_vars:
809
- if key not in default_env or not default_env[key]:
810
- default_env[key] = default_registry_vars[key]
882
+ merged_env_dict = prepare_server_env_vars(user_env)
811
883
 
812
- # Merge the default environment with the user environment
813
- merged_env_dict = {
814
- **default_env,
815
- **user_env,
816
- }
817
-
818
- merged_env_dict = apply_server_env_dict_defaults(merged_env_dict)
819
-
820
- # Auto-configure callback IP for async tools
821
- merged_env_dict = auto_configure_callback_ip(merged_env_dict)
822
884
  if not _check_exclusive_observibility(experimental_with_langfuse, experimental_with_ibm_telemetry):
823
885
  logger.error("Please select either langfuse or ibm telemetry for observability not both")
824
886
  sys.exit(1)
@@ -835,14 +897,12 @@ def server_start(
835
897
  merged_env_dict['USE_IBM_TELEMETRY'] = 'true'
836
898
 
837
899
  try:
900
+ dev_edition_source = get_dev_edition_source(merged_env_dict)
838
901
  docker_login_by_dev_edition_source(merged_env_dict, dev_edition_source)
839
902
  except ValueError as e:
840
903
  logger.error(f"Error: {e}")
841
904
  sys.exit(1)
842
905
 
843
- apply_llm_api_key_defaults(merged_env_dict)
844
-
845
-
846
906
  final_env_file = write_merged_env_file(merged_env_dict)
847
907
 
848
908
  run_compose_lite(final_env_file=final_env_file,
@@ -1000,5 +1060,55 @@ def run_db_migration() -> None:
1000
1060
  )
1001
1061
  sys.exit(1)
1002
1062
 
1063
+
1064
+ def bump_file_iteration(filename: str) -> str:
1065
+ regex = re.compile(f"^(?P<name>[^\\(\\s\\.\\)]+)(\\((?P<num>\\d+)\\))?(?P<type>\\.(?:{'|'.join(_EXPORT_FILE_TYPES)}))?$")
1066
+ _m = regex.match(filename)
1067
+ iter = int(_m['num']) + 1 if (_m and _m['num']) else 1
1068
+ return f"{_m['name']}({iter}){_m['type'] or ''}"
1069
+
1070
+ def get_next_free_file_iteration(filename: str) -> str:
1071
+ while Path(filename).exists():
1072
+ filename = bump_file_iteration(filename)
1073
+ return filename
1074
+
1075
+ @server_app.command(name="eject", help="output the docker-compose file and associated env file used to run the server")
1076
+ def server_eject(
1077
+ user_env_file: str = typer.Option(
1078
+ None,
1079
+ "--env-file",
1080
+ "-e",
1081
+ help="Path to a .env file that overrides default.env. Then environment variables override both."
1082
+ )
1083
+ ):
1084
+
1085
+ if not user_env_file:
1086
+ logger.error(f"To use 'server eject' you need to specify an env file with '--env-file' or '-e'")
1087
+ sys.exit(1)
1088
+
1089
+ if not Path(user_env_file).exists():
1090
+ logger.error(f"The specified environment file '{user_env_file}' does not exist.")
1091
+ sys.exit(1)
1092
+
1093
+ logger.warning("Changes to your docker compose file are not supported")
1094
+
1095
+ compose_file_path = get_compose_file()
1096
+
1097
+ compose_output_file = get_next_free_file_iteration('docker-compose.yml')
1098
+ logger.info(f"Exporting docker compose file to '{compose_output_file}'")
1099
+
1100
+ shutil.copyfile(compose_file_path,compose_output_file)
1101
+
1102
+
1103
+ user_env = read_env_file(user_env_file)
1104
+ merged_env_dict = prepare_server_env_vars(user_env)
1105
+
1106
+ env_output_file = get_next_free_file_iteration('server.env')
1107
+ logger.info(f"Exporting env file to '{env_output_file}'")
1108
+
1109
+ write_merged_env_file(merged_env=merged_env_dict,target_path=env_output_file)
1110
+
1111
+ logger.info(f"To make use of the exported configuration file run \"orchestrate server start -e {env_output_file} -f {compose_output_file}\"")
1112
+
1003
1113
  if __name__ == "__main__":
1004
1114
  server_app()
@@ -64,8 +64,8 @@ def import_toolkit(
64
64
  else:
65
65
  tool_list = None
66
66
 
67
- if not package and not package_root:
68
- logger.error("You must provide either '--package' or '--package-root'.")
67
+ if not package and not package_root and not command:
68
+ logger.error("You must provide either '--package', '--package-root' or '--command'.")
69
69
  sys.exit(1)
70
70
 
71
71
  if package_root and not command:
@@ -85,6 +85,8 @@ def import_toolkit(
85
85
  else:
86
86
  logger.error("Unable to infer start up command: '--language' flag must be either 'node' or 'python' when using the '--package' flag without '--command' flag.")
87
87
  sys.exit(1)
88
+ else:
89
+ logger.warning(f"Default package installation command for package '{package}' overridden by '--command {command}'.")
88
90
 
89
91
 
90
92
  toolkit_controller = ToolkitController(
@@ -70,7 +70,7 @@ class ToolkitController:
70
70
  self.client = None
71
71
 
72
72
  self.source: ToolkitSource = (
73
- ToolkitSource.PUBLIC_REGISTRY if package else ToolkitSource.FILES
73
+ ToolkitSource.FILES if package_root else ToolkitSource.PUBLIC_REGISTRY
74
74
  )
75
75
 
76
76
  def get_client(self) -> ToolKitClient:
@@ -105,6 +105,14 @@ class ToolkitController:
105
105
  command = command_parts[0]
106
106
  args = command_parts[1:]
107
107
 
108
+ if self.package_root:
109
+ is_folder = os.path.isdir(self.package_root)
110
+ is_zip_file = os.path.isfile(self.package_root) and zipfile.is_zipfile(self.package_root)
111
+
112
+ if not is_folder and not is_zip_file:
113
+ logger.error(f"Unable to find a valid directory or zip file at location '{self.package_root}'")
114
+ sys.exit(1)
115
+
108
116
  console = Console()
109
117
 
110
118
  with tempfile.TemporaryDirectory() as tmpdir:
@@ -1,3 +1,4 @@
1
+ name: docker
1
2
  services:
2
3
  ########################
3
4
  # Orchestrate Lite dependencies
@@ -780,7 +781,6 @@ services:
780
781
  LANGFUSE_PUBLIC_KEY: ${LANGFUSE_PUBLIC_KEY:-pk-lf-7417757e-d6df-421b-957e-683b76acb5df}
781
782
  LANGFUSE_SECRET_KEY: ${LANGFUSE_PRIVATE_KEY:-sk-lf-7bc4da63-7b2b-40c0-b5eb-1e0cf64f9af2}
782
783
  LOG_LEVEL: info
783
- DISABLE_FLOW_BINDING: true
784
784
  DOCPROC_ENABLED: ${DOCPROC_ENABLED:-false}
785
785
  DOCPROC_BASE_URL: http://wxo-doc-processing-infra-standalone:9080
786
786
  WO_API_KEY: ${WO_API_KEY}
@@ -825,7 +825,7 @@ services:
825
825
  ########################
826
826
 
827
827
  wxo-doc-processing-service:
828
- image: ${DOCPROC_REGISTRY:-us.icr.io/watson-orchestrate-private}/document-processing/wo_doc_processing_service:${DOCPROC_DPS_TAG:-20250606-172035-246-4191121}
828
+ image: ${DOCPROC_REGISTRY:-us.icr.io/watson-orchestrate-private}/document-processing/wo_doc_processing_service:${DOCPROC_DPS_TAG:-20250721-164412-250-503756a}
829
829
  platform: linux/amd64
830
830
  restart: unless-stopped
831
831
  environment:
@@ -841,9 +841,9 @@ services:
841
841
  IBM_DPS_CACHE_SERVICE: https://wxo-doc-processing-cache:8080
842
842
  profiles:
843
843
  - docproc
844
- # depends_on:
845
- # wxo-doc-processing-cache:
846
- # condition: service_healthy
844
+ depends_on:
845
+ wxo-doc-processing-cache:
846
+ condition: service_healthy
847
847
  ports:
848
848
  - "18081:8080"
849
849
  healthcheck:
@@ -855,6 +855,7 @@ services:
855
855
  wdu-runtime:
856
856
  image: ${WDU_REGISTRY:-us.icr.io/watson-orchestrate-private}/document-processing/wdu-runtime:${WDU_TAG:-2.4.0}
857
857
  platform: linux/amd64
858
+ user: app
858
859
  restart: unless-stopped
859
860
  environment:
860
861
  MEMORY_MINIMAL: "true"
@@ -894,6 +895,48 @@ services:
894
895
  tmpfs:
895
896
  - "/dev/shm"
896
897
 
898
+ wxo-doc-processing-cache:
899
+ image: ${DOCPROC_REGISTRY:-us.icr.io/watson-orchestrate-private}/document-processing/wo_doc_processing_cache:${DOCPROC_CACHE_TAG:-20250723-100852-70-9edc1ab}
900
+ platform: linux/amd64
901
+ restart: unless-stopped
902
+ environment:
903
+ SERVICE_NAME: wxo-doc-processing-cache
904
+ LOG_LEVEL: info
905
+ RATE_LIMITING_ENABLED: "false"
906
+ USE_DUMMY_CACHE: "false"
907
+ CACHE_ENFORCE_STRICT_JWT: "false"
908
+ PGHOST: wxo-server-db
909
+ PGPORT: "5432"
910
+ PGUSER: ${POSTGRES_USER:-postgres}
911
+ PGPASSWORD: ${POSTGRES_PASSWORD:-postgres}
912
+ PGDATABASE: wxo-document-processing-cache
913
+ PG_DB_SCHEMA: dpschema
914
+ # PG_USE_SSL: false
915
+ S3_ENDPOINT_URL: http://wxo-server-minio:9000
916
+ S3_ACCESS_KEY: ${MINIO_ROOT_USER:-minioadmin}
917
+ S3_SECRET_KEY: ${MINIO_ROOT_PASSWORD:-watsonxorchestrate}
918
+ S3_REGION: us-east-1
919
+ S3_BUCKET_NAME: wxo-document-processing-cache
920
+ VERIFY_CLIENT_CERT: 1
921
+ # S3_USE_SSL: false
922
+ # S3_VERIFY_CERT: false
923
+ profiles:
924
+ - docproc
925
+ depends_on:
926
+ wxo-doc-processing-pg-init:
927
+ condition: service_completed_successfully
928
+ wxo-doc-processing-cache-minio-init:
929
+ condition: service_completed_successfully
930
+ ports:
931
+ - "18083:8080"
932
+ # volumes:
933
+ # - ./docker/wo_doc_processing_rag_base/etc/certs:/etc/certs
934
+ healthcheck:
935
+ test: ["CMD-SHELL", "curl -fk https://localhost:8080/ping"]
936
+ interval: 30s
937
+ timeout: 30s
938
+ retries: 10
939
+
897
940
  wxo-doc-processing-infra-standalone:
898
941
  image: ${DOCPROC_REGISTRY:-us.icr.io/watson-orchestrate-private}/document-processing/wo-doc-processing-infra-standalone:${DOCPROC_DPI_TAG:-2025-06-13-dev-1}
899
942
  platform: linux/amd64
@@ -918,7 +961,7 @@ services:
918
961
  SIDECAR_METERED_ENABLED: "false"
919
962
  DPI_DEBUG: "false"
920
963
  DPI_WO_WDU_SERVER_ENDPOINT: https://wxo-doc-processing-service:8080
921
- # DPI_RAG_SERVER_ENDPOINT: https://wxo-doc-processing-llm-service:8083
964
+ DPI_RAG_SERVER_ENDPOINT: https://wxo-doc-processing-llm-service:8083
922
965
  DISABLE_TLS: true
923
966
  STANDALONE_DPI: "true"
924
967
  depends_on:
@@ -928,8 +971,8 @@ services:
928
971
  condition: service_completed_successfully
929
972
  wxo-doc-processing-service:
930
973
  condition: service_healthy
931
- # wxo-doc-processing-llm-service:
932
- # condition: service_healthy
974
+ wxo-doc-processing-llm-service:
975
+ condition: service_healthy
933
976
  ports:
934
977
  - 19080:9080
935
978
  - 19443:9443
@@ -939,6 +982,33 @@ services:
939
982
  timeout: 30s
940
983
  retries: 10
941
984
 
985
+ wxo-doc-processing-llm-service:
986
+ image: ${DOCPROC_REGISTRY:-us.icr.io/watson-orchestrate-private}/document-processing/wo_doc_processing_rag:${DOCPROC_LLMSERVICE_TAG:-20250725-100249-111-51d3e51}
987
+ platform: linux/amd64
988
+ restart: unless-stopped
989
+ environment:
990
+ SERVICE_NAME: wxo-doc-processing-llm-service
991
+ LOG_LEVEL: info
992
+ WATSONX_API_ENDPOINT: ${WATSONX_URL:-https://us-south.ml.cloud.ibm.com}
993
+ WATSONX_API_KEY: ${WATSONX_APIKEY}
994
+ WATSONX_PROJECT_ID: ${WATSONX_PROJECT_ID}
995
+ WATSONX_SPACE_ID: ${WATSONX_SPACE_ID}
996
+ IBM_DPS_CACHE_SERVICE: 'wxo-doc-processing-cache:8080'
997
+ profiles:
998
+ - docproc
999
+ depends_on:
1000
+ wxo-doc-processing-cache:
1001
+ condition: service_healthy
1002
+ ports:
1003
+ - "18084:8083"
1004
+ # volumes:
1005
+ # - ./conf/rag/certs:/etc/certs
1006
+ healthcheck:
1007
+ test: ["CMD-SHELL", "curl -fk https://localhost:8083/ping"]
1008
+ interval: 30s
1009
+ timeout: 30s
1010
+ retries: 10
1011
+
942
1012
  wxo-doc-processing-infra-pg-init:
943
1013
  image: ${DOCPROC_REGISTRY:-us.icr.io/watson-orchestrate-private}/document-processing/wo-doc-processing-infra-pg-init:${DOCPROC_DPI_TAG:-2025-06-13-dev-1}
944
1014
  platform: linux/amd64
@@ -963,6 +1033,28 @@ services:
963
1033
  timeout: 5s
964
1034
  retries: 50
965
1035
 
1036
+ wxo-doc-processing-pg-init:
1037
+ image: ${DOCPROC_REGISTRY:-us.icr.io/watson-orchestrate-private}/document-processing/wo_doc_processing_cache_rds_init:${DOCPROC_CACHE_TAG:-20250723-100852-70-9edc1ab}
1038
+ platform: linux/amd64
1039
+ environment:
1040
+ PGHOST: wxo-server-db
1041
+ PGPORT: "5432"
1042
+ PGUSER: ${POSTGRES_USER:-postgres}
1043
+ PGPASSWORD: ${POSTGRES_PASSWORD:-postgres}
1044
+ PGDATABASE: wxo-document-processing-cache
1045
+ PG_DB_SCHEMA: dpschema
1046
+ # PG_USE_SSL: false
1047
+ profiles:
1048
+ - docproc
1049
+ depends_on:
1050
+ wxo-server-db:
1051
+ condition: service_started
1052
+ healthcheck:
1053
+ test: ["CMD-SHELL", "psql -h localhost -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_PASSWORD:-postgres}"]
1054
+ interval: 1s
1055
+ timeout: 5s
1056
+ retries: 50
1057
+
966
1058
  wxo-doc-processing-dpi-minio-init:
967
1059
  image: ${OPENSOURCE_REGISTRY_PROXY:-docker.io}/minio/mc:latest
968
1060
  platform: linux/amd64
@@ -978,6 +1070,21 @@ services:
978
1070
  exit 0;
979
1071
  "
980
1072
 
1073
+ wxo-doc-processing-cache-minio-init:
1074
+ image: ${OPENSOURCE_REGISTRY_PROXY:-docker.io}/minio/mc:latest
1075
+ platform: linux/amd64
1076
+ profiles:
1077
+ - docproc
1078
+ depends_on:
1079
+ wxo-server-minio:
1080
+ condition: service_healthy
1081
+ entrypoint: >
1082
+ /bin/sh -c "
1083
+ /usr/bin/mc alias set wxo-server-minio http://wxo-server-minio:9000 ${MINIO_ROOT_USER:-minioadmin} ${MINIO_ROOT_PASSWORD:-watsonxorchestrate};
1084
+ /usr/bin/mc mb wxo-server-minio/wxo-document-processing-cache;
1085
+ exit 0;
1086
+ "
1087
+
981
1088
  volumes:
982
1089
  tools:
983
1090
  driver: local
@@ -1,3 +1,7 @@
1
+ # These credentials are for local development only.
2
+ # They are default values and can be overridden by the user.
3
+ # These do NOT provide access to any production or sensitive
4
+
1
5
  #DOCKER_IAM_KEY=dummy #Must Define in env
2
6
  #You can generate any JWT_SECRET with python -c 'import secrets; print(secrets.token_hex(32))'
3
7
  JWT_SECRET=11759cbc89dbec64956715e10a854eb38f8b7a1775bdf68142786170f5e8b5b2
@@ -53,24 +57,24 @@ EVENT_BROKER_TTL="3600"
53
57
  REGISTRY_URL=
54
58
 
55
59
 
56
- SERVER_TAG=22-07-2025
60
+ SERVER_TAG=31-07-2025
57
61
  SERVER_REGISTRY=
58
62
 
59
- WORKER_TAG=22-07-2025
63
+ WORKER_TAG=31-07-2025
60
64
  WORKER_REGISTRY=
61
65
 
62
66
  AI_GATEWAY_TAG=21-07-2025
63
67
  AI_GATEWAY_REGISTRY=
64
68
 
65
- AGENT_GATEWAY_TAG=07-07-2025
69
+ AGENT_GATEWAY_TAG=29-07-2025
66
70
  AGENT_GATEWAY_REGISTRY=
67
71
 
68
72
  DB_REGISTRY=
69
73
  # If you build multiarch set all three of these to the same, we have a pr against main
70
74
  # to not have this separation, but we can merge it later
71
- DBTAG=22-07-2025
72
- AMDDBTAG=24-06-2025-v1
73
- ARM64DBTAG=24-06-2025-v1
75
+ DBTAG=29-07-2025-9f3661b
76
+ AMDDBTAG=29-07-2025-9f3661b
77
+ ARM64DBTAG=29-07-2025-9f3661b
74
78
 
75
79
  UI_REGISTRY=
76
80
  UITAG=23-07-2025
@@ -84,10 +88,10 @@ TRM_REGISTRY=
84
88
  TR_TAG=23-07-2025-3c60549f0bac275de3e5736265a3fd49cdd3a203
85
89
  TR_REGISTRY=
86
90
 
87
- BUILDER_TAG=22-07-2025-v1
91
+ BUILDER_TAG=29-07-2025
88
92
  BUILDER_REGISTRY=
89
93
 
90
- FLOW_RUNTIME_TAG=15-07-2025
94
+ FLOW_RUNTIME_TAG=28-07-2025-v2
91
95
  FLOW_RUMTIME_REGISTRY=
92
96
 
93
97
 
@@ -107,10 +111,10 @@ CPE_REGISTRY=
107
111
  WDU_TAG=2.5.0
108
112
  WDU_REGISTRY=
109
113
 
110
- DOCPROC_DPS_TAG=20250610-183301-248-865fbc1
111
- DOCPROC_LLMSERVICE_TAG=20250604-192056-107-e1d4d66
112
- DOCPROC_CACHE_TAG=20250610-214940-68-f3258f4
113
- DOCPROC_DPI_TAG=20250702-000808-237-7b1e424d
114
+ DOCPROC_DPS_TAG=20250721-164412-250-503756a
115
+ DOCPROC_LLMSERVICE_TAG=20250725-100249-111-51d3e51
116
+ DOCPROC_CACHE_TAG=20250723-100852-70-9edc1ab
117
+ DOCPROC_DPI_TAG=20250710-195309-241-8f9fb6d7
114
118
  DOCPROC_REGISTRY=
115
119
 
116
120
  # END -- IMAGE REGISTRIES AND TAGS
@@ -17,3 +17,5 @@ RESERVED = {
17
17
  ANY_USER,
18
18
  CURRENT_USER
19
19
  }
20
+
21
+
@@ -8,7 +8,7 @@ from datetime import datetime
8
8
  from enum import Enum
9
9
  import inspect
10
10
  from typing import (
11
- Any, AsyncIterator, Callable, cast, List, Sequence, Union, Tuple
11
+ Any, AsyncIterator, Callable, Optional, cast, List, Sequence, Union, Tuple
12
12
  )
13
13
  import json
14
14
  import logging
@@ -18,7 +18,7 @@ import pytz
18
18
  import os
19
19
 
20
20
  from typing_extensions import Self
21
- from pydantic import BaseModel, Field, SerializeAsAny
21
+ from pydantic import BaseModel, Field, SerializeAsAny, create_model
22
22
  import yaml
23
23
  from ibm_watsonx_orchestrate.agent_builder.tools.python_tool import PythonTool
24
24
  from ibm_watsonx_orchestrate.client.tools.tool_client import ToolClient
@@ -27,11 +27,11 @@ from ibm_watsonx_orchestrate.client.utils import instantiate_client
27
27
  from ..types import (
28
28
  EndNodeSpec, Expression, ForeachPolicy, ForeachSpec, LoopSpec, BranchNodeSpec, MatchPolicy, PromptLLMParameters, PromptNodeSpec,
29
29
  StartNodeSpec, ToolSpec, JsonSchemaObject, ToolRequestBody, ToolResponseBody, UserFieldKind, UserFieldOption, UserFlowSpec, UserNodeSpec, WaitPolicy,
30
- DocProcSpec, TextExtractionResponse, File, DecisionsNodeSpec, DecisionsRule
30
+ DocProcSpec, TextExtractionResponse, File, DecisionsNodeSpec, DecisionsRule, DocExtSpec, LanguageCode
31
31
  )
32
32
  from .constants import CURRENT_USER, START, END, ANY_USER
33
33
  from ..node import (
34
- EndNode, Node, PromptNode, StartNode, UserNode, AgentNode, DataMap, ToolNode, DocProcNode, DecisionsNode
34
+ EndNode, Node, PromptNode, StartNode, UserNode, AgentNode, DataMap, ToolNode, DocProcNode, DecisionsNode, DocExtNode
35
35
  )
36
36
  from ..types import (
37
37
  AgentNodeSpec, extract_node_spec, FlowContext, FlowEventType, FlowEvent, FlowSpec,
@@ -433,6 +433,50 @@ class Flow(Node):
433
433
  node = self._add_node(node)
434
434
  return cast(PromptNode, node)
435
435
 
436
+ def docext(self,
437
+ name: str,
438
+ llm : str = "meta-llama/llama-3-2-11b-vision-instruct",
439
+ version: str = "TIP",
440
+ display_name: str| None = None,
441
+ input_entities: type[BaseModel]| None = None,
442
+ description: str | None = None,
443
+ input_map: DataMap = None) -> tuple[DocExtNode, type[BaseModel]]:
444
+
445
+ if name is None :
446
+ raise ValueError("name must be provided.")
447
+
448
+ doc_ext_config = DocExtNode.generate_config(llm=llm, input_entites=input_entities)
449
+
450
+ DocExtFieldValue = DocExtNode.generate_docext_field_value_model(input_entities=input_entities)
451
+
452
+ input_schema_obj = _get_json_schema_obj(parameter_name = "input", type_def = File)
453
+ output_schema_obj = _get_json_schema_obj("output", DocExtFieldValue)
454
+
455
+ if "$defs" in output_schema_obj.model_extra:
456
+ output_schema_obj.model_extra.pop("$defs")
457
+
458
+ # Create the docext spec
459
+ task_spec = DocExtSpec(
460
+ name=name,
461
+ display_name=display_name if display_name is not None else name,
462
+ description=description,
463
+ input_schema=_get_tool_request_body(input_schema_obj),
464
+ output_schema=_get_tool_response_body(output_schema_obj),
465
+ output_schema_object = output_schema_obj,
466
+ config=doc_ext_config,
467
+ version=version
468
+ )
469
+ node = DocExtNode(spec=task_spec)
470
+
471
+ # setup input map
472
+ if input_map:
473
+ node.input_map = self._get_data_map(input_map)
474
+
475
+ # add the node to the list of node
476
+
477
+ node = self._add_node(node)
478
+ return cast(DocExtNode, node), DocExtFieldValue
479
+
436
480
  def decisions(self,
437
481
  name: str,
438
482
  display_name: str|None=None,
@@ -486,8 +530,6 @@ class Flow(Node):
486
530
  if name is None :
487
531
  raise ValueError("name must be provided.")
488
532
 
489
- if task is None:
490
- raise ValueError("task must be provided.")
491
533
 
492
534
  output_schema_dict = {
493
535
  "text_extraction" : TextExtractionResponse
@@ -1,11 +1,14 @@
1
1
  import json
2
- from typing import Any, cast
2
+ from typing import Any, cast, Type
3
3
  import uuid
4
4
 
5
5
  import yaml
6
- from pydantic import BaseModel, Field, SerializeAsAny
6
+ from pydantic import BaseModel, Field, SerializeAsAny, create_model
7
+ from enum import Enum
8
+
9
+ from .types import EndNodeSpec, NodeSpec, AgentNodeSpec, PromptNodeSpec, StartNodeSpec, ToolNodeSpec, UserFieldKind, UserFieldOption, UserNodeSpec, DocProcSpec, \
10
+ DocExtSpec, DocExtConfig, LanguageCode, DecisionsNodeSpec
7
11
 
8
- from .types import EndNodeSpec, NodeSpec, AgentNodeSpec, PromptNodeSpec, StartNodeSpec, ToolNodeSpec, UserFieldKind, UserFieldOption, UserNodeSpec, DocProcSpec, DecisionsNodeSpec
9
12
  from .data_map import DataMap
10
13
 
11
14
  class Node(BaseModel):
@@ -116,6 +119,34 @@ class DocProcNode(Node):
116
119
 
117
120
  def get_spec(self) -> DocProcSpec:
118
121
  return cast(DocProcSpec, self.spec)
122
+
123
+ class DocExtNode(Node):
124
+ def __repr__(self):
125
+ return f"DocExtNode(name='{self.spec.name}', description='{self.spec.description}')"
126
+
127
+ def get_spec(self) -> DocExtSpec:
128
+ return cast(DocExtSpec, self.spec)
129
+
130
+ @staticmethod
131
+ def generate_config(llm: str, input_entites: type[BaseModel]) -> DocExtConfig:
132
+ entities = input_entites.__dict__.values()
133
+ return DocExtConfig(llm=llm, entities=entities)
134
+
135
+ @staticmethod
136
+ def generate_docext_field_value_model(input_entities: type[BaseModel]) -> type[BaseModel]:
137
+ create_field_value_description = lambda field_name: "Extracted value for " + field_name
138
+
139
+ DocExtFieldValue = create_model(
140
+ "DocExtFieldValue",
141
+ **{
142
+ name: (str, Field(
143
+ title=value['name'],
144
+ description=create_field_value_description(value['name']),
145
+ )
146
+ )
147
+ for name, value in input_entities.model_dump().items()})
148
+ return DocExtFieldValue
149
+
119
150
  class DecisionsNode(Node):
120
151
  def __repr__(self):
121
152
  return f"DecisionsNode(name='{self.spec.name}', description='{self.spec.description}')"
@@ -9,7 +9,6 @@ from typing import (
9
9
  )
10
10
 
11
11
  import docstring_parser
12
- from munch import Munch
13
12
  from pydantic import BaseModel, Field
14
13
 
15
14
  from langchain_core.tools.base import create_schema_from_function
@@ -164,6 +163,39 @@ class NodeSpec(BaseModel):
164
163
 
165
164
  return model_spec
166
165
 
166
+ class DocExtConfigEntity(BaseModel):
167
+ name: str = Field(description="Entity name")
168
+ type: Literal["string", "date", "number"] = Field(default="string", description="The type of the entity values")
169
+ description: str = Field(title="Description", description="Description of the entity", default="")
170
+ field_name: str = Field(title="Field Name", description="The normalized name of the entity", default="")
171
+ multiple_mentions: bool = Field(title="Multiple mentions",description="When true, we can produce multiple mentions of this entity", default=False)
172
+ example_value: str = Field(description="Value of example", default="")
173
+ examples: list[str] = Field(title="Examples", description="Examples that help the LLM understand the expected entity mentions", default=[])
174
+
175
+ class DocExtConfig(BaseModel):
176
+ domain: str = Field(description="Domiain of the document", default="other")
177
+ type: str = Field(description="Document type", default="agreement")
178
+ llm: str = Field(description="The LLM used for the document extraction", default="meta-llama/llama-3-2-11b-vision-instruct")
179
+ entities: list[DocExtConfigEntity] = Field(default=[])
180
+
181
+ class LanguageCode(StrEnum):
182
+ en = auto()
183
+ fr = auto()
184
+
185
+ class DocExtSpec(NodeSpec):
186
+ version : str = Field(description="A version of the spec")
187
+ config : DocExtConfig
188
+
189
+ def __init__(self, **data):
190
+ super().__init__(**data)
191
+ self.kind = "docext"
192
+
193
+ def to_json(self) -> dict[str, Any]:
194
+ model_spec = super().to_json()
195
+ model_spec["version"] = self.version
196
+ model_spec["config"] = self.config.model_dump()
197
+ return model_spec
198
+
167
199
  class DocProcTask(StrEnum):
168
200
  '''
169
201
  Possible names for the Document processing task parameter
@@ -674,6 +706,7 @@ class TaskEventType(Enum):
674
706
  ON_TASK_END = "task:on_task_end"
675
707
  ON_TASK_STREAM = "task:on_task_stream"
676
708
  ON_TASK_ERROR = "task:on_task_error"
709
+ ON_TASK_RESUME= "task:on_task_resume"
677
710
 
678
711
  class FlowData(BaseModel):
679
712
  '''This class represents the data that is passed between tasks in a flow.'''
@@ -708,7 +741,7 @@ class FlowEventType(Enum):
708
741
  ON_FLOW_START = "flow:on_flow_start"
709
742
  ON_FLOW_END = "flow:on_flow_end"
710
743
  ON_FLOW_ERROR = "flow:on_flow_error"
711
-
744
+ ON_FLOW_RESUME = "flow:on_flow_resume"
712
745
 
713
746
  @dataclass
714
747
  class FlowEvent:
@@ -763,22 +796,15 @@ class File(BaseModel):
763
796
  description='Optional language code of the document, defaults to "en"',
764
797
  title='Document language code',
765
798
  default=LanguageCode.en)
766
-
767
- class TextExtraction(BaseModel):
768
- '''
769
- This class represents the output generated by a "text_extraction" document processing (docproc) operation.
770
- Attributes:
771
- text (str): the text extracted from the input document.
772
- '''
773
- text: str = Field(description='The text extracted from the input document', title='Text extraction')
799
+
774
800
 
775
801
  class TextExtractionResponse(BaseModel):
776
802
  '''
777
803
  The text extraction operation response.
778
804
  Attributes:
779
- output (TextExtraction): a wrapper for the text extraction response
805
+ text (str): the text extracted from the input document.
780
806
  '''
781
- output: TextExtraction = Field(description='The text extraction response')
807
+ text : str = Field(description="the text extracted from the input document.")
782
808
 
783
809
 
784
810
  class DecisionsCondition(BaseModel):
@@ -6,9 +6,7 @@ import logging
6
6
  from pydantic import BaseModel, TypeAdapter
7
7
 
8
8
  from langchain_core.utils.json_schema import dereference_refs
9
- from rpds import List
10
9
  import typer
11
- import yaml
12
10
 
13
11
  from ibm_watsonx_orchestrate.agent_builder.tools.base_tool import BaseTool
14
12
  from ibm_watsonx_orchestrate.agent_builder.tools.flow_tool import create_flow_json_tool
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ibm-watsonx-orchestrate
3
- Version: 1.9.0b0
3
+ Version: 1.9.0b1
4
4
  Summary: IBM watsonx.orchestrate SDK
5
5
  Author-email: IBM <support@ibm.com>
6
6
  License: MIT License
@@ -13,10 +13,8 @@ Requires-Dist: httpx<1.0.0,>=0.28.1
13
13
  Requires-Dist: ibm-cloud-sdk-core>=3.24.2
14
14
  Requires-Dist: ibm-watsonx-orchestrate-evaluation-framework==1.0.8
15
15
  Requires-Dist: jsonref==1.1.0
16
- Requires-Dist: jsonschema<5.0.0,>=4.23.0
17
16
  Requires-Dist: langchain-core<=0.3.63
18
17
  Requires-Dist: langsmith<=0.3.45
19
- Requires-Dist: munch>=4.0.0
20
18
  Requires-Dist: packaging>=24.2
21
19
  Requires-Dist: pydantic<3.0.0,>=2.10.3
22
20
  Requires-Dist: pyjwt<3.0.0,>=2.10.1
@@ -1,4 +1,4 @@
1
- ibm_watsonx_orchestrate/__init__.py,sha256=2UaugDcM-5kU7VcYFZlaSUp30w1dBcZbs9OZJ-nA2vA,427
1
+ ibm_watsonx_orchestrate/__init__.py,sha256=wenjO7SaJ_OKOQuhufZaqfd2aSi-hCVjmnDeyymUqj0,427
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
@@ -27,14 +27,13 @@ ibm_watsonx_orchestrate/agent_builder/tools/openapi_tool.py,sha256=h9ma18GUQHt88
27
27
  ibm_watsonx_orchestrate/agent_builder/tools/python_tool.py,sha256=FDY-y9jy4bNy88i7JG85Zj_YrxnPfJPD0DjwvL9ITxc,12012
28
28
  ibm_watsonx_orchestrate/agent_builder/tools/types.py,sha256=SAyDEnWYuguTFk6WxgSDnMaONqDqcr6QhBAxD1u5FDU,8165
29
29
  ibm_watsonx_orchestrate/agent_builder/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
- ibm_watsonx_orchestrate/agent_builder/utils/pydantic_utils.py,sha256=QEanM6FpkmntvS02whdhWx1d4v6zT_1l9ipEbfTgHs8,7623
31
30
  ibm_watsonx_orchestrate/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
31
  ibm_watsonx_orchestrate/cli/config.py,sha256=iXjDxymWhAmLSUu6eh7zJR20dYZDzbxcU5VoBdh3VIw,8318
33
32
  ibm_watsonx_orchestrate/cli/init_helper.py,sha256=qxnKdFcPtGsV_6RqP_IuLshRxgB004SxzDAkBTExA-4,1675
34
33
  ibm_watsonx_orchestrate/cli/main.py,sha256=eE71dfx-EdDYHymYDqXcTjyMXpX0b3cueXOxCI2YLLs,3119
35
34
  ibm_watsonx_orchestrate/cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
35
  ibm_watsonx_orchestrate/cli/commands/agents/agents_command.py,sha256=Zif3bH3X7j5qf7MWGcr53mJ2oEKXNRHeg3ZHeoHTIqQ,8984
37
- ibm_watsonx_orchestrate/cli/commands/agents/agents_controller.py,sha256=AvDZ3HSRFzaCQ00Kgu9IsOtq0Dv6HPv2E0o9IrisA7Y,47981
36
+ ibm_watsonx_orchestrate/cli/commands/agents/agents_controller.py,sha256=gEsuG3Mbz6shuv8yB2C-dPcqM5mMXUAVO0YniNNOMk0,48379
38
37
  ibm_watsonx_orchestrate/cli/commands/channels/channels_command.py,sha256=fVIFhPUTPdxsxIE10nWL-W5wvBR-BS8V8D6r__J8R98,822
39
38
  ibm_watsonx_orchestrate/cli/commands/channels/channels_controller.py,sha256=WjQxwJujvo28SsWgfJSXIpkcgniKcskJ2arL4MOz0Ys,455
40
39
  ibm_watsonx_orchestrate/cli/commands/channels/types.py,sha256=hMFvWPr7tAmDrhBqtzfkCsrubX3lsU6lapTSOFsUbHM,475
@@ -42,9 +41,9 @@ ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_command.p
42
41
  ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_controller.py,sha256=CGfmKsCBX4E3HMZ8C0IXD-DHQNwe96V1Y_BxUZM2us0,8557
43
42
  ibm_watsonx_orchestrate/cli/commands/chat/chat_command.py,sha256=Q9vg2Z5Fsunu6GQFY_TIsNRhUCa0SSGSPnK4jxSGK34,1581
44
43
  ibm_watsonx_orchestrate/cli/commands/connections/connections_command.py,sha256=bZBzaaVMFmGY4Guk-JCknZqd8HvXY5L-FirxpxddQfc,10497
45
- ibm_watsonx_orchestrate/cli/commands/connections/connections_controller.py,sha256=odsqxthEDyPO3C-GEtSn31sxLjRYgUBf1Vdkg6ZEwms,22290
44
+ ibm_watsonx_orchestrate/cli/commands/connections/connections_controller.py,sha256=_s1chAQ4Oqz-A0tQ4LkRAHL3-lGDtalbrLHFJ35lA_I,22293
46
45
  ibm_watsonx_orchestrate/cli/commands/copilot/copilot_command.py,sha256=IxasApIyQYWRMKPXKa38ZPVkUvOc4chggSmSGjgQGXc,2345
47
- ibm_watsonx_orchestrate/cli/commands/copilot/copilot_controller.py,sha256=rr6p4_yqriq3ts1FwFC4aV0ub5UC5D6JqpuLoba4j_U,14808
46
+ ibm_watsonx_orchestrate/cli/commands/copilot/copilot_controller.py,sha256=fLnrBpO6avs-V3wnK_-8KPmT5iRSHejnLOyFhrthlbg,14752
48
47
  ibm_watsonx_orchestrate/cli/commands/copilot/copilot_server_controller.py,sha256=AcBE97qNYsRN0ftY_E-AAjKFyVea4fHtU5eB2HsB42I,5619
49
48
  ibm_watsonx_orchestrate/cli/commands/environment/environment_command.py,sha256=xwq7gdyjMtl2RYAnLAahGk2wDetr9BStt8yu7JkeBhk,3768
50
49
  ibm_watsonx_orchestrate/cli/commands/environment/environment_controller.py,sha256=oHZ7LONtPg3-SSnU_rRZryLi8N2mplz5h-LGg4XjzD4,10261
@@ -57,7 +56,7 @@ ibm_watsonx_orchestrate/cli/commands/login/login_command.py,sha256=xArMiojoozg7E
57
56
  ibm_watsonx_orchestrate/cli/commands/models/model_provider_mapper.py,sha256=RVZfFCuPWiASkR9Mox61v5SZ1AoRxo4_g9stnbfjCkc,7994
58
57
  ibm_watsonx_orchestrate/cli/commands/models/models_command.py,sha256=PW-PIM5Nq0qdCopWjANGBWEuEoA3NLTFThYrN8ggGCI,6425
59
58
  ibm_watsonx_orchestrate/cli/commands/models/models_controller.py,sha256=eZSYQUg9TL_-8lgcPVpKIx7MtOE7K_NCvZW9Y9YsFA0,18466
60
- ibm_watsonx_orchestrate/cli/commands/server/server_command.py,sha256=ho1rSTN_fIJKeKzA5d4BdoQELl_4aF5Gzx90VySbaX8,39687
59
+ ibm_watsonx_orchestrate/cli/commands/server/server_command.py,sha256=9VM9i2g54UwK0wsQ7z1m3KSDItoAslSk693YKGXPq0s,43309
61
60
  ibm_watsonx_orchestrate/cli/commands/server/types.py,sha256=UCrgGErbSVBnOzesfjrIii4tTCuVfWemYz5AKGZX0oA,4213
62
61
  ibm_watsonx_orchestrate/cli/commands/settings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
62
  ibm_watsonx_orchestrate/cli/commands/settings/settings_command.py,sha256=CzXRkd-97jXyS6LtaaNtMah-aZu0919dYl-mDwzGThc,344
@@ -65,8 +64,8 @@ ibm_watsonx_orchestrate/cli/commands/settings/observability/__init__.py,sha256=4
65
64
  ibm_watsonx_orchestrate/cli/commands/settings/observability/observability_command.py,sha256=TAkpKwoqocsShSgEeR6LzHCzJx16VDQ6cYsbpljxeqI,372
66
65
  ibm_watsonx_orchestrate/cli/commands/settings/observability/langfuse/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
66
  ibm_watsonx_orchestrate/cli/commands/settings/observability/langfuse/langfuse_command.py,sha256=Wa0L8E44EdxH9LdOvmnluLk_ApJVfTLauNOC1kV4W8k,6515
68
- ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_command.py,sha256=e2VwpxbN7vwfFp6Gu8hDe2B5c3fdzXYfQBkN15tYR90,4195
69
- ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_controller.py,sha256=fq48tWNbuYFjrHXyVDmJBT96tww5iMdE2iOYUjr-fUc,11563
67
+ ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_command.py,sha256=KI96Yexq4ZkM-VxcW88oMszjnOxbdU7quSxFtvf_ry4,4367
68
+ ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_controller.py,sha256=3Jykp5-DzMM_At8kYJto171V6LesaqKdsk2nfg1TRpk,11949
70
69
  ibm_watsonx_orchestrate/cli/commands/tools/tools_command.py,sha256=Cuo1ZvlfsymojqbadCqdwwS0HUjaWpe2XQrV70g61_s,3943
71
70
  ibm_watsonx_orchestrate/cli/commands/tools/tools_controller.py,sha256=uL0WHi0YD7NIYSLOui-CymVHj-h9Y0i3PxS7T2SXSvo,40408
72
71
  ibm_watsonx_orchestrate/cli/commands/tools/types.py,sha256=_md0GEa_cTH17NO_moWDY_LNdFvyEFQ1UVB9_FltYiA,173
@@ -97,8 +96,8 @@ ibm_watsonx_orchestrate/client/models/models_client.py,sha256=ZvP3iPgUFw_SXp41kJ
97
96
  ibm_watsonx_orchestrate/client/toolkit/toolkit_client.py,sha256=TLFNS39EeBD_t4Y-rX9sGp4sWBDr--mE5qVtHq8Q2hk,3121
98
97
  ibm_watsonx_orchestrate/client/tools/tempus_client.py,sha256=24fKDZUOVHBW-Vj4mubnpnUmab5LgGn8u5hOVyJaozI,1804
99
98
  ibm_watsonx_orchestrate/client/tools/tool_client.py,sha256=d3i3alVwa0TCN72w9sWOrM20GCbNmnpTnqEOJVbBIFM,1994
100
- ibm_watsonx_orchestrate/docker/compose-lite.yml,sha256=igtukwqVFamdaRbuAbrlLPU8EfZ7hpveWSA0Ka34YHo,39437
101
- ibm_watsonx_orchestrate/docker/default.env,sha256=84p3BEFeA0mVe_C_WKMi4JLiOhQkFLq8hwI_Hoe1eWE,5894
99
+ ibm_watsonx_orchestrate/docker/compose-lite.yml,sha256=JrBImiUmcIfk0BJfQe_LFgPlLKnfZ1B7PTH1IPfedt0,43150
100
+ ibm_watsonx_orchestrate/docker/default.env,sha256=33zXK2uObFVZzJPZ6O53Zt7e2TKnugIWrUIeFz8jGhc,6087
102
101
  ibm_watsonx_orchestrate/docker/proxy-config-single.yaml,sha256=WEbK4ENFuTCYhzRu_QblWp1_GMARgZnx5vReQafkIG8,308
103
102
  ibm_watsonx_orchestrate/docker/start-up.sh,sha256=LTtwHp0AidVgjohis2LXGvZnkFQStOiUAxgGABOyeUI,1811
104
103
  ibm_watsonx_orchestrate/docker/sdk/ibm_watsonx_orchestrate-0.6.0-py3-none-any.whl,sha256=Hi3-owh5OM0Jz2ihX9nLoojnr7Ky1TV-GelyqLcewLE,2047417
@@ -106,14 +105,14 @@ ibm_watsonx_orchestrate/docker/sdk/ibm_watsonx_orchestrate-0.6.0.tar.gz,sha256=e
106
105
  ibm_watsonx_orchestrate/docker/tempus/common-config.yaml,sha256=Zo3F36F5DV4VO_vUg1RG-r4WhcukVh79J2fXhGl6j0A,22
107
106
  ibm_watsonx_orchestrate/flow_builder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
108
107
  ibm_watsonx_orchestrate/flow_builder/data_map.py,sha256=1brmWWFERDsNG2XGais-5-r58LKUUwBtqwdaLQIFRhE,503
109
- ibm_watsonx_orchestrate/flow_builder/node.py,sha256=I90a-K_xnEgZrl2NHo_rDmfT2Dj0n0Om15aDnEzhe74,4755
110
- ibm_watsonx_orchestrate/flow_builder/types.py,sha256=xNXHWxVMx7e954ERveBpl52BFTGOx6pZq4k3zVxJEng,37166
111
- ibm_watsonx_orchestrate/flow_builder/utils.py,sha256=wTyYnLmB_SsT7A-VxRRnqNZ6jwChJ95EnlZ2wZXU03o,11731
108
+ ibm_watsonx_orchestrate/flow_builder/node.py,sha256=l9J9bMyrvU5yKT2W0G9M-KM5rrfCeuG8jcANegQkrL8,5971
109
+ ibm_watsonx_orchestrate/flow_builder/types.py,sha256=3KckhswqMPsFM7md28K-C93jYgH7LZW4dROeuEuHltU,38519
110
+ ibm_watsonx_orchestrate/flow_builder/utils.py,sha256=OgJxIXeF4-qT3CMct4qi87IzXcUByOldwU0KqhIJ81E,11697
112
111
  ibm_watsonx_orchestrate/flow_builder/flows/__init__.py,sha256=dHS2fB-xbVS5yt_yNyZqYeuiAGs78lbCF65AX_VQlD4,1025
113
- ibm_watsonx_orchestrate/flow_builder/flows/constants.py,sha256=XXYtL5Y1OTjj3jKo2zoJiwb7FCUNu_M43fgU8w591TY,322
112
+ ibm_watsonx_orchestrate/flow_builder/flows/constants.py,sha256=-TGneZyjA4YiAtJJK7OmmjDHYQC4mw2e98MPAZqiB50,324
114
113
  ibm_watsonx_orchestrate/flow_builder/flows/decorators.py,sha256=lr4qSWq5PWqlGFf4fzUQZCVQDHBYflrYwZ24S89Aq80,2794
115
114
  ibm_watsonx_orchestrate/flow_builder/flows/events.py,sha256=VyaBm0sADwr15LWfKbcBQS1M80NKqzYDj3UlW3OpOf4,2984
116
- ibm_watsonx_orchestrate/flow_builder/flows/flow.py,sha256=a33ciPFM5VUQlY4BdcXAQVed_MGARNi_GpChIHJ1uS4,55124
115
+ ibm_watsonx_orchestrate/flow_builder/flows/flow.py,sha256=NivtbU33urrE0oi0yGrirh757dz2s9_WZi68h3gf4hQ,56822
117
116
  ibm_watsonx_orchestrate/run/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
118
117
  ibm_watsonx_orchestrate/run/connections.py,sha256=K-65GXPA8GEsVmRdPfMe_LB2G9RfXQUr95wvRUOhkS4,1828
119
118
  ibm_watsonx_orchestrate/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -122,8 +121,8 @@ ibm_watsonx_orchestrate/utils/utils.py,sha256=U7z_2iASoFiZ2zM0a_2Mc2Y-P5oOT7hOwu
122
121
  ibm_watsonx_orchestrate/utils/logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
123
122
  ibm_watsonx_orchestrate/utils/logging/logger.py,sha256=FzeGnidXAjC7yHrvIaj4KZPeaBBSCniZFlwgr5yV3oA,1037
124
123
  ibm_watsonx_orchestrate/utils/logging/logging.yaml,sha256=9_TKfuFr1barnOKP0fZT5D6MhddiwsXVTFjtRbcOO5w,314
125
- ibm_watsonx_orchestrate-1.9.0b0.dist-info/METADATA,sha256=UJ2foCbjQAimZdumyE7BfggZo_iLLQGeNDZKWbtz5Po,1431
126
- ibm_watsonx_orchestrate-1.9.0b0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
127
- ibm_watsonx_orchestrate-1.9.0b0.dist-info/entry_points.txt,sha256=SfIT02-Jen5e99OcLhzbcM9Bdyf8SGVOCtnSplgZdQI,69
128
- ibm_watsonx_orchestrate-1.9.0b0.dist-info/licenses/LICENSE,sha256=Shgxx7hTdCOkiVRmfGgp_1ISISrwQD7m2f0y8Hsapl4,1083
129
- ibm_watsonx_orchestrate-1.9.0b0.dist-info/RECORD,,
124
+ ibm_watsonx_orchestrate-1.9.0b1.dist-info/METADATA,sha256=Jxibq7aV6_Wqi15CpBEFfRnx8QckAtI2sEx4ZKBs0qA,1362
125
+ ibm_watsonx_orchestrate-1.9.0b1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
126
+ ibm_watsonx_orchestrate-1.9.0b1.dist-info/entry_points.txt,sha256=SfIT02-Jen5e99OcLhzbcM9Bdyf8SGVOCtnSplgZdQI,69
127
+ ibm_watsonx_orchestrate-1.9.0b1.dist-info/licenses/LICENSE,sha256=Shgxx7hTdCOkiVRmfGgp_1ISISrwQD7m2f0y8Hsapl4,1083
128
+ ibm_watsonx_orchestrate-1.9.0b1.dist-info/RECORD,,
@@ -1,149 +0,0 @@
1
- import json
2
- from pathlib import Path
3
- from typing import Any, Dict, Type, Literal
4
-
5
- import jsonschema
6
- from pydantic import BaseModel
7
- from pydantic.json_schema import DEFAULT_REF_TEMPLATE, GenerateJsonSchema, JsonSchemaMode
8
- from pydantic.main import IncEx
9
- from typing_extensions import Self
10
-
11
- from ibm_watsonx_orchestrate.agent_builder.tools import ToolRequestBody, ToolResponseBody, JsonSchemaObject
12
-
13
-
14
- def generate_schema_only_base_model(schema: ToolRequestBody | ToolResponseBody | JsonSchemaObject) -> Type[BaseModel]:
15
- class SchemaOnlyBaseModel(BaseModel):
16
- __primitive__: Any
17
- model_config = {
18
- 'extra': 'allow'
19
- }
20
- """
21
- The purpose of a SchemaOnlyBaseModel is to pass along the json schema represented by schema
22
- to a langchain tool's arg_schema
23
- :arg schema The json schema to emulate
24
- :returns a fake BaseModel that only returns a json schema
25
- """
26
-
27
- def __init__(self, /, *args, **kwargs: Any) -> None:
28
- if schema.type == 'object':
29
- super().__init__(**kwargs)
30
- for name, value in kwargs.items():
31
- setattr(self, name, value)
32
- else:
33
- kwargs={}
34
- kwargs['__primitive__'] = args[0]
35
- super().__init__(**kwargs)
36
- setattr(self, '__primitive__', args[0])
37
-
38
- @classmethod
39
- def model_json_schema(cls, by_alias: bool = True, ref_template: str = DEFAULT_REF_TEMPLATE,
40
- schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema,
41
- mode: JsonSchemaMode = 'validation') -> dict[str, Any]:
42
- return schema.model_dump(exclude_unset=True, exclude_none=True)
43
-
44
- @classmethod
45
- def schema(cls, by_alias: bool = True, ref_template: str = DEFAULT_REF_TEMPLATE) -> Dict[str, Any]:
46
- return schema.model_dump(exclude_unset=True, exclude_none=True)
47
-
48
- @classmethod
49
- def schema_json(cls, *, by_alias: bool = True, ref_template: str = DEFAULT_REF_TEMPLATE,
50
- **dumps_kwargs: Any) -> str:
51
- return schema.model_dump_json(exclude_unset=True, exclude_none=True)
52
-
53
- @classmethod
54
- def model_validate_json(cls, json_data: str | bytes | bytearray, *, strict: bool | None = None,
55
- context: Any | None = None) -> Self:
56
- obj = json.loads(json_data)
57
- jsonschema.validate(obj, schema=schema.model_dump(exclude_unset=True))
58
- if schema.type == 'object':
59
- return SchemaOnlyBaseModel(**obj)
60
- else:
61
- return SchemaOnlyBaseModel(obj)
62
-
63
- @classmethod
64
- def model_validate(cls, obj: Any, *, strict: bool | None = None, from_attributes: bool | None = None,
65
- context: Any | None = None) -> Self:
66
- jsonschema.validate(obj, schema=schema.model_dump(exclude_unset=True))
67
- if schema.type == 'object':
68
- return SchemaOnlyBaseModel(**obj)
69
- else:
70
- return SchemaOnlyBaseModel(obj)
71
-
72
- @classmethod
73
- def model_validate_strings(cls, obj: Any, *, strict: bool | None = None, context: Any | None = None) -> Self:
74
- raise NotImplementedError('unimplemented for SchemaOnlyBaseModel')
75
-
76
- @classmethod
77
- def validate(cls, value: Any) -> Self:
78
- jsonschema.validate(value, schema=schema.model_dump(exclude_unset=True))
79
- return SchemaOnlyBaseModel(**value)
80
-
81
- @classmethod
82
- def model_construct(cls, _fields_set: set[str] | None = None, **values: Any) -> Self:
83
- raise NotImplementedError('unimplemented for SchemaOnlyBaseModel')
84
-
85
- @classmethod
86
- def model_parametrized_name(cls, params: tuple[type[Any], ...]) -> str:
87
- raise NotImplementedError('unimplemented for SchemaOnlyBaseModel')
88
-
89
- @classmethod
90
- def model_rebuild(cls, *, force: bool = False, raise_errors: bool = True, _parent_namespace_depth: int = 2,
91
- _types_namespace: Any = None) -> bool | None:
92
- raise NotImplementedError('unimplemented for SchemaOnlyBaseModel')
93
-
94
- @classmethod
95
- def parse_obj(cls, obj: Any) -> Self:
96
- raise NotImplementedError('unimplemented for SchemaOnlyBaseModel')
97
-
98
- @classmethod
99
- def parse_raw(cls, b: str | bytes, *, content_type: str | None = None, encoding: str = 'utf8',
100
- proto: Any | None = None, allow_pickle: bool = False) -> Self:
101
- raise NotImplementedError('unimplemented for SchemaOnlyBaseModel')
102
-
103
- @classmethod
104
- def parse_file(cls, path: str | Path, *, content_type: str | None = None, encoding: str = 'utf8',
105
- proto: Any | None = None, allow_pickle: bool = False) -> Self:
106
- raise NotImplementedError('unimplemented for SchemaOnlyBaseModel')
107
-
108
- @classmethod
109
- def from_orm(cls, obj: Any) -> Self:
110
- raise NotImplementedError('unimplemented for SchemaOnlyBaseModel')
111
-
112
- @classmethod
113
- def construct(cls, _fields_set: set[str] | None = None, **values: Any) -> Self:
114
- raise NotImplementedError('unimplemented for SchemaOnlyBaseModel')
115
-
116
- @classmethod
117
- def update_forward_refs(cls, **localns: Any) -> None:
118
- raise NotImplementedError('unimplemented for SchemaOnlyBaseModel')
119
-
120
- def model_dump(self, *, mode: Literal['json', 'python'] | str = 'python', include: IncEx | None = None,
121
- exclude: IncEx | None = None, context: Any | None = None, by_alias: bool = False,
122
- exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False,
123
- round_trip: bool = False, warnings: bool | Literal['none', 'warn', 'error'] = True,
124
- serialize_as_any: bool = False) -> dict[str, Any]:
125
- primitive = getattr(self, '__primitive__', None)
126
- if primitive is not None:
127
- return primitive
128
- else:
129
- return super().model_dump(mode=mode, include=include, exclude=exclude, context=context, by_alias=by_alias,
130
- exclude_unset=exclude_unset, exclude_defaults=exclude_defaults,
131
- exclude_none=exclude_none, round_trip=round_trip, warnings=warnings,
132
- serialize_as_any=serialize_as_any)
133
-
134
- def model_dump_json(self, *, indent: int | None = None, include: IncEx | None = None,
135
- exclude: IncEx | None = None, context: Any | None = None, by_alias: bool = False,
136
- exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False,
137
- round_trip: bool = False, warnings: bool | Literal['none', 'warn', 'error'] = True,
138
- serialize_as_any: bool = False) -> str:
139
- primitive = getattr(self, '__primitive__')
140
- if primitive is not None:
141
- return json.dumps(primitive)
142
- else:
143
- return super().model_dump_json(indent=indent, include=include, exclude=exclude, context=context,
144
- by_alias=by_alias, exclude_unset=exclude_unset,
145
- exclude_defaults=exclude_defaults, exclude_none=exclude_none,
146
- round_trip=round_trip, warnings=warnings, serialize_as_any=serialize_as_any)
147
-
148
- return SchemaOnlyBaseModel
149
-