ibm-watsonx-orchestrate 1.5.1__py3-none-any.whl → 1.7.0a0__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 (70) hide show
  1. ibm_watsonx_orchestrate/__init__.py +1 -1
  2. ibm_watsonx_orchestrate/agent_builder/agents/__init__.py +1 -1
  3. ibm_watsonx_orchestrate/agent_builder/agents/agent.py +1 -0
  4. ibm_watsonx_orchestrate/agent_builder/agents/types.py +58 -4
  5. ibm_watsonx_orchestrate/agent_builder/agents/webchat_customizations/__init__.py +2 -0
  6. ibm_watsonx_orchestrate/agent_builder/agents/webchat_customizations/prompts.py +33 -0
  7. ibm_watsonx_orchestrate/agent_builder/agents/webchat_customizations/welcome_content.py +20 -0
  8. ibm_watsonx_orchestrate/agent_builder/connections/__init__.py +2 -2
  9. ibm_watsonx_orchestrate/agent_builder/connections/types.py +38 -31
  10. ibm_watsonx_orchestrate/agent_builder/model_policies/types.py +1 -1
  11. ibm_watsonx_orchestrate/agent_builder/models/types.py +0 -1
  12. ibm_watsonx_orchestrate/agent_builder/tools/flow_tool.py +83 -0
  13. ibm_watsonx_orchestrate/agent_builder/tools/openapi_tool.py +41 -3
  14. ibm_watsonx_orchestrate/agent_builder/tools/python_tool.py +2 -1
  15. ibm_watsonx_orchestrate/agent_builder/tools/types.py +14 -1
  16. ibm_watsonx_orchestrate/cli/commands/agents/agents_command.py +18 -1
  17. ibm_watsonx_orchestrate/cli/commands/agents/agents_controller.py +122 -17
  18. ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_controller.py +104 -22
  19. ibm_watsonx_orchestrate/cli/commands/connections/connections_command.py +26 -18
  20. ibm_watsonx_orchestrate/cli/commands/connections/connections_controller.py +56 -58
  21. ibm_watsonx_orchestrate/cli/commands/environment/environment_command.py +29 -4
  22. ibm_watsonx_orchestrate/cli/commands/environment/environment_controller.py +74 -8
  23. ibm_watsonx_orchestrate/cli/commands/environment/types.py +1 -0
  24. ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_command.py +224 -0
  25. ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_controller.py +158 -0
  26. ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_command.py +2 -2
  27. ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_controller.py +2 -2
  28. ibm_watsonx_orchestrate/cli/commands/models/model_provider_mapper.py +31 -25
  29. ibm_watsonx_orchestrate/cli/commands/models/models_command.py +6 -6
  30. ibm_watsonx_orchestrate/cli/commands/models/models_controller.py +17 -8
  31. ibm_watsonx_orchestrate/cli/commands/server/server_command.py +162 -27
  32. ibm_watsonx_orchestrate/cli/commands/server/types.py +2 -1
  33. ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_controller.py +9 -6
  34. ibm_watsonx_orchestrate/cli/commands/tools/tools_controller.py +37 -22
  35. ibm_watsonx_orchestrate/cli/config.py +2 -0
  36. ibm_watsonx_orchestrate/cli/main.py +6 -0
  37. ibm_watsonx_orchestrate/client/agents/agent_client.py +83 -9
  38. ibm_watsonx_orchestrate/client/agents/assistant_agent_client.py +3 -3
  39. ibm_watsonx_orchestrate/client/agents/external_agent_client.py +2 -2
  40. ibm_watsonx_orchestrate/client/base_api_client.py +11 -10
  41. ibm_watsonx_orchestrate/client/connections/connections_client.py +49 -14
  42. ibm_watsonx_orchestrate/client/connections/utils.py +4 -2
  43. ibm_watsonx_orchestrate/client/credentials.py +4 -0
  44. ibm_watsonx_orchestrate/client/local_service_instance.py +1 -1
  45. ibm_watsonx_orchestrate/client/model_policies/model_policies_client.py +2 -2
  46. ibm_watsonx_orchestrate/client/service_instance.py +42 -1
  47. ibm_watsonx_orchestrate/client/tools/tempus_client.py +8 -3
  48. ibm_watsonx_orchestrate/client/utils.py +37 -2
  49. ibm_watsonx_orchestrate/docker/compose-lite.yml +425 -81
  50. ibm_watsonx_orchestrate/docker/default.env +53 -15
  51. ibm_watsonx_orchestrate/docker/proxy-config-single.yaml +12 -0
  52. ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/flows/__init__.py +3 -2
  53. ibm_watsonx_orchestrate/flow_builder/flows/decorators.py +77 -0
  54. ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/flows/events.py +6 -1
  55. ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/flows/flow.py +85 -92
  56. ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/types.py +15 -6
  57. ibm_watsonx_orchestrate/flow_builder/utils.py +215 -0
  58. ibm_watsonx_orchestrate/run/connections.py +4 -4
  59. {ibm_watsonx_orchestrate-1.5.1.dist-info → ibm_watsonx_orchestrate-1.7.0a0.dist-info}/METADATA +2 -1
  60. {ibm_watsonx_orchestrate-1.5.1.dist-info → ibm_watsonx_orchestrate-1.7.0a0.dist-info}/RECORD +68 -61
  61. ibm_watsonx_orchestrate/experimental/flow_builder/flows/decorators.py +0 -144
  62. ibm_watsonx_orchestrate/experimental/flow_builder/utils.py +0 -115
  63. /ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/__init__.py +0 -0
  64. /ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/data_map.py +0 -0
  65. /ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/flows/constants.py +0 -0
  66. /ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/node.py +0 -0
  67. /ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/resources/flow_status.openapi.yml +0 -0
  68. {ibm_watsonx_orchestrate-1.5.1.dist-info → ibm_watsonx_orchestrate-1.7.0a0.dist-info}/WHEEL +0 -0
  69. {ibm_watsonx_orchestrate-1.5.1.dist-info → ibm_watsonx_orchestrate-1.7.0a0.dist-info}/entry_points.txt +0 -0
  70. {ibm_watsonx_orchestrate-1.5.1.dist-info → ibm_watsonx_orchestrate-1.7.0a0.dist-info}/licenses/LICENSE +0 -0
