Files
e02174e358 feat: plugin marketplace and related dashboard polish (#815)
* feat: add in-tree plugin marketplace and related dashboard polish

Ship a catalog install flow (market API + Admin UI), stop auto-seeding new
bundled plugins, and include storage rename, plugin tools listing, agent
lifecycle locking, and history/trajectory path cleanup in the same change.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(dashboard): use ToolsTabs in Experts tools drawer

Align the Experts tools catalog with Personalization so builtin, plugin,
and ACP tabs are available in the same drawer.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: per-tool chat icons and init seed expectation

Show distinct Lucide icons for common built-in tools in chat tool rows,
and stop expecting octop init to auto-copy catalog plugins after the
marketplace seed change.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(test): drain captcha siteverify POST bodies on Windows

Unread form bodies from the mock HTTP server could leave the connection
half-closed and flake reCAPTCHA v3 multi-call assertions under Windows CI.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: jubaoliang <jubaoliang@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 19:35:36 +08:00

39 lines
1.0 KiB
Python

"""TrajectoryLiveBus — in-process pub/sub per thread_id."""
from __future__ import annotations
from octop.infra.history.trajectory.live import TrajectoryLiveBus
def test_publish_delivers_to_subscriber() -> None:
bus = TrajectoryLiveBus()
queue = bus.subscribe("T1")
message = {"event_id": "e1", "kind": "user"}
bus.publish("T1", message)
assert queue.get_nowait() == message
def test_unsubscribe_stops_delivery_and_isolates_threads() -> None:
bus = TrajectoryLiveBus()
t1 = bus.subscribe("T1")
t2 = bus.subscribe("T2")
bus.unsubscribe("T1", t1)
bus.publish("T1", {"event_id": "dropped"})
bus.publish("T2", {"event_id": "kept"})
assert t1.empty()
assert t2.get_nowait() == {"event_id": "kept"}
def test_slow_subscriber_keeps_only_latest_bounded_events() -> None:
bus = TrajectoryLiveBus(subscriber_queue_size=2)
queue = bus.subscribe("T1")
for seq in range(4):
bus.publish("T1", {"seq": seq})
assert [queue.get_nowait(), queue.get_nowait()] == [{"seq": 2}, {"seq": 3}]