Skip to content

channels/wasm: implement telegram broadcast path for message tool - #395

Closed
davidpty wants to merge 3 commits into
nearai:stagingfrom
davidpty:fix/wasm-telegram-broadcast
Closed

davidpty wants to merge 3 commits into
nearai:stagingfrom
davidpty:fix/wasm-telegram-broadcast

Conversation

@davidpty

@davidpty davidpty commented Feb 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fix proactive Telegram sends from the message tool when channel is WASM-backed.

Root Cause

WasmChannel/SharedWasmChannel did not implement broadcast(), so the default trait implementation returned Ok(()) without delivering anything.

Changes

  • Implement WasmChannel::broadcast() for Telegram proactive sends.
  • Delegate broadcast() in SharedWasmChannel.
  • Return explicit errors for unsupported WASM broadcast cases (attachments/non-telegram).
  • Add regression tests for broadcast behavior in src/channels/wasm/wrapper.rs.

Validation

  • cargo test -q test_broadcast_ -- src/channels/wasm/wrapper.rs
  • Live gateway test delivered TEST-WASM-BROADCAST-1772150835 to chat 146032821.

@github-actions github-actions Bot added size: M 50-199 changed lines scope: channel/wasm WASM channel runtime risk: medium Business logic, config, or moderate-risk modules contributor: new First-time contributor and removed size: M 50-199 changed lines labels Feb 27, 2026
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves an issue preventing proactive Telegram messages from being sent via WASM-backed channels. The core change involves implementing the broadcast functionality within the WASM channel wrapper, specifically tailored for Telegram's requirements. It also introduces robust error handling for unsupported broadcast scenarios and refines timeout management for HTTP requests to align with callback durations. These changes ensure reliable and predictable message delivery for WASM-based Telegram integrations.

Highlights

  • Telegram Broadcast Implementation: Implemented the broadcast method for WasmChannel to enable proactive Telegram sends from the message tool, addressing a previous issue where the default trait implementation resulted in no delivery.
  • Error Handling for Unsupported Broadcasts: Added explicit error returns for WASM broadcast attempts involving attachments (currently unsupported) or non-Telegram channels, ensuring clear feedback for invalid usage.
  • Timeout Management: Modified HTTP request timeout logic to cap the caller-specified timeout by the callback_timeout, preventing HTTP requests from outliving callback execution.
  • Code Refactoring: Introduced a new callback_timeout helper method in WasmChannel and refactored existing code to use it, improving consistency and maintainability.
  • Regression Tests: Added new regression tests to validate the broadcast behavior, covering cases for non-Telegram channels, invalid Telegram chat IDs, and successful Telegram chat ID broadcasts.
Changelog
  • src/channels/wasm/shared.rs
    • Delegated the broadcast method implementation to the inner WasmChannel instance.
  • src/channels/wasm/wrapper.rs
    • Implemented the broadcast method for WasmChannel to handle proactive message sending.
    • Added a new callback_timeout helper method to WasmChannel for consistent timeout retrieval.
    • Updated HTTP request timeout calculation to cap it by the callback_timeout from channel capabilities.
    • Refactored multiple call sites to use the new callback_timeout helper method.
    • Added new test functions (create_telegram_test_channel, test_broadcast_rejects_non_telegram_channels, test_broadcast_rejects_invalid_telegram_chat_id, test_broadcast_accepts_valid_telegram_chat_id) to validate broadcast behavior.
