Refactor MCP tree server: dispatch table, caching, validation, subprocess cleanup

Break up the 1735-line handle_tool match into 45 individual handler functions
with hashtable-based dispatch. Add mtime-based file parse caching (AST + CST),
consolidated run_command helper replacing 9 bare open_process_in patterns,
require_file/require_dir input validation, and pagination (limit/offset) for
sx_find_across, sx_comp_list, sx_comp_usage. Also includes pending VM changes:
rest-arity support, hyperscript parser, compiler/transpiler updates.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-08 10:12:57 +00:00
parent 4d1079aa5e
commit 387a6cb49e
19 changed files with 1353 additions and 966 deletions

View File

@@ -1132,6 +1132,9 @@ let run_foundation_tests () =
(* Spec test runner *)
(* ====================================================================== *)
(* Called after module loading to sync JIT globals with env *)
let _jit_refresh_globals : (unit -> unit) ref = ref (fun () -> ())
let run_spec_tests env test_files =
(* Find project root: walk up from cwd until we find spec/tests *)
let rec find_root dir =
@@ -1303,6 +1306,19 @@ let run_spec_tests env test_files =
load_module "bytecode.sx" lib_dir;
load_module "compiler.sx" lib_dir;
load_module "vm.sx" lib_dir;
(* Rebind vm-execute-module and code-from-value to native OCaml implementations.
The SX versions from vm.sx run bytecode step-by-step in the interpreter —
far too slow for the test suite. Native versions use the compiled OCaml VM. *)
(* Rebind vm-execute-module to use the native OCaml VM directly.
The SX version from vm.sx runs bytecode step-by-step in the interpreter.
code-from-value stays as the SX version — it produces dicts that
vm-execute-module converts to native vm_code internally. *)
ignore (Sx_types.env_bind env "vm-execute-module" (NativeFn ("vm-execute-module", fun args ->
match args with
| [code; Dict globals] ->
let c = Sx_vm.code_from_value code in
Sx_vm.execute_module c globals
| _ -> Nil)));
load_module "signals.sx" spec_dir; (* core reactive primitives *)
load_module "signals.sx" web_dir; (* web extensions *)
load_module "freeze.sx" lib_dir;
@@ -1432,6 +1448,10 @@ let run_spec_tests env test_files =
) test_files
in
(* Refresh JIT globals after all modules loaded — vm-execute-module,
code-from-value, and other late-bound functions must be visible. *)
!_jit_refresh_globals ();
List.iter (fun path ->
if Sys.file_exists path then begin
let name = Filename.basename path in
@@ -1479,6 +1499,11 @@ let () =
match e.Sx_types.parent with Some p -> env_to_globals p | None -> ()
in
env_to_globals env;
(* Seed VM globals with native primitives — CALL_PRIM resolves from globals *)
Hashtbl.iter (fun name fn ->
Hashtbl.replace globals name (NativeFn (name, fn))
) Sx_primitives.primitives;
_jit_refresh_globals := (fun () -> env_to_globals env);
(try
let compiler_path = if Sys.file_exists "lib/compiler.sx" then "lib/compiler.sx"
else "../../lib/compiler.sx" in
@@ -1493,8 +1518,16 @@ let () =
| Lambda l ->
(match l.l_compiled with
| Some cl when not (Sx_vm.is_jit_failed cl) ->
(* VmSuspended = IO perform, Eval_error "VM undefined" = missing
special form. Both fall back to CEK safely — mark as failed
so we don't retry. *)
(try Some (Sx_vm.call_closure cl args cl.vm_env_ref)
with _ -> None)
with
| Sx_vm.VmSuspended _ ->
l.l_compiled <- Some Sx_vm.jit_failed_sentinel; None
| Eval_error msg when String.length msg > 14
&& String.sub msg 0 14 = "VM undefined: " ->
l.l_compiled <- Some Sx_vm.jit_failed_sentinel; None)
| Some _ -> None
| None ->
if l.l_name = None then None
@@ -1502,7 +1535,13 @@ let () =
l.l_compiled <- Some Sx_vm.jit_failed_sentinel;
match Sx_vm.jit_compile_lambda l globals with
| Some cl -> l.l_compiled <- Some cl;
(try Some (Sx_vm.call_closure cl args cl.vm_env_ref) with _ -> None)
(try Some (Sx_vm.call_closure cl args cl.vm_env_ref)
with
| Sx_vm.VmSuspended _ ->
l.l_compiled <- Some Sx_vm.jit_failed_sentinel; None
| Eval_error msg when String.length msg > 14
&& String.sub msg 0 14 = "VM undefined: " ->
l.l_compiled <- Some Sx_vm.jit_failed_sentinel; None)
| None -> None
end)
| _ -> None);