Skip to content

Commit 30e7e34

Browse files
authored
Merge pull request #68 from fumito-ito/feature/admin-api
Admin API support
2 parents dcfedf3 + b269538 commit 30e7e34

File tree

85 files changed

+2606
-171
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+2606
-171
lines changed

README.md

Lines changed: 131 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,137 @@ for try await chunk in stream {
8585
}
8686
```
8787

88+
### [Message Batches (beta)](https://docs.anthropic.com/en/docs/build-with-claude/message-batches)
89+
90+
The Message Batches API is a powerful, cost-effective way to asynchronously process large volumes of [Messages](https://docs.anthropic.com/en/api/messages) requests. This approach is well-suited to tasks that do not require immediate responses, reducing costs by 50% while increasing throughput.
91+
92+
This is especially useful for bulk operations that don’t require immediate results.
93+
94+
Here's an example of how to process many messages with the Message Batches API:
95+
96+
```swift
97+
let anthropic = Anthropic(apiKey: "YOUR_OWN_API_KEY")
98+
99+
let messages = [
100+
Message(role: .user, content: [.text("Write a haiku about robots.")]),
101+
Message(role: .user, content: [.text("Write a haiku about robots. Skip the preamble; go straight into the poem.")]),
102+
Message(role: .user, content: [.text("Who is the best basketball player of all time?")]),
103+
Message(role: .user, content: [.text("Who is the best basketball player of all time? Yes, there are differing opinions, but if you absolutely had to pick one player, who would it be?")])
104+
// ....
105+
]
106+
107+
let batch = MessageBatch(
108+
customId: "my-first-batch-request",
109+
parameter: .init(
110+
messages: messages,
111+
maxTokens: 1024
112+
)
113+
)
114+
115+
let response = try await anthropic.messageBatches.createBatches(batches: [batch])
116+
```
117+
118+
### [Admin API](https://docs.anthropic.com/en/docs/administration/administration-api)
119+
120+
This library also supports an Admin API for managing workspaces and organization members.
121+
122+
#### [Organization Members API](https://docs.anthropic.com/en/docs/administration/administration-api#organization-members)
123+
124+
- **Get Organization Member**: Retrieve details about a specific organization member.
125+
- **List Organization Members**: List organization members.
126+
- **Remove Organization Member**: Remove a member from the organization.
127+
- **Update Organization Member**: Update the role or details of an existing organization member.
128+
129+
Example of updating an organization member:
130+
131+
```swift
132+
let admin = AnthropicAdmin(adminAPIKey: "YOUR_OWN_ADMIN_API_KEY")
133+
try await admin.organizationMembers.get(userId: "user_01WCz1FkmYMm4gnmykNKUu3Q")
134+
```
135+
136+
#### [Organization Invites API](https://docs.anthropic.com/en/docs/administration/administration-api#organization-invites)
137+
138+
- **Get Organization Invites**: Retrieve details about a specific organization invitation.
139+
- **List Organization Invites**: List organization invitations.
140+
- **Remove Organization Invites**: Remove a invitation from the organization.
141+
- **Create Organization Invites**: Create a new organization invitation.
142+
143+
Example of updating an organization invitation:
144+
145+
```swift
146+
let admin = AnthropicAdmin(adminAPIKey: "YOUR_OWN_ADMIN_API_KEY")
147+
try await admin.organizationInvites.list()
148+
```
149+
150+
#### [Workspaces API](https://docs.anthropic.com/en/docs/administration/administration-api#workspaces)
151+
152+
- **Get Workspace**: Retrieve details about a specific workspace.
153+
- **List Workspaces**: List workspaces.
154+
- **Create Workspace**: Create a new workspace.
155+
- **Archive Workspace**: Archive an existing workspace.
156+
- **Update Workspace**: Update the details of an existing workspace.
157+
158+
Example of creating a workspace:
159+
160+
```swift
161+
let admin = AnthropicAdmin(adminAPIKey: "YOUR_OWN_ADMIN_API_KEY")
162+
try await admin.workspaces.get(workspaceId: "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ")
163+
```
164+
165+
#### [Workspace Members API](https://docs.anthropic.com/en/docs/administration/administration-api#workspace-members)
166+
167+
- **Get Workspace Member**: Retrieve details about a specific workspace member.
168+
- **List Workspace Members**: List workspace members.
169+
- **Create Workspace Member**: Add a new member for the workspace.
170+
- **Remove Workspace Member**: Remove a member from the workspace.
171+
- **Update Workspace Member**: Update the role or details of an existing workspace member.
172+
173+
Example of updating an workspace member:
174+
175+
```swift
176+
let admin = AnthropicAdmin(adminAPIKey: "YOUR_OWN_ADMIN_API_KEY")
177+
try await admin.workspaceMembers.get(userId: "user_01WCz1FkmYMm4gnmykNKUu3Q")
178+
```
179+
180+
#### [API Keys API](https://docs.anthropic.com/en/docs/administration/administration-api#api-keys)
181+
182+
- **Get Organization Member**: Retrieve details about a specific API key.
183+
- **List Organization Members**: List API keys.
184+
- **Update Organization Member**: Update the status or name of an existing API key.
185+
186+
Example of updating an organization member:
187+
188+
```swift
189+
let admin = AnthropicAdmin(adminAPIKey: "YOUR_OWN_ADMIN_API_KEY")
190+
try await admin.apiKeys.get(apiKeyId: "apikey_01Rj2N8SVvo6BePZj99NhmiT")
191+
```
192+
193+
### [Token Counting](https://docs.anthropic.com/en/docs/build-with-claude/token-counting)
194+
195+
Token counting enables you to determine the number of tokens in a message before sending it to Claude, helping you make informed decisions about your prompts and usage. With token counting, you can
196+
197+
- Proactively manage rate limits and costs
198+
- Make smart model routing decisions
199+
- Optimize prompts to be a specific length
200+
201+
```swift
202+
let anthropic = Anthropic(apiKey: "YOUR_OWN_API_KEY")
203+
204+
let message = Message(role: .user, content: [.text("Find flights from San Francisco to a place with warmer weather.")])
205+
let response = try await anthropic.countTokens.countTokens(
206+
[message],
207+
maxTokens: 1024,
208+
tools: [
209+
.computer(.init(name: "my_computer", displayWidthPx: 1024, displayHeightPx: 768, displayNumber: 1),
210+
.bash(.init(name: "bash"))
211+
]
212+
)
213+
```
214+
215+
The token counting endpoint accepts the same structured list of inputs for creating a message, including support for system prompts, tools, images, and PDFs. The response contains the total number of input tokens.
216+
217+
## Supporting Features
218+
88219
### [Tool Use](https://docs.anthropic.com/en/docs/build-with-claude/tool-use)
89220

90221
Claude is capable of interacting with external client-side tools and functions, allowing you to equip Claude with your own custom tools to perform a wider variety of tasks.
@@ -134,36 +265,6 @@ let response = try await anthropic.messages.createMessage(
134265
)
135266
```
136267

137-
### [Message Batches (beta)](https://docs.anthropic.com/en/docs/build-with-claude/message-batches)
138-
139-
The Message Batches API is a powerful, cost-effective way to asynchronously process large volumes of [Messages](https://docs.anthropic.com/en/api/messages) requests. This approach is well-suited to tasks that do not require immediate responses, reducing costs by 50% while increasing throughput.
140-
141-
This is especially useful for bulk operations that don’t require immediate results.
142-
143-
Here's an example of how to process many messages with the Message Bathches API:
144-
145-
```swift
146-
let anthropic = Anthropic(apiKey: "YOUR_OWN_API_KEY")
147-
148-
let messages = [
149-
Message(role: .user, content: [.text("Write a haiku about robots.")]),
150-
Message(role: .user, content: [.text("Write a haiku about robots. Skip the preamble; go straight into the poem.")]),
151-
Message(role: .user, content: [.text("Who is the best basketball player of all time?")]),
152-
Message(role: .user, content: [.text("Who is the best basketball player of all time? Yes, there are differing opinions, but if you absolutely had to pick one player, who would it be?")])
153-
// ....
154-
]
155-
156-
let batch = MessageBatch(
157-
customId: "my-first-batch-request",
158-
parameter: .init(
159-
messages: messages,
160-
maxTokens: 1024
161-
)
162-
)
163-
164-
let response = try await anthropic.messageBatches.createBatches(batches: [batch])
165-
```
166-
167268
### [Computer Use (beta)](https://docs.anthropic.com/en/docs/build-with-claude/computer-use#computer-tool)
168269

169270
The upgraded Claude 3.5 Sonnet model is capable of interacting with tools that can manipulate a computer desktop environment.
@@ -184,30 +285,6 @@ let response = try await anthropic.messages.createMessage(
184285
)
185286
```
186287

187-
### [Token Counting](https://docs.anthropic.com/en/docs/build-with-claude/token-counting)
188-
189-
Token counting enables you to determine the number of tokens in a message before sending it to Claude, helping you make informed decisions about your prompts and usage. With token counting, you can
190-
191-
- Proactively manage rate limits and costs
192-
- Make smart model routing decisions
193-
- Optimize prompts to be a specific length
194-
195-
```swift
196-
let anthropic = Anthropic(apiKey: "YOUR_OWN_API_KEY")
197-
198-
let message = Message(role: .user, content: [.text("Find flights from San Francisco to a place with warmer weather.")])
199-
let response = try await anthropic.countTokens.countTokens(
200-
[message],
201-
maxTokens: 1024,
202-
tools: [
203-
.computer(.init(name: "my_computer", displayWidthPx: 1024, displayHeightPx: 768, displayNumber: 1),
204-
.bash(.init(name: "bash"))
205-
]
206-
)
207-
```
208-
209-
The token counting endpoint accepts the same structured list of inputs for creating a message, including support for system prompts, tools, images, and PDFs. The response contains the total number of input tokens.
210-
211288
## Extensions
212289

213290
By introducing an extension Swift package, it is possible to access the Anthropic Claude API through AWS Bedrock and Vertex AI. The supported services are as follows:

Sources/AnthropicSwiftSDK-TestUtils/HTTPMock.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public class HTTPMock: URLProtocol {
4545
client?.urlProtocol(self, didLoad: getBasicJSONStringData())
4646
case .request(_, nil), .requestHeader(_, nil):
4747
client?.urlProtocol(self, didReceive: succeedResponse, cacheStoragePolicy: .notAllowed)
48+
client?.urlProtocol(self, didLoad: getBasicJSONStringData())
4849
case .request(_, let jsonString), .requestHeader(_, let jsonString):
4950
client?.urlProtocol(self, didReceive: succeedResponse, cacheStoragePolicy: .notAllowed)
5051
guard let jsonString, let data = jsonString.data(using: .utf8) else {

Sources/AnthropicSwiftSDK-TestUtils/MessagesRequest+Extensions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import AnthropicSwiftSDK
1111
public struct NopRequest: Request {
1212
public let method: HttpMethod
1313
public let path: String
14-
public let queries: [String : any CustomStringConvertible]? = nil
14+
public let queries: [String: any CustomStringConvertible]? = nil
1515
public let body: Never? = nil
1616

1717
public init(
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//
2+
// APIKeys.swift
3+
// AnthropicSwiftSDK
4+
//
5+
// Created by 伊藤史 on 2024/11/28.
6+
//
7+
import Foundation
8+
9+
public struct APIKeys {
10+
private let apiKey: String
11+
private let session: URLSession
12+
13+
init(adminAPIKey: String, session: URLSession) {
14+
self.apiKey = adminAPIKey
15+
self.session = session
16+
}
17+
18+
public func get(apiKeyId: String) async throws -> APIKeyResponse {
19+
try await get(
20+
apiKeyId: apiKeyId,
21+
anthropicHeaderProvider: DefaultAnthropicHeaderProvider(),
22+
authenticationHeaderProvider: APIKeyAuthenticationHeaderProvider(apiKey: apiKey)
23+
)
24+
}
25+
26+
public func get(
27+
apiKeyId: String,
28+
anthropicHeaderProvider: AnthropicHeaderProvider,
29+
authenticationHeaderProvider: AuthenticationHeaderProvider
30+
) async throws -> APIKeyResponse {
31+
let client = APIClient(
32+
session: session,
33+
anthropicHeaderProvider: anthropicHeaderProvider,
34+
authenticationHeaderProvider: authenticationHeaderProvider
35+
)
36+
37+
return try await client.send(request: GetAPIKeyRequest(apiKeyId: apiKeyId))
38+
}
39+
40+
public func list(
41+
limit: Int = 20,
42+
beforeId: String? = nil,
43+
afterId: String? = nil,
44+
status: APIKeyStatus? = nil,
45+
workspaceId: String? = nil,
46+
createdByUserId: String? = nil
47+
) async throws -> ObjectListResponse<APIKeyResponse> {
48+
fatalError("not implemented")
49+
}
50+
51+
public func list(
52+
limit: Int = 20,
53+
beforeId: String? = nil,
54+
afterId: String? = nil,
55+
status: APIKeyStatus? = nil,
56+
workspaceId: String? = nil,
57+
createdByUserId: String? = nil,
58+
anthropicHeaderProvider: AnthropicHeaderProvider,
59+
authenticationHeaderProvider: AuthenticationHeaderProvider
60+
) async throws -> ObjectListResponse<APIKeyResponse> {
61+
try await list(
62+
session: session,
63+
type: .apiKey,
64+
limit: limit,
65+
beforeId: beforeId,
66+
afterId: afterId,
67+
anthropicHeaderProvider: anthropicHeaderProvider,
68+
authenticationHeaderProvider: authenticationHeaderProvider
69+
)
70+
}
71+
72+
public func update(apiKeyId: String, name: String, status: APIKeyStatus? = nil) async throws -> APIKeyResponse {
73+
try await update(
74+
apiKeyId: apiKeyId,
75+
name: name,
76+
status: status,
77+
anthropicHeaderProvider: DefaultAnthropicHeaderProvider(),
78+
authenticationHeaderProvider: APIKeyAuthenticationHeaderProvider(apiKey: apiKey)
79+
)
80+
}
81+
82+
public func update(
83+
apiKeyId: String,
84+
name: String,
85+
status: APIKeyStatus? = nil,
86+
anthropicHeaderProvider: AnthropicHeaderProvider,
87+
authenticationHeaderProvider: AuthenticationHeaderProvider
88+
) async throws -> APIKeyResponse {
89+
let client = APIClient(
90+
session: session,
91+
anthropicHeaderProvider: anthropicHeaderProvider,
92+
authenticationHeaderProvider: authenticationHeaderProvider
93+
)
94+
95+
return try await client.send(
96+
request: UpdateAPIKeyRequest(
97+
body: .init(name: name, status: status),
98+
apiKeyId: apiKeyId
99+
)
100+
)
101+
}
102+
}
103+
104+
extension APIKeys: ObjectListable {
105+
typealias Object = APIKeyResponse
106+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// Admin.swift
3+
// AnthropicSwiftSDK
4+
//
5+
// Created by 伊藤史 on 2024/11/28.
6+
//
7+
import Foundation
8+
9+
public struct Admin {
10+
public let organizationMembers: OrganizationMembers
11+
public let organizationInvites: OrganizationInvites
12+
public let workspaces: Workspaces
13+
public let workspaceMembers: WorkspaceMembers
14+
public let apiKeys: APIKeys
15+
16+
public init(adminAPIKey apiKey: String, session: URLSession = .shared) {
17+
self.organizationMembers = OrganizationMembers(adminAPIKey: apiKey, session: session)
18+
self.organizationInvites = OrganizationInvites(adminAPIKey: apiKey, session: session)
19+
self.workspaces = Workspaces(adminAPIKey: apiKey, session: session)
20+
self.workspaceMembers = WorkspaceMembers(adminAPIKey: apiKey, session: session)
21+
self.apiKeys = APIKeys(adminAPIKey: apiKey, session: session)
22+
}
23+
}

0 commit comments

Comments
 (0)