Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7604609
Add method to update workspace settings
Strift Aug 6, 2025
4897fbf
add CRUD methods
Strift Aug 13, 2025
51f4400
Refactor
Strift Aug 13, 2025
cd2b8df
Add chat completion streaming
Strift Aug 13, 2025
e52759c
Lint
Strift Aug 13, 2025
1395b8d
Run phpstan
Strift Aug 13, 2025
f87bde4
Fix doc types
Strift Aug 13, 2025
b063d4b
Add get/update methods for chat settings
Strift Aug 15, 2025
b09585f
Fix incorrect exception catch block
Strift Aug 15, 2025
0cc3972
lint
Strift Aug 15, 2025
2b98215
Update src/Http/Client.php
Strift Aug 22, 2025
bde19cc
Update src/Http/Client.php
Strift Aug 22, 2025
c2ee6ca
Merge branch 'main' into feat/add-chat-api
Strift Aug 22, 2025
cb6c0bb
Improve chat workspaces type hints
Strift Aug 22, 2025
b6ae3bb
Make workspaceName non-empty-string
Strift Aug 22, 2025
c91b873
Throw exception if token is not available
Strift Aug 22, 2025
dd6aef9
Update types and tests
Strift Aug 22, 2025
340b57f
Merge branch 'main' into feat/add-chat-api
Strift Aug 26, 2025
eafe1f2
Merge branch 'main' into feat/add-chat-api
Strift Aug 27, 2025
d78323d
Update src/Contracts/ChatWorkspacesResults.php
Strift Sep 2, 2025
4dce531
Update src/Contracts/ChatWorkspacesResults.php
Strift Sep 2, 2025
72e933e
Require prompts settings search params to be non-empty
Strift Sep 3, 2025
586c3c6
Add type hints to chat workspace settings
Strift Sep 3, 2025
fb27035
Added typehints to chat workspaces results
Strift Sep 3, 2025
56c6996
Add import and use only class name
Strift Sep 3, 2025
84b8ee0
Lint
Strift Sep 3, 2025
f67b66b
Import streaminterface and use class name
Strift Sep 3, 2025
4990e74
Make class attributes private
Strift Sep 3, 2025
2b0b414
Make chats property private
Strift Sep 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
namespace Meilisearch;

use Meilisearch\Endpoints\Batches;
use Meilisearch\Endpoints\ChatWorkspaces;
use Meilisearch\Endpoints\Delegates\HandlesBatches;
use Meilisearch\Endpoints\Delegates\HandlesChatWorkspaces;
use Meilisearch\Endpoints\Delegates\HandlesDumps;
use Meilisearch\Endpoints\Delegates\HandlesIndex;
use Meilisearch\Endpoints\Delegates\HandlesKeys;
Expand All @@ -31,6 +33,7 @@

