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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bf6557334d788f5b1e0db6604a4e243ebccbe17e747a95062e25d8cf2e5b0590
|
|
4
|
+
data.tar.gz: 7acf3ad5c8c5cc4d987aa26fc3264298acfd752e0d2b98bc9304dba968c39d21
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|