voice-vibecoder 2.9.7__tar.gz → 2.10.1__tar.gz
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.
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/CHANGELOG.md +16 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/PKG-INFO +1 -1
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/pyproject.toml +1 -1
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/__init__.py +1 -1
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/code_providers/openclaw.py +41 -7
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/.github/workflows/ci.yml +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/.github/workflows/release.yml +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/.gitignore +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/LICENSE +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/README.md +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/app.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/index.html +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/app_config.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/audio.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/cli_serve.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/code_providers/__init__.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/code_providers/claude.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/code_providers/cursor.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/code_providers/registry.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/config.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/instances.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/server.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/session.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/tools/__init__.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/tools/agent_task.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/tools/definitions.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/tools/dispatch.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/tools/file_tree.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/tools/handlers.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/ui/__init__.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/ui/callbacks.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/ui/diff_view.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/ui/help_modal.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/ui/panels.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/ui/screen.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/ui/setup.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/ui/state.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/ui/styles.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/ui/update_modal.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/ui/wizard.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/voice_providers/__init__.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/voice_providers/openai.py +0 -0
- {voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/worktrees.py +0 -0
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- version list -->
|
|
4
4
|
|
|
5
|
+
## v2.10.1 (2026-02-21)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- Buffer streaming text to avoid fragmented output
|
|
10
|
+
([`f46e2c1`](https://github.com/snokam/voice-vibecoder/commit/f46e2c13f9eca5a42df4fa8d46ebb56e479d4bea))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## v2.10.0 (2026-02-21)
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
- Add tool and thinking stream support
|
|
18
|
+
([`21a9589`](https://github.com/snokam/voice-vibecoder/commit/21a9589bc11fbc928a6f7a8c9742948c9c38e113))
|
|
19
|
+
|
|
20
|
+
|
|
5
21
|
## v2.9.7 (2026-02-21)
|
|
6
22
|
|
|
7
23
|
### Bug Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: voice-vibecoder
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.10.1
|
|
4
4
|
Summary: Olaf The Vibecoder — a voice-controlled coding assistant using OpenAI Realtime API + Claude Code
|
|
5
5
|
Project-URL: Homepage, https://github.com/snokam/voice-vibecoder
|
|
6
6
|
Project-URL: Repository, https://github.com/snokam/voice-vibecoder
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "voice-vibecoder"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.10.1"
|
|
8
8
|
description = "Olaf The Vibecoder — a voice-controlled coding assistant using OpenAI Realtime API + Claude Code"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
{voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/code_providers/openclaw.py
RENAMED
|
@@ -243,6 +243,14 @@ class OpenClawRunner:
|
|
|
243
243
|
|
|
244
244
|
result_text = ""
|
|
245
245
|
last_text = ""
|
|
246
|
+
text_buffer = ""
|
|
247
|
+
last_flush_time = time.time()
|
|
248
|
+
|
|
249
|
+
async def flush_buffer():
|
|
250
|
+
nonlocal text_buffer
|
|
251
|
+
if text_buffer and on_output:
|
|
252
|
+
on_output(AgentOutput(category="text", content=text_buffer))
|
|
253
|
+
text_buffer = ""
|
|
246
254
|
|
|
247
255
|
while True:
|
|
248
256
|
msg = await asyncio.wait_for(ws.recv(), timeout=300.0)
|
|
@@ -257,22 +265,48 @@ class OpenClawRunner:
|
|
|
257
265
|
|
|
258
266
|
if stream == "assistant" and "text" in agent_data:
|
|
259
267
|
text = agent_data["text"]
|
|
260
|
-
#
|
|
268
|
+
# Buffer delta and flush on sentence boundaries or timeout
|
|
261
269
|
if text and len(text) > len(last_text):
|
|
262
270
|
delta = text[len(last_text):]
|
|
263
|
-
|
|
264
|
-
on_output(AgentOutput(category="text", content=delta))
|
|
271
|
+
text_buffer += delta
|
|
265
272
|
last_text = text
|
|
266
273
|
result_text = text
|
|
274
|
+
|
|
275
|
+
# Flush on sentence boundaries or every ~500ms worth of text
|
|
276
|
+
now = time.time()
|
|
277
|
+
should_flush = (
|
|
278
|
+
delta.endswith((".", "!", "?", "\n", ":", "|"))
|
|
279
|
+
or len(text_buffer) > 80
|
|
280
|
+
or (now - last_flush_time) > 0.5
|
|
281
|
+
)
|
|
282
|
+
if should_flush:
|
|
283
|
+
await flush_buffer()
|
|
284
|
+
last_flush_time = now
|
|
285
|
+
|
|
286
|
+
elif stream == "tool":
|
|
287
|
+
# Tool execution
|
|
288
|
+
name = agent_data.get("name", "")
|
|
289
|
+
status = agent_data.get("status", "")
|
|
290
|
+
if name and on_output:
|
|
291
|
+
if status == "started":
|
|
292
|
+
on_output(AgentOutput(category="tool_call", content=f"\n🔧 [{name}] "))
|
|
293
|
+
elif status == "completed":
|
|
294
|
+
result = agent_data.get("result", "")
|
|
295
|
+
if result:
|
|
296
|
+
preview = str(result)[:200]
|
|
297
|
+
on_output(AgentOutput(category="tool_result", content=f"✓ {preview}...\n"))
|
|
267
298
|
|
|
268
|
-
elif stream == "
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
299
|
+
elif stream == "thinking":
|
|
300
|
+
# Reasoning/thinking
|
|
301
|
+
text = agent_data.get("text", "")
|
|
302
|
+
delta = agent_data.get("delta", "")
|
|
303
|
+
if delta and on_output:
|
|
304
|
+
on_output(AgentOutput(category="thinking", content=delta))
|
|
272
305
|
|
|
273
306
|
elif event == "chat":
|
|
274
307
|
state = payload.get("state")
|
|
275
308
|
if state == "final":
|
|
309
|
+
await flush_buffer() # Flush remaining text
|
|
276
310
|
# Get final message
|
|
277
311
|
msg_content = payload.get("message", {})
|
|
278
312
|
if isinstance(msg_content, dict) and "content" in msg_content:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/code_providers/__init__.py
RENAMED
|
File without changes
|
{voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/code_providers/claude.py
RENAMED
|
File without changes
|
{voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/code_providers/cursor.py
RENAMED
|
File without changes
|
{voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/code_providers/registry.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/voice_providers/__init__.py
RENAMED
|
File without changes
|
{voice_vibecoder-2.9.7 → voice_vibecoder-2.10.1}/src/voice_vibecoder/voice_providers/openai.py
RENAMED
|
File without changes
|
|
File without changes
|