ibm-watsonx-orchestrate 1.7.0b1__py3-none-any.whl → 1.8.0b0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,8 +5,7 @@
5
5
 
6
6
  pkg_name = "ibm-watsonx-orchestrate"
7
7
 
8
- __version__ = "1.7.0b1"
9
-
8
+ __version__ = "1.8.0b0"
10
9
 
11
10
 
12
11
 
@@ -14,7 +14,17 @@ from ibm_watsonx_orchestrate.utils.exceptions import BadRequest
14
14
  from ibm_watsonx_orchestrate.agent_builder.tools.types import JsonSchemaObject
15
15
 
16
16
  # TO-DO: this is just a placeholder. Will update this later to align with backend
17
- DEFAULT_LLM = "watsonx/meta-llama/llama-3-1-70b-instruct"
17
+ DEFAULT_LLM = "watsonx/meta-llama/llama-3-2-90b-vision-instruct"
18
+
19
+ # Handles yaml formatting for multiline strings to improve readability
20
+ def str_presenter(dumper, data):
21
+ if len(data.splitlines()) > 1: # check for multiline string
22
+ data = "\n".join([line.rstrip() for line in data.splitlines()])
23
+ return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
24
+ return dumper.represent_scalar('tag:yaml.org,2002:str', data)
25
+
26
+ yaml.add_representer(str, str_presenter)
27
+ yaml.representer.SafeRepresenter.add_representer(str, str_presenter) # to use with safe_dum
18
28
 
19
29
  class SpecVersion(str, Enum):
20
30
  V1 = "v1"
@@ -25,6 +35,12 @@ class AgentKind(str, Enum):
25
35
  EXTERNAL = "external"
26
36
  ASSISTANT = "assistant"
27
37
 
38
+ def __str__(self):
39
+ return self.value
40
+
41
+ def __repr__(self):
42
+ return repr(self.value)
43
+
28
44
  class ExternalAgentAuthScheme(str, Enum):
29
45
  BEARER_TOKEN = 'BEARER_TOKEN'
30
46
  API_KEY = "API_KEY"
@@ -4,7 +4,7 @@ import jwt
4
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, is_ibm_cloud, 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_platform, get_environment, get_cpd_instance_id_from_url, is_saas_env, 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
 
@@ -22,7 +22,7 @@ class ChannelsWebchatController:
22
22
  return self.native_client
23
23
 
24
24
  def extract_tenant_id_from_crn(self, crn: str) -> str:
25
- is_ibm_cloud_env = is_ibm_cloud()
25
+ is_ibm_cloud_env = is_ibm_cloud_platform()
26
26
  if is_ibm_cloud_env:
27
27
  try:
28
28
  parts = crn.split("a/")[1].split(":")
@@ -77,6 +77,7 @@ class ChannelsWebchatController:
77
77
  agent_environments = agent.get("environments", [])
78
78
 
79
79
  is_local = is_local_dev()
80
+ is_saas = is_saas_env()
80
81
  target_env = env or 'draft'
81
82
 
82
83
  if is_local:
@@ -91,7 +92,7 @@ class ChannelsWebchatController:
91
92
  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')
92
93
  exit(1)
93
94
 
94
- if target_env == 'draft' and is_local == False:
95
+ if target_env == 'draft' and is_saas == True:
95
96
  logger.error(f'For SAAS, please ensure this agent exists in a Live Environment')
96
97
  exit(1)
97
98
 
@@ -99,7 +100,7 @@ class ChannelsWebchatController:
99
100
 
100
101
  return filtered_environments[0].get("id")
101
102
 
102
- def get_tennent_id(self):
103
+ def get_tenant_id(self):
103
104
  auth_cfg = Config(AUTH_CONFIG_FILE_FOLDER, AUTH_CONFIG_FILE)
104
105
 
105
106
  cfg = Config()
@@ -154,30 +155,40 @@ class ChannelsWebchatController:
154
155
 
155
156
  def create_webchat_embed_code(self):
156
157
  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")
158
+ environment = get_environment()
159
+
160
+ match (environment):
161
+ case "local":
162
+ tenant_id = self.get_tenant_id_local()
163
+
164
+ case "cpd":
165
+ tenant_id = get_cpd_instance_id_from_url()
166
+
167
+ case "ibmcloud":
168
+ crn = input("Please enter your CRN which can be retrieved from the IBM Cloud UI: ")
169
+ if crn == "":
170
+ logger.error("You must enter your CRN for IBM Cloud instances")
171
+ sys.exit(1)
172
+ is_crn_correct = self.check_crn_is_correct(crn)
173
+ if is_crn_correct == False:
174
+ logger.error("Invalid CRN format provided.")
175
+ sys.exit(1)
176
+ tenant_id = self.extract_tenant_id_from_crn(crn)
177
+
178
+ case "ga":
179
+ tenant_id = self.get_tenant_id()
180
+
181
+ case _:
182
+ logger.error("Environment not recognized")
163
183
  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()
184
+
174
185
  host_url = self.get_host_url()
175
186
  agent_id = self.get_agent_id(self.agent_name)
176
187
  agent_env_id = self.get_environment_id(self.agent_name, self.env)
177
188
 
178
189
  script_path = (
179
190
  "/wxoLoader.js?embed=true"
180
- if is_local
191
+ if environment == "local"
181
192
  else "/wxochat/wxoLoader.js?embed=true"
182
193
  )
183
194
 
@@ -189,9 +200,8 @@ class ChannelsWebchatController:
189
200
  ]
190
201
 
191
202
  # Conditional fields for IBM Cloud
192
- if is_ibm_cloud_env:
203
+ if environment == "ibmcloud":
193
204
  config_lines.append(f'crn: "{crn}"')
194
- if is_ibm_cloud_env:
195
205
  config_lines.append(f'deploymentPlatform: "ibmcloud"')
196
206
 
