v3.6.0
Added
Atlas::batch()submits large request sets as deferred jobs for ~50% lower cost — OpenAI (text, vision, embeddings), Anthropic and Google/Gemini (text, vision). With persistence on,submit()auto-tracks the job,atlas:batch-pollpulls results in keyed bycustom_id, andatlas:batch-prunebounds history (atlas.batch.retention_days, default 90); with it off, batching is stateless and you poll the provider yourself. Tools and per-request middleware aren't supported and are rejected up front.->reasoning(ReasoningEffort)on text and agent requests (and anAgent::reasoning()default) enables extended thinking at one effort level (Minimal/Low/Medium/High), mapped to each provider's format. OptionalbudgetTokens:andincludeSummary:.->countTokens()on text and agent requests returns input-token count before sending — exact on Anthropic/OpenAI/Google, estimated on xAI/Ollama/LM Studio. Returns aTokenCountwith anestimatedflag.
Fixed
- Extended thinking now works through multi-step tool calls and persisted-conversation reloads.
- Google (Gemini) tool calls no longer 400 on non-object results (number, boolean, array, quoted string) — wrapped automatically. Plain strings and JSON objects are unchanged.
- Google (Gemini)
withProviderOptions()no longer corrupts nestedgenerationConfigfields — extra keys (e.g.topP) merge alongside Atlas's values, and an overridden key (e.g.temperature) now replaces the value instead of becoming a list Gemini rejects with a 400. - Google (Gemini) now honors
temperature: 0.0instead of silently dropping it, so deterministic output works. - Streaming Google (Gemini) tool calls now surface
FinishReason::ToolCallsand keep every call when several arrive in one chunk — previously a streamed, tool-terminated response lost its finish reason and could drop a parallel call. - Chunked embeddings now work when persistence runs on a separate Postgres connection (
atlas.persistence.connection) and the app default isn't Postgres — pgvector is detected on the persistence connection, so chunk writes and similarity search no longer fail. - OpenAI (and xAI) document inputs now send the correct
input_filecontent part instead ofinput_image, so attaching aDocument(PDF, Word, Excel, CSV, text, Markdown, …) works — previously non-file-ID documents were sent as images and rejected with a 400. URLs pass through asfile_url; base64/path/storage/upload inline asfile_data. - xAI streaming errors are now attributed to
xai, notopenai— a mid-stream error through the shared Responses parser previously carried$provider === 'openai', misattributing xAI failures for anything branching on the provider. - Providers on the shared
chat_completions/responsesdrivers (Ollama, Groq, LM Studio, custom OpenAI-compatible endpoints) now report their configured provider key in exceptions, events, and middleware — previously failures were attributed to the generic driver type (chat_completions), making two such providers indistinguishable.
Migration
No breaking changes — drop-in upgrade. Stateless batching (submit, then poll the provider yourself) needs no setup. Tracked batching (auto-polled, persisted results) adds new tables — publish and migrate:
php artisan vendor:publish --tag=atlas-migrations
php artisan migratePR Summary List
- Add reasoning support and APIs for text/agent requests by @timothymarois in #49
- Add pre-flight token counting API and documentation by @timothymarois in #50
- Add Batch API (jobs, polling, persistence) by @timothymarois in #51
- Handle pgvector, Anthropic thinking, OpenAI batch by @timothymarois in #52
- Map Document inputs to OpenAI input_file by @timothymarois in #53
- Pass provider through SSE parsing; add tests by @timothymarois in #54
- Use configured provider name and fix parsers by @timothymarois in #55
- Extract shared Responses handlers, xAI adapters by @timothymarois in #56
Full Changelog: v3.5.0...v3.6.0