Skip to content

Commit 3938e23

Browse files
GarothAndrei Eternal
andauthored
[PROTOBUS] subscription for addToInput (RooCodeInc#3781)
* Protobus subscription for addToInput * formatfix * prettier * dont re-add selectedImages --------- Co-authored-by: Andrei Eternal <[email protected]>
1 parent 86bb0c6 commit 3938e23

File tree

5 files changed

+105
-25
lines changed

5 files changed

+105
-25
lines changed

proto/ui.proto

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,7 @@ service UiService {
1313

1414
// Marks the current announcement as shown and returns whether an announcement should still be shown
1515
rpc onDidShowAnnouncement(EmptyRequest) returns (Boolean);
16+
17+
// Subscribe to addToInput events (when user adds content via context menu)
18+
rpc subscribeToAddToInput(EmptyRequest) returns (stream String);
1619
}

src/core/controller/index.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import {
5252
import { Task, cwd } from "../task"
5353
import { ClineRulesToggles } from "@shared/cline-rules"
5454
import { sendStateUpdate } from "./state/subscribeToState"
55+
import { sendAddToInputEvent } from "./ui/subscribeToAddToInput"
5556
import { sendAuthCallbackEvent } from "./account/subscribeToAuthCallback"
5657
import { refreshClineRulesToggles } from "@core/context/instructions/user-instructions/cline-rules"
5758
import { refreshExternalRulesToggles } from "@core/context/instructions/user-instructions/external-rules"
@@ -922,10 +923,7 @@ export class Controller {
922923
input += `\nProblems:\n${problemsString}`
923924
}
924925

925-
await this.postMessageToWebview({
926-
type: "addToInput",
927-
text: input,
928-
})
926+
await sendAddToInputEvent(input)
929927

930928
console.log("addSelectedCodeToChat", code, filePath, languageId)
931929
}
@@ -943,10 +941,7 @@ export class Controller {
943941
// terminalName
944942
// })
945943

946-
await this.postMessageToWebview({
947-
type: "addToInput",
948-
text: `Terminal output:\n\`\`\`\n${output}\n\`\`\``,
949-
})
944+
await sendAddToInputEvent(`Terminal output:\n\`\`\`\n${output}\n\`\`\``)
950945

951946
console.log("addSelectedTerminalOutputToChat", output, terminalName)
952947
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import * as vscode from "vscode"
2+
import { Controller } from "../index"
3+
import { EmptyRequest } from "../../../shared/proto/common"
4+
import { String as ProtoString } from "../../../shared/proto/common"
5+
import { StreamingResponseHandler, getRequestRegistry } from "../grpc-handler"
6+
7+
// Keep track of active addToInput subscriptions
8+
const activeAddToInputSubscriptions = new Set<StreamingResponseHandler>()
9+
10+
/**
11+
* Subscribe to addToInput events
12+
* @param controller The controller instance
13+
* @param request The empty request
14+
* @param responseStream The streaming response handler
15+
* @param requestId The ID of the request (passed by the gRPC handler)
16+
*/
17+
export async function subscribeToAddToInput(
18+
controller: Controller,
19+
request: EmptyRequest,
20+
responseStream: StreamingResponseHandler,
21+
requestId?: string,
22+
): Promise<void> {
23+
console.log("[DEBUG] set up addToInput subscription")
24+
25+
// Add this subscription to the active subscriptions
26+
activeAddToInputSubscriptions.add(responseStream)
27+
28+
// Register cleanup when the connection is closed
29+
const cleanup = () => {
30+
activeAddToInputSubscriptions.delete(responseStream)
31+
console.log("[DEBUG] Cleaned up addToInput subscription")
32+
}
33+
34+
// Register the cleanup function with the request registry if we have a requestId
35+
if (requestId) {
36+
getRequestRegistry().registerRequest(requestId, cleanup, { type: "addToInput_subscription" }, responseStream)
37+
}
38+
}
39+
40+
/**
41+
* Send an addToInput event to all active subscribers
42+
* @param text The text to add to the input
43+
*/
44+
export async function sendAddToInputEvent(text: string): Promise<void> {
45+
// Send the event to all active subscribers
46+
const promises = Array.from(activeAddToInputSubscriptions).map(async (responseStream) => {
47+
try {
48+
const event: ProtoString = {
49+
value: text,
50+
}
51+
await responseStream(
52+
event,
53+
false, // Not the last message
54+
)
55+
console.log("[DEBUG] sending addToInput event", text.length, "chars")
56+
} catch (error) {
57+
console.error("Error sending addToInput event:", error)
58+
// Remove the subscription if there was an error
59+
activeAddToInputSubscriptions.delete(responseStream)
60+
}
61+
})
62+
63+
await Promise.all(promises)
64+
}

src/shared/ExtensionMessage.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ export interface ExtensionMessage {
3535
| "userCreditsBalance"
3636
| "userCreditsUsage"
3737
| "userCreditsPayments"
38-
| "addToInput"
3938
| "browserConnectionResult"
4039
| "fileSearchResults"
4140
| "grpc_response" // New type for gRPC responses

webview-ui/src/components/chat/ChatView.tsx

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { combineCommandSequences } from "@shared/combineCommandSequences"
1818
import { getApiMetrics } from "@shared/getApiMetrics"
1919
import { useExtensionState } from "@/context/ExtensionStateContext"
2020
import { vscode } from "@/utils/vscode"
21-
import { TaskServiceClient, SlashServiceClient, FileServiceClient } from "@/services/grpc-client"
21+
import { TaskServiceClient, SlashServiceClient, FileServiceClient, UiServiceClient } from "@/services/grpc-client"
2222
import HistoryPreview from "@/components/history/HistoryPreview"
2323
import { normalizeApiConfiguration } from "@/components/settings/ApiOptions"
2424
import Announcement from "@/components/chat/Announcement"
@@ -686,21 +686,6 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
686686
break
687687
}
688688
break
689-
case "addToInput":
690-
setInputValue((prevValue) => {
691-
const newText = message.text ?? ""
692-
const newTextWithNewline = newText + "\n"
693-
return prevValue ? `${prevValue}\n${newTextWithNewline}` : newTextWithNewline
694-
})
695-
// Add scroll to bottom after state update
696-
// Auto focus the input and start the cursor on a new linefor easy typing
697-
setTimeout(() => {
698-
if (textAreaRef.current) {
699-
textAreaRef.current.scrollTop = textAreaRef.current.scrollHeight
700-
textAreaRef.current.focus()
701-
}
702-
}, 0)
703-
break
704689
}
705690
// textAreaRef.current is not explicitly required here since react guarantees that ref will be stable across re-renders, and we're not using its value but its reference.
706691
},
@@ -709,6 +694,40 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
709694

