webbee 0.3.5__tar.gz → 0.3.6__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.
- {webbee-0.3.5 → webbee-0.3.6}/CHANGELOG.md +7 -0
- {webbee-0.3.5 → webbee-0.3.6}/PKG-INFO +1 -1
- {webbee-0.3.5 → webbee-0.3.6}/pyproject.toml +1 -1
- webbee-0.3.6/src/webbee/__init__.py +1 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/repl.py +9 -3
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/thread.py +20 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_thread.py +22 -0
- webbee-0.3.5/src/webbee/__init__.py +0 -1
- {webbee-0.3.5 → webbee-0.3.6}/.github/workflows/publish.yml +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/.gitignore +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/LICENSE +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/README.md +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/install.sh +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/account.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/banner_art.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/checkpoints.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/cli.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/clipboard.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/commands.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/config.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/details.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/events.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/frames.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/intel/__init__.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/intel/chunker.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/intel/embed.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/intel/graph.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/intel/indexer.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/intel/models.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/intel/query.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/intel/service.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/intel/store.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/intel/vectors.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/intel/watch.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/output_pane.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/remote.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/render.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/repo.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/session.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/sessions.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/stream.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/tools.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/tui.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/src/webbee/update.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/__init__.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_account.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_checkpoints.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_cli.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_clipboard.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_commands.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_config.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_cpc_contract_stable.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_details.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_events.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_freeze_fix.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_intel_chunker.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_intel_embed.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_intel_graph.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_intel_indexer.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_intel_no_numpy.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_intel_query.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_intel_service.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_intel_store.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_intel_vectors.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_intel_watch.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_marathon.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_packaging.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_render.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_repl.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_repo.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_session.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_sessions.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_stream.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_tools.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_tui.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_tui_hardening.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_update.py +0 -0
- {webbee-0.3.5 → webbee-0.3.6}/tests/test_version.py +0 -0
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.6
|
|
4
|
+
|
|
5
|
+
- Boot replay shows only the conversation: flattened tool traffic
|
|
6
|
+
(`[tool_use …]` / `[tool_result] …` blocks the agent keeps as its own
|
|
7
|
+
working memory) no longer floods the boot screen — each replayed message
|
|
8
|
+
shows its human-readable part, pure tool messages are skipped.
|
|
9
|
+
|
|
3
10
|
## 0.3.5
|
|
4
11
|
|
|
5
12
|
- Surface-aware conversation: turns steered from Telegram/the panel render
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.6"
|
|
@@ -296,13 +296,19 @@ async def run_repl(cfg, mode: str = "default", *, once: bool = False, sink=None,
|
|
|
296
296
|
# never a boot blocker (network down, no such session yet, etc.).
|
|
297
297
|
try:
|
|
298
298
|
from imperal_mcp.client import ImperalClient
|
|
299
|
-
from webbee.thread import fetch_recent_thread,
|
|
299
|
+
from webbee.thread import (conversational_text, fetch_recent_thread,
|
|
300
|
+
truncate_for_display)
|
|
300
301
|
_iid = await ImperalClient(cfg, token_provider).whoami()
|
|
301
302
|
_msgs = await fetch_recent_thread(cfg, token_provider, f"marathon-{_iid}-rboot")
|
|
303
|
+
_shown = 0
|
|
302
304
|
for _m in _msgs[-40:]:
|
|
305
|
+
_text = conversational_text(_m.get("content", ""))
|
|
306
|
+
if not _text:
|
|
307
|
+
continue # pure tool traffic -- mind-food, not conversation
|
|
303
308
|
_sink.foreign_turn(_m.get("surface", "terminal"), _m.get("role", ""),
|
|
304
|
-
truncate_for_display(
|
|
305
|
-
|
|
309
|
+
truncate_for_display(_text))
|
|
310
|
+
_shown += 1
|
|
311
|
+
if _shown:
|
|
306
312
|
_sink.note("— live —")
|
|
307
313
|
except Exception:
|
|
308
314
|
pass # replay is best-effort; never block boot
|
|
@@ -11,6 +11,26 @@ from __future__ import annotations
|
|
|
11
11
|
|
|
12
12
|
_DISPLAY_LIMIT = 400
|
|
13
13
|
|
|
14
|
+
# The durable thread stores each tool exchange FLATTENED into the message
|
|
15
|
+
# text ("[tool_use bash] {...}" / "[tool_result] ..."), so the agent can
|
|
16
|
+
# reread its own past work. That is mind-food, not conversation -- replaying
|
|
17
|
+
# it verbatim floods the boot screen with raw JSON (Valentin, live
|
|
18
|
+
# 2026-07-15). Replay shows only the conversational part of each message.
|
|
19
|
+
_FLATTEN_MARKERS = ("[tool_use ", "[tool_result]")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def conversational_text(content) -> str:
|
|
23
|
+
"""The human-conversation part of one stored thread message: everything
|
|
24
|
+
up to the first flattened tool block, stripped. "" means the message was
|
|
25
|
+
pure tool traffic and must be skipped by the replay."""
|
|
26
|
+
text = str(content or "")
|
|
27
|
+
cut = len(text)
|
|
28
|
+
for m in _FLATTEN_MARKERS:
|
|
29
|
+
i = text.find(m)
|
|
30
|
+
if i != -1:
|
|
31
|
+
cut = min(cut, i)
|
|
32
|
+
return text[:cut].strip()
|
|
33
|
+
|
|
14
34
|
|
|
15
35
|
async def fetch_recent_thread(cfg, token_provider, session_id: str) -> list[dict]:
|
|
16
36
|
import httpx
|
|
@@ -129,3 +129,25 @@ def test_truncate_for_display_long_text_capped_with_ellipsis():
|
|
|
129
129
|
|
|
130
130
|
def test_truncate_for_display_respects_custom_limit():
|
|
131
131
|
assert truncate_for_display("abcdef", limit=3) == "abc…"
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def test_conversational_text_plain_message_untouched():
|
|
135
|
+
from webbee.thread import conversational_text
|
|
136
|
+
assert conversational_text("почини тесты") == "почини тесты"
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def test_conversational_text_pure_tool_traffic_skipped():
|
|
140
|
+
from webbee.thread import conversational_text
|
|
141
|
+
assert conversational_text('[tool_result] {"content": "COMPILE_OK", "ok": true}') == ""
|
|
142
|
+
assert conversational_text('[tool_use bash] {"command": "pytest -q"}') == ""
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def test_conversational_text_narration_kept_tool_tail_cut():
|
|
146
|
+
from webbee.thread import conversational_text
|
|
147
|
+
mixed = 'Всё компилируется чисто. Теперь коммичу.\n[tool_use bash] {"command": "git push"}'
|
|
148
|
+
assert conversational_text(mixed) == "Всё компилируется чисто. Теперь коммичу."
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def test_conversational_text_none_is_empty():
|
|
152
|
+
from webbee.thread import conversational_text
|
|
153
|
+
assert conversational_text(None) == ""
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.3.5"
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|