1313Edit a ``.das `` file, save it, and the running application picks up
1414the changes instantly --- preserving windows, GPU state, game entities,
1515and everything stored in the persistent byte store. No restart, no
16- lost state. Applications range from games to REST APIs to MCP plugins.
16+ lost state. Applications range from games to REST APIs to stdio
17+ JSON-RPC integrations and MCP plugins.
1718
1819.. contents ::
1920 :local:
@@ -164,6 +165,15 @@ and ``daslang.exe`` (standalone). Under ``daslang.exe`` the ``main()``
164165function drives the loop; under ``daslang-live.exe `` the host calls
165166``init() ``, ``update() ``, and ``shutdown() `` directly.
166167
168+ For a stdin/stdout JSON-RPC transport instead of HTTP, swap one require
169+ line and use ``examples/daslive/hello_stdio/ ``::
170+
171+ require live/live_api_stdio // instead of live/live_api
172+
173+ User commands (any ``[live_command] ``) work identically over both
174+ transports. The two transports differ in wire protocol and in how
175+ built-in lifecycle commands are surfaced; see :ref: `stdio_api ` below.
176+
167177
168178Mode detection
169179==============
@@ -195,9 +205,9 @@ Lifecycle
195205
196206**Failed reload: **
197207The host reverts to the old context, pauses execution, and stores the
198- compilation error. Retrieve it via ``GET /error `` or
199- ``get_last_error() ``. The next successful reload unpauses
200- automatically.
208+ compilation error. Retrieve it via ``GET /error ``, the
209+ ``last_error `` stdio command, or `` get_last_error() ``. The next
210+ successful reload unpauses automatically.
201211
202212**Runtime exception: **
203213The host pauses, clears the persistent store (potentially corrupted),
@@ -271,7 +281,7 @@ Reload annotations
271281 - Called after recompile, before ``init() ``. Restore state here.
272282 * - ``[before_update] ``
273283 - Called every frame before ``update() ``. Used internally by
274- ``live_api ``.
284+ ``live_api ``, `` live_api_stdio ``, and other transport agents .
275285
276286The host discovers annotated functions by name prefix
277287(``__before_reload_* ``, ``__after_reload_* ``, ``__before_update_* ``).
@@ -351,16 +361,25 @@ Helper modules
351361 * - ``live/decs_live ``
352362 - Auto-serialization of DECS entities across reloads.
353363 * - ``live/live_commands ``
354- - ``[live_command] `` annotation for REST -callable functions.
364+ - ``[live_command] `` annotation for transport -callable functions.
355365 * - ``live/live_vars ``
356366 - ``@live `` variable macro (auto-persistence).
357367 * - ``live/live_watch ``
358368 - File watcher (auto-reload on save).
359369 * - ``live/live_watch_boost ``
360370 - File watcher with diagnostic commands (recommended over
361371 ``live_watch ``).
372+ * - ``live/live_api_builtins ``
373+ - Built-in commands (``status ``, ``last_error ``, ``reload ``,
374+ ``reload_full ``, ``pause ``, ``unpause ``, ``shutdown ``). Required
375+ transitively by ``live_api_stdio `` so stdio clients can drive
376+ lifecycle by name. The HTTP transport exposes the same
377+ operations as REST endpoints (``GET /status ``, ``POST /reload ``,
378+ …) rather than pulling these built-ins in.
362379 * - ``live/live_api ``
363- - REST API server on port 9090.
380+ - REST API server on port 9090 (requires ``dasHV ``).
381+ * - ``live/live_api_stdio ``
382+ - JSON-RPC 2.0 over stdin/stdout. No ``dasHV `` dependency.
364383 * - ``live/audio_live ``
365384 - Audio state persistence across reloads.
366385
@@ -446,21 +465,43 @@ restored entities:
446465 ``live/live_commands ``
447466----------------------
448467
449- Functions annotated ``[live_command] `` are callable via
450- ``POST /command ``. Signature:
451- ``def cmd_name(input : JsonValue?) : JsonValue? ``.
452- Convention: prefix with ``cmd_ ``. The ``set_color `` command in the
453- hello example above demonstrates the pattern.
468+ Functions annotated ``[live_command] `` are callable via any installed
469+ transport — HTTP ``POST /command `` or stdio
470+ ``{"method":"name", ...} ``. Signature:
471+ ``def cmd_name(input : JsonValue?) : JsonValue? ``. Convention: prefix
472+ with ``cmd_ ``. The ``set_color `` command in the hello example above
473+ demonstrates the pattern.
454474
475+ The built-in lifecycle commands (``status ``, ``last_error ``,
476+ ``reload ``, ``reload_full ``, ``pause ``, ``unpause ``, ``shutdown ``)
477+ live in ``live/live_api_builtins ``. They are pulled in by
478+ ``live/live_api_stdio `` so stdio clients can invoke lifecycle
479+ operations by name. The HTTP transport exposes the same operations
480+ as REST endpoints (``GET /status ``, ``POST /reload ``, …) — see below.
455481
456- REST API
457- ========
482+
483+ Transports
484+ ==========
485+
486+ Two transport modules ship in-tree. Pick one — they coexist but the
487+ typical script requires only one:
488+
489+ * ``live/live_api `` — HTTP REST API on a TCP port. Requires
490+ ``dasHV ``. Lifecycle operations are surfaced as REST endpoints;
491+ user ``[live_command] `` functions are reached via ``POST /command ``.
492+ * ``live/live_api_stdio `` — JSON-RPC 2.0 over stdin/stdout. No
493+ ``dasHV `` dependency; suitable for embedding in host processes that
494+ drive the script via pipes. Lifecycle and user commands are both
495+ invoked by name in the ``method `` field.
496+
497+ REST API (``live/live_api ``)
498+ ----------------------------
458499
459500``require live/live_api `` starts an HTTP server on port 9090.
460501Configure the port with ``live_api_set_port() `` before ``init() ``.
461502
462503Endpoints
463- ---------
504+ ^^^^^^^^^
464505
465506.. list-table ::
466507 :header-rows: 1
@@ -499,7 +540,7 @@ Endpoints
499540 - JSON help with all endpoints and curl examples.
500541
501542curl examples
502- -------------
543+ ^^^^^^^^^^^^^
503544
504545Check status::
505546
@@ -518,6 +559,108 @@ When using the daslang MCP server, prefer ``live_*`` MCP tools over
518559curl (see :ref: `utils_mcp `).
519560
520561
562+ .. _stdio_api :
563+
564+ Stdio API (``live/live_api_stdio ``)
565+ -----------------------------------
566+
567+ ``require live/live_api_stdio `` installs a debug agent that reads
568+ newline-delimited JSON-RPC 2.0 messages from ``stdin `` and writes
569+ responses to ``stdout ``. No HTTP server is started; no port is opened;
570+ no ``dasHV `` dependency.
571+
572+ The ``method `` field is the live command name — any
573+ ``[live_command] `` function plus the built-ins listed below.
574+ ``params `` is passed verbatim to the command as its input
575+ ``JsonValue? ``.
576+
577+ Request / response shape::
578+
579+ → {"jsonrpc":"2.0","id":1,"method":"status"}
580+ ← {"jsonrpc":"2.0","id":1,"result":{"fps":60.0,"uptime":3.2,"paused":false,"dt":0.016,"has_error":false}}
581+
582+ → {"jsonrpc":"2.0","id":2,"method":"set_color","params":{"r":1.0,"g":0.0,"b":0.0}}
583+ ← {"jsonrpc":"2.0","id":2,"result":"{\"r\": 1.0, \"g\": 0.0, \"b\": 0.0}"}
584+
585+ → {"method":"shutdown"} ← (no response: notification)
586+
587+ The ``result `` field embeds whatever JSON value the command returned —
588+ an object when the command returned an object (``status ``), a string
589+ when the command returned a string (``set_color `` in the demo returns a
590+ ``JV(string) `` so the result is a quoted JSON string), and so on.
591+
592+ **Framing guarantee. ** The transport always writes exactly one
593+ response per line on stdout, with no embedded newlines in the envelope.
594+ ``write_json `` pretty-prints by default, so the dispatch result is
595+ post-processed by ``compact_json_whitespace `` before being embedded in
596+ the envelope — whitespace outside string literals is stripped;
597+ whitespace inside ``"..." `` is preserved verbatim.
598+
599+ **Notifications. ** Per JSON-RPC 2.0 §4.1, a request that omits the
600+ ``id `` field is a *notification *: the server MUST NOT respond.
601+ ``live_api_stdio `` honors this — fire-and-forget commands like
602+ ``{"method":"shutdown"} `` produce no output, useful for clients that
603+ don't want to bookkeep a response. An explicit ``"id":null `` is *not *
604+ a notification; the server responds with ``"id":null ``. Parse errors
605+ and invalid requests are *not * treated as notifications either — they
606+ emit ``-32700 `` / ``-32600 `` responses with ``"id":null `` so a buggy
607+ client doesn't hang waiting for a reply.
608+
609+ **Permissive JSON-RPC subset. ** Two deviations from strict JSON-RPC 2.0
610+ to ease integration with real-world clients:
611+
612+ * The ``jsonrpc `` member is **optional **. Strict compliance would
613+ reject ``{"id":1,"method":"status"} `` because the ``"jsonrpc":"2.0" ``
614+ field is missing — this transport accepts it. Requests with a
615+ different version (``"jsonrpc":"1.0" ``) are also accepted.
616+ * All other JSON-RPC 2.0 rules are enforced: ``method `` is required and
617+ must be a string, ``id `` must be string / number / null when present
618+ (objects / arrays / booleans are rejected with ``-32600 ``), and
619+ notifications produce no response.
620+
621+ Error envelopes follow JSON-RPC 2.0 codes: ``-32700 `` parse error,
622+ ``-32600 `` invalid request (missing/non-string ``method ``).
623+
624+ Available methods (built-ins from ``live/live_api_builtins ``):
625+
626+ .. list-table ::
627+ :header-rows: 1
628+ :widths: 25 75
629+
630+ * - method
631+ - Description
632+ * - ``status ``
633+ - JSON: ``fps ``, ``uptime ``, ``paused ``, ``dt ``, ``has_error ``.
634+ * - ``last_error ``
635+ - Last compilation error string (or JSON ``null `` if none).
636+ * - ``reload ``
637+ - Incremental reload.
638+ * - ``reload_full ``
639+ - Full recompile (clears ``@live `` vars).
640+ * - ``pause ``
641+ - Pause execution.
642+ * - ``unpause ``
643+ - Resume execution.
644+ * - ``shutdown ``
645+ - Graceful shutdown.
646+
647+ Any user-defined ``[live_command] `` is also callable by name.
648+
649+ .. warning ::
650+
651+ ``stdout `` is the response channel. Scripts that use this transport
652+ must redirect ``print() `` to ``stderr `` or a log file — calling
653+ ``print() `` from the script's main loop will interleave application
654+ output with JSON-RPC responses and break clients that parse stdout
655+ line-by-line. ``daslang-live `` itself logs lifecycle messages to
656+ ``stdout ``; either silence them or have the client tolerate
657+ non-JSON lines.
658+
659+ The example at ``examples/daslive/hello_stdio/ `` is the HTTP hello
660+ example with the single ``require `` line swapped — see the same
661+ ``set_color `` command driven over stdio instead of ``POST /command ``.
662+
663+
521664CLI reference
522665=============
523666
@@ -552,6 +695,9 @@ Examples
552695 - Description
553696 * - ``examples/daslive/hello/ ``
554697 - Minimal GLFW window with background color tuning.
698+ * - ``examples/daslive/hello_stdio/ ``
699+ - Minimal stdio (JSON-RPC) variant of the hello example.
700+ Same ``set_color `` command, no ``dasHV `` dependency.
555701 * - ``examples/daslive/triangle/ ``
556702 - DECS + OpenGL shaders, rotating triangle.
557703 * - ``examples/games/arcanoid/ ``
0 commit comments