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
11 changes: 5 additions & 6 deletions .github/workflows/doctum.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,11 @@ jobs:
run: |
corepack enable
corepack prepare pnpm@12.10.1 --activate
pnpm config set ignore-workspace-root-check true
pnpm --version

- name: Deploy
uses: cloudflare/wrangler-action@953926a2e2182532811c01a25e53647d93bf07c0 # v4.1.3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy doctum/build --project-name=${{ secrets.CLOUDFLARE_PAGE_PROJECT_NAME }}
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_PAGE_PROJECT_NAME: ${{ secrets.CLOUDFLARE_PAGE_PROJECT_NAME }}
run: pnpm dlx wrangler@4 pages deploy doctum/build --project-name="$CLOUDFLARE_PAGE_PROJECT_NAME"
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ Build complete, long-term solutions, not MVPs or local workarounds. A broad chan
- **Use Laravel observer conventions** — place Eloquent observers in a top-level `Observers/` directory. Register model-specific observers with `#[ObservedBy(...)]`; use `observe()` only for dynamic registration or observers supplied automatically by a reusable concern.
- **Use attributed local scopes** — define local Eloquent query scopes as protected methods marked with `#[Scope]`, rather than legacy public `scopeFoo()` methods. Use separate scope classes only for genuine global scopes.
- **No class docblocks unless warranted** — only add a class-level docblock if something unusual or complex needs explanation: purpose, architectural role, usage patterns. Never write one that inventories the class — trait lists, method summaries, "registers X, configures Y" — that duplicates the members' own docblocks and goes stale. Method docblocks (title only, Laravel-style, imperative mood: "Return", not "Returns") are always added, except on test methods, whether identified by a test name prefix or PHPUnit’s `#[Test]` attribute. A body can accompany the title for complex methods that need further explanation.
- **Add comments only where they're genuinely useful** (required Laravel-style method title docblocks and config section comment blocks still apply) — a short WHY for logic that isn't obvious from reading the code, the reason behind a bug fix, or logic that's coupled to code in other files and hard to understand in isolation. Avoid unnecessary code comments; don't comment what the code does, and don't annotate framework divergences, routine casts, or type normalizations.
- **Add comments only where they're genuinely useful** (required Laravel-style method title docblocks and config section comment blocks still apply) — a short WHY for logic that isn't obvious from reading the code, the reason behind a bug fix, or logic that's coupled to code in other files and hard to understand in isolation. Avoid unnecessary code comments; don't comment what the code does, and don't annotate framework divergences, routine casts, or type normalizations. When reconciling upstream changes, add missing explanations for non-obvious Hypervel behavior being retained, so future syncs can understand why it exists.
- **Don't make classes final by default** — keep classes open; add `final` only when it protects a real invariant or avoids a concrete framework/API problem, e.g. immutability, coroutine-safety, or a security guarantee.
- **Place methods logically, not at the end** — group new methods with related ones (getters with getters, setters with setters). Two exceptions: preserve upstream order when merging ported code (see Porting rules), and `flushState()` has its own placement rule (see Static state and test cleanup).
- **Only extract methods when justified** — extract only when the logic is complex enough to benefit from a name, it's likely to be reused, or two or more methods call it. Don't extract a simple one-liner with a single caller.
Expand Down
6 changes: 3 additions & 3 deletions dogfood/ai/workbench/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/ai/src/Classification.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ class Classification
/**
* Create a new pending classification for the given state.
*
* @param array<string, mixed>|string $state
* @param array<int, File|UploadedFile> $attachments
* @param array<array-key, mixed>|string $state
* @param array<int|string, File|UploadedFile> $attachments
*
* @throws InvalidArgumentException if the state is blank
*/
Expand Down
4 changes: 2 additions & 2 deletions src/ai/src/Contracts/Gateway/ClassificationGateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ interface ClassificationGateway
/**
* Answer the given questions about the state.
*
* @param array<string, mixed>|string $state
* @param array<array-key, mixed>|string $state
* @param array<string, Question> $questions
* @param array<string, mixed> $providerOptions
* @param array<int, File|UploadedFile> $attachments
* @param array<int|string, File|UploadedFile> $attachments
*/
public function classify(
ClassificationProvider $provider,
Expand Down
4 changes: 2 additions & 2 deletions src/ai/src/Contracts/Providers/ClassificationProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ interface ClassificationProvider extends Provider
/**
* Answer the given questions about the state.
*
* @param array<string, mixed>|string $state
* @param array<array-key, mixed>|string $state
* @param array<string, Question> $questions
* @param array<string, mixed> $providerOptions
* @param array<int, File|UploadedFile> $attachments
* @param array<int|string, File|UploadedFile> $attachments
*/
public function classify(string|array $state, array $questions, ?string $model = null, int $timeout = 30, array $providerOptions = [], array $attachments = []): ClassificationResponse;

Expand Down
23 changes: 23 additions & 0 deletions src/ai/src/Events/AddingFileToStoreFailed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Hypervel\Ai\Events;

use Hypervel\Ai\Contracts\Providers\Provider;
use Throwable;

class AddingFileToStoreFailed
{
/**
* Create an event for a failed attempt to add a file to a store.
*/
public function __construct(
public string $invocationId,
public Provider $provider,
public string $storeId,
public string $fileId,
public Throwable $exception,
) {
}
}
27 changes: 27 additions & 0 deletions src/ai/src/Events/AudioFailed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Hypervel\Ai\Events;

use Hypervel\Ai\Contracts\Providers\Provider;
use Hypervel\Ai\Prompts\AudioPrompt;
use Throwable;

/**
* Dispatched once per failed attempt, including attempts failover recovers from.
*/
class AudioFailed
{
/**
* Create an event for a failed audio generation attempt.
*/
public function __construct(
public string $invocationId,
public Provider $provider,
public string $model,
public AudioPrompt $prompt,
public Throwable $exception,
) {
}
}
3 changes: 3 additions & 0 deletions src/ai/src/Events/ClassificationFailed.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
use Hypervel\Ai\Prompts\ClassificationPrompt;
use Throwable;

/**
* Dispatched once per failed attempt, including attempts failover recovers from.
*/
class ClassificationFailed
{
/**
Expand Down
27 changes: 27 additions & 0 deletions src/ai/src/Events/CreatingStoreFailed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Hypervel\Ai\Events;

use DateInterval;
use Hypervel\Ai\Contracts\Providers\Provider;
use Hypervel\Support\Collection;
use Throwable;

class CreatingStoreFailed
{
/**
* Create an event for a failed store creation.
*/
public function __construct(
public string $invocationId,
public Provider $provider,
public string $name,
public ?string $description,
public Collection $fileIds,
public ?DateInterval $expiresWhenIdleFor,
public Throwable $exception,
) {
}
}
3 changes: 3 additions & 0 deletions src/ai/src/Events/EmbeddingsFailed.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
use Hypervel\Ai\Prompts\EmbeddingsPrompt;
use Throwable;

/**
* Dispatched once per failed attempt, including attempts failover recovers from.
*/
class EmbeddingsFailed
{
/**
Expand Down
27 changes: 27 additions & 0 deletions src/ai/src/Events/ImageFailed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Hypervel\Ai\Events;

use Hypervel\Ai\Contracts\Providers\Provider;
use Hypervel\Ai\Prompts\ImagePrompt;
use Throwable;

/**
* Dispatched once per failed attempt, including attempts failover recovers from.
*/
class ImageFailed
{
/**
* Create an event for a failed image generation attempt.
*/
public function __construct(
public string $invocationId,
public Provider $provider,
public string $model,
public ImagePrompt $prompt,
public Throwable $exception,
) {
}
}
23 changes: 23 additions & 0 deletions src/ai/src/Events/RemovingFileFromStoreFailed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Hypervel\Ai\Events;

use Hypervel\Ai\Contracts\Providers\Provider;
use Throwable;

class RemovingFileFromStoreFailed
{
/**
* Create an event for a failed attempt to remove a file from a store.
*/
public function __construct(
public string $invocationId,
public Provider $provider,
public string $storeId,
public string $documentId,
public Throwable $exception,
) {
}
}
27 changes: 27 additions & 0 deletions src/ai/src/Events/RerankingFailed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Hypervel\Ai\Events;

use Hypervel\Ai\Contracts\Providers\Provider;
use Hypervel\Ai\Prompts\RerankingPrompt;
use Throwable;

/**
* Dispatched once per failed attempt, including attempts failover recovers from.
*/
class RerankingFailed
{
/**
* Create an event for a failed reranking attempt.
*/
public function __construct(
public string $invocationId,
public Provider $provider,
public string $model,
public RerankingPrompt $prompt,
public Throwable $exception,
) {
}
}
23 changes: 23 additions & 0 deletions src/ai/src/Events/StoringFileFailed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Hypervel\Ai\Events;

use Hypervel\Ai\Contracts\Files\StorableFile;
use Hypervel\Ai\Contracts\Providers\Provider;
use Throwable;

class StoringFileFailed
{
/**
* Create an event for a failed file upload.
*/
public function __construct(
public string $invocationId,
public Provider $provider,
public StorableFile $file,
public Throwable $exception,
) {
}
}
27 changes: 27 additions & 0 deletions src/ai/src/Events/TranscriptionFailed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Hypervel\Ai\Events;

use Hypervel\Ai\Contracts\Providers\Provider;
use Hypervel\Ai\Prompts\TranscriptionPrompt;
use Throwable;

/**
* Dispatched once per failed attempt, including attempts failover recovers from.
*/
class TranscriptionFailed
{
/**
* Create an event for a failed transcription attempt.
*/
public function __construct(
public string $invocationId,
public Provider $provider,
public string $model,
public TranscriptionPrompt $prompt,
public Throwable $exception,
) {
}
}
12 changes: 7 additions & 5 deletions src/ai/src/Gateway/Anthropic/AnthropicFileGateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Hypervel\Ai\Contracts\Providers\FileProvider;
use Hypervel\Ai\Enums\Lab;
use Hypervel\Ai\Gateway\Anthropic\Concerns\CreatesAnthropicClient;
use Hypervel\Ai\Gateway\Concerns\EncodesResourceIds;
use Hypervel\Ai\Gateway\Concerns\HandlesFailoverErrors;
use Hypervel\Ai\Gateway\Concerns\PreparesStorableFiles;
use Hypervel\Ai\Providers\Provider;
Expand All @@ -19,6 +20,7 @@
class AnthropicFileGateway implements FileGateway
{
use CreatesAnthropicClient;
use EncodesResourceIds;
use HandlesFailoverErrors;
use PreparesStorableFiles;

Expand All @@ -30,13 +32,13 @@ public function getFile(FileProvider $provider, string $fileId): FileResponse
/** @var FileProvider&Provider $provider */
$response = $this->withErrorHandling(
$provider->name(),
fn () => $this->client($provider)->get("files/{$fileId}"),
fn () => $this->client($provider)->get("files/{$this->resourceId($fileId)}"),
);

return new FileResponse(
return (new FileResponse(
id: $response->json('id'),
mimeType: $response->json('mime_type'),
);
))->withRawResponse($response);
}

/**
Expand All @@ -60,7 +62,7 @@ public function putFile(
->post('files', $providerOptions),
);

return new StoredFileResponse($response->json('id'));
return (new StoredFileResponse($response->json('id')))->withRawResponse($response);
}

/**
Expand All @@ -71,7 +73,7 @@ public function deleteFile(FileProvider $provider, string $fileId): void
/** @var FileProvider&Provider $provider */
$this->withErrorHandling(
$provider->name(),
fn () => $this->client($provider)->delete("files/{$fileId}"),
fn () => $this->client($provider)->delete("files/{$this->resourceId($fileId)}"),
);
}

Expand Down
Loading
Loading