Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ final class Config {
public function __construct(
public readonly string $projectApiKey,
public readonly Consumer $consumer,
public readonly string $agentName = 'Roundtable',
public readonly string $agentName = 'Clara',
public readonly ?string $agentAvatarUrl = null,
public readonly int $timeoutSeconds = 30,
public readonly ?string $hubBaseUrl = null,
Expand Down
12 changes: 12 additions & 0 deletions src/Consumer.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,16 @@ public function metadata(): ?string;
* @return string|null The version string, or null.
*/
public function clientVersion(): ?string;

/**
* The install's licence material, verified server-side by the hub.
*
* Sent with every chat turn as the `licence` body field. Hubs with licence
* verification enabled refuse chat turns without a valid payload; return null
* when the consumer has no licence system (the hub project must then run with
* verification disabled).
*
* @return array{key: string, activation_id: string}|null The licence material, or null.
*/
public function licence(): ?array;
}
14 changes: 14 additions & 0 deletions src/HubClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,7 @@ private function buildBody( string $message, bool $isFirstTurn, ?string $trigger
'subject_id' => $this->config->consumer->subjectId(),
),
$this->triggerField( $trigger ),
$this->licenceField(),
);
if ( $isFirstTurn ) {
$metadata = $this->config->consumer->metadata();
Expand Down Expand Up @@ -653,4 +654,17 @@ private function triggerField( ?string $trigger ): array {
}
return array( 'trigger' => $trigger );
}

/**
* Optional `licence` field for a chat-turn body, when the consumer provides one.
*
* @return array<string, array{key: string, activation_id: string}> Zero or one keyed entry.
*/
private function licenceField(): array {
$licence = $this->config->consumer->licence();
if ( null === $licence ) {
return array();
}
return array( 'licence' => $licence );
}
}
2 changes: 1 addition & 1 deletion tests/ConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public function test_exposes_its_values_with_defaults(): void

self::assertSame('pk_live_123', $config->projectApiKey);
self::assertSame($consumer, $config->consumer);
self::assertSame('Roundtable', $config->agentName);
self::assertSame('Clara', $config->agentName);
self::assertNull($config->agentAvatarUrl);
self::assertSame(30, $config->timeoutSeconds);
self::assertNull($config->hubBaseUrl);
Expand Down
23 changes: 23 additions & 0 deletions tests/HubClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,29 @@ public function test_first_turn_body_carries_metadata_and_client_version(): void
self::assertSame('1.2.3', $body['client_version']);
}

public function test_body_carries_licence_on_every_turn_when_consumer_provides_one(): void
{
$transport = new FakeTransport(200, '');
$licence = array('key' => 'lic-1', 'activation_id' => 'act-1');
$client = new HubClient($this->config(new FakeConsumer(true, 'subj', null, null, $licence)), $transport);

$client->postMessage('chat-1', 'hello', false);

$body = \json_decode((string) $transport->lastBody, true);
self::assertSame($licence, $body['licence']);
}

public function test_body_omits_licence_when_consumer_has_none(): void
{
$transport = new FakeTransport(200, '');
$client = new HubClient($this->config(new FakeConsumer()), $transport);

$client->postMessage('chat-1', 'hello', false);

$body = \json_decode((string) $transport->lastBody, true);
self::assertArrayNotHasKey('licence', $body);
}

public function test_later_turn_body_omits_metadata_and_client_version(): void
{
$transport = new FakeTransport(200, '');
Expand Down
1 change: 1 addition & 0 deletions tests/Rest/GateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public function isUserAllowed(): bool { return $this->allowed; }
public function subjectId(): string { return 's'; }
public function metadata(): ?string { return null; }
public function clientVersion(): ?string { return null; }
public function licence(): ?array { return null; }
};
return new Config( 'pk_secret', $consumer );
}
Expand Down
1 change: 1 addition & 0 deletions tests/RoundtableMountTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public function isUserAllowed(): bool { return true; }
public function subjectId(): string { return 's'; }
public function metadata(): ?string { return null; }
public function clientVersion(): ?string { return null; }
public function licence(): ?array { return null; }
};
$added = array();
Functions\when( 'add_action' )->alias(
Expand Down
1 change: 1 addition & 0 deletions tests/SessionControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public function isUserAllowed(): bool { return true; }
public function subjectId(): string { return 's'; }
public function metadata(): ?string { return null; }
public function clientVersion(): ?string { return null; }
public function licence(): ?array { return null; }
};
return new SessionController( new Config( 'pk_secret', $consumer ) );
}
Expand Down
4 changes: 4 additions & 0 deletions tests/Support/FakeConsumer.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,19 @@
/** A configurable Consumer test double. */
final class FakeConsumer implements Consumer
{
/** @param array{key: string, activation_id: string}|null $licence */
public function __construct(
private bool $allowed = true,
private string $subjectId = 'subject-1',
private ?string $metadata = null,
private ?string $clientVersion = null,
private ?array $licence = null,
) {}

public function isUserAllowed(): bool { return $this->allowed; }
public function subjectId(): string { return $this->subjectId; }
public function metadata(): ?string { return $this->metadata; }
public function clientVersion(): ?string { return $this->clientVersion; }
/** @return array{key: string, activation_id: string}|null */
public function licence(): ?array { return $this->licence; }
}
Loading