v2.5.0
·
64 commits
to development
since this release
What's New
- Added configuration settings for file uploads, that allow administrators to specify allowed file types and maximum file sizes, enhancing security and control over user uploads. See the environment variables documentation for more details.
- Improved accessiblity of the frontend by adding ARIA attributes and improving keyboard navigation, making it easier for users with disabilities to use the application. Thanks to Thomas Orgeldinger for the tremendous help!
- Extended supported file formats for attachments: documents (PPTX, XLSX, HTML, Markdown, AsciiDoc, CSV, WebVTT) and additional image formats (SVG, TIFF, PSD, EPS, AI, BMP, ICO) are now handled via an image pre-processing pipeline using
rsvg-convertand ImageMagick — auto-detected from$PATHwhen available. Note: PostScript-based formats (EPS, AI, PS) requireghostscriptto be installed alongside ImageMagick. See the optional dependencies documentation for installation instructions. - Added support for the Kreuzberg open-source document extraction API as a new file converter option. Configure via
KREUZBERG_FILE_CONVERTER_API_URLin the.envfile. No API key is required. - All file access (attachments and avatars) is now securely proxied through the application via a dedicated storage proxy controller, with proper access control enforced for all file types and storage backends. Direct storage URLs are no longer exposed to clients.
- Drag-and-drop file upload now provides real-time visual feedback: files are classified as valid or invalid against the server-configured allowed MIME types before the upload begins, and the file picker's
acceptattribute is automatically populated to match. - We now have an official Contribution guide that provides detailed instructions and guidelines for contributing to the project, including coding standards, testing procedures, and how to submit pull requests. This should make it easier for new contributors to get started and ensure a consistent codebase.
- Introduced the External App (ExtApp) system, enabling third-party applications to integrate with HAWKI via an OAuth-like connection flow with cryptographic keypairs. Includes app user management, feature-level access control (e.g. AI in group chats), and a user-facing confirmation page. Manage apps via artisan commands:
ext-app:create,ext-app:list,ext-app:remove. Seeconfig/external_access.phpfor feature toggle configuration. - Added the SyncLog system for real-time synchronization of server-side state changes. Supports both incremental and full sync strategies with entity-specific handlers (rooms, messages, users, members, invitations, AI models, etc.). Provides a REST API endpoint and broadcasts events via WebSocket, enabling clients to stay in sync efficiently.
- Added User Keychain — a secure per-user storage system for cryptographic key material and configuration data. Supports symmetric, asymmetric, and hybrid crypto value types with dedicated Eloquent casts. Includes REST endpoints for managing keychain values.
- Added message threading support. Messages can now belong to threads via
thread_idandhas_threadcolumns. Thread parent tracking is handled automatically via event listeners. Existing messages are backfilled via migrations. - Added System Prompt management via
SystemPromptRepository. Supports multiple prompt types (DEFAULT, SUMMARY, IMPROVEMENT, NAME) with locale-aware resolution. - Added locale-aware AI model descriptions: administrators can now provide human-readable descriptions for each AI model in multiple languages. Users see descriptions in their preferred locale automatically via the new
/api/v1/ai-model-descriptionsendpoint. - Added AI model flags: models can now be tagged with status flags (e.g. experimental, deprecated) that carry a label, description, and color code for display in the frontend. Flags are managed server-side and exposed via
/api/v1/ai-model-flags. - Introduced the Frontend Migrations system — a structured mechanism for managing schema and data migrations on the client side. Applied migrations are tracked per user in the database, ensuring each migration runs exactly once across deployments. Exposed via
/api/v1/migrations. - HAWKI now ships a full JSON:API v1 REST API at
/api/hawki/v1. The API covers 20+ resource types — AI infrastructure (providers, models, tools, capabilities, MCP servers, model flags, model descriptions, system models, system prompts), collaborative chat (rooms, messages, members, attachments), user data (profiles, keychain values, frontend migrations), and external app integrations. All resources follow the JSON:API specification with relationship includes, pagination, and attribute-level authorization. A single connection bootstrap endpoint (GET /connections/hawki) provides the entire frontend initialization payload in one request: user identity, locale, WebSocket config, encryption salts, and any pending frontend migrations — eliminating the previous scatter of individual initialization requests. - Introduced the new Svelte-based chat composer UI — a fully rewritten message composition interface built with Svelte 5. It features a unified composer panel combining message input, model selector, tool menu, file attachments, sampling parameter controls, and a system prompt editor. The composer supports four interaction modes: default chat, threaded reply, message edit, and AI response regeneration. Each mode independently manages its own state snapshot, allowing seamless and reversible transitions between contexts.
- AI model responses can now render inline citations — sources are displayed as numbered chips in the message text, each linking to a source tile below the message with the favicon, domain, and title of the referenced page. Clicking a citation scrolls and highlights the corresponding tile.
- The message renderer now supports LaTeX math (inline
$...$and block```math ```), Mermaid diagrams (flowcharts, sequence diagrams, state machines, and more), and Monaco-powered syntax-highlighted code blocks, all rendered via worker threads to keep the UI responsive. Messages stream in with a typewriter effect while the AI is generating. External links show a URL preview tooltip with favicon and page title on hover. - Added support for four new AI provider types: Anthropic, AWS Bedrock, Deepseek, and OpenRouter. Administrators can configure any of these via the provider adapter system.
- The model picker now shows a real-time demand indicator (three-bar load meter: low / medium / high) and an online/offline status dot per model, giving users a clear picture of model availability and current load before sending a request.
- Models can now carry well-known flags visible in the model picker: descriptive tags such as open weights, eco-friendly, self-hosted, multi-modal, and strength indicators (creative writing, code generation, math, reasoning), as well as feature flags (prompt caching, response schema, streaming, sampling parameters, and reasoning level). This helps users choose the right model for their task at a glance.
- Introduced the Announcements system — administrators can post announcements that appear in the application UI. Announcements support flexible targeting (all users or a specific list), scheduled display windows (start and expiry dates), and a forced-display mode for critical notices. Whether a user has seen or accepted each announcement is tracked individually.
- Added an "Improve Message" feature: a Sparkles button in the composer sends the current draft to the AI for suggestions before sending, letting users refine their message without starting a new conversation.
- Chats can now be exported in four formats: PDF, Word (DOCX), CSV, and JSON. The export menu is accessible from the chat header.
Quality of Life
- AI Model errors will now be logged to the log file in addition to being printed to the screen, making it easier to debug issues in production.
- The
VITE_REVERB_*environment variables have been removed, as they are no longer used in the frontend. This simplifies the configuration and reduces potential confusion for users. The information about the connection will now be negotiated automatically. - Attachment file icons are now dynamically generated SVGs with per-extension colors, replacing the previous static PNG icons for PDF and DOCX. Any file type now shows a proper labeled icon.
- Cryptographic salts are now delivered via the frontend connection payload instead of individual network requests, reducing initial page load latency.
- The frontend translation system has been rewritten. Translations are now available via a unified
__()helper function, consistent with Laravel's backend translation API. - HAWKI's locale and settings panel are now also available on the login and gateway pages, enabling translated UI before a user is authenticated.
- Development workflow improvements: new
phpunit,phpstan,prettier, andphp-cs-fixertools are now integrated to make testing and code formatting easier. Runbin/env test allfor tests and static analysis, orbin/env style php/bin/env style jsfor code formatting. - CSRF tokens are now automatically included in response headers (
X-HAWKI-CSRF-TOKEN), allowing frontend applications to retrieve tokens without additional requests. - API responses now include sync log entries in a
_hawki_sync_logfield automatically, enabling reactive frontends to process state changes immediately without waiting for WebSocket messages. - AI model metadata (capabilities, pricing tiers, context limits, documentation links) is now automatically enriched from the LiteLLM API catalog on a 24-hour cache cycle, with a bundled static data store as a reliable fallback when the API is unavailable. Model information stays accurate without manual maintenance.
- Added health check infrastructure: quick checks (database connectivity) and deep checks (database, cache, Redis, storage) are now available for load balancer probes and monitoring integrations.
- New artisan commands for administrators and operators:
php artisan ai:check-statusupdates online/offline status for all models and MCP servers in one pass;php artisan ai:models:listlists all configured models;php artisan filestorage:converter:types:listprints the MIME types and extensions your active file converter accepts — useful for diagnosing upload rejections. - The sampling parameter panel now includes three quick presets — Creative, Balanced, and Precise — that set temperature and top_p in one click, with per-model defaults preserved when switching models.
- The composer textarea auto-sizes as you type, expanding up to 250 px before scrolling, so short messages don't feel lost in a large input box.
Bugfix
bin/env devnow no longer dies after 300 seconds, allowing for longer-running development sessions without interruption.- The last selected AI model is now automatically re-selected when the model list reloads, preserving the user's choice across page refreshes and model list updates.
- Fixed stream chunk processing to correctly handle partial data from AI providers, preventing garbled or truncated responses.
php artisan ai:tools:mcp:addnow uses the correct api key to fetch server information, removing the hardcoded api key for the HAWKI dev environment. Thanks to Raphael Fetzer for pointing out this issue!- The external API endpoint to HAWKI no longer throws an error if the
streamparameter is missing, improving the robustness of the API and allowing for more flexible usage. Thanks to willirath for pointing this out and providing a fix. - Fixed a typo in the session expiry message: "Your accound has been suspended." → "Your account has been suspended."
- Fixed a fatal error in the
PreventBackHistorymiddleware when processing streaming responses that do not support HTTP headers. - Removed the
/req/crypto/getServerSaltserver endpoint, which inadvertently exposed server-side environment variables. Cryptographic salts are now embedded in the frontend connection payload and never returned via a dedicated HTTP request.
Internals
- Refactoring of the "file converter" logic, improving the handling of file conversions and reducing potential errors. Also implemented a lot of logging in this area to make it easier to debug issues related to file conversions.
- Refactoring and code cleanup of the tool calling logic, improving readability and maintainability. The
ToolCallingClientnow properly validates that incoming requests contain a model; requests without a model are logged with a warning and passed through to the underlying client without tool calling support. - Inherited a lot of code from the
external-chatbranch, as preparation for V3 merge and to avoid merge conflicts later on. This also allows us to use the new "connection" logic to pass backend information to the frontend. - It is now possible to implement "custom file converters" using the "file_converter.converters" array in the configuration. This allows for more flexibility and extensibility in handling file conversions, as users can now easily add their own custom converters without modifying the core codebase. A new "class" property has been added to the converter configuration, which specifies the class that should be used for the converter. This class must implement the
FileConverterInterfaceand can be autoloaded using Composer's PSR-4 autoloading. - The
FileConverterFactoryhas been removed, to retrieve the converter simply ask for theFileConverterInterface, which will always provide you the currently configured converter. To determine if the converter is active (e.g. configured or not) check theisAvailable()method on the converter instance. - Complete overhaul of the storage layer with a new value-object-driven architecture. Key new types:
StoredFile,FileReference,StoredFileIdentifier,StoredFileCategory,FileCollection,FileType,PlainTextLanguageType. All storage service method signatures have changed — any custom code callingFileStorageServiceorAvatarStorageServicedirectly must be updated. - Every stored file now has a
.meta.jsonsidecar written alongside it, capturing original filename, MIME type, extracted content references, and creation timestamp. Files without a sidecar (pre-existing uploads) have their metadata generated retroactively on first access. - Attachment formatting for AI providers has been extracted into dedicated per-provider classes (
GoogleAttachmentFormatter,GwdgAttachmentFormatter,OllamaAttachmentFormatter,OpenAiAttachmentFormatter), replacing duplicated inline logic in each request converter. - The
AttachmentServiceandAttachmentFactoryhave been replaced by a leanerAttachmentRepositoryservice. Stored file cleanup on attachment deletion is now handled automatically via the newAttachmentDeletingmodel event and a dedicated event listener. - The
MessageHandlerFactoryhas been removed. Message handlers (PrivateMessageHandler,GroupMessageHandler) are now resolved via Laravel's service container. - Six new
JsonResourceclasses underHttp/Resources/Legacy/standardize JSON serialization for existing API endpoints, replacing manual inline array construction scattered across models and services. - A new
TranslationServiceProvideroverrides Laravel's built-in translation loader to merge HAWKI's own JSON language files on top of any Laravel fallback translations. Translation labels are now embedded in the frontend connection payload. - Added
RecursiveMergerutility (app/Utils/Arrays/) with configurable deep merge behaviour, including support for unsetting keys. Exposed asArr::mergeRecursive()macro. AiErrorResponsenow captures a stack trace at construction time and exposes it intoArray()whenapp.debugis enabled, making AI provider errors significantly easier to trace during development.- Event listeners in
app/Services/*/Listenersare now auto-discovered via a glob registered inbootstrap/app.php. ext-fileinfois now declared as a required PHP extension incomposer.json.- Introduced
AbstractCastableObject(App\Utils\Casts) — a foundational reflection-based utility for hydrating and serializing typed PHP objects from/to string arrays. Supports built-in type casting (int, float, bool, string, array), enums, dates, encrypted values, and custom casters via#[CastedValue]annotations. Serves as the base for the upcoming database-backed configuration layer (AbstractConfig). - Added phpstan for static analysis which should help catch potential bugs and improve code quality. Run
composer run stanto execute the static analysis checks. Currently NOT in the pipeline, because there are still some issues to fix, but we will get there eventually. - Refactored the
AiModeldata layer to use structured value objects (ModelCapabilities,ModelIoMethods,ModelParameters,ModelSettings,OnlineStatus,ModelDemand), replacing flat array structures. Model attributesinput,output,parameters,status,demand,capabilities, andsettingsare now cast to typed PHP objects. - AI tools and MCP servers are now database-backed Eloquent models (
AiTool,AiToolCapability,McpServer) with full JSON:API endpoints and authorization policies, replacing the previous static configuration approach. Usephp artisan ai:tools:syncto populate from config. - Refactored the frontend bootstrap into a six-stage pipeline (preparation → migration → early → main → late → finalization). Each stage supports pre/post hooks; within a stage, up to five tasks run concurrently via
ParallelAsyncWorkflow. The connection resource is fetched once at the preparation stage and shared as the authoritative source for locale, user info, and pending migrations for all subsequent stages. - Added
php artisan dev:ai:update-lite-llm-static-datacommand to refresh static LiteLLM model provider data from the upstream API. Available in local environments only. - Achieved 100% test coverage for
App\Utilsmodule with comprehensive PHPUnit tests for utility classes likeAssert,Arrays, andCastshelpers. - The model config files of
config/model_providers.phpandconfig/model_listsare now automatically copied to_docker_productionwhen a new release branch is created. - The
jquerylibrary has been removed from the frontend dependencies, as it is not used in the codebase. This reduces the overall bundle size and improves performance. - Update of all major frontend dependencies.
- Add
prettierandphp-cs-fixerconfigurations to enforce consistent code formatting across the codebase. Runbin/env style phporbin/env style jsto automatically format the code according to the defined standards. - Added
phpunitandphpstanto run tests and static analysis of the main application. Runbin/env test unitto execute the unit tests andbin/env test stanto run static analysis. Run all tests and checks withbin/env test all. - Comprehensive domain event system with abstract base classes for all major entities (
AbstractRoomEvent,AbstractMessageEvent,AbstractUserEvent,AbstractMemberEvent,AbstractInvitationEvent,AbstractExtAppEvent, etc.). Events are dispatched automatically on model lifecycle changes and power the SyncLog broadcasting. - Added
ApiRequestMigratorfor version-based API request format translation (v2 to legacy), supporting field mapping and ID conversion for backwards compatibility. - Added Eloquent casts for cryptographic types:
AsAsymmetricPublicKeyCast,AsHybridCryptoValueCast,AsSymmetricCryptoValueCast— enabling transparent encryption/decryption of model attributes. - Added
AiModelIdMapmodel andModelIdMapDbservice for database-backed mapping between internal numeric IDs and external AI model identifiers. - Added
CastableObjectCastertoAbstractCastableObject, enabling nested castable objects as typed properties. - Storage value objects have been moved from
Value/toValues/namespace (App\Services\Storage\Values). - The
ExternalCommunicationCheckmiddleware has been replaced by the newExternalAccessMiddlewareandAppAccessMiddlewarewith fine-grained feature flag control. - New Svelte component library with 20+ accessible UI primitives, all styled with scoped CSS and bits-ui (no Tailwind):
Badge,BorderBeam,Button,ButtonWithTooltip,Citation/CitationList/CitationRoot,ConfirmDialog/Dialog/InfoDialog,DropdownMenu(with checkbox, radio, switch, detail view variants),InfoPopover/Popover,RadialProgress,RadioCard/RadioCardGroup,SingleSelect,Separator,BottomSheet,Slider,StatusDot,Switch,Tabs,Textarea,Toaster,Tooltip/UrlPreviewTooltip, andTxt. - Introduced a CSS cascade layers architecture: styles are ordered strictly as
reset → tokens → base → components → utilities. A custom Svelte preprocessor (ComponentCssLayerProcessor) automatically wraps all component<style>blocks in@layer components {}, preventing specificity conflicts without any manual intervention in component code. - Icon system migrated from custom icons to Hugeicons (
@hugeicons/core-free-icons). A custom Vite plugin generates Svelte icon components from the library at build time, with version-based caching to avoid unnecessary rebuilds. - Composer state is split into composable "aspect" classes (
ModelAspect,ToolAspect,AttachmentAspect,ModelParameterAspect,ModelUsageAspect,GuardAspect) — each independently manages a self-contained slice of state using Svelte 5 reactivity. Derived aspects are purely computed from others and carry no mutable state of their own. - Added a composer mode system (
ChatDefaultMode,ChatEditMode,ChatInThreadMode,ChatRegenMode). Mode transitions use aContextCheckpointerto snapshot and restore all aspect state, making every transition fully reversible without each mode managing its own copies of shared data. - Added
OldUiBridge— a Svelte-to-legacy compatibility layer that forwards message sends, passkey UI, and message history interactions from the new Svelte composer to the existing Blade/JS UI. This enables incremental migration to the new frontend without a big-bang replacement. - Added a Svelte snippet loader (
<svelte-snippet>custom HTML element): Blade templates can mount Vite-chunked Svelte components by name without any manual JS glue. The element resolves the component from a registry, hydrates it with props passed via data attributes, and destroys it on disconnect — enabling Svelte islands inside server-rendered pages. - The frontend data layer is built around a typed JSON:API client backed by Zod schemas.
getResourceCollectionFromApi()andgetResourceFromApi()deserialize JSON:API envelopes, validate against declared schemas, and return flat typed objects. A resource schema registry using TypeScript declaration merging lets any file contribute its schema and have it automatically inferred at call sites without central registration. - End-to-end encryption uses a three-tier cryptographic system: symmetric (AES-256-GCM with random 12-byte IVs) for bulk data and room messages; asymmetric (RSA-OAEP-4096) for encrypting and distributing symmetric keys per recipient; and hybrid (random AES key + asymmetric wrapping) for large data that only the server should decrypt. All keys are stored encrypted at rest in the User Keychain, protected by a passkey-derived key.
- Existing passkey keys stored in the legacy JWK format are automatically migrated to the new base64 format on first login via a frontend migration. The migration is non-destructive — the old room key format is preserved until all room keys are re-wrapped in the new structure.
- New pluggable provider adapter system (
ProviderAdapterRegistry) with first-party adapters for: Anthropic, AWS Bedrock, Azure OpenAI, Cohere, Deepseek, Gemini, GWDG, Mistral, Ollama, OpenAI, OpenAI-compatible, and OpenRouter. Custom adapters can be registered by implementingProviderAdapterInterface. - Added the model information enrichment pipeline (
AiModelInfoEnrichmentPipeline) — an ordered chain of injectable enrichers that populateAiModelrecords with capabilities, limits, flags, pricing, and documentation URLs. Includes a LiteLLM API enricher, a static GWDG enricher, and a documentation URL enricher. 100+ provider data files are bundled inresources/static_llm_data/lite_llm/as a static fallback. - Added well-known registries for model capabilities, flags, limits, and pricing — each extensible via PHP registries. Predefined constants in
WellKnownCapabilities(web search, web fetch, code execution, knowledge base, tool calling) andWellKnownModelFlags(20+ flags covering model character, strengths, and supported features) ship out of the box. - Introduced the contextual scopes system (
HasContextualScopesTrait): Eloquent models can now register conditional global scopes that activate based on request context. Built-in scopes includeLocaleAwareScope,UsageTypeFilterScope,ActiveFilterScope,BelongsToUserScope, andActiveFilterOnRelationScope. - Added
UsageContextsingleton tracking whether the current request originates from the main application or an external integration — used to filter model availability and evaluate feature flags.UserContexttracks user state across the request lifecycle (guest, registered, registering, external app user). - Added
ConfigFileSyncer— orchestrates all registered config syncers with built-in change detection, only re-running a syncer when its source data has actually changed. Powers thephp artisan ai:config:syncartisan command (--forceflag available to bypass change detection). - Introduced
ChatAgent— a structured agent abstraction over the AI service layer. Replaces ad-hoc controller logic for AI conversations with a clean request/response lifecycle supporting context, instructions, message history, and tool resolution. - Three custom LaravelAI driver extensions ship with this release.
GeminiExtendedadds configuration hoisting (fixing nestedgenerationConfig/safetySettingsextraction) and citation streaming.OpenAiCompatibleGatewaybridges GWDG and similar OpenAI-compatible endpoints pending upstream support in the Laravel AI library. Both drivers emitCitationevents during streaming so the frontend can inject inline source chips as the response arrives. - Added
AnnouncementServiceandAnnouncementmodel backing the new announcements feature. Supports global and targeted delivery, scheduling windows, forced-display mode, and per-user seen/accepted tracking. - Added asset cache busting via
AssetCacheBustingUrlGenerator: non-Vite assets get a content-hash query parameter appended automatically. Vite build outputs are exempted because their filenames are already content-hashed, which would break ES module URL matching. - The
bin/_envsystem has been refactored into an addon-based architecture: project-specific commands (artisan,queue,websocket,dev,setup-models,clear-cache) live inproject.addon.tsand are executed inside Docker containers. Test infrastructure lives intest.addon.ts. This makes it straightforward to add new CLI commands without touching core env logic. - Added three new config files for administrators and contributors:
config/external_access.phpcontrols which external API features are enabled (ALLOW_EXTERNAL_COMMUNICATION,ALLOW_USER_TOKEN_CREATION,ALLOW_EXTERNAL_APPS,ALLOW_EXTERNAL_APPS_GROUPS_AI);config/tools.phpregisters function-calling tools and MCP servers;config/encryption.phpcentralizes the five application-level encryption salts (USERDATA, INVITATION, AI_CRYPTO, PASSKEY, BACKUP) with auto-generation fallback viaSaltProvider. - Docker production deployments now require five pre-configured encryption salts in
_docker_production/.env(APP_ENCRYPTION_SALT_*). These replace the previous approach of deriving salts at runtime and must be set before the first migration run. See the upgrade guide for details. - Added
make:frontend-migrationartisan command for contributors: generates a paired PHP backend migration and TypeScript client migration with a selectable run-type (after_login,after_passkey, or a custom value), pre-wired to the frontend migration system. - PHP upgraded to 8.3 (minimum requirement raised from 8.2) and Laravel upgraded to 13 (from 12). The
composer.jsonnow also explicitly declares all required PHP extensions:curl,dom,fileinfo,libxml,openssl,zip, andgd. - Major new PHP packages:
laravel-json-api/laravel(^5.2, powers the JSON:API layer),laravel/ai(Laravel's first-party AI abstraction),logiscape/mcp-sdk-php(^1.7, MCP protocol client),opis/json-schema(^2.6, tool input schema validation),phpseclib(^3.0, cryptographic operations). - Frontend stack upgraded across the board: Svelte 5 (^5.56), TypeScript 6 (^6.0), Vite 8 (^8.1), bits-ui (^2.18), shadcn-svelte (^1.2). Rendering: Monaco Editor (^0.55, code blocks), Mermaid (^11.16, diagrams), KaTeX (^0.17, math), markstream-svelte (streaming markdown). Export: jsPDF, pdfjs-dist, docx, docx-preview, cropperjs.
- The Docker base image moves to
neunerlei/php-nginx:8.3and theDockerfilenow installsghostscript,imagemagick, andlibrsvg2-binas system packages, so all file pre-processing features work in Docker without any additional steps. - WebSocket broadcast channels restructured: a private
User.{id}channel per user and a semi-publicAllUserschannel replace the previous approach. Client-side channel subscriptions are negotiated via the connection payload. - Added
AgentRegistrywithWellKnownAgentsconstants — a central registry for named agent types.ChatAgentis the first registered agent; new agent types can be added by registering them withAgentRegistry::register(). - Added
AlternatingMessageHistory— enforces the user/assistant alternating message pattern required by most LLM APIs, merging consecutive same-role messages automatically so malformed histories never reach the provider. - Tool input and output schemas are now validated with
JsonSchemaValidator(backed byopis/json-schema) before tool calls are dispatched, catching schema violations before they reach the provider. FunctionToolSyncerdiscovers PHP function tools via the#[Tag(ToolInterface::class)]attribute and syncs them to the database automatically, removing the need for manual tool registration.SyncActionDetectoradds hash-based change detection toConfigFileSyncer: each syncer records a hash of its source data after running, and is skipped on subsequent calls unless the data has changed.- Added
BeforeCallingMcpToolFilterEvent— a filterable event dispatched before any MCP tool call. Listeners can short-circuit the call and inject a synthetic result, which is essential for integration tests that need to mock external MCP servers. ApiDataScopeContextSettingMiddlewarelets API clients opt out of specific contextual scopes per request via the?no_scope[resource]=*query parameter, providing escape hatches for admin queries that need unfiltered data.- The
AiServicefacade has been expanded with:getAgent(name),tryToGetAgent(name),getMcpClient(server),getSystemPrompts(),getSystemModels()— making it the single entry point for all AI-related service resolution. - Background queue workers now run with
--timeout=0(no per-job timeout), preventing long-running AI streaming jobs from being killed mid-response. - The
Clockservice has been renamed toCarbonClockand a newCarbonClockInterface(extendingPsr\Clock\ClockInterface) has been introduced. The interface guaranteesCarbonImmutableas the return type ofnow(), improving type safety across all time-dependent services. BothClockInterfaceandCarbonClockInterfaceresolve to the same singleton in the service container. All internal services (caching, crypto, URL signing, file converters, frontend migrations) now use constructor injection of this clock, making time-dependent logic fully testable.
Deprecation
LanguageController::getTranslation()andgetAvailableLanguages()are deprecated and will be removed in a future version. UseLocaleServiceand the frontend connection payload instead.- The
/req/profile/validatePasskeyand/api/link-previewroutes are deprecated. Replacements are available via the JSON:API v1 endpoints. - OpenAI requests that still run against the "/chats/completions" endpoint now trigger a warning log, to help understand why the requests are failing.
Upgrade Guide
This release requires manual upgrade steps. Please see the upgrade guide before upgrading.