class Client
{
use HandlesChatWorkspaces;
use HandlesDumps;
use HandlesIndex;
use HandlesTasks;
Expand All @@ -53,6 +56,7 @@ public function __construct(
?StreamFactoryInterface $streamFactory = null
) {
$this->http = new MeilisearchClientAdapter($url, $apiKey, $httpClient, $requestFactory, $clientAgents, $streamFactory);
$this->chats = new ChatWorkspaces($this->http);
$this->index = new Indexes($this->http);
$this->health = new Health($this->http);
$this->version = new Version($this->http);
Expand Down
88 changes: 88 additions & 0 deletions src/Contracts/ChatWorkspaceSettings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

declare(strict_types=1);

namespace Meilisearch\Contracts;

class ChatWorkspaceSettings extends Data
{
private ?string $source;
private ?string $orgId;
private ?string $projectId;
private ?string $apiVersion;
private ?string $deploymentId;
private ?string $baseUrl;
private ?string $apiKey;
private array $prompts;

public function __construct(array $params)
{
parent::__construct($params);

$this->source = $params['source'] ?? null;
$this->orgId = $params['orgId'] ?? null;
$this->projectId = $params['projectId'] ?? null;
$this->apiVersion = $params['apiVersion'] ?? null;
$this->deploymentId = $params['deploymentId'] ?? null;
$this->baseUrl = $params['baseUrl'] ?? null;
$this->apiKey = $params['apiKey'] ?? null;
$this->prompts = $params['prompts'] ?? [];
}

public function getSource(): ?string
{
return $this->source;
}

public function getOrgId(): ?string
{
return $this->orgId;
}

public function getProjectId(): ?string
{
return $this->projectId;
}

public function getApiVersion(): ?string
{
return $this->apiVersion;
}

public function getDeploymentId(): ?string
{
return $this->deploymentId;
}

public function getBaseUrl(): ?string
{
return $this->baseUrl;
}

public function getApiKey(): ?string
{
return $this->apiKey;
}

/**
* @return array{system?: string, searchDescription?: string, searchQParam?: string, searchIndexUidParam?: string}
*/
public function getPrompts(): array
{
return $this->prompts;
}

public function toArray(): array
{
return [
'source' => $this->source,
'orgId' => $this->orgId,
'projectId' => $this->projectId,
'apiVersion' => $this->apiVersion,
'deploymentId' => $this->deploymentId,
'baseUrl' => $this->baseUrl,
'apiKey' => $this->apiKey,
'prompts' => $this->prompts,
];
}
}
59 changes: 59 additions & 0 deletions src/Contracts/ChatWorkspacesResults.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

namespace Meilisearch\Contracts;

class ChatWorkspacesResults extends Data
{
private int $offset;
private int $limit;
private int $total;

public function __construct(array $params)
{
parent::__construct($params['results'] ?? []);

$this->offset = $params['offset'];
$this->limit = $params['limit'];
$this->total = $params['total'] ?? 0;
}

/**
* @return array<int, array{uid: string}>
*/
public function getResults(): array
{
return $this->data;
}

public function getOffset(): int
{
return $this->offset;
}

public function getLimit(): int
{
return $this->limit;
}

public function getTotal(): int
{
return $this->total;
}

public function toArray(): array
{
return [
'results' => $this->data,
'offset' => $this->offset,
'limit' => $this->limit,
'total' => $this->total,
];
}

public function count(): int
{
return \count($this->data);
}
}
6 changes: 6 additions & 0 deletions src/Contracts/Http.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,10 @@ public function patch(string $path, $body = null, array $query = []);
* @throws JsonDecodingException
*/
public function delete(string $path, array $query = []);

/**
* @throws ApiException
* @throws JsonEncodingException
*/
public function postStream(string $path, $body = null, array $query = []): \Psr\Http\Message\StreamInterface;
}
37 changes: 37 additions & 0 deletions src/Endpoints/ChatWorkspaces.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Meilisearch\Endpoints;

use Meilisearch\Contracts\ChatWorkspacesResults;
use Meilisearch\Contracts\Endpoint;
use Meilisearch\Contracts\Http;
use Meilisearch\Endpoints\Delegates\HandlesChatWorkspaceSettings;

class ChatWorkspaces extends Endpoint
{
use HandlesChatWorkspaceSettings;

protected const PATH = '/chats';

private ?string $workspaceName;

public function __construct(Http $http, ?string $workspaceName = null)
{
$this->workspaceName = $workspaceName;
parent::__construct($http);
}

public function listWorkspaces(): ChatWorkspacesResults
{
$response = $this->http->get(self::PATH);

return new ChatWorkspacesResults($response);
}

public function workspace(string $workspaceName): self
{
return new self($this->http, $workspaceName);
}
}
81 changes: 81 additions & 0 deletions src/Endpoints/Delegates/HandlesChatWorkspaceSettings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php

declare(strict_types=1);

namespace Meilisearch\Endpoints\Delegates;

use Meilisearch\Contracts\ChatWorkspaceSettings;

trait HandlesChatWorkspaceSettings
{
/**
* Get the current settings for this chat workspace.
*/
public function getSettings(): ChatWorkspaceSettings
{
if (null === $this->workspaceName) {
throw new \InvalidArgumentException('Workspace name is required to get settings');
}

$response = $this->http->get('/chats/'.$this->workspaceName.'/settings');

return new ChatWorkspaceSettings($response);
}

/**
* Update the settings for this chat workspace.
*
* @param array{
* source?: 'openAi'|'azureOpenAi'|'mistral'|'gemini'|'vLlm',
* orgId?: string,
* projectId?: string,
* apiVersion?: string,
* deploymentId?: string,
* baseUrl?: string,
* apiKey?: string,
* prompts?: array<string, string>
* } $settings
*/
public function updateSettings(array $settings): ChatWorkspaceSettings
{
if (null === $this->workspaceName) {
throw new \InvalidArgumentException('Workspace name is required to update settings');
}

$response = $this->http->patch('/chats/'.$this->workspaceName.'/settings', $settings);

return new ChatWorkspaceSettings($response);
}

/**
* Reset the settings for this chat workspace to default values.
*/
public function resetSettings(): ChatWorkspaceSettings
{
if (null === $this->workspaceName) {
throw new \InvalidArgumentException('Workspace name is required to reset settings');
}

$response = $this->http->delete('/chats/'.$this->workspaceName.'/settings');

return new ChatWorkspaceSettings($response);
}

/**
* Create a streaming chat completion using OpenAI-compatible API.
*
* @param array{
* model: string,
* messages: array<array{role: string, content: string}>,
* stream: bool
* } $options The request body for the chat completion
*/
public function streamCompletion(array $options): \Psr\Http\Message\StreamInterface
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But \Psr\Http\Message\StreamInterface is still not imported, right? :)

Copy link
Collaborator Author

@Strift Strift Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh, sorry, I missed that one 😅

Updated the code!

{
if (null === $this->workspaceName) {
throw new \InvalidArgumentException('Workspace name is required for chat completion');
}

return $this->http->postStream('/chats/'.$this->workspaceName.'/chat/completions', $options);
}
}
29 changes: 29 additions & 0 deletions src/Endpoints/Delegates/HandlesChatWorkspaces.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Meilisearch\Endpoints\Delegates;

use Meilisearch\Contracts\ChatWorkspacesResults;
use Meilisearch\Endpoints\ChatWorkspaces;

trait HandlesChatWorkspaces
{
public ChatWorkspaces $chats;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why public?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to design a fluent API and then got lost in refactoring 😅 I fixed this now


/**
* List all chat workspaces.
*/
public function getChatWorkspaces(): ChatWorkspacesResults
{
return $this->chats->listWorkspaces();
}

/**
* Get a specific chat workspace instance.
*/
public function chatWorkspace(string $workspaceName): ChatWorkspaces
{
return $this->chats->workspace($workspaceName);
}
}
Loading
Loading