Activity
  • The author identified and fixed an issue where proactive Telegram sends from the message tool failed when the channel was WASM-backed.
  • The root cause was determined to be the lack of implementation for the broadcast trait, leading to a default no-op.
  • The broadcast method was implemented for Telegram proactive sends within the WASM channel.
  • The broadcast method was delegated in SharedWasmChannel to its inner WasmChannel.
  • Explicit errors were added for unsupported WASM broadcast cases, such as attachments or non-Telegram channels.
  • Regression tests were added to src/channels/wasm/wrapper.rs to verify the new broadcast functionality.
  • Validation included running 5 tests, all of which passed, and a live gateway test successfully delivered a message to a chat.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements the broadcast method for WasmChannel to enable proactive messaging, specifically for the Telegram channel, adding it to WasmChannel and SharedWasmChannel with regression tests. A security vulnerability of medium severity exists as the new broadcast path lacks authorization checks, potentially allowing unauthorized messaging and bypassing owner_id restrictions, which violates the rule regarding verifying authenticated user IDs for user-owned resources. Furthermore, the broadcast method in the generic WasmChannel contains Telegram-specific logic, which could impact maintainability, and one new test for the success path of broadcast is not fully effective due to using a mock channel without a WASM component. Positively, the fix to cap HTTP request timeouts and the refactoring of callback timeouts are solid improvements, with the implementation correctly handling Telegram-specific metadata and robust HTTP timeout mechanisms.

Comment on lines +2020 to +2024
async fn broadcast(
&self,
user_id: &str,
response: OutgoingResponse,
) -> Result<(), ChannelError> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The broadcast method allows the agent to send proactive messages to any Telegram chat_id provided in the user_id parameter without performing any authorization checks. This implementation bypasses the owner_id restriction and pairing-based access controls that are enforced for incoming messages in the Telegram channel's WASM guest.

If an attacker can influence the user_id passed to the broadcast method (for example, through prompt injection into a tool that calls this method), they could use the bot to send unauthorized messages or spam to arbitrary Telegram users.

Recommendation: Implement a check within the broadcast method to verify that the target user_id is authorized to receive messages from the bot, respecting the channel's configured privacy policy (e.g., checking against the owner_id or the pairing store).

References
  1. Tools that interact with user-owned resources, such as sandbox jobs, must verify that the authenticated user ID in the tool context matches the resource owner's ID (e.g., by using a ContextManager) before performing any read or write operations to prevent unauthorized cross-user access.