710695
useEvent("message", handleMessage)
711696

697+
// Set up addToInput subscription
698+
useEffect(() => {
699+
const cleanup = UiServiceClient.subscribeToAddToInput(
700+
{},
701+
{
702+
onResponse: (event) => {
703+
if (event.value) {
704+
setInputValue((prevValue) => {
705+
const newText = event.value
706+
const newTextWithNewline = newText + "\n"
707+
return prevValue ? `${prevValue}\n${newTextWithNewline}` : newTextWithNewline
708+
})
709+
// Add scroll to bottom after state update
710+
// Auto focus the input and start the cursor on a new line for easy typing
711+
setTimeout(() => {
712+
if (textAreaRef.current) {
713+
textAreaRef.current.scrollTop = textAreaRef.current.scrollHeight
714+
textAreaRef.current.focus()
715+
}
716+
}, 0)
717+
}
718+
},
719+
onError: (error) => {
720+
console.error("Error in addToInput subscription:", error)
721+
},
722+
onComplete: () => {
723+
console.log("addToInput subscription completed")
724+
},
725+
},
726+
)
727+
728+
return cleanup
729+
}, [])
730+
712731
useMount(() => {
713732
// NOTE: the vscode window needs to be focused for this to work
714733
textAreaRef.current?.focus()

0 commit comments

Comments
 (0)