arcade-core 4.0.0__py3-none-any.whl → 4.2.0__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.
- arcade_core/auth.py +9 -0
- arcade_core/converters/__init__.py +34 -0
- arcade_core/converters/anthropic.py +194 -0
- arcade_core/converters/openai.py +2 -1
- arcade_core/converters/utils.py +54 -0
- {arcade_core-4.0.0.dist-info → arcade_core-4.2.0.dist-info}/METADATA +1 -1
- {arcade_core-4.0.0.dist-info → arcade_core-4.2.0.dist-info}/RECORD +8 -5
- {arcade_core-4.0.0.dist-info → arcade_core-4.2.0.dist-info}/WHEEL +0 -0
arcade_core/auth.py
CHANGED
|
@@ -150,6 +150,15 @@ class Notion(OAuth2):
|
|
|
150
150
|
super().__init__(id=id, scopes=scopes)
|
|
151
151
|
|
|
152
152
|
|
|
153
|
+
class PagerDuty(OAuth2):
|
|
154
|
+
"""Marks a tool as requiring PagerDuty authorization."""
|
|
155
|
+
|
|
156
|
+
provider_id: str = "pagerduty"
|
|
157
|
+
|
|
158
|
+
def __init__(self, *, id: Optional[str] = None, scopes: Optional[list[str]] = None): # noqa: A002
|
|
159
|
+
super().__init__(id=id, scopes=scopes)
|
|
160
|
+
|
|
161
|
+
|
|
153
162
|
class Reddit(OAuth2):
|
|
154
163
|
"""Marks a tool as requiring Reddit authorization."""
|
|
155
164
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Converters for transforming tool definitions between formats."""
|
|
2
|
+
|
|
3
|
+
from .anthropic import (
|
|
4
|
+
AnthropicInputSchema,
|
|
5
|
+
AnthropicInputSchemaProperty,
|
|
6
|
+
AnthropicToolList,
|
|
7
|
+
AnthropicToolSchema,
|
|
8
|
+
to_anthropic,
|
|
9
|
+
)
|
|
10
|
+
from .openai import (
|
|
11
|
+
OpenAIFunctionParameterProperty,
|
|
12
|
+
OpenAIFunctionParameters,
|
|
13
|
+
OpenAIFunctionSchema,
|
|
14
|
+
OpenAIToolList,
|
|
15
|
+
OpenAIToolSchema,
|
|
16
|
+
to_openai,
|
|
17
|
+
)
|
|
18
|
+
from .utils import denormalize_tool_name, normalize_tool_name
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"AnthropicInputSchema",
|
|
22
|
+
"AnthropicInputSchemaProperty",
|
|
23
|
+
"AnthropicToolList",
|
|
24
|
+
"AnthropicToolSchema",
|
|
25
|
+
"OpenAIFunctionParameterProperty",
|
|
26
|
+
"OpenAIFunctionParameters",
|
|
27
|
+
"OpenAIFunctionSchema",
|
|
28
|
+
"OpenAIToolList",
|
|
29
|
+
"OpenAIToolSchema",
|
|
30
|
+
"denormalize_tool_name",
|
|
31
|
+
"normalize_tool_name",
|
|
32
|
+
"to_anthropic",
|
|
33
|
+
"to_openai",
|
|
34
|
+
]
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""Converter for converting Arcade ToolDefinition to Anthropic tool schema."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, TypedDict
|
|
4
|
+
|
|
5
|
+
from arcade_core.catalog import MaterializedTool
|
|
6
|
+
from arcade_core.converters.utils import normalize_tool_name
|
|
7
|
+
from arcade_core.schema import InputParameter, ValueSchema
|
|
8
|
+
|
|
9
|
+
# ----------------------------------------------------------------------------
|
|
10
|
+
# Type definitions for JSON tool schemas used by Anthropic APIs.
|
|
11
|
+
# Defines the proper types for tool schemas to ensure
|
|
12
|
+
# compatibility with Anthropic's Messages API tool use feature.
|
|
13
|
+
# Reference: https://docs.anthropic.com/en/docs/build-with-claude/tool-use
|
|
14
|
+
# ----------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AnthropicInputSchemaProperty(TypedDict, total=False):
|
|
18
|
+
"""Type definition for a property within Anthropic input schema."""
|
|
19
|
+
|
|
20
|
+
type: str
|
|
21
|
+
"""The JSON Schema type for this property."""
|
|
22
|
+
|
|
23
|
+
description: str
|
|
24
|
+
"""Description of the property."""
|
|
25
|
+
|
|
26
|
+
enum: list[Any]
|
|
27
|
+
"""Allowed values for enum properties."""
|
|
28
|
+
|
|
29
|
+
items: dict[str, Any]
|
|
30
|
+
"""Schema for array items when type is 'array'."""
|
|
31
|
+
|
|
32
|
+
properties: dict[str, "AnthropicInputSchemaProperty"]
|
|
33
|
+
"""Nested properties when type is 'object'."""
|
|
34
|
+
|
|
35
|
+
required: list[str]
|
|
36
|
+
"""Required fields for nested objects."""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class AnthropicInputSchema(TypedDict, total=False):
|
|
40
|
+
"""Type definition for Anthropic tool input schema."""
|
|
41
|
+
|
|
42
|
+
type: str
|
|
43
|
+
"""Must be 'object' for tool input schemas."""
|
|
44
|
+
|
|
45
|
+
properties: dict[str, AnthropicInputSchemaProperty]
|
|
46
|
+
"""The properties of the tool input parameters."""
|
|
47
|
+
|
|
48
|
+
required: list[str]
|
|
49
|
+
"""List of required parameter names."""
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class AnthropicToolSchema(TypedDict, total=False):
|
|
53
|
+
"""
|
|
54
|
+
Schema for a tool definition passed to Anthropic's `tools` parameter.
|
|
55
|
+
|
|
56
|
+
Unlike OpenAI, Anthropic uses a flat structure without a wrapper object.
|
|
57
|
+
The schema uses `input_schema` instead of `parameters`.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
name: str
|
|
61
|
+
"""The name of the tool."""
|
|
62
|
+
|
|
63
|
+
description: str
|
|
64
|
+
"""Description of what the tool does."""
|
|
65
|
+
|
|
66
|
+
input_schema: AnthropicInputSchema
|
|
67
|
+
"""JSON Schema describing the tool's input parameters."""
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# Type alias for a list of Anthropic tool schemas
|
|
71
|
+
AnthropicToolList = list[AnthropicToolSchema]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# ----------------------------------------------------------------------------
|
|
75
|
+
# Converters
|
|
76
|
+
# ----------------------------------------------------------------------------
|
|
77
|
+
def to_anthropic(tool: MaterializedTool) -> AnthropicToolSchema:
|
|
78
|
+
"""Convert a MaterializedTool to Anthropic tool schema format.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
tool: The MaterializedTool to convert
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
The Anthropic tool schema format (what is passed to the Anthropic API)
|
|
85
|
+
"""
|
|
86
|
+
name = normalize_tool_name(tool.definition.fully_qualified_name)
|
|
87
|
+
description = tool.description
|
|
88
|
+
input_schema = _convert_input_parameters_to_json_schema(tool.definition.input.parameters)
|
|
89
|
+
|
|
90
|
+
return _create_tool_schema(name, description, input_schema)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _create_tool_schema(
|
|
94
|
+
name: str, description: str, input_schema: AnthropicInputSchema
|
|
95
|
+
) -> AnthropicToolSchema:
|
|
96
|
+
"""Create a properly typed Anthropic tool schema.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
name: The name of the tool
|
|
100
|
+
description: Description of what the tool does
|
|
101
|
+
input_schema: JSON schema for the tool input parameters
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
A properly typed AnthropicToolSchema
|
|
105
|
+
"""
|
|
106
|
+
tool: AnthropicToolSchema = {
|
|
107
|
+
"name": name,
|
|
108
|
+
"description": description,
|
|
109
|
+
"input_schema": input_schema,
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return tool
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _convert_value_schema_to_json_schema(
|
|
116
|
+
value_schema: ValueSchema,
|
|
117
|
+
) -> AnthropicInputSchemaProperty:
|
|
118
|
+
"""Convert Arcade ValueSchema to JSON Schema format for Anthropic."""
|
|
119
|
+
type_mapping = {
|
|
120
|
+
"string": "string",
|
|
121
|
+
"integer": "integer",
|
|
122
|
+
"number": "number",
|
|
123
|
+
"boolean": "boolean",
|
|
124
|
+
"json": "object",
|
|
125
|
+
"array": "array",
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
schema: AnthropicInputSchemaProperty = {"type": type_mapping[value_schema.val_type]}
|
|
129
|
+
|
|
130
|
+
if value_schema.val_type == "array" and value_schema.inner_val_type:
|
|
131
|
+
items_schema: dict[str, Any] = {"type": type_mapping[value_schema.inner_val_type]}
|
|
132
|
+
|
|
133
|
+
# For arrays, enum should be applied to the items, not the array itself
|
|
134
|
+
if value_schema.enum:
|
|
135
|
+
items_schema["enum"] = value_schema.enum
|
|
136
|
+
|
|
137
|
+
schema["items"] = items_schema
|
|
138
|
+
else:
|
|
139
|
+
# Handle enum for non-array types
|
|
140
|
+
if value_schema.enum:
|
|
141
|
+
schema["enum"] = value_schema.enum
|
|
142
|
+
|
|
143
|
+
# Handle object properties
|
|
144
|
+
if value_schema.val_type == "json" and value_schema.properties:
|
|
145
|
+
schema["properties"] = {
|
|
146
|
+
name: _convert_value_schema_to_json_schema(nested_schema)
|
|
147
|
+
for name, nested_schema in value_schema.properties.items()
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return schema
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _convert_input_parameters_to_json_schema(
|
|
154
|
+
parameters: list[InputParameter],
|
|
155
|
+
) -> AnthropicInputSchema:
|
|
156
|
+
"""Convert list of InputParameter to JSON schema parameters object.
|
|
157
|
+
|
|
158
|
+
Unlike OpenAI's strict mode, Anthropic uses standard JSON Schema:
|
|
159
|
+
- Only actually required parameters are listed in 'required'
|
|
160
|
+
- No need to add 'null' to optional parameter types
|
|
161
|
+
- No 'additionalProperties: false' requirement
|
|
162
|
+
"""
|
|
163
|
+
if not parameters:
|
|
164
|
+
# Minimal JSON schema for a tool with no input parameters
|
|
165
|
+
return {
|
|
166
|
+
"type": "object",
|
|
167
|
+
"properties": {},
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
properties: dict[str, AnthropicInputSchemaProperty] = {}
|
|
171
|
+
required: list[str] = []
|
|
172
|
+
|
|
173
|
+
for parameter in parameters:
|
|
174
|
+
param_schema = _convert_value_schema_to_json_schema(parameter.value_schema)
|
|
175
|
+
|
|
176
|
+
if parameter.description:
|
|
177
|
+
param_schema["description"] = parameter.description
|
|
178
|
+
|
|
179
|
+
properties[parameter.name] = param_schema
|
|
180
|
+
|
|
181
|
+
# Only add actually required parameters to the required list
|
|
182
|
+
if parameter.required:
|
|
183
|
+
required.append(parameter.name)
|
|
184
|
+
|
|
185
|
+
json_schema: AnthropicInputSchema = {
|
|
186
|
+
"type": "object",
|
|
187
|
+
"properties": properties,
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
# Only include 'required' if there are required parameters
|
|
191
|
+
if required:
|
|
192
|
+
json_schema["required"] = required
|
|
193
|
+
|
|
194
|
+
return json_schema
|
arcade_core/converters/openai.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from typing import Any, Literal, TypedDict
|
|
4
4
|
|
|
5
5
|
from arcade_core.catalog import MaterializedTool
|
|
6
|
+
from arcade_core.converters.utils import normalize_tool_name
|
|
6
7
|
from arcade_core.schema import InputParameter, ValueSchema
|
|
7
8
|
|
|
8
9
|
# ----------------------------------------------------------------------------
|
|
@@ -101,7 +102,7 @@ def to_openai(tool: MaterializedTool) -> OpenAIToolSchema:
|
|
|
101
102
|
Returns:
|
|
102
103
|
The OpenAI JsonToolSchema format (what is passed to the OpenAI API)
|
|
103
104
|
"""
|
|
104
|
-
name = tool.definition.fully_qualified_name
|
|
105
|
+
name = normalize_tool_name(tool.definition.fully_qualified_name)
|
|
105
106
|
description = tool.description
|
|
106
107
|
parameters_schema = _convert_input_parameters_to_json_schema(tool.definition.input.parameters)
|
|
107
108
|
return _create_tool_schema(name, description, parameters_schema)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Shared utilities for tool name conversion across providers.
|
|
2
|
+
|
|
3
|
+
This module contains common utilities used by both OpenAI and Anthropic converters.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def normalize_tool_name(name: str) -> str:
|
|
8
|
+
"""
|
|
9
|
+
Normalize a tool name for LLM provider compatibility.
|
|
10
|
+
|
|
11
|
+
Both OpenAI and Anthropic have restrictions on tool names:
|
|
12
|
+
- OpenAI: allows alphanumeric, hyphens, underscores (max 64 chars)
|
|
13
|
+
- Anthropic: allows alphanumeric and underscores only (no dots)
|
|
14
|
+
|
|
15
|
+
Arcade uses dot notation for fully qualified names (e.g., "Google.Search"),
|
|
16
|
+
so we normalize by replacing dots with underscores.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
name: The original tool name (e.g., "Google.Search")
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
The normalized tool name (e.g., "Google_Search")
|
|
23
|
+
|
|
24
|
+
Examples:
|
|
25
|
+
>>> normalize_tool_name("Google.Search")
|
|
26
|
+
'Google_Search'
|
|
27
|
+
>>> normalize_tool_name("MyTool")
|
|
28
|
+
'MyTool'
|
|
29
|
+
>>> normalize_tool_name("Namespace.Sub.Tool")
|
|
30
|
+
'Namespace_Sub_Tool'
|
|
31
|
+
"""
|
|
32
|
+
return name.replace(".", "_")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def denormalize_tool_name(normalized_name: str, separator: str = ".") -> str:
|
|
36
|
+
"""
|
|
37
|
+
Reverse the normalization of a tool name.
|
|
38
|
+
|
|
39
|
+
This converts provider-format names back to Arcade's dot notation.
|
|
40
|
+
Note: This is a best-effort reversal and may not be accurate if the original
|
|
41
|
+
name contained underscores.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
normalized_name: The normalized tool name (e.g., "Google_Search")
|
|
45
|
+
separator: The separator to use (default: ".")
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
The denormalized tool name (e.g., "Google.Search")
|
|
49
|
+
|
|
50
|
+
Examples:
|
|
51
|
+
>>> denormalize_tool_name("Google_Search")
|
|
52
|
+
'Google.Search'
|
|
53
|
+
"""
|
|
54
|
+
return normalized_name.replace("_", separator)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
arcade_core/__init__.py,sha256=1heu3AROAjpistehPzY2H-2nkj_IjQEh-vVlVOCRF1E,88
|
|
2
2
|
arcade_core/annotations.py,sha256=Nst6aejLWXlpTu7GwzWETu1gQCG1XVAUR_qcFbNvyRc,198
|
|
3
|
-
arcade_core/auth.py,sha256=
|
|
3
|
+
arcade_core/auth.py,sha256=UkIJBcXcsmN2OqEKV2HleIQ5bMaQYuXQTnZeDT2W_d4,6420
|
|
4
4
|
arcade_core/auth_tokens.py,sha256=4VAd634lgGigNHezoy2dBpLztliG4Qd2GH8ZBdZVDNo,3169
|
|
5
5
|
arcade_core/catalog.py,sha256=AA13L-ZG4O0S5rB1Fjc-wpLaa6im-dwIBx7GsE2ZW80,43527
|
|
6
6
|
arcade_core/config.py,sha256=e98XQAkYySGW9T_yrJg54BB8Wuq06GPVHp7xqe2d1vU,572
|
|
@@ -17,7 +17,10 @@ arcade_core/schema.py,sha256=y32Ndlb1b3Hw7_Wm3eVXxh0kSg3oGitWUYBfwFLjHuY,21198
|
|
|
17
17
|
arcade_core/toolkit.py,sha256=lLlOL6fA6Lmo-dtLTMMcPCzKDf9YQObwxG1LdVADv3E,14431
|
|
18
18
|
arcade_core/utils.py,sha256=_3bM-yfIDFmMVqt-NFYp2Lx1QcNWp7xytGjUQzPs2LY,3255
|
|
19
19
|
arcade_core/version.py,sha256=CpXi3jGlx23RvRyU7iytOMZrnspdWw4yofS8lpP1AJU,18
|
|
20
|
-
arcade_core/converters/
|
|
20
|
+
arcade_core/converters/__init__.py,sha256=ckb7c0LCq62_bARxoV7XlRYF7vtGbG1SJnDTWZ9Z7P4,827
|
|
21
|
+
arcade_core/converters/anthropic.py,sha256=Spkf6crPGPF8O82nyxqYI3whRs9togDqoTzTVYaZ6fc,6175
|
|
22
|
+
arcade_core/converters/openai.py,sha256=J4kQlmUzyZjp2vsnS0iDxyF_NhN3NfegiFTl7xYCwXM,7472
|
|
23
|
+
arcade_core/converters/utils.py,sha256=syN6G88UA8sChiLlr1VBna29sczuevb76_OAYuUfvtE,1699
|
|
21
24
|
arcade_core/network/__init__.py,sha256=8GEcg6QAr63U8U1n4bnf7cL-F7FrUrc9otHM2J9ODwk,53
|
|
22
25
|
arcade_core/network/org_transport.py,sha256=DZdIYdldtYZ6gtmWA1C8dXmsNuOv7tePhlpBuAvkhRQ,3222
|
|
23
26
|
arcade_core/usage/__init__.py,sha256=SUR5mqF-bjdbl-P-OOHN6OFAjXZu4agXyPhr7xdVXCw,234
|
|
@@ -26,6 +29,6 @@ arcade_core/usage/constants.py,sha256=1FQIhkFFMZUhU-H4A7GvMb7KQ3qLFrNAZb2-LEvSF3
|
|
|
26
29
|
arcade_core/usage/identity.py,sha256=egclRR26jGP1vVvoOoaaZdcS4AtSTZ8fLHpBq1HRgHw,8452
|
|
27
30
|
arcade_core/usage/usage_service.py,sha256=xzWWSEktm58liiNYugBHRactSru8V5foriHcsoH0j1A,3407
|
|
28
31
|
arcade_core/usage/utils.py,sha256=FqBOmlhwT68cbnpI5Vx9ZW6vLRYPVg4FJ0GaMEp8qEM,398
|
|
29
|
-
arcade_core-4.
|
|
30
|
-
arcade_core-4.
|
|
31
|
-
arcade_core-4.
|
|
32
|
+
arcade_core-4.2.0.dist-info/METADATA,sha256=9MoBNcEU1QcYlpXatMEe6Lj_OhbJUKCuyaCuZ0FQ52E,2412
|
|
33
|
+
arcade_core-4.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
34
|
+
arcade_core-4.2.0.dist-info/RECORD,,
|
|
File without changes
|