llm_meta_client 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2fcc6377f3293f8ecd13b81cd79ea63891c18f55dfa05ee225a151f7e1fa5b84
4
- data.tar.gz: 35c4cba209aed5989b43606715205a7e2b85c669fa7dd71d65a33f4dd47a293a
3
+ metadata.gz: bf6557334d788f5b1e0db6604a4e243ebccbe17e747a95062e25d8cf2e5b0590
4
+ data.tar.gz: 7acf3ad5c8c5cc4d987aa26fc3264298acfd752e0d2b98bc9304dba968c39d21
5
5
  SHA512:
6
- metadata.gz: c959d77e7d3b8c9f5070bf2f63a74e83ba1082391694788e094c09629e76883dcf0142336af7742dd08fa46c0d36ec20ad31ad85b558ea4199cb8b7e3c4345fc
7
- data.tar.gz: 651d88ddb211fd11234daf2ecee22e368d8886d27e43b94c1786d4d3980cedfb078a562ee0cd0ad06a48140c7fb07cae779326237e604b21a819d4ceb663d815
6
+ metadata.gz: 1da9179adfdc90c842125f4205693aeb99faec1d5667d51e6840f10d0e82c680cbabf450b74e37a56ee3a9b56b6d69e6df1b8ebc1e22b4635eb32047b7a72abb
7
+ data.tar.gz: 904194c2c0e5251bc14edbeebe5f65d44c39e58fb1dcc178ad9ab469524ace23a2d522334f26ce1a4cec27fc5f49206875ef7d852bb582502afca3e8cd390fc7
data/CHANGELOG.md CHANGED
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.4.0] - 2026-05-11
9
+
10
+ ### Added
11
+
12
+ - Phase indicator in the streaming bubble. `message_stream_controller` now handles `event: phase` from the server and updates the role label (e.g. "🤔 Thinking…") so the user sees progress during turn 1 tool selection and turn 2 reasoning. The label auto-flips back to "🤖 streaming…" on the first content delta.
13
+ - Streaming endpoint emits SSE keepalive comment lines during long synchronous waits (works alongside the server-side heartbeat thread on `llm_meta_server`). EventSource ignores these by design; they keep the connection warm through buffering proxies.
14
+
15
+ ### Notes
16
+
17
+ - Requires `llm_meta_server` with the matching `on_phase_change` plumbing in `LlmRbFacade.stream!` and the heartbeat thread in `Api::ChatStreamsController`.
18
+
8
19
  ## [1.3.0] - 2026-05-10
9
20
 
10
21
  ### Added
@@ -15,6 +15,7 @@ export default class extends Controller {
15
15
  this.source.addEventListener("title", (e) => this.#onTitle(e))
16
16
  this.source.addEventListener("saved", (e) => this.#onSaved(e))
17
17
  this.source.addEventListener("tool_calls", (e) => this.#onToolCalls(e))
18
+ this.source.addEventListener("phase", (e) => this.#onPhase(e))
18
19
  this.source.addEventListener("error", (e) => this.#onError(e))
19
20
  }
20
21
 
@@ -26,10 +27,20 @@ export default class extends Controller {
26
27
  let delta
27
28
  try { delta = JSON.parse(event.data).delta } catch { return }
28
29
  if (!delta) return
30
+ // First content delta after a "thinking" phase: flip the role label so
31
+ // the user knows generation has actually started.
32
+ this.#exitThinkingPhase()
29
33
  this.contentTarget.append(delta)
30
34
  this.#scrollToBottom()
31
35
  }
32
36
 
37
+ #exitThinkingPhase() {
38
+ const role = this.element.querySelector(".message-role")
39
+ if (role && role.textContent.includes("Thinking")) {
40
+ role.textContent = "🤖 streaming…"
41
+ }
42
+ }
43
+
33
44
  #onTitle(event) {
34
45
  try {
35
46
  const data = JSON.parse(event.data)
@@ -69,6 +80,21 @@ export default class extends Controller {
69
80
  document.querySelectorAll(".tool-call-streaming").forEach((el) => el.remove())
70
81
  }
71
82
 
83
+ // Phase events from the server signal what it's currently doing during the
84
+ // synchronous parts of a tool turn (model thinking, tool execution). The role
85
+ // label reflects the phase so users know progress is real, not a hang.
86
+ #onPhase(event) {
87
+ let name
88
+ try { name = JSON.parse(event.data).name } catch { return }
89
+ const role = this.element.querySelector(".message-role")
90
+ if (!role) return
91
+ const labels = {
92
+ thinking: "🤔 Thinking…",
93
+ responding: "🤖 streaming…",
94
+ }
95
+ if (labels[name]) role.textContent = labels[name]
96
+ }
97
+
72
98
  // Swap the streaming bubble's role + content with the host-rendered _message
73
99
  // partial output so any markdown / syntax highlighting / partial customizations
74
100
  // applied on reload also apply right after the stream finishes. We don't
@@ -1,3 +1,3 @@
1
1
  module LlmMetaClient
2
- VERSION = "1.3.0"
2
+ VERSION = "1.4.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: llm_meta_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - dhq_boiler