mirror of
https://github.com/TencentCloud/Octop.git
synced 2026-10-20 06:19:17 +08:00
* 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>
39 lines
1.0 KiB
Python
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}]
|