Repository navigation
feat(progressive): execute canonical typed output events - #145
Conversation
Advance the tinybus and wiki submodule pointers to their latest commits. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a test asserting that FeedOutput forwards canonical events in order, assigning consecutive sequence numbers from the supplied starting point and preserving the turn id on each transport request. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
…port Add a FeedOutput command that carries canonical channel output events through the module's ordered transport, with a sequence number giving each batch a stable delivery identity so hosts can retry without changing it. The sender dispatches each event to the controller backend and the worker rejects batches larger than 32 events or replies that are already closing. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Adjust the expected final message in the progressive feed test to build OutboundContentPart::Content with the part field instead of content and caption, matching the current channel API. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Update the progressive delivery test to include the new markdown_dialect field on text content parts, keeping it in sync with the bus content type. Also bump the tinybus and wiki submodule pointers. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
The test now filters transport requests down to output events before checking their count and order, so unrelated requests no longer break the assertions. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
…dependency The module now opts out of the tinychannels crate's default features and enables only email, lark, and relay-websocket explicitly, so hosts that link it without those providers no longer pull in the default set. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a ProgressiveResult::OutputUpdated variant carrying typed terminal delivery results in event order, so callers can observe canonical output events while retaining receipts and partial failures. Also derive Debug and PartialEq on ProgressiveTransportResult to support comparison and inspection of these results. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Output updates now collect the transport results produced while sending typed parts and surface them through a new OutputUpdated variant, so callers can observe individual deliveries instead of only a generic updated status. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
FeedOutput now forwards the handle to the worker and sends final messages through the typed transport, collecting the resulting deliveries so callers receive OutputUpdated instead of a bare Updated. The Feed path keeps returning Updated since it produces no deliveries. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
The progressive transport fixture now answers SendTyped requests with a ChannelSendOutcome carrying a platform message id, and the output forwarding test asserts that the final message is delivered through typed provider transport with the expected turn, sequence, idempotency key and parts. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Final message events now carry their original receipt through to the rebuilt event, so a delivery that returns no outcome no longer drops it. Formatting in the affected modules was also tidied up. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
The FeedOutput variant now stores its channel and conversation references behind Box, shrinking the enum so the common variants stay small. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
The FeedOutput command now dereferences the borrowed channel_ref and conversation values so the owned types expected by the command are produced. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
The output event and typed send helpers took the channel, turn, and conversation as separate arguments, which made call sites long and easy to mix up. These are now bundled into an OutputScope struct, and the FeedOutput command variant carries a boxed FeedOutput struct so the enum stays small. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Tiny Sweeper reviewReviewed head: FindingsNo active actionable findings. Unverified notes — repository context was unavailable; these are not actionable findings Unverified note — critique
Verdict: Ready for maintainer review · Priority: none Diagnostics and supporting detailsFull summaryPull request purpose (title): feat(progressive): execute canonical typed output events. Tiny Sweeper completed its review; deterministic results follow. Review snapshot
Completeness: Complete Features
Tests
Before mergeNone. How this fits togetherflowchart LR
n0["ProgressiveCommand<br/>changed"]:::changed
n1["ProgressiveTransportRequest<br/>changed"]:::changed
n2["Closing<br/>changed"]:::changed
n3["Replies<br/>changed"]:::changed
n4["Callback<br/>changed"]:::changed
n5["...nking_and_tool_state_before_terminal_send<br/>changed"]:::changed
n6["fixture"]:::impacted
n7["Result"]:::impacted
n8["FeedOutput"]:::impacted
n9["expect"]:::impacted
n10["execute"]:::impacted
n11["...receipts_when_output_event_callbacks_fail"]:::impacted
n2 -->|uses| n7
n4 -->|uses| n1
n5 -->|calls| n6
n5 -->|tests| n6
n6 -->|uses| n3
n6 -->|uses| n4
n10 -->|uses| n0
n10 -->|uses| n7
n10 -->|calls| n8
n10 -->|uses| n8
n11 -->|calls| n6
n11 -->|tests| n6
n11 -->|uses| n8
n11 -->|calls| n9
n11 -->|tests| n9
classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Agent review detailscritique
security
tests
commits
description
Evidence and run details
|
|
Warning Review limit reached
This review includes 6 billable files and costs up to $1.50. Or wait 55 minutes for your next included review. View limit details
Comment |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ab6675257f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ries Output-event callback failures are now collected by sequence and returned alongside transport deliveries instead of aborting the whole batch, so a single failing callback no longer discards provider delivery results. Sequence arithmetic is also checked for overflow before applying events. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
The FeedOutput command variant now carries an AppliedOutput result instead of a vector of ProgressiveTransportResult, simplifying the response type returned to callers. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Progressive transport requests now carry the turn's output scope, so sends, edits, deletes and typing indicators are attributed to the correct turn and conversation. A replay cache was added to the entry so output batches can be reapplied, and the output event failures field is deserialized with a default for backward compatibility. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Replaced the checked_add and unwrap_or fallback with saturating_add when computing the end of the previous event range, which is simpler and avoids the unreachable overflow branch. The test callback was also collapsed into a let-chain to match. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 08b4ddc522
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Add a test that drives a progressive channel through a flushed draft followed by a typed final message, asserting the draft is sent first, the canonical final second, and the stale draft deleted last. This locks in the ordering guarantee for channels that support progressive edits. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
The module now reports whether the final message was actually delivered by the transport path, and the reply cleans up its draft, filler, and thinking bubbles once that delivery succeeds. A failed delivery keeps the draft visible while still removing the transient filler and thinking messages. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9176e4aa07
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Output scope was applied to the sender before the batch was validated, so a rejected batch left the sender pointing at the new scope. Scope assignment now happens inside a wrapper that only runs once the output is accepted, and tests cover the accepted typed final and over-limit final message paths. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
The progressive reply test passed a string literal through into, which is redundant since the literal already coerces to the expected type. Removing the call keeps the test compiling without the extra conversion. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
The callback fixture now stores a separate result for typed sends so tests can control the typed transport outcome independently of the default result. The accepted typed final test was updated to set this new field, keeping its behaviour unchanged. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Reformatted the test assertions to satisfy rustfmt and replaced the empty-requests check with a filter that verifies no typed send or output event requests were issued, making the test's intent explicit. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 16ec785aec
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…elta budget Add tests verifying that the first scoped output batch starts typing with the output batch scope, that a rejected legacy feed keeps the previous progressive sender scope, and that repeated final text is not double counted against the delta budget. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
The typing tick was only sent once before the command loop, so scoped feeds stopped refreshing the indicator after the first output. The tick now runs after each non-terminal output that has an active scope, and legacy feeds reset the scope through a dedicated helper. Oversized final messages are also detected up front so they no longer slip past the content limit check. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
The legacy feed path now triggers a typing tick once the feed succeeds, and the output path only refreshes typing when the feed succeeded, was not terminal, and did not deliver a final message. The scope check was dropped since a successful feed already implies an active scope, and apply_legacy_feed now clears the scope only after applying events so a failure leaves state untouched. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
The test now wraps the channel and conversation references in `Box` to match the updated `ProgressiveCommand::FeedOutput` variant, keeping the scoped output typing test compiling against the boxed fields. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Typing indicators are now only emitted while a scope is set, so the legacy feed path no longer triggers a typing tick after a successful feed. This keeps typing state consistent with the scoped output flow. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0ccac67a8a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Add tests asserting that replaying an accepted output batch retries the failed observation callback without repeating typed delivery, and that a reply handle rejects scope changes once its first batch is accepted. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Replayed output batches now re-deliver events whose callbacks previously failed instead of returning the cached result untouched, and the cached result is refreshed when the replay matches. A reply handle also pins the output scope of its first accepted batch so later batches cannot silently switch scopes. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
FeedOutput now replays a previously applied batch through the same retry path used by apply_output, so failed observation callbacks are re-run instead of being dropped when a duplicate request arrives. The retry logic was extracted into a shared helper to keep both paths consistent. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 10bae518f3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if let Some(applied) = replay_output(previous.as_ref(), &scope, sequence, &events) { | ||
| let mut applied = applied?; | ||
| retry_failed_output_callbacks( |
There was a problem hiding this comment.
Retry transient typed-final delivery failures
When the initial SendTyped call returns Unavailable or its dispatch error is converted to Failed, the batch is still cached and the final event terminates the worker. An identical FeedOutput retry then takes this replay path, retries only failed observation callbacks, and returns the cached delivery failure forever, so a transient outage permanently loses the user's final response despite the stable idempotency key. Reattempt failed typed deliveries on replay while continuing to deduplicate successful or pending sends.
Useful? React with 👍 / 👎.
| if sender | ||
| .output_event(scope, failed_sequence, event.clone()) |
There was a problem hiding this comment.
Preserve the enriched receipt when retrying final callbacks
If the first OutputEvent callback for a final message fails after SendTyped returns an Outcome, the initial callback contains the provider receipt, but this retry clones the original request event instead. That original event commonly has receipt: None, so the successful retry projects a final message without the delivery receipt even though it remains available in applied.deliveries; rebuild the retried final event with the cached outcome receipt.
Useful? React with 👍 / 👎.
| reply.typing_tick().await; | ||
| } | ||
| }, | ||
| _ = fillers.tick() => reply.filler_tick().await, |
There was a problem hiding this comment.
Gate filler sends until the output scope is known
For a FeedOutput turn whose first batch is delayed beyond FILLER_INTERVAL, this timer fires while Sender.scope is still None. Unlike the now-gated typing timer, filler_tick() always posts a static filler, so its Send request lacks the turn, account, and conversation references and can appear in the parent conversation or default account. Defer filler ticks until a scoped batch has been accepted, or make the scope available when the handle is opened.
Useful? React with 👍 / 👎.
Adds typed progressive output execution to the TinyChannels module. Hosts can feed ordered
ChannelOutputEventbatches with turn and conversation scope; final messages use provider-ownedSendTyped, and returned delivery results preserve receipts and partial outcomes. The existing legacyFeedoperation remains available. The module dependency now disables TinyChannels defaults so its explicitwhatsapp-webfeature controls that stack.Refs tinyhumansai/openhuman#7964
Refs #99
Verification:
cargo fmt --all -- --checkcargo check --workspacecargo clippy -p tinychannels-module --all-targets -- -D warningscargo test -p tinychannels-module(201 passed; 3 artifact tests ignored by design)cargo test -p tinychannels-bus(103 passed)feed_output_forwards_canonical_events_in_order_with_delivery_scoperegression passed.