diff --git a/chat.go b/chat.go index feec519..dbcfe2a 100644 --- a/chat.go +++ b/chat.go @@ -434,10 +434,11 @@ func RunCompletion(ctx context.Context, response *Stream, request *openrouter.Ch defer stream.Close() var ( - id string - open int - close int - tool *ToolCall + id string + open int + close int + reasoning bool + tool *ToolCall ) buf := GetFreeBuffer() @@ -506,6 +507,12 @@ func RunCompletion(ctx context.Context, response *Stream, request *openrouter.Ch response.WriteChunk(NewChunk(ChunkText, delta.Content)) } else if delta.Reasoning != nil { + if !reasoning && len(delta.ReasoningDetails) != 0 { + reasoning = true + + response.WriteChunk(NewChunk(ChunkReasoningType, delta.ReasoningDetails[0].Type)) + } + response.WriteChunk(NewChunk(ChunkReasoning, *delta.Reasoning)) } else if len(delta.Images) > 0 { for _, image := range delta.Images { diff --git a/static/js/chat.js b/static/js/chat.js index 7fdc6c9..6085ccc 100644 --- a/static/js/chat.js +++ b/static/js/chat.js @@ -3,12 +3,13 @@ 0: "start", 1: "id", 2: "reason", - 3: "text", - 4: "image", - 5: "tool", - 6: "error", - 7: "end", - 8: "alive", + 3: "reason_type", + 4: "text", + 5: "image", + 6: "tool", + 7: "error", + 8: "end", + 9: "alive", }; const $version = document.getElementById("version"), @@ -166,6 +167,7 @@ #id; #role; #reasoning; + #reasoningType; #text; #images = []; #files = []; @@ -196,33 +198,48 @@ #_tool; #_statistics; - constructor(role, reasoning, text, tool = false, files = [], images = [], tags = [], time = 0, collapsed = false) { + constructor(data) { this.#id = uid(); - this.#role = role; - this.#reasoning = reasoning || ""; - this.#text = text || ""; + this.#role = data.role; + this.#reasoning = data.reasoning || ""; + this.#reasoningType = data.reasoningType || ""; + this.#text = data.text || ""; - this.#time = time; + this.#time = data.time; this.#_diff = document.createElement("div"); - this.#build(collapsed); + this.#build(data.collapsed); this.#render(); - if (tool?.name) { - this.setTool(tool); + if (data.tool?.name) { + this.setTool(data.tool); } - for (const file of files) { - this.addFile(file); + if (data.files) { + for (const file of data.files) { + this.addFile(file); + } } - for (const image of images) { - this.addImage(image); + if (data.images) { + for (const image of data.images) { + this.addImage(image); + } } - for (const tag of tags) { - this.addTag(tag); + if (data.tags) { + for (const tag of data.tags) { + this.addTag(tag); + } + } + + if (data.statistics) { + this.setStatistics(data.statistics); + } + + if (data.error) { + this.setError(data.error); } messages.push(this); @@ -755,6 +772,12 @@ } if (!only || only === "reasoning") { + let reasoning = this.#reasoning || ""; + + if (this.#reasoningType === "reasoning.summary") { + reasoning = reasoning.replace(/(? { this.#updateReasoningHeight(); @@ -825,6 +848,10 @@ if (this.#reasoning && full) { data.reasoning = this.#reasoning; + + if (this.#reasoningType) { + data.reasoningType = this.#reasoningType; + } } if (this.#images.length && full) { @@ -1003,6 +1030,13 @@ this.#save(); } + setReasoningType(type) { + this.#reasoningType = type; + + this.#render("reasoning"); + this.#save(); + } + addText(text) { this.#text += text; @@ -1333,7 +1367,9 @@ function start() { started = Date.now(); - message = new Message("assistant", "", ""); + message = new Message({ + role: "assistant", + }); message.setState("waiting"); @@ -1436,6 +1472,10 @@ message.setState("reasoning"); message.addReasoning(chunk.data); + break; + case "reason_type": + message.setReasoningType(chunk.data); + break; case "text": message.setState("receiving"); @@ -1722,25 +1762,7 @@ } loadValue("messages", []).forEach(message => { - const obj = new Message( - message.role, - message.reasoning, - message.text, - message.tool, - message.files || [], - message.images || [], - message.tags || [], - message.time || 0, - message.collapsed - ); - - if (message.statistics) { - obj.setStatistics(message.statistics); - } - - if (message.error) { - obj.setError(message.error); - } + new Message(message); }); chatTitle = loadValue("title"); @@ -1879,7 +1901,11 @@ $message.value = ""; storeValue("message", ""); - const message = new Message($role.value, "", text, false, attachments); + const message = new Message({ + role: $role.value, + text: text, + files: attachments, + }); clearAttachments(); updateTitle(); diff --git a/stream.go b/stream.go index 89ab1b9..d9fbb5f 100644 --- a/stream.go +++ b/stream.go @@ -13,15 +13,16 @@ import ( ) const ( - ChunkStart ChunkType = 0 - ChunkID ChunkType = 1 - ChunkReasoning ChunkType = 2 - ChunkText ChunkType = 3 - ChunkImage ChunkType = 4 - ChunkTool ChunkType = 5 - ChunkError ChunkType = 6 - ChunkEnd ChunkType = 7 - ChunkAlive ChunkType = 8 + ChunkStart ChunkType = 0 + ChunkID ChunkType = 1 + ChunkReasoning ChunkType = 2 + ChunkReasoningType ChunkType = 3 + ChunkText ChunkType = 4 + ChunkImage ChunkType = 5 + ChunkTool ChunkType = 6 + ChunkError ChunkType = 7 + ChunkEnd ChunkType = 8 + ChunkAlive ChunkType = 9 ) type ChunkType uint8