Repository navigation
v0.61.0
[v0.61.0] - 2026-09-20
Added
- Claude Opus 5, Claude Fable 5 and Claude Fable 5.1 join the Anthropic backend, and Opus 5 the two hosted profiles:
claude-5-opus,claude-5-fableandclaude-5.1-fableare served on Anthropic's own model ids, and all three are reachable on Pipelex Manifold through Bedrock'sglobal.anthropic.*endpoints, the way every other Claude already is. Only Opus 5 is served on the Pipelex Gateway: Bedrock refuses both Fables through Portkey withdata retention mode 'default' is not available for this model, a mode no model spec can set, so listing them there would publish handles that fail on every request. All of them take text, images and PDF, cap output at 128k tokens, and think adaptively with the temperature parameter refused. Fable 5.1 additionally declaresstructure_method = "instructor/anthropic_reasoning_tools", because it rejects the forcedtool_choicethat the backend's defaultinstructor/anthropic_toolssends and structured output fails without it. - The GPT-5.6 series and GPT-6 Astra are served on OpenAI, Azure OpenAI, the Pipelex Gateway and Pipelex Manifold:
gpt-5.6-sol,gpt-5.6-terra,gpt-5.6-lunaandgpt-6-astraare registered on the two direct backends and, through the remote config, on both hosted routing profiles. All four take text, images and PDF, produce text and structured output, and reason underthinking_mode = "manual"with a fixed temperature of 1. The Azure entries carry the dated deployment ids the hosted profiles also use as their wire model ids.
Changed
add-modelskill follows the model's nearest sibling: the skill derives which backend TOMLs, test collection and deck entries a new model belongs in from the model it succeeds, instead of a fixed provider-to-backend table, and checks each backend actually serves the model. It takes the model's facts from the provider's own documentation with OpenRouter as a cross-check, hands the live tests to/test-modelwith a test class per declared capability, and adds the deck and changelog steps andmake ugmonce the gateway catalog carries the model.
Removed
- The superseded GPT generations are retired from the rosters we ship (Breaking): the GPT-4.1 series, the
o1,o3ando4reasoning models and the GPT-5, GPT-5.1 and GPT-5.2 generations are gone fromazure_openai, fromopenai— which also losesgpt-3.5-turbo,gpt-4,gpt-4-turbo, the codex variants of those generations and the datedgpt-4oaliases — and from the gateway and manifold catalogs.o4-miniis retired fromportkeyin the same pass, since no other backend served it. None of them is unsupported: they are unlisted, and a project that still wants one keeps it by declaring it in its own backend config. What genuinely retires is their availability on the Pipelex Gateway and Pipelex Manifold, where the roster is ours.gpt-4oandgpt-4o-ministay on both direct backends; the retired names thatportkeyandblackboxaistill declare remain reachable through those, andopenrouter's bulk third-party catalog is untouched.
Fixed
- Claude Sonnet 5 is priced at its standard rate:
claude-5-sonnetcarried the $3 / $15 per million tokens it was announced at, but its $2 / $10 introductory rate became the standard price and the scheduled increase was cancelled. The entry is corrected on the Anthropic backend and in both hosted catalogs, so cost reporting and budget ceilings no longer overstate a Sonnet 5 run. - A failed publish can be recovered without damaging what already shipped:
publish-pypi.ymlscopes the signature upload todist/*.sigstore.jsonso it no longer clobbers the wheel and sdist attached just before it, turnsskip-existingon for a re-run or a manual dispatch, and refuses to touch a release whose tag names a commit other than the one being published. A retry no longer rebuilds the dists either: the build job asks PyPI what this version published and recovers those bytes from the first place that holds them — the build an earlier attempt of this run stored, an artifact an earlier run stored for the same commit, or the files PyPI itself serves — building fresh only when PyPI answers that nothing was published under this version. Whatever it holds is then checked to be one wheel and one source tarball of the version being released and, when PyPI serves that version, byte-for-byte what PyPI publishes, so the release assets are the bytes PyPI serves rather than a rebuild that probably matches them. The release is now tagged at the commit it ships, named explicitly with--target, rather than at the default branch's head. - A generated image is stored under its own media type, so a store no longer serves it as
binary/octet-stream:GeneratedContentFactory.make_image_contentresolves the effective mime type once and already used it to mint the storage key's extension, but passed nocontent_typetoStorageProviderAbstract.storeon either the direct-bytes path or the fetched-remote one. The S3 provider only setsContentTypewhen it is given one, so every generated image landed untyped and S3 answeredbinary/octet-streamon the way back out — which reached any consumer that trusts the stored type, a same-origin assets route serving the object to a browser among them. Both calls now pass the resolved mime type, so the key's extension, the object's stored type and the reportedmime_typecannot diverge. - A generated image fetched from a remote URL is stored under the media type that URL served:
GeneratedImageRawDetailsadmits a bare URL with no mime type and no image format on the promise that the type is settled when the bytes are downloaded, and nothing kept that promise — the fetch discarded the response'sContent-Typeand the resolution fell through to the requested image format or to a hardcodedimage/jpeg. The newfetch_file_and_content_type_from_url_httpxreports the declared type alongside the bytes, normalized and with its parameters stripped, and the factory stores under anyimage/<subtype>it names — not merely the formatsImageFormatcan itself produce, since what this runtime generates is a different question from what a remote URL may serve, and a GIF or an AVIF stored asimage/jpegis the very error being removed. The storage key's extension follows that subtype so it keeps agreeing with the stored type. A type the caller declared still wins, and a served type that is not an image at all — thetext/htmlof an error page dressed as a 200 — is dropped. - A remote image that fails to download degrades to its URL instead of failing the pipe:
make_image_contentguarded its fetch withexcept (httpx.HTTPStatusError, httpx.RequestError), butfetch_file_from_url_httpxconverts every httpx failure intoRemoteFileFetchError, so that clause caught nothing and a 404 or a timeout on a remote image propagated out and failed the whole run. The guard now names the exception the fetch actually raises, and the fallback it was written for — log the warning, keep the remote URL — runs. - A remote fetch honours a timeout again:
fetch_file_from_url_httpxpassed itsrequest_timeoutstraight to httpx, and httpx reads an explicittimeout=None— the parameter's own default — as no timeout at all rather than as its client default. Every caller that did not name one therefore had no timeout, so a hanging server blocked the caller indefinitely and theTimeoutExceptionbranch that raises a caller-facingRemoteFileFetchErrorwas unreachable. The helper now passes httpx'sUSE_CLIENT_DEFAULTsentinel where no timeout was asked for. - A manifold error on the native routes keeps its request id under the gateway's pipelex-spelled trace header:
extract_manifold_metadatareads the gateway's trace id fromx-pipelex-trace-idbefore the inheritedx-portkey-trace-id, still preferring a provider's ownx-request-idover both. The gateway emits the two spellings with the same value today, so nothing changes yet; once it drops the vendor one, such an error whose provider sent nox-request-idkeeps a request id instead of reporting none.extract_gateway_metadatais unchanged and still reads the vendor spelling alone — it serves the Portkey cloud and the manifold image path, which travels onportkey_aiand keeps that spelling until it is ported off the SDK.
What's Changed
- feature/Manifold-trace-id-spelling · L-260918-a332cc by @lchoquel in #1213
- feature/Refresh-add-model-skill · L-260919-74f437 by @lchoquel in #1217
- feature/Add-models · L-260920-1feb2b by @lchoquel in #1218
- feature/Generated-image-stored-untyped · L-260920-76086e by @lchoquel in #1220
- feature/Publish-workflow-recovery · L-260827-8724d3 — sigstore upload clobbers dists by @lchoquel in #1222
- feature/Roster-refresh · L-260920-6c3d2b by @lchoquel in #1219
- feature/Dispatch-retry-rebuilds-dists · L-260920-487091 by @lchoquel in #1223
- Release v0.61.0 by @lchoquel in #1224
Full Changelog: v0.60.0...v0.61.0