AG-UI alignments for AI bridge#9
Conversation
Switch AG-UI approval tooling to use aistream types and interrupt-based outcomes. Replaced agui.ToolApproval/ToolApprovalResponse usages with aistream equivalents across runner, plans, types, and client code, and call writer.Interrupt() when approval is requested. Updated tests to expect TOOL_CALL_RESULT and RUN_FINISHED interrupts (and to check interrupt metadata/choices) instead of custom approval events; added helpers (firstInterrupts, eventInterrupts, approvalChoicesFromMetadata, stringFromAny) to normalize interrupt/choice payloads. Adjusted annotateApprovalEventIDs to annotate interrupt outcomes, and updated buildAIApprovalContinuationRunWithApprovals call sites. Also updated go.mod/go.sum (dependency bumps and local replace for ai-bridge).
Bump github.com/beeper/ai-bridge and adapt code to its updated APIs. Replace ToolApprovalRequestedWithMetadata with ToolApprovalRequestedWithRequest in ai_runner, constructing an ApprovalRequest. Expand approval context to include title/description/plan/expires/choices/metadata and add parsing helpers (mapField, approvalChoicesField). Refactor DummyClient message waiting to use aibridgev2.WaitForMessageEventID with per-receiver timeouts, remove the old lookupMessageMXID usage, and centralize approval context creation via approvalContextForPrompt. These changes align the connector with the newer ai-bridge contract and provide richer approval metadata and more robust message lookup.
|
Warning Review limit reached
More reviews will be available in 52 minutes and 41 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, 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 include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (11)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
Remove the replace directive that pointed github.com/beeper/ai-bridge to a local ../ai-bridge path in go.mod so the module is resolved from its published version. go.sum is updated with checksum entries for the resolved ai-bridge pseudo-version.
| for i := min(limit, len(text)); i >= minCutoff; i-- { | ||
| if text[i-1] == ' ' { | ||
| return strings.Trim(strings.TrimSpace(text[:i]), ".,;:") | ||
| for i := min(limit+128, len(text)); i > limit; i++ { |
There was a problem hiding this comment.
Crash: this loop increments i while requiring i > limit, so it walks past len(text) and text[i-1] panics with index out of range. Earlier in the function we return when len(text) <= limit, so on entry len(text) > limit and i starts at ≥ limit+1; i++ keeps the condition true forever. This is reachable any time the descending loop above doesn't find .!? in [3/4*limit, limit] — very common for the short chars values that flow through buildLoremText → trimText → trimCompleteText. Walk forward with an upper bound instead, e.g. for i := limit + 1; i <= min(limit+128, len(text)); i++ { … }.
| log.Warn().Err(err).Str("approval_id", approvalID).Msg("Timed-out AI approval message was not found") | ||
| return | ||
| } | ||
| response := aistream.TimedOutApprovalResponse(approvalID) |
There was a problem hiding this comment.
Receiver mismatch with waitForMessageMXID. That helper tries both portal.Receiver and dc.UserLogin.ID to resolve the approval Matrix event, but this timeout fallback only queries portal.Receiver. Whenever the approval message was persisted under the alternate receiver, dc.lookupMessage returns nil and the timeout silently drops (just a Timed-out AI approval message was not found warning), so the run stays paused forever. Iterate the same receiver list here, or expose a lookupMessageByAnyReceiver(...) helper used by both paths.
| @@ -1034,44 +1225,112 @@ func approvalContextFromAny(value any) (aistream.ApprovalContext, bool) { | |||
| } | |||
There was a problem hiding this comment.
Lost fallback for stringified ApprovalContext. The previous implementation also handled case string: return approvalContextFromJSON([]byte(typed)) and a generic json.Marshal/Unmarshal round-trip. The new switch only accepts aistream.ApprovalContext, map[string]any, json.RawMessage, and []byte. Any caller that lands an approval context as a JSON-encoded string (or any other shape) will hit the bare return aistream.ApprovalContext{}, false and the approval continuation will be dropped without explanation. Either restore the string/default JSON fallback or document why this shape is now impossible.
No description provided.