@@ -25,7 +25,7 @@ from ibm_watsonx_orchestrate.agent_builder.agents import (
25
25
  AgentKind,
26
26
  SpecVersion
27
27
  )
28
- from ibm_watsonx_orchestrate.client.agents.agent_client import AgentClient
28
+ from ibm_watsonx_orchestrate.client.agents.agent_client import AgentClient, AgentUpsertResponse
29
29
  from ibm_watsonx_orchestrate.client.agents.external_agent_client import ExternalAgentClient
30
30
  from ibm_watsonx_orchestrate.client.agents.assistant_agent_client import AssistantAgentClient
31
31
  from ibm_watsonx_orchestrate.client.tools.tool_client import ToolClient
@@ -99,6 +99,7 @@ def parse_create_native_args(name: str, kind: AgentKind, description: str | None
99
99
  "style": args.get("style"),
100
100
  "custom_join_tool": args.get("custom_join_tool"),
101
101
  "structured_output": args.get("structured_output"),
102
+ "context_access_enabled": args.get("context_access_enabled", True),
102
103
  }
103
104
 
104
105
  collaborators = args.get("collaborators", [])
@@ -116,6 +117,23 @@ def parse_create_native_args(name: str, kind: AgentKind, description: str | None
116
117
  knowledge_base = [x.strip() for x in knowledge_base if x.strip() != ""]
117
118
  agent_details["knowledge_base"] = knowledge_base
118
119
 
120
+ context_variables = args.get("context_variables", [])
121
+ context_variables = context_variables if context_variables else []
122
+ context_variables = [x.strip() for x in context_variables if x.strip() != ""]
123
+ agent_details["context_variables"] = context_variables
124
+
125
+ # hidden = args.get("hidden")
126
+ # if hidden:
127
+ # agent_details["hidden"] = hidden
128
+
129
+ # starter_prompts = args.get("starter_prompts")
130
+ # if starter_prompts:
131
+ # agent_details["starter_prompts"] = starter_prompts
132
+
133
+ # welcome_content = args.get("welcome_content")
134
+ # if welcome_content:
135
+ # agent_details["welcome_content"] = welcome_content
136
+
119
137
  return agent_details
120
138
 
121
139
  def parse_create_external_args(name: str, kind: AgentKind, description: str | None, **args) -> dict:
@@ -133,8 +151,14 @@ def parse_create_external_args(name: str, kind: AgentKind, description: str | No
133
151
  "config": args.get("config", {}),
134
152
  "nickname": args.get("nickname"),
135
153
  "app_id": args.get("app_id"),
154
+ "context_access_enabled": args.get("context_access_enabled", True),
136
155
  }
137
156
 
157
+ context_variables = args.get("context_variables", [])
158
+ context_variables = context_variables if context_variables else []
159
+ context_variables = [x.strip() for x in context_variables if x.strip() != ""]
160
+ agent_details["context_variables"] = context_variables
161
+
138
162
  return agent_details
139
163
 
140
164
  def parse_create_assistant_args(name: str, kind: AgentKind, description: str | None, **args) -> dict:
@@ -146,8 +170,14 @@ def parse_create_assistant_args(name: str, kind: AgentKind, description: str | N
146
170
  "tags": args.get("tags", []),
147
171
  "config": args.get("config", {}),
148
172
  "nickname": args.get("nickname"),
173
+ "context_access_enabled": args.get("context_access_enabled", True),
149
174
  }
150
175
 
176
+ context_variables = args.get("context_variables", [])
177
+ context_variables = context_variables if context_variables else []
178
+ context_variables = [x.strip() for x in context_variables if x.strip() != ""]
179
+ agent_details["context_variables"] = context_variables
180
+
151
181
  return agent_details
152
182
 
153
183
  def get_conn_id_from_app_id(app_id: str) -> str:
@@ -177,6 +207,10 @@ def get_agent_details(name: str, client: AgentClient | ExternalAgentClient | Ass
177
207
 
178
208
  return agent_specs[0]
179
209
 
210
+ def _raise_guidelines_warning(response: AgentUpsertResponse) -> None:
211
+ if response.warning:
212
+ logger.warning(f"Agent Configuration Issue: {response.warning}")
213
+
180
214
  class AgentsController:
181
215
  def __init__(self):
182
216
  self.native_client = None
@@ -420,6 +454,72 @@ class AgentsController:
420
454
  ref_agent.knowledge_base = ref_knowledge_bases
421
455
  return ref_agent
422
456
 
457
+ def dereference_guidelines(self, agent: Agent) -> Agent:
458
+ tool_client = self.get_tool_client()
459
+
460
+ guideline_tool_names = set()
461
+
462
+ for guideline in agent.guidelines:
463
+ if guideline.tool:
464
+ guideline_tool_names.add(guideline.tool)
465
+
466
+ if len(guideline_tool_names) == 0:
467
+ return agent
468
+
469
+ deref_agent = deepcopy(agent)
470
+
471
+ matching_tools = tool_client.get_drafts_by_names(list(guideline_tool_names))
472
+
473
+ name_id_lookup = {}
474
+ for tool in matching_tools:
475
+ if tool.get("name") in name_id_lookup:
476
+ logger.error(f"Duplicate draft entries for tool '{tool.get('name')}'")
477
+ sys.exit(1)
478
+ name_id_lookup[tool.get("name")] = tool.get("id")
479
+
480
+ for guideline in deref_agent.guidelines:
481
+ if guideline.tool:
482
+ id = name_id_lookup.get(guideline.tool)
483
+ if not id:
484
+ logger.error(f"Failed to find guideline tool. No tools found with the name '{guideline.tool}'")
485
+ sys.exit(1)
486
+ guideline.tool = id
487
+
488
+ return deref_agent
489
+
490
+ def reference_guidelines(self, agent: Agent) -> Agent:
491
+ tool_client = self.get_tool_client()
492
+
493
+ guideline_tool_ids = set()
494
+
495
+ for guideline in agent.guidelines:
496
+ if guideline.tool:
497
+ guideline_tool_ids.add(guideline.tool)
498
+
499
+ if len(guideline_tool_ids) == 0:
500
+ return agent
501
+
502
+ ref_agent = deepcopy(agent)
503
+
504
+ matching_tools = tool_client.get_drafts_by_ids(list(guideline_tool_ids))
505
+
506
+ id_name_lookup = {}
507
+ for tool in matching_tools:
508
+ if tool.get("id") in id_name_lookup:
509
+ logger.error(f"Duplicate draft entries for tool '{tool.get('id')}'")
510
+ sys.exit(1)
511
+ id_name_lookup[tool.get("id")] = tool.get("name")
512
+
513
+ for guideline in ref_agent.guidelines:
514
+ if guideline.tool:
515
+ name = id_name_lookup.get(guideline.tool)
516
+ if not name:
517
+ logger.error(f"Failed to find guideline tool. No tools found with the id '{guideline.tool}'")
518
+ sys.exit(1)
519
+ guideline.tool = name
520
+
521
+ return ref_agent
522
+
423
523
  @staticmethod
424
524
  def dereference_app_id(agent: ExternalAgent | AssistantAgent) -> ExternalAgent | AssistantAgent:
425
525
  if agent.kind == AgentKind.EXTERNAL:
@@ -448,6 +548,8 @@ class AgentsController:
448
548
  agent = self.dereference_tools(agent)
449
549
  if agent.knowledge_base and len(agent.knowledge_base):
450
550
  agent = self.dereference_knowledge_bases(agent)
551
+ if agent.guidelines and len(agent.guidelines):
552
+ agent = self.dereference_guidelines(agent)
451
553
 
452
554
  return agent
453
555
 
@@ -458,10 +560,12 @@ class AgentsController:
458
560
  agent = self.reference_tools(agent)
459
561
  if agent.knowledge_base and len(agent.knowledge_base):
460
562
  agent = self.reference_knowledge_bases(agent)
563
+ if agent.guidelines and len(agent.guidelines):
564
+ agent = self.reference_guidelines(agent)
461
565
 
462
566
  return agent
463
567
 
464
- def dereference_external_or_assistant_agent_dependencies(self, agent: ExternalAgent | AssistantAgent) -> ExternalAgent | AssistantAgent:
568
+ def dereference_external_or_assistant_agent_dependencies(self, agent: ExternalAgent | AssistantAgent) -> ExternalAgent | AssistantAgent:
465
569
  agent_dict = agent.model_dump()
466
570
 
467
571
  if agent_dict.get("app_id") or agent.config.model_dump().get("app_id"):
@@ -469,7 +573,7 @@ class AgentsController:
469
573
 
470
574
  return agent
471
575
 
472
- def reference_external_or_assistant_agent_dependencies(self, agent: ExternalAgent | AssistantAgent) -> ExternalAgent | AssistantAgent:
576
+ def reference_external_or_assistant_agent_dependencies(self, agent: ExternalAgent | AssistantAgent) -> ExternalAgent | AssistantAgent:
473
577
  agent_dict = agent.model_dump()
474
578
 
475
579
  if agent_dict.get("connection_id") or agent.config.model_dump().get("connection_id"):
@@ -543,7 +647,8 @@ class AgentsController:
543
647
 
544
648
  def publish_agent(self, agent: Agent, **kwargs) -> None:
545
649
  if isinstance(agent, Agent):
546
- self.get_native_client().create(agent.model_dump(exclude_none=True))
650
+ response = self.get_native_client().create(agent.model_dump(exclude_none=True))
651
+ _raise_guidelines_warning(response)
547
652
  logger.info(f"Agent '{agent.name}' imported successfully")
548
653
  if isinstance(agent, ExternalAgent):
549
654
  self.get_external_client().create(agent.model_dump(exclude_none=True))
@@ -557,7 +662,8 @@ class AgentsController:
557
662
  ) -> None:
558
663
  if isinstance(agent, Agent):
559
664
  logger.info(f"Existing Agent '{agent.name}' found. Updating...")
560
- self.get_native_client().update(agent_id, agent.model_dump(exclude_none=True))
665
+ response = self.get_native_client().update(agent_id, agent.model_dump(exclude_none=True))
666
+ _raise_guidelines_warning(response)
561
667
  logger.info(f"Agent '{agent.name}' updated successfully")
562
668
  if isinstance(agent, ExternalAgent):
563
669
  logger.info(f"Existing External Agent '{agent.name}' found. Updating...")
@@ -660,14 +766,14 @@ class AgentsController:
660
766
  show_lines=True
661
767
  )
