Search by

adams100111 / typesafe-laravel

adams100111

Laravel integration for adams100111/typesafe-php — config, a facade, and a transport on Laravel's HTTP client so Http::fake() works in your tests. Unofficial; not affiliated with TypeSafe.

Package info

github.com/adams100111/typesafe-laravel

pkg:composer/adams100111/typesafe-laravel

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-09-21 15:53 UTC

This package is auto-updated.

Last update: 2026-09-21 17:27:16 UTC


README

CI

Laravel integration for adams100111/typesafe-php, a client for TypeSafe's System One API (Jev), which returns typed judgements — a probability, a choice, a score — instead of generated text.

Unofficial. A community package, not affiliated with, endorsed by, or supported by TypeSafe.

composer require adams100111/typesafe-laravel

Requires PHP 8.2+ and Laravel 12 or 13. The service provider and TypeSafe facade are auto-discovered.

Setup

TYPESAFE_API_KEY=your-key

Then confirm the key works:

php artisan typesafe:models

To customise, publish the config:

php artisan vendor:publish --tag=typesafe-config

Usage

use Adams100111\TypeSafe\Laravel\Facades\TypeSafe;
use Adams100111\TypeSafe\Question\Question;

$result = TypeSafe::systemOne(
    state: ['ticket' => $ticket->body],
    questions: [
        'refund'  => Question::noul('Does `ticket` ask for a refund?'),
        'team'    => Question::choice('Which team should handle `ticket`?', [
            'billing'   => 'Payments, refunds and invoices.',
            'technical' => 'Bugs, errors and outages.',
        ]),
        'urgency' => Question::score('How urgent is `ticket`?', [
            'Routine — can wait days.',
            'Soon — should be handled today.',
            'Now — the customer is losing money.',
        ]),
    ],
);

if ($result->noul('refund') > 0.8) {
    $ticket->assignTo($result->choice('team')->choice);
}

Or inject the client:

use Adams100111\TypeSafe\TypeSafeClient;

public function __construct(private TypeSafeClient $typesafe) {}

The question builders, answer types, retry behaviour and exceptions are documented in the core package README.

Testing your application

Requests go through Laravel's HTTP client, so Http::fake() intercepts them — no live calls, no custom mocks:

use Illuminate\Support\Facades\Http;

Http::fake([
    'api.typesafe.ai/*' => Http::response([
        'model'   => 'jev-1.13.0',
        'answers' => ['refund' => ['type' => 'noul', 'noul' => 0.94]],
        'usage'   => ['input_tokens' => 120, 'output_tokens' => 0],
    ]),
]);

// …exercise your code…

Http::assertSent(fn ($request) => str_contains($request->url(), '/v1/systemone'));

Failures fake the same way — Http::response([...], 429) raises RateLimitException, 401 raises AuthenticationException — so you can test your error handling too.

Configuration

Key Env Default
api_key TYPESAFE_API_KEY
base_url TYPESAFE_BASE_URL https://api.typesafe.ai
default_model TYPESAFE_DEFAULT_MODEL jev-latest
timeout_ms TYPESAFE_TIMEOUT_MS 10000, per attempt
retry.max_retries TYPESAFE_MAX_RETRIES 2
transport TYPESAFE_TRANSPORT laravel
log_channel TYPESAFE_LOG_CHANNEL none

The key is only checked when the client is first used. An application with the package installed but no key configured still boots; resolving the client then fails with a message naming TYPESAFE_API_KEY.

Pin a versioned model once you have tuned thresholds — jev-latest moves when TypeSafe ships a release:

TYPESAFE_DEFAULT_MODEL=jev-1.13.0

Transport

laravel (the default) sends through Laravel's HTTP client — Http::fake() works, global HTTP middleware applies, and requests appear in Telescope. curl uses the core package's own cURL transport and bypasses Laravel's HTTP stack.

Retries are always done by the client, never by Laravel's ->retry(), so they never compound.

Logging

Set TYPESAFE_LOG_CHANNEL to a channel name. info records one line per attempt; debug adds the request body — your state — so keep the channel above debug if that is sensitive. The Authorization header is redacted at every level.

Using it responsibly

The answers are calibrated probabilities, not certainties.

  • Don't gate on it. The model is self-consistent but not bit-deterministic; an answer near a threshold can cross it between identical runs. Route low-confidence answers to a person rather than acting on them.
  • Validate thresholds on your own labelled data, by confidence band, before relying on them.

Supported versions

PHP 8.2, 8.3, 8.4
Laravel 12, 13

Laravel 10 and 11 are not supported. Both are past their security-fix window, and every Laravel 11 release now carries unpatched security advisories that Composer refuses to install by default.

License

MIT