localharness 0.51.0

Agents that own themselves: one Rust crate that's both an agent SDK (streaming, tools, hooks, policies, triggers, MCP) and a wallet-owning, self-sovereign agent that runs in the browser.
Documentation
;; hello.wat — a tiny WASI command for the in-browser WASI-subset sandbox.
;;
;; A demonstrable end-to-end CLI: it exports `_start` (the WASI command entry),
;; prints a fixed greeting AND its argv to stdout via `fd_write`, then calls
;; `proc_exit(0)`. Hand-authored WAT so the example needs no Rust/clang wasi-sdk
;; toolchain to (re)build — `wat2wasm examples/cli/hello.wat -o examples/cli/hello.wasm`.
;;
;; Any real wasm32-wasi command (`clang --target=wasm32-wasi`, `rustc --target
;; wasm32-wasi`, TinyGo, etc.) exporting `_start` runs under the SAME host; this
;; file is just the committed proof so the path works with zero external setup.
(module
  ;; The WASI host import we use: fd_write(fd, iovs, iovs_len, nwritten) -> errno.
  (import "wasi_snapshot_preview1" "fd_write"
    (func $fd_write (param i32 i32 i32 i32) (result i32)))
  (import "wasi_snapshot_preview1" "proc_exit" (func $proc_exit (param i32)))
  ;; args_sizes_get(argc_ptr, buf_size_ptr) + args_get(argv_ptr, argv_buf_ptr).
  (import "wasi_snapshot_preview1" "args_sizes_get"
    (func $args_sizes_get (param i32 i32) (result i32)))
  (import "wasi_snapshot_preview1" "args_get"
    (func $args_get (param i32 i32) (result i32)))

  (memory (export "memory") 1)

  ;; The greeting string, laid out at offset 100.
  (data (i32.const 100) "hello from wasm cli\0a")          ;; 20 bytes incl. \n
  ;; A label before we dump argv.
  (data (i32.const 200) "argv:\0a")                         ;; 6 bytes

  ;; Print a [ptr,len] region to stdout (fd 1) using one iovec at scratch 8..16
  ;; and nwritten at scratch 0.
  (func $print (param $ptr i32) (param $len i32)
    (i32.store (i32.const 8) (local.get $ptr))    ;; iov.base
    (i32.store (i32.const 12) (local.get $len))   ;; iov.len
    (drop (call $fd_write
      (i32.const 1)        ;; fd = stdout
      (i32.const 8)        ;; iovs ptr
      (i32.const 1)        ;; iovs len
      (i32.const 0)))      ;; nwritten ptr
  )

  (func (export "_start")
    (local $argc i32)
    (local $i i32)
    (local $argv_ptr i32)
    (local $str i32)
    (local $slen i32)
    ;; greeting
    (call $print (i32.const 100) (i32.const 20))
    ;; "argv:\n"
    (call $print (i32.const 200) (i32.const 6))

    ;; args_sizes_get -> argc at 300, buf size at 304
    (drop (call $args_sizes_get (i32.const 300) (i32.const 304)))
    (local.set $argc (i32.load (i32.const 300)))
    ;; args_get -> argv pointer array at 320, arg bytes buffer at 400
    (drop (call $args_get (i32.const 320) (i32.const 400)))

    ;; for each arg: print the NUL-terminated string, then a newline
    (local.set $i (i32.const 0))
    (block $done
      (loop $loop
        (br_if $done (i32.ge_u (local.get $i) (local.get $argc)))
        ;; argv_ptr = *(320 + i*4)
        (local.set $argv_ptr
          (i32.load (i32.add (i32.const 320) (i32.mul (local.get $i) (i32.const 4)))))
        ;; compute strlen
        (local.set $str (local.get $argv_ptr))
        (local.set $slen (i32.const 0))
        (block $slen_done
          (loop $slen_loop
            (br_if $slen_done
              (i32.eqz (i32.load8_u (i32.add (local.get $str) (local.get $slen)))))
            (local.set $slen (i32.add (local.get $slen) (i32.const 1)))
            (br $slen_loop)))
        (call $print (local.get $argv_ptr) (local.get $slen))
        ;; newline: reuse byte at offset 119 ('\n' from the greeting's trailing \n)
        (call $print (i32.const 119) (i32.const 1))
        (local.set $i (i32.add (local.get $i) (i32.const 1)))
        (br $loop)))

    (call $proc_exit (i32.const 0))
  )
)