662
768
  column_args = {
663
- "Name": {},
769
+ "Name": {"overflow": "fold"},
664
770
  "Description": {},
665
771
  "LLM": {"overflow": "fold"},
666
772
  "Style": {},
667
773
  "Collaborators": {},
668
774
  "Tools": {},
669
775
  "Knowledge Base": {},
670
- "ID": {},
776
+ "ID": {"overflow": "fold"},
671
777
  }
672
778
  for column in column_args:
673
779
  native_table.add_column(column, **column_args[column])
@@ -717,7 +823,7 @@ class AgentsController:
717
823
  show_lines=True
718
824
  )
719
825
  column_args = {
720
- "Name": {},
826
+ "Name": {"overflow": "fold"},
721
827
  "Title": {},
722
828
  "Description": {},
723
829
  "Tags": {},
@@ -725,9 +831,9 @@ class AgentsController:
725
831
  "Chat Params": {},
726
832
  "Config": {},
727
833
  "Nickname": {},
728
- "App ID": {},
729
- "ID": {}
730
- }
834
+ "App ID": {"overflow": "fold"},
835
+ "ID": {"overflow": "fold"}
836
+ }
731
837
 
732
838
  for column in column_args:
733
839
  external_table.add_column(column, **column_args[column])
@@ -778,17 +884,17 @@ class AgentsController:
778
884
  title="Assistant Agents",
