#!/usr/bin/env python3 """Python reference driver for the differential tests of the misc modules (tests/misc_diff.py). Runs one scenario against the real tai.py and prints a line-oriented transcript. The C++ side (tests/misc_driver.cpp) prints the same transcript for the same scenario; the orchestrator diffs them. Usage: misc_py.py SCENARIO ROOT [prepare] """ import importlib.util import json import os import sys HERE = os.path.dirname(os.path.abspath(__file__)) TAI_PY = os.path.join(os.path.dirname(os.path.dirname(HERE)), "tai.py") DATA = os.path.join(HERE, "misc_data") def load_tai(): spec = importlib.util.spec_from_file_location("tai", TAI_PY) mod = importlib.util.module_from_spec(spec) sys.modules["tai"] = mod spec.loader.exec_module(mod) return mod tai = load_tai() def data(name): with open(os.path.join(DATA, name), encoding="utf-8") as handle: return json.load(handle) def j(value): return json.dumps(value) def out(line=""): sys.stdout.write(line + "\n") def show(label, text): out("%s: %s" % (label, j(text))) # ------------------------------------------------------------------ scenarios without state def sc_json(root): for case in data("json_cases.json"): try: value = json.loads(case) out("%s => %s" % (j(case), json.dumps(value))) except ValueError: out("%s => ERR" % j(case)) def sc_datetime(root): for case in data("datetime_cases.json"): try: moment = tai._fromisoformat(case) iso = moment.isoformat() except Exception: iso = "ERR" try: parsed = tai.parse_schedule_at(case) except Exception as exc: parsed = "ERR " + str(exc) shown = "-" if not parsed.startswith("ERR"): try: shown = j(tai.local_display(parsed)) except Exception as exc: shown = "ERR " + str(exc) out("%s => %s | %s | %s" % (j(case), iso, parsed, shown)) for case in data("duration_cases.json"): out("duration %s => %s" % (j(case), j(tai.parse_duration(case)))) for case in data("delay_cases.json"): out("delay %s => %s" % (j(case), j(tai.format_delay(case)))) def sc_chunk(root): for case in data("chunk_cases.json"): chunks = tai.chunk_lines(case["text"], case["max_lines"], case["overlap"], case["max_chars"]) out("chunks %d %s" % (len(chunks), j(chunks))) out("collapse %s" % j(tai.collapse_repeated_lines(case["text"]))) out("lines %s" % j(case["text"].splitlines())) out("strip %s" % j(case["text"].strip())) def sc_fts(root): for case in data("fts_cases.json"): terms = tai.fts_escape(case) out("%s => %s" % (j(case), j(terms))) if terms: out(" match %s" % j(tai.fts_match(terms))) out(" or %s" % j(tai.fts_match_or(terms))) out(" prefix %s" % j(tai.fts_match_prefix(terms))) out(" variants %s" % j(tai.fts_match_variants(terms))) out("rank %s" % j(tai.fts_rank("fts_docs"))) for raw in ["Release Notes!", " a b ", "---", "x" * 40, "été", "a,b;c", "Hello World 2", "..", "UPPER", "a-b-c"]: out("tag %s => %s" % (j(raw), j(tai.normalize_tag(raw)))) out("tags %s" % j(tai.normalize_tags(["A b", "a-b", "", "C!", "d" * 40, "d" * 39 + "e"] + ["t%d" % i for i in range(30)]))) def sc_skills_data(root): for name in sorted(tai.BUNDLED_SKILLS): out("skill %s upstream %s" % (name, j(tai.BUNDLED_SKILL_UPSTREAM[name]))) for rel in sorted(tai.BUNDLED_SKILLS[name]): text = tai.BUNDLED_SKILLS[name][rel] out(" file %s len %d sha8 %s sha256 %s" % (rel, len(text.encode("utf-8")), tai.bundled_skill_digest(text), __import__("hashlib").sha256(text.encode("utf-8")).hexdigest())) for name in sorted(tai.SKILL_BLUEPRINTS): bp = tai.SKILL_BLUEPRINTS[name] out("blueprint %s hint %s scope %s brief %s" % (name, j(bp["hint"]), bp["scope"], j(bp["brief"]))) out("catalog empty %s" % j(tai.skill_catalog({}))) out("catalog one %s" % j(tai.skill_catalog({"deep-research": {"description": "x" * 400}, "zeta": {"description": "short"}}))) out("prompt %s" % j(tai.create_skill_prompt("my-skill", "do the thing", "/tmp/x/my-skill"))) for raw in ["a", "ab", "a-b", "-a", "a-", "A", "a_b", "a" * 64, "a" * 65, "", "a b", "0x", "a\n"]: out("name %s => %s" % (j(raw), bool(tai.SKILL_NAME_RE.match(raw)))) front_cases = [ ["name: x", "description: y"], ["name: 'x'", 'description: "y z"'], ["name: x", "description: >", " line one", " line two", "other: v"], ["name: x", "description: |", " line one", " line two", "tail: 1"], ["name: x", "description: >-", " folded"], [" indented: no", "key: va:lue", "noval", "k2:", "k3: ''quoted''"], ["a: >", "b: 1"], ["a: |", "\tt1", " t2", "z: 9"], ] for lines in front_cases: out("front %s => %s" % (j(lines), j(tai.parse_skill_front(lines)))) # ------------------------------------------------------------------ helpers for filesystem scenarios def write(path, text): os.makedirs(os.path.dirname(path), exist_ok=True) with open(path, "w", encoding="utf-8", newline="") as handle: handle.write(text) def read(path): with open(path, encoding="utf-8", newline="") as handle: return handle.read() def tai_home(): return os.environ["TAI_HOME"] def sc_skills_files(root): home = tai_home() out("== front-matter parse") cases = { "ok": "---\nname: ok\ndescription: fine one\n---\n\n\nbody here\n", "crlf": "---\r\nname: crlf\r\ndescription: win\r\n---\r\nbody\r\n", "nofront": "just text\n", "noend": "---\nname: noend\ndescription: d\n", "badname": "---\nname: Bad_Name\ndescription: d\n---\nbody\n", "nodesc": "---\nname: nodesc\n---\nbody\n", "quoted": "---\nname: 'quoted'\ndescription: \"has: colon\"\n---\nbody\n", "folded": "---\nname: folded\ndescription: >\n one\n two\n---\nbody\n", "emptybody": "---\nname: emptybody\ndescription: d\n---", } for key, text in cases.items(): path = os.path.join(root, "parse", key, "SKILL.md") write(path, text) skill = tai.parse_skill_file(path) out("parse %s => %s" % (key, j(skill))) out("== discover with external roots and collisions") proj = os.path.join(root, "proj") write(os.path.join(os.path.expanduser("~"), ".claude", "skills", "ext-home", "SKILL.md"), "---\nname: ext-home\ndescription: from claude home\n---\nbody ext-home\n") write(os.path.join(os.path.expanduser("~"), ".claude", "skills", "shared", "SKILL.md"), "---\nname: shared\ndescription: external copy\n---\nbody external\n") write(os.path.join(proj, ".claude", "skills", "proj-claude", "SKILL.md"), "---\nname: proj-claude\ndescription: project claude\n---\nbody pc\n") write(os.path.join(proj, ".agents", "skills", "proj-agents", "SKILL.md"), "---\nname: proj-agents\ndescription: project agents\n---\nbody pa\n") write(os.path.join(home, "skills", "shared", "SKILL.md"), "---\nname: shared\ndescription: tai copy\n---\nbody tai\n") write(os.path.join(home, "skills", "native", "SKILL.md"), "---\nname: native\ndescription: native home skill\n---\nbody native\n") write(os.path.join(home, "skills", "native", "scripts", "run.sh"), "echo hi\n") write(os.path.join(home, "skills", "native", "references", "ref.md"), "ref\n") write(os.path.join(home, "skills", "native", "assets", "a.txt"), "a\n") write(os.path.join(proj, ".tai", "skills", "proj-tai", "SKILL.md"), "---\nname: proj-tai\ndescription: project tai skill\n---\nbody ptai\n") write(os.path.join(home, "skills", "broken", "SKILL.md"), "no front matter\n") write(os.path.join(home, "skills", "stray-file.txt"), "x\n") tai.save_skill_install_meta(os.path.join(home, "skills"), "native", {"source": "/some/path", "mode": "symlink", "scope": "home", "n": 3, "nested": {"a": [1, None, True]}}) skills = tai.discover_skills(home, proj) for name in skills: s = skills[name] out("skill %s root=%s managed=%s install=%s note=%s extras=%s" % (name, s["root"], s["managed"], j(s["install"]), j(tai.skill_provenance_note(s)), j(tai.skill_extra_files(s["root"])))) out(" desc=%s body=%s" % (j(s["description"]), j(s["body"]))) out("order %s" % j(list(skills))) out("catalog %s" % j(tai.skill_catalog(skills))) out("== scope helpers") for scope in ("project", "home"): out("scope_dir %s %s" % (scope, tai.skill_scope_dir(scope, home, proj, "nm"))) out("scope_dir %s %s" % (scope, tai.skill_scope_dir(scope, home, proj))) empty = os.path.join(root, "emptyproj") os.makedirs(empty, exist_ok=True) out("default scope empty %s" % tai.default_skill_scope(empty)) for marker in (".git", ".tai", ".claude/skills", ".agents/skills"): d = os.path.join(root, "mk-" + marker.replace("/", "_")) os.makedirs(os.path.join(d, marker), exist_ok=True) out("default scope %s %s" % (marker, tai.default_skill_scope(d))) for path in ("/a/b/.claude/skills/x", "/a/b/.agents/skills/x/", "/a/b/other/x", "/a/.claude/skills/../x", "/a/.claude/skills//x"): out("external %s %s" % (path, tai.is_external_skill_root(path))) out("meta none %s" % j(tai.load_skill_install_meta(os.path.join(home, "skills"), "nothing"))) write(os.path.join(home, "skills", ".installs", "bad.json"), "{not json") out("meta bad %s" % j(tai.load_skill_install_meta(os.path.join(home, "skills"), "bad"))) out("meta ok %s" % j(tai.load_skill_install_meta(os.path.join(home, "skills"), "native"))) def sc_skills_ops(root): home = tai_home() def tree(): found = [] base = os.path.join(home, "skills") for dirpath, _dirs, files in os.walk(base): for f in files: found.append(os.path.relpath(os.path.join(dirpath, f), base)) return sorted(found) def step(label, mode): out("%s => %s" % (label, tai.op_skills(mode, home))) out(" status: %s" % tai.status_lines(home)[-2]) out(" files: %d" % len(tree())) out("-- fresh") step("install", "install") step("install again", "install") step("upgrade clean", "upgrade") out("pristine all %s" % j([tai.bundled_skill_pristine(home, n) for n in sorted(tai.BUNDLED_SKILLS)])) taste = os.path.join(home, "skills", "taste", "SKILL.md") write(taste, "user rewrite") out("-- modified taste") step("install", "install") step("upgrade", "upgrade") extra = os.path.join(home, "skills", "taste", "mynotes.md") write(extra, "mine") step("reinstall", "reinstall") out("extra kept %s" % os.path.isfile(extra)) out("-- crlf edit counts as equal after universal newlines") path = os.path.join(home, "skills", "plan", "SKILL.md") write(path, read(path).replace("\n", "\r\n")) step("upgrade crlf", "upgrade") out("-- uninstall with user content") gitp = os.path.join(home, "skills", "git", "SKILL.md") write(gitp, "user rewrite git") gextra = os.path.join(home, "skills", "git", "mynotes.md") write(gextra, "mine") write(os.path.join(home, "skills", "git", "sub", "deep.txt"), "deep") step("uninstall", "uninstall") step("uninstall again", "uninstall") os.remove(gitp) os.remove(gextra) os.remove(os.path.join(home, "skills", "git", "sub", "deep.txt")) step("uninstall final", "uninstall") step("uninstall empty", "uninstall") out("-- sidecar-only uninstall") tai.save_skill_install_meta(os.path.join(home, "skills"), "taste", {"files": {}}) step("uninstall sidecar", "uninstall") out("-- tracked-digest removal of an edited file") step("install", "install") meta = tai.load_skill_install_meta(os.path.join(home, "skills"), "taste") out("meta %s" % j(sorted(meta))) out("meta files %s" % j(meta["files"])) out("meta fixed %s" % j({k: meta[k] for k in ("source", "mode", "scope", "upstream", "bundled_version")})) os.chmod(os.path.join(home, "skills", "taste"), 0o500) step("install readonly", "install") os.chmod(os.path.join(home, "skills", "taste"), 0o700) out("-- error path: skills dir is a file") other = os.path.join(root, "home2") os.makedirs(other, exist_ok=True) write(os.path.join(other, "skills"), "file not dir") out("blocked => %s" % tai.op_skills("install", other)) out("blocked uninstall => %s" % tai.op_skills("uninstall", other)) sc_skills_install_tool(root) class SkillApp: def __init__(self, home, cwd): self.config = type("C", (), {"home": home})() self.profile = "default" self.skills = {} self.store = None self.depth = 0 self.runner_override = None self.approvals = [] self.refreshed = 0 self.approve = True def ask_approval(self, text): self.approvals.append(text) return self.approve def apply_system(self): self.refreshed += 1 def sc_skills_install_tool(root): home = tai_home() proj = os.path.join(root, "proj") os.chdir(proj) app = SkillApp(home, proj) app.skills = tai.discover_skills(home, proj) tools = tai.Tools(app) out("== install_skill / load_skill / create_skill") src = os.path.join(root, "srcskill") write(os.path.join(src, "SKILL.md"), "---\nname: from-src\ndescription: installed from a dir\n---\nbody src\n") write(os.path.join(src, "scripts", "x.sh"), "echo x\n") write(os.path.join(src, "references", "r.md"), "r\n") nested = os.path.join(root, "nested") write(os.path.join(nested, "inner", "SKILL.md"), "---\nname: inner\ndescription: nested one\n---\nbody inner\n") two = os.path.join(root, "two") write(os.path.join(two, "a", "SKILL.md"), "---\nname: aa\ndescription: d\n---\nb\n") write(os.path.join(two, "b", "SKILL.md"), "---\nname: bb\ndescription: d\n---\nb\n") barefile = os.path.join(root, "bare.md") write(barefile, "---\nname: bare-one\ndescription: bare md file\n---\nbody bare\n") badfile = os.path.join(root, "bad.md") write(badfile, "no front\n") ext = os.path.join(proj, ".claude", "skills", "extskill") write(os.path.join(ext, "SKILL.md"), "---\nname: extskill\ndescription: external one\n---\nbody ext\n") notes = [] def call(label, args): res = tools.dispatch("install_skill", json.dumps(args)) out("%s => %s" % (label, j(res))) call("empty", {"source": ""}) call("bad scope", {"source": src, "scope": "mars"}) call("bad mode", {"source": src, "mode": "link"}) call("missing", {"source": os.path.join(root, "nope")}) call("dir home", {"source": src, "scope": "home"}) call("dir home again denied?", {"source": src, "scope": "home"}) app.approve = False call("dir home denied", {"source": src, "scope": "home"}) app.approve = True call("dir home force", {"source": src, "scope": "home", "force": True}) call("dir project", {"source": src, "scope": "project", "name": "renamed"}) call("bad name", {"source": src, "name": "Bad Name"}) call("nested", {"source": nested, "scope": "home"}) call("two children", {"source": two, "scope": "home"}) call("bare file", {"source": barefile, "scope": "home"}) call("bad file", {"source": badfile}) call("symlink ext default", {"source": ext, "scope": "home"}) call("symlink explicit", {"source": src, "scope": "home", "mode": "symlink", "name": "linked", "force": True}) call("symlink bare", {"source": barefile, "mode": "symlink"}) call("not a skill source", {"source": "/dev/null"}) out("approvals %s" % j(app.approvals)) out("refreshed %d" % app.refreshed) out("skills %s" % j(sorted(app.skills))) out("== load_skill") app.skills = tai.discover_skills(home, proj) for name in ("from-src", "deep-research", "extskill", "bot-creator", "nonexistent", ""): if name == "bot-creator": continue out("load %s => %s" % (j(name), j(tools.dispatch("load_skill", json.dumps({"name": name}))))) out("== create_skill") app.runner_override = lambda prompt, profile, timeout: "worker said: " + prompt[:40] + " t=%s" % timeout for args in ({"name": "", "brief": "b"}, {"name": "ok-name", "brief": ""}, {"name": "ok-name", "brief": "b", "scope": "mars"}, {"name": "made", "brief": "make it", "scope": "home", "timeout": 10}, {"name": "made2", "brief": "make it", "timeout": "abc"}, {"name": "made3", "brief": "x", "timeout": 99999}): out("create %s => %s" % (j(args), j(tools.dispatch("create_skill", json.dumps(args))))) app.depth = 5 out("create depth => %s" % j(tools.dispatch("create_skill", json.dumps({"name": "dd", "brief": "b"})))) app.depth = 0 def worker(prompt, profile, timeout): marker = "Create a new agent skill named 'wrote' in " path = prompt[len(marker):].split(".\n", 1)[0] write(os.path.join(path, "SKILL.md"), "---\nname: wrote\ndescription: written by worker\n---\nbody wrote\n") return "done writing " + path.replace(root, "") app.runner_override = worker out("create written => %s" % j(tools.dispatch("create_skill", json.dumps({"name": "wrote", "brief": "w", "scope": "home"})).replace(root, ""))) out("create replaced => %s" % j(tools.dispatch("create_skill", json.dumps({"name": "wrote", "brief": "w", "scope": "home"})).replace(root, ""))) out("refreshed %d" % app.refreshed) # ------------------------------------------------------------------ install scenarios class FakeBox: """Deterministic stand-in for the container probes (patched into tai.py; the C++ twin is FakeBox in the driver).""" def __init__(self, engine, state, venv, ensure_error): self.engine, self.state, self.venv, self.ensure_error = engine, state, venv, ensure_error def install(self): tai.container_engine = lambda: self.engine tai.box_state = lambda engine: self.state tai.box_venv_state = lambda engine: self.venv def ensure(): if self.ensure_error: raise tai.BackendError(self.ensure_error) return self.engine tai.ensure_box = ensure def install_env(root, engine=None, state="running", venv="venv ready", ensure_error=""): FakeBox(engine, state, venv, ensure_error).install() def sc_install_hooks(root): install_env(root) home = tai_home() rc = os.path.join(os.path.expanduser("~"), ".bashrc") zrc = os.path.join(os.path.expanduser("~"), ".zshrc") write(rc, "# my bashrc\nexport A=1") write(zrc, "") steps = [ ("bash install", lambda: tai.op_hook("install", home)), ("bash install again", lambda: tai.op_hook("install", home)), ("bash upgrade", lambda: tai.op_hook("upgrade", home)), ("plexer install", lambda: tai.op_plexer_hook("install", home)), ("plexer again", lambda: tai.op_plexer_hook("install", home)), ("zsh install", lambda: tai.op_zsh_hook("install", home)), ("zsh again", lambda: tai.op_zsh_hook("install", home)), ("fish install", lambda: tai.op_fish_hook("install", home)), ("zsh plexer install", lambda: tai.op_zsh_plexer_hook("install", home)), ("fish plexer install", lambda: tai.op_fish_plexer_hook("install", home)), ("status", lambda: "\n".join(tai.status_lines(home))), ("bash reinstall", lambda: tai.op_hook("reinstall", home)), ("plexer reinstall", lambda: tai.op_plexer_hook("reinstall", home)), ("zsh uninstall", lambda: tai.op_zsh_hook("uninstall", home)), ("fish uninstall", lambda: tai.op_fish_hook("uninstall", home)), ("zsh uninstall again", lambda: tai.op_zsh_hook("uninstall", home)), ("bash uninstall", lambda: tai.op_hook("uninstall", home)), ("plexer uninstall", lambda: tai.op_plexer_hook("uninstall", home)), ("zsh plexer uninstall", lambda: tai.op_zsh_plexer_hook("uninstall", home)), ("fish plexer uninstall", lambda: tai.op_fish_plexer_hook("uninstall", home)), ("status after", lambda: "\n".join(tai.status_lines(home))), ] for label, fn in steps: out("%s => %s" % (label, j(fn()))) out("rc %s" % j(read(rc))) out("zrc %s" % j(read(zrc))) out("== stale and duplicated blocks") write(rc, "head\n" + tai.BASHRC_MARK_BEGIN + "\nstale content\n" + tai.BASHRC_MARK_END + "\nmid\n" + tai.BASHRC_MARK_BEGIN + "\nsecond stale\n" + tai.BASHRC_MARK_END + "\ntail\n") out("install over stale => %s" % j(tai.op_hook("install", home))) out("rc %s" % j(read(rc))) write(rc, "x\n" + tai.BASHRC_MARK_BEGIN + "\nunterminated\n") out("install over unterminated => %s" % j(tai.op_hook("install", home))) out("rc %s" % j(read(rc))) out("uninstall unterminated => %s" % j(tai.op_hook("uninstall", home))) out("rc %s" % j(read(rc))) write(rc, "crlf\r\nline\r\n") out("install crlf => %s" % j(tai.op_hook("install", home))) out("rc %s" % j(read(rc))) os.chmod(rc, 0o400) out("readonly install => %s" % j(tai.op_plexer_hook("install", home))) os.chmod(rc, 0o600) blocks = [tai.hook_present, tai.zsh_hook_present, tai.fish_hook_present, tai.plexer_hook_present, tai.zsh_plexer_hook_present, tai.fish_plexer_hook_present] out("present %s" % j([fn(rc) for fn in blocks])) out("present missing %s" % j([fn(os.path.join(root, "nope")) for fn in blocks])) for shell in ("bash", "zsh", "fish", "other"): out("rc path %s %s" % (shell, tai.shell_rc_path(shell))) os.environ["XDG_CONFIG_HOME"] = os.path.join(root, "xdg") out("rc path fish xdg %s" % tai.shell_rc_path("fish")) del os.environ["XDG_CONFIG_HOME"] out("shell_present %s" % j([tai.shell_present(n) for n in ("zsh", "fish", "bash", "nosuchshell")])) def sc_install_ops(root): install_env(root, engine="podman", state="running", venv="venv ready") home = tai_home() out("-- binary") for mode in ("install", "install", "upgrade", "reinstall", "uninstall", "uninstall", "install"): out("binary %s => %s" % (mode, j(tai.op_binary(mode, home)))) target = os.path.join(os.path.expanduser("~"), ".local", "bin", "tai.py") out("binary mode %s size_equal %s" % (oct(os.stat(target).st_mode & 0o777), os.path.getsize(target) == os.path.getsize(tai.__file__))) write(target, "VERSION = \"0.0.1\"\n") out("binary refresh => %s" % j(tai.op_binary("install", home))) out("binary refresh upgrade => %s" % j(tai.op_binary("upgrade", home))) out("script_version %s %s %s" % (j(tai.script_version(target)), j(tai.script_version(os.path.join(root, "nope"))), j(tai.script_version(tai.__file__)))) write(os.path.join(root, "v1"), "x\nVERSION = \"1.2.3\"\ny\n") write(os.path.join(root, "v2"), "VERSION = \"1.2\"\n VERSION = \"1.2.3\"\nVERSION = \"a.b.c\"\n") write(os.path.join(root, "v3"), "VERSION = \"4.5.6\"") write(os.path.join(root, "v4"), "VERSION = \"4.5.6\" \n") out("script_version v1..v4 %s" % j([tai.script_version(os.path.join(root, n)) for n in ("v1", "v2", "v3", "v4")])) out("-- venv") for mode in ("install", "install", "reinstall", "uninstall", "uninstall", "install"): out("venv %s => %s" % (mode, j(tai.op_venv(mode, home).replace(root, "")))) out("venv helpers %s %s %s" % (j(tai.venv_dir(home).replace(root, "")), j((tai.venv_python(home) or "").replace(root, "")), tai.venv_available())) out("-- services (no systemctl)") for mode in ("install", "install", "reinstall", "upgrade", "uninstall", "uninstall"): out("scheduler %s => %s" % (mode, j(tai.op_scheduler_service(mode, home).replace(root, "")))) out("telegram without token => %s" % j(tai.op_telegram_service("install", home))) out("service_exec %s" % j(tai.service_exec(home, "/x/tai.py", "--a", "b").replace(root, ""))) out("unit_dir %s" % j(tai.unit_dir(home).replace(root, ""))) out("service_state %s" % j(tai.service_state("tai-scheduler.service"))) out("activate %s" % j(tai.activate_service("tai-scheduler.service"))) out("remove %s" % j(tai.remove_service_unit(home, "tai-scheduler.service"))) out("-- container") for mode in ("install", "upgrade", "reinstall", "uninstall"): out("container %s => %s" % (mode, j(tai.op_container(mode, home)))) install_env(root, engine="podman", state="stopped", venv="no venv (reinstall container to rebuild)") for mode in ("install", "reinstall"): out("container stopped %s => %s" % (mode, j(tai.op_container(mode, home)))) install_env(root, engine="podman", state="running", venv="venv ready", ensure_error="engine exploded") out("container failing => %s" % j(tai.op_container("install", home))) install_env(root, engine=None) for mode in ("install", "uninstall"): out("container noengine %s => %s" % (mode, j(tai.op_container(mode, home)))) install_env(root, engine="podman", state="running", venv="venv ready") out("-- install_report") for action, targets in (("install", ["skills", "bash-hook", "venv"]), ("status", ["skills"]), ("upgrade", list(tai.INSTALL_TARGETS)), ("uninstall", ["skills", "bash-hook", "plexer-hook", "binary"])): out("report %s %s =>\n%s" % (action, targets, tai.install_report(action, targets, home).replace(root, ""))) out("-- install_self") for shell in ("/bin/bash", "/usr/bin/zsh", "/usr/bin/fish", "", "/bin/sh"): os.environ["SHELL"] = shell out("shell %s" % j(shell)) sys.stdout.flush() tai.install_self() out("-- install tool") app = SkillApp(home, root) app.config.home = home tools = tai.Tools(app) for args in ({"action": "bogus"}, {"action": "status"}, {"action": "STATUS ", "targets": ["skills"]}, {"action": "install", "targets": ["nope"]}, {"action": "install", "targets": []}, {"action": "install", "targets": "skills"}, {"action": "install", "targets": ["skills"]}, {"action": "uninstall", "targets": ["skills", "bash-hook"]}, {}): app.skills = {} res = tools.dispatch("install", json.dumps(args)).replace(root, "") out("tool %s => %s | skills=%s" % (j(args), j(res), j(sorted(app.skills)))) app.approve = False out("tool denied => %s" % j(tools.dispatch("install", json.dumps({"action": "install", "targets": ["skills"]})))) out("approvals %s" % j(app.approvals)) def sc_install_noengine(root): install_env(root, engine=None) home = tai_home() out("%s" % j(tai.status_lines(home)[-3:])) for mode in ("install", "uninstall"): out("container %s => %s" % (mode, j(tai.op_container(mode, home)))) def sc_vault_line(root): home = tai_home() out("empty %s" % j(tai.vault_line(home))) write(os.path.join(home, "memory.db"), "") out("kept %s" % j(tai.vault_line(home).replace(root, ""))) # ------------------------------------------------------------------ scheduler scenarios def open_store(profile="t"): class FakeArgs: yes = True FakeArgs.profile = profile config = tai.Config(FakeArgs) seal = tai.Seal(config.home, "") store = tai.Store(config, seal) return config, seal, store NOW_FIXED = "2026-10-25T12:00:00+00:00" LONG_EVERY = 315360000 # ten years: recurring claims land far in the future so reruns are stable def prep_sched(root): config, seal, store = open_store() past = "2026-01-01T00:00:00+00:00" store.add_schedule("once-due", "do:once", "t", 0, past, 300) store.add_schedule("rec-due", "do:rec", "t", LONG_EVERY, past, 600, ["alpha", "beta"]) store.add_schedule("future", "do:future", "t", 0, "2099-01-01T00:00:00+00:00", 600, []) store.add_schedule("leased", "do:leased", "t", LONG_EVERY, "2026-02-01T00:00:00+00:00", 600) store.add_schedule("stale-lease", "do:stale", "t", LONG_EVERY, "2026-03-01T00:00:00+00:00", 600) store.add_schedule("exploder", "boom: fail", "t", 0, "2026-04-01T00:00:00+00:00", 300) store.add_schedule("other-profile", "do:other", "other", 0, "2026-06-01T00:00:00+00:00", 300) store.add_schedule("bad-time", "do:badtime", "t", LONG_EVERY, "!!bad", 300) store.add_schedule("", "x" * 100, "t", 0, "2099-06-01T00:00:00+00:00", 300, ["one"]) store.add_schedule("with-result", "do:result", "t", 3600, "2099-07-01T00:00:00+00:00", 300) store.db.execute("UPDATE schedules SET last_status = 'running', updated = ? WHERE name = 'leased'", (tai.datetime.now(tai.timezone.utc).isoformat(),)) store.db.execute("UPDATE schedules SET last_status = 'running', updated = '2000-01-01T00:00:00+00:00' WHERE name = 'stale-lease'") store.db.execute("UPDATE schedules SET last_status = 'done', last_result = ? WHERE name = 'with-result'", ("r" * 200,)) store.db.commit() store.close() def sched_rows(store, label): rows = store.db.execute("SELECT id, name, prompt, profile, every_sec, next_run, timeout, status, last_status, last_result, updated FROM schedules ORDER BY id").fetchall() out("-- %s" % label) for row in rows: out("row %s" % j(list(row))) tags = store.db.execute("SELECT item, tag, profile FROM tags WHERE item LIKE 'sched:%' ORDER BY item, tag").fetchall() out("tags %s" % j([list(t) for t in tags])) class Gate: """Blocks 'slow:' tasks until released, like a long-running worker.""" def __init__(self): self.event = tai.threading.Event() def runner(self, task, profile, timeout): if task.startswith("slow:"): self.event.wait(30) return "slow done " + task if "boom" in task: raise RuntimeError("boom") return "ok:" + task def quiesce(): for _ in range(200): if tai.threading.active_count() <= 1: return tai.time.sleep(0.05) def sc_sched(root): config, seal, store = open_store() gate = Gate() out("== list and format") items = store.list_schedules() for it in items: out("item %s" % j(it)) out("format:\n%s" % tai.format_schedule_lines(items, tai._fromisoformat(NOW_FIXED))) out("format empty: %s" % tai.format_schedule_lines([], tai._fromisoformat(NOW_FIXED))) out("other profile: %s" % j(store.list_schedules("other"))) out("== running leases") for status, updated, timeout in (("running", tai.datetime.now(tai.timezone.utc).isoformat(), 600), ("running", "2000-01-01T00:00:00+00:00", 600), ("done", "", 0), ("running", "garbage", 10), ("running", tai.datetime.now(tai.timezone.utc).isoformat(), 0)): out("running %s %s %s => %s" % (status, "now" if updated.startswith("2026") else updated, timeout, tai.schedule_running(status, updated, timeout))) out("== sealed rows (added now: Store refuses to open with them present and no passphrase)") store.add_schedule("sealed", "tai1$AAAA$BBBB$CCCC", "t", 0, "2026-05-01T00:00:00+00:00", 300) store.add_schedule("sealed-corrupt", "tai1$bad", "t", 0, "2026-05-02T00:00:00+00:00", 300) out("== tick 1") sys.stdout.flush() fired = tai.scheduler_tick(config, seal, gate.runner) sys.stdout.flush() out("fired %d" % fired) quiesce() sched_rows(store, "after tick 1") out("== tick 2") out("fired %d" % tai.scheduler_tick(config, seal, gate.runner)) quiesce() out("== cap phase") for k in range(9): store.add_schedule("slow%d" % k, "slow:%d" % k, "t", LONG_EVERY, "2025-01-0%dT00:00:00+00:00" % (k + 1), 600) out("fired %d" % tai.scheduler_tick(config, seal, gate.runner)) out("fired %d" % tai.scheduler_tick(config, seal, gate.runner)) out("running agents %d" % tai.running_agents()) out("fired %d" % tai.scheduler_tick(config, seal, gate.runner)) sys.stdout.flush() sched_rows(store, "after cap ticks") out("== AgentsFull restore branch") store.add_schedule("full-once", "slow:once", "t", 0, "2025-02-01T00:00:00+00:00", 600) real = tai.running_agents tai.running_agents = lambda: 0 out("fired %d" % tai.scheduler_tick(config, seal, gate.runner)) tai.running_agents = real sched_rows(store, "after AgentsFull") gate.event.set() quiesce() sched_rows(store, "after release") out("== schedule tool") app = SkillApp(tai_home(), root) app.store = store app.profile = "t" tools = tai.Tools(app) calls = [ {"prompt": ""}, {"prompt": "p"}, {"prompt": "p", "at": "2099-01-01T10:00", "every": 120}, {"prompt": "p", "at": "nonsense"}, {"prompt": "p", "every": "abc"}, {"prompt": "p", "every": 30}, {"prompt": "tool one", "at": "2099-01-01T10:00", "name": "N" * 100, "timeout": 5, "tags": ["Alpha", "beta!", "", "x" * 40]}, {"prompt": "tool two", "every": 3600, "timeout": "abc", "profile": "t"}, {"prompt": "tool three", "every": "7200", "timeout": 99999}, {"prompt": "p", "every": 60, "profile": "other"}, {"prompt": "p", "every": 60, "profile": "bad profile!"}, {"prompt": "p", "every": 60, "tags": "notalist"}, {"prompt": "p", "every": 60, "tags": [1, 2]}, {"prompt": "tool four", "every": 86400, "tags": []}, {"prompt": " padded ", "at": "2099-02-02T02:02:02Z", "timeout": 0}, {"prompt": "p", "at": "9999-12-31T24:00"}, {"prompt": "p", "at": "0001-01-01T00:00"}, {"prompt": "p", "every": 60.5}, {"prompt": "p", "every": True}, ] for args in calls: out("schedule %s => %s" % (j(args), j(tools.dispatch("schedule", json.dumps(args))))) app.approve = False out("schedule denied => %s" % j(tools.dispatch("schedule", json.dumps({"prompt": "denied", "every": 60})))) app.approve = True out("schedules => %s" % j(tools.dispatch("schedules", "{}"))) for args in ({"id": 999}, {"id": "abc"}, {"id": 0}, {}, {"id": "13"}, {"id": 14.0}): out("unschedule %s => %s" % (j(args), j(tools.dispatch("unschedule", json.dumps(args))))) app.approve = False out("unschedule denied => %s" % j(tools.dispatch("unschedule", json.dumps({"id": 15})))) app.approve = True out("approvals %s" % j(app.approvals)) sched_rows(store, "final") out("remove nonexistent %s" % store.remove_schedule(99999)) store.close() # ------------------------------------------------------------------ rag scenarios WORDS = ("alpha bravo charlie delta echo foxtrot golf hotel india juliet kilo lima mike november oscar papa quebec romeo sierra tango uniform victor whiskey xray yankee zulu " "database retrieval indexing scheduler terminal pipeline compiler optimizer allocator tokenizer scanner buffer kernel module package release rollback deployment " "café naïve résumé über 中文 snake_case kebab-case CamelCase ALLCAPS numbers123 v2beta").split() def prep_rag(root): import random rng = random.Random(7) config, seal, store = open_store() ids = [] for index in range(30): title = " ".join(rng.choice(WORDS) for _ in range(rng.randint(1, 4))) lines = [] for _ in range(rng.randint(1, 12)): lines.append(" ".join(rng.choice(WORDS) for _ in range(rng.randint(3, 14)))) content = "\n".join(lines) kind = rng.choice(["note", "doc", "termlog"]) rid = store.add_record(kind, title, content, [rng.choice(["x", "y", "zed"])] if index % 3 == 0 else [], "t") store.add_chunks("record", rid, tai.chunk_lines(content, 3, 1, 200), "t") ids.append(rid) store.add_record("note", "unique zebra", "the quick zebra jumps over the lazy dog " * 30, [], "t") store.add_record("note", "other profile secret", "alpha bravo hidden", [], "other") store.add_edge(ids[0], ids[1], "relates to", "t") store.add_edge(ids[2], ids[0], "see also", "t") store.add_edge(ids[0], ids[3], "x", "t") store.add_edge(ids[0], ids[4], "y", "t") store.add_edge(ids[0], ids[5], "z", "t") for index in range(6): store.audit_event("main", "write", "/tmp/file%d.txt" % index, "wrote alpha file %d" % index, None, "content %d" % index, ["t%d" % index], None, None, "t") store.log_event("t", "user", "message", "hello alpha retrieval message") store.log_event("t", "assistant", "message", "bravo reply about indexing") # implicit pairs: search events followed by reads store.log_event("t", "tool", "search-query", "q=alpha\tlimit=5\thits=record:%s,record:%s,chunk:3" % (ids[0], ids[1])) store.log_event("t", "tool", "record-read", ids[1]) store.log_event("t", "tool", "search-query", "q=nothing here\tlimit=5\thits=") store.log_event("t", "tool", "search-query", "q=bravo\tlimit=5\thits=%s,record:%s" % (ids[2], ids[3])) store.log_event("t", "tool", "record-read", " %s " % ids[9]) store.log_event("t", "tool", "record-read", ids[2]) store.log_event("t", "tool", "search-query", "no equals sign") store.log_event("t", "tool", "search-query", "q=\thits=x") store.log_event("t", "tool", "search-query", "q=a=b\tq=delta\thits=,,record:%s," % ids[6]) store.log_event("t", "tool", "record-read", "") store.close() def hit_json(h): return {"item": h["item"], "kind": h["kind"], "sub": h["sub"], "title": h["title"], "snippet": h["snippet"], "rank": h["rank"]} def sc_rag(root): config, seal, store = open_store() out("== fts_search") queries = ["alpha", "alpha bravo", "zebra", "café", "résumé naïve", "snake_case", "numbers123", "nothingmatchesthis", "", "!!!", "retrieval index", "wh", "ALPHA", "x" * 50, "unique zebra jumps", "message", "file", "ro", "v2beta kernel"] for q in queries: for kinds in ((), ("record",), ("chunk",), ("audit",), ("event",), ("record", "chunk")): for limit in (10, 3): hits = store.fts_search(q, kinds, "t", limit) out("search %s %s %d => %s" % (j(q), j(list(kinds)), limit, j([hit_json(h) for h in hits]))) out("other profile %s" % j([hit_json(h) for h in store.fts_search("alpha", ("record",), "other", 10)])) out("limits %s" % j([len(store.fts_search("alpha", (), "t", n)) for n in (0, -5, 1, 100, 500)])) out("== eval") out("tokens %s" % j(tai.RetrievalEval.tokens("The quick Brown fox jumped_over 123456 abcdefg ABCDEFG cafés résumés"))) out("tokens4 %s" % j(tai.RetrievalEval.tokens("The quick Brown fox", 4))) goldens = tai.RetrievalEval.goldens_from_vault(store, "t") out("goldens %d" % len(goldens)) for g in goldens: out("golden %s" % j(g)) result = tai.RetrievalEval.score(store, goldens, "t") out("score %s" % j(result)) pairs = tai.RetrievalEval.implicit_pairs(store, "t") out("pairs %s" % j(pairs)) out("report:\n%s" % tai.RetrievalEval.format_report(result, pairs)) out("empty report:\n%s" % tai.RetrievalEval.format_report(tai.RetrievalEval.score(store, [], "t"), tai.RetrievalEval.implicit_pairs(store, "nobody"))) out("small k %s" % j(tai.RetrievalEval.score(store, goldens[:12], "t", ("record",), 1, 2))) out("rank_of %s %s %s" % (j(tai.RetrievalEval.rank_of("b", ["a", "b"])), j(tai.RetrievalEval.rank_of("z", ["a"])), j(tai.RetrievalEval.best_rank(["z", "a"], ["q", "a", "z"])))) out("metrics %s" % j([tai.RetrievalEval.hit_at_k(3), tai.RetrievalEval.hit_at_k(6), tai.RetrievalEval.hit_at_k(None), tai.RetrievalEval.reciprocal_rank(4), tai.RetrievalEval.ndcg_at_k(3), tai.RetrievalEval.ndcg_at_k(9), tai.RetrievalEval.context_precision(["a", "c"], ["a", "b", "c", "d"]), tai.RetrievalEval.context_precision([], ["a"]), tai.RetrievalEval.context_precision(["x"], ["a"])])) for text in ("q=alpha\thits=record:m1,m2,,chunk:4", "nothing", "q=\thits=a", "a=b=c\tq= spaced \thits= x ,y ", "q=a\tq=b\thits=record:z"): out("parse %s => %s" % (j(text), j(tai.RetrievalEval._parse_search_event(text)))) out("== chunks table") rid = store.db.execute("SELECT id FROM records WHERE profile = 't' ORDER BY id LIMIT 1").fetchone()[0] store.add_chunks("record", rid, ["one", "two", "three"], "t") rows = store.db.execute("SELECT id, parent_kind, parent_id, idx, text, profile FROM chunks WHERE parent_id = ? ORDER BY idx", (rid,)).fetchall() out("chunks %s" % j([list(r) for r in rows])) ids = [r[0] for r in rows] got = store.get_chunks_by_ids(ids + [999999], "t") out("by ids %s" % j({str(k): v for k, v in sorted(got.items())})) out("by ids empty %s other %s" % (j(store.get_chunks_by_ids([], "t")), j(store.get_chunks_by_ids(ids, "other")))) store.add_chunks("record", rid, [], "t") out("after clear %d" % store.db.execute("SELECT COUNT(*) FROM chunks WHERE parent_id = ?", (rid,)).fetchone()[0]) out("== search tool") app = SkillApp(tai_home(), root) app.store = store app.profile = "t" tools = tai.Tools(app) calls = [{"query": ""}, {"query": "alpha"}, {"query": "alpha", "limit": 3}, {"query": "alpha", "limit": "2"}, {"query": "alpha", "limit": "x"}, {"query": "alpha", "limit": 0}, {"query": "alpha", "limit": -2}, {"query": "retrieval", "kinds": ["chunk"]}, {"query": "alpha", "kinds": ["record"], "expand": True, "limit": 20}, {"query": "alpha", "kinds": ["bogus"]}, {"query": "alpha", "kinds": []}, {"query": "alpha", "kinds": "record"}, {"query": "file", "kinds": ["audit"]}, {"query": "message", "kinds": ["event"]}, {"query": "zebra", "kinds": ["record", "chunk", "audit"]}, {"query": "nothingmatchesthis"}, {"query": "x" * 200}, {"query": " spaced "}, {"query": "café résumé", "limit": 50}] for args in calls: out("search %s => %s" % (j(args), j(tools.dispatch("search", json.dumps(args))))) out("logged %s" % j([list(r) for r in store.db.execute("SELECT profile, role, kind, text FROM events WHERE kind = 'search-query' ORDER BY id DESC LIMIT 25").fetchall()])) store.close() # ------------------------------------------------------------------ telegram scenarios class CtxDict(dict): def __setitem__(self, key, value): out("CTX set %s=%s" % (key, value)) dict.__setitem__(self, key, value) def pop(self, key, *default): out("CTX pop %s" % key) return dict.pop(self, key, *default) class LogStub: enabled = False def __init__(self): self.context = CtxDict() def event(self, level, component, event, message, profile="", bot="", chat="", meta=None): out("LOG %s" % j([level, component, event, message, profile, bot, chat, meta])) class TgAgent: profile = "t" bot = "main" def __init__(self, home): self.config = type("C", (), {"home": home})() self.store = type("S", (), {"seal": None})() def reset_history(self): out("AGENT reset_history") def run_turn(self, text, capture=False): out("AGENT run_turn %s capture=%s" % (j(text), capture)) if "explode" in text: raise RuntimeError("agent exploded") if text == "long": return "L" * 9000 if text == "empty reply": return "" return "echo:" + text class StopLoop(Exception): pass def tg_setup(root): tai.TELEGRAM_API = os.environ["MISC_TG_API"] tai.TELEGRAM_FILE_API = os.environ["MISC_TG_FILE"] tai.LOG = LogStub() def ensure(): out("BOX ensure_box") if os.environ.get("MISC_BOX_FAIL"): raise tai.BackendError("box down") return "eng" def transcribe(engine, audio): out("BOX transcribe %s %s" % (engine, j(audio.decode("latin-1")))) if audio == b"AUDIO": return "voice says hi" return "error: model failed" tai.ensure_box = ensure tai.box_transcribe = transcribe tai.start_scheduler = lambda config, seal: out("start_scheduler called") def sc_telegram(root): tg_setup(root) home = tai_home() out("== token") env_path = tai.telegram_env_path(home) out("env path %s" % j(env_path.replace(root, ""))) os.environ.pop("TELEGRAM_BOT_TOKEN", None) out("no file => %s" % j(tai.load_telegram_token(home))) for label, body in (("plain", "TELEGRAM_BOT_TOKEN=abc123\n"), ("quoted", "TELEGRAM_BOT_TOKEN='abc'\n"), ("dquoted", 'TELEGRAM_BOT_TOKEN="x y"\n'), ("spaces", "TELEGRAM_BOT_TOKEN= spaced \n"), ("other first", "OTHER=1\nTELEGRAM_BOT_TOKEN=second\nTELEGRAM_BOT_TOKEN=third\n"), ("none", "OTHER=1\n"), ("empty", ""), ("crlf", "TELEGRAM_BOT_TOKEN=win\r\n"), ("noeq", "TELEGRAM_BOT_TOKEN\n"), ("eq in value", "TELEGRAM_BOT_TOKEN=a=b=c\n"), ("quotes only", "TELEGRAM_BOT_TOKEN=''\n"), ("indented", " TELEGRAM_BOT_TOKEN=nope\n")): write(env_path, body) out("file %s => %s" % (label, j(tai.load_telegram_token(home)))) os.environ["TELEGRAM_BOT_TOKEN"] = "fromenv" out("env wins => %s" % j(tai.load_telegram_token(home))) os.environ["TELEGRAM_BOT_TOKEN"] = "" out("empty env falls back => %s" % j(tai.load_telegram_token(home))) os.environ.pop("TELEGRAM_BOT_TOKEN", None) os.remove(env_path) out("== call / send") good = tai.Telegram("good") out("getMe %s" % j(good.call("getMe", {}))) for label, token, method in (("bad token", "bad", "getMe"), ("not json", "nojson", "getMe")): try: res = tai.Telegram(token).call(method, {}) out("%s => %s" % (label, j(res))) except (OSError, ValueError) as exc: out("%s => raised %s" % (label, j(tai.short_error(exc)))) for text in ("", "short", "S" * 4000, "S" * 4001, "S" * 8000, "S" * 8001, "é" * 4001, "\U0001f600" * 4100, "line\n" * 2000): tai.telegram_send(good, 42, text) tai.telegram_send(good, "chat-as-string", "hi") out("== updates") agent = TgAgent(home) updates = [ {"update_id": 1, "message": {"chat": {"id": 111}, "text": "/start"}}, {"update_id": 2, "message": {"chat": {"id": 111}, "text": "/new"}}, {"update_id": 3, "message": {"chat": {"id": 111}, "text": "hello there"}}, {"update_id": 4, "message": {"chat": {"id": 111}, "text": ""}}, {"update_id": 5, "message": {"chat": {"id": 111}, "text": " "}}, {"update_id": 6, "message": {"chat": {"id": 0}, "text": "zero chat"}}, {"update_id": 7, "message": {"text": "no chat"}}, {"update_id": 8}, {"update_id": 9, "message": {"chat": {"id": 111}}}, {"update_id": 10, "message": {"chat": {"id": 111}, "text": "explode please"}}, {"update_id": 11, "message": {"chat": {"id": 111}, "text": "long"}}, {"update_id": 12, "message": {"chat": {"id": 111}, "text": "empty reply"}}, {"update_id": 13, "message": {"chat": {"id": 222}, "voice": {"file_id": "f1"}}}, {"update_id": 14, "message": {"chat": {"id": 222}, "audio": {"file_id": "f1"}}}, {"update_id": 15, "message": {"chat": {"id": 222}, "voice": {"file_id": "nofile"}}}, {"update_id": 16, "message": {"chat": {"id": 222}, "voice": {"file_id": "fbad"}}}, {"update_id": 17, "message": {"chat": {"id": 222}, "voice": {"file_id": "fmodel"}}}, {"update_id": 18, "message": {"chat": {"id": 222}, "voice": {}, "text": "text with empty voice"}}, {"update_id": 19, "message": {"chat": {"id": 222}, "voice": {"file_id": "fmissingfile"}}}, {"update_id": 20, "message": {"chat": {"id": "str-chat"}, "text": "string chat id"}}, {"update_id": 21, "message": {"chat": {"id": 111}, "text": "unicode café \U0001f600"}}, ] for update in updates: out("-- update %s" % j(update)) try: tai.handle_telegram_update(agent, good, update) except Exception as exc: out("raised %s" % j(tai.short_error(exc))) os.environ["MISC_BOX_FAIL"] = "1" out("-- box failing") try: tai.handle_telegram_update(agent, good, {"update_id": 30, "message": {"chat": {"id": 5}, "voice": {"file_id": "f1"}}}) except Exception as exc: out("raised %s" % j(tai.short_error(exc))) os.environ.pop("MISC_BOX_FAIL", None) out("== run_telegram_bot") for label, token in (("missing", None), ("bad auth", "bad"), ("not json", "nojson"), ("no username", "noname"), ("good", "good")): os.environ.pop("TELEGRAM_BOT_TOKEN", None) if token: os.environ["TELEGRAM_BOT_TOKEN"] = token out("-- run %s" % label) sys.stdout.flush() def stop_sleep(seconds): out("sleep %s" % seconds) raise StopLoop() tai.time.sleep = stop_sleep try: res = tai.run_telegram_bot(agent) out("returned %s" % res) except StopLoop: out("stopped by sleep") sys.stdout.flush() sys.stderr.flush() def sc_telegram_install(root): tg_setup(root) home = tai_home() install_env(root, engine="podman", state="running", venv="venv ready") for label, token in (("good", "good"), ("bad", "bad"), ("nojson", "nojson"), ("noname", "noname")): os.environ["TELEGRAM_BOT_TOKEN"] = token out("-- install_telegram %s" % label) sys.stdout.flush() res = tai.install_telegram() out("returned %s" % res) out("unit exists %s env exists %s" % (os.path.exists(os.path.join(os.path.expanduser("~"), ".config", "systemd", "user", "tai-telegram.service")), os.path.exists(tai.telegram_env_path(home)))) os.environ.pop("TELEGRAM_BOT_TOKEN", None) out("-- install_telegram without token (stdin closed)") sys.stdout.flush() out("returned %s" % tai.install_telegram()) out("-- install_telegram box failing") install_env(root, engine="podman", ensure_error="no engine here") os.environ["TELEGRAM_BOT_TOKEN"] = "good" out("returned %s" % tai.install_telegram()) install_env(root, engine="podman", state="running", venv="venv ready") out("-- op_telegram_service") for token in ("good", "bad", "nojson", "noname"): os.environ["TELEGRAM_BOT_TOKEN"] = token for mode in ("install", "install", "reinstall", "upgrade", "uninstall", "uninstall"): out("service %s %s => %s" % (token, mode, j(tai.op_telegram_service(mode, home).replace(root, "")))) os.environ.pop("TELEGRAM_BOT_TOKEN", None) write(tai.telegram_env_path(home), "TELEGRAM_BOT_TOKEN=good\n") out("service from env file => %s" % j(tai.op_telegram_service("install", home))) out("-- uninstall_telegram") out("returned %s" % tai.uninstall_telegram()) install_env(root, engine=None) out("returned noengine %s" % tai.uninstall_telegram()) # ------------------------------------------------------------------ release / audit scenarios def prep_release(root): config, seal, store = open_store() store.close() def sc_release(root): import shutil config, seal, store = open_store() script = os.path.join(root, "script.py") shutil.copy(tai.__file__, script) tai.__file__ = script folder = os.path.join(root, "backups") out("== versions") for cur, part in (("1.2.3", "patch"), ("1.2.3", "minor"), ("1.2.3", "major"), ("9.9.9", "patch"), ("1.2.3", "bogus"), ("1.2", "patch"), ("a.b.c", "patch"), ("1.2.3.4", "patch")): try: out("next %s %s => %s" % (cur, part, tai.next_version(cur, part))) except Exception as exc: out("next %s %s => raised %s" % (cur, part, j(str(exc)))) out("== bump") for part in ("patch", "minor", "major", "patch"): out("bump %s => %s" % (part, j(tai.release_bump(script, part)))) with open(script, encoding="utf-8") as handle: text = handle.read() out("version line %s" % j([l for l in text.splitlines() if l.startswith("VERSION = ")])) novers = os.path.join(root, "nov.py") write(novers, "print('x')\n") for f in (novers, os.path.join(root, "missing.py")): try: tai.release_bump(f, "patch") except Exception as exc: out("bump error %s" % j(str(exc).replace(root, ""))) write(os.path.join(root, "crlf.py"), 'a\r\nVERSION = "1.0.0"\r\nb\r\n') out("crlf bump %s %s" % (j(tai.release_bump(os.path.join(root, "crlf.py"), "patch")), j(open(os.path.join(root, "crlf.py"), "rb").read().decode()))) out("== snapshots and pruning") first, digest = tai.snapshot_self(script, folder, "9.9.9") out("snapshot %s %s" % (j(os.path.basename(first)), digest)) out("has digest %s %s" % (tai.backup_has_digest(folder, digest), tai.backup_has_digest(folder, "deadbeef"))) out("has digest nofolder %s" % tai.backup_has_digest(os.path.join(root, "nofolder"), digest)) for index in range(14): name = os.path.join(folder, "tai-0.0.%d-20200101T000000Z-%08d.py" % (index, index)) write(name, "x") os.utime(name, (1000 + index, 1000 + index)) write(os.path.join(folder, "notes.txt"), "keep") out("pruned %d" % tai.prune_backups(folder)) out("left %s" % j(sorted(os.listdir(folder))).replace(os.path.basename(first), "")) out("prune missing %d" % tai.prune_backups(os.path.join(root, "nofolder"))) out("== ensure_self_backup") shutil.rmtree(folder) home = tai_home() first = tai.ensure_self_backup(config, store, script) out("ensure first %s" % j(os.path.basename(first))) out("ensure second %s" % j(tai.ensure_self_backup(config, store, script))) rows = store.db.execute("SELECT actor, action, path, message, old_size, new_size, tags FROM audit ORDER BY id").fetchall() out("audit %s" % j([list(r) for r in rows])) out("== do_release") try: tai.do_release(store, script, folder, "patch", " ") except Exception as exc: out("blank message %s" % j(str(exc))) res = tai.do_release(store, script, folder, "minor", " ship it ", "tester") out("do_release %s" % j([res[0], res[1], os.path.basename(res[2]), res[3]])) out("== release tool") app = SkillApp(home, root) app.store = store app.profile = "t" tools = tai.Tools(app) for args in ({"part": "", "message": "m"}, {"part": "patch", "message": ""}, {"part": "huge", "message": "m"}, {"part": "Patch", "message": "tool release"}, {"part": "major", "message": "m" * 300}): out("release %s => %s" % (j(args), j(tools.dispatch("release", json.dumps(args)).replace(root, "")))) app.approve = False out("release denied => %s" % j(tools.dispatch("release", json.dumps({"part": "patch", "message": "no"})))) app.approve = True write(script, "nothing here\n") out("release no version => %s" % j(tools.dispatch("release", json.dumps({"part": "patch", "message": "m"})))) out("approvals %s" % j(app.approvals)) out("== capped helpers") out("capped %s" % j([tai.capped_text(None), tai.capped_text("abc"), tai.capped_text("é" * 20001)[1], tai.capped_text("x" * 20001)[0][-60:], tai.trunc_marker(5)])) big = os.path.join(root, "big.txt") write(big, "line\r\nsecond\rthird\n" + "é" * 30000) for cap in (20000, 50, 100000): r = tai.read_capped(big, cap) out("read_capped %d => %s %s" % (cap, j(r[0][:40] if r[0] else r[0]), j(r[1]))) write(os.path.join(root, "bad.bin"), "") with open(os.path.join(root, "bad.bin"), "wb") as handle: handle.write(b"ok \xff\xfe bad \xc3 end") out("read_capped invalid %s" % j(tai.read_capped(os.path.join(root, "bad.bin")))) out("read_capped missing %s" % j(tai.read_capped(os.path.join(root, "missing")))) store.close() def prep_audit(root): config, seal, store = open_store() store.audit_event("main", "write", os.path.join("area", "a.txt"), "first write", None, "hello\n", ["file", "Doc"], None, None, "t") store.audit_event("main", "edit", os.path.join("area", "a.txt"), "edit it", "hello\n", "hello world\n", ["file"], None, None, "t") store.audit_event("main", "delete", os.path.join("area", "a.txt"), "", "hello world\n", None, [], None, None, "t") store.audit_event("main", "write", os.path.join("area", "big.txt"), "big", None, "B" * 25000, ["file"], None, None, "t") store.audit_event("main", "write", os.path.join("area", "sized.txt"), "oversize", None, "small", [], None, 99999, "t") store.audit_event("main", "snapshot", "/x/tai.py", "backed up", None, None, ["snapshot"], None, None, "t") store.audit_event("main", "release", "/x/tai.py", "released", "1.0.0", "1.0.1", ["release", "v1.0.1"], None, None, "t") store.audit_event("main", "write", "sandbox:/box/f.txt", "in box", None, "boxed", [], None, None, "t") store.audit_event("other", "write", "/o/f.txt", "other profile", None, "o", [], None, None, "other") store.audit_event("main", "write", os.path.join("area", "sub", "deep", "r.txt"), "restore deep", None, "deep content", ["file"], None, None, "t") store.audit_event("main", "write", os.path.join("area", "u.txt"), "unicode é alpha", None, "café \U0001f600", ["file"], None, None, "t") store.audit_event("main", "noop", "/n", "no content", None, None, [], None, None, "t") store.tag_item("mem:t1", ["alpha", "beta"], "t") store.tag_item("mem:t2", ["alpha"], "t") store.tag_item("mem:t3", ["a_b", "a%c", "alphabet"], "t") store.close() class AuditApp(SkillApp): def __init__(self, home, root, store): SkillApp.__init__(self, home, root) self.store = store self.profile = "t" self.env = "home" def sc_audit(root): config, seal, store = open_store() app = AuditApp(tai_home(), root, store) tools = tai.Tools(app) def call(name, args): res = tools.dispatch(name, json.dumps(args)) out("%s %s => %s" % (name, j(args), j(res.replace(root, "")))) out("== audit") for args in ({}, {"limit": 3}, {"path": os.path.join("area", "a.txt")}, {"tag": "file"}, {"tag": "nomatch"}, {"query": "alpha"}, {"query": "write"}, {"query": "zzzz"}, {"limit": "x"}, {"limit": 500}, {"query": "unicode"}): call("audit", args) out("== tags") for args in ({}, {"prefix": "al"}, {"prefix": "A_"}, {"prefix": "a%"}, {"prefix": "zzz"}, {"limit": 1}, {"limit": "x"}, {"prefix": " Al "}): call("tags", args) out("== restore") for args in ({}, {"id": "x"}, {"id": 9999}, {"id": 6}, {"id": 7}, {"id": 1}, {"id": 3}, {"id": 4}, {"id": 5}, {"id": 12}, {"id": 10}, {"id": 11}): call("restore", args) for rel in ("a.txt", "sub/deep/r.txt", "u.txt"): path = os.path.join("area", rel) out("file %s %s" % (rel, j(open(path, encoding="utf-8").read() if os.path.exists(path) else None))) app.approve = False call("restore", {"id": 2}) app.approve = True out("approvals %s" % j([a.replace(root, "") for a in app.approvals])) store.close() SCENARIOS = { "release": sc_release, "audit": sc_audit, "telegram": sc_telegram, "telegram_install": sc_telegram_install, "rag": sc_rag, "sched": sc_sched, "install_hooks": sc_install_hooks, "install_hooks_noshell": sc_install_hooks, "install_ops": sc_install_ops, "install_noengine": sc_install_noengine, "vault_line": sc_vault_line, "json": sc_json, "datetime": sc_datetime, "chunk": sc_chunk, "fts": sc_fts, "skills_data": sc_skills_data, "skills_files": sc_skills_files, "skills_ops": sc_skills_ops, } PREPARE = {"sched": prep_sched, "rag": prep_rag, "release": prep_release, "audit": prep_audit} def main(): name, root = sys.argv[1], sys.argv[2] prepare = len(sys.argv) > 3 and sys.argv[3] == "prepare" os.chdir(os.path.join(root, "proj")) if prepare: fn = PREPARE.get(name) if fn: fn(root) return 0 SCENARIOS[name](root) return 0 if __name__ == "__main__": sys.exit(main())