#!/usr/bin/env python3
"""Differential test of the C++ shell/util port against ../tai.py.
Builds build/shell_parity_driver from src/shell + src/util, runs every case through the driver
and through the Python function of tai.py, and compares the bytes. Real processes, a real pty,
real files: no mocks. Outputs go under build/ only.
python3 tests/shell_parity.py [--filter NAME] [--fuzz N] [--seed S] [--no-build] [-v]
"""
import argparse
import codecs
import hashlib
import importlib.util
import io
import json
import os
import random
import re
import shutil
import subprocess
import sys
import tempfile
import time
HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.dirname(HERE)
BUILD = os.path.join(ROOT, "build")
DRIVER = os.path.join(BUILD, "shell_parity_driver")
PY_FILE = os.path.join(os.path.dirname(ROOT), "tai.py")
spec = importlib.util.spec_from_file_location("tai", PY_FILE)
tai = importlib.util.module_from_spec(spec)
sys.modules["tai"] = tai
spec.loader.exec_module(tai)
RS, US = "\x1e", "\x1f"
NONE = "\x01NONE"
def build():
os.makedirs(BUILD, exist_ok=True)
srcs = []
for sub in ("src/util", "src/shell"):
for name in sorted(os.listdir(os.path.join(ROOT, sub))):
if name.endswith(".cpp") and name not in ("http.cpp",):
srcs.append(os.path.join(ROOT, sub, name))
srcs.append(os.path.join(HERE, "shell_parity_driver.cpp"))
cmd = ["g++", "-std=c++23", "-Wall", "-Wextra", "-O1", "-I" + os.path.join(ROOT, "src/util"), "-I" + os.path.join(ROOT, "src/shell"), "-pthread"] + srcs + ["-lcurl", "-o", DRIVER]
done = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
if done.returncode != 0 or done.stdout.strip():
print(done.stdout)
if done.returncode != 0:
sys.exit("driver build failed")
sys.exit("driver build produced warnings: the port must be warning-free")
def cpp(*args, timeout=60):
argv, spill = [], []
for item in args:
item = str(item)
if len(item.encode("utf-8")) > 100000: # beyond the kernel's per-argument limit: pass by file
handle = tempfile.NamedTemporaryFile(dir=BUILD, delete=False)
handle.write(item.encode("utf-8"))
handle.close()
spill.append(handle.name)
item = "@@FILE:" + handle.name
argv.append(item)
try:
done = subprocess.run([DRIVER] + argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=timeout)
finally:
for name in spill:
os.unlink(name)
return done.stdout
def b(text):
return text.encode("utf-8", "replace") if isinstance(text, str) else text
# ---------- python side, one function per driver verb ----------
def py_capped(text, flag):
out, size = tai.capped_text(None if flag == "none" else text)
return ("0" if out is None else "1") + RS + str(0 if size is None else size) + RS + (out or "")
def py_describe(name, raw):
verb, target, extra, preview = tai.Glow.describe_call(name, raw)
return "\n".join(json.dumps(x) for x in (verb, target, extra, preview))
def py_json(text):
try:
value = json.loads(text)
except ValueError:
return "ERR"
return "\n".join((json.dumps(value), json.dumps(value, sort_keys=True), str(value), repr(value)))
def py_tool_args(text):
return "\n".join((tai.tool_args_text(text), tai.tool_args_valid(text), tai.action_signature("name", text)))
def py_sess_stat(text):
parsed = tai.ShellSession.parse_stat(text)
if parsed is None:
return "None"
return "%s %d %d" % (json.dumps(parsed[0]), parsed[1], parsed[2])
def py_sess_current(env_value, pid, proc_root, now, clk):
env = {"TAI_SESSION": env_value} if env_value else {}
sess = tai.ShellSession.current(env=env, pid=int(pid), proc_root=proc_root, now=float(now), clk_tck=int(clk))
chain = "".join("%d,%d,%s,%s,%s,%s,%s;" % (e["pid"], e["ppid"], e["comm"], e["argv0"], e["name"], e["start_iso"], e["sid"]) for e in sess.chain)
return "\n".join((json.dumps(sess.sid), json.dumps(sess.shell), str(sess.pid), json.dumps(sess.started), json.dumps(sess.parent) if sess.parent is not None else "null", chain))
def py_live(height, width, status, *lines):
sink = io.StringIO()
stream = tai.LiveStream(int(height), int(width), sink, True)
for line in lines:
if line == "\x01PAUSE":
stream.pause()
else:
stream.feed(line)
stream.close(status)
return sink.getvalue()
class Recorder(object):
def __init__(self):
self.log = []
def feed(self, line):
self.log.append("FEED " + json.dumps(line) + "\n")
def pause(self):
self.log.append("PAUSE\n")
def py_run(timeout, mode, ask, *rest):
rest = list(rest)
dash = rest.index("--")
answers, cmd = rest[:dash], rest[dash + 1:]
rec = Recorder()
nxt = [0]
def answer(text, secret):
rec.log.append("ASK %s %s\n" % (json.dumps(text), "secret" if secret else "plain"))
if nxt[0] >= len(answers):
return None
value = answers[nxt[0]]
nxt[0] += 1
if value.startswith("\x01SLEEP"):
delay, _, value = value[6:].partition(":")
time.sleep(int(delay) / 1000.0)
return None if value == "\x01DECLINE" else value
old = tai.SHELL_TIMEOUT
try:
if mode == "shell":
result = tai.run_live(cmd[0], timeout=float(timeout), shell=True, stream=rec, ask=answer if ask == "1" else None)
else:
result = tai.run_live(cmd, timeout=float(timeout), shell=False, stream=rec, ask=answer if ask == "1" else None)
except OSError as exc:
rec.log.append("ERROR " + json.dumps(str(exc)) + "\n")
return "".join(rec.log)
code, output, _elapsed, timed_out = result
rec.log.append("RESULT %d %s %s\n" % (code, "timeout" if timed_out else "ok", json.dumps(output)))
return "".join(rec.log)
def py_lane(seq, width, cap):
lists = json.loads(seq)
calls = [0]
real = tai.list_agents
def fake(profile):
value = lists[min(calls[0], len(lists) - 1)]
calls[0] += 1
return value
tai.list_agents = fake
try:
sink = io.StringIO()
board = tai.LaneBoard("prof", int(width), int(cap), sink)
board.start()
board.stop()
return sink.getvalue() + "\npainted=%d" % board.painted
finally:
tai.list_agents = real
PY = {
"truncate": lambda t, h, n: tai.truncate(t, int(h), int(n)),
"capped": py_capped,
"chunk": lambda t, a, c, d: RS.join(tai.chunk_lines(t, int(a), int(c), int(d))),
"collapse": lambda t, n: tai.collapse_repeated_lines(t, int(n)),
"tags": lambda t: US.join(tai.split_leading_tags(t)[0]) + RS + tai.split_leading_tags(t)[1],
"mentions": lambda t, d: tai.expand_file_mentions(t, d),
"complete": lambda p, d, c: "\n".join(tai.complete_files(p, d, int(c))),
"human_size": lambda n: tai.human_size(int(n)),
"stream_status": lambda c, o, e, t: tai.stream_status(int(c), o, float(e), t == "1"),
"duration": lambda r: str(tai.parse_duration(r)),
"delay": lambda n: tai.format_delay(int(n)),
"tokens": lambda t: str(tai.estimate_tokens(t)),
"as_int": lambda v, d: str(tai.as_int(v, int(d))),
"toolname": lambda t: tai.tool_name_clean(t),
"target_paths": lambda c, w: "\n".join(tai.shell_target_paths(c, w)),
"segment": lambda *t: "\n".join(tai.segment_targets(list(t))),
"curl_hint": lambda c: tai.curl_hint(c),
"strip_ansi": lambda t: tai.strip_ansi(t),
"wrap": lambda t, w, f, n: "\n".join(tai.wrap_ansi(t, int(w), f, n)),
"trunc_ansi": lambda t, w: tai.truncate_ansi(t, int(w)),
"pad_tinted": lambda t, w: tai.pad_tinted(t, int(w)),
"style_span": lambda t, c1, c2: tai.style_span(t, c1, c2),
"md_inline": lambda t: tai.md_inline(t),
"markdown": lambda t, w: tai.render_markdown(t, int(w), True),
"diff": lambda p, o, n, w, c: tai.render_diff(p, None if o == NONE else o, None if n == NONE else n, int(w), c == "1"),
"highlight": lambda t: tai.highlight_python(t),
"g_event": lambda i, v, t, m, w, c: tai.Glow.event_row(i, v, t, m, int(w), c),
"g_done": lambda v, t, c, e, f, w: tai.Glow.done_row(v, t, int(c), float(e), f == "1", int(w)),
"g_ellipsis": lambda t, c, h: tai.Glow.ellipsis(t, int(c), h == "1"),
"g_shimmer": lambda t, p, s: tai.Glow.shimmer(t, int(p), int(s)),
"g_describe": py_describe,
"g_status": lambda v, p, d, y, a, w: tai.Glow.statusbar(v, p, d, y == "1", int(a), int(w)),
"g_accent": lambda n: "%s|%s|%s" % (tai.Glow.accent_for(n), tai.Glow.bar(n), tai.Glow.icon_for(n)),
"g_hair": lambda w: tai.Glow.hairline(int(w)),
"g_prompt": lambda: tai.Glow.prompt_text(),
"g_preview": lambda t, w: tai.Glow.preview_row(t, int(w)),
"g_agent_row": lambda r, w, p, s: tai.Glow.agent_row(json.loads(r), int(w), p, s),
"g_lanes": lambda r, c, w, p: "\n".join(tai.Glow.lanes(json.loads(r), int(c), int(w), p)),
"json": py_json,
"tool_args": py_tool_args,
"md5": lambda t: hashlib.md5(t.encode("utf-8")).hexdigest(),
"sess_stat": py_sess_stat,
"sess_name": lambda a, c: tai.ShellSession.shell_name(a, c),
"sess_boot": lambda r: tai.ShellSession.boot_tag(r),
"sess_current": py_sess_current,
"live": py_live,
"run": py_run,
"lane": py_lane,
}
CASES = [] # (label, func, args)
def case(func, *args, label=None, env=None):
CASES.append((label or func, func, tuple(str(a) for a in args), env))
def corpus():
texts = [
"", "a", "plain text", "line one\nline two\n", "tab\there\tx", "unicode: \u00e9\u00e8 \u4e2d\u6587 \U0001f600 end",
"x" * 3000, "y" * 40 + "\n" + "z" * 5000, "crlf\r\nline\rcr only\n", "nbsp\u00a0space\u2003em",
"\x1b[31mred\x1b[0m plain \x1b[1;4mbold\x1b[0m tail",
"a\n\n\nb\n\n", "same\nsame\nsame\nsame\nother\nsame\nsame\n",
]
for t in texts:
for head, tail in ((1500, 500), (10, 5), (0, 0), (3, 60)):
case("truncate", t, head, tail)
case("capped", t, "text")
case("chunk", t, 60, 3, 4000)
case("chunk", t, 2, 1, 30)
case("collapse", t, 3)
case("collapse", t, 2)
case("strip_ansi", t)
case("tokens", t)
case("capped", "", "none")
case("capped", "w" * 20001, "text")
case("capped", "\u00e9" * 20001, "text")
case("truncate", "\u00e9" * 600, 100, 100)
case("truncate", "x" * 2051, 1500, 500)
case("truncate", "x" * 2050, 1500, 500)
case("chunk", "\n".join("line %d" % i for i in range(300)), 60, 3, 4000)
case("chunk", "\n".join("l" * 100 for _ in range(100)), 60, 3, 4000)
case("chunk", "\n".join(["a", "", " ", "b"] * 20), 5, 2, 100)
case("collapse", "\n".join(["tick"] * 10 + ["done"]), 3)
for text in ("@a @b rest of it", "@onlytag", "no tag", "@a\t@b\n text", "@ spaced", "@", "@@x y", "", "@\u00e9 \u4e2d x"):
case("tags", text)
for raw in ("5", "5s", "10m", "2h", "1d", "3 w", " 7 ", "abc", "", "5x", "-5", "5 m", "5mm", "0", "007"):
case("duration", raw)
for n in (-5, 0, 1, 59, 60, 3599, 3600, 86399, 86400, 999999):
case("delay", n)
case("human_size", n)
for n in (1023, 1024, 1048575, 1048576, 123456789):
case("human_size", n)
for value in ("12", " 12 ", "+3", "-4", "1_0", "1__0", "_1", "1_", "abc", "", "3.5", "0x10"):
case("as_int", value, 7)
for name in ("shell", "shell<|channel|>commentary", " spaced ", "", "<|x"):
case("toolname", name)
for cmd in ("curl http://x", "wget https://y", "curl ftp://z", "echo curlhttp", "CURL HTTP://X", "mycurl http", "curl_x http", "x wget", "", "echo http curl"):
case("curl_hint", cmd)
case("stream_status", 0, "a\nb\nc", 1.234, 0)
case("stream_status", 3, "", 0.04, 0)
case("stream_status", 1, "x" * 2000, 99.96, 1)
case("stream_status", 0, "\u00e9\u00e8\n\u4e2d", 2.5, 0)
def corpus_ansi():
samples = [
"plain", "\x1b[31mred\x1b[0m", "\x1b[1m\x1b[36mbold cyan\x1b[0m trailing text here that is long enough to wrap",
"word " * 40, "a\u00e9\u4e2d long\u00a0word " * 8, "\x1b[2mdim\x1b[0m \x1b[4munder \x1b[0m end", "x" * 200,
"tab\tsep\nnew\nline", "", " ", "\x1b[9mstrike", "esc \x1b alone \x1b[ broken", "a\u3000b\u3000c " * 10,
]
for s in samples:
for w in (0, 1, 8, 20, 40, 80):
case("trunc_ansi", s, w)
case("pad_tinted", s, w)
for w in (10, 25, 60):
case("wrap", s, w, "", "")
case("wrap", s, w, "> ", " ")
case("wrap", s, w, "\x1b[2m| \x1b[0m", "\x1b[2m| \x1b[0m")
case("style_span", s, "\x1b[44m", "\x1b[33m")
MD = [
"# Title\n\nparagraph with `code` and **bold** and *dim* and ~~gone~~.\n",
"## Sub\n### Third\n#### Fourth\n####### seven\n#nospace\n#\n# \n",
"- one\n- two\n - nested\n - deeper\n- [ ] todo\n- [x] done\n- [X] done2\n",
"1. first\n2. second\n 1. inner\n 2. inner2\n3. third\n",
"> quote line\n> second line\n>\n> new para\n>> nested\n",
"```python\nprint('x')\n\nmore\n```\nafter\n~~~\nraw\n~~~\n",
"| a | b |\n|---|:-:|\n| 1 | 2 |\n| long cell here | x |\n",
"| a | b | c |\n|:--|--:|:-:|\n| 1 | 2 |\n| only |\n",
"***\n---\n___\n- - -\ntext\n",
"line one \nline two\nline three\n\npara two\n",
"[link](http://example.com) and  and [x](y \"title\") and \n",
"escaped \\* star \\` tick \\[no\\](x) snake_case_word _em_ __strong__ __x__y\n",
"
and
and
here\ttab\n",
"plain\ntext\ncontinues here\n# not a heading mid paragraph\n",
"**unclosed bold and `unclosed code and [broken](\n",
"mixed *a **b** c* and `**no**` and **`code`**\n",
"\u00e9\u00e8 \u4e2d\u6587 **bold \u00e9** `\u4e2d` [\u00e9](u)\n",
"1) paren\n2) paren two\n\n* star\n+ plus\n\ntext after\n",
" - indented bullet\n - more\n\n| not | table\n|just|text|\n",
"a | b\n--|--\nc | d\n",
"```\nunterminated fence\n",
"- item with a very long line that should wrap around the width of the terminal when rendered with a small width\n",
"~~~lang x\n``` inside\n~~~\n",
]
def corpus_markdown():
for text in MD:
case("md_inline", text)
for width in (20, 40, 80):
case("markdown", text, width)
case("markdown", "", 80)
case("markdown", "\n\n\n", 80)
case("md_inline", "[nested **bold** link](http://u/**x**)")
case("md_inline", "`a` `b` \\`c\\`  [t](u)")
DIFF_OLD = "def f(x):\n return x + 1\n\n\nclass A:\n pass\n\nprint('end')\n"
DIFF_NEW = "def f(x):\n return x + 2\n\n\nclass A:\n \"\"\"doc\n string\"\"\"\n pass\n\n# comment 12 3.5e3\nprint('end')\n"
def corpus_diff():
big_old = "\n".join("line %d" % i for i in range(300)) + "\n"
big_new = "\n".join(("line %d changed" % i if i % 7 == 0 else "line %d" % i) for i in range(300)) + "\n"
pairs = [
("a.py", DIFF_OLD, DIFF_NEW), ("a.txt", DIFF_OLD, DIFF_NEW), ("new.py", "", DIFF_NEW), ("gone.py", DIFF_OLD, NONE),
("same.py", "x\n", "x\n"), ("e.py", "", ""), ("b.py", big_old, big_new), ("tabs.py", "a\tb\n", "a\tc\n"),
("u.py", "caf\u00e9 = 1\n", "caf\u00e9 = 2\n"), ("ansi.py", "x \x1b[31my\x1b[0m\n", "x \x1b[31mz\x1b[0m\n"),
("nonl.py", "a", "b"), ("deleteall.txt", "a\nb\n", ""), ("kw.py", "x = 1\n", "if x:\n import os as o # c\n def g(): return None\n"),
("long.py", "a" * 400 + "\n", "b" * 400 + "\n"),
("trip.py", "'''open\nmid\n'''\nx = 1\n", "'''open\nmid2\n'''\nx = 2\n"),
]
for path, old, new in pairs:
for width in (0 + 100, 60):
for colors in (1, 0):
case("diff", path, old, new, width, colors, label="diff:" + path)
case("diff", "n.py", NONE, "x\n", 80, 1)
for line in ("def f(x, y=3):", "class Foo: # comment", "x = 'str' + \"dq\" + 12 + 0x1f + 1.5e3j", "@decorator.attr(1)", "'''triple''' in line",
" return None ", "s = \"unterminated", "# only comment", "print(\"a\\\"b\") # c", "w1 = 1_000 and 3x or x3", "async def go(): await y",
"\"\"\"doc\"\"\" + '''doc2'''", "d = {'k': 1} ", "name = 'caf\u00e9' # \u4e2d", "def two_spaces(): pass", "1.e5 2e+ 3e+4 5.5.5 0_0"):
case("highlight", line)
JSON_SAMPLES = [
'{"a": 1, "b": [1, 2.5, "x"], "c": null, "d": true}', '[]', '{}', '"str"', '12', '-0', '1e5', '1.5E-3', '123456789012345678901234567890',
'{"k": {"z": 1, "a": [{"q": "\\u00e9\\n\\"x\\""}]}}', '{"dup": 1, "dup": 2}', 'nope', '', '{"a":', '[1,]', "{'a': 1}", 'NaN', 'Infinity', '-Infinity',
'"\\ud83d\\ude00"', '{"s": "it\'s"}', '{"s": "say \\"hi\\" it\'s"}', '[1e400]', '0.1', '1e16', '1e-5', '100.0', '[true, false, null]', ' {"a" : 1 } ',
'{"a": "\\u0007\\u007f\\u00a0"}', '"tab\\there"', '[[[[1]]]]', '{"b": 1, "a": 2}', '1.0', '5e-324', '0.30000000000000004',
]
def corpus_json():
for text in JSON_SAMPLES:
case("json", text)
case("tool_args", text)
DESCRIBE = [
("shell", '{"command": "ls -la /tmp"}'), ("shell", '{"command": " many spaces\\nand newline "}'), ("shell", ""), ("shell", "not json"), ("shell", "[1,2]"),
("read_file", '{"path": "/a/b/c.txt"}'), ("read_file", '{"path": "/a/b/"}'), ("read_file", '{"file": "rel/x.py"}'), ("write_file", '{"path": "/"}'),
("edit_file", '{"path": "x.py", "old": "a", "new": "b"}'), ("web_fetch", '{"url": "http://example.com/" }'), ("web_search", '{"query": "q"}'),
("describe_image", '{"image": "pic.png"}'), ("describe_image", '{"path": "/x/y.png", "image": "z"}'), ("speak", '{"text": "hello world"}'),
("fork", '{"task": "' + "long task " * 20 + '"}'), ("poll", '{"agent_id": 7}'), ("poll", '{}'), ("poll", '{"target": "t"}'), ("ask_user", '{"question": "ok?"}'),
("store_secret", '{"name": "k", "value": "topsecret"}'), ("store_secret", '{"name": "k"}'), ("delete_secret", '{"name": "k"}'),
("schedule", '{"prompt": "do it", "at": "2026-01-01T00:00"}'), ("schedule", '{"prompt": "do it", "every": "5m"}'), ("schedule", '{"prompt": "p"}'),
("release", '{"part": "patch", "message": "msg"}'), ("plexer_show", '{"spec": {"title": "My flow", "screens": [1,2]}}'), ("plexer_show", '{"spec": {"screens": [1,2,3]}}'),
("plexer_show", '{"spec": {}}'), ("plexer_show", '{"spec": "str"}'), ("plexer_send", '{"id": "x"}'), ("record_save", '{"title": "T", "content": "C"}'),
("unknown_tool", '{"a": 1}'), ("unknown_tool", ''), ("unknown_tool", 'raw text here'), ("shell", '{"command": null}'), ("shell", '{"command": 12}'),
("shell", '{"command": ["a", "b"]}'), ("shell", '{"command": {"k": "v"}}'), ("shell", '{"command": true}'), ("tags", '{"prefix": "p"}'),
("install", '{"component": "venv"}'), ("graph_query", '{"node": "n"}'), ("audit", '{"path": "/p/q"}'), ("listen", '{"seconds": 5}'), ("remember", '{"instruction": "x"}'),
("load_skill", '{"name": "s"}'), ("install_skill", '{"source": "github"}'), ("create_bot", '{"name": "bot"}'), ("search", '{"query": "z"}'),
("shell", '{"command": "' + "x" * 300 + '"}'), ("read_file", '{"path": "' + "d/" * 50 + 'file.txt"}'), ("tui_screen", '{}'), ("sysinfo", '{}'), ("unschedule", '{"id": 3}'),
]
def corpus_glow():
for icon, verb, target, meta, width, color in (("\u25c6", "Edited", "path/to/file.py", "(+1 -2)", 0, ""), ("\u25c6", "Run", "ls", "", 40, "\x1b[32m"), ("x", "V", "", "m", 5, ""),
("\u25c6", "Created", "a" * 80, "(new file, 10 lines)", 30, "")):
case("g_event", icon, verb, target, meta, width, color)
for verb, target, chars, ms, failed, width in (("Run", "ls", 120, 12.7, 0, 0), ("Run", "ls", 120, 1500, 0, 60), ("Run", "ls", 5, 999, 1, 60), ("Read", "f" * 100, 1, 2500.55, 0, 30),
("Done", "", 0, 0, 0, 20), ("R", "t", 10, 1000, 0, 17)):
case("g_done", verb, target, chars, ms, failed, width)
for text, cap, head in (("short", 60, 0), ("x" * 100, 60, 0), ("y" * 100, 50, 1), ("abc" * 5, 7, 0), ("\u00e9" * 100, 20, 0), ("", 60, 0), ("a" * 61, 60, 0), ("path/" * 30, 33, 0)):
case("g_ellipsis", text, cap, head)
for text, pos in (("thinking", 0), ("thinking", 5), ("thinking", 17), ("", 3), ("\u00e9\u4e2d", 2), ("x", 100)):
case("g_shimmer", text, pos, 3)
case("g_shimmer", "merging memory", 7, 5)
for name, raw in DESCRIBE:
case("g_describe", name, raw)
for yolo, agents, width in ((0, 0, 80), (1, 0, 80), (0, 3, 80), (1, 2, 120), (1, 2, 40), (0, 0, 20), (1, 1, 10), (0, 0, 200)):
case("g_status", "1.44.2", "default", os.path.expanduser("~") + "/work/proj", yolo, agents, width)
case("g_status", "1.44.2", "prof", "/tmp/x", yolo, agents, width)
case("g_status", "1.44.2", "prof", os.path.expanduser("~"), yolo, agents, width)
for name in ("shell", "fork", "poll", "write_file", "edit_file", "delete_file", "ask_user", "store_secret", "list_secrets", "delete_secret", "other"):
case("g_accent", name)
case("g_hair", 0 + 30)
case("g_hair", 1)
case("g_prompt")
case("g_preview", "some text", 0)
case("g_preview", "some text that is long", 10)
recs = [
{"id": 1, "status": "running", "task": "build the thing " * 5, "elapsed": 75, "tools": 3},
{"id": 2, "status": "done", "task": "finished", "elapsed": 3.7, "tools": 0, "collected": False},
{"id": 3, "status": "error", "task": "bad", "elapsed": 100000, "tools": 2, "collected": True},
{"id": 4, "status": "timeout", "task": "slow\n\ttask x", "elapsed": 0},
{"id": 5, "status": "weird", "task": "w", "elapsed": 7200},
{"id": 6, "status": "done", "task": None, "elapsed": None, "tools": 0},
]
for rec in recs:
for width in (0, 50):
case("g_agent_row", json.dumps(rec), width, "\x1b[2m", " sfx")
for cap in (6, 2, 1):
for width in (0, 60):
case("g_lanes", json.dumps(recs), cap, width, "\x1b[1m")
case("g_lanes", json.dumps([]), 6, 0, "")
case("g_lanes", json.dumps([recs[2]]), 6, 0, "")
case("g_lanes", json.dumps(recs[:2]), 6, 40, "")
def make_proc_root(base):
"""A fake /proc: chain 5000 (python) <- 4000 (bash) <- 3000 (-zsh) <- 1 (init)."""
root = os.path.join(base, "proc")
os.makedirs(os.path.join(root, "sys/kernel/random"), exist_ok=True)
with open(os.path.join(root, "stat"), "w") as handle:
handle.write("cpu 1 2 3\nbtime 1760000000\nprocesses 5\n")
with open(os.path.join(root, "sys/kernel/random/boot_id"), "w") as handle:
handle.write("ABCDEF12-3456-7890-abcd-ef1234567890\n")
procs = [(5000, "python3", 4000, 9000, "python3\0tai.py\0"), (4000, "bash", 3000, 8000, "bash\0--norc\0"), (3000, "zsh", 1, 7000, "-zsh\0"), (1, "systemd", 0, 100, "/sbin/init\0")]
for pid, comm, ppid, ticks, cmdline in procs:
os.makedirs(os.path.join(root, str(pid)), exist_ok=True)
fields = ["S", str(ppid)] + ["0"] * 17 + [str(ticks)] + ["0"] * 20
with open(os.path.join(root, str(pid), "stat"), "w") as handle:
handle.write("%d (%s) %s\n" % (pid, comm, " ".join(fields)))
with open(os.path.join(root, str(pid), "cmdline"), "w", newline="") as handle:
handle.write(cmdline)
# a process whose comm contains parentheses and a nested shell
os.makedirs(os.path.join(root, "6000"), exist_ok=True)
with open(os.path.join(root, "6000", "stat"), "w") as handle:
handle.write("6000 (we(ird) name) S 5000 " + " ".join(["0"] * 17 + ["12345"] + ["0"] * 20) + "\n")
with open(os.path.join(root, "6000", "cmdline"), "w", newline="") as handle:
handle.write("/usr/bin/fish\0-l\0")
with open(os.path.join(root, "7000"), "w") as handle:
handle.write("")
return root
def corpus_session(base):
root = make_proc_root(base)
for text in ("1 (bash) S 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 6 7", "", "no parens", "(only) ", "12 (a b) S 4 " + " ".join(["0"] * 17 + ["99"]),
"12 (a)b) S 4 " + " ".join(["0"] * 17 + ["99"]), "12 (a) S x " + " ".join(["0"] * 17 + ["99"]), "12 (a) S 4 1"):
case("sess_stat", text)
for argv0, comm in (("bash", "bash"), ("-zsh", "zsh"), ("/bin/FISH", "x"), ("python3", "python3"), ("", "sh"), ("-", "-nu"), ("tcsh", ""), ("x", "-ksh")):
case("sess_name", argv0, comm)
case("sess_boot", root)
case("sess_boot", os.path.join(base, "nonexistent"))
for pid in (5000, 6000, 1, 99999):
for env in ("", "mypinned", "20250101-000000-p4000-abcdef12", "20250101-000000-p1234-abcdef12", "weird chars!@#", "x" * 100):
case("sess_current", env, pid, root, 1760001000.5, 100, label="sess_current:%s:%s" % (pid, env[:12]))
for text in ("", "a", "abc", "hello world" * 20, "\u00e9"):
case("md5", text)
# no boot_id: falls back to md5 of btime
alt = os.path.join(base, "proc2")
os.makedirs(alt, exist_ok=True)
shutil.copytree(os.path.join(root, "5000"), os.path.join(alt, "5000"))
with open(os.path.join(alt, "stat"), "w") as handle:
handle.write("btime 1760000123\n")
case("sess_boot", alt)
case("sess_current", "", 5000, alt, 1760001000.0, 100)
def corpus_targets(base):
work = os.path.join(base, "work")
os.makedirs(os.path.join(work, "sub/deeper"), exist_ok=True)
os.makedirs(os.path.join(work, "empty"), exist_ok=True)
for name in ("a.txt", "b.txt", "c.log", ".hidden", "sub/s1.txt", "sub/s2.py", "sub/deeper/d.txt", "name with space.txt"):
with open(os.path.join(work, name), "w") as handle:
handle.write("x")
os.symlink(os.path.join(work, "a.txt"), os.path.join(work, "link"))
for i in range(40):
with open(os.path.join(work, "sub", "many%02d.dat" % i), "w") as handle:
handle.write("x")
cmds = [
"rm a.txt", "rm -rf sub", "rm -f *.txt", "rm sub/*", "rm **/*.txt", "rm sub/**", "rm [ab].txt", "rm ?.txt", "rm -- -weird", "mv a.txt b.txt", "cp a.txt x/y.txt",
"tee b.txt < in", "echo hi > a.txt", "echo hi >> b.txt", "echo hi > /dev/null", "echo x 2>&1 > c.log", "cat a >&2", "truncate -s 10 a.txt", "truncate -s 10K a.txt b.txt",
"dd if=/dev/zero of=a.txt bs=1", "shred a.txt", "sudo rm a.txt", "sudo -u x rm a.txt", "env FOO=1 rm a.txt", "FOO=1 BAR=2 rm a.txt", "timeout 5 rm a.txt",
"timeout 5s rm a.txt", "timeout x rm a.txt", "nice -n 5 rm a.txt", "command rm a.txt", "nohup rm a.txt", "setsid rm a.txt", "ls; rm a.txt; rm b.txt", "ls && rm a.txt || rm b.txt",
"ls | tee c.log", "(rm a.txt)", "rm 'name with space.txt'", 'rm "name with space.txt"', "rm name\\ with\\ space.txt", "rm 'unclosed", 'rm "unclosed', "rm trailing\\",
"rm a.txt &", "rm a.txt & rm b.txt", "rm nonexistent", "", " ", ";;", "rm", "mv", "mv a.txt", "cp a b c", "rm empty", "rm sub/deeper", "rm /dev/null", "rm .", "rm ..", "rm -r .",
"rm sub/many*", "rm sub", "rm link", "rm .hidden", "rm *", "rm .*", "tee", "tee -a a.txt", "echo > a.txt > b.txt", "echo >a.txt", "echo>b.txt", "FOO=bar", "env", "sudo",
"rm $HOME", "rm ~", "rm a.txt;rm b.txt", "rm a.txt|cat", "rm \"a\".txt", "rm a'.'txt", "rm '' a.txt", "rm \\\\", "echo 'a b' > 'b.txt'", "rm sub/../a.txt", "rm ./a.txt",
"rm " + os.path.join(work, "a.txt"), "rm /nonexistent/dir/*", "rm [", "rm [a", "rm [!a].txt", "rm [a-b].txt", "rm [b-a].txt", "rm *.t[x]t", "rm sub/*/*", "rm */", "rm sub/",
]
for cmd in cmds:
case("target_paths", cmd, work, label="target_paths:" + cmd)
case("target_paths", "rm a.txt", "relative/workdir")
case("target_paths", "rm *", os.path.join(work, "sub"))
for tokens in (["rm", "a", "b"], ["mv", "x", "y"], ["cp"], [], [">", "f"], ["echo", ">", "&2"], ["echo", ">", "/dev/null"], ["A=1", "rm", "x"], ["sudo", "env", "A=1", "tee", "f"],
["timeout", "10", "rm", "f"], ["timeout", "1.5m", "rm", "f"], ["truncate", "-s", "5", "f"], ["truncate", "1GiB", "f"], ["dd", "of=out", "if=in"], ["-", "x"], ["rm", "-", "x"],
["=x", "rm", "y"], [">x", "rm"], ["/a=b", "rm"], ["rm", "-rf", "--", "-x"], ["shred", "-u", "z"], ["/bin/rm", "f"], ["tee", ">", "f"]):
case("segment", *tokens)
# complete_files / mentions need a stable dir
comp = os.path.join(base, "comp")
os.makedirs(os.path.join(comp, "Alpha"), exist_ok=True)
os.makedirs(os.path.join(comp, "sub/inner"), exist_ok=True)
for name in ("alpha.txt", "Beta.md", ".dot", "Apple", "z.py", "sub/one.txt", "sub/Two.txt", "sub/.hid"):
with open(os.path.join(comp, name), "w") as handle:
handle.write("x")
for prefix in ("", "a", "A", "al", "B", ".", ".d", "sub/", "sub/o", "sub/T", "nothing", "sub/inner", "sub/inner/", "/", "zz", "z"):
case("complete", prefix, comp, 100)
case("complete", "", comp, 2)
case("complete", "a", "/nonexistent/dir", 100)
case("complete", "~/", comp, 5)
for text in ("see @alpha.txt please", "@alpha.txt,", "@alpha.txt) and @Beta.md!", "mail me@alpha.txt", "@nothing here", "@", "x @ y", "@sub/one.txt:", "@/etc/hostname", "@~", "@sub", "a\n@z.py\n@sub/Two.txt",
"@alpha.txt@Beta.md", "\u00e9 @alpha.txt \u4e2d", "(@alpha.txt)", "@.dot", "@.", "@..", "@sub/../z.py", "@@z.py", "@z.py?;"):
case("mentions", text, comp)
def corpus_live():
case("live", 4, 40, "exit 0 done", "one\n", "two\n", "three\n")
case("live", 4, 40, "status", "1\n", "2\n", "3\n", "4\n", "5\n", "6\n")
case("live", 2, 30, "s", "tab\there\n", "carriage\rreturn\n", "\x1b[31mred\x1b[0m long line " + "x" * 80 + "\n", "last\n")
case("live", 3, 20, "s")
case("live", 3, 20, "s", "a\n", "\x01PAUSE", "b\n", "c\n", "d\n", "e\n")
case("live", 1, 8, "very long status line here that gets cut", "x\n")
case("live", 5, 100, "s", "\u00e9\u4e2d\u00e8\n", "plain\n\n", "trailing newlines\n\n\n")
def corpus_run():
sh = "shell"
case("run", 10, sh, 0, "--", "echo hello; echo err >&2; exit 3")
case("run", 10, sh, 0, "--", "printf 'a\\rb\\r\\nc\\n'")
case("run", 10, sh, 0, "--", "printf 'no newline at end'")
case("run", 10, sh, 0, "--", "printf 'x\\ry'")
case("run", 10, sh, 0, "--", "printf 'bad \\xff\\xfe utf8 \\xe4\\xb8 cut\\n'")
case("run", 10, sh, 0, "--", "seq 1 5000")
case("run", 10, sh, 0, "--", "head -c 300000 /dev/zero | tr '\\0' 'a'; echo")
case("run", 10, sh, 0, "--", "for i in 1 2 3; do echo $i; sleep 0.05; done")
case("run", 10, sh, 0, "--", "exit 0")
case("run", 10, sh, 0, "--", "kill -9 $$")
case("run", 10, sh, 0, "--", "cat /nonexistent 2>&1; echo $?")
case("run", 10, sh, 0, "--", "echo $0; pwd >/dev/null; cat; echo eof-ok")
case("run", 1, sh, 0, "--", "echo before; sleep 5; echo after")
case("run", 10, "argv", 0, "--", "echo", "arg one", "two")
case("run", 10, "argv", 0, "--", "/nonexistent/program")
case("run", 10, "argv", 0, "--", "sh", "-c", "exit 7")
# pty path
case("run", 10, sh, 1, "--", "echo plain; exit 2")
case("run", 10, sh, 1, "--", "printf 'a\\rb\\n'; echo done")
case("run", 10, sh, 1, "hunter2", "--", "printf 'Password: '; read -r x; echo \"got:$x\"")
case("run", 10, sh, 1, "yes", "--", "printf 'Continue? (y/n) '; read -r x; echo \"answer:$x\"")
case("run", 10, sh, 1, "\x01DECLINE", "--", "printf 'Name: '; read -r x; echo \"read:$x:\"")
case("run", 10, sh, 1, "a", "b", "--", "printf 'First: '; read -r x; printf 'Second: '; read -r y; echo \"$x$y\"")
case("run", 10, sh, 1, "s3cret", "--", "stty -echo; printf 'Secret: '; read -r x; stty echo; echo; echo \"len:${#x}\"")
case("run", 10, sh, 1, "--", "echo not a prompt; sleep 1.3; echo end")
case("run", 10, sh, 1, "--", "printf 'no prompt chars here'; sleep 1.3; echo")
case("run", 10, sh, 1, "line1\nline2", "--", "printf 'Q: '; read -r x; echo \"[$x]\"")
case("run", 10, sh, 1, "x" * 1200, "--", "printf 'Q: '; read -r x; echo ${#x}")
case("run", 10, sh, 1, "--", "seq 1 20000")
case("run", 10, sh, 1, "--", "tty >/dev/null && echo has-tty; stty size; echo $PAGER $GIT_PAGER")
case("run", 10, sh, 1, "--", "exit 5")
case("run", 10, sh, 1, "--", "kill -9 $$")
case("run", 1, sh, 1, "--", "echo start; sleep 6; echo never")
case("run", 10, sh, 1, "--", "printf '\\033[31mred\\033[0m \\033]0;title\\007ok\\n'")
case("run", 10, sh, 1, "--", "printf 'caf\\xc3\\xa9 \\xe4\\xb8\\xad\\n'")
case("run", 10, "argv", 1, "--", "/nonexistent/program")
if shutil.which("su"): # a real password prompt from a real program (secret detection, EOF on decline)
case("run", 30, sh, 1, "nope", "--", "su root -c true; echo rc=$?", label="run:su-answer")
case("run", 30, sh, 1, "\x01DECLINE", "--", "su root -c true; echo rc=$?", label="run:su-decline")
case("run", 10, sh, 1, "answer", "--", "printf 'Proceed? '; read -r x; echo got:$x; printf 'Again? '; read -r y; echo got2:$y")
# waiting for the user does not count against the timeout: 2s budget, 3s of thinking
case("run", 2, sh, 1, "\x01SLEEP3000:slowanswer", "--", "printf 'Name: '; read -r x; echo \"hi $x\"")
case("run", 2, sh, 1, "\x01SLEEP3000:a", "\x01SLEEP1500:b", "--", "printf 'One: '; read -r x; printf 'Two: '; read -r y; echo \"$x$y\"")
# output cap on the pty path (RUN_OUTPUT_CAP), none on the pipe path
case("run", 60, sh, 1, "--", "seq 1 700000")
case("run", 60, sh, 0, "--", "seq 1 300000")
case("run", 10, sh, 1, "--", "printf 'x%.0s' $(seq 1 100); echo; printf 'tab\\there\\n'")
def corpus_lane():
r1 = {"id": 1, "status": "running", "task": "alpha", "elapsed": 5, "tools": 1}
r2 = {"id": 2, "status": "done", "task": "beta", "elapsed": 9, "tools": 0}
r3 = {"id": 3, "status": "running", "task": "gamma", "elapsed": 1}
case("lane", json.dumps([[r1], [r1]]), 60, 6)
case("lane", json.dumps([[r1], [r1, r2]]), 60, 6)
case("lane", json.dumps([[r1, r2], [r1, r2, r3]]), 0 + 40, 2)
case("lane", json.dumps([[], [r1]]), 50, 6)
case("lane", json.dumps([[r1, r2, r3], [r1, r2, r3]]), 80, 1)
def pty_stderr(argv, env):
"""Run argv with stderr on a pty (so isatty is true); return what it wrote there."""
import pty as ptymod
master, slave = ptymod.openpty()
proc = subprocess.Popen(argv, stdout=subprocess.DEVNULL, stderr=slave, env=env)
os.close(slave)
data = b""
while True:
try:
chunk = os.read(master, 65536)
except OSError:
break
if not chunk:
break
data += chunk
proc.wait()
os.close(master)
return data.decode("utf-8", "replace")
def spinner_cases(opts):
"""Spinner under a real pty: same frames, same clear sequence. Frame count depends on
sleep granularity, so the first frames and the final clear are compared, plus the count within one."""
failures = 0
runner = ("import importlib.util, sys, time\n"
"spec = importlib.util.spec_from_file_location('tai', %r)\n"
"tai = importlib.util.module_from_spec(spec); sys.modules['tai'] = tai; spec.loader.exec_module(tai)\n"
"s = tai.Spinner(sys.argv[1]); s.start(); time.sleep(int(sys.argv[2]) / 1000.0); s.stop()\n") % PY_FILE
for label, ms, no_color in (("thinking", 500, False), ("merging memory", 700, False), ("plain label", 400, True), ("x", 300, False)):
env = dict(os.environ)
env.pop("NO_COLOR", None)
if no_color:
env["NO_COLOR"] = "1"
want = pty_stderr([sys.executable, "-c", runner, label, str(ms)], env)
got = pty_stderr([DRIVER, "spinner", label, str(ms)], env)
norm = lambda text: re.sub(r"\d+\.\ds", "T.Ts", text.replace("\r\n", "\n"))
w, g = norm(want).split("\r"), norm(got).split("\r")
ok = w[:4] == g[:4] and w[-2:] == g[-2:] and abs(len(w) - len(g)) <= 2
print("%s spinner %r %dms (frames py=%d cpp=%d)" % ("ok " if ok else "FAIL", label, ms, len(w), len(g)))
if not ok:
failures += 1
print(" want: %r" % w[:5])
print(" got : %r" % g[:5])
return failures
def burst_cases():
"""Concurrent runs through both paths: every run must equal the Python result."""
from concurrent.futures import ThreadPoolExecutor
want = {}
for mode in ("0", "1"):
want[mode] = b(py_run(30, "shell", mode, "--", "seq 1 20000; echo done >&2"))
jobs = [(mode,) for _ in range(12) for mode in ("0", "1")]
with ThreadPoolExecutor(max_workers=24) as pool:
results = list(pool.map(lambda job: (job[0], cpp("run", 30, "shell", job[0], "--", "seq 1 20000; echo done >&2", timeout=120)), jobs))
bad = sum(1 for mode, out in results if out != want[mode])
print("%s burst: %d concurrent runs (pipe and pty), %d differ from tai.py" % ("ok " if not bad else "FAIL", len(results), bad))
return 1 if bad else 0
import contextlib
@contextlib.contextmanager
def fixed_env(now):
"""Deterministic clock, urandom and uuid4 for the edge-speech functions (the C++ driver does the same)."""
counter = [0]
class Uuid(object):
def __init__(self, n):
self.hex = "%032x" % n
def uuid4():
counter[0] += 1
return Uuid(counter[0])
saved = (time.time, os.urandom, tai.uuid.uuid4)
real_gmtime = time.gmtime
time.gmtime = lambda secs=None: real_gmtime(float(now) if secs is None else secs)
time.time = lambda: float(now)
os.urandom = lambda n: bytes((i * 7 + 1) % 256 for i in range(n))
tai.uuid.uuid4 = uuid4
try:
yield
finally:
time.time, os.urandom, tai.uuid.uuid4 = saved
time.gmtime = real_gmtime
class FakeSock(object):
def __init__(self, inbox=b""):
self.inbox, self.sent = inbox, b""
def sendall(self, data):
self.sent += data
def recv(self, n):
out, self.inbox = self.inbox[:n], self.inbox[n:]
return out
def close(self):
pass
def py_ws_recv(hexframes):
sock = FakeSock(bytes.fromhex(hexframes))
with fixed_env(0):
try:
opcode, payload = tai.ws_recv(sock)
head = "OK %d %s" % (opcode, payload.hex())
except tai.BackendError as exc:
head = "ERR %s" % exc
return head + "|sent=" + sock.sent.hex()
def py_edge_session(frames, text, voice, now):
sock = FakeSock(bytes.fromhex(frames))
real = tai.edge_connect
tai.edge_connect = lambda: sock
try:
with fixed_env(now):
try:
head = "OK " + tai.edge_synthesize(text, voice).hex()
except tai.BackendError as exc:
head = "ERR %s" % exc
finally:
tai.edge_connect = real
return head + "|sent=" + sock.sent.hex()
def py_ws_send(payload):
sock = FakeSock()
with fixed_env(0):
tai.ws_send(sock, payload)
return sock.sent.hex()
def py_edge_token(skew, now):
with fixed_env(now):
return tai.edge_token(int(skew))
def py_edge_ts(now):
with fixed_env(now):
return tai.edge_timestamp()
def py_edge_skew(header, now):
with fixed_env(now):
return str(tai.edge_skew(header))
def frame(opcode, payload, fin=True, mask=None, ext=None):
"""One websocket frame as the server (unmasked) or a test (masked) would send it."""
first = (0x80 if fin else 0) | opcode
n = len(payload)
if ext == 16 or (ext is None and 126 <= n < 65536):
head = bytes([first, (0x80 if mask else 0) | 126]) + n.to_bytes(2, "big")
elif ext == 64 or (ext is None and n >= 65536):
head = bytes([first, (0x80 if mask else 0) | 127]) + n.to_bytes(8, "big")
else:
head = bytes([first, (0x80 if mask else 0) | n])
if mask:
payload = bytes(b ^ mask[i % 4] for i, b in enumerate(payload))
return (head + mask + payload).hex()
return (head + payload).hex()
PY.update({
"edge_token": py_edge_token,
"edge_ts": py_edge_ts,
"edge_ssml": lambda t, v: tai.edge_ssml(t, v),
"edge_chunks": lambda t, n: RS.join(tai.edge_chunks(t, int(n))),
"ws_send": py_ws_send,
"ws_recv": py_ws_recv,
"edge_skew": py_edge_skew,
"edge_session": py_edge_session,
"listen": lambda sec, work: tai.listen_audio(int(sec), work),
"play": lambda path: str(tai.play_audio(path)),
})
def live_edge():
"""One real synthesis against the Edge service (network): sizes within 30%, same container header."""
text, voice = "Hello from the parity test.", "en-US-EmmaMultilingualNeural"
try:
audio = tai.edge_synthesize(text, voice)
want = "OK"
size_py = len(audio)
except Exception as exc: # network down: report, do not fail the run
print("skip live edge synthesis (python side failed: %s)" % exc)
return 0
out = cpp("edge_live", text, voice, timeout=90).decode("utf-8", "replace")
parts = out.split()
ok = parts[:1] == ["OK"] and abs(int(parts[1]) - size_py) <= 0.3 * size_py and parts[2] == audio[:3].hex()
print("%s live edge synthesis: python %d bytes, cpp %s" % ("ok " if ok else "FAIL", size_py, out))
return 0 if ok else 1
def corpus_edge():
for skew in (0, 5, -3600, 7200):
for now in (0, 1760000000, 1760000299, 1760000300.7):
case("edge_token", skew, now)
for now in (0, 1760000000, 1760086399.5):
case("edge_ts", now)
for text in ("hello", "a < b & c > d", "line\nbreak\rcr", "it's \"q\"", "\u00e9\u4e2d"):
case("edge_ssml", text, "en-US-EmmaMultilingualNeural")
for text, limit in (("One. Two! Three? Four.", 4000), ("One sentence here. Another sentence there. And a third.", 25), (" padded text ", 4000), ("", 10),
("no punctuation just words " * 10, 40), ("A. B. C. D.", 3), ("x" * 100, 10), ("Dr. Smith went. He left.\n\nNew para.", 30), ("\u00e9\u00e9\u00e9. \u00e9\u00e9\u00e9.", 7)):
case("edge_chunks", text, limit)
for payload in ("", "hi", "x" * 125, "x" * 126, "x" * 65535, "x" * 65536, "\u00e9\u4e2d"):
case("ws_send", payload, label="ws_send:%d" % len(payload))
mask = bytes([9, 8, 7, 6])
frames = {
"text": frame(1, b"Path:turn.end"), "binary-masked": frame(2, b"abc", mask=mask), "ext16": frame(2, b"z" * 300), "ext64": frame(2, b"y" * 70000, ext=64),
"ping-then-text": frame(9, b"") + frame(1, b"after"), "close": frame(8, b""), "fragmented": frame(1, b"par", fin=False) + frame(0, b"ts"),
"fragment-binary": frame(2, b"ab", fin=False) + frame(0, b"cd", fin=False) + frame(0, b"ef"), "truncated": frame(1, b"hello")[:-4], "empty": "", "one-byte": "81",
"ping-in-fragments": frame(1, b"a", fin=False) + frame(9, b"") + frame(0, b"b"), "pong-ignored": frame(10, b"x") + frame(1, b"y"),
}
for name, data in frames.items():
case("ws_recv", data, label="ws_recv:" + name)
for header, now in (("HTTP/1.1 403 Forbidden\r\nDate: Mon, 06 Jan 2025 10:00:00 GMT\r\n\r\n", 1736157600), ("HTTP/1.1 403\r\ndate: Tue, 07 Jan 2025 10:00:01 UTC\r\nX: y\r\n\r\n", 1736157600),
("HTTP/1.1 403\r\nDate: garbage\r\n\r\n", 1736157600), ("HTTP/1.1 403\r\n\r\n", 1736157600), ("Date:Mon, 6 Jan 2025 1:2:3 GMT", 1736157600),
("Date: Mon, 06 Jan 2025 10:00:00 CET\r\n", 1736157600), ("Date: Mon, 32 Jan 2025 10:00:00 GMT\r\n", 1736157600), ("Date: Monday, 06 January 2025 10:00:00 GMT\r\n", 1736157600),
("Date: Mon,06 Jan 2025 10:00:00 GMT\r\n", 1736157600), ("x\r\nDATE: Wed, 08 Jan 2025 23:59:59 GMT \r\n", 1736157600), ("Date: Mon, 06 Jan 2025 10:00:00\r\n", 1736157600)):
case("edge_skew", header, now)
turn_end = frame(1, b"X-RequestId:1\r\nPath:turn.end\r\n\r\n{}")
session = frame(1, b"Path:turn.start") + frame(2, (5).to_bytes(2, "big") + b"HDR:x" + b"AUDIO1") + frame(2, b"\x00\x01") + frame(9, b"") + frame(2, (0).to_bytes(2, "big") + b"AUDIO2") + turn_end
case("edge_session", session, "Hello there.", "en-US-X", 1760000000)
case("edge_session", session + session, "One sentence. " * 400, "en-US-X", 1760000000, label="edge_session:two-chunks")
case("edge_session", frame(1, b"nothing useful") + frame(8, b""), "Hi.", "v", 1760000000, label="edge_session:closed")
case("edge_session", "", "Hi.", "v", 1760000000, label="edge_session:eof")
case("edge_session", frame(2, b"\x00\x00") + turn_end, "Hi.", "v", 1760000000, label="edge_session:short-binary")
def corpus_audio(base):
"""listen/play with fake recorder, transcriber and player binaries on private PATHs."""
def make_bin(name, scripts):
bindir = os.path.join(base, name)
os.makedirs(bindir)
for binary, body in scripts.items():
path = os.path.join(bindir, binary)
with open(path, "w") as handle:
handle.write("#!/bin/sh\n" + body + "\n")
os.chmod(path, 0o755)
return bindir
work = os.path.join(base, "audio")
os.makedirs(work)
rec = 'for last; do :; done; echo rec > "$last"'
full = make_bin("bin_full", {"arecord": rec, "whisper": 'n=${1##*/}; echo "transcript of ${n%%-*}"', "paplay": "exit 0"})
plain = make_bin("bin_plain", {"rec": rec, "whisper-cpp": 'echo " spoken words "', "aplay": "exit 3"})
broken = make_bin("bin_broken", {"ffmpeg": rec, "whisper-cli": 'echo "model missing" >&2; exit 4', "pw-play": "exit 0"})
empty = make_bin("bin_empty", {"arecord": rec, "faster-whisper": "true"})
longtext = make_bin("bin_long", {"arecord": rec, "whisper": 'i=0; while [ $i -lt 700 ]; do printf "word%d " $i; i=$((i+1)); done; echo'})
norec = make_bin("bin_norec", {"whisper": "true"})
nothing = make_bin("bin_nothing", {})
for name, path in (("full", full), ("plain", plain), ("broken", broken), ("empty", empty), ("long", longtext), ("norec", norec), ("nothing", nothing)):
env = {"PATH": path}
case("listen", 3, work, label="listen:" + name, env=env)
case("play", os.path.join(work, "x.mp3"), label="play:" + name, env=env)
case("listen", 3, work + "/", label="listen:trailing-slash", env={"PATH": full})
case("listen", 3, os.path.join(base, "no-such-dir"), label="listen:bad-workdir", env={"PATH": full})
FAKE_PODMAN = r"""#!/bin/sh
D="$FAKE_DIR"
log() { printf '%s\n' "$*" >> "$D/calls.log"; }
cmd="$1"
case "$cmd" in
inspect) log "inspect $*"; [ -f "$D/state" ] || exit 1; if [ "$(cat "$D/state")" = running ]; then echo true; else echo false; fi ;;
start) log "start $*"; if [ "$FAKE_START_FAIL" = 1 ]; then echo "start failed badly" >&2; exit 125; fi; echo running > "$D/state" ;;
update) log "update $*"; if [ "$FAKE_UPDATE_FAIL" = 1 ]; then echo "cgroup write denied" >&2; exit 1; fi ;;
build) log "build $2 $3 "; for f in Containerfile stt.py tts.py; do echo "--- $f" >> "$D/calls.log"; cat "$4/$f" >> "$D/calls.log"; done
if [ "$FAKE_BUILD_FAIL" = 1 ]; then exit 1; fi ;;
run) log "run $*"; if [ "$FAKE_RUN_FAIL" = 1 ]; then echo "run failed" >&2; exit 125; fi; echo running > "$D/state" ;;
exec)
log "exec $*"
while [ "$1" != "tai-box" ]; do shift; done; shift
case "$1" in
test) exit "${FAKE_TEST_RC:-0}" ;;
which) exit "${FAKE_WHICH_RC:-0}" ;;
sh) if [ "$2" = "-c" ]; then log "script-start"; log "$3"; exit "${FAKE_INSTALL_RC:-0}"; fi ;;
opencode) in="$(cat)"; log "stdin: $in"; echo "OC-OUT $*"; echo "OC-ERR" >&2; exit "${FAKE_OC_RC:-0}" ;;
/box/venv/bin/python|python3)
in="$(cat)"; log "stdin: $in"
case "$2" in
/box/stt.py) if [ "$FAKE_STT_FAIL" = 1 ]; then echo "stt broke" >&2; exit 2; fi; echo " heard: $in " ;;
/box/tts.py) if [ "$FAKE_TTS_FAIL" = 1 ]; then echo "tts broke" >&2; exit 2; fi; if [ "$FAKE_TTS_EMPTY" = 1 ]; then exit 0; fi; printf 'MP3[%s|%s]' "$in" "$3" ;;
esac ;;
*) echo "unknown exec $*" >&2; exit 9 ;;
esac ;;
*) echo "unknown $cmd" >&2; exit 9 ;;
esac
"""
def box_reset():
tai._BOX_CAPS_STAMP["done"] = False
tai._BOX_PYTHON_CACHE.clear()
tai._BOX_OPENCODE_CACHE.clear()
def py_box(scenario, engine, *rest):
box_reset()
out = io.StringIO()
real_parse = tai.opencode_parse_events
tai.opencode_parse_events = lambda stdout_text, returncode, stderr_text: "PARSE|%d|%s|%s" % (returncode, stdout_text, stderr_text)
try:
with contextlib.redirect_stdout(out), contextlib.redirect_stderr(out):
try:
if scenario == "engine":
result = tai.container_engine()
elif scenario == "state":
result = tai.box_state(engine)
elif scenario == "ensure":
result = "OK " + tai.ensure_box()
elif scenario == "caps":
result = str(tai.update_box_caps(engine))
elif scenario == "python":
result = tai.box_python(engine)
elif scenario == "stt":
result = "OK " + tai.box_transcribe(engine, rest[0].encode("utf-8"))
elif scenario == "tts":
result = "OK " + tai.box_speak(engine, rest[0], rest[1]).hex()
elif scenario == "ocbin":
result = str(tai.box_opencode_binary(engine))
elif scenario == "ocrun":
result = tai.box_opencode_run(engine, rest[0], rest[1], float(rest[2]) if "." in rest[2] else int(rest[2]))
elif scenario == "exec":
done = tai.box_exec(engine, list(rest))
result = "RC %d %s %s" % (done.returncode, json.dumps(done.stdout.decode("utf-8", "replace")), json.dumps(done.stderr.decode("utf-8", "replace")))
except tai.BackendError as exc:
result = "ERR %s" % exc
except subprocess.TimeoutExpired as exc:
result = "TIMEOUT %s" % exc
except OSError as exc:
result = "OSERR %s" % exc
finally:
tai.opencode_parse_events = real_parse
return out.getvalue() + result
def corpus_box(base):
"""Box lifecycle against a scripted fake `podman`: same calls, same prints, same errors as tai.py."""
bindir = os.path.join(base, "fakebin")
os.makedirs(bindir)
with open(os.path.join(bindir, "podman"), "w") as handle:
handle.write(FAKE_PODMAN)
os.chmod(os.path.join(bindir, "podman"), 0o755)
sysbin = "/usr/bin:/bin"
on = {"PATH": bindir + ":" + sysbin, "FAKE_TEMPLATE_STATE": ""}
def scenario(label, name, state=None, extra=None, args=()):
env = dict(on)
env["FAKE_TEMPLATE_STATE"] = state or ""
env.update(extra or {})
case("box", name, "podman", *args, label="box:" + label, env=env)
scenario("engine", "engine")
case("box", "engine", "podman", label="box:engine-none", env={"PATH": os.path.join(base, "emptybin"), "FAKE_TEMPLATE_STATE": ""})
case("box", "ensure", "podman", label="box:ensure-no-engine", env={"PATH": os.path.join(base, "emptybin"), "FAKE_TEMPLATE_STATE": ""})
for st in ("", "running", "stopped"):
scenario("state-" + (st or "missing"), "state", st)
scenario("ensure-running", "ensure", "running")
scenario("ensure-running-nocaps-env", "ensure", "running", {"TAI_BOX_CAPS": "0"})
scenario("ensure-running-capfail", "ensure", "running", {"FAKE_UPDATE_FAIL": "1"})
scenario("ensure-stopped", "ensure", "stopped")
scenario("ensure-stopped-startfail", "ensure", "stopped", {"FAKE_START_FAIL": "1"})
scenario("ensure-missing-builds", "ensure", "")
scenario("ensure-build-fail", "ensure", "", {"FAKE_BUILD_FAIL": "1"})
scenario("ensure-run-fail", "ensure", "", {"FAKE_RUN_FAIL": "1"})
scenario("caps", "caps", "running")
scenario("caps-fail", "caps", "running", {"FAKE_UPDATE_FAIL": "1"})
scenario("python-venv", "python", "running")
scenario("python-fallback", "python", "running", {"FAKE_TEST_RC": "1"})
scenario("stt", "stt", "running", args=("hello audio",))
scenario("stt-fail", "stt", "running", {"FAKE_STT_FAIL": "1"}, args=("x",))
scenario("tts", "tts", "running", args=("say this \u00e9", ""))
scenario("tts-voice", "tts", "running", args=("say this", "en-US-X"))
scenario("tts-fail", "tts", "running", {"FAKE_TTS_FAIL": "1"}, args=("x", ""))
scenario("tts-empty", "tts", "running", {"FAKE_TTS_EMPTY": "1"}, args=("x", ""))
scenario("ocbin-present", "ocbin", "running")
scenario("ocbin-install-ok", "ocbin", "running", {"FAKE_WHICH_RC": "1"})
scenario("ocbin-install-fail", "ocbin", "running", {"FAKE_WHICH_RC": "1", "FAKE_INSTALL_RC": "3"})
scenario("ocrun", "ocrun", "running", args=("mimo-v2.6-flash-free", "the prompt \u00e9", "30"))
scenario("ocrun-fail", "ocrun", "running", {"FAKE_OC_RC": "5"}, args=("m", "p", "30"))
scenario("exec-echo", "exec", "running", args=("test", "-x", "/x"))
scenario("exec-unknown", "exec", "running", args=("frobnicate",))
case("box", "state", "/nonexistent/engine", label="box:state-bad-engine", env=on)
case("box", "python", "/nonexistent/engine", label="box:python-bad-engine", env=on)
case("box", "ocbin", "/nonexistent/engine", label="box:ocbin-bad-engine", env=on)
case("box", "ocrun", "/nonexistent/engine", "m", "p", "30", label="box:ocrun-bad-engine", env=on)
case("box", "exec", "/nonexistent/engine", "ls", label="box:exec-bad-engine", env=on)
PY["box"] = py_box
# ---------- runner ----------
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--filter", default="")
parser.add_argument("--fuzz", type=int, default=300)
parser.add_argument("--seed", type=int, default=1)
parser.add_argument("--no-build", action="store_true")
parser.add_argument("--live", action="store_true", help="also run the network synthesis against the Edge service")
parser.add_argument("-v", action="store_true")
opts = parser.parse_args()
if not opts.no_build:
build()
os.environ["TZ"] = "Europe/Amsterdam"
base = tempfile.mkdtemp(prefix="shell_parity_", dir=BUILD)
try:
os.environ["HOME"] = os.path.join(base, "home")
os.makedirs(os.environ["HOME"], exist_ok=True)
corpus()
corpus_ansi()
corpus_markdown()
corpus_diff()
corpus_json()
corpus_glow()
corpus_session(base)
corpus_targets(base)
corpus_live()
corpus_run()
corpus_lane()
corpus_edge()
corpus_audio(base)
corpus_box(base)
fuzz(opts)
failures = 0
total = 0
for label, func, args, case_env in CASES:
if opts.filter and opts.filter not in label and opts.filter not in func:
continue
total += 1
cwd = os.getcwd()
case_env = dict(case_env or {})
template_state = case_env.pop("FAKE_TEMPLATE_STATE", None)
saved_env = {k: os.environ.get(k) for k in list(case_env) + ["FAKE_DIR"]}
for key, value in case_env.items():
os.environ[key] = value
def fake_dir(side):
if template_state is None:
return None
path = os.path.join(base, "fake_%s_%d" % (side, total))
os.makedirs(path)
if template_state:
with open(os.path.join(path, "state"), "w") as handle:
handle.write(template_state)
os.environ["FAKE_DIR"] = path
return path
def fake_log(path, out):
if path is None:
return out
log = ""
if os.path.exists(os.path.join(path, "calls.log")):
log = open(os.path.join(path, "calls.log"), encoding="utf-8", errors="replace").read()
log = re.sub(r"/[^ \n]*/(tai-box-\w+|tmp\w+)", "", log)
return out + b"\n--calls--\n" + log.encode("utf-8")
pydir = fake_dir("py")
try:
want = fake_log(pydir, b(PY[func](*args)))
except Exception as exc: # the Python function raised: the driver must not crash either
want = b("PYEXC " + type(exc).__name__)
cppdir = fake_dir("cpp")
try:
got = fake_log(cppdir, cpp(func, *args))
except subprocess.TimeoutExpired:
got = b"TIMEOUT"
os.chdir(cwd)
for key, value in saved_env.items():
if value is None:
os.environ.pop(key, None)
else:
os.environ[key] = value
if func == "sess_current":
norm = lambda raw: re.sub(rb"(-e\d+-)[0-9a-f]{4}", rb"\1XXXX", raw)
got, want = norm(got), norm(want)
if got != want:
failures += 1
print("FAIL %s %r" % (label, [a[:80] for a in args]))
print(" want: %r" % want[:400])
print(" got : %r" % got[:400])
elif opts.v:
print("ok %s" % label)
if not opts.filter:
failures += spinner_cases(opts)
failures += burst_cases()
if opts.live:
failures += live_edge()
print("%d cases, %d failures" % (total, failures))
return 1 if failures else 0
finally:
shutil.rmtree(base, ignore_errors=True)
ALPHABET = list("ab c\n\t`*_~#>-+|[]()!\\:0123456789.\u00e9\u4e2d") + ["\x1b[31m", "\x1b[0m", " ", "**", "__", "~~", "```", "- ", "1. ", "> ", "| a |", "|---|", "
", "](u)", "[x](", "![", "def ", "'''", '"""', "# c", "@", "\r"]
def fuzz(opts):
rng = random.Random(opts.seed)
def text(maxlen=60):
return "".join(rng.choice(ALPHABET) for _ in range(rng.randint(0, maxlen)))
for _ in range(opts.fuzz):
t = text()
case("md_inline", t, label="fuzz:md_inline")
case("markdown", t, rng.choice((10, 30, 80)), label="fuzz:markdown")
case("wrap", t, rng.choice((5, 12, 40)), rng.choice(("", "> ")), rng.choice(("", " ")), label="fuzz:wrap")
case("trunc_ansi", t, rng.randint(0, 30), label="fuzz:trunc_ansi")
case("highlight", t, label="fuzz:highlight")
case("truncate", t, rng.randint(0, 20), rng.randint(0, 20), label="fuzz:truncate")
case("chunk", t, rng.randint(1, 4), rng.randint(0, 2), rng.randint(5, 50), label="fuzz:chunk")
case("collapse", t, rng.randint(1, 4), label="fuzz:collapse")
case("strip_ansi", t, label="fuzz:strip_ansi")
old = "\n".join(text(12) for _ in range(rng.randint(0, 8)))
new = "\n".join(rng.choice(old.split("\n") + [text(12)]) if old else text(12) for _ in range(rng.randint(0, 8)))
case("diff", rng.choice(("f.py", "f.txt")), old, new, 60, rng.choice((0, 1)), label="fuzz:diff")
case("g_ellipsis", t, rng.randint(0, 30), rng.choice((0, 1)), label="fuzz:ellipsis")
case("json", rng.choice(JSON_SAMPLES[:12]) if rng.random() < 0.3 else t, label="fuzz:json")
if __name__ == "__main__":
sys.exit(main())