feat(cli): add provider-agnostic channel bridge core (replacement)#114
feat(cli): add provider-agnostic channel bridge core (replacement)#114cdenneen wants to merge 1 commit intohappier-dev:devfrom
Conversation
|
@coderabbitai review |
|
@greptile review |
✅ Actions performedReview triggered.
|
|
Warning Rate limit exceeded
⌛ 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. ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Warning Rate limit exceeded
⌛ 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. ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
Greptile SummaryThis PR introduces the provider-agnostic channel bridge core: a polling worker that maps external messaging-channel conversations (Telegram, Discord, etc.) to Happier sessions. It adds Key changes:
The implementation is well-structured with excellent error isolation and comprehensive test coverage. Confidence Score: 5/5
|
| Filename | Overview |
|---|---|
| apps/cli/src/channels/core/channelBridgeWorker.ts | Core channel bridge worker: well-structured with good error isolation. The implementation correctly handles inbound message routing, slash commands, cursor persistence, and adapter lifecycle management with proper async handling throughout. |
| apps/cli/src/channels/core/channelBridgeWorker.test.ts | 1922-line test suite with excellent coverage of inbound commands, outbound forwarding, cursor persistence, deduplication, stop/drain semantics, and edge cases (store failures, ambiguous sessions, duplicate adapters). |
| docs/channel-bridge.md | New documentation accurately describing the core bridge runtime, tick loop behavior, binding model, and adapter contract. Correctly scopes out-of-scope items for follow-up PRs. |
| docs/README.md | Updated index adds a reference to channel-bridge.md; no issues. |
Sequence Diagram
sequenceDiagram
participant L as SingleFlightLoop
participant W as ChannelBridgeWorker (tick)
participant A as Adapter(s)
participant S as ChannelBindingStore
participant D as ChannelBridgeDeps
L->>W: runTick() [microtask]
W->>A: pullInboundMessages() [timeout guarded]
A-->>W: ChannelBridgeInboundMessage[]
alt Message is slash command
W->>D: authorizeCommand() [if not /help or /start]
D-->>W: {allowed, message}
alt authorized
W->>S: getBinding / upsertBinding / removeBinding
W->>A: sendMessage(reply)
else denied
W->>A: sendMessage(denial)
end
else Non-command message
W->>S: getBinding(ref)
S-->>W: ChannelSessionBinding | null
alt bound
W->>D: sendUserMessageToSession() [timeout guarded]
else unbound
W->>A: sendMessage("No session attached")
end
end
W->>S: listBindings()
S-->>W: ChannelSessionBinding[]
loop for each binding
W->>D: fetchAgentMessagesAfterSeq({sessionId, afterSeq})
D-->>W: [{seq, text}]
W->>W: sort by seq, filter seq > lastForwardedSeq
loop for each new row
W->>A: sendMessage({conversationId, threadId, text}) [timeout guarded]
W->>S: updateLastForwardedSeq(binding, seq) [monotonic]
end
end
Last reviewed commit: ea92de6
Summary
upstream/devSupersedes
Notes
feat/channel-bridge-core-v2