refactor: LangGraph gateway layer for UI-agnostic graph and thread access (#295)

* feat(gateway): graph gateway protocol

* refactor(cli): wire gateway in cli/tui

* refactor(gateway): centralize runtime gateway init

* chore(gateway): restrict RunRequest message type

* feat(gateway): add langgraph server gateway

* chore(cli): tighten serve runtime state typing

* refactor(cli): route async task state reads through graph gateway

* refactor(gateway): support graph targets in server gateway

* refactor(cli): route session commands through graph gateway

* refactor(cli): fold thread store under graph gateway

* refactor(gateway): route graph state access through gateway

* refactor(channels): wire graph gateway

* refactor(memory): preserve graph threads for cloning

* feat(gateway): add thread cloning

* fix(tui): pass effective workspace for thread creation

* chore(memory): add workspare dir to memory worker metadata

* fix(sessions): filter preloaded UUID registy entries by the current scope

* test(fakes): use https

* refactor(consumer): consolidate imports

* fix(stream): optional summarization event

* fix(gateway): resolve abbreviated thread IDs by search

* fix(gateway): page server thread listings

* fix(gateway): emit pending interrupt events

* style: fmt

* feat(gateway): persist workspace_dir & model in thread metadata

* fix(gateway): page server thread prefix resolution

* fix(gateway): expose server thread list metadata

* refactor: add back type def

* refactor: tighten types

* revert: add back worker thread deletion

The worker thread forking changes are out of scope for now, so to
maintain parity with the existing behavior we'll leave this intact.

* fix(gateway): apply compaction to server thread history

* refactor(stream): restore direct summary replay suppression

* fix(gateway): preserve compaction state and server stream output

* fix(gateway): close local stream generator on cancellation

---------

Co-authored-by: Xi Zhang <106144707+X-iZhang@users.noreply.github.com>
This commit is contained in:
dinos
2026-06-22 15:54:14 +02:00
committed by GitHub
parent 6eb467e70b
commit bd307f3a11
49 changed files with 5071 additions and 1582 deletions
+4 -2
View File
@@ -1,6 +1,6 @@
"""Tests for the /new command."""
from unittest.mock import MagicMock
from unittest.mock import AsyncMock, MagicMock
from tests.conftest import run_async as _run
@@ -11,6 +11,7 @@ class TestNewCommand:
from EvoScientist.commands.implementation.session import NewCommand
ui = MagicMock()
ui.start_new_session = AsyncMock()
ctx = CommandContext(
agent=None,
thread_id="old-tid",
@@ -18,7 +19,7 @@ class TestNewCommand:
workspace_dir="/old/ws",
)
_run(NewCommand().execute(ctx, []))
ui.start_new_session.assert_called_once()
ui.start_new_session.assert_awaited_once()
def test_requires_agent_false(self):
from EvoScientist.commands.implementation.session import NewCommand
@@ -31,6 +32,7 @@ class TestNewCommand:
from EvoScientist.commands.implementation.session import NewCommand
ui = MagicMock()
ui.start_new_session = AsyncMock()
ctx = CommandContext(agent=None, thread_id="tid", ui=ui)
# No AttributeError even though ctx.agent is None
_run(NewCommand().execute(ctx, []))