197
207
  config_lines.append(f"""chatOptions: {{
@@ -0,0 +1,65 @@
1
+ import typer
2
+ from typing_extensions import Annotated
3
+ from pathlib import Path
4
+ from ibm_watsonx_orchestrate.cli.commands.copilot.copilot_controller import prompt_tune, create_agent
5
+ from ibm_watsonx_orchestrate.cli.commands.copilot.copilot_server_controller import start_server, stop_server
6
+
7
+ copilot_app = typer.Typer(no_args_is_help=True)
8
+
9
+ # Server Commands
10
+ @copilot_app.command(name="start", help='Start the copilot server')
11
+ def start_server_command(
12
+ user_env_file: str = typer.Option(
13
+ None,
14
+ "--env-file", "-e",
15
+ help="Path to a .env file that overrides default.env. Then environment variables override both."
16
+ )
17
+ ):
18
+ user_env_file_path = Path(user_env_file) if user_env_file else None
19
+
20
+ start_server(user_env_file_path=user_env_file_path)
21
+
22
+ @copilot_app.command(name="stop", help='Stop the copilot server')
23
+ def stop_server_command():
24
+ stop_server()
25
+
26
+ # Functional Commands
27
+ @copilot_app.command(name="prompt-tune", help='Tune the instructions of an Agent using IBM Conversational Prompt Engineering (CPE) to improve agent performance')
28
+ def prompt_tume_command(
29
+ file: Annotated[
30
+ str,
31
+ typer.Option("--file", "-f", help="Path to agent spec file"),
32
+ ] = None,
33
+ output_file: Annotated[
34
+ str,
35
+ typer.Option("--output-file", "-o", help="Optional output file to avoid overwriting existing agent spec"),
36
+ ] = None,
37
+ dry_run_flag: Annotated[
38
+ bool,
39
+ typer.Option("--dry-run", help="Dry run will prevent the tuned content being saved and output the results to console"),
40
+ ] = False,
41
+ llm: Annotated[
42
+ str,
43
+ typer.Option("--llm", help="Select the agent LLM"),
44
+ ] = None,
45
+ samples: Annotated[
46
+ str,
47
+ typer.Option("--samples", "-s", help="Path to utterances sample file (txt file where each line is a utterance, or csv file with a single \"input\" column)"),
48
+ ] = None
49
+ ):
50
+ if file is None:
51
+ # create agent yaml from scratch
52
+ create_agent(
53
+ llm=llm,
54
+ output_file=output_file,
55
+ samples_file=samples,
56
+ dry_run_flag=dry_run_flag
57
+ )
58
+ else:
59
+ # improve existing agent instruction
60
+ prompt_tune(
61
+ agent_spec=file,
62
+ samples_file=samples,
63
+ output_file=output_file,
64
+ dry_run_flag=dry_run_flag,
65
+ )
@@ -0,0 +1,293 @@
1
+ import logging
2
+ import os
3
+ import sys
4
+ import csv
5
+
6
+ import rich
7
+ from rich.console import Console
8
+ from rich.prompt import Prompt
9
+ from rich.progress import Progress, SpinnerColumn, TextColumn
10
+ from requests import ConnectionError
11
+ from typing import List
12
+ from ibm_watsonx_orchestrate.client.base_api_client import ClientAPIException
13
+ from ibm_watsonx_orchestrate.agent_builder.tools import ToolSpec, ToolPermission, ToolRequestBody, ToolResponseBody
14
+ from ibm_watsonx_orchestrate.cli.commands.agents.agents_controller import AgentsController, AgentKind
15
+ from ibm_watsonx_orchestrate.agent_builder.agents.types import DEFAULT_LLM
16
+ from ibm_watsonx_orchestrate.client.tools.tool_client import ToolClient
17
+ from ibm_watsonx_orchestrate.client.copilot.cpe.copilot_cpe_client import CPEClient
18
+ from ibm_watsonx_orchestrate.client.utils import instantiate_client
19
+ from ibm_watsonx_orchestrate.utils.exceptions import BadRequest
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+ def _validate_output_file(output_file: str, dry_run_flag: bool) -> None:
24
+ if not output_file and not dry_run_flag:
25
+ logger.error("Please provide a valid yaml output file. Or use the `--dry-run` flag to output generated agent content to terminal")
26
+ sys.exit(1)
27
+
28
+ if output_file and dry_run_flag:
29
+ logger.error("Cannot set output file when performing a dry run")
30
+ sys.exit(1)
31
+
32
+ if output_file:
33
+ _, file_extension = os.path.splitext(output_file)
34
+ if file_extension not in {".yaml", ".yml", ".json"}:
35
+ logger.error("Output file must be of type '.yaml', '.yml' or '.json'")
36
+ sys.exit(1)
37
+
38
+ def _get_progress_spinner() -> Progress:
39
+ console = Console()
40
+ return Progress(
41
+ SpinnerColumn(spinner_name="dots"),
42
+ TextColumn("[progress.description]{task.description}"),
43
+ transient=True,
44
+ console=console,
45
+ )
46
+
47
+ def _get_incomplete_tool_from_name(tool_name: str) -> dict:
48
+ input_schema = ToolRequestBody(**{"type": "object", "properties": {}})
49
+ output_schema = ToolResponseBody(**{"description": "None"})
50
+ spec = ToolSpec(**{"name": tool_name, "description": tool_name, "permission": ToolPermission.ADMIN, "input_schema": input_schema, "output_schema": output_schema})
51
+ return spec.model_dump()
52
+
53
+ def _get_tools_from_names(tool_names: List[str]) -> List[dict]:
54
+ if not len(tool_names):
55
+ return []
56
+
57
+ tool_client = get_tool_client()
58
+
59
+ try:
60
+ with _get_progress_spinner() as progress:
61
+ task = progress.add_task(description="Fetching tools", total=None)
62
+ tools = tool_client.get_drafts_by_names(tool_names)
63
+ found_tools = {tool.get("name") for tool in tools}
64
+ rich.print("\n")
65
+ for tool_name in tool_names:
66
+ if tool_name not in found_tools:
67
+ logger.warning(f"Failed to find tool named '{tool_name}'. Falling back to incomplete tool definition. Copilot performance maybe effected.")
68
+ tools.append(_get_incomplete_tool_from_name(tool_name))
69
+ progress.remove_task(task)
70
+ except ConnectionError:
71
+ logger.warning(f"Failed to fetch tools from server. For optimal results please start the server and import the relevant tools {', '.join(tool_names)}.")
72
+ tools = []
73
+ for tool_name in tool_names:
74
+ tools.append(_get_incomplete_tool_from_name(tool_name))
75
+
76
+ return tools
77
+
78
+ def get_cpe_client() -> CPEClient:
79
+ url = os.getenv('CPE_URL', "http://localhost:8081")
80
+ return instantiate_client(client=CPEClient, url=url)
81
+
82
+
83
+ def gather_utterances(max: int) -> list[str]:
84
+ utterances = []
85
+ logger.info("Please provide 3 sample utterances you expect your agent to handle:")
86
+
87
+ count = 0
88
+
89
+ while count < max:
90
+ utterance = Prompt.ask(" [green]>[/green]").strip()
91
+
92
+ if utterance.lower() == 'q':
93
+ break
94
+
95
+ if utterance:
96
+ utterances.append(utterance)
97
+ count += 1
98
+
99
+ return utterances
100
+
101
+ def pre_cpe_step(cpe_client, tool_client):
102
+ user_message = ""
103
+ with _get_progress_spinner() as progress:
104
+ task = progress.add_task(description="Initilizing Prompt Engine", total=None)
105
+ response = cpe_client.submit_pre_cpe_chat(user_message=user_message)
106
+ progress.remove_task(task)
107
+
108
+ res = {}
109
+ while True:
110
+ if "message" in response and response["message"]:
111
+ rich.print('\n🤖 Copilot: ' + response["message"])
112
+ user_message = Prompt.ask("\n👤 You").strip()
113
+ message_content = {"user_message": user_message}
114
+ elif "description" in response and response["description"]:
115
+ res["description"] = response["description"]
116
+ tools = find_tools_by_description(res["description"], tool_client)
117
+ message_content = {"tools": tools}
118
+ elif "metadata" in response:
119
+ res["agent_name"] = response["metadata"]["agent_name"]
120
+ res["agent_style"] = response["metadata"]["style"]
121
+ res["tools"] = [t for t in tools if t["name"] in response["metadata"]["tools"]]
122
+ return res
123
+ with _get_progress_spinner() as progress:
124
+ task = progress.add_task(description="Thinking...", total=None)
125
+ response = cpe_client.submit_pre_cpe_chat(**message_content)
126
+ progress.remove_task(task)
127
+
128
+ # TODO: Add description RAG search
129
+ def find_tools_by_description(description, tool_client):
130
+ with _get_progress_spinner() as progress:
131
+ task = progress.add_task(description="Fetching Tools", total=None)
132
+ try:
133
+ tools = tool_client.get()
134
+ except ConnectionError:
135
+ tools = []
136
+ rich.print("\n")
137
+ logger.warning("Failed to contact wxo server to fetch tools. Proceeding with empty tool list")
138
+ progress.remove_task(task)
139
+ return tools
140
+
141
+ def gather_examples(samples_file=None):
142
+ if samples_file:
143
+ if samples_file.endswith('.txt'):
144
+ with open(samples_file) as f:
145
+ examples = f.read().split('\n')
146
+ elif samples_file.endswith('.csv'):
147
+ with open(samples_file, 'r', encoding='utf-8') as f:
148
+ reader = csv.DictReader(f)
149
+ if 'utterance' not in reader.fieldnames:
150
+ raise BadRequest("CSV must have a column named 'utterance'")
151
+ examples = [row['utterance'].strip() for row in reader if row['utterance'].strip()]
152
+ else:
153
+ raise BadRequest(f'Unsupported samples file format: {os.path.basename(samples_file)}')
154
+ else:
155
+ examples = gather_utterances(3)
156
+
157
+ console = Console()
158
+ logger.info("You provided the following samples:")
159
+ for i, utterance in enumerate(examples, 1):
160
+ console.print(f" {i}. {utterance}")
161
+
162
+ return examples
163
+
164
+
165
+ def talk_to_cpe(cpe_client, samples_file=None, context_data=None):
166
+ context_data = context_data or {}
167
+ examples = gather_examples(samples_file)
168
+ # upload or gather input examples
169
+ context_data['examples'] = examples
170
+ response=None
171
+ with _get_progress_spinner() as progress:
172
+ task = progress.add_task(description="Thinking...", total=None)
173
+ response = cpe_client.init_with_context(context_data=context_data)
174
+ progress.remove_task(task)
175
+ accepted_prompt = None
176
+ while accepted_prompt is None:
177
+ resp = response.get('response')[0]
178
+ accepted_prompt = resp.get("final_zsh_prompt", None)
179
+ if not accepted_prompt:
180
+ cpe_message = resp.get("message", "")
181
+ rich.print('\n🤖 Copilot: ' + cpe_message)
182
+ message = Prompt.ask("\n👤 You").strip()
183
+ with _get_progress_spinner() as progress:
184
+ task = progress.add_task(description="Thinking...", total=None)
185
+ response = cpe_client.invoke(prompt=message)
186
+ progress.remove_task(task)
187
+
188
+ return accepted_prompt
189
+
190
+
191
+ def prompt_tune(agent_spec: str, output_file: str | None, samples_file: str | None, dry_run_flag: bool) -> None:
192
+ agent = AgentsController.import_agent(file=agent_spec, app_id=None)[0]
193
+ agent_kind = agent.kind
194
+
195
+ if agent_kind != AgentKind.NATIVE:
196
+ logger.error(
197
+ f"Only native agents are supported for prompt tuning. Provided agent spec is on kind '{agent_kind}'")
198
+ sys.exit(1)
199
+
200
+ if not output_file and not dry_run_flag:
201
+ output_file = agent_spec
202
+
203
+ _validate_output_file(output_file, dry_run_flag)
204
+
205
+ client = get_cpe_client()
206
+
207
+ instr = agent.instructions
208
+ prompt = 'My current prompt is:\n' + instr if instr else "I don't have an initial prompt."
209
+
210
+ tools = _get_tools_from_names(agent.tools)
211
+
212
+ try:
213
+ new_prompt = talk_to_cpe(cpe_client=client, samples_file=samples_file, context_data={"prompt": prompt, 'tools': tools, 'description': agent.description})
214
+ except ConnectionError:
215
+ logger.error("Failed to connect to Copilot server. Please ensure Copilot is running via `orchestrate copilot start`")
216
+ sys.exit(1)
217
+ except ClientAPIException:
218
+ logger.error("An unexpected server error has occur with in the Copilot server. Please check the logs via `orchestrate server logs`")
219
+ sys.exit(1)
220
+
221
+ if new_prompt:
222
+ logger.info(f"The new instruction is: {new_prompt}")
223
+ agent.instructions = new_prompt
224
+
225
+ if dry_run_flag:
226
+ rich.print(agent.model_dump())
227
+ else:
228
+ if os.path.dirname(output_file):
229
+ os.makedirs(os.path.dirname(output_file), exist_ok=True)
230
+ AgentsController.persist_record(agent, output_file=output_file)
231
+
232
+
233
+ def get_tool_client(*args, **kwargs):
234
+ return instantiate_client(ToolClient)
235
+
236
+ def create_agent(output_file: str, llm: str, samples_file: str | None, dry_run_flag: bool = False) -> None:
237
+ _validate_output_file(output_file, dry_run_flag)
238
+ # 1. prepare the clients
239
+ cpe_client = get_cpe_client()
240
+ tool_client = get_tool_client()
241
+
242
+ # 2. Pre-CPE stage:
243
+ try:
244
+ res = pre_cpe_step(cpe_client, tool_client)
245
+ except ConnectionError:
246
+ logger.error("Failed to connect to Copilot server. Please ensure Copilot is running via `orchestrate copilot start`")
247
+ sys.exit(1)
248
+ except ClientAPIException:
249
+ logger.error("An unexpected server error has occur with in the Copilot server. Please check the logs via `orchestrate server logs`")
250
+ sys.exit(1)
251
+
252
+ tools = res["tools"]
253
+ description = res["description"]
254
+ agent_name = res["agent_name"]
255
+ agent_style = res["agent_style"]
256
+
257
+ # 4. discuss the instructions
258
+ instructions = talk_to_cpe(cpe_client, samples_file, {'tools': tools, 'description': description})
259
+
260
+ # 6. create and save the agent
261
+ llm = llm if llm else DEFAULT_LLM
262
+ params = {
263
+ 'style': agent_style,
264
+ 'tools': [t['name'] for t in tools],
265
+ 'llm': llm
266
+ }
267
+ agent = AgentsController.generate_agent_spec(agent_name, AgentKind.NATIVE, description, **params)
268
+ agent.instructions = instructions
269
+
270
+ if dry_run_flag:
271
+ rich.print(agent.model_dump())
272
+ return
273
+
274
+ if os.path.dirname(output_file):
275
+ os.makedirs(os.path.dirname(output_file), exist_ok=True)
276
+ AgentsController.persist_record(agent, output_file=output_file)
277
+
278
+
279
+ message_lines = [
280
+ "Your agent building session finished successfully!",
281
+ f"Agent YAML saved in file:",
282
+ f"{os.path.abspath(output_file)}"
283
+ ]
284
+
285
+ # Determine the width of the frame
286
+ max_length = max(len(line) for line in message_lines)
287
+ frame_width = max_length + 4 # Padding for aesthetics
288
+
289
+ # Print the framed message
290
+ rich.print("╔" + "═" * frame_width + "╗")
291
+ for line in message_lines:
292
+ rich.print("║ " + line.ljust(max_length) + " ║")
293
+ rich.print("╚" + "═" * frame_width + "╝")
@@ -0,0 +1,154 @@
1
+ import logging
2
+ import sys
3
+ from pathlib import Path
4
+ import subprocess
5
+ import time
6
+ import requests
7
+ from ibm_watsonx_orchestrate.cli.commands.server.server_command import (
8
+ get_compose_file,
9
+ ensure_docker_compose_installed,
10
+ _prepare_clean_env,
11
+ ensure_docker_installed,
12
+ read_env_file,
13
+ get_default_env_file,
14
+ get_persisted_user_env,
15
+ get_dev_edition_source,
16
+ get_default_registry_env_vars_by_dev_edition_source,
17
+ docker_login_by_dev_edition_source,
18
+ write_merged_env_file,
19
+ )
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+ def _verify_env_contents(env: dict) -> None:
24
+ if not env.get("WATSONX_APIKEY") or not env.get("WATSONX_SPACE_ID"):
25
+ logger.error("The Copilot feature requires wx.ai credentials to passed through the provided env file. Please set 'WATSONX_SPACE_ID' and 'WATSONX_APIKEY'")
26
+ sys.exit(1)
27
+
28
+ def wait_for_wxo_cpe_health_check(timeout_seconds=45, interval_seconds=2):
29
+ url = "http://localhost:8081/version"
30
+ logger.info("Waiting for Copilot component to be initialized...")
31
+ start_time = time.time()
32
+ while time.time() - start_time <= timeout_seconds:
33
+ try:
34
+ response = requests.get(url)
35
+ if 200 <= response.status_code < 300:
36
+ return True
37
+ else:
38
+ pass
39
+ except requests.RequestException as e:
40
+ pass
41
+
42
+ time.sleep(interval_seconds)
43
+ return False
44
+
45
+ def run_compose_lite_cpe(user_env_file: Path) -> bool:
46
+ compose_path = get_compose_file()
47
+ compose_command = ensure_docker_compose_installed()
48
+ _prepare_clean_env(user_env_file)
49
+ ensure_docker_installed()
50
+
51
+ default_env = read_env_file(get_default_env_file())
52
+ user_env = read_env_file(user_env_file) if user_env_file else {}
53
+ if not user_env:
54
+ user_env = get_persisted_user_env() or {}
55
+
56
+ dev_edition_source = get_dev_edition_source(user_env)
57
+ default_registry_vars = get_default_registry_env_vars_by_dev_edition_source(default_env, user_env, source=dev_edition_source)
58
+
59
+ # Update the default environment with the default registry variables only if they are not already set
60
+ for key in default_registry_vars:
61
+ if key not in default_env or not default_env[key]:
62
+ default_env[key] = default_registry_vars[key]
63
+
64
+ # Merge the default environment with the user environment
65
+ merged_env_dict = {
66
+ **default_env,
67
+ **user_env,
68
+ }
69
+
70
+ _verify_env_contents(merged_env_dict)
71
+
72
+ try:
73
+ docker_login_by_dev_edition_source(merged_env_dict, dev_edition_source)
74
+ except ValueError as ignored:
75
+ # do nothing, as the docker login here is not mandatory
76
+ pass
77
+
78
+ final_env_file = write_merged_env_file(merged_env_dict)
79
+
80
+ command = compose_command + [
81
+ "-f", str(compose_path),
82
+ "--env-file", str(final_env_file),
83
+ "up",
84
+ "cpe",
85
+ "-d",
86
+ "--remove-orphans"
87
+ ]
88
+
89
+ logger.info(f"Starting docker-compose Copilot service...")
90
+ result = subprocess.run(command, capture_output=False)
91
+
92
+ if result.returncode == 0:
93
+ logger.info("Copilot Service started successfully.")
94
+ # Remove the temp file if successful
95
+ if final_env_file.exists():
96
+ final_env_file.unlink()
97
+ else:
98
+ error_message = result.stderr.decode('utf-8') if result.stderr else "Error occurred."
99
+ logger.error(
100
+ f"Error running docker-compose (temporary env file left at {final_env_file}):\n{error_message}"
101
+ )
102
+ return False
103
+
104
+ is_successful_cpe_healthcheck = wait_for_wxo_cpe_health_check()
105
+ if not is_successful_cpe_healthcheck:
106
+ logger.error("The Copilot service did not initialize within the expected time. Check the logs for any errors.")
107
+
108
+ return True
109
+
110
+ def run_compose_lite_cpe_down(is_reset: bool = False) -> None:
111
+ compose_path = get_compose_file()
112
+ compose_command = ensure_docker_compose_installed()
113
+ ensure_docker_installed()
114
+
115
+ default_env = read_env_file(get_default_env_file())
116
+ final_env_file = write_merged_env_file(default_env)
117
+
118
+ command = compose_command + [
119
+ "-f", str(compose_path),
120
+ "--env-file", final_env_file,
121
+ "down",
122
+ "cpe"
123
+ ]
124
+
125
+ if is_reset:
126
+ command.append("--volumes")
127
+ logger.info("Stopping docker-compose Copilot service and resetting volumes...")
128
+ else:
129
+ logger.info("Stopping docker-compose Copilot service...")
130
+
131
+ result = subprocess.run(command, capture_output=False)
132
+
133
+ if result.returncode == 0:
134
+ logger.info("Copilot service stopped successfully.")
135
+ # Remove the temp file if successful
136
+ if final_env_file.exists():
137
+ final_env_file.unlink()
138
+ else:
139
+ error_message = result.stderr.decode('utf-8') if result.stderr else "Error occurred."
140
+ logger.error(
141
+ f"Error running docker-compose (temporary env file left at {final_env_file}):\n{error_message}"
142
+ )
143
+ sys.exit(1)
144
+
145
+ def start_server(user_env_file_path: Path) -> None:
146
+ is_server_started = run_compose_lite_cpe(user_env_file=user_env_file_path)
147
+
148
+ if is_server_started:
149
+ logger.info("Copilot service successfully started")
150
+ else:
151
+ logger.error("Unable to start orchestrate Copilot service. Please check error messages and logs")
152
+
153
+ def stop_server() -> None:
154
+ run_compose_lite_cpe_down()
@@ -390,6 +390,8 @@ def run_compose_lite(final_env_file: Path, experimental_with_langfuse=False, exp
390
390
  "up",
391
391
  "--scale",
392
392
  "ui=0",
393
+ "--scale",
394
+ "cpe=0",
393
395
  "-d",
394
396
  "--remove-orphans",
395
397
  ]
@@ -1,3 +1,4 @@
1
+
1
2
  import typer
2
3
  import sys
3
4
 
@@ -14,6 +15,7 @@ from ibm_watsonx_orchestrate.cli.commands.channels.channels_command import chann
14
15
  from ibm_watsonx_orchestrate.cli.commands.knowledge_bases.knowledge_bases_command import knowledge_bases_app
15
16
  from ibm_watsonx_orchestrate.cli.commands.toolkit.toolkit_command import toolkits_app
16
17
  from ibm_watsonx_orchestrate.cli.commands.evaluations.evaluations_command import evaluation_app
18
+ from ibm_watsonx_orchestrate.cli.commands.copilot.copilot_command import copilot_app
17
19
  from ibm_watsonx_orchestrate.cli.init_helper import init_callback
18
20
 
19
21
  import urllib3
@@ -38,6 +40,7 @@ app.add_typer(chat_app, name="chat", help='Launch the chat ui for your local Dev
38
40
  app.add_typer(models_app, name="models", help='List the available large language models (llms) that can be used in your agent definitions')
39
41
  app.add_typer(channel_app, name="channels", help="Configure channels where your agent can exist on (such as embedded webchat)")
40
42
  app.add_typer(evaluation_app, name="evaluations", help='Evaluate the performance of your agents in your active env')
43
+ app.add_typer(copilot_app, name="copilot", help='Access AI powered assistance to help refine your agents')
41
44
  app.add_typer(settings_app, name="settings", help='Configure the settings for your active env')
42
45
 
43
46
  if __name__ == "__main__":
@@ -3,6 +3,7 @@ import json
3
3
  import requests
4
4
  from abc import ABC, abstractmethod
5
5
  from ibm_cloud_sdk_core.authenticators import MCSPAuthenticator
6
+ from typing_extensions import List
6
7
 
7
8
 
8
9
  class ClientAPIException(requests.HTTPError):
@@ -62,6 +63,17 @@ class BaseAPIClient:
62
63
  self._check_response(response)
63
64
  return response.json() if response.text else {}
64
65
 
66
+ def _post_nd_json(self, path: str, data: dict = None, files: dict = None) -> List[dict]:
67
+ url = f"{self.base_url}{path}"
68
+ response = requests.post(url, headers=self._get_headers(), json=data, files=files)
69
+ self._check_response(response)
70
+
71
+ res = []
72
+ if response.text:
73
+ for line in response.text.splitlines():
74
+ res.append(json.loads(line))
75
+ return res
76
+
65
77
  def _post_form_data(self, path: str, data: dict = None, files: dict = None) -> dict:
66
78
  url = f"{self.base_url}{path}"
67
79
  # Use data argument instead of json so data is encoded as application/x-www-form-urlencoded
@@ -0,0 +1,66 @@
1
+ from typing import Dict, Any
2
+ from uuid import uuid4
3
+
4
+ from ibm_watsonx_orchestrate.client.base_api_client import BaseAPIClient
5
+
6
+
7
+ class CPEClient(BaseAPIClient):
8
+ """
9
+ Client to handle CRUD operations for Conversational Prompt Engineering Service
10
+ """
11
+
12
+ def __init__(self, *args, **kwargs):
13
+ self.chat_id = str(uuid4())
14
+ super().__init__(*args, **kwargs)
15
+ self.base_url = kwargs.get("base_url", self.base_url)
16
+ self.chat_model_name = 'llama-3-3-70b-instruct'
17
+
18
+ def _get_headers(self) -> dict:
19
+ return {
20
+ "chat_id": self.chat_id
21
+ }
22
+
23
+
24
+ def submit_pre_cpe_chat(self, user_message: str | None =None, tools: Dict[str, Any] = None) -> dict:
25
+ payload = {
26
+ "message": user_message,
27
+ "tools": tools,
28
+ "chat_id": self.chat_id,
29
+ "chat_model_name": self.chat_model_name
30
+ }
31
+
32
+ response = self._post_nd_json("/wxo-cpe/create-agent", data=payload)
33
+
34
+ if response:
35
+ return response[-1]
36
+
37
+
38
+ def init_with_context(self, model: str | None = None, context_data: Dict[str, Any] = None) -> dict:
39
+ payload = {
40
+ "context_data": context_data,
41
+ "chat_id": self.chat_id
42
+ }
43
+
44
+ if model:
45
+ payload["target_model_name"] = model
46
+
47
+ response = self._post_nd_json("/wxo-cpe/init_cpe_from_wxo", data=payload)
48
+
49
+ if response:
50
+ return response[-1]
51
+
52
+
53
+ def invoke(self, prompt: str, model: str | None = None, context_data: Dict[str, Any] = None) -> dict:
54
+ payload = {
55
+ "prompt": prompt,
56
+ "context_data": context_data,
57
+ "chat_id": self.chat_id
58
+ }
59
+
60
+ if model:
61
+ payload["target_model_name"] = model
62
+
63
+ response = self._post_nd_json("/wxo-cpe/invoke", data=payload)
64
+
65
+ if response:
66
+ return response[-1]
@@ -21,17 +21,32 @@ from typing import TypeVar
21
21
  import os
22
22
  import jwt
23
23
  import time
24
+ import sys
24
25
 
25
26
  logger = logging.getLogger(__name__)
26
27
  LOCK = Lock()
27
28
  T = TypeVar("T", bound=BaseAPIClient)
28
29
 
30
+ def get_current_env_url() -> str:
31
+ cfg = Config()
32
+ active_env = cfg.read(CONTEXT_SECTION_HEADER, CONTEXT_ACTIVE_ENV_OPT)
33
+ return cfg.get(ENVIRONMENTS_SECTION_HEADER, active_env, ENV_WXO_URL_OPT)
34
+
35
+ def get_cpd_instance_id_from_url(url: str | None = None) -> str:
36
+ if url is None:
37
+ url = get_current_env_url()
38
+
39
+ if not is_cpd_env(url):
40
+ logger.error(f"The host {url} is not a CPD instance")
41
+ sys.exit(1)
42
+
43
+ url_fragments = url.split('/')
44
+ return url_fragments[-1] if url_fragments[-1] else url_fragments[-2]
45
+
29
46
 
30
47
  def is_local_dev(url: str | None = None) -> bool:
31
48
  if url is None:
32
- cfg = Config()
33
- active_env = cfg.read(CONTEXT_SECTION_HEADER, CONTEXT_ACTIVE_ENV_OPT)
34
- url = cfg.get(ENVIRONMENTS_SECTION_HEADER, active_env, ENV_WXO_URL_OPT)
49
+ url = get_current_env_url()
35
50
 
36
51
  if url.startswith("http://localhost"):
37
52
  return True
@@ -47,21 +62,45 @@ def is_local_dev(url: str | None = None) -> bool:
47
62
 
48
63
  return False
49
64
 
50
- def is_ibm_cloud():
51
- cfg = Config()
52
- active_env = cfg.read(CONTEXT_SECTION_HEADER, CONTEXT_ACTIVE_ENV_OPT)
53
- url = cfg.get(ENVIRONMENTS_SECTION_HEADER, active_env, ENV_WXO_URL_OPT)
65
+ def is_cpd_env(url: str | None = None) -> bool:
66
+ if url is None:
67
+ url = get_current_env_url()
68
+
69
+ if url.lower().startswith("https://cpd"):
70
+ return True
71
+ return False
72
+
73
+ def is_saas_env():
74
+ return is_ga_platform() or is_ibm_cloud_platform()
75
+
76
+ def is_ibm_cloud_platform(url:str | None = None) -> bool:
77
+ if url is None:
78
+ url = get_current_env_url()
54
79
 
55
80
  if url.__contains__("cloud.ibm.com"):
56
81
  return True
57
82
  return False
58
83
 
84
+ def is_ga_platform(url: str | None = None) -> bool:
85
+ if url is None:
86
+ url = get_current_env_url()
59
87
 
60
- def is_cpd_env(url: str) -> bool:
61
- if url.lower().startswith("https://cpd"):
88
+ if url.__contains__("orchestrate.ibm.com"):
62
89
  return True
63
90
  return False
64
91
 
92
+
93
+ def get_environment() -> str:
94
+ if is_local_dev():
95
+ return "local"
96
+ if is_cpd_env():
97
+ return "cpd"
98
+ if is_ibm_cloud_platform():
99
+ return "ibmcloud"
100
+ if is_ga_platform():
101
+ return "ga"
102
+ return None
103
+
65
104
  def check_token_validity(token: str) -> bool:
66
105
  try:
67
106
  token_claimset = jwt.decode(token, options={"verify_signature": False})
@@ -796,6 +796,16 @@ services:
796
796
  - 9044:9044
797
797
  depends_on:
798
798
  - wxo-server-db
799
+
800
+ cpe:
801
+ image: ${CPE_REGISTRY:-us.icr.io/watson-orchestrate-private}/wxo-prompt-optimizer:${CPE_TAG:-latest}
802
+ platform: linux/amd64
803
+ restart: unless-stopped
804
+ environment:
805
+ WATSONX_APIKEY: ${WATSONX_APIKEY}
806
+ WATSONX_SPACE_ID: ${WATSONX_SPACE_ID}
807
+ ports:
808
+ - 8081:8080
799
809
 
800
810
  ########################
801
811
  # DOCPROC dependencies
@@ -78,16 +78,16 @@ UITAG=27-06-2025
78
78
  CM_REGISTRY=
79
79
  CM_TAG=27-06-2025
80
80
 
81
- TRM_TAG=26-06-2025
81
+ TRM_TAG=08-07-2025
82
82
  TRM_REGISTRY=
83
83
 
84
- TR_TAG=26-06-2025
84
+ TR_TAG=08-07-2025
85
85
  TR_REGISTRY=
86
86
 
87
87
  BUILDER_TAG=02-07-2025
88
88
  BUILDER_REGISTRY=
89
89
 
90
- FLOW_RUNTIME_TAG=04-07-2025
90
+ FLOW_RUNTIME_TAG=10-07-2025
91
91
  FLOW_RUMTIME_REGISTRY=
92
92
 
93
93
 
@@ -100,6 +100,9 @@ JAEGER_PROXY_REGISTRY=
100
100
  SOCKET_HANDLER_TAG=29-05-2025
101
101
  SOCKET_HANDLER_REGISTRY=
102
102
 
103
+ CPE_TAG=08-07-2025
104
+ CPE_REGISTRY=
105
+
103
106
  # IBM Document Processing
104
107
  WDU_TAG=2.5.0
105
108
  WDU_REGISTRY=
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ibm-watsonx-orchestrate
3
- Version: 1.7.0b1
3
+ Version: 1.8.0b0
4
4
  Summary: IBM watsonx.orchestrate SDK
5
5
  Author-email: IBM <support@ibm.com>
6
6
  License: MIT License
@@ -1,10 +1,10 @@
1
- ibm_watsonx_orchestrate/__init__.py,sha256=kgFqHhOhj-KJp85mk6doUh9YAGBHphAO7fjQfLyIeKQ,428
1
+ ibm_watsonx_orchestrate/__init__.py,sha256=4d69fLyzfeRTVOA__Q6T_majiXB51xYDqWZBiQE1VKw,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
5
5
  ibm_watsonx_orchestrate/agent_builder/agents/assistant_agent.py,sha256=NnWThJ2N8HUOD9IDL6ZhtTKyLMHSacJCpxDNityRmgY,1051
6
6
  ibm_watsonx_orchestrate/agent_builder/agents/external_agent.py,sha256=7HzEFjd7JiiRTgvA1RVA3M0-Mr42FTQnOtGMII5ufk0,1045
7
- ibm_watsonx_orchestrate/agent_builder/agents/types.py,sha256=48oSYRYDPspu9XCf2BPohTm_CrLYgOqCoko8bHh6-cY,12159
7
+ ibm_watsonx_orchestrate/agent_builder/agents/types.py,sha256=6in639wzd0mhy5X6LD6sojWiIePRD5Ryzd_btJ746BA,12797
8
8
  ibm_watsonx_orchestrate/agent_builder/agents/webchat_customizations/__init__.py,sha256=5TXa8UqKUAlDo4hTbE5S9OPEkQhxXhPJHJC4pEe8U00,92
9
9
  ibm_watsonx_orchestrate/agent_builder/agents/webchat_customizations/prompts.py,sha256=jNVF_jgz1Dmt7-RxAceAS0XWXk_fx9h3sS_fGrvZT28,941
10
10
  ibm_watsonx_orchestrate/agent_builder/agents/webchat_customizations/welcome_content.py,sha256=U76wZrblSXx4qv7phcPYs3l8SiFzwZ5cJ74u8Y2iYhU,608
@@ -31,7 +31,7 @@ ibm_watsonx_orchestrate/agent_builder/utils/pydantic_utils.py,sha256=QEanM6Fpkmn
31
31
  ibm_watsonx_orchestrate/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
32
  ibm_watsonx_orchestrate/cli/config.py,sha256=iXjDxymWhAmLSUu6eh7zJR20dYZDzbxcU5VoBdh3VIw,8318
33
33
  ibm_watsonx_orchestrate/cli/init_helper.py,sha256=qxnKdFcPtGsV_6RqP_IuLshRxgB004SxzDAkBTExA-4,1675
34
- ibm_watsonx_orchestrate/cli/main.py,sha256=38e975eZ333VKCapYFdrBsm_sIX8MF2tfq8LewikgoU,2926
34
+ ibm_watsonx_orchestrate/cli/main.py,sha256=eE71dfx-EdDYHymYDqXcTjyMXpX0b3cueXOxCI2YLLs,3119
35
35
  ibm_watsonx_orchestrate/cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
36
  ibm_watsonx_orchestrate/cli/commands/agents/agents_command.py,sha256=Zif3bH3X7j5qf7MWGcr53mJ2oEKXNRHeg3ZHeoHTIqQ,8984
37
37
  ibm_watsonx_orchestrate/cli/commands/agents/agents_controller.py,sha256=skAElLfh8Ip4wVkxpn1wnLskHb1eLU1p9W7GF1abHus,47998
@@ -39,10 +39,13 @@ ibm_watsonx_orchestrate/cli/commands/channels/channels_command.py,sha256=fVIFhPU
39
39
  ibm_watsonx_orchestrate/cli/commands/channels/channels_controller.py,sha256=WjQxwJujvo28SsWgfJSXIpkcgniKcskJ2arL4MOz0Ys,455
40
40
  ibm_watsonx_orchestrate/cli/commands/channels/types.py,sha256=h8gA3EM7k5X08sk8T9b5siL-XL9uUE-hl_jS-0PDBHA,254
41
41
  ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_command.py,sha256=vPCr6z1n1yzGDjTlM4f3_9MiuVRzNmXbvUifm6XyQi8,1103
42
- ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_controller.py,sha256=0S1ch8SwkGRtAyy7nAZEjKl92hFkIE9TU71JJ82zdjU,8128
42
+ ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_controller.py,sha256=1Oze6sN8rH8LVL_52-lG_fjfGLCI0Ui4OytwHRdXAH0,8410
43
43
  ibm_watsonx_orchestrate/cli/commands/chat/chat_command.py,sha256=Q9vg2Z5Fsunu6GQFY_TIsNRhUCa0SSGSPnK4jxSGK34,1581
44
44
  ibm_watsonx_orchestrate/cli/commands/connections/connections_command.py,sha256=qgg2NbAB7g_PHPHd0ZLUm0EjyaCSPi1qpOhtyOlydcY,10151
45
45
  ibm_watsonx_orchestrate/cli/commands/connections/connections_controller.py,sha256=ka7uBpuRlICZ4ACGiT4WqmufZYEw566NlZX5FhB9pXM,22178
46
+ ibm_watsonx_orchestrate/cli/commands/copilot/copilot_command.py,sha256=IxasApIyQYWRMKPXKa38ZPVkUvOc4chggSmSGjgQGXc,2345
47
+ ibm_watsonx_orchestrate/cli/commands/copilot/copilot_controller.py,sha256=FdvBmz7KXq-B9yp6MAuHCXILTgJcvEGZMtXsHFGWfmw,11777
48
+ ibm_watsonx_orchestrate/cli/commands/copilot/copilot_server_controller.py,sha256=OYt0WA0PW9p2R3unpcIplwlTXIK2so9L65JqdGgnLlA,5348
46
49
  ibm_watsonx_orchestrate/cli/commands/environment/environment_command.py,sha256=xwq7gdyjMtl2RYAnLAahGk2wDetr9BStt8yu7JkeBhk,3768
47
50
  ibm_watsonx_orchestrate/cli/commands/environment/environment_controller.py,sha256=oHZ7LONtPg3-SSnU_rRZryLi8N2mplz5h-LGg4XjzD4,10261
48
51
  ibm_watsonx_orchestrate/cli/commands/environment/types.py,sha256=HX8QvqYcc-DGnunQKgYp8q2ohedaHKqsJc7WGlaCxks,223
@@ -54,7 +57,7 @@ ibm_watsonx_orchestrate/cli/commands/login/login_command.py,sha256=xArMiojoozg7E
54
57
  ibm_watsonx_orchestrate/cli/commands/models/model_provider_mapper.py,sha256=RVZfFCuPWiASkR9Mox61v5SZ1AoRxo4_g9stnbfjCkc,7994
55
58
  ibm_watsonx_orchestrate/cli/commands/models/models_command.py,sha256=PW-PIM5Nq0qdCopWjANGBWEuEoA3NLTFThYrN8ggGCI,6425
56
59
  ibm_watsonx_orchestrate/cli/commands/models/models_controller.py,sha256=BNfUoWST60x3k7yIvSbtBR3rmyTQmz9g0TDK2WOoOE4,18610
57
- ibm_watsonx_orchestrate/cli/commands/server/server_command.py,sha256=_nSu5l0WJGvagumScA93h9Nt_T3uzjAN7uwnKyUZHvA,39916
60
+ ibm_watsonx_orchestrate/cli/commands/server/server_command.py,sha256=IkVcYjC_ijmDOYtKfeoMmGNC0Y0M63j5k8x2dF8Cqnc,39952
58
61
  ibm_watsonx_orchestrate/cli/commands/server/types.py,sha256=UCrgGErbSVBnOzesfjrIii4tTCuVfWemYz5AKGZX0oA,4213
59
62
  ibm_watsonx_orchestrate/cli/commands/settings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
63
  ibm_watsonx_orchestrate/cli/commands/settings/settings_command.py,sha256=CzXRkd-97jXyS6LtaaNtMah-aZu0919dYl-mDwzGThc,344
@@ -68,14 +71,14 @@ ibm_watsonx_orchestrate/cli/commands/tools/tools_command.py,sha256=Cuo1Zvlfsymoj
68
71
  ibm_watsonx_orchestrate/cli/commands/tools/tools_controller.py,sha256=uL0WHi0YD7NIYSLOui-CymVHj-h9Y0i3PxS7T2SXSvo,40408
69
72
  ibm_watsonx_orchestrate/cli/commands/tools/types.py,sha256=_md0GEa_cTH17NO_moWDY_LNdFvyEFQ1UVB9_FltYiA,173
70
73
  ibm_watsonx_orchestrate/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
- ibm_watsonx_orchestrate/client/base_api_client.py,sha256=NklphjtCpSFroBocOp4OiklC0iIF0JzXJjtJhUd8gZ8,4752
74
+ ibm_watsonx_orchestrate/client/base_api_client.py,sha256=cSbQb7-K9KoMeFLEIiYGho4cQqf8TcPyYklju9X4cC4,5214
72
75
  ibm_watsonx_orchestrate/client/base_service_instance.py,sha256=sM_r7bln9BpgEOhaJMdFI9-je3T7GLQxLduk-in0oRY,235
73
76
  ibm_watsonx_orchestrate/client/client.py,sha256=pgYeXHe4_Makrw0gTyM343DQdrZZB8cjitFHKcbdzuc,2432
74
77
  ibm_watsonx_orchestrate/client/client_errors.py,sha256=72MKCNZbKoo2QXyY0RicLhP3r0ALRjgOEbHOHNSyOYI,11712
75
78
  ibm_watsonx_orchestrate/client/credentials.py,sha256=gDVeeQZDdbbjJiO1EI61yx2oRgTQctxA2ZesSDHI4DA,3786
76
79
  ibm_watsonx_orchestrate/client/local_service_instance.py,sha256=dt7vfLnjgt7mT8wSq8SJZndNTwsPzhb0XDhcnPUPFpU,3524
77
80
  ibm_watsonx_orchestrate/client/service_instance.py,sha256=fp3Lc4yQf4zTkxVS5WnIAkrHT0xG_a5i44qcLeQkaa4,6600
78
- ibm_watsonx_orchestrate/client/utils.py,sha256=86UH5H54uTJA2kFb4dXrnGfs7hFQZ3h21ElwngZpT24,4745
81
+ ibm_watsonx_orchestrate/client/utils.py,sha256=xf52qHluV-fKiKY29IeIN0xWlBCFbdUF19XCnN6HxQA,5666
79
82
  ibm_watsonx_orchestrate/client/agents/agent_client.py,sha256=v1ZqXKj3p5JeJyOLpV84UUI2LY8XPjW1ejo5yzkeiMQ,4708
80
83
  ibm_watsonx_orchestrate/client/agents/assistant_agent_client.py,sha256=1JQN0E4T_uz5V0LM-LD1ahNu2KCeFBjXAr8WCiP9mkE,1745
81
84
  ibm_watsonx_orchestrate/client/agents/external_agent_client.py,sha256=iQ44XBdC4rYfS-zFn4St1xC5y5gf5SNqKHzMNQcFDZc,1808
@@ -85,6 +88,7 @@ ibm_watsonx_orchestrate/client/analytics/llm/analytics_llm_client.py,sha256=0YS_
85
88
  ibm_watsonx_orchestrate/client/connections/__init__.py,sha256=J7TOyVg38h71AlaJjlFs5fOuAXTceHvELtOJ9oz4Mvg,207
86
89
  ibm_watsonx_orchestrate/client/connections/connections_client.py,sha256=B6LQPwoFHg_CIXHEJBjVu6fXnRj_xVsLGsC-DhmdfSQ,8478
87
90
  ibm_watsonx_orchestrate/client/connections/utils.py,sha256=f6HsiDI6cycOqfYN6P4uZ3SQds83xlh83zTUioZPeYk,2618
91
+ ibm_watsonx_orchestrate/client/copilot/cpe/copilot_cpe_client.py,sha256=ZXm0o-LDcmSoMw2o4AaCwRDLT0GuffmAidsbHwW856M,1878
88
92
  ibm_watsonx_orchestrate/client/knowledge_bases/knowledge_base_client.py,sha256=YjC16dcL_l0jd-6yZ6uH8anlL4yaIv9f-7Y_urPuXWM,2201
89
93
  ibm_watsonx_orchestrate/client/model_policies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
90
94
  ibm_watsonx_orchestrate/client/model_policies/model_policies_client.py,sha256=Ddjraesv1MRPhZebB0PdBL0zgdsoWmnYpWTUci_6XFI,2258
@@ -93,8 +97,8 @@ ibm_watsonx_orchestrate/client/models/models_client.py,sha256=ZvP3iPgUFw_SXp41kJ
93
97
  ibm_watsonx_orchestrate/client/toolkit/toolkit_client.py,sha256=TLFNS39EeBD_t4Y-rX9sGp4sWBDr--mE5qVtHq8Q2hk,3121
94
98
  ibm_watsonx_orchestrate/client/tools/tempus_client.py,sha256=24fKDZUOVHBW-Vj4mubnpnUmab5LgGn8u5hOVyJaozI,1804
95
99
  ibm_watsonx_orchestrate/client/tools/tool_client.py,sha256=d3i3alVwa0TCN72w9sWOrM20GCbNmnpTnqEOJVbBIFM,1994
96
- ibm_watsonx_orchestrate/docker/compose-lite.yml,sha256=nj8KI8zimCITXCKc7HmsXpyywtyHU7fGbQQ-8ZDhw-c,38869
97
- ibm_watsonx_orchestrate/docker/default.env,sha256=mumkO_rbhOI8K4p8Wt5uQnRHo-u9EIF7VHQyThO1GWA,5761
100
+ ibm_watsonx_orchestrate/docker/compose-lite.yml,sha256=KG2k-HsRBpxlhlEMTY9dUecSpdkzIPf__Kcm1AeJxOk,39168
101
+ ibm_watsonx_orchestrate/docker/default.env,sha256=jyaZtxq7G6oPfmSl74DRmnEImkmwXaIFKmud2QVt5bQ,5795
98
102
  ibm_watsonx_orchestrate/docker/proxy-config-single.yaml,sha256=WEbK4ENFuTCYhzRu_QblWp1_GMARgZnx5vReQafkIG8,308
99
103
  ibm_watsonx_orchestrate/docker/start-up.sh,sha256=LTtwHp0AidVgjohis2LXGvZnkFQStOiUAxgGABOyeUI,1811
100
104
  ibm_watsonx_orchestrate/docker/sdk/ibm_watsonx_orchestrate-0.6.0-py3-none-any.whl,sha256=Hi3-owh5OM0Jz2ihX9nLoojnr7Ky1TV-GelyqLcewLE,2047417
@@ -118,8 +122,8 @@ ibm_watsonx_orchestrate/utils/utils.py,sha256=U7z_2iASoFiZ2zM0a_2Mc2Y-P5oOT7hOwu
118
122
  ibm_watsonx_orchestrate/utils/logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
119
123
  ibm_watsonx_orchestrate/utils/logging/logger.py,sha256=FzeGnidXAjC7yHrvIaj4KZPeaBBSCniZFlwgr5yV3oA,1037
120
124
  ibm_watsonx_orchestrate/utils/logging/logging.yaml,sha256=9_TKfuFr1barnOKP0fZT5D6MhddiwsXVTFjtRbcOO5w,314
121
- ibm_watsonx_orchestrate-1.7.0b1.dist-info/METADATA,sha256=wA2E8JONRenc9NFy4Q3h6ZM_NoRYP8p1txL8BqQwUn4,1431
122
- ibm_watsonx_orchestrate-1.7.0b1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
123
- ibm_watsonx_orchestrate-1.7.0b1.dist-info/entry_points.txt,sha256=SfIT02-Jen5e99OcLhzbcM9Bdyf8SGVOCtnSplgZdQI,69
124
- ibm_watsonx_orchestrate-1.7.0b1.dist-info/licenses/LICENSE,sha256=Shgxx7hTdCOkiVRmfGgp_1ISISrwQD7m2f0y8Hsapl4,1083
125
- ibm_watsonx_orchestrate-1.7.0b1.dist-info/RECORD,,
125
+ ibm_watsonx_orchestrate-1.8.0b0.dist-info/METADATA,sha256=MlvtXVevJQdRFHTTwAFAXw0TFTI4ZP8E2tyWQobPvuI,1431
126
+ ibm_watsonx_orchestrate-1.8.0b0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
127
+ ibm_watsonx_orchestrate-1.8.0b0.dist-info/entry_points.txt,sha256=SfIT02-Jen5e99OcLhzbcM9Bdyf8SGVOCtnSplgZdQI,69
128
+ ibm_watsonx_orchestrate-1.8.0b0.dist-info/licenses/LICENSE,sha256=Shgxx7hTdCOkiVRmfGgp_1ISISrwQD7m2f0y8Hsapl4,1083
129
+ ibm_watsonx_orchestrate-1.8.0b0.dist-info/RECORD,,