@@ -8,7 +8,7 @@ import { startCursorOAuth } from "./auth";
88import { LineBuffer } from "./streaming/line-buffer.js" ;
99import { StreamToSseConverter , formatSseDone } from "./streaming/openai-sse.js" ;
1010import { parseStreamJsonLine } from "./streaming/parser.js" ;
11- import { extractText , isAssistantText } from "./streaming/types.js" ;
11+ import { extractText , extractThinking , isAssistantText , isThinking } from "./streaming/types.js" ;
1212import { createLogger } from "./utils/logger" ;
1313import { parseAgentError , formatErrorForUser , stripAnsi } from "./utils/errors" ;
1414import { OpenCodeToolDiscovery } from "./tools/discovery.js" ;
@@ -38,7 +38,16 @@ function getGlobalKey(): string {
3838 return "__opencode_cursor_proxy_server__" ;
3939}
4040
41- function createChatCompletionResponse ( model : string , content : string ) {
41+ function createChatCompletionResponse ( model : string , content : string , reasoningContent ?: string ) {
42+ const message : { role : "assistant" ; content : string ; reasoning_content ?: string } = {
43+ role : "assistant" ,
44+ content,
45+ } ;
46+
47+ if ( reasoningContent && reasoningContent . length > 0 ) {
48+ message . reasoning_content = reasoningContent ;
49+ }
50+
4251 return {
4352 id : `cursor-acp-${ Date . now ( ) } ` ,
4453 object : "chat.completion" ,
@@ -47,7 +56,7 @@ function createChatCompletionResponse(model: string, content: string) {
4756 choices : [
4857 {
4958 index : 0 ,
50- message : { role : "assistant" , content } ,
59+ message,
5160 finish_reason : "stop" ,
5261 } ,
5362 ] ,
@@ -70,16 +79,30 @@ function createChatCompletionChunk(id: string, created: number, model: string, d
7079 } ;
7180}
7281
73- function extractAssistantTextFromStream ( output : string ) : string {
82+ function extractCompletionFromStream ( output : string ) : { assistantText : string ; reasoningText : string } {
7483 const lines = output . split ( "\n" ) ;
75- let content = "" ;
84+ let assistantText = "" ;
85+ let reasoningText = "" ;
86+
7687 for ( const line of lines ) {
7788 const event = parseStreamJsonLine ( line ) ;
78- if ( event && isAssistantText ( event ) ) {
79- content = extractText ( event ) ;
89+ if ( ! event ) {
90+ continue ;
91+ }
92+
93+ if ( isAssistantText ( event ) ) {
94+ assistantText = extractText ( event ) ;
95+ }
96+
97+ if ( isThinking ( event ) ) {
98+ const thinking = extractThinking ( event ) ;
99+ if ( thinking ) {
100+ reasoningText += thinking ;
101+ }
80102 }
81103 }
82- return content ;
104+
105+ return { assistantText, reasoningText } ;
83106}
84107
85108function formatToolUpdateEvent ( update : ToolUpdate ) : string {
@@ -198,6 +221,7 @@ async function ensureCursorProxyServer(workspaceDirectory: string, toolRouter?:
198221 "--print" ,
199222 "--output-format" ,
200223 "stream-json" ,
224+ "--stream-partial-output" ,
201225 "--workspace" ,
202226 workspaceDirectory ,
203227 "--model" ,
@@ -239,8 +263,12 @@ async function ensureCursorProxyServer(workspaceDirectory: string, toolRouter?:
239263 } ) ;
240264 }
241265
242- const assistantText = extractAssistantTextFromStream ( stdout ) ;
243- const payload = createChatCompletionResponse ( model , assistantText || stdout || stderr ) ;
266+ const completion = extractCompletionFromStream ( stdout ) ;
267+ const payload = createChatCompletionResponse (
268+ model ,
269+ completion . assistantText || stdout || stderr ,
270+ completion . reasoningText || undefined ,
271+ ) ;
244272 return new Response ( JSON . stringify ( payload ) , {
245273 status : 200 ,
246274 headers : { "Content-Type" : "application/json" } ,
@@ -452,6 +480,7 @@ async function ensureCursorProxyServer(workspaceDirectory: string, toolRouter?:
452480 "--print" ,
453481 "--output-format" ,
454482 "stream-json" ,
483+ "--stream-partial-output" ,
455484 "--workspace" ,
456485 workspaceDirectory ,
457486 "--model" ,
@@ -474,7 +503,7 @@ async function ensureCursorProxyServer(workspaceDirectory: string, toolRouter?:
474503 child . on ( "close" , async ( code ) => {
475504 const stdout = Buffer . concat ( stdoutChunks ) . toString ( ) . trim ( ) ;
476505 const stderr = Buffer . concat ( stderrChunks ) . toString ( ) . trim ( ) ;
477- const assistantText = extractAssistantTextFromStream ( stdout ) ;
506+ const completion = extractCompletionFromStream ( stdout ) ;
478507
479508 if ( code !== 0 && stderr . length > 0 ) {
480509 const parsed = parseAgentError ( stderr ) ;
@@ -507,7 +536,15 @@ async function ensureCursorProxyServer(workspaceDirectory: string, toolRouter?:
507536 choices : [
508537 {
509538 index : 0 ,
510- message : { role : "assistant" , content : assistantText || stdout || stderr } ,
539+ message : {
540+ role : "assistant" ,
541+ content : completion . assistantText || stdout || stderr ,
542+ ...( completion . reasoningText
543+ ? {
544+ reasoning_content : completion . reasoningText ,
545+ }
546+ : { } ) ,
547+ } ,
511548 finish_reason : "stop" ,
512549 } ,
513550 ] ,
0 commit comments