Compare commits

...

5 Commits

Author SHA1 Message Date
Andrei Eternal e3444ccbb2 dont re-add selectedImages 2025-05-27 18:14:35 -07:00
Andrei Eternal 09d839df78 prettier 2025-05-27 18:08:28 -07:00
Andrei Eternal 52433a48fe Merge remote-tracking branch 'origin/main' into protobus-sub-addToInput 2025-05-27 18:06:51 -07:00
Andrei Eternal 2872bfcb8a formatfix 2025-05-23 13:55:43 -07:00
Andrei Eternal 952b439236 Protobus subscription for addToInput 2025-05-23 13:06:09 -07:00
5 changed files with 105 additions and 25 deletions
+3
View File
@@ -13,4 +13,7 @@ service UiService {
// Marks the current announcement as shown and returns whether an announcement should still be shown
rpc onDidShowAnnouncement(EmptyRequest) returns (Boolean);
// Subscribe to addToInput events (when user adds content via context menu)
rpc subscribeToAddToInput(EmptyRequest) returns (stream String);
}
+3 -8
View File
@@ -52,6 +52,7 @@ import {
import { Task, cwd } from "../task"
import { ClineRulesToggles } from "@shared/cline-rules"
import { sendStateUpdate } from "./state/subscribeToState"
import { sendAddToInputEvent } from "./ui/subscribeToAddToInput"
import { sendAuthCallbackEvent } from "./account/subscribeToAuthCallback"
import { refreshClineRulesToggles } from "@core/context/instructions/user-instructions/cline-rules"
import { refreshExternalRulesToggles } from "@core/context/instructions/user-instructions/external-rules"
@@ -929,10 +930,7 @@ export class Controller {
input += `\nProblems:\n${problemsString}`
}
await this.postMessageToWebview({
type: "addToInput",
text: input,
})
await sendAddToInputEvent(input)
console.log("addSelectedCodeToChat", code, filePath, languageId)
}
@@ -950,10 +948,7 @@ export class Controller {
// terminalName
// })
await this.postMessageToWebview({
type: "addToInput",
text: `Terminal output:\n\`\`\`\n${output}\n\`\`\``,
})
await sendAddToInputEvent(`Terminal output:\n\`\`\`\n${output}\n\`\`\``)
console.log("addSelectedTerminalOutputToChat", output, terminalName)
}
@@ -0,0 +1,64 @@
import * as vscode from "vscode"
import { Controller } from "../index"
import { EmptyRequest } from "../../../shared/proto/common"
import { String as ProtoString } from "../../../shared/proto/common"
import { StreamingResponseHandler, getRequestRegistry } from "../grpc-handler"
// Keep track of active addToInput subscriptions
const activeAddToInputSubscriptions = new Set<StreamingResponseHandler>()
/**
* Subscribe to addToInput events
* @param controller The controller instance
* @param request The empty request
* @param responseStream The streaming response handler
* @param requestId The ID of the request (passed by the gRPC handler)
*/
export async function subscribeToAddToInput(
controller: Controller,
request: EmptyRequest,
responseStream: StreamingResponseHandler,
requestId?: string,
): Promise<void> {
console.log("[DEBUG] set up addToInput subscription")
// Add this subscription to the active subscriptions
activeAddToInputSubscriptions.add(responseStream)
// Register cleanup when the connection is closed
const cleanup = () => {
activeAddToInputSubscriptions.delete(responseStream)
console.log("[DEBUG] Cleaned up addToInput subscription")
}
// Register the cleanup function with the request registry if we have a requestId
if (requestId) {
getRequestRegistry().registerRequest(requestId, cleanup, { type: "addToInput_subscription" }, responseStream)
}
}
/**
* Send an addToInput event to all active subscribers
* @param text The text to add to the input
*/
export async function sendAddToInputEvent(text: string): Promise<void> {
// Send the event to all active subscribers
const promises = Array.from(activeAddToInputSubscriptions).map(async (responseStream) => {
try {
const event: ProtoString = {
value: text,
}
await responseStream(
event,
false, // Not the last message
)
console.log("[DEBUG] sending addToInput event", text.length, "chars")
} catch (error) {
console.error("Error sending addToInput event:", error)
// Remove the subscription if there was an error
activeAddToInputSubscriptions.delete(responseStream)
}
})
await Promise.all(promises)
}
-1
View File
@@ -35,7 +35,6 @@ export interface ExtensionMessage {
| "userCreditsBalance"
| "userCreditsUsage"
| "userCreditsPayments"
| "addToInput"
| "browserConnectionResult"
| "fileSearchResults"
| "grpc_response" // New type for gRPC responses
+35 -16
View File
@@ -18,7 +18,7 @@ import { combineCommandSequences } from "@shared/combineCommandSequences"
import { getApiMetrics } from "@shared/getApiMetrics"
import { useExtensionState } from "@/context/ExtensionStateContext"
import { vscode } from "@/utils/vscode"
import { TaskServiceClient, SlashServiceClient, FileServiceClient } from "@/services/grpc-client"
import { TaskServiceClient, SlashServiceClient, FileServiceClient, UiServiceClient } from "@/services/grpc-client"
import HistoryPreview from "@/components/history/HistoryPreview"
import { normalizeApiConfiguration } from "@/components/settings/ApiOptions"
import Announcement from "@/components/chat/Announcement"
@@ -687,21 +687,6 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
break
}
break
case "addToInput":
setInputValue((prevValue) => {
const newText = message.text ?? ""
const newTextWithNewline = newText + "\n"
return prevValue ? `${prevValue}\n${newTextWithNewline}` : newTextWithNewline
})
// Add scroll to bottom after state update
// Auto focus the input and start the cursor on a new linefor easy typing
setTimeout(() => {
if (textAreaRef.current) {
textAreaRef.current.scrollTop = textAreaRef.current.scrollHeight
textAreaRef.current.focus()
}
}, 0)
break
}
// 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.
},
@@ -710,6 +695,40 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
useEvent("message", handleMessage)
// Set up addToInput subscription
useEffect(() => {
const cleanup = UiServiceClient.subscribeToAddToInput(
{},
{
onResponse: (event) => {
if (event.value) {
setInputValue((prevValue) => {
const newText = event.value
const newTextWithNewline = newText + "\n"
return prevValue ? `${prevValue}\n${newTextWithNewline}` : newTextWithNewline
})
// Add scroll to bottom after state update
// Auto focus the input and start the cursor on a new line for easy typing
setTimeout(() => {
if (textAreaRef.current) {
textAreaRef.current.scrollTop = textAreaRef.current.scrollHeight
textAreaRef.current.focus()
}
}, 0)
}
},
onError: (error) => {
console.error("Error in addToInput subscription:", error)
},
onComplete: () => {
console.log("addToInput subscription completed")
},
},
)
return cleanup
}, [])
useMount(() => {
// NOTE: the vscode window needs to be focused for this to work
textAreaRef.current?.focus()