#!/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 ![img](a.png \"t\") and [x](y \"title\") and ![](p.png)\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\\` ![alt](u) [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())