ibm-watsonx-orchestrate 1.7.0b1__tar.gz → 1.8.0b0__tar.gz
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-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/PKG-INFO +1 -1
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/__init__.py +1 -2
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/agents/types.py +17 -1
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_controller.py +33 -23
- ibm_watsonx_orchestrate-1.8.0b0/src/ibm_watsonx_orchestrate/cli/commands/copilot/copilot_command.py +65 -0
- ibm_watsonx_orchestrate-1.8.0b0/src/ibm_watsonx_orchestrate/cli/commands/copilot/copilot_controller.py +293 -0
- ibm_watsonx_orchestrate-1.8.0b0/src/ibm_watsonx_orchestrate/cli/commands/copilot/copilot_server_controller.py +154 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/server/server_command.py +2 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/main.py +3 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/base_api_client.py +12 -0
- ibm_watsonx_orchestrate-1.8.0b0/src/ibm_watsonx_orchestrate/client/copilot/cpe/copilot_cpe_client.py +66 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/utils.py +48 -9
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/docker/compose-lite.yml +10 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/docker/default.env +6 -3
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/.gitignore +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/LICENSE +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/pyproject.toml +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/agents/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/agents/agent.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/agents/assistant_agent.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/agents/external_agent.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/agents/webchat_customizations/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/agents/webchat_customizations/prompts.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/agents/webchat_customizations/welcome_content.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/connections/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/connections/connections.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/connections/types.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/knowledge_bases/knowledge_base.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/knowledge_bases/knowledge_base_requests.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/knowledge_bases/types.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/model_policies/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/model_policies/types.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/models/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/models/types.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/toolkits/base_toolkit.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/toolkits/types.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/tools/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/tools/base_tool.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/tools/flow_tool.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/tools/openapi_tool.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/tools/python_tool.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/tools/types.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/utils/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/agent_builder/utils/pydantic_utils.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/agents/agents_command.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/agents/agents_controller.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/channels/channels_command.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/channels/channels_controller.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/channels/types.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_command.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/chat/chat_command.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/connections/connections_command.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/connections/connections_controller.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/environment/environment_command.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/environment/environment_controller.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/environment/types.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_command.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_controller.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_command.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_controller.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/login/login_command.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/models/model_provider_mapper.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/models/models_command.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/models/models_controller.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/server/types.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/settings/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/settings/observability/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/settings/observability/langfuse/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/settings/observability/langfuse/langfuse_command.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/settings/observability/observability_command.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/settings/settings_command.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_command.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_controller.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/tools/tools_command.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/tools/tools_controller.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/commands/tools/types.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/config.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/cli/init_helper.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/agents/agent_client.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/agents/assistant_agent_client.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/agents/external_agent_client.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/analytics/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/analytics/llm/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/analytics/llm/analytics_llm_client.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/base_service_instance.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/client.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/client_errors.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/connections/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/connections/connections_client.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/connections/utils.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/credentials.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/knowledge_bases/knowledge_base_client.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/local_service_instance.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/model_policies/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/model_policies/model_policies_client.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/models/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/models/models_client.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/service_instance.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/toolkit/toolkit_client.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/tools/tempus_client.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/client/tools/tool_client.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/docker/proxy-config-single.yaml +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/docker/sdk/ibm_watsonx_orchestrate-0.6.0-py3-none-any.whl +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/docker/sdk/ibm_watsonx_orchestrate-0.6.0.tar.gz +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/docker/start-up.sh +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/docker/tempus/common-config.yaml +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/flow_builder/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/flow_builder/data_map.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/flow_builder/flows/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/flow_builder/flows/constants.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/flow_builder/flows/decorators.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/flow_builder/flows/events.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/flow_builder/flows/flow.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/flow_builder/node.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/flow_builder/types.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/flow_builder/utils.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/run/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/run/connections.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/utils/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/utils/exceptions.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/utils/logging/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/utils/logging/logger.py +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/utils/logging/logging.yaml +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1 → ibm_watsonx_orchestrate-1.8.0b0}/src/ibm_watsonx_orchestrate/utils/utils.py +0 -0
@@ -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-
|
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,
|
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 =
|
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
|
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
|
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
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
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
|
-
|
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
|
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
|
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: {{
|
ibm_watsonx_orchestrate-1.8.0b0/src/ibm_watsonx_orchestrate/cli/commands/copilot/copilot_command.py
ADDED
@@ -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()
|