Skip to content

Commit 0dca4de

Browse files
celestial-vaultElephant Lumps
andauthored
migrate partialMessage (RooCodeInc#4033)
Co-authored-by: Elephant Lumps <[email protected]>
1 parent c6e7b52 commit 0dca4de

File tree

13 files changed

+725
-62
lines changed

13 files changed

+725
-62
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
2+
// Generated by proto/build-proto.js
3+
4+
import { StreamingResponseHandler } from "./host-grpc-handler"
5+
import { handleUriServiceRequest, handleUriServiceStreamingRequest } from "./uri/index"
6+
import { handleWatchServiceRequest, handleWatchServiceStreamingRequest } from "./watch/index"
7+
8+
/**
9+
* Configuration for a host service handler
10+
*/
11+
export interface HostServiceHandlerConfig {
12+
requestHandler: (method: string, message: any) => Promise<any>
13+
streamingHandler: (
14+
method: string,
15+
message: any,
16+
responseStream: StreamingResponseHandler,
17+
requestId?: string,
18+
) => Promise<void>
19+
}
20+
21+
/**
22+
* Map of host service names to their handler configurations
23+
*/
24+
export const hostServiceHandlers: Record<string, HostServiceHandlerConfig> = {
25+
"host.UriService": {
26+
requestHandler: handleUriServiceRequest,
27+
streamingHandler: handleUriServiceStreamingRequest,
28+
},
29+
"host.WatchService": {
30+
requestHandler: handleWatchServiceRequest,
31+
streamingHandler: handleWatchServiceStreamingRequest,
32+
},
33+
}

hosts/vscode/uri/index.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
2+
// Generated by proto/build-proto.js
3+
4+
import { createServiceRegistry, ServiceMethodHandler, StreamingMethodHandler } from "../host-grpc-service"
5+
import { StreamingResponseHandler } from "../host-grpc-handler"
6+
import { registerAllMethods } from "./methods"
7+
8+
// Create uri service registry
9+
const uriService = createServiceRegistry("uri")
10+
11+
// Export the method handler types and registration function
12+
export type UriMethodHandler = ServiceMethodHandler
13+
export type UriStreamingMethodHandler = StreamingMethodHandler
14+
export const registerMethod = uriService.registerMethod
15+
16+
// Export the request handlers
17+
export const handleUriServiceRequest = uriService.handleRequest
18+
export const handleUriServiceStreamingRequest = uriService.handleStreamingRequest
19+
export const isStreamingMethod = uriService.isStreamingMethod
20+
21+
// Register all uri methods
22+
registerAllMethods()

hosts/vscode/uri/methods.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
2+
// Generated by proto/build-proto.js
3+
4+
// Import all method implementations
5+
import { registerMethod } from "./index"
6+
import { file } from "./file"
7+
import { joinPath } from "./joinPath"
8+
import { parse } from "./parse"
9+
10+
// Register all uri service methods
11+
export function registerAllMethods(): void {
12+
// Register each method with the registry
13+
registerMethod("file", file)
14+
registerMethod("joinPath", joinPath)
15+
registerMethod("parse", parse)
16+
}

hosts/vscode/watch/index.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
2+
// Generated by proto/build-proto.js
3+
4+
import { createServiceRegistry, ServiceMethodHandler, StreamingMethodHandler } from "../host-grpc-service"
5+
import { StreamingResponseHandler } from "../host-grpc-handler"
6+
import { registerAllMethods } from "./methods"
7+
8+
// Create watch service registry
9+
const watchService = createServiceRegistry("watch")
10+
11+
// Export the method handler types and registration function
12+
export type WatchMethodHandler = ServiceMethodHandler
13+
export type WatchStreamingMethodHandler = StreamingMethodHandler
14+
export const registerMethod = watchService.registerMethod
15+
16+
// Export the request handlers
17+
export const handleWatchServiceRequest = watchService.handleRequest
18+
export const handleWatchServiceStreamingRequest = watchService.handleStreamingRequest
19+
export const isStreamingMethod = watchService.isStreamingMethod
20+
21+
// Register all watch methods
22+
registerAllMethods()

hosts/vscode/watch/methods.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
2+
// Generated by proto/build-proto.js
3+
4+
// Import all method implementations
5+
import { registerMethod } from "./index"
6+
import { subscribeToFile } from "./subscribeToFile"
7+
8+
// Streaming methods for this service
9+
export const streamingMethods = ["subscribeToFile"]
10+
11+
// Register all watch service methods
12+
export function registerAllMethods(): void {
13+
// Register each method with the registry
14+
registerMethod("subscribeToFile", subscribeToFile, { isStreaming: true })
15+
}

proto/ui.proto

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,206 @@ message WebviewProviderTypeRequest {
1818
WebviewProviderType providerType = 2;
1919
}
2020

21+
// Enum for ClineMessage type
22+
enum ClineMessageType {
23+
ASK = 0;
24+
SAY = 1;
25+
}
26+
27+
// Enum for ClineAsk types
28+
enum ClineAsk {
29+
FOLLOWUP = 0;
30+
PLAN_MODE_RESPOND = 1;
31+
COMMAND = 2;
32+
COMMAND_OUTPUT = 3;
33+
COMPLETION_RESULT = 4;
34+
TOOL = 5;
35+
API_REQ_FAILED = 6;
36+
RESUME_TASK = 7;
37+
RESUME_COMPLETED_TASK = 8;
38+
MISTAKE_LIMIT_REACHED = 9;
39+
AUTO_APPROVAL_MAX_REQ_REACHED = 10;
40+
BROWSER_ACTION_LAUNCH = 11;
41+
USE_MCP_SERVER = 12;
42+
NEW_TASK = 13;
43+
CONDENSE = 14;
44+
REPORT_BUG = 15;
45+
}
46+
47+
// Enum for ClineSay types
48+
enum ClineSay {
49+
TASK = 0;
50+
ERROR = 1;
51+
API_REQ_STARTED = 2;
52+
API_REQ_FINISHED = 3;
53+
TEXT = 4;
54+
REASONING = 5;
55+
COMPLETION_RESULT_SAY = 6;
56+
USER_FEEDBACK = 7;
57+
USER_FEEDBACK_DIFF = 8;
58+
API_REQ_RETRIED = 9;
59+
COMMAND_SAY = 10;
60+
COMMAND_OUTPUT_SAY = 11;
61+
TOOL_SAY = 12;
62+
SHELL_INTEGRATION_WARNING = 13;
63+
BROWSER_ACTION_LAUNCH_SAY = 14;
64+
BROWSER_ACTION = 15;
65+
BROWSER_ACTION_RESULT = 16;
66+
MCP_SERVER_REQUEST_STARTED = 17;
67+
MCP_SERVER_RESPONSE = 18;
68+
USE_MCP_SERVER_SAY = 19;
69+
DIFF_ERROR = 20;
70+
DELETED_API_REQS = 21;
71+
CLINEIGNORE_ERROR = 22;
72+
CHECKPOINT_CREATED = 23;
73+
LOAD_MCP_DOCUMENTATION = 24;
74+
INFO = 25;
75+
}
76+
77+
// Enum for ClineSayTool tool types
78+
enum ClineSayToolType {
79+
EDITED_EXISTING_FILE = 0;
80+
NEW_FILE_CREATED = 1;
81+
READ_FILE = 2;
82+
LIST_FILES_TOP_LEVEL = 3;
83+
LIST_FILES_RECURSIVE = 4;
84+
LIST_CODE_DEFINITION_NAMES = 5;
85+
SEARCH_FILES = 6;
86+
WEB_FETCH = 7;
87+
}
88+
89+
// Enum for browser actions
90+
enum BrowserAction {
91+
LAUNCH = 0;
92+
CLICK = 1;
93+
TYPE = 2;
94+
SCROLL_DOWN = 3;
95+
SCROLL_UP = 4;
96+
CLOSE = 5;
97+
}
98+
99+
// Enum for MCP server request types
100+
enum McpServerRequestType {
101+
USE_MCP_TOOL = 0;
102+
ACCESS_MCP_RESOURCE = 1;
103+
}
104+
105+
// Enum for API request cancel reasons
106+
enum ClineApiReqCancelReason {
107+
STREAMING_FAILED = 0;
108+
USER_CANCELLED = 1;
109+
RETRIES_EXHAUSTED = 2;
110+
}
111+
112+
// Message for conversation history deleted range
113+
message ConversationHistoryDeletedRange {
114+
int32 start_index = 1;
115+
int32 end_index = 2;
116+
}
117+
118+
// Message for ClineSayTool
119+
message ClineSayTool {
120+
ClineSayToolType tool = 1;
121+
string path = 2;
122+
string diff = 3;
123+
string content = 4;
124+
string regex = 5;
125+
string file_pattern = 6;
126+
bool operation_is_located_in_workspace = 7;
127+
}
128+
129+
// Message for ClineSayBrowserAction
130+
message ClineSayBrowserAction {
131+
BrowserAction action = 1;
132+
string coordinate = 2;
133+
string text = 3;
134+
}
135+
136+
// Message for BrowserActionResult
137+
message BrowserActionResult {
138+
string screenshot = 1;
139+
string logs = 2;
140+
string current_url = 3;
141+
string current_mouse_position = 4;
142+
}
143+
144+
// Message for ClineAskUseMcpServer
145+
message ClineAskUseMcpServer {
146+
string server_name = 1;
147+
McpServerRequestType type = 2;
148+
string tool_name = 3;
149+
string arguments = 4;
150+
string uri = 5;
151+
}
152+
153+
// Message for ClinePlanModeResponse
154+
message ClinePlanModeResponse {
155+
string response = 1;
156+
repeated string options = 2;
157+
string selected = 3;
158+
}
159+
160+
// Message for ClineAskQuestion
161+
message ClineAskQuestion {
162+
string question = 1;
163+
repeated string options = 2;
164+
string selected = 3;
165+
}
166+
167+
// Message for ClineAskNewTask
168+
message ClineAskNewTask {
169+
string context = 1;
170+
}
171+
172+
// Message for API request retry status
173+
message ApiReqRetryStatus {
174+
int32 attempt = 1;
175+
int32 max_attempts = 2;
176+
int32 delay_sec = 3;
177+
string error_snippet = 4;
178+
}
179+
180+
// Message for ClineApiReqInfo
181+
message ClineApiReqInfo {
182+
string request = 1;
183+
int32 tokens_in = 2;
184+
int32 tokens_out = 3;
185+
int32 cache_writes = 4;
186+
int32 cache_reads = 5;
187+
double cost = 6;
188+
ClineApiReqCancelReason cancel_reason = 7;
189+
string streaming_failed_message = 8;
190+
ApiReqRetryStatus retry_status = 9;
191+
}
192+
193+
// Main ClineMessage type
194+
message ClineMessage {
195+
int64 ts = 1;
196+
ClineMessageType type = 2;
197+
ClineAsk ask = 3;
198+
ClineSay say = 4;
199+
string text = 5;
200+
string reasoning = 6;
201+
repeated string images = 7;
202+
repeated string files = 8;
203+
bool partial = 9;
204+
string last_checkpoint_hash = 10;
205+
bool is_checkpoint_checked_out = 11;
206+
bool is_operation_outside_workspace = 12;
207+
int32 conversation_history_index = 13;
208+
ConversationHistoryDeletedRange conversation_history_deleted_range = 14;
209+
210+
// Additional fields for specific ask/say types
211+
ClineSayTool say_tool = 15;
212+
ClineSayBrowserAction say_browser_action = 16;
213+
BrowserActionResult browser_action_result = 17;
214+
ClineAskUseMcpServer ask_use_mcp_server = 18;
215+
ClinePlanModeResponse plan_mode_response = 19;
216+
ClineAskQuestion ask_question = 20;
217+
ClineAskNewTask ask_new_task = 21;
218+
ClineApiReqInfo api_req_info = 22;
219+
}
220+
21221
// UiService provides methods for managing UI interactions
22222
service UiService {
23223
// Scrolls to a specific settings section in the settings view
@@ -43,4 +243,7 @@ service UiService {
43243

44244
// Subscribe to settings button clicked events
45245
rpc subscribeToSettingsButtonClicked(WebviewProviderTypeRequest) returns (stream Empty);
246+
247+
// Subscribe to partial message updates (streaming Cline messages as they're built)
248+
rpc subscribeToPartialMessage(EmptyRequest) returns (stream ClineMessage);
46249
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { Controller } from "../index"
2+
import { EmptyRequest } from "@shared/proto/common"
3+
import { ClineMessage } from "@shared/proto/ui"
4+
import { StreamingResponseHandler, getRequestRegistry } from "../grpc-handler"
5+
6+
// Keep track of active partial message subscriptions
7+
const activePartialMessageSubscriptions = new Set<StreamingResponseHandler>()
8+
9+
/**
10+
* Subscribe to partial message events
11+
* @param controller The controller instance
12+
* @param request The empty request
13+
* @param responseStream The streaming response handler
14+
* @param requestId The ID of the request (passed by the gRPC handler)
15+
*/
16+
export async function subscribeToPartialMessage(
17+
controller: Controller,
18+
request: EmptyRequest,
19+
responseStream: StreamingResponseHandler,
20+
requestId?: string,
21+
): Promise<void> {
22+
// Add this subscription to the active subscriptions
23+
activePartialMessageSubscriptions.add(responseStream)
24+
25+
// Register cleanup when the connection is closed
26+
const cleanup = () => {
27+
activePartialMessageSubscriptions.delete(responseStream)
28+
}
29+
30+
// Register the cleanup function with the request registry if we have a requestId
31+
if (requestId) {
32+
getRequestRegistry().registerRequest(requestId, cleanup, { type: "partial_message_subscription" }, responseStream)
33+
}
34+
}
35+
36+
/**
37+
* Send a partial message event to all active subscribers
38+
* @param partialMessage The ClineMessage to send
39+
*/
40+
export async function sendPartialMessageEvent(partialMessage: ClineMessage): Promise<void> {
41+
// Send the event to all active subscribers
42+
const promises = Array.from(activePartialMessageSubscriptions).map(async (responseStream) => {
43+
try {
44+
await responseStream(
45+
partialMessage,
46+
false, // Not the last message
47+
)
48+
} catch (error) {
49+
console.error("Error sending partial message event:", error)
50+
// Remove the subscription if there was an error
51+
activePartialMessageSubscriptions.delete(responseStream)
52+
}
53+
})
54+
55+
await Promise.all(promises)
56+
}

0 commit comments

Comments
 (0)