Comment on lines +2032 to +2040
// Broadcast routing metadata is channel-specific. For now, support
// Telegram's expected metadata shape so proactive notifications can be
// delivered to a chat ID.
if self.name != "telegram" {
return Err(ChannelError::SendFailed {
name: self.name.clone(),
reason: "WASM broadcast is only implemented for telegram".to_string(),
});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The broadcast function contains logic specific to Telegram, such as parsing the user_id as a chat_id and constructing Telegram-specific metadata. This is implemented in the generic WasmChannel wrapper, which makes it difficult to support broadcasting for other WASM-backed channels in the future without adding more channel-specific if/else blocks.

For better maintainability, this logic should ideally be delegated to the WASM module itself. A potential improvement would be to add an on_broadcast function to the WIT interface. WasmChannel::broadcast would then call this function, and each WASM channel supporting broadcast would implement its own logic.

While the current approach is a pragmatic fix, this is a suggestion for future refactoring when expanding broadcast capabilities.

Comment on lines +2548 to +2556
#[tokio::test]
async fn test_broadcast_accepts_valid_telegram_chat_id() {
let channel = create_telegram_test_channel();
let result = channel
.broadcast("146032821", OutgoingResponse::text("hello"))
.await;

assert!(result.is_ok());
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test test_broadcast_accepts_valid_telegram_chat_id uses a test channel without a WASM component. In this scenario, call_on_status returns Ok(()) immediately without executing any WASM code. As a result, this test only verifies that the initial validation in broadcast passes, but it doesn't cover the full success path of the call_on_status invocation.

To make this test more robust, consider using a mock WASM component that can assert it was called correctly, or find another way to verify that call_on_status is invoked with the expected parameters.

@serrrfirat serrrfirat left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

This is a well-scoped, focused PR that fixes a real bug (WasmChannel/SharedWasmChannel silently dropping broadcasts due to the trait's no-op default). The implementation is pragmatic — piggybacking broadcast on the existing call_on_status path avoids a new WASM callback while reusing Telegram's retry logic. The three new tests cover the main validation paths.

The main concerns are: (1) the callback_timeout() refactoring silently changes timeout source for 8 existing callsites, which could be intentional but warrants documentation; (2) the happy-path test doesn't exercise actual WASM execution due to component: None; (3) the synthetic metadata (user_id = chat_id, is_private = true) hardcodes assumptions that may break for group chats. None of these are blocking — the PR achieves its stated goal correctly for the private-chat Telegram use case it was built for.

reason: format!("Invalid telegram chat_id '{}': {}", user_id, e),
})?;

let metadata = serde_json::json!({

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

user_id metadata field set to chat_id may be incorrect for group chats

The broadcast metadata hardcodes "user_id": chat_id. In Telegram, user_id and chat_id are distinct concepts: a group/supergroup chat_id is negative and is not a user_id. If the downstream WASM module's on_status handler uses the user_id field for any authorization, attribution, or routing logic, it will receive the chat_id instead, which is semantically wrong for non-private chats. Combined with is_private: true being hardcoded, a broadcast to a group chat_id would present contradictory metadata.

Suggested fix:

Either (a) validate that chat_id is positive (private chats only) and reject group chat IDs explicitly, or (b) accept an optional separate user_id parameter for group-chat broadcasts and set is_private accordingly. At minimum, add a comment documenting that this path is only valid for private chats.

Severity: medium · Confidence: medium

assert!(err.contains("Invalid telegram chat_id"));
}

#[tokio::test]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test_broadcast_accepts_valid_telegram_chat_id does not exercise WASM execution

The test creates a WasmChannel with component: None, which causes call_on_status to return Ok(()) immediately (line ~1253: if self.prepared.component().is_none() { return Ok(()); }). This means the test only validates the input-validation path (name check, chat_id parsing) but never tests that the WASM component actually receives and processes the broadcast. A valid chat_id could still fail when a real component is present (e.g., the WASM module rejects message_id: 0, or the status handler doesn't handle Status variant as a broadcast).

Suggested fix:

Add a comment to the test clarifying it only validates pre-WASM validation. Consider adding an integration test with a minimal WASM component that asserts the `on_status` callback is invoked with the expected `Status` payload and synthetic metadata.

Severity: medium · Confidence: high

Comment thread src/channels/wasm/wrapper.rs Outdated
impl WasmChannel {
#[inline]
fn callback_timeout(&self) -> Duration {
self.capabilities.callback_timeout

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

callback_timeout() silently changes timeout source from runtime config to per-channel capabilities across 8 callsites

The new callback_timeout() helper returns self.capabilities.callback_timeout instead of the previous self.runtime.config().callback_timeout. This changes all 8 existing callsites (call_on_start, call_on_respond, call_on_http_request, call_on_poll, call_on_status, handle_status_update, on_credentials_refreshed). If ChannelCapabilities::callback_timeout and WasmChannelRuntimeConfig::callback_timeout ever have different values, all callback timeout behavior changes. The PR description focuses on broadcast but this refactoring has broader impact.

Suggested fix:

This is likely intentional (per-channel timeout overrides global runtime timeout), but add a brief comment on the method explaining this design choice: that capabilities timeout takes precedence over runtime config timeout. Also verify that `ChannelCapabilities::for_channel()` initializes `callback_timeout` to a sane default that matches or improves on the runtime config default.

Severity: medium · Confidence: medium

}

let chat_id = user_id.parse::<i64>().map_err(|e| ChannelError::SendFailed {
name: self.name.clone(),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No validation that chat_id is non-zero

The code parses user_id as i64 but does not check for zero. A chat_id of 0 is invalid in Telegram's API and would cause a silent failure or error at the Telegram API level when the WASM module tries to send the message.

Suggested fix:

Add a check after parsing: `if chat_id == 0 { return Err(ChannelError::SendFailed { name: self.name.clone(), reason: "chat_id cannot be zero".into() }); }`

Severity: low · Confidence: medium

@@ -2435,6 +2521,40 @@ mod tests {
assert!(channel.health_check().await.is_err());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing test for attachment rejection path

The broadcast implementation rejects non-empty attachments (lines 2025-2029), but there is no test covering this path. Only non-telegram rejection and invalid chat_id are tested.

Suggested fix:

Add a test: create a telegram test channel, call `broadcast` with `OutgoingResponse::text("hello").with_attachments(vec!["file.png".to_string()])`, and assert the error contains "does not support attachments".

Severity: low · Confidence: high

})?;

let metadata = serde_json::json!({
"chat_id": chat_id,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded is_private: true may cause issues if broadcast is extended to groups

The metadata hardcodes is_private: true. If broadcast is later used for group notifications (negative chat_id), this field will be incorrect. The Telegram WASM module may use this flag to decide reply behavior, formatting, or permission checks.

Suggested fix:

Derive `is_private` from the chat_id sign: `"is_private": chat_id > 0`. In Telegram, positive IDs are users/private chats, negative IDs are groups/supergroups/channels.

Severity: low · Confidence: medium

self.handle_status_update(status, metadata).await
}

async fn broadcast(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

broadcast method lacks doc comment explaining contract and limitations

The broadcast implementation is non-trivial — it only supports telegram, rejects attachments, synthesizes metadata with hardcoded fields, and piggybacks on call_on_status. A doc comment would help future maintainers understand the design choices and constraints without reading the full implementation.

Suggested fix:

Add a doc comment above the `broadcast` method explaining: (1) only telegram is supported, (2) attachments are not supported, (3) broadcast uses the `on_status(Status)` callback path, (4) `message_id: 0` signals the WASM module to skip reply context, (5) assumes private chat targeting.

Severity: low · Confidence: high

@github-actions github-actions Bot added the size: M 50-199 changed lines label Feb 27, 2026
@davidpty

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review — addressed in the latest push (5302194).

What changed:

  • Scoped the PR back to broadcast-only behavior:
    • Reverted the callback-timeout-source refactor (self.capabilities.callback_timeout), so existing callback timeout callsites now continue using self.runtime.config().callback_timeout.
    • Reverted the unrelated host HTTP timeout cap change in this PR.
  • Tightened Telegram broadcast contract:
    • Added explicit private-chat validation (chat_id > 0), which also rejects chat_id == 0.
    • Kept this path private-chat only for now.
    • Added method-level doc comment describing limitations and callback path.
  • Metadata clarity:
    • is_private now derived from chat_id > 0.
    • With private-only validation, synthetic metadata is now consistent for supported inputs.
  • Test coverage improvements:
    • Added test for attachment rejection path.
    • Added test for non-private/negative chat_id rejection.
    • Added note in the valid-chat test clarifying it validates pre-WASM path only (component: None).

If useful, I can follow up with a separate integration test PR that uses a minimal WASM component to assert on_status invocation payload end-to-end.

@serrrfirat

Copy link
Copy Markdown
Collaborator

Thanks for the detailed review — addressed in the latest push (5302194).

What changed:

  • Scoped the PR back to broadcast-only behavior:

    • Reverted the callback-timeout-source refactor (self.capabilities.callback_timeout), so existing callback timeout callsites now continue using self.runtime.config().callback_timeout.
    • Reverted the unrelated host HTTP timeout cap change in this PR.
  • Tightened Telegram broadcast contract:

    • Added explicit private-chat validation (chat_id > 0), which also rejects chat_id == 0.
    • Kept this path private-chat only for now.
    • Added method-level doc comment describing limitations and callback path.
  • Metadata clarity:

    • is_private now derived from chat_id > 0.
    • With private-only validation, synthetic metadata is now consistent for supported inputs.
  • Test coverage improvements:

    • Added test for attachment rejection path.
    • Added test for non-private/negative chat_id rejection.
    • Added note in the valid-chat test clarifying it validates pre-WASM path only (component: None).

If useful, I can follow up with a separate integration test PR that uses a minimal WASM component to assert on_status invocation payload end-to-end.

Yeah that would be great! Rest looks good now.

@davidpty davidpty closed this Feb 27, 2026
@davidpty davidpty reopened this Feb 27, 2026

@zmanian zmanian left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Telegram Broadcast Path for WASM Channels

The code quality is good -- input validation, error handling, and test coverage are solid. But there's an architectural conflict that needs resolving.

Blocker: Conflicts with Existing Generic Broadcast

PR #398 (merged after this PR was branched) added a generic broadcast() implementation to WasmChannel at line 2103 that uses last_broadcast_metadata and calls call_on_respond. This PR adds a second Telegram-specific broadcast() at line ~2153 that hardcodes metadata from user_id and calls call_on_status.

These two implementations will conflict on rebase. More importantly, the project convention is "prefer generic/extensible architectures over hardcoding specific integrations."

The existing generic approach is the right architecture. The gap it has is: it fails with "No messages received yet" when no prior message has been received (so last_broadcast_metadata is empty). This PR solves a real problem -- proactive sends to users who haven't messaged yet -- but the fix should enhance the generic path, not add a Telegram-specific bypass.

Suggested Approach

Instead of hardcoding Telegram metadata construction, extend the existing generic broadcast to accept a fallback when last_broadcast_metadata is unavailable:

  1. Let the WASM channel module (Telegram, etc.) define how to construct broadcast metadata from a user_id via a new WIT callback (e.g., build-broadcast-metadata(user-id: string) -> option<string>)
  2. Or, simpler: have the broadcast try last_broadcast_metadata first, then fall back to calling the WASM module's on_status with a minimal metadata envelope constructed from capabilities/config (not hardcoded per channel name)

Specific Hardcoding Issues

  1. if self.name != "telegram" -- hardcodes channel name check
  2. user_id.parse::<i64>() -- assumes Telegram's numeric chat_id format
  3. Hardcoded metadata JSON shape (chat_id, message_id: 0, user_id, is_private)
  4. chat_id > 0 for private-chat detection -- Telegram-specific semantics
  5. Uses call_on_status instead of call_on_respond -- different code path than the generic broadcast

What's Good

  • Input validation is thorough (invalid chat_id, non-private, attachments)
  • Error messages are clear and actionable
  • 5 tests cover all the error paths plus the happy path
  • The comment "This path is private-chat only" documents the limitation honestly
  • SharedWasmChannel delegation is correct

Recommendation

Rebase onto main, resolve the conflict with the existing broadcast() from #398, and rework this as an enhancement to the generic broadcast path rather than a Telegram-specific bypass. The test suite can largely be kept as-is.

@henrypark133
henrypark133 changed the base branch from main to staging March 10, 2026 02:24

@zmanian zmanian left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean implementation. Error handling follows IronClaw conventions (no .unwrap()/.expect(), ChannelError::SendFailed with context throughout). Guards for unsupported cases (attachments, non-telegram, non-private chats) are correct. SharedWasmChannel delegation is consistent with the existing pattern. Good test coverage on all error paths.

One minor observation: is_private: chat_id > 0 in the metadata JSON is always true at that point since the function returns early when chat_id <= 0. Not a bug -- it correctly communicates intent to the WASM module -- just a tautology. Fine to leave as-is.

@zmanian
zmanian enabled auto-merge (squash) March 12, 2026 19:13
@ilblackdragon

Copy link
Copy Markdown
Member

CI Fix

Merged staging and resolved conflicts:

  1. Duplicate broadcast() removed — staging already has a generic broadcast via call_on_broadcast. Removed the PR's telegram-specific version and its SharedWasmChannel duplicate.
  2. create_telegram_test_channel removed — was using the old 5-arg WasmChannel::new signature (now takes 7 args). Replaced 5 telegram-specific tests with one generic test_broadcast_delegates_to_call_on_broadcast test.
  3. fallback_deliverable: None added — pre-existing staging issue in job_monitor.rs test SseEvent::JobResult constructors.

The fixed branch is at nearai/ironclaw:fix/wasm-telegram-broadcast. Could not push to your fork due to OAuth workflow scope restriction (staging merge included .github/workflows/ changes).

@davidpty — please pull from origin/fix/wasm-telegram-broadcast and force-push to your fork, or I can open a replacement PR from the origin branch.

@ilblackdragon

Copy link
Copy Markdown
Member

Superseded by #1460 which merges staging and fixes CI. Thanks @davidpty for the original work!

auto-merge was automatically disabled March 20, 2026 07:37

Pull request was closed

ilblackdragon added a commit that referenced this pull request Mar 20, 2026
* channels/wasm: implement telegram broadcast path for message tool

* channels/wasm: tighten telegram broadcast contract and tests

* fix: resolve merge conflicts with staging for wasm broadcast

- Remove duplicate broadcast() impls from WasmChannel and SharedWasmChannel
  (staging already has the generic call_on_broadcast path)
- Remove obsolete telegram-specific test helpers and tests that tested
  the old telegram-only broadcast logic
- Add test_broadcast_delegates_to_call_on_broadcast for the generic path
- Fix missing fallback_deliverable field in job_monitor test SseEvents

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: davidpty <127684147+davidpty@users.noreply.github.com>
Co-authored-by: firat.sertgoz <f@nuff.tech>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
zmanian pushed a commit that referenced this pull request Mar 21, 2026
* channels/wasm: implement telegram broadcast path for message tool

* channels/wasm: tighten telegram broadcast contract and tests

* fix: resolve merge conflicts with staging for wasm broadcast

- Remove duplicate broadcast() impls from WasmChannel and SharedWasmChannel
  (staging already has the generic call_on_broadcast path)
- Remove obsolete telegram-specific test helpers and tests that tested
  the old telegram-only broadcast logic
- Add test_broadcast_delegates_to_call_on_broadcast for the generic path
- Fix missing fallback_deliverable field in job_monitor test SseEvents

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: davidpty <127684147+davidpty@users.noreply.github.com>
Co-authored-by: firat.sertgoz <f@nuff.tech>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
zmanian pushed a commit that referenced this pull request Mar 21, 2026
* channels/wasm: implement telegram broadcast path for message tool

* channels/wasm: tighten telegram broadcast contract and tests

* fix: resolve merge conflicts with staging for wasm broadcast

- Remove duplicate broadcast() impls from WasmChannel and SharedWasmChannel
  (staging already has the generic call_on_broadcast path)
- Remove obsolete telegram-specific test helpers and tests that tested
  the old telegram-only broadcast logic
- Add test_broadcast_delegates_to_call_on_broadcast for the generic path
- Fix missing fallback_deliverable field in job_monitor test SseEvents

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: davidpty <127684147+davidpty@users.noreply.github.com>
Co-authored-by: firat.sertgoz <f@nuff.tech>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bkutasi pushed a commit to bkutasi/ironclaw that referenced this pull request Mar 28, 2026
…nearai#1460)

* channels/wasm: implement telegram broadcast path for message tool

* channels/wasm: tighten telegram broadcast contract and tests

* fix: resolve merge conflicts with staging for wasm broadcast

- Remove duplicate broadcast() impls from WasmChannel and SharedWasmChannel
  (staging already has the generic call_on_broadcast path)
- Remove obsolete telegram-specific test helpers and tests that tested
  the old telegram-only broadcast logic
- Add test_broadcast_delegates_to_call_on_broadcast for the generic path
- Fix missing fallback_deliverable field in job_monitor test SseEvents

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: davidpty <127684147+davidpty@users.noreply.github.com>
Co-authored-by: firat.sertgoz <f@nuff.tech>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
drchirag1991 pushed a commit to drchirag1991/ironclaw that referenced this pull request Apr 8, 2026
…nearai#1460)

* channels/wasm: implement telegram broadcast path for message tool

* channels/wasm: tighten telegram broadcast contract and tests

* fix: resolve merge conflicts with staging for wasm broadcast

- Remove duplicate broadcast() impls from WasmChannel and SharedWasmChannel
  (staging already has the generic call_on_broadcast path)
- Remove obsolete telegram-specific test helpers and tests that tested
  the old telegram-only broadcast logic
- Add test_broadcast_delegates_to_call_on_broadcast for the generic path
- Fix missing fallback_deliverable field in job_monitor test SseEvents

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: davidpty <127684147+davidpty@users.noreply.github.com>
Co-authored-by: firat.sertgoz <f@nuff.tech>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: new First-time contributor risk: medium Business logic, config, or moderate-risk modules scope: channel/wasm WASM channel runtime size: M 50-199 changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants