Skip to content

Commit e3e35cc

Browse files
committed
Initial release of the Datalumo PHP client.
Covers Me, Pages, Widgets, Conversations, Identity, and streaming against the current API.
0 parents  commit e3e35cc

44 files changed

Lines changed: 2065 additions & 0 deletions

Some content is hidden

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

.github/workflows/tests.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
branches: [main, master]
6+
pull_request:
7+
8+
jobs:
9+
tests:
10+
runs-on: ubuntu-latest
11+
strategy:
12+
fail-fast: false
13+
matrix:
14+
php: ['8.2', '8.3', '8.4']
15+
16+
name: PHP ${{ matrix.php }}
17+
18+
steps:
19+
- uses: actions/checkout@v4
20+
21+
- name: Setup PHP
22+
uses: shivammathur/setup-php@v2
23+
with:
24+
php-version: ${{ matrix.php }}
25+
coverage: none
26+
tools: composer:v2
27+
28+
- name: Install dependencies
29+
run: composer install --prefer-dist --no-interaction --no-progress
30+
31+
- name: Run tests
32+
run: vendor/bin/pest

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/vendor/
2+
/composer.lock
3+
/.phpunit.cache/
4+
/.phpunit.result.cache
5+
/.idea/
6+
/.vscode/
7+
*.swp
8+
.DS_Store

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) Datalumo
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# datalumo/php
2+
3+
PHP client for the [Datalumo](https://datalumo.app) API.
4+
5+
## Install
6+
7+
```bash
8+
composer require datalumo/php
9+
```
10+
11+
Requires PHP 8.2+.
12+
13+
## Quick start
14+
15+
```php
16+
use Datalumo\Client;
17+
18+
$client = new Client(
19+
token: getenv('DATALUMO_TOKEN'),
20+
organisation: getenv('DATALUMO_ORG'), // organisation public id, not the slug
21+
);
22+
23+
// Confirm the token and list sources
24+
$me = $client->me()->get();
25+
26+
// Push a page (indexing is asynchronous)
27+
$client->pages('docs')->upsert([
28+
'external_id' => 'post-42',
29+
'name' => 'Hello',
30+
'content' => '# Hello',
31+
'content_mime' => 'text/markdown',
32+
'source_url' => 'https://example.com/hello',
33+
]);
34+
35+
// Search via a widget
36+
$result = $client->widgets($widgetId)->search([
37+
'query' => 'how does pricing work',
38+
'limit' => 5,
39+
]);
40+
41+
foreach ($result->data as $hit) {
42+
echo $hit->name;
43+
}
44+
```
45+
46+
Self-hosted:
47+
48+
```php
49+
$client = new Client(
50+
token: $token,
51+
organisation: $orgId,
52+
baseUrl: 'https://your-instance.example',
53+
);
54+
```
55+
56+
## Next steps
57+
58+
- [API docs](https://datalumo.app/docs)
59+
- Laravel package: [`datalumo/laravel`](https://github.com/datalumo/laravel)

composer.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"name": "datalumo/php",
3+
"description": "Official PHP client for the Datalumo API",
4+
"type": "library",
5+
"license": "MIT",
6+
"keywords": [
7+
"datalumo",
8+
"search",
9+
"ai",
10+
"sdk"
11+
],
12+
"authors": [
13+
{
14+
"name": "Datalumo",
15+
"homepage": "https://datalumo.app"
16+
}
17+
],
18+
"require": {
19+
"php": "^8.2",
20+
"guzzlehttp/guzzle": "^7.8",
21+
"psr/log": "^3.0"
22+
},
23+
"require-dev": {
24+
"laravel/pint": "^1.18",
25+
"mockery/mockery": "^1.6",
26+
"pestphp/pest": "^3.0"
27+
},
28+
"autoload": {
29+
"psr-4": {
30+
"Datalumo\\": "src/"
31+
}
32+
},
33+
"autoload-dev": {
34+
"psr-4": {
35+
"Datalumo\\Tests\\": "tests/"
36+
}
37+
},
38+
"scripts": {
39+
"test": "pest",
40+
"format": "pint"
41+
},
42+
"config": {
43+
"sort-packages": true,
44+
"allow-plugins": {
45+
"pestphp/pest-plugin": true
46+
}
47+
},
48+
"minimum-stability": "stable",
49+
"prefer-stable": true
50+
}

phpunit.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
4+
bootstrap="vendor/autoload.php"
5+
colors="true"
6+
cacheDirectory=".phpunit.cache"
7+
>
8+
<testsuites>
9+
<testsuite name="Datalumo PHP SDK">
10+
<directory>tests</directory>
11+
</testsuite>
12+
</testsuites>
13+
<source>
14+
<include>
15+
<directory>src</directory>
16+
</include>
17+
</source>
18+
</phpunit>

src/Client.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
namespace Datalumo;
4+
5+
use Datalumo\Resources\MeResource;
6+
use Datalumo\Resources\PagesResource;
7+
use Datalumo\Resources\WidgetsResource;
8+
9+
class Client
10+
{
11+
private HttpClient $http;
12+
13+
public function __construct(
14+
private readonly string $token,
15+
private readonly string $organisation,
16+
private readonly string $baseUrl = 'https://datalumo.app',
17+
?HttpClientOptions $options = null,
18+
) {
19+
$this->http = new HttpClient(
20+
baseUrl: $this->baseUrl,
21+
organisation: $this->organisation,
22+
token: $this->token,
23+
options: $options,
24+
);
25+
}
26+
27+
public function http(): HttpClient
28+
{
29+
return $this->http;
30+
}
31+
32+
public function organisation(): string
33+
{
34+
return $this->organisation;
35+
}
36+
37+
public function baseUrl(): string
38+
{
39+
return $this->baseUrl;
40+
}
41+
42+
public function me(): MeResource
43+
{
44+
return new MeResource($this->http);
45+
}
46+
47+
public function pages(string $source): PagesResource
48+
{
49+
return new PagesResource($this->http, $source);
50+
}
51+
52+
/** @param string $widget Widget public id only, not the org/widget embed key */
53+
public function widgets(string $widget): WidgetsResource
54+
{
55+
return new WidgetsResource($this->http, $widget);
56+
}
57+
}

src/Data/ChatReply.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Datalumo\Data;
4+
5+
final readonly class ChatReply
6+
{
7+
/**
8+
* @param list<SearchHit> $sources
9+
*/
10+
public function __construct(
11+
public string $text,
12+
public ?string $conversationId,
13+
public ?string $answerId,
14+
public array $sources,
15+
public string $sessionId,
16+
) {}
17+
18+
/**
19+
* @param array<string, mixed> $payload
20+
*/
21+
public static function fromArray(array $payload): self
22+
{
23+
$data = $payload['data'] ?? $payload;
24+
$sources = array_map(
25+
fn (array $hit) => SearchHit::fromArray($hit),
26+
$data['sources'] ?? [],
27+
);
28+
29+
return new self(
30+
text: (string) ($data['text'] ?? ''),
31+
conversationId: isset($data['conversation_id']) ? (string) $data['conversation_id'] : null,
32+
answerId: isset($data['answer_id']) ? (string) $data['answer_id'] : null,
33+
sources: $sources,
34+
sessionId: (string) ($payload['session_id'] ?? $data['session_id'] ?? ''),
35+
);
36+
}
37+
}

src/Data/Conversation.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Datalumo\Data;
4+
5+
final readonly class Conversation
6+
{
7+
public function __construct(
8+
public string $conversationId,
9+
public ?string $title,
10+
public bool $kept,
11+
public ?string $lastMessageAt,
12+
) {}
13+
14+
/**
15+
* @param array<string, mixed> $data
16+
*/
17+
public static function fromArray(array $data): self
18+
{
19+
return new self(
20+
conversationId: (string) ($data['conversation_id'] ?? ''),
21+
title: isset($data['title']) ? (string) $data['title'] : null,
22+
kept: (bool) ($data['kept'] ?? false),
23+
lastMessageAt: isset($data['last_message_at']) ? (string) $data['last_message_at'] : null,
24+
);
25+
}
26+
}

src/Data/ConversationDetail.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Datalumo\Data;
4+
5+
final readonly class ConversationDetail
6+
{
7+
/**
8+
* @param list<ConversationMessage> $messages
9+
*/
10+
public function __construct(
11+
public string $conversationId,
12+
public bool $kept,
13+
public array $messages,
14+
) {}
15+
16+
/**
17+
* @param array<string, mixed> $payload
18+
*/
19+
public static function fromArray(array $payload): self
20+
{
21+
$data = $payload['data'] ?? $payload;
22+
$messages = array_map(
23+
fn (array $message) => ConversationMessage::fromArray($message),
24+
$data['messages'] ?? [],
25+
);
26+
27+
return new self(
28+
conversationId: (string) ($data['conversation_id'] ?? ''),
29+
kept: (bool) ($data['kept'] ?? false),
30+
messages: $messages,
31+
);
32+
}
33+
}

0 commit comments

Comments
 (0)