Files
EvoScientist-Multi/EvoScientist/gateway/runtime.py
T
dinos f2f010a350 feat(memory): observation linking (#307)
* refactor(gateway): create module for launching async/bg agents

* refactor(memory): refactor worker launch around source context & output deltas

* refactor(gateway): generalize async/bg module

* refactor(memory): revamp worker launching

* feat(memory): add observation linking

* test(memory): remove redundant test branches

* fix(memory): make 'supersedes' relation directional

* fix(memory): don't create empty project observation dirs

* fix(memory): schedule direct observations for linking

* fix(cli): wait for observation linker before shutdown

* fix(memory): block arbitrary writes to /memories

* fix(linker): remove `linked_by` attribute from frontmatter

* refactor(linker): rename base relationship to `comlpements`

* fix(cli): bump worker wait to 2m

* feat(tools): catch malformed tool calls & retry

* feat(status): add linking result to statusbar

* fix(linker): don't launch linker when observations are disabled

* fix(memory): use posix paths

* fix(watcher): call abort hook on error status

* fix(watcher): delete thread on failed run creation

* fix(watcher): preserve url

* fix(observation): record session_id, drop unused fields

* fix(memory): reject unsupported worker source types

* refactor(backends): shared memory backend builder

* fix(scheduler): resolve linker inputs outside lock

* fix(memory): dont launch workers / record observations without thread_id

* feat(memory): include related observations in tool results

* fix(memory): skip malformed observation frontmatter

* revert(tools): drop tool error handling changes from this PR

* fix(memory): serialize observation link writes

* fix(memory): queue observations written by aborted workers

* fix(memory): track observation linker launch handoff

* fix(memory): resolve cross-project related observations

* fix(status): avoid recounting reason-only link updates

* fix(memory): avoid rereading file for content

* fix(linker): use neutral prose for bidirectional reasons

* test(memory): coverage for aborted/failed launches

* test(memory): cleanup & helpers

* feat(linker): add observations index hint
2026-06-26 22:20:52 +01:00

64 lines
1.9 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
from typing import Literal
from langgraph_sdk import get_client
from langgraph_sdk.client import LangGraphClient
from .local import LocalGraphGateway, LocalThreadStore
from .server import (
DEFAULT_GRAPH_ID,
LangGraphServerGateway,
LangGraphServerThreadStore,
)
from .types import GraphGateway, ThreadStore
RuntimeGatewayBackend = Literal["local", "langgraph_server"]
@dataclass(frozen=True, slots=True)
class RuntimeGateways:
"""Gateway handles for one CLI/TUI/serve runtime."""
thread_store: ThreadStore
graph_gateway: GraphGateway
def create_runtime_gateways(
*,
backend: RuntimeGatewayBackend = "local",
base_url: str | None = None,
graph_id: str = DEFAULT_GRAPH_ID,
headers: dict[str, str] | None = None,
langgraph_client: LangGraphClient | None = None,
) -> RuntimeGateways:
"""Create gateway handles for CLI/TUI/serve execution."""
if backend == "langgraph_server":
if base_url is None and langgraph_client is None:
raise ValueError("base_url is required for langgraph_server gateways")
server_thread_store = LangGraphServerThreadStore(
client=langgraph_client
if langgraph_client is not None
else get_client(url=base_url, headers=headers),
graph_id=graph_id,
)
return RuntimeGateways(
thread_store=server_thread_store,
graph_gateway=LangGraphServerGateway(
server_thread_store,
graph_id=graph_id,
),
)
if backend != "local":
raise ValueError(f"Unsupported runtime gateway backend: {backend}")
local_thread_store = LocalThreadStore()
return RuntimeGateways(
thread_store=local_thread_store,
graph_gateway=LocalGraphGateway(thread_store=local_thread_store),
)