Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ for the complete activation description and instructions.
<!-- skills:start -->
| Skill | Summary |
|-------|---------|
| [antigravity-cli](skills/antigravity-cli/SKILL.md) | Delegate work to Antigravity CLI, inspect progress and tool failures, and continue the same conversation across follow-up tasks. |
| [codex-cli](skills/codex-cli/SKILL.md) | Reach for the Codex CLI when a task is hard enough to earn it: second-model review, bounded hand-offs, sandbox permissions, and a model and effort matched to the difficulty. |
| [grok-cli](skills/grok-cli/SKILL.md) | Delegate work to Grok Build, keep its session for follow-ups, and inspect results while the supervising agent continues working. |
| [marketing-copy](skills/marketing-copy/SKILL.md) | Write outbound promo copy that stays truthful, discloses only what may be public, and earns attention without hype. |
Expand Down Expand Up @@ -97,6 +98,11 @@ The archive is written to `dist/<skill>.zip`. Its root contains `SKILL.md`
and the skill's supporting files, ready to upload as one file. Root-level
`evals/` and local build artifacts are excluded.

The CLI skills bundle their shared task runtime so each skill can be installed
independently. After editing `scripts/agent_task_runtime.py`, run
`python scripts/sync_agent_runtime.py` to update the bundled copies. The test
suite checks that those copies match the maintained source.

## Feedback and contributions

Report problems or suggest improvements through
Expand Down
287 changes: 287 additions & 0 deletions scripts/agent_task_runtime.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
"""Shared task storage, worker launch, and Windows process ownership for CLI skills.

Run scripts/sync_agent_runtime.py after editing this canonical source.
"""

from __future__ import annotations

import argparse
import ctypes
import json
import math
import os
import sqlite3
import subprocess
import sys
import threading
import time
import uuid
from ctypes import wintypes
from pathlib import Path
from typing import Any

HEARTBEAT_TIMEOUT = 15


class TaskError(RuntimeError):
pass


def encode(value: Any) -> str:
# ASCII escapes keep redirected JSON usable on non-UTF-8 Windows terminals.
return json.dumps(value, ensure_ascii=True, allow_nan=False)


class Store:
def __init__(self, root: Path):
self.root = root.expanduser().resolve()
self.root.mkdir(parents=True, exist_ok=True, mode=0o700)
self.db = sqlite3.connect(self.root / "tasks.sqlite3", timeout=10)
self.db.execute("PRAGMA journal_mode=WAL")
self.db.executescript("""
CREATE TABLE IF NOT EXISTS tasks (
id TEXT PRIMARY KEY, config TEXT NOT NULL, state TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS commands (
id INTEGER PRIMARY KEY AUTOINCREMENT, task_id TEXT NOT NULL,
payload TEXT NOT NULL, result TEXT
);
""")

def close(self) -> None:
self.db.close()

def create(self, config: dict[str, Any]) -> dict[str, Any]:
task_id = uuid.uuid4().hex
directory = self.root / task_id
directory.mkdir(mode=0o700)
state = {
"task_id": task_id,
"session_id": None,
"status": "starting",
"closed": False,
"turn": 0,
"text": "",
"pending_permissions": [],
"tools": [],
"cwd": config["cwd"],
"updated_at": time.time(),
"log_dir": str(directory),
}
with self.db:
self.db.execute(
"INSERT INTO tasks VALUES (?, ?, ?)",
(task_id, encode(config), encode(state)),
)
return state

def get(self, task_id: str) -> tuple[dict[str, Any], dict[str, Any]]:
if len(task_id) != 32 or any(c not in "0123456789abcdef" for c in task_id):
raise TaskError("Invalid task ID; use the task_id returned by start")
row = self.db.execute(
"SELECT config, state FROM tasks WHERE id=?", (task_id,)
).fetchone()
if row is None:
raise TaskError("Unknown task ID; use the same --state-dir as start")
return json.loads(row[0]), json.loads(row[1])

def save(self, state: dict[str, Any]) -> None:
state["updated_at"] = time.time()
with self.db:
self.db.execute(
"UPDATE tasks SET state=? WHERE id=?", (encode(state), state["task_id"])
)

def status(self, task_id: str) -> dict[str, Any]:
_, state = self.get(task_id)
if (
not state["closed"]
and time.time() - state["updated_at"] > HEARTBEAT_TIMEOUT
):
state = {
**state,
"status": "unresponsive",
"error": "Worker heartbeat expired; inspect worker.log before starting another task",
}
return state

def submit(self, task_id: str, payload: dict[str, Any]) -> dict[str, Any]:
state = self.status(task_id)
if state["closed"] or state["status"] == "unresponsive":
raise TaskError(
"Task is closed or unresponsive; its recorded result remains available via status"
)
with self.db:
cursor = self.db.execute(
"INSERT INTO commands(task_id,payload) VALUES (?,?)",
(task_id, encode(payload)),
)
command_id = cursor.lastrowid
deadline = time.monotonic() + 5
while time.monotonic() < deadline:
row = self.db.execute(
"SELECT result FROM commands WHERE id=?", (command_id,)
).fetchone()
if row[0] is not None:
result = json.loads(row[0])
if "command_error" in result:
raise TaskError(result["command_error"])
return {"command_id": command_id, **result}
time.sleep(0.05)
return {
"task_id": task_id,
"command_id": command_id,
"command_status": "queued",
"note": "Command not yet acknowledged; check status before retrying",
}

def commands(self, task_id: str) -> list[tuple[int, str]]:
return self.db.execute(
"SELECT id,payload FROM commands WHERE task_id=? AND result IS NULL ORDER BY id",
(task_id,),
).fetchall()

