PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 2.3.1
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v2.3.1
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.2 2.2.1 2.2.0 2.1.2 2.1.1 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 All 66 releases
better-payment / includes / AI / Providers / ClaudeProvider.php

ClaudeProvider.php in Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More 2.3.1, at includes/AI/Providers/ClaudeProvider.php

118 lines 3.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Better_Payment\Lite\AI\Providers;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit;
7 }
8
9 /**
10 * Anthropic Claude provider (Messages API).
11 *
12 * Uses native tool-use so the model returns Builder Operations as structured
13 * `tool_use` blocks rather than free text. Anthropic does not generate images,
14 * so image support is off.
15 */
16 class ClaudeProvider extends AbstractProvider {
17
18 const ENDPOINT = 'https://api.anthropic.com/v1/messages';
19 const API_VERSION = '2023-06-01';
20
21 public function get_id(): string {
22 return 'claude';
23 }
24
25 public function get_label(): string {
26 return 'Claude (Anthropic)';
27 }
28
29 public function get_models(): array {
30 return [ 'claude-sonnet-5', 'claude-opus-4-8', 'claude-haiku-4-5-20251001' ];
31 }
32
33 public function chat( array $messages, array $options = [] ): array {
34 list( $system, $turns ) = self::split_system( $messages, (string) ( $options['system'] ?? '' ) );
35
36 $payload_messages = [];
37 foreach ( $turns as $turn ) {
38 $payload_messages[] = [
39 'role' => $turn['role'],
40 'content' => $turn['content'],
41 ];
42 }
43
44 $body = [
45 'model' => $this->resolve_model( $options ),
46 'max_tokens' => $this->max_tokens( $options ),
47 'temperature' => $this->temperature( $options ),
48 'messages' => $payload_messages,
49 ];
50 if ( '' !== $system ) {
51 $body['system'] = $system;
52 }
53 if ( ! empty( $options['tools'] ) ) {
54 $body['tools'] = $this->format_tools( $options['tools'] );
55 if ( 'required' === ( $options['tool_choice'] ?? '' ) ) {
56 $body['tool_choice'] = [ 'type' => 'any' ];
57 }
58 }
59
60 $headers = [
61 'x-api-key' => sanitize_text_field( (string) $this->config['api_key'] ),
62 'anthropic-version' => self::API_VERSION,
63 ];
64
65 $result = $this->post_json( self::ENDPOINT, $headers, $body );
66 if ( ! $result['ok'] ) {
67 return [ 'text' => '', 'tool_calls' => [], 'usage' => [], 'error' => $result['error'], 'raw' => $result['data'] ];
68 }
69
70 return $this->normalize_chat( $result['data'] );
71 }
72
73 /**
74 * @param array $tools
75 * @return array
76 */
77 protected function format_tools( array $tools ): array {
78 $out = [];
79 foreach ( $tools as $tool ) {
80 $out[] = [
81 'name' => $tool['name'],
82 'description' => $tool['description'] ?? '',
83 'input_schema' => self::params_to_json_schema( $tool['params'] ?? [] ),
84 ];
85 }
86 return $out;
87 }
88
89 /**
90 * @param mixed $data
91 * @return array
92 */
93 protected function normalize_chat( $data ): array {
94 $text = '';
95 $tool_calls = [];
96
97 foreach ( (array) ( $data['content'] ?? [] ) as $block ) {
98 $btype = $block['type'] ?? '';
99 if ( 'text' === $btype ) {
100 $text .= (string) ( $block['text'] ?? '' );
101 } elseif ( 'tool_use' === $btype ) {
102 $tool_calls[] = [
103 'name' => (string) ( $block['name'] ?? '' ),
104 'arguments' => self::decode_arguments( $block['input'] ?? [] ),
105 ];
106 }
107 }
108
109 return [
110 'text' => $text,
111 'tool_calls' => $tool_calls,
112 'usage' => $data['usage'] ?? [],
113 'error' => null,
114 'raw' => $data,
115 ];
116 }
117 }
118