webbee 0.3.32__tar.gz → 0.3.33__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.32 → webbee-0.3.33}/CHANGELOG.md +11 -0
- {webbee-0.3.32 → webbee-0.3.33}/PKG-INFO +1 -1
- {webbee-0.3.32 → webbee-0.3.33}/pyproject.toml +1 -1
- webbee-0.3.33/src/webbee/__init__.py +1 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/coding_context.py +13 -1
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/tools.py +6 -1
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/tui.py +27 -1
- webbee-0.3.33/tests/test_coding_context.py +31 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_tools.py +16 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_tui.py +38 -0
- webbee-0.3.32/src/webbee/__init__.py +0 -1
- {webbee-0.3.32 → webbee-0.3.33}/.github/workflows/publish.yml +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/.gitignore +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/LICENSE +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/README.md +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/docs/superpowers/plans/2026-07-21-interactive-home-dashboard.md +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/install.sh +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/account.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/active_sessions.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/banner_art.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/boot.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/checkpoints.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/cli.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/clipboard.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/commands.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/config.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/consent.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/details.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/events.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/frames.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/home.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/home_view.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/http.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/instance_lock.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/intel/__init__.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/intel/chunker.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/intel/embed.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/intel/graph.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/intel/indexer.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/intel/models.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/intel/query.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/intel/service.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/intel/store.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/intel/vectors.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/intel/watch.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/mode_store.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/newtab_mode.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/output_pane.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/queue_panel.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/reflow.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/remote.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/render.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/repl.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/repo.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/selection.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/session.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/sessions.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/sizing.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/slots.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/steer.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/stream.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/tabs.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/thread.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/todo_panel.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/tokens.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/update.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/urlopen.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/wallet.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/src/webbee/worktrees.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/__init__.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/conftest.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_account.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_active_sessions.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_checkpoints.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_cli.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_clipboard.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_commands.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_config.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_cpc_contract_stable.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_details.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_events.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_freeze_fix.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_home.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_home_view.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_instance_lock.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_intel_chunker.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_intel_embed.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_intel_graph.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_intel_indexer.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_intel_no_numpy.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_intel_query.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_intel_service.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_intel_store.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_intel_vectors.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_intel_watch.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_marathon.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_mode_store.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_newtab_mode.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_packaging.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_reflow.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_render.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_repl.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_repo.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_session.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_sessions.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_sizing.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_slots.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_steer.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_stream.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_tabs.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_thread.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_todo_panel.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_tokens.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_tui_hardening.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_update.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_urlopen.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_version.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_wallet.py +0 -0
- {webbee-0.3.32 → webbee-0.3.33}/tests/test_worktrees.py +0 -0
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.33
|
|
4
|
+
|
|
5
|
+
Performance.
|
|
6
|
+
|
|
7
|
+
- When nothing is happening, the terminal now wakes about once a second
|
|
8
|
+
instead of four times a second — easier on the CPU and the battery — while
|
|
9
|
+
staying instant the moment a task runs or you're drag-scrolling.
|
|
10
|
+
- The agent's file search and per-task project snapshot no longer crawl
|
|
11
|
+
`node_modules`, `vendor`, `dist`, `build`, and friends, so both stay fast on
|
|
12
|
+
large repositories.
|
|
13
|
+
|
|
3
14
|
## 0.3.32
|
|
4
15
|
|
|
5
16
|
- Fixed the screen getting scrambled by stray output from background helper
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.33"
|
|
@@ -5,6 +5,17 @@ proof-of-done command a marathon carries in that context."""
|
|
|
5
5
|
import os
|
|
6
6
|
import subprocess
|
|
7
7
|
|
|
8
|
+
# Heavy dependency/build dirs the file-tree walk and the agent `grep` tool
|
|
9
|
+
# must NEVER descend: they blow up walk time on real repos and (with the tree's
|
|
10
|
+
# 200-file cap) would otherwise fill the snapshot with dependency junk instead
|
|
11
|
+
# of the user's own code. `.git` + all dotdirs are pruned separately by the
|
|
12
|
+
# callers; these are the non-dot offenders. Shared with tools._t_grep.
|
|
13
|
+
WALK_IGNORE_DIRS = frozenset({
|
|
14
|
+
"node_modules", "vendor", "dist", "build", "target", "__pycache__",
|
|
15
|
+
".git", ".venv", "venv", ".next", ".cache", ".tox", ".mypy_cache",
|
|
16
|
+
".pytest_cache",
|
|
17
|
+
})
|
|
18
|
+
|
|
8
19
|
|
|
9
20
|
def build_coding_context(workspace_root: str, intel=None) -> dict:
|
|
10
21
|
"""Snapshot handed to the cloud brain: cwd (realpath), `git status -sb`
|
|
@@ -23,7 +34,8 @@ def build_coding_context(workspace_root: str, intel=None) -> dict:
|
|
|
23
34
|
git = ""
|
|
24
35
|
paths = []
|
|
25
36
|
for dirpath, dirnames, filenames in os.walk(cwd):
|
|
26
|
-
dirnames[:] = [d for d in dirnames
|
|
37
|
+
dirnames[:] = [d for d in dirnames
|
|
38
|
+
if d not in WALK_IGNORE_DIRS and not d.startswith(".")]
|
|
27
39
|
for fn in filenames:
|
|
28
40
|
paths.append(os.path.relpath(os.path.join(dirpath, fn), cwd))
|
|
29
41
|
if len(paths) >= 200:
|
|
@@ -327,12 +327,17 @@ class LocalToolExecutor:
|
|
|
327
327
|
return {"ok": proc.returncode == 0, "content": out or f"(exit {proc.returncode})"}
|
|
328
328
|
|
|
329
329
|
def _t_grep(self, a: dict) -> dict:
|
|
330
|
+
from webbee.coding_context import WALK_IGNORE_DIRS
|
|
330
331
|
pat = re.compile(a["pattern"])
|
|
331
332
|
base = self.resolve_in_workspace(a.get("path", "."))
|
|
332
333
|
hits = []
|
|
333
|
-
for dp,
|
|
334
|
+
for dp, dns, fns in os.walk(base):
|
|
334
335
|
if _is_git_dir(dp):
|
|
336
|
+
dns[:] = []
|
|
335
337
|
continue
|
|
338
|
+
# Prune heavy dependency/build dirs (node_modules, vendor, dist,
|
|
339
|
+
# …) so a grep on a real repo doesn't crawl megabytes of deps.
|
|
340
|
+
dns[:] = [d for d in dns if d not in WALK_IGNORE_DIRS]
|
|
336
341
|
for fn in fns:
|
|
337
342
|
fp = os.path.join(dp, fn)
|
|
338
343
|
try:
|
|
@@ -211,6 +211,32 @@ def _width_watch(pane, app) -> None:
|
|
|
211
211
|
pass
|
|
212
212
|
|
|
213
213
|
|
|
214
|
+
def _ticker_busy(slots, is_busy) -> bool:
|
|
215
|
+
"""Whether the dock's animation loop must stay at the FAST (0.25s) cadence:
|
|
216
|
+
a turn is running, a copy-flash toast is live, OR an edge-drag auto-scroll
|
|
217
|
+
is in flight (`pane._edge_drag` — a drag-select past the viewport edge that
|
|
218
|
+
`pane.edge_tick()` keeps scrolling every tick). All three need smooth ~4x/s
|
|
219
|
+
updates; miss the edge-drag one and idle drag-scrolling crawls 4x slower.
|
|
220
|
+
Otherwise the loop is idle → the caller uses the slow 1.0s cadence."""
|
|
221
|
+
try:
|
|
222
|
+
pane = slots.active().pane
|
|
223
|
+
if bool(pane.flash()) or bool(getattr(pane, "_edge_drag", 0)):
|
|
224
|
+
return True
|
|
225
|
+
except Exception:
|
|
226
|
+
pass
|
|
227
|
+
return bool(is_busy())
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def _tick_interval(busy: bool) -> float:
|
|
231
|
+
"""The dock's animation-loop sleep. 0.25s while a turn is running (or a
|
|
232
|
+
copy-flash is live) so the spinner/elapsed-clock animate smoothly; 1.0s
|
|
233
|
+
when fully idle, so the loop wakes 1×/s instead of 4×/s (less CPU/battery)
|
|
234
|
+
with no visible cost — an idle tick only resize-detects + re-syncs hover,
|
|
235
|
+
both of which tolerate a 1s lag (and a turn's first frame still shows
|
|
236
|
+
instantly via the submit's own invalidate)."""
|
|
237
|
+
return 0.25 if busy else 1.0
|
|
238
|
+
|
|
239
|
+
|
|
214
240
|
def _tick_once(slots, app, is_busy) -> None:
|
|
215
241
|
"""One iteration of run_session's `_ticker` loop, extracted module-level
|
|
216
242
|
so the wiring itself is directly unit-testable (an `async def` infinite
|
|
@@ -1272,7 +1298,7 @@ async def run_session(*, slots, on_line, on_cycle, steps_nav=None,
|
|
|
1272
1298
|
# is_busy this ticker feeds it, since the old top-level is_busy
|
|
1273
1299
|
# param died with the rest of the sink-shaped params.
|
|
1274
1300
|
while True:
|
|
1275
|
-
await asyncio.sleep(
|
|
1301
|
+
await asyncio.sleep(_tick_interval(_ticker_busy(slots, _busy_live)))
|
|
1276
1302
|
_sync_hover_mode()
|
|
1277
1303
|
_tick_once(slots, app, _busy_live)
|
|
1278
1304
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from webbee.coding_context import WALK_IGNORE_DIRS, build_coding_context
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_walk_ignore_dirs_has_the_heavy_hitters():
|
|
5
|
+
for d in ("node_modules", "vendor", "dist", "build", "target", "__pycache__"):
|
|
6
|
+
assert d in WALK_IGNORE_DIRS
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_build_coding_context_prunes_heavy_dirs(tmp_path):
|
|
10
|
+
# W6: the per-turn file-tree walk must not descend node_modules/etc. — on a
|
|
11
|
+
# real repo it's slow and (with the 200-file cap) would fill the snapshot
|
|
12
|
+
# with dependency junk instead of the user's own code.
|
|
13
|
+
(tmp_path / "src").mkdir()
|
|
14
|
+
(tmp_path / "src" / "a.py").write_text("x\n")
|
|
15
|
+
nm = tmp_path / "node_modules" / "pkg"
|
|
16
|
+
nm.mkdir(parents=True)
|
|
17
|
+
(nm / "index.js").write_text("y\n")
|
|
18
|
+
tree = build_coding_context(str(tmp_path))["tree"]
|
|
19
|
+
assert "src/a.py" in tree
|
|
20
|
+
assert "node_modules" not in tree
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_build_coding_context_still_prunes_dotdirs(tmp_path):
|
|
24
|
+
(tmp_path / "src").mkdir()
|
|
25
|
+
(tmp_path / "src" / "a.py").write_text("x\n")
|
|
26
|
+
hidden = tmp_path / ".secret"
|
|
27
|
+
hidden.mkdir()
|
|
28
|
+
(hidden / "k.txt").write_text("y\n")
|
|
29
|
+
tree = build_coding_context(str(tmp_path))["tree"]
|
|
30
|
+
assert "src/a.py" in tree
|
|
31
|
+
assert ".secret" not in tree
|
|
@@ -49,6 +49,22 @@ def test_grep_skips_git_dir(tmp_path):
|
|
|
49
49
|
assert r["ok"] and "a.py" in r["content"] and ".git" not in r["content"]
|
|
50
50
|
|
|
51
51
|
|
|
52
|
+
def test_grep_prunes_heavy_dirs(tmp_path):
|
|
53
|
+
# W6: a code grep must never crawl node_modules/vendor/dist/etc. — huge and
|
|
54
|
+
# never what the user meant. A match in src surfaces; one in node_modules
|
|
55
|
+
# does not (the walk is pruned, not just filtered).
|
|
56
|
+
ex = _ex(tmp_path)
|
|
57
|
+
(tmp_path / "src").mkdir()
|
|
58
|
+
(tmp_path / "src" / "a.py").write_text("needle\n")
|
|
59
|
+
nm = tmp_path / "node_modules" / "pkg"
|
|
60
|
+
nm.mkdir(parents=True)
|
|
61
|
+
(nm / "index.js").write_text("needle\n")
|
|
62
|
+
r = ex.run("grep", {"pattern": "needle"})
|
|
63
|
+
assert r["ok"]
|
|
64
|
+
assert "a.py" in r["content"]
|
|
65
|
+
assert "node_modules" not in r["content"]
|
|
66
|
+
|
|
67
|
+
|
|
52
68
|
def test_grep_skips_git_dir_windows_style():
|
|
53
69
|
# The os.walk-driven .git skip in _t_grep normalizes dp with os.sep so it
|
|
54
70
|
# also matches on Windows, where os.walk yields backslash paths (an
|
|
@@ -5206,3 +5206,41 @@ def test_hover_scoping_present_and_home_only():
|
|
|
5206
5206
|
src = inspect.getsource(tui.run_session)
|
|
5207
5207
|
assert "?1003h" in src and "?1003l" in src
|
|
5208
5208
|
assert "_sync_hover_mode" in src
|
|
5209
|
+
|
|
5210
|
+
|
|
5211
|
+
def test_tick_interval_fast_when_busy_slow_when_idle():
|
|
5212
|
+
# W6: the animation loop wakes 4x/s only while busy/flash; 1x/s when idle.
|
|
5213
|
+
from webbee.tui import _tick_interval
|
|
5214
|
+
assert _tick_interval(True) == 0.25
|
|
5215
|
+
assert _tick_interval(False) == 1.0
|
|
5216
|
+
|
|
5217
|
+
|
|
5218
|
+
def test_ticker_busy_includes_turn_flash_and_edge_drag():
|
|
5219
|
+
# W6 review fix: the fast-cadence predicate must fire for a running turn,
|
|
5220
|
+
# a live copy-flash, AND an in-flight edge-drag auto-scroll (else idle
|
|
5221
|
+
# drag-scrolling crawls 4x slower). A pane lacking _edge_drag (HomeView)
|
|
5222
|
+
# must not crash.
|
|
5223
|
+
from webbee.tui import _ticker_busy
|
|
5224
|
+
|
|
5225
|
+
class _Pane:
|
|
5226
|
+
def __init__(self, flash="", edge=0):
|
|
5227
|
+
self._flash, self._edge_drag = flash, edge
|
|
5228
|
+
def flash(self):
|
|
5229
|
+
return self._flash
|
|
5230
|
+
|
|
5231
|
+
class _Slots:
|
|
5232
|
+
def __init__(self, pane):
|
|
5233
|
+
self._p = pane
|
|
5234
|
+
def active(self):
|
|
5235
|
+
return type("S", (), {"pane": self._p})()
|
|
5236
|
+
|
|
5237
|
+
idle, running = (lambda: False), (lambda: True)
|
|
5238
|
+
assert _ticker_busy(_Slots(_Pane()), idle) is False
|
|
5239
|
+
assert _ticker_busy(_Slots(_Pane()), running) is True
|
|
5240
|
+
assert _ticker_busy(_Slots(_Pane(flash="copied")), idle) is True
|
|
5241
|
+
assert _ticker_busy(_Slots(_Pane(edge=1)), idle) is True
|
|
5242
|
+
|
|
5243
|
+
class _Bare:
|
|
5244
|
+
def flash(self):
|
|
5245
|
+
return ""
|
|
5246
|
+
assert _ticker_busy(_Slots(_Bare()), idle) is False
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.3.32"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{webbee-0.3.32 → webbee-0.3.33}/docs/superpowers/plans/2026-07-21-interactive-home-dashboard.md
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
|
|
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
|
|
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
|