PHP code example of fluffydiscord / honkers-sdk

1. Go to this page and download the library: Download fluffydiscord/honkers-sdk library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

fluffydiscord / honkers-sdk example snippets


use FluffyDiscord\Honkers\Contract\ChatbotToolInterface;
use FluffyDiscord\Honkers\DTO\ContentItem;
use FluffyDiscord\Honkers\DTO\ToolCallContext;
use FluffyDiscord\Honkers\DTO\ToolDefinition;
use FluffyDiscord\Honkers\DTO\ToolResult;

class GreetTool implements ChatbotToolInterface
{
    public function getDefinition(): ToolDefinition
    {
        return new ToolDefinition('greet', 'app.chatbot.greet.description');
    }

    public function getArgumentsClass(): string
    {
        return GreetArguments::class;
    }

    public function execute(object $arguments, ToolCallContext $context): ToolResult
    {
        return new ToolResult([new ContentItem('Hello ' . $arguments->name)]);
    }
}

use Symfony\Component\Validator\Constraints as Assert;

class GreetArguments
{
    public function __construct(
        #[Assert\NotBlank]
        #[Assert\Length(max: 64)]
        public string $name = '',
    ) {
    }
}

// $generator->generate(GreetArguments::class)
// => ['type' => 'object',
//     'properties' => ['name' => ['type' => 'string', 'maxLength' => 64]],
//     '

$tool = $toolRegistry->get('greet');   // null when unknown
foreach ($toolRegistry->all() as $tool) { /* ... */ }

use FluffyDiscord\Honkers\Registry\ToolRegistry;
use FluffyDiscord\Honkers\Registry\DataSourceRegistry;
use FluffyDiscord\Honkers\Registry\ToolChoiceLoaderRegistry;
use FluffyDiscord\Honkers\Schema\ArgumentsSchemaGenerator;
use Symfony\Component\Validator\Validation;

$tools   = [new GreetTool()];   // ChatbotToolInterface, keyed at runtime by getDefinition()->name
$sources = [];                  // ChatbotDataSourceInterface
$loaders = [];                  // ToolChoiceLoaderInterface, matched by class

$toolRegistry   = new ToolRegistry($tools);
$sourceRegistry = new DataSourceRegistry($sources);
$schema         = new ArgumentsSchemaGenerator(new ToolChoiceLoaderRegistry($loaders));
$validator      = Validation::createValidatorBuilder()->enableAttributeMapping()->getValidator();

$out = [];
foreach ($toolRegistry->all() as $tool) {
    $out[] = $tool->getDefinition()
        ->withInputSchema($schema->generate($tool->getArgumentsClass()))
        ->jsonSerialize();
}
echo json_encode(['tools' => $out]);

use FluffyDiscord\Honkers\DTO\ToolCallContext;
use FluffyDiscord\Honkers\DTO\Violation;
use FluffyDiscord\Honkers\Exception\ToolNotFoundException;
use FluffyDiscord\Honkers\Exception\ArgumentsValidationException;

$tool = $toolRegistry->get($name) ?? throw new ToolNotFoundException($name);
$body = json_decode($rawRequestBody, true);

// Turn the arguments array into the typed DTO. Any deserializer works;
// symfony/serializer is what the bundles use (not an SDK dependency).
$arguments = $serializer->denormalize($body['arguments'] ?? [], $tool->getArgumentsClass());

$violations = [];
foreach ($validator->validate($arguments) as $violation) {
    $violations[] = new Violation($violation->getPropertyPath(), (string) $violation->getMessage());
}
if ($violations !== []) {
    throw new ArgumentsValidationException($violations);   // -> 422 envelope
}

$context = new ToolCallContext(
    $body['context']['conversationId'],   // must be a UUID
    $body['context']['locale'],           // an ICU locale, e.g. cs_CZ
    $body['context']['channelCode'] ?? null,
);
echo json_encode($tool->execute($arguments, $context)->jsonSerialize());

use FluffyDiscord\Honkers\DTO\SourceQuery;
use FluffyDiscord\Honkers\Exception\SourceNotFoundException;

// list
$out = [];
foreach ($sourceRegistry->all() as $source) {
    $out[] = $source->getDefinition()->jsonSerialize();
}
echo json_encode(['sources' => $out]);

// read: ?locale=cs_CZ&channel=&cursor=&ids[]=
$source = $sourceRegistry->get($name) ?? throw new SourceNotFoundException($name);
$query = new SourceQuery(
    locale: $_GET['locale'] ?? '',
    channel: $_GET['channel'] ?? null,
    cursor: $_GET['cursor'] ?? null,
    ids: $_GET['ids'] ?? null,
);
echo json_encode($source->getDocuments($query)->jsonSerialize());

use FluffyDiscord\Honkers\DTO\CatalogChange;
use FluffyDiscord\Honkers\Enum\CatalogSourceName;
use FluffyDiscord\Honkers\Ingest\CatalogIngestClient;

$client = new CatalogIngestClient(
    $psr18Client,     // Psr\Http\Client\ClientInterface
    $psr17Factory,    // Psr\Http\Message\RequestFactoryInterface
    $psr17Factory,    // Psr\Http\Message\StreamFactoryInterface
    'https://honkers.dev',
    $ingestSecret,
);

$change = new CatalogChange(CatalogSourceName::Products, 'cs_CZ', ['CLIPPER-01', 'CLIPPER-02']);
$result = $client->send($siteKey, $change);

if ($result->isThrottled()) {
    // backend is busy — retry after $result->retryAfterSeconds
}
foreach ($result->jobs as $job) {
    // $job->externalId, $job->jobId, $job->status (CatalogJobStatus), $job->violation
}

use FluffyDiscord\Honkers\Widget\WidgetSnippet;

echo (new WidgetSnippet())->render(
    'https://honkers.dev',  // backend origin
    $siteKey,                            // public site key
    $cdnUrl,                             // optional; '' → {backend}/widget/v1/chat.js
    $locale,                             // optional; '' → the browser detects it
);