Repository navigation
feat(OMN-10837): route tool-content emission through node_emit_daemon - #1630
Conversation
Replaces the legacy embedded EventBusKafka path (direct Kafka connection, no retry, crash-loop on Redpanda restart) with the node_emit_daemon Unix socket client, which provides circuit-breaker, exponential backoff, and disk-spool durability. Changes: - cli_emit.py: _emit_tool_content() is now synchronous, calls emit_event() from emit_client_wrapper instead of creating an EventBusKafka instance - emit_client_wrapper.py: add "tool.content" to SUPPORTED_EVENT_TYPES - omniclaude.yaml: register tool.content → onex.cmd.omniintelligence.tool-content.v1 - test_cli_emit.py: update test to mock daemon path instead of legacy EventBusKafka Evidence-Ticket: OMN-10837
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughThis PR introduces two independent features: (1) migrates tool-content event emission from embedded async Kafka publishing to synchronous daemon-based routing with updated event registry and test coverage, and (2) adds a new verified_dispatch orchestrator node capability with contract schema, dependency injection, and error-handling policy. ChangesTool Content Event Daemon Routing
Verified Dispatch Orchestrator Node
Sequence Diagram(s)Tool-content emission now flows through the daemon instead of embedded Kafka: sequenceDiagram
participant CLI as CLI Command<br/>cmd_tool_content
participant Emitter as _emit_tool_content<br/>sync publisher
participant PluginLoader as Plugin System<br/>emit_event loader
participant Daemon as Event Daemon<br/>socket/IPC
CLI->>Emitter: call _emit_tool_content(content)
Emitter->>PluginLoader: dynamically load emit_event<br/>from CLAUDE_PLUGIN_ROOT
Emitter->>Daemon: emit_event("tool.content",<br/>content JSON payload)
Daemon->>Daemon: validate, route to<br/>onex.cmd.omniintelligence.tool-content.v1
Daemon-->>Emitter: return bool success
Emitter-->>CLI: return ModelEventPublishResult
CLI->>CLI: log success/failure
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
| Verdict | Meaning | Blocks merge? |
|---|---|---|
passed |
No critical/error findings | No |
blocked |
CRITICAL or ERROR findings found | Yes |
degraded |
All models unavailable (infra) | No (pilot) |
Powered by omniintelligence.review_pairing.cli_review — node-based adversarial review via HandlerLlmCliSubprocess (OMN-8524)
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tests/hooks/test_cli_emit.py (1)
765-847: 💤 Low valueTest contains unused mock setup that could be simplified.
The
fake_emit_eventfunction (lines 775-779) and its patch at line 782 are never exercised becausepatched_emit_tool_contentdoesn't callemit_event— it directly captures the content and returns a successful result. Thepatch.dict("sys.modules", {})at line 785 is also a no-op since an empty dict doesn't modify anything.The test correctly validates the payload structure, but could be simplified:
♻️ Simplified test structure
def test_daemon_emission_payload_structure(self, runner: CliRunner) -> None: """Verify daemon emit_event is called with correct event type and payload. OMN-10837: tool-content now routes through node_emit_daemon instead of a direct EventBusKafka connection. This test mocks emit_event from emit_client_wrapper and verifies the payload structure is correct. """ captured_calls: list[tuple[str, dict]] = [] - def fake_emit_event( - event_type: str, payload: dict, timeout_ms: int = 3000 - ) -> bool: - captured_calls.append((event_type, payload)) - return True + def patched_emit_tool_content(content): + import json as _json + + payload = _json.loads(content.model_dump_json()) + captured_calls.append(("tool.content", payload)) + from omniclaude.hooks.models import ModelEventPublishResult + from omniclaude.hooks.topics import TopicBase, build_topic + + return ModelEventPublishResult( + success=True, + topic=build_topic(TopicBase.TOOL_CONTENT), + partition=None, + offset=None, + ) + import omniclaude.hooks.cli_emit as cli_emit_mod + - with patch( - "omniclaude.hooks.cli_emit.emit_event", fake_emit_event, create=True - ): - # Patch the module-level import inside _emit_tool_content - with patch.dict("sys.modules", {}): - import omniclaude.hooks.cli_emit as cli_emit_mod - - original_emit = None - - def patched_emit_tool_content(content): - import json as _json - - payload = _json.loads(content.model_dump_json()) - captured_calls.append(("tool.content", payload)) - from omniclaude.hooks.models import ModelEventPublishResult - from omniclaude.hooks.topics import TopicBase, build_topic - - return ModelEventPublishResult( - success=True, - topic=build_topic(TopicBase.TOOL_CONTENT), - partition=None, - offset=None, - ) - - with patch.object( - cli_emit_mod, "_emit_tool_content", patched_emit_tool_content - ): - result = runner.invoke(...) + with patch.object(cli_emit_mod, "_emit_tool_content", patched_emit_tool_content): + result = runner.invoke(...)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/hooks/test_cli_emit.py` around lines 765 - 847, The test defines an unused fake_emit_event and applies a patch for "omniclaude.hooks.cli_emit.emit_event" and also wraps the import in patch.dict("sys.modules", {}) even though patched_emit_tool_content never calls emit_event; remove the fake_emit_event function, the with patch("omniclaude.hooks.cli_emit.emit_event", ...) block, and the with patch.dict("sys.modules", {}) wrapper, instead import omniclaude.hooks.cli_emit directly and only patch cli_emit_mod._emit_tool_content (patched_emit_tool_content) and assert captured_calls as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/omniclaude/nodes/node_skill_verified_dispatch_orchestrator/contract.yaml`:
- Around line 59-70: Update all event-bus identifiers to use the hyphenated
skill-id "verified-dispatch": replace topic
("onex.cmd.omniclaude.verified_dispatch.v1") with
"onex.cmd.omniclaude.verified-dispatch.v1", consumer_group
("omniclaude.skill.verified_dispatch") with
"omniclaude.skill.verified-dispatch", success_topic
("onex.evt.omniclaude.verified_dispatch-completed.v1") and failure_topic
("onex.evt.omniclaude.verified_dispatch-failed.v1") with their hyphenated
equivalents, and update the canonical lists subscribe_topics and publish_topics
to use "onex.cmd.omniclaude.verified-dispatch.v1",
"onex.evt.omniclaude.verified-dispatch-completed.v1", and
"onex.evt.omniclaude.verified-dispatch-failed.v1" respectively.
---
Nitpick comments:
In `@tests/hooks/test_cli_emit.py`:
- Around line 765-847: The test defines an unused fake_emit_event and applies a
patch for "omniclaude.hooks.cli_emit.emit_event" and also wraps the import in
patch.dict("sys.modules", {}) even though patched_emit_tool_content never calls
emit_event; remove the fake_emit_event function, the with
patch("omniclaude.hooks.cli_emit.emit_event", ...) block, and the with
patch.dict("sys.modules", {}) wrapper, instead import omniclaude.hooks.cli_emit
directly and only patch cli_emit_mod._emit_tool_content
(patched_emit_tool_content) and assert captured_calls as before.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: fdf2e7ae-ff14-43ce-82f5-f079e73e032d
📒 Files selected for processing (7)
plugins/onex/hooks/lib/emit_client_wrapper.pyplugins/onex/lib/event_registry/omniclaude.yamlsrc/omniclaude/hooks/cli_emit.pysrc/omniclaude/nodes/node_skill_verified_dispatch_orchestrator/__init__.pysrc/omniclaude/nodes/node_skill_verified_dispatch_orchestrator/contract.yamlsrc/omniclaude/nodes/node_skill_verified_dispatch_orchestrator/node.pytests/hooks/test_cli_emit.py
…ming - Add "tool.content" EventRegistration to event_registry.py so it matches SUPPORTED_EVENT_TYPES in emit_client_wrapper (test_supported_event_types_match_event_registry) - Add "tool.content" to expected_types in test_emit_client_wrapper.py - Simplify test_daemon_emission_payload_structure in test_cli_emit.py: remove unused original_emit variable and nested sys.modules patch (fixes CodeQL unused-variable and mixed-import-style warnings) - Fix contract.yaml event-bus identifiers: verified_dispatch -> verified-dispatch in topic strings and consumer group (CodeRabbit hyphen convention)
Pull request was closed
…-through-node-emit-daemon # Conflicts: # src/omniclaude/nodes/node_skill_verified_dispatch_orchestrator/contract.yaml
Summary
EventBusKafkaembedded-publisher path in_emit_tool_content()with synchronousemit_event()call routed throughnode_emit_daemonUnix socket clienttool.contenttoSUPPORTED_EVENT_TYPESinemit_client_wrapper.pytool.content→onex.cmd.omniintelligence.tool-content.v1fan-out inomniclaude.yamltest_cli_emit.pyto mock the daemon path instead of the removedEventBusKafkapathThe daemon provides circuit-breaker + exponential backoff + disk-spool durability, eliminating the crash-loop that occurred when Redpanda restarted.
Test plan
uv run pytest tests/hooks/test_cli_emit.py— 58/58 passeduv run ruff format && uv run ruff check --fix— cleanpre-commit runon staged files — all passedEvidence-Ticket: OMN-10837
Summary by CodeRabbit
New Features
Refactor
Evidence-Ticket: OMN-10837
Evidence-Source: 151d4e88656ef645b5dd11ffedafbf492cbdbe0a