|
NeoGraph 0.10.0
A C++17 Graph Agent Engine Library — LangGraph for C++
|
HTTP-less, stdio-first ACP server hosting a NeoGraph engine. More...
#include <server.h>
Public Types | |
| using | NotificationSink = std::function< void(const neograph::json &)> |
| Sink for agent→client notifications (session/update). | |
Public Member Functions | |
| ACPServer (std::shared_ptr< neograph::graph::GraphEngine > engine, neograph::json info, std::shared_ptr< ACPGraphAdapter > adapter={}) | |
| void | attach_client (std::shared_ptr< ACPClient > c) |
| Install a pre-constructed client and bind it to this server. | |
| neograph::json | call_client (std::string method, neograph::json params, std::chrono::milliseconds timeout=std::chrono::seconds(30)) |
| Issue a JSON-RPC request to the connected client and block until a response arrives. | |
| AgentCapabilities & | capabilities () |
| Mutable access to the capabilities advertised in initialize. | |
| std::shared_ptr< ACPClient > | client () |
| Handle for issuing agent→client requests (fs/*, etc.). | |
| neograph::json | handle_message (const neograph::json &envelope) |
| Process exactly one parsed JSON-RPC envelope. | |
| bool | initialized () const |
| True after at least one initialize has been processed. | |
| bool | is_running () const |
True while run() is actively reading from its input stream. | |
| void | run () |
| Convenience overload — uses std::cin / std::cout. | |
| void | run (std::istream &in, std::ostream &out) |
Drive the server loop reading newline-delimited JSON-RPC envelopes from in and writing them to out. | |
| void | set_notification_sink (NotificationSink sink) |
| Where session/update notifications go. | |
| void | stop () |
| Signal a running run() loop to exit at the next message boundary. | |
HTTP-less, stdio-first ACP server hosting a NeoGraph engine.
Lifecycle:
ACPServer server(engine, info); server.run(); // blocks: reads std::cin, writes std::cout
The single-shot handle_message form is provided for testing and for embedding inside a custom transport (HTTP, WebSocket, in-process pipe). It takes one parsed JSON-RPC envelope and returns the response envelope (or a null json for notifications); side-effect notifications (session/update) are delivered through the NotificationSink set on the server.
| using neograph::acp::ACPServer::NotificationSink = std::function<void(const neograph::json&)> |
| neograph::acp::ACPServer::ACPServer | ( | std::shared_ptr< neograph::graph::GraphEngine > | engine, |
| neograph::json | info, | ||
| std::shared_ptr< ACPGraphAdapter > | adapter = {} |
||
| ) |
| engine | The graph engine that handles incoming prompts. |
| info | Free-form agent_info bag returned in initialize. Typically {"name":"my-agent","version":"0.1.0"}. |
| adapter | Optional input/output mapping override. |
| void neograph::acp::ACPServer::attach_client | ( | std::shared_ptr< ACPClient > | c | ) |
Install a pre-constructed client and bind it to this server.
Useful when the engine's nodes captured a client at compile() time before the server existed: pass that same shared_ptr here to make it usable. Replaces any previously cached client.
| neograph::json neograph::acp::ACPServer::call_client | ( | std::string | method, |
| neograph::json | params, | ||
| std::chrono::milliseconds | timeout = std::chrono::seconds(30) |
||
| ) |
Issue a JSON-RPC request to the connected client and block until a response arrives.
Used internally by ACPClient; exposed publicly so user code can issue protocol extensions (e.g. session/request_permission once that surface is added). Throws on transport not yet connected, on error envelope, and on timeout.
| AgentCapabilities & neograph::acp::ACPServer::capabilities | ( | ) |
Mutable access to the capabilities advertised in initialize.
Defaults: load_session=false, no prompt extras, no MCP transports (stdio is required by spec — its presence is implicit).
| std::shared_ptr< ACPClient > neograph::acp::ACPServer::client | ( | ) |
Handle for issuing agent→client requests (fs/*, etc.).
On first call lazily creates a client bound to this server and caches it. Subsequent calls return the same instance. Nodes in the graph capture this handle to talk back to the editor.
| neograph::json neograph::acp::ACPServer::handle_message | ( | const neograph::json & | envelope | ) |
Process exactly one parsed JSON-RPC envelope.
Returns:
{ "jsonrpc","id","result"|"error" })| bool neograph::acp::ACPServer::is_running | ( | ) | const |
True while run() is actively reading from its input stream.
Set on entry, cleared on exit. Mirrors neograph::a2a::A2AServer::is_running so a generic supervisor can poll either without protocol-specific casing.
| void neograph::acp::ACPServer::run | ( | std::istream & | in, |
| std::ostream & | out | ||
| ) |
Drive the server loop reading newline-delimited JSON-RPC envelopes from in and writing them to out.
Returns when in reaches EOF or stop() is called from another thread.
Lifecycle parallel with neograph::a2a::A2AServer: run() here is the synchronous read-loop equivalent of A2A's start() (also synchronous, blocks until shutdown). Neither server exposes a built-in async-spawn helper because the host embedder usually picks the threading model; spawn run() on a std::thread if you want it to run in the background.
| void neograph::acp::ACPServer::set_notification_sink | ( | NotificationSink | sink | ) |
Where session/update notifications go.
Default: dropped on the floor (test-friendly). When run() is driving, the sink is set to write to the output stream automatically.
| void neograph::acp::ACPServer::stop | ( | ) |
Signal a running run() loop to exit at the next message boundary.
Cancellation semantics: ACP session/cancel flips a flag that the server consults after engine->run() naturally returns — it does NOT preempt an in-flight graph turn. The session/prompt response will carry StopReason::Cancelled if the flag was set by the time the graph finished, but a long-running LLM call inside a node still completes in full. Wire cancel into your nodes (or set a tight max_steps on RunConfig) for shorter cancel latency.
Destructor semantics: ~ACPServer joins all in-flight session/prompt worker threads before returning. Each worker blocks until its engine->run() completes, so destroying the server during a 60-second LLM call blocks the destroying thread for the full duration. Drain or cancel before destruction if you need a bounded-latency teardown.