779
885
  show_lines=True)
780
886
  column_args = {
781
- "Name": {},
887
+ "Name": {"overflow": "fold"},
782
888
  "Title": {},
783
889
  "Description": {},
784
890
  "Tags": {},
785
891
  "Nickname": {},
786
892
  "CRN": {},
787
893
  "Instance URL": {},
788
- "Assistant ID": {},
789
- "Environment ID": {},
790
- "ID": {}
791
- }
894
+ "Assistant ID": {"overflow": "fold"},
895
+ "Environment ID": {"overflow": "fold"},
896
+ "ID": {"overflow": "fold"}
897
+ }
792
898
 
793
899
  for column in column_args:
794
900
  assistants_table.add_column(column, **column_args[column])
@@ -875,7 +981,6 @@ class AgentsController:
875
981
 
876
982
 
877
983
  def export_agent(self, name: str, kind: AgentKind, output_path: str, agent_only_flag: bool=False, zip_file_out: zipfile.ZipFile | None = None) -> None:
878
-
879
984
  output_file = Path(output_path)
880
985
  output_file_extension = output_file.suffix
881
986
  output_file_name = output_file.stem
@@ -1,10 +1,10 @@
1
1
  import logging
2
- import logging
3
2
  import rich
4
3
  import jwt
4
+ import sys
5
5
 