def acknowledge(self, command_id: int, result: dict[str, Any]) -> None:
with self.db:
self.db.execute(
"UPDATE commands SET result=? WHERE id=?", (encode(result), command_id)
)


def launch_worker(store: Store, config: dict[str, Any], script: Path) -> dict[str, Any]:
state = store.create(config)
command = [
sys.executable,
str(script.resolve()),
"--state-dir",
str(store.root),
"--worker",
state["task_id"],
]
options: dict[str, Any] = {}
if os.name == "nt":
options["creationflags"] = (
subprocess.CREATE_NO_WINDOW | subprocess.CREATE_NEW_PROCESS_GROUP
)
else:
options["start_new_session"] = True
try:
with (store.root / state["task_id"] / "worker.log").open("ab") as log:
process = subprocess.Popen(
command,
stdin=subprocess.DEVNULL,
stdout=log,
stderr=log,
cwd=store.root,
close_fds=True,
**options,
)
# Retain no inherited pipes: a caller can exit while the worker lives.
threading.Thread(target=process.wait, daemon=True).start()
return {**state, "worker_pid": process.pid}
except OSError as exc:
state.update(status="failed", closed=True, error=str(exc))
store.save(state)
raise


def read_prompt(args: argparse.Namespace) -> str:
if args.prompt_file is not None:
text = args.prompt_file.read_text(encoding="utf-8-sig")
elif args.prompt is not None:
text = args.prompt
else:
text = sys.stdin.buffer.read().decode("utf-8-sig")
if not text.strip():
raise TaskError(
"Prompt is empty; provide --prompt, --prompt-file, or UTF-8 stdin"
)
return text


def seconds(value: str) -> float:
number = float(value)
if not math.isfinite(number) or number <= 0:
raise argparse.ArgumentTypeError(
"timeout must be a finite number greater than zero"
)
return number


class BasicLimits(ctypes.Structure):
_fields_ = [
("process_time", ctypes.c_int64),
("job_time", ctypes.c_int64),
("flags", wintypes.DWORD),
("min_working_set", ctypes.c_size_t),
("max_working_set", ctypes.c_size_t),
("active_processes", wintypes.DWORD),
("affinity", ctypes.c_size_t),
("priority", wintypes.DWORD),
("scheduling", wintypes.DWORD),
]


class ExtendedLimits(ctypes.Structure):
_fields_ = [
("basic", BasicLimits),
("io_counters", ctypes.c_uint64 * 6),
("process_memory", ctypes.c_size_t),
("job_memory", ctypes.c_size_t),
("peak_process_memory", ctypes.c_size_t),
("peak_job_memory", ctypes.c_size_t),
]


class WindowsJob:
def __init__(self, pid: int):
self.kernel = ctypes.WinDLL("kernel32", use_last_error=True)
signatures = {
"CreateJobObjectW": ([ctypes.c_void_p, wintypes.LPCWSTR], wintypes.HANDLE),
"SetInformationJobObject": (
[wintypes.HANDLE, ctypes.c_int, ctypes.c_void_p, wintypes.DWORD],
wintypes.BOOL,
),
"OpenProcess": (
[wintypes.DWORD, wintypes.BOOL, wintypes.DWORD],
wintypes.HANDLE,
),
"AssignProcessToJobObject": (
[wintypes.HANDLE, wintypes.HANDLE],
wintypes.BOOL,
),
"CloseHandle": ([wintypes.HANDLE], wintypes.BOOL),
}
for name, (args, result) in signatures.items():
function = getattr(self.kernel, name)
function.argtypes = args
function.restype = result
self.handle = self.kernel.CreateJobObjectW(None, None)
if not self.handle:
raise ctypes.WinError(ctypes.get_last_error())
try:
limits = ExtendedLimits()
limits.basic.flags = 0x2000 # JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
if not self.kernel.SetInformationJobObject(
self.handle, 9, ctypes.byref(limits), ctypes.sizeof(limits)
):
raise ctypes.WinError(ctypes.get_last_error())
process = self.kernel.OpenProcess(
0x0101, False, pid
) # SET_QUOTA | TERMINATE
if not process:
raise ctypes.WinError(ctypes.get_last_error())
try:
if not self.kernel.AssignProcessToJobObject(self.handle, process):
raise ctypes.WinError(ctypes.get_last_error())
finally:
self.kernel.CloseHandle(process)
except BaseException:
self.close()
raise

def close(self):
if self.handle:
if not self.kernel.CloseHandle(self.handle):
raise ctypes.WinError(ctypes.get_last_error())
self.handle = None
41 changes: 41 additions & 0 deletions scripts/sync_agent_runtime.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env python3
"""Bundle the shared runtime into each independently installable CLI skill."""

import argparse
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
SKILLS = ("grok-cli", "antigravity-cli")
HEADER = "# Generated by scripts/sync_agent_runtime.py; edit scripts/agent_task_runtime.py.\n"


def sync(root: Path, check: bool = False) -> list[str]:
expected = HEADER + (root / "scripts/agent_task_runtime.py").read_text(
encoding="utf-8"
)
stale = []
for name in SKILLS:
target = root / "skills" / name / "scripts/agent_task_runtime.py"
if not target.exists() or target.read_text(encoding="utf-8") != expected:
stale.append(name)
if not check:
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text(expected, encoding="utf-8", newline="\n")
return stale


def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--check", action="store_true")
args = parser.parse_args()
stale = sync(ROOT, args.check)
if stale:
print(
("Stale runtime copies: " if args.check else "Updated runtime copies: ")
+ ", ".join(stale)
)
return int(args.check and bool(stale))


if __name__ == "__main__":
raise SystemExit(main())
Loading