Fix pipe desync: send_ok_raw escapes newlines, expand-components? in env
- send_ok_raw: when SX wire format contains newlines (string literals), fall back to (ok "...escaped...") instead of (ok-raw ...) to keep the pipe single-line. Prevents multi-line responses from desyncing subsequent requests. - expand-components? flag set in kernel env (not just VM adapter globals) so aser-list's env-has? check finds it during component expansion. - SX_STANDALONE: restore no_oauth but generate CSRF via session cookie so mutation handlers (DELETE etc.) still work without account service. - Shell statics injection: only inject small values (hashes, URLs) as kernel vars. Large blobs (CSS, component_defs) use placeholder tokens. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -71,6 +71,22 @@ let send_ok_value v = send (Printf.sprintf "(ok %s)" (serialize_value v))
|
||||
let send_ok_string s = send (Printf.sprintf "(ok \"%s\")" (escape_sx_string s))
|
||||
let send_error msg = send (Printf.sprintf "(error \"%s\")" (escape_sx_string msg))
|
||||
|
||||
(** Send ok-raw, ensuring single-line output.
|
||||
SX wire format from aser may contain newlines inside string literals.
|
||||
We must escape those to prevent pipe desync (Python reads one line
|
||||
at a time), but we can't blindly replace newlines in the raw SX
|
||||
because that would break string content.
|
||||
|
||||
Strategy: wrap as a properly escaped string literal.
|
||||
Python side will unescape it. *)
|
||||
let send_ok_raw s =
|
||||
(* If the result has no newlines, send as-is for backward compat *)
|
||||
if not (String.contains s '\n') then
|
||||
send (Printf.sprintf "(ok-raw %s)" s)
|
||||
else
|
||||
(* Wrap as escaped string so newlines are preserved *)
|
||||
send (Printf.sprintf "(ok \"%s\")" (escape_sx_string s))
|
||||
|
||||
|
||||
(* ====================================================================== *)
|
||||
(* IO bridge — primitives that yield to Python *)
|
||||
@@ -806,7 +822,7 @@ let dispatch env cmd =
|
||||
| RawHTML s -> "\"" ^ escape_sx_string s ^ "\""
|
||||
| _ -> "nil"
|
||||
in
|
||||
send (Printf.sprintf "(ok-raw %s)" (raw_serialize result))
|
||||
send_ok_raw (raw_serialize result)
|
||||
with
|
||||
| Eval_error msg -> send_error msg
|
||||
| exn -> send_error (Printexc.to_string exn))
|
||||
@@ -830,7 +846,7 @@ let dispatch env cmd =
|
||||
(* Send raw SX wire format without re-escaping.
|
||||
Use (ok-raw ...) so Python knows not to unescape. *)
|
||||
(match result with
|
||||
| String s | SxExpr s -> send (Printf.sprintf "(ok-raw %s)" s)
|
||||
| String s | SxExpr s -> send_ok_raw s
|
||||
| _ -> send_ok_value result)
|
||||
with
|
||||
| Eval_error msg -> send_error msg
|
||||
@@ -891,7 +907,7 @@ let dispatch env cmd =
|
||||
let t2 = Unix.gettimeofday () in
|
||||
Printf.eprintf "[aser-slot] eval=%.1fs io_flush=%.1fs batched=%d result=%d chars\n%!"
|
||||
(t1 -. t0) (t2 -. t1) n_batched (String.length final);
|
||||
send (Printf.sprintf "(ok-raw %s)" final)
|
||||
send_ok_raw final
|
||||
with
|
||||
| Eval_error msg ->
|
||||
io_batch_mode := false;
|
||||
|
||||
Reference in New Issue
Block a user