6
6
  from ibm_watsonx_orchestrate.cli.config import Config, ENV_WXO_URL_OPT, ENVIRONMENTS_SECTION_HEADER, CONTEXT_SECTION_HEADER, CONTEXT_ACTIVE_ENV_OPT, CHAT_UI_PORT
7
- from ibm_watsonx_orchestrate.client.utils import is_local_dev, AUTH_CONFIG_FILE_FOLDER, AUTH_SECTION_HEADER, AUTH_MCSP_TOKEN_OPT, AUTH_CONFIG_FILE
7
+ from ibm_watsonx_orchestrate.client.utils import is_local_dev, is_ibm_cloud, AUTH_CONFIG_FILE_FOLDER, AUTH_SECTION_HEADER, AUTH_MCSP_TOKEN_OPT, AUTH_CONFIG_FILE
8
8
 
9
9
  from ibm_watsonx_orchestrate.client.agents.agent_client import AgentClient
10
10
 
@@ -20,7 +20,41 @@ class ChannelsWebchatController:
20
20
  def get_native_client(self):
21
21
  self.native_client = instantiate_client(AgentClient)
22
22
  return self.native_client
23
-
23
+
24
+ def extract_tenant_id_from_crn(self, crn: str) -> str:
25
+ is_ibm_cloud_env = is_ibm_cloud()
26
+ if is_ibm_cloud_env:
27
+ try:
28
+ parts = crn.split("a/")[1].split(":")
29
+ account_part = parts[0]
30
+ instance_part = parts[1]
31
+ tenant_id = f"{account_part}_{instance_part}"
32
+ return tenant_id
33
+ except (IndexError, AttributeError):
34
+ raise ValueError(f"Invalid CRN format: {crn}")
35
+ else:
36
+ try:
37
+ parts = crn.split("sub/")[1].split(":")
38
+ account_part = parts[0]
39
+ instance_part = parts[1]
40
+ tenant_id = f"{account_part}_{instance_part}"
41
+ return tenant_id
42
+ except (IndexError, AttributeError):
43
+ raise ValueError(f"Invalid CRN format: {crn}")
44
+
45
+
46
+
47
+ def check_crn_is_correct(self, crn: str):
48
+ parts = crn.split("a/")[1].split(":")
49
+ instance_part_crn = parts[1]
50
+ cfg = Config()
51
+ active_env = cfg.read(CONTEXT_SECTION_HEADER, CONTEXT_ACTIVE_ENV_OPT)
52
+ url = cfg.get(ENVIRONMENTS_SECTION_HEADER, active_env, ENV_WXO_URL_OPT)
53
+ instance_part_url = url.rstrip("/").split("/")[-1]
54
+ if instance_part_crn == instance_part_url:
55
+ return True
56
+ else:
57
+ return False
24
58
 
