ibm-watsonx-orchestrate 1.1.0__tar.gz → 1.2.0__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.1.0 → ibm_watsonx_orchestrate-1.2.0}/PKG-INFO +1 -1
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/__init__.py +1 -1
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/tools/types.py +18 -5
- ibm_watsonx_orchestrate-1.2.0/src/ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_command.py +71 -0
- ibm_watsonx_orchestrate-1.2.0/src/ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_controller.py +212 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/tools/tools_controller.py +37 -8
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/main.py +4 -2
- ibm_watsonx_orchestrate-1.2.0/src/ibm_watsonx_orchestrate/client/toolkit/toolkit_client.py +81 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/docker/compose-lite.yml +1 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/docker/default.env +7 -7
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/.gitignore +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/LICENSE +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/pyproject.toml +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/agents/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/agents/agent.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/agents/assistant_agent.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/agents/external_agent.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/agents/types.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/connections/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/connections/connections.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/connections/types.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/knowledge_bases/knowledge_base.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/knowledge_bases/knowledge_base_requests.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/knowledge_bases/types.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/tools/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/tools/base_tool.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/tools/openapi_tool.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/tools/python_tool.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/utils/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/agent_builder/utils/pydantic_utils.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/agents/agents_command.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/agents/agents_controller.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/channels/channels_command.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/channels/channels_controller.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/channels/types.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_command.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_controller.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/chat/chat_command.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/connections/connections_command.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/connections/connections_controller.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/environment/environment_command.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/environment/environment_controller.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/environment/types.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_command.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_controller.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/login/login_command.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/models/models_command.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/server/server_command.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/settings/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/settings/observability/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/settings/observability/langfuse/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/settings/observability/langfuse/langfuse_command.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/settings/observability/observability_command.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/settings/settings_command.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/tools/tools_command.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/commands/tools/types.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/cli/config.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/agents/agent_client.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/agents/assistant_agent_client.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/agents/external_agent_client.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/analytics/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/analytics/llm/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/analytics/llm/analytics_llm_client.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/base_api_client.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/base_service_instance.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/client.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/client_errors.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/connections/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/connections/connections_client.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/connections/utils.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/credentials.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/knowledge_bases/knowledge_base_client.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/local_service_instance.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/service_instance.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/tools/tool_client.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/client/utils.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/docker/sdk/ibm_watsonx_orchestrate-0.6.0-py3-none-any.whl +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/docker/sdk/ibm_watsonx_orchestrate-0.6.0.tar.gz +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/docker/start-up.sh +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/docker/tempus/common-config.yaml +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/run/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/run/connections.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/utils/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/utils/logging/__init__.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/utils/logging/logger.py +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/utils/logging/logging.yaml +0 -0
- {ibm_watsonx_orchestrate-1.1.0 → ibm_watsonx_orchestrate-1.2.0}/src/ibm_watsonx_orchestrate/utils/utils.py +0 -0
@@ -1,5 +1,5 @@
|
|
1
1
|
from enum import Enum
|
2
|
-
from typing import List, Any, Dict, Literal, Optional
|
2
|
+
from typing import List, Any, Dict, Literal, Optional, Union
|
3
3
|
|
4
4
|
from pydantic import BaseModel, model_validator, ConfigDict, Field, AliasChoices
|
5
5
|
|
@@ -14,7 +14,7 @@ class ToolPermission(str, Enum):
|
|
14
14
|
class JsonSchemaObject(BaseModel):
|
15
15
|
model_config = ConfigDict(extra='allow')
|
16
16
|
|
17
|
-
type: Optional[Literal['object', 'string', 'number', 'integer', 'boolean', 'array', 'null']] = None
|
17
|
+
type: Optional[Union[Literal['object', 'string', 'number', 'integer', 'boolean', 'array', 'null'], List[Literal['object', 'string', 'number', 'integer', 'boolean', 'array', 'null']]]] = None
|
18
18
|
title: str | None = None
|
19
19
|
description: str | None = None
|
20
20
|
properties: Optional[Dict[str, 'JsonSchemaObject']] = None
|
@@ -34,13 +34,19 @@ class JsonSchemaObject(BaseModel):
|
|
34
34
|
aliasName: str | None = None
|
35
35
|
"Runtime feature where the sdk can provide the original name of a field before prefixing"
|
36
36
|
|
37
|
+
@model_validator(mode='after')
|
38
|
+
def normalize_type_field(self) -> 'JsonSchemaObject':
|
39
|
+
if isinstance(self.type, list):
|
40
|
+
self.type = self.type[0]
|
41
|
+
return self
|
42
|
+
|
37
43
|
|
38
44
|
class ToolRequestBody(BaseModel):
|
39
45
|
model_config = ConfigDict(extra='allow')
|
40
46
|
|
41
47
|
type: Literal['object']
|
42
48
|
properties: Dict[str, JsonSchemaObject]
|
43
|
-
required: List[str]
|
49
|
+
required: Optional[List[str]] = None
|
44
50
|
|
45
51
|
|
46
52
|
class ToolResponseBody(BaseModel):
|
@@ -52,7 +58,7 @@ class ToolResponseBody(BaseModel):
|
|
52
58
|
items: JsonSchemaObject = None
|
53
59
|
uniqueItems: bool = None
|
54
60
|
anyOf: List['JsonSchemaObject'] = None
|
55
|
-
required: List[str] = None
|
61
|
+
required: Optional[List[str]] = None
|
56
62
|
|
57
63
|
class OpenApiSecurityScheme(BaseModel):
|
58
64
|
type: Literal['apiKey', 'http', 'oauth2', 'openIdConnect']
|
@@ -128,6 +134,10 @@ class SkillToolBinding(BaseModel):
|
|
128
134
|
class ClientSideToolBinding(BaseModel):
|
129
135
|
pass
|
130
136
|
|
137
|
+
class McpToolBinding(BaseModel):
|
138
|
+
server_url: Optional[str] = None
|
139
|
+
source: str
|
140
|
+
connections: Dict[str, str]
|
131
141
|
|
132
142
|
class ToolBinding(BaseModel):
|
133
143
|
openapi: OpenApiToolBinding = None
|
@@ -135,6 +145,7 @@ class ToolBinding(BaseModel):
|
|
135
145
|
wxflows: WxFlowsToolBinding = None
|
136
146
|
skill: SkillToolBinding = None
|
137
147
|
client_side: ClientSideToolBinding = None
|
148
|
+
mcp: McpToolBinding = None
|
138
149
|
|
139
150
|
@model_validator(mode='after')
|
140
151
|
def validate_binding_type(self) -> 'ToolBinding':
|
@@ -143,7 +154,8 @@ class ToolBinding(BaseModel):
|
|
143
154
|
self.python is not None,
|
144
155
|
self.wxflows is not None,
|
145
156
|
self.skill is not None,
|
146
|
-
self.client_side is not None
|
157
|
+
self.client_side is not None,
|
158
|
+
self.mcp is not None
|
147
159
|
]
|
148
160
|
if sum(bindings) == 0:
|
149
161
|
raise ValueError("One binding must be set")
|
@@ -159,4 +171,5 @@ class ToolSpec(BaseModel):
|
|
159
171
|
input_schema: ToolRequestBody = None
|
160
172
|
output_schema: ToolResponseBody = None
|
161
173
|
binding: ToolBinding = None
|
174
|
+
toolkit_id: str | None = None
|
162
175
|
|
ibm_watsonx_orchestrate-1.2.0/src/ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_command.py
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
import typer
|
2
|
+
from typing import List
|
3
|
+
from typing_extensions import Annotated, Optional
|
4
|
+
from ibm_watsonx_orchestrate.cli.commands.toolkit.toolkit_controller import ToolkitController, ToolkitKind
|
5
|
+
|
6
|
+
toolkits_app = typer.Typer(no_args_is_help=True)
|
7
|
+
|
8
|
+
@toolkits_app.command(name="import")
|
9
|
+
def import_toolkit(
|
10
|
+
kind: Annotated[
|
11
|
+
ToolkitKind,
|
12
|
+
typer.Option("--kind", "-k", help="Kind of toolkit, currently only MCP is supported"),
|
13
|
+
],
|
14
|
+
name: Annotated[
|
15
|
+
str,
|
16
|
+
typer.Option("--name", "-n", help="Name of the toolkit"),
|
17
|
+
],
|
18
|
+
description: Annotated[
|
19
|
+
str,
|
20
|
+
typer.Option("--description", help="Description of the toolkit"),
|
21
|
+
],
|
22
|
+
package_root: Annotated[
|
23
|
+
str,
|
24
|
+
typer.Option("--package-root", "-p", help="Root directory of the MCP server package"),
|
25
|
+
],
|
26
|
+
command: Annotated[
|
27
|
+
str,
|
28
|
+
typer.Option(
|
29
|
+
"--command",
|
30
|
+
help="Command to start the MCP server. Can be a string (e.g. 'node dist/index.js --transport stdio') "
|
31
|
+
"or a JSON-style list of arguments (e.g. '[\"node\", \"dist/index.js\", \"--transport\", \"stdio\"]'). "
|
32
|
+
"The first argument will be used as the executable, the rest as its arguments."
|
33
|
+
),
|
34
|
+
],
|
35
|
+
tools: Annotated[
|
36
|
+
Optional[str],
|
37
|
+
typer.Option("--tools", "-t", help="Comma-separated list of tools to import. Or you can use `*` to use all tools"),
|
38
|
+
] = None,
|
39
|
+
app_id: Annotated[
|
40
|
+
List[str],
|
41
|
+
typer.Option(
|
42
|
+
"--app-id", "-a",
|
43
|
+
help='The app id of the connection to associate with this tool. A application connection represents the server authentication credentials needed to connect to this tool. Only type key_value is currently supported for MCP.'
|
44
|
+
)
|
45
|
+
] = None
|
46
|
+
):
|
47
|
+
if tools == "*":
|
48
|
+
tool_list = ["*"] # Wildcard to use all tools
|
49
|
+
elif tools:
|
50
|
+
tool_list = [tool.strip() for tool in tools.split(",")]
|
51
|
+
else:
|
52
|
+
tool_list = None
|
53
|
+
|
54
|
+
toolkit_controller = ToolkitController(
|
55
|
+
kind=kind,
|
56
|
+
name=name,
|
57
|
+
description=description,
|
58
|
+
package_root=package_root,
|
59
|
+
command=command,
|
60
|
+
)
|
61
|
+
toolkit_controller.import_toolkit(tools=tool_list, app_id=app_id)
|
62
|
+
|
63
|
+
@toolkits_app.command(name="remove")
|
64
|
+
def remove_toolkit(
|
65
|
+
name: Annotated[
|
66
|
+
str,
|
67
|
+
typer.Option("--name", "-n", help="Name of the toolkit you wish to remove"),
|
68
|
+
],
|
69
|
+
):
|
70
|
+
toolkit_controller = ToolkitController()
|
71
|
+
toolkit_controller.remove_toolkit(name=name)
|
ibm_watsonx_orchestrate-1.2.0/src/ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_controller.py
ADDED
@@ -0,0 +1,212 @@
|
|
1
|
+
import os
|
2
|
+
import zipfile
|
3
|
+
import tempfile
|
4
|
+
from typing import List, Optional
|
5
|
+
from enum import Enum
|
6
|
+
import logging
|
7
|
+
import sys
|
8
|
+
import re
|
9
|
+
import requests
|
10
|
+
from ibm_watsonx_orchestrate.client.toolkit.toolkit_client import ToolKitClient
|
11
|
+
from ibm_watsonx_orchestrate.client.utils import instantiate_client
|
12
|
+
from ibm_watsonx_orchestrate.utils.utils import sanatize_app_id
|
13
|
+
from ibm_watsonx_orchestrate.client.connections import get_connections_client
|
14
|
+
import typer
|
15
|
+
import json
|
16
|
+
from rich.console import Console
|
17
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn
|
18
|
+
from ibm_watsonx_orchestrate.client.utils import is_local_dev
|
19
|
+
|
20
|
+
logger = logging.getLogger(__name__)
|
21
|
+
|
22
|
+
class ToolkitKind(str, Enum):
|
23
|
+
MCP = "mcp"
|
24
|
+
|
25
|
+
def get_connection_id(app_id: str) -> str:
|
26
|
+
connections_client = get_connections_client()
|
27
|
+
existing_draft_configuration = connections_client.get_config(app_id=app_id, env='draft')
|
28
|
+
existing_live_configuration = connections_client.get_config(app_id=app_id, env='live')
|
29
|
+
|
30
|
+
for config in [existing_draft_configuration, existing_live_configuration]:
|
31
|
+
if config and config.security_scheme != 'key_value_creds':
|
32
|
+
logger.error("Only key_value credentials are currently supported")
|
33
|
+
exit(1)
|
34
|
+
connection_id = None
|
35
|
+
if app_id is not None:
|
36
|
+
connection = connections_client.get(app_id=app_id)
|
37
|
+
if not connection:
|
38
|
+
logger.error(f"No connection exists with the app-id '{app_id}'")
|
39
|
+
exit(1)
|
40
|
+
connection_id = connection.connection_id
|
41
|
+
return connection_id
|
42
|
+
|
43
|
+
def validate_params(kind: str):
|
44
|
+
if kind != ToolkitKind.MCP:
|
45
|
+
raise ValueError(f"Unsupported toolkit kind: {kind}")
|
46
|
+
|
47
|
+
|
48
|
+
class ToolkitController:
|
49
|
+
def __init__(
|
50
|
+
self,
|
51
|
+
kind: ToolkitKind = None,
|
52
|
+
name: str = None,
|
53
|
+
description: str = None,
|
54
|
+
package_root: str = None,
|
55
|
+
command: str = None,
|
56
|
+
):
|
57
|
+
self.kind = kind
|
58
|
+
self.name = name
|
59
|
+
self.description = description
|
60
|
+
self.package_root = package_root
|
61
|
+
self.command = command
|
62
|
+
self.client = None
|
63
|
+
|
64
|
+
def get_client(self) -> ToolKitClient:
|
65
|
+
if not self.client:
|
66
|
+
self.client = instantiate_client(ToolKitClient)
|
67
|
+
return self.client
|
68
|
+
|
69
|
+
def import_toolkit(self, tools: Optional[List[str]] = None, app_id: Optional[List[str]] = None):
|
70
|
+
if not is_local_dev():
|
71
|
+
logger.error("This functionality is only available for Local Environments")
|
72
|
+
sys.exit(1)
|
73
|
+
|
74
|
+
if app_id and isinstance(app_id, str):
|
75
|
+
app_id = [app_id]
|
76
|
+
elif not app_id:
|
77
|
+
app_id = []
|
78
|
+
|
79
|
+
validate_params(kind=self.kind)
|
80
|
+
|
81
|
+
remapped_connections = self._remap_connections(app_id)
|
82
|
+
|
83
|
+
client = self.get_client()
|
84
|
+
draft_toolkits = client.get_draft_by_name(toolkit_name=self.name)
|
85
|
+
if len(draft_toolkits) > 0:
|
86
|
+
logger.error(f"Existing toolkit found with name '{self.name}'. Failed to create toolkit.")
|
87
|
+
sys.exit(1)
|
88
|
+
|
89
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
90
|
+
# Handle zip file or directory
|
91
|
+
if self.package_root.endswith(".zip") and os.path.isfile(self.package_root):
|
92
|
+
zip_file_path = self.package_root
|
93
|
+
else:
|
94
|
+
zip_file_path = os.path.join(tmpdir, os.path.basename(f"{self.package_root.rstrip(os.sep)}.zip"))
|
95
|
+
with zipfile.ZipFile(zip_file_path, "w", zipfile.ZIP_DEFLATED) as mcp_zip_tool_artifacts:
|
96
|
+
self._populate_zip(self.package_root, mcp_zip_tool_artifacts)
|
97
|
+
|
98
|
+
try:
|
99
|
+
command_parts = json.loads(self.command)
|
100
|
+
if not isinstance(command_parts, list):
|
101
|
+
raise ValueError("JSON command must be a list of strings")
|
102
|
+
except (json.JSONDecodeError, ValueError):
|
103
|
+
command_parts = self.command.split()
|
104
|
+
|
105
|
+
command = command_parts[0]
|
106
|
+
args = command_parts[1:]
|
107
|
+
|
108
|
+
console = Console()
|
109
|
+
# List tools if not provided
|
110
|
+
if tools is None:
|
111
|
+
with Progress(
|
112
|
+
SpinnerColumn(spinner_name="dots"),
|
113
|
+
TextColumn("[progress.description]{task.description}"),
|
114
|
+
transient=True,
|
115
|
+
console=console,
|
116
|
+
) as progress:
|
117
|
+
progress.add_task(description="No tools specified, retrieving all tools from provided MCP server", total=None)
|
118
|
+
tools = self.get_client().list_tools(
|
119
|
+
zip_file_path=zip_file_path,
|
120
|
+
command=command,
|
121
|
+
args=args,
|
122
|
+
)
|
123
|
+
# Normalize tools to a list of tool names
|
124
|
+
tools = [
|
125
|
+
tool["name"] if isinstance(tool, dict) and "name" in tool else tool
|
126
|
+
for tool in tools
|
127
|
+
]
|
128
|
+
|
129
|
+
|
130
|
+
logger.info("✅ The following tools will be imported:")
|
131
|
+
for tool in tools:
|
132
|
+
console.print(f" • {tool}")
|
133
|
+
|
134
|
+
|
135
|
+
# Create toolkit metadata
|
136
|
+
payload = {
|
137
|
+
"name": self.name,
|
138
|
+
"description": self.description,
|
139
|
+
"mcp": {
|
140
|
+
"source": "files",
|
141
|
+
"command": command,
|
142
|
+
"args": args,
|
143
|
+
"tools": tools,
|
144
|
+
"connections": remapped_connections,
|
145
|
+
}
|
146
|
+
}
|
147
|
+
toolkit = self.get_client().create_toolkit(payload)
|
148
|
+
toolkit_id = toolkit["id"]
|
149
|
+
|
150
|
+
console = Console()
|
151
|
+
# Upload zip file
|
152
|
+
with Progress(
|
153
|
+
SpinnerColumn(spinner_name="dots"),
|
154
|
+
TextColumn("[progress.description]{task.description}"),
|
155
|
+
transient=True,
|
156
|
+
console=console,
|
157
|
+
) as progress:
|
158
|
+
progress.add_task(description="Uploading toolkit zip file...", total=None)
|
159
|
+
self.get_client().upload(toolkit_id=toolkit_id, zip_file_path=zip_file_path)
|
160
|
+
logger.info(f"Successfully imported tool kit {self.name}")
|
161
|
+
|
162
|
+
def _populate_zip(self, package_root: str, zipfile: zipfile.ZipFile) -> str:
|
163
|
+
for root, _, files in os.walk(package_root):
|
164
|
+
for file in files:
|
165
|
+
full_path = os.path.join(root, file)
|
166
|
+
relative_path = os.path.relpath(full_path, start=package_root)
|
167
|
+
zipfile.write(full_path, arcname=relative_path)
|
168
|
+
return zipfile
|
169
|
+
|
170
|
+
def _remap_connections(self, app_ids: List[str]):
|
171
|
+
app_id_dict = {}
|
172
|
+
for app_id in app_ids:
|
173
|
+
split_pattern = re.compile(r"(?<!\\)=")
|
174
|
+
split_id = re.split(split_pattern, app_id)
|
175
|
+
split_id = [x.replace("\\=", "=") for x in split_id]
|
176
|
+
if len(split_id) == 2:
|
177
|
+
runtime_id, local_id = split_id
|
178
|
+
elif len(split_id) == 1:
|
179
|
+
runtime_id = split_id[0]
|
180
|
+
local_id = split_id[0]
|
181
|
+
else:
|
182
|
+
raise typer.BadParameter(f"The provided --app-id '{app_id}' is not valid. This is likely caused by having mutliple equal signs, please use '\\=' to represent a literal '=' character")
|
183
|
+
|
184
|
+
if not len(runtime_id.strip()) or not len(local_id.strip()):
|
185
|
+
raise typer.BadParameter(f"The provided --app-id '{app_id}' is not valid. --app-id cannot be empty or whitespace")
|
186
|
+
|
187
|
+
runtime_id = sanatize_app_id(runtime_id)
|
188
|
+
app_id_dict[runtime_id] = get_connection_id(local_id)
|
189
|
+
|
190
|
+
return app_id_dict
|
191
|
+
|
192
|
+
|
193
|
+
def remove_toolkit(self, name: str):
|
194
|
+
if not is_local_dev():
|
195
|
+
logger.error("This functionality is only available for Local Environments")
|
196
|
+
sys.exit(1)
|
197
|
+
try:
|
198
|
+
client = self.get_client()
|
199
|
+
draft_toolkits = client.get_draft_by_name(toolkit_name=name)
|
200
|
+
if len(draft_toolkits) > 1:
|
201
|
+
logger.error(f"Multiple existing toolkits found with name '{name}'. Failed to remove toolkit")
|
202
|
+
sys.exit(1)
|
203
|
+
if len(draft_toolkits) > 0:
|
204
|
+
draft_toolkit = draft_toolkits[0]
|
205
|
+
toolkit_id = draft_toolkit.get("id")
|
206
|
+
self.get_client().delete(toolkit_id=toolkit_id)
|
207
|
+
logger.info(f"Successfully removed tool {name}")
|
208
|
+
else:
|
209
|
+
logger.warning(f"No toolkit named '{name}' found")
|
210
|
+
except requests.HTTPError as e:
|
211
|
+
logger.error(e.response.text)
|
212
|
+
exit(1)
|
@@ -27,8 +27,9 @@ from ibm_watsonx_orchestrate.cli.config import Config, CONTEXT_SECTION_HEADER, C
|
|
27
27
|
DEFAULT_CONFIG_FILE_CONTENT
|
28
28
|
from ibm_watsonx_orchestrate.agent_builder.connections import ConnectionSecurityScheme, ExpectedCredentials
|
29
29
|
from ibm_watsonx_orchestrate.client.tools.tool_client import ToolClient
|
30
|
+
from ibm_watsonx_orchestrate.client.toolkit.toolkit_client import ToolKitClient
|
30
31
|
from ibm_watsonx_orchestrate.client.connections import get_connections_client, get_connection_type
|
31
|
-
from ibm_watsonx_orchestrate.client.utils import instantiate_client
|
32
|
+
from ibm_watsonx_orchestrate.client.utils import instantiate_client, is_local_dev
|
32
33
|
from ibm_watsonx_orchestrate.utils.utils import sanatize_app_id
|
33
34
|
|
34
35
|
from ibm_watsonx_orchestrate import __version__
|
@@ -41,6 +42,7 @@ __supported_characters_pattern = re.compile("^(\\w|_)+$")
|
|
41
42
|
class ToolKind(str, Enum):
|
42
43
|
openapi = "openapi"
|
43
44
|
python = "python"
|
45
|
+
mcp = "mcp"
|
44
46
|
# skill = "skill"
|
45
47
|
|
46
48
|
def validate_app_ids(kind: ToolKind, **args) -> None:
|
@@ -368,21 +370,24 @@ class ToolsController:
|
|
368
370
|
response = self.get_client().get()
|
369
371
|
tool_specs = [ToolSpec.model_validate(tool) for tool in response]
|
370
372
|
tools = [BaseTool(spec=spec) for spec in tool_specs]
|
371
|
-
|
372
373
|
|
373
374
|
if verbose:
|
374
375
|
tools_list = []
|
375
376
|
for tool in tools:
|
376
|
-
|
377
377
|
tools_list.append(json.loads(tool.dumps_spec()))
|
378
378
|
|
379
379
|
rich.print(JSON(json.dumps(tools_list, indent=4)))
|
380
380
|
else:
|
381
381
|
table = rich.table.Table(show_header=True, header_style="bold white", show_lines=True)
|
382
|
-
columns = ["Name", "Description", "Permission", "Type", "App ID"]
|
382
|
+
columns = ["Name", "Description", "Permission", "Type", "Toolkit", "App ID"]
|
383
383
|
for column in columns:
|
384
384
|
table.add_column(column)
|
385
|
-
|
385
|
+
|
386
|
+
connections_client = get_connections_client()
|
387
|
+
connections = connections_client.list()
|
388
|
+
|
389
|
+
connections_dict = {conn.connection_id: conn for conn in connections}
|
390
|
+
|
386
391
|
for tool in tools:
|
387
392
|
tool_binding = tool.__tool_spec__.binding
|
388
393
|
|
@@ -394,25 +399,49 @@ class ToolsController:
|
|
394
399
|
elif tool_binding.python is not None and hasattr(tool_binding.python, "connections") and tool_binding.python.connections is not None:
|
395
400
|
for conn in tool_binding.python.connections:
|
396
401
|
connection_ids.append(tool_binding.python.connections[conn])
|
397
|
-
|
398
|
-
|
402
|
+
elif tool_binding.mcp is not None and hasattr(tool_binding.mcp, "connections"):
|
403
|
+
for conn in tool_binding.mcp.connections:
|
404
|
+
connection_ids.append(tool_binding.mcp.connections[conn])
|
405
|
+
|
406
|
+
|
399
407
|
app_ids = []
|
400
408
|
for connection_id in connection_ids:
|
401
|
-
|
409
|
+
connection = connections_dict.get(connection_id)
|
410
|
+
if connection:
|
411
|
+
app_id = str(connection.app_id or connection.connection_id)
|
412
|
+
elif connection_id:
|
413
|
+
app_id = str(connection_id)
|
414
|
+
else:
|
415
|
+
app_id = ""
|
402
416
|
app_ids.append(app_id)
|
403
417
|
|
404
418
|
if tool_binding.python is not None:
|
405
419
|
tool_type=ToolKind.python
|
406
420
|
elif tool_binding.openapi is not None:
|
407
421
|
tool_type=ToolKind.openapi
|
422
|
+
elif tool_binding.mcp is not None:
|
423
|
+
tool_type=ToolKind.mcp
|
408
424
|
else:
|
409
425
|
tool_type="Unknown"
|
410
426
|
|
427
|
+
toolkit_name = ""
|
428
|
+
|
429
|
+
if is_local_dev():
|
430
|
+
toolkit_client = instantiate_client(ToolKitClient)
|
431
|
+
if tool.__tool_spec__.toolkit_id:
|
432
|
+
toolkit = toolkit_client.get_draft_by_id(tool.__tool_spec__.toolkit_id)
|
433
|
+
if isinstance(toolkit, dict) and "name" in toolkit:
|
434
|
+
toolkit_name = toolkit["name"]
|
435
|
+
elif toolkit:
|
436
|
+
toolkit_name = str(toolkit)
|
437
|
+
|
438
|
+
|
411
439
|
table.add_row(
|
412
440
|
tool.__tool_spec__.name,
|
413
441
|
tool.__tool_spec__.description,
|
414
442
|
tool.__tool_spec__.permission,
|
415
443
|
tool_type,
|
444
|
+
toolkit_name,
|
416
445
|
", ".join(app_ids),
|
417
446
|
)
|
418
447
|
|
@@ -11,6 +11,7 @@ from ibm_watsonx_orchestrate.cli.commands.models.models_command import models_ap
|
|
11
11
|
from ibm_watsonx_orchestrate.cli.commands.environment.environment_command import environment_app
|
12
12
|
from ibm_watsonx_orchestrate.cli.commands.channels.channels_command import channel_app
|
13
13
|
from ibm_watsonx_orchestrate.cli.commands.knowledge_bases.knowledge_bases_command import knowledge_bases_app
|
14
|
+
from ibm_watsonx_orchestrate.cli.commands.toolkit.toolkit_command import toolkits_app
|
14
15
|
|
15
16
|
app = typer.Typer(
|
16
17
|
no_args_is_help=True,
|
@@ -20,10 +21,11 @@ app.add_typer(login_app)
|
|
20
21
|
app.add_typer(environment_app, name="env", help='Add, remove, or select the activate env other commands will interact with (either your local server or a production instance)')
|
21
22
|
app.add_typer(agents_app, name="agents", help='Interact with the agents in your active env')
|
22
23
|
app.add_typer(tools_app, name="tools", help='Interact with the tools in your active env')
|
24
|
+
app.add_typer(toolkits_app, name="toolkits", help="Interact with the toolkits in your active env")
|
23
25
|
app.add_typer(knowledge_bases_app, name="knowledge-bases", help="Upload knowledge your agents can search through to your active env")
|
24
26
|
app.add_typer(connections_app, name="connections", help='Interact with the agents in your active env')
|
25
|
-
app.add_typer(server_app, name="server", help='Manipulate your local Orchestrate Developer Edition server [requires
|
26
|
-
app.add_typer(chat_app, name="chat", help='Launch the chat ui for your local Developer Edition server [requires
|
27
|
+
app.add_typer(server_app, name="server", help='Manipulate your local Orchestrate Developer Edition server [requires entitlement]')
|
28
|
+
app.add_typer(chat_app, name="chat", help='Launch the chat ui for your local Developer Edition server [requires entitlement]')
|
27
29
|
app.add_typer(models_app, name="models", help='List the available large language models (llms) that can be used in your agent definitions')
|
28
30
|
app.add_typer(channel_app, name="channels", help="Configure channels where your agent can exist on (such as embedded webchat)")
|
29
31
|
app.add_typer(settings_app, name="settings", help='Configure the settings for your active env')
|
@@ -0,0 +1,81 @@
|
|
1
|
+
from ibm_watsonx_orchestrate.client.base_api_client import BaseAPIClient, ClientAPIException
|
2
|
+
from typing_extensions import List
|
3
|
+
import os
|
4
|
+
import json
|
5
|
+
|
6
|
+
class ToolKitClient(BaseAPIClient):
|
7
|
+
# POST /toolkits/prepare/list-tools
|
8
|
+
def list_tools(self, zip_file_path: str, command: str, args: List[str]) -> List[str]:
|
9
|
+
"""
|
10
|
+
List the available tools inside the MCP server
|
11
|
+
"""
|
12
|
+
|
13
|
+
filename = os.path.basename(zip_file_path)
|
14
|
+
|
15
|
+
list_toolkit_obj = {
|
16
|
+
"source": "files",
|
17
|
+
"command": command,
|
18
|
+
"args": args,
|
19
|
+
}
|
20
|
+
|
21
|
+
with open(zip_file_path, "rb") as f:
|
22
|
+
files = {
|
23
|
+
"list_toolkit_obj": (None, json.dumps(list_toolkit_obj), "application/json"),
|
24
|
+
"file": (filename, f, "application/zip"),
|
25
|
+
}
|
26
|
+
|
27
|
+
response = self._post("/orchestrate/toolkits/prepare/list-tools", files=files)
|
28
|
+
|
29
|
+
return response.get("tools", [])
|
30
|
+
|
31
|
+
|
32
|
+
# POST /api/v1/orchestrate/toolkits
|
33
|
+
def create_toolkit(self, payload) -> dict:
|
34
|
+
"""
|
35
|
+
Creates new toolkit metadata
|
36
|
+
"""
|
37
|
+
try:
|
38
|
+
return self._post("/orchestrate/toolkits", data=payload)
|
39
|
+
except ClientAPIException as e:
|
40
|
+
if e.response.status_code == 400 and "already exists" in e.response.text:
|
41
|
+
raise ClientAPIException(
|
42
|
+
status_code=400,
|
43
|
+
message=f"There is already a Toolkit with the same name that exists for this tenant."
|
44
|
+
)
|
45
|
+
raise(e)
|
46
|
+
|
47
|
+
# POST /toolkits/{toolkit-id}/upload
|
48
|
+
def upload(self, toolkit_id: str, zip_file_path: str) -> dict:
|
49
|
+
"""
|
50
|
+
Upload zip file to the toolkit.
|
51
|
+
"""
|
52
|
+
filename = os.path.basename(zip_file_path)
|
53
|
+
with open(zip_file_path, "rb") as f:
|
54
|
+
files = {
|
55
|
+
"file": (filename, f, "application/zip", {"Expires": "0"})
|
56
|
+
}
|
57
|
+
return self._post(f"/orchestrate/toolkits/{toolkit_id}/upload", files=files)
|
58
|
+
|
59
|
+
# DELETE /toolkits/{toolkit-id}
|
60
|
+
def delete(self, toolkit_id: str) -> dict:
|
61
|
+
return self._delete(f"/orchestrate/toolkits/{toolkit_id}")
|
62
|
+
|
63
|
+
def get_draft_by_name(self, toolkit_name: str) -> List[dict]:
|
64
|
+
return self.get_drafts_by_names([toolkit_name])
|
65
|
+
|
66
|
+
def get_drafts_by_names(self, toolkit_names: List[str]) -> List[dict]:
|
67
|
+
formatted_toolkit_names = [f"names={x}" for x in toolkit_names]
|
68
|
+
return self._get(f"/orchestrate/toolkits?{'&'.join(formatted_toolkit_names)}")
|
69
|
+
|
70
|
+
def get_draft_by_id(self, toolkit_id: str) -> dict:
|
71
|
+
if toolkit_id is None:
|
72
|
+
return ""
|
73
|
+
else:
|
74
|
+
try:
|
75
|
+
toolkit = self._get(f"/orchestrate/toolkits/{toolkit_id}")
|
76
|
+
return toolkit
|
77
|
+
except ClientAPIException as e:
|
78
|
+
if e.response.status_code == 404 and "not found with the given name" in e.response.text:
|
79
|
+
return ""
|
80
|
+
raise(e)
|
81
|
+
|
@@ -49,18 +49,18 @@ EVENT_BROKER_TTL="-1"
|
|
49
49
|
# THE VALUES FOR REGISTRY_URL AND *_REGISTRY ARE NOT SET HERE; THEY ARE EITHER PROVIDED BY THE USER OR DETERMINED AT RUNTIME BASED ON WO_DEVELOPER_EDITION_SOURCE.
|
50
50
|
REGISTRY_URL=
|
51
51
|
|
52
|
-
SERVER_TAG=
|
52
|
+
SERVER_TAG=03-05-2025
|
53
53
|
SERVER_REGISTRY=
|
54
54
|
|
55
|
-
WORKER_TAG=
|
55
|
+
WORKER_TAG=03-05-2025
|
56
56
|
WORKER_REGISTRY=
|
57
57
|
|
58
58
|
DB_REGISTRY=
|
59
59
|
# If you build multiarch set all three of these to the same, we have a pr against main
|
60
60
|
# to not have this separation, but we can merge it later
|
61
|
-
DBTAG=
|
62
|
-
AMDDBTAG=
|
63
|
-
ARM64DBTAG=
|
61
|
+
DBTAG=02-05-2025
|
62
|
+
AMDDBTAG=02-05-2025
|
63
|
+
ARM64DBTAG=02-05-2025
|
64
64
|
|
65
65
|
UI_REGISTRY=
|
66
66
|
UITAG=01-05-2025
|
@@ -68,10 +68,10 @@ UITAG=01-05-2025
|
|
68
68
|
CM_REGISTRY=
|
69
69
|
CM_TAG=30-04-2025
|
70
70
|
|
71
|
-
TRM_TAG=
|
71
|
+
TRM_TAG=02-05-2025
|
72
72
|
TRM_REGISTRY=
|
73
73
|
|
74
|
-
TR_TAG=
|
74
|
+
TR_TAG=02-05-2025
|
75
75
|
TR_REGISTRY=
|
76
76
|
|
77
77
|
BUILDER_REGISTRY=
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|