Repository navigation
chore: release v0.4.0 - #272
Merged
Merged
Conversation
Contributor
QualOps Code Quality AnalysisStatus: ✅ PASSED - No issues found Summary
No issues found in the analyzed code. 📊 Full ReportPowered by QualOps |
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release v0.4.0
Added
eggaipackage is type-checked in CI(
poetry run mypy, config inpyproject.toml);mypyis a new dev dependency.RedisTransport: newgroup_startsubscribe option ("$"default,"0"ora stream id) chooses where a NEW consumer group starts reading, so a consumer
added to a channel that already carries traffic can pick up the existing
backlog. The transport now creates its consumer groups itself before the
broker starts (RedisTransport:
last_id="0"creates the group at 0 but XREADGROUP then never delivers; need a group-start option #260).Fixed
json.JSONEncodeError, so a failingjson.dumpsraisedAttributeErrorandmasked the real error. It now catches
(TypeError, ValueError).proper A2A message; a skill registered with
data_type=NoneraisedTypeErrorwhen building the message and now falls back toBaseMessage.data_typewhosetypefield has no default (e.g. rawBaseMessage) silently dropped every message;subscribe()now raisesValueErrorasking for a default discriminator.Agent.subscribe(): plugin-prefixed kwargs (e.g.a2a_*) on an agent whoseplugin was never initialised raised an opaque
KeyError; nowValueError.RedisTransport:agent.stop()could hang forever on Python 3.10/3.11 withredis-py >= 8. redis-py 8 sends every command through
asyncio.wait_for(
socket_timeoutnow defaults to 5s), and on CPython < 3.12wait_forcanswallow the
CancelledErrorwhen the inner await completes concurrently, sothe reclaimer task survived its own cancellation. The reclaimer loop now exits
on a running flag as well as on cancellation.
EGGAI_NAMESPACE(RedisTransport: with a non-default EGGAI_NAMESPACE the reclaimer, retry and DLQ streams use eggai.<ns>.<topic> while consumption uses <ns>.<topic>, so retries never fire #261): thereclaimer, group monitor,
.retryand.dlqstreams were keyed undereggai.<ns>.<topic>while consumption and publishing used<ns>.<topic>, soretry_on_idle_ms/max_retriesnever fired outside the default namespace.The transport no longer adds its own
eggai.prefix;Channelalreadynamespaces the name exactly once. After upgrading, entries stuck in the PEL
under a custom namespace are retried immediately and dead-lettered once the
retry budget is exhausted. Stale empty
eggai.<ns>.*shadow keys can bedeleted.
PendingReclaimer: the retry envelope's header length prefix countedcharacters instead of bytes, truncating non-ASCII header values on every
retry delivery (PendingReclaimer: _BinaryWriter.write_string uses character count for the length prefix, corrupting non-ASCII headers on retry #263).
Agent.subscribe()without a channel listened on the literaleggai.channelinstead of
<EGGAI_NAMESPACE>.channel, so under a custom namespace a bareChannel().publish()never reached it (Agent.subscribe() with no channel hardcodes "eggai.channel", ignoring EGGAI_NAMESPACE #264).Changed
satisfy mypy (no behaviour change).
Transport.subscribe()'s secondparameter is now named
handlerin the abstract base and all transports.BaseMessage.datais now required. The generic base previouslydeclared
data: TData = Field(default_factory=dict). Pydantic does notvalidate defaults, so an envelope missing
datavalidated cleanly on anytyped subclass (
BaseMessage[Order]) withdataas a plain{}— thehandler then crashed on first attribute access, and under
NACK_ON_ERRORthat single malformed message wedged the subscription. A missing or malformed
payload now fails validation, which typed subscriptions
(
wrap_handler_with_filters) already treat as "not ours: skip and ack".The concrete
Messagekeeps its{}default, where the annotation really isa dict. Migration: construct payload-less envelopes with
Message(or passdata=explicitly).ruff >=0.14.4,<0.17) and exclude Markdown from ruff, whichnow formats fenced code blocks by default.
RedisTransport:last_idother than">"together with a consumer groupnow raises
ValueError. That combination never delivered new entries (Redisreturns only the consumer's own pending entries for an explicit id) and
hot-looped XREADGROUP; the earlier note about replaying a backlog with
last_id="0"was wrong. Usegroup_start="0"instead.After merging, the release will be automatically tagged and published to PyPI.