25
59
  def get_agent_id(self, agent_name: str):
26
60
  native_client = self.get_native_client()
@@ -40,7 +74,7 @@ class ChannelsWebchatController:
40
74
  raise ValueError(f"No agent found with the name '{agent_name}'")
41
75
 
42
76
  agent = existing_native_agents[0]
43
- agent_environments = agent.get("environments", [])
77
+ agent_environments = agent.get("environments", [])
44
78
 
45
79
  is_local = is_local_dev()
46
80
  target_env = env or 'draft'
@@ -57,15 +91,37 @@ class ChannelsWebchatController:
57
91
  logger.error(f'This agent does not exist in the {env} environment. You need to deploy it to {env} before you can embed the agent')
58
92
  exit(1)
59
93
 
60
- return filtered_environments[0].get("id")
94
+ if target_env == 'draft' and is_local == False:
95
+ logger.error(f'For SAAS, please ensure this agent exists in a Live Environment')
96
+ exit(1)
97
+
61
98
 
62
99
 
100
+ return filtered_environments[0].get("id")
101
+
63
102
  def get_tennent_id(self):
64
103
  auth_cfg = Config(AUTH_CONFIG_FILE_FOLDER, AUTH_CONFIG_FILE)
65
104
 
66
105
  cfg = Config()
67
106
  active_env = cfg.read(CONTEXT_SECTION_HEADER, CONTEXT_ACTIVE_ENV_OPT)
68
- is_local = is_local_dev()
107
+
108
+ existing_auth_config = auth_cfg.get(AUTH_SECTION_HEADER).get(active_env, {})
109
+
110
+ existing_token = existing_auth_config.get(AUTH_MCSP_TOKEN_OPT) if existing_auth_config else None
111
+ token = jwt.decode(existing_token, options={"verify_signature": False})
112
+ crn = ""
113
+ crn = token.get('aud', None)
114
+
115
+ tenant_id = self.extract_tenant_id_from_crn(crn)
116
+ return tenant_id
117
+
118
+
119
+
120
+ def get_tenant_id_local(self):
121
+ auth_cfg = Config(AUTH_CONFIG_FILE_FOLDER, AUTH_CONFIG_FILE)
122
+
123
+ cfg = Config()
124
+ active_env = cfg.read(CONTEXT_SECTION_HEADER, CONTEXT_ACTIVE_ENV_OPT)
69
125
 
70
126
  existing_auth_config = auth_cfg.get(AUTH_SECTION_HEADER).get(active_env, {})
71
127
 
@@ -73,10 +129,7 @@ class ChannelsWebchatController:
73
129
 
74
130
  token = jwt.decode(existing_token, options={"verify_signature": False})
75
131
  tenant_id = ""
76
- if is_local:
77
- tenant_id = token.get('woTenantId', None)
78
- else:
79
- tenant_id = token.get('tenantId', None)
132
+ tenant_id = token.get('woTenantId', None)
80
133
 
81
134
  return tenant_id
82
135
 
@@ -100,41 +153,70 @@ class ChannelsWebchatController:
100
153
 
101
154
 
102
155
  def create_webchat_embed_code(self):
103
- tenant_id = self.get_tennent_id()
156
+ crn = None
157
+ is_ibm_cloud_env = is_ibm_cloud()
158
+ is_local = is_local_dev()
159
+ if is_ibm_cloud_env is True:
160
+ crn = input("Please enter your CRN which can be gotten from the IBM Cloud UI: ")
161
+ if crn == "":
162
+ logger.error("You must enter your CRN for IBM Cloud instances")
163
+ sys.exit(1)
164
+ is_crn_correct = self.check_crn_is_correct(crn)
165
+ if is_crn_correct == False:
166
+ logger.error("Invalid CRN format provided.")
167
+
168
+ if is_ibm_cloud_env and crn is not None:
169
+ tenant_id = self.extract_tenant_id_from_crn(crn)
170
+ elif is_ibm_cloud_env is False and is_local is False:
171
+ tenant_id = self.get_tennent_id()
172
+ elif is_local:
173
+ tenant_id = self.get_tenant_id_local()
104
174
  host_url = self.get_host_url()
105
175
  agent_id = self.get_agent_id(self.agent_name)
106
176
  agent_env_id = self.get_environment_id(self.agent_name, self.env)
107
177
 
108
- is_local = is_local_dev()
109
178
  script_path = (
110
179
  "/wxoLoader.js?embed=true"
111
180
  if is_local
112
181
  else "/wxochat/wxoLoader.js?embed=true"
113
182
  )
114
183
 
184
+ config_lines = [
185
+ f'orchestrationID: "{tenant_id}"',
186
+ f'hostURL: "{host_url}"',
187
+ 'rootElementID: "root"',
188
+ 'showLauncher: true',
189
+ ]
190
+
191
+ # Conditional fields for IBM Cloud
192
+ if is_ibm_cloud_env:
193
+ config_lines.append(f'crn: "{crn}"')
194
+ if is_ibm_cloud_env:
195
+ config_lines.append(f'deploymentPlatform: "ibmcloud"')
196
+
197
+ config_lines.append(f"""chatOptions: {{
198
+ agentId: "{agent_id}",
199
+ agentEnvironmentId: "{agent_env_id}"
200
+ }}""")
201
+
202
+ config_body = ",\n ".join(config_lines)
203
+
115
204
  script = f"""
116
205
  <script>
117
206
  window.wxOConfiguration = {{
118
- orchestrationID: "{tenant_id}",
119
- hostURL: "{host_url}",
120
- rootElementID: "root",
121
- showLauncher: true,
122
- chatOptions: {{
123
- agentId: "{agent_id}",
124
- agentEnvironmentId: "{agent_env_id}"
125
- }},
207
+ {config_body}
126
208
  }};
127
209
 
128
210
  setTimeout(function () {{
129
211
  const script = document.createElement('script');
130
212
  script.src = `${{window.wxOConfiguration.hostURL}}{script_path}`;
131
213
  script.addEventListener('load', function () {{
132
- wxoLoader.init();
214
+ wxoLoader.init();
133
215
  }});
134
216
  document.head.appendChild(script);
135
217
  }}, 0);
136
218
  </script>
137
- """
219
+ """
138
220
 
139
221
  rich.print(script)
140
222
  return script
@@ -191,31 +191,31 @@ def set_credentials_connection_command(
191
191
  typer.Option(
192
192
  '--client-id',
193
193
  # help='For oauth_auth_on_behalf_of_flow, oauth_auth_code_flow, oauth_auth_implicit_flow, oauth_auth_password_flow and oauth_auth_client_credentials_flow, the client_id to authenticate against the application token server'
194
- help='For oauth_auth_on_behalf_of_flow, the client_id to authenticate against the application token server'
194
+ help='For oauth_auth_on_behalf_of_flow and oauth_auth_client_credentials_flow, the client_id to authenticate against the application token server'
195
+ )
196
+ ] = None,
197
+ client_secret: Annotated[
198
+ str,
199
+ typer.Option(
200
+ '--client-secret',
201
+ help='For oauth_auth_client_credentials_flow, the client_secret to authenticate with'
195
202
  )
196
203
  ] = None,
197
- # client_secret: Annotated[
198
- # str,
199
- # typer.Option(
200
- # '--client-secret',
201
- # help='For oauth_auth_code_flow, oauth_auth_password_flow and oauth_auth_client_credentials_flow, the client_secret to authenticate with'
202
- # )
203
- # ] = None,
204
204
  token_url: Annotated[
205
205
  str,
206
206
  typer.Option(
207
207
  '--token-url',
208
208
  # help='For oauth_auth_on_behalf_of_flow, oauth_auth_code_flow, oauth_auth_password_flow and oauth_auth_client_credentials_flow, the url of the application token server'
209
- help='For oauth_auth_on_behalf_of_flow, the url of the application token server'
209
+ help='For oauth_auth_on_behalf_of_flow and oauth_auth_client_credentials_flow, the url of the application token server'
210
+ )
211
+ ] = None,
212
+ auth_url: Annotated[
213
+ str,
214
+ typer.Option(
215
+ '--auth-url',
216
+ help='For oauth_auth_code_flow, the url of the application token server'
210
217
  )
211
218
  ] = None,
212
- # auth_url: Annotated[
213
- # str,
214
- # typer.Option(
215
- # '--auth-url',
216
- # help='For oauth_auth_code_flow, oauth_auth_implicit_flow and oauth_auth_password_flow, the url of the application token server'
217
- # )
218
- # ] = None,
219
219
  grant_type: Annotated[
220
220
  str,
221
221
  typer.Option(
@@ -223,6 +223,13 @@ def set_credentials_connection_command(
223
223
  help='For oauth_auth_on_behalf_of_flow, the grant type used by the application token server'
224
224
  )
225
225
  ] = None,
226
+ scopes: Annotated[
227
+ List[str],
228
+ typer.Option(
229
+ '--scopes',
230
+ help='For oauth_auth_code_flow and oauth_auth_client_credentials_flow, the optional scopes used by the application token server'
231
+ )
232
+ ] = None,
226
233
  entries: Annotated[
227
234
  List[str],
228
235
  typer.Option(
@@ -239,10 +246,11 @@ def set_credentials_connection_command(
239
246
  token=token,
240
247
  api_key=api_key,
241
248
  client_id=client_id,
242
- # client_secret=client_secret,
249
+ client_secret=client_secret,
243
250
  token_url=token_url,
244
- # auth_url=auth_url,
251
+ auth_url=auth_url,
245
252
  grant_type=grant_type,
253
+ scopes=scopes,
246
254
  entries=entries
247
255
  )
248
256