Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
109 / 109
100.00% covered (success)
100.00%
23 / 23
CRAP
100.00% covered (success)
100.00%
1 / 1
ControlPlane
100.00% covered (success)
100.00%
109 / 109
100.00% covered (success)
100.00%
23 / 23
46
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 listIndexes
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 createIndex
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 createForModel
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 describeIndex
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 deleteIndex
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 configureIndex
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 createCollection
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 listCollections
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 describeCollection
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 deleteCollection
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 createBackup
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 listBackups
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 describeBackup
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 deleteBackup
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 createIndexFromBackup
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 listRestoreJobs
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 describeRestoreJob
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 createAssistant
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 listAssistants
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 describeAssistant
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 updateAssistant
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 deleteAssistant
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace Mbvb1223\Pinecone\Control;
6
7use GuzzleHttp\Client;
8use GuzzleHttp\Exception\GuzzleException;
9use Mbvb1223\Pinecone\Errors\PineconeException;
10use Mbvb1223\Pinecone\Utils\HandlesApiResponse;
11
12class ControlPlane
13{
14    use HandlesApiResponse;
15
16    public function __construct(private readonly Client $httpClient)
17    {
18    }
19
20    /** @return array<int, array<string, mixed>> */
21    public function listIndexes(): array
22    {
23        try {
24            $response = $this->httpClient->get('/indexes');
25            $data = $this->handleResponse($response);
26
27            return $data['indexes'] ?? [];
28        } catch (GuzzleException $e) {
29            throw new PineconeException('Failed to list indexes: ' . $e->getMessage(), 0, $e);
30        }
31    }
32
33    /**
34     * @param array{dimension?: int, metric?: string, spec?: array<string, mixed>, ...} $requestData
35     * @return array<string, mixed>
36     */
37    public function createIndex(string $name, array $requestData): array
38    {
39        try {
40            $payload = array_merge(['metric' => 'cosine'], $requestData, ['name' => $name]);
41
42            $response = $this->httpClient->post('/indexes', ['json' => $payload]);
43
44            return $this->handleResponse($response);
45        } catch (GuzzleException $e) {
46            throw new PineconeException("Failed to create index: $name{$e->getMessage()}", 0, $e);
47        }
48    }
49
50    /**
51     * @param array{cloud: string, region: string, embed: array{model: string, ...}, ...} $requestData
52     * @return array<string, mixed>
53     */
54    public function createForModel(string $name, array $requestData): array
55    {
56        try {
57            $payload = array_merge(['name' => $name], $requestData);
58
59            $response = $this->httpClient->post('/indexes/create-for-model', ['json' => $payload]);
60
61            return $this->handleResponse($response);
62        } catch (GuzzleException $e) {
63            throw new PineconeException("Failed to create index for model: $name{$e->getMessage()}", 0, $e);
64        }
65    }
66
67    /** @return array<string, mixed> */
68    public function describeIndex(string $name): array
69    {
70        try {
71            $encodedName = urlencode($name);
72            $response = $this->httpClient->get("/indexes/{$encodedName}");
73
74            return $this->handleResponse($response);
75        } catch (GuzzleException $e) {
76            throw new PineconeException("Failed to describe index: $name{$e->getMessage()}", 0, $e);
77        }
78    }
79
80    public function deleteIndex(string $name): void
81    {
82        try {
83            $encodedName = urlencode($name);
84            $response = $this->httpClient->delete("/indexes/{$encodedName}");
85            $this->handleResponse($response);
86        } catch (GuzzleException $e) {
87            throw new PineconeException("Failed to delete index: $name{$e->getMessage()}", 0, $e);
88        }
89    }
90
91    /**
92     * @param array<string, mixed> $requestData
93     * @return array<string, mixed>
94     */
95    public function configureIndex(string $name, array $requestData): array
96    {
97        try {
98            $encodedName = urlencode($name);
99            $response = $this->httpClient->patch("/indexes/{$encodedName}", ['json' => $requestData]);
100
101            return $this->handleResponse($response);
102        } catch (GuzzleException $e) {
103            throw new PineconeException("Failed to configure index: $name{$e->getMessage()}", 0, $e);
104        }
105    }
106
107    // Collection methods
108
109    /**
110     * @param array{name: string, source: string} $config
111     * @return array<string, mixed>
112     */
113    public function createCollection(array $config): array
114    {
115        try {
116            $response = $this->httpClient->post('/collections', ['json' => $config]);
117
118            return $this->handleResponse($response);
119        } catch (GuzzleException $e) {
120            throw new PineconeException('Failed to create collection: ' . $e->getMessage(), 0, $e);
121        }
122    }
123
124    /** @return array<int, array<string, mixed>> */
125    public function listCollections(): array
126    {
127        try {
128            $response = $this->httpClient->get('/collections');
129            $data = $this->handleResponse($response);
130
131            return $data['collections'] ?? [];
132        } catch (GuzzleException $e) {
133            throw new PineconeException('Failed to list collections: ' . $e->getMessage(), 0, $e);
134        }
135    }
136
137    /** @return array<string, mixed> */
138    public function describeCollection(string $name): array
139    {
140        try {
141            $encodedName = urlencode($name);
142            $response = $this->httpClient->get("/collections/{$encodedName}");
143
144            return $this->handleResponse($response);
145        } catch (GuzzleException $e) {
146            throw new PineconeException("Failed to describe collection: $name{$e->getMessage()}", 0, $e);
147        }
148    }
149
150    public function deleteCollection(string $name): void
151    {
152        try {
153            $encodedName = urlencode($name);
154            $response = $this->httpClient->delete("/collections/{$encodedName}");
155            $this->handleResponse($response);
156        } catch (GuzzleException $e) {
157            throw new PineconeException("Failed to delete collection: $name{$e->getMessage()}", 0, $e);
158        }
159    }
160
161    // Backup methods
162
163    /**
164     * @param array{source_index_name: string, name?: string, description?: string} $config
165     * @return array<string, mixed>
166     */
167    public function createBackup(array $config): array
168    {
169        try {
170            $response = $this->httpClient->post('/backups', ['json' => $config]);
171
172            return $this->handleResponse($response);
173        } catch (GuzzleException $e) {
174            throw new PineconeException('Failed to create backup: ' . $e->getMessage(), 0, $e);
175        }
176    }
177
178    /** @return array<int, array<string, mixed>> */
179    public function listBackups(): array
180    {
181        try {
182            $response = $this->httpClient->get('/backups');
183            $data = $this->handleResponse($response);
184
185            return $data['data'] ?? [];
186        } catch (GuzzleException $e) {
187            throw new PineconeException('Failed to list backups: ' . $e->getMessage(), 0, $e);
188        }
189    }
190
191    /** @return array<string, mixed> */
192    public function describeBackup(string $id): array
193    {
194        try {
195            $encodedId = urlencode($id);
196            $response = $this->httpClient->get("/backups/{$encodedId}");
197
198            return $this->handleResponse($response);
199        } catch (GuzzleException $e) {
200            throw new PineconeException("Failed to describe backup: $id{$e->getMessage()}", 0, $e);
201        }
202    }
203
204    public function deleteBackup(string $id): void
205    {
206        try {
207            $encodedId = urlencode($id);
208            $response = $this->httpClient->delete("/backups/{$encodedId}");
209            $this->handleResponse($response);
210        } catch (GuzzleException $e) {
211            throw new PineconeException("Failed to delete backup: $id{$e->getMessage()}", 0, $e);
212        }
213    }
214
215    // Restore methods
216
217    /**
218     * @param array{name: string, ...} $config
219     * @return array<string, mixed>
220     */
221    public function createIndexFromBackup(string $backupId, array $config): array
222    {
223        try {
224            $encodedId = urlencode($backupId);
225            $response = $this->httpClient->post("/backups/{$encodedId}/create-index", ['json' => $config]);
226
227            return $this->handleResponse($response);
228        } catch (GuzzleException $e) {
229            throw new PineconeException("Failed to create index from backup: $backupId{$e->getMessage()}", 0, $e);
230        }
231    }
232
233    /**
234     * @param array<string, mixed> $params
235     * @return array<int, array<string, mixed>>
236     */
237    public function listRestoreJobs(array $params = []): array
238    {
239        try {
240            $options = !empty($params) ? ['query' => $params] : [];
241            $response = $this->httpClient->get('/restore-jobs', $options);
242            $data = $this->handleResponse($response);
243
244            return $data['data'] ?? [];
245        } catch (GuzzleException $e) {
246            throw new PineconeException('Failed to list restore jobs: ' . $e->getMessage(), 0, $e);
247        }
248    }
249
250    /** @return array<string, mixed> */
251    public function describeRestoreJob(string $id): array
252    {
253        try {
254            $encodedId = urlencode($id);
255            $response = $this->httpClient->get("/restore-jobs/{$encodedId}");
256
257            return $this->handleResponse($response);
258        } catch (GuzzleException $e) {
259            throw new PineconeException("Failed to describe restore job: $id{$e->getMessage()}", 0, $e);
260        }
261    }
262
263    // Assistant methods
264
265    /**
266     * @param array{name: string, instructions?: string, metadata?: array<string, mixed>} $config
267     * @return array<string, mixed>
268     */
269    public function createAssistant(array $config): array
270    {
271        try {
272            $response = $this->httpClient->post('/assistants', ['json' => $config]);
273
274            return $this->handleResponse($response);
275        } catch (GuzzleException $e) {
276            throw new PineconeException('Failed to create assistant: ' . $e->getMessage(), 0, $e);
277        }
278    }
279
280    /** @return array<int, array<string, mixed>> */
281    public function listAssistants(): array
282    {
283        try {
284            $response = $this->httpClient->get('/assistants');
285            $data = $this->handleResponse($response);
286
287            return $data['assistants'] ?? [];
288        } catch (GuzzleException $e) {
289            throw new PineconeException('Failed to list assistants: ' . $e->getMessage(), 0, $e);
290        }
291    }
292
293    /** @return array<string, mixed> */
294    public function describeAssistant(string $name): array
295    {
296        try {
297            $encodedName = urlencode($name);
298            $response = $this->httpClient->get("/assistants/{$encodedName}");
299
300            return $this->handleResponse($response);
301        } catch (GuzzleException $e) {
302            throw new PineconeException("Failed to describe assistant: $name{$e->getMessage()}", 0, $e);
303        }
304    }
305
306    /**
307     * @param array{instructions?: string, metadata?: array<string, mixed>} $config
308     * @return array<string, mixed>
309     */
310    public function updateAssistant(string $name, array $config): array
311    {
312        try {
313            $encodedName = urlencode($name);
314            $response = $this->httpClient->patch("/assistants/{$encodedName}", ['json' => $config]);
315
316            return $this->handleResponse($response);
317        } catch (GuzzleException $e) {
318            throw new PineconeException("Failed to update assistant: $name{$e->getMessage()}", 0, $e);
319        }
320    }
321
322    public function deleteAssistant(string $name): void
323    {
324        try {
325            $encodedName = urlencode($name);
326            $response = $this->httpClient->delete("/assistants/{$encodedName}");
327            $this->handleResponse($response);
328        } catch (GuzzleException $e) {
329            throw new PineconeException("Failed to delete assistant: $name{$e->getMessage()}", 0, $e);
330        }
331    }
332}