diff --git a/core/src/main/kotlin/cc/unitmesh/devti/llms/custom/ResponseBodyCallback.kt b/core/src/main/kotlin/cc/unitmesh/devti/llms/custom/ResponseBodyCallback.kt index c9d840a46..6ecc2cd8a 100644 --- a/core/src/main/kotlin/cc/unitmesh/devti/llms/custom/ResponseBodyCallback.kt +++ b/core/src/main/kotlin/cc/unitmesh/devti/llms/custom/ResponseBodyCallback.kt @@ -59,68 +59,70 @@ class ResponseBodyCallback(private val emitter: FlowableEmitter, private va reader = BufferedReader(InputStreamReader(inputStream, StandardCharsets.UTF_8)) var line: String? = null var sse: SSE? = null - while (!emitter.isCancelled && reader.readLine().also { line = it } != null) { - sse = when { - line!!.startsWith("data:") -> { - val data = line!!.substring(5).trim { it <= ' ' } - SSE(data) - } - line == "" && sse != null -> { - if (sse.isDone) { - if (emitDone) { - emitter.onNext(sse) - } - break + //用于兼容非标准格式的SSE:一条数据拆成了多行,每行都以data:开头 + val dataBuilder = StringBuilder() // 用于合并多行 data 内容 + while (!emitter.isCancelled && reader.readLine().also { line = it } != null) { + if (line!!.startsWith("data:")) { + val dataPart = line!!.substring(5).trim { it <= ' ' } + dataBuilder.append(dataPart) // 追加 data 内容 + } else if (line == "" && dataBuilder.isNotEmpty()) { + // 遇到空行且有累积的 data 内容,创建 SSE 对象 + val data = dataBuilder.toString() + sse = SSE(data) + if (sse.isDone) { + if (emitDone) { + emitter.onNext(sse) } - emitter.onNext(sse) - null + break } - // starts with event: - line!!.startsWith("event:") -> { - // https://github.com/sysid/sse-starlette/issues/16 - val eventName = line!!.substring(6).trim { it <= ' ' } - if (eventName == "ping") { - // skip ping event and data - emitter.onNext(sse ?: SSE("")) - emitter.onNext(sse ?: SSE("")) - } + emitter.onNext(sse) + dataBuilder.clear() // 清空 data 内容 + sse = null + } else { + // 其他情况,按照原逻辑处理 + sse = when { + // starts with event: + line!!.startsWith("event:") -> { + // https://github.com/sysid/sse-starlette/issues/16 + val eventName = line!!.substring(6).trim { it <= ' ' } + if (eventName == "ping") { + // skip ping event and data + emitter.onNext(sse ?: SSE("")) + emitter.onNext(sse ?: SSE("")) + } - null - } + null + } - // skip `: ping` comments for: https://github.com/sysid/sse-starlette/issues/16 - line!!.startsWith(": ping") -> { - null - } + // skip `: ping` comments for: https://github.com/sysid/sse-starlette/issues/16 + line!!.startsWith(": ping") -> { + null + } - else -> { - when { // sometimes the server maybe returns empty line line == "" -> { null } - // : is comment - // https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream - line!!.startsWith(":") -> { - null - } + // : is comment + // https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream + line!!.startsWith(":") -> { + null + } - line.startsWith("{") && line.endsWith("}") -> { - emitter.onNext(SSE(line)) - emitter.onComplete() - return - } + line.startsWith("{") && line.endsWith("}") -> { + emitter.onNext(SSE(line)) + emitter.onComplete() + return + } - else -> { - throw AutoDevHttpException("Invalid sse format! '$line'", response.code) - } + else -> { + throw AutoDevHttpException("Invalid sse format! '$line'", response.code) } } } } - emitter.onComplete() } catch (t: Throwable) { logger().error("Error while reading SSE", t) diff --git a/exts/devins-lang/src/main/kotlin/cc/unitmesh/devti/language/highlight/DevInHighlightingAnnotator.kt b/exts/devins-lang/src/main/kotlin/cc/unitmesh/devti/language/highlight/DevInHighlightingAnnotator.kt new file mode 100644 index 000000000..311de242c --- /dev/null +++ b/exts/devins-lang/src/main/kotlin/cc/unitmesh/devti/language/highlight/DevInHighlightingAnnotator.kt @@ -0,0 +1,21 @@ +package cc.unitmesh.devti.language.highlight + +import cc.unitmesh.devti.language.psi.DevInTypes +import com.intellij.lang.annotation.AnnotationHolder +import com.intellij.lang.annotation.Annotator +import com.intellij.lang.annotation.HighlightSeverity +import com.intellij.openapi.editor.DefaultLanguageHighlighterColors +import com.intellij.psi.PsiElement +import com.intellij.psi.util.PsiUtilCore + +class DevInHighlightingAnnotator : Annotator { + override fun annotate(element: PsiElement, holder: AnnotationHolder) { + when (PsiUtilCore.getElementType(element)) { + DevInTypes.IDENTIFIER -> { + holder.newSilentAnnotation(HighlightSeverity.INFORMATION) + .textAttributes(DefaultLanguageHighlighterColors.IDENTIFIER) + .create() + } + } + } +} diff --git a/exts/devins-lang/src/main/resources/cc.unitmesh.devti.language.xml b/exts/devins-lang/src/main/resources/cc.unitmesh.devti.language.xml index 18aaba9ad..d8971f69b 100644 --- a/exts/devins-lang/src/main/resources/cc.unitmesh.devti.language.xml +++ b/exts/devins-lang/src/main/resources/cc.unitmesh.devti.language.xml @@ -24,6 +24,8 @@ + +