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.
- ibm_watsonx_orchestrate/__init__.py +1 -1
- ibm_watsonx_orchestrate/agent_builder/agents/__init__.py +1 -1
- ibm_watsonx_orchestrate/agent_builder/agents/agent.py +1 -0
- ibm_watsonx_orchestrate/agent_builder/agents/types.py +58 -4
- ibm_watsonx_orchestrate/agent_builder/agents/webchat_customizations/__init__.py +2 -0
- ibm_watsonx_orchestrate/agent_builder/agents/webchat_customizations/prompts.py +33 -0
- ibm_watsonx_orchestrate/agent_builder/agents/webchat_customizations/welcome_content.py +20 -0
- ibm_watsonx_orchestrate/agent_builder/connections/__init__.py +2 -2
- ibm_watsonx_orchestrate/agent_builder/connections/types.py +38 -31
- ibm_watsonx_orchestrate/agent_builder/model_policies/types.py +1 -1
- ibm_watsonx_orchestrate/agent_builder/models/types.py +0 -1
- ibm_watsonx_orchestrate/agent_builder/tools/flow_tool.py +83 -0
- ibm_watsonx_orchestrate/agent_builder/tools/openapi_tool.py +41 -3
- ibm_watsonx_orchestrate/agent_builder/tools/python_tool.py +2 -1
- ibm_watsonx_orchestrate/agent_builder/tools/types.py +14 -1
- ibm_watsonx_orchestrate/cli/commands/agents/agents_command.py +18 -1
- ibm_watsonx_orchestrate/cli/commands/agents/agents_controller.py +122 -17
- ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_controller.py +104 -22
- ibm_watsonx_orchestrate/cli/commands/connections/connections_command.py +26 -18
- ibm_watsonx_orchestrate/cli/commands/connections/connections_controller.py +56 -58
- ibm_watsonx_orchestrate/cli/commands/environment/environment_command.py +29 -4
- ibm_watsonx_orchestrate/cli/commands/environment/environment_controller.py +74 -8
- ibm_watsonx_orchestrate/cli/commands/environment/types.py +1 -0
- ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_command.py +224 -0
- ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_controller.py +158 -0
- ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_command.py +2 -2
- ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_controller.py +2 -2
- ibm_watsonx_orchestrate/cli/commands/models/model_provider_mapper.py +31 -25
- ibm_watsonx_orchestrate/cli/commands/models/models_command.py +6 -6
- ibm_watsonx_orchestrate/cli/commands/models/models_controller.py +17 -8
- ibm_watsonx_orchestrate/cli/commands/server/server_command.py +162 -27
- ibm_watsonx_orchestrate/cli/commands/server/types.py +2 -1
- ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_controller.py +9 -6
- ibm_watsonx_orchestrate/cli/commands/tools/tools_controller.py +37 -22
- ibm_watsonx_orchestrate/cli/config.py +2 -0
- ibm_watsonx_orchestrate/cli/main.py +6 -0
- ibm_watsonx_orchestrate/client/agents/agent_client.py +83 -9
- ibm_watsonx_orchestrate/client/agents/assistant_agent_client.py +3 -3
- ibm_watsonx_orchestrate/client/agents/external_agent_client.py +2 -2
- ibm_watsonx_orchestrate/client/base_api_client.py +11 -10
- ibm_watsonx_orchestrate/client/connections/connections_client.py +49 -14
- ibm_watsonx_orchestrate/client/connections/utils.py +4 -2
- ibm_watsonx_orchestrate/client/credentials.py +4 -0
- ibm_watsonx_orchestrate/client/local_service_instance.py +1 -1
- ibm_watsonx_orchestrate/client/model_policies/model_policies_client.py +2 -2
- ibm_watsonx_orchestrate/client/service_instance.py +42 -1
- ibm_watsonx_orchestrate/client/tools/tempus_client.py +8 -3
- ibm_watsonx_orchestrate/client/utils.py +37 -2
- ibm_watsonx_orchestrate/docker/compose-lite.yml +425 -81
- ibm_watsonx_orchestrate/docker/default.env +53 -15
- ibm_watsonx_orchestrate/docker/proxy-config-single.yaml +12 -0
- ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/flows/__init__.py +3 -2
- ibm_watsonx_orchestrate/flow_builder/flows/decorators.py +77 -0
- ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/flows/events.py +6 -1
- ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/flows/flow.py +85 -92
- ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/types.py +15 -6
- ibm_watsonx_orchestrate/flow_builder/utils.py +215 -0
- ibm_watsonx_orchestrate/run/connections.py +4 -4
- {ibm_watsonx_orchestrate-1.5.1.dist-info → ibm_watsonx_orchestrate-1.7.0a0.dist-info}/METADATA +2 -1
- {ibm_watsonx_orchestrate-1.5.1.dist-info → ibm_watsonx_orchestrate-1.7.0a0.dist-info}/RECORD +68 -61
- ibm_watsonx_orchestrate/experimental/flow_builder/flows/decorators.py +0 -144
- ibm_watsonx_orchestrate/experimental/flow_builder/utils.py +0 -115
- /ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/__init__.py +0 -0
- /ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/data_map.py +0 -0
- /ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/flows/constants.py +0 -0
- /ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/node.py +0 -0
- /ibm_watsonx_orchestrate/{experimental/flow_builder → flow_builder}/resources/flow_status.openapi.yml +0 -0
- {ibm_watsonx_orchestrate-1.5.1.dist-info → ibm_watsonx_orchestrate-1.7.0a0.dist-info}/WHEEL +0 -0
- {ibm_watsonx_orchestrate-1.5.1.dist-info → ibm_watsonx_orchestrate-1.7.0a0.dist-info}/entry_points.txt +0 -0
- {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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
249
|
+
client_secret=client_secret,
|
243
250
|
token_url=token_url,
|
244
|
-
|
251
|
+
auth_url=auth_url,
|
245
252
|
grant_type=grant_type,
|
253
|
+
scopes=scopes,
|
246
254
|
entries=entries
|
247
255
|
)
|
248
256
|
|