diff --git a/9p b/9p index 9b747e0..8b233c2 160000 --- a/9p +++ b/9p @@ -1 +1 @@ -Subproject commit 9b747e011b72f1bf203f5b35066b19531bb916f0 +Subproject commit 8b233c295eb22614fc2641fdb7ce307ae3ce0dbd diff --git a/core b/core index fc1d1c6..e09a6c1 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit fc1d1c6f834a89f9d1838dc623ae66450d229280 +Subproject commit e09a6c12507bc285ea46ae8cc10f567774339d24 diff --git a/doc/OBSERVATIONS.md b/doc/OBSERVATIONS.md index e481a56..d0fc81d 100644 --- a/doc/OBSERVATIONS.md +++ b/doc/OBSERVATIONS.md @@ -20,6 +20,8 @@ **Sub-agents** — `subagent_spawn` implements fork-join over the `b/` namespace: spawn N specialized agents with a shared prompt, wait for all to complete, collect results in submission order. For heterogeneous parallel delegation (N agents, N different prompts), use a `{parallel: [...]}` stage in `execute_code` — each parallel step calls `subagent_spawn` with a different prompt, all running concurrently. +**Environment injection is a front-end concern** — Because the daemon is a long-running process separate from the front-end, any environment variable the session needs (e.g. `SUPERPOWERD_SESSION_TOKEN`) must be injected by the front-end via `s/{id}/env`. This is not a serious limitation, but it makes front-end setup slightly more involved: tools like `superpowers` require the front-end itself to be launched inside the privileged context (`superpowers run-session ollie-tui ...`), rather than simply having the variable present in the daemon's environment. + **AI pipelines with standard tools** — ollie scripts compose into multi-stage AI pipelines via Unix pipes. Proof-of-concept: ``` diff --git a/scripts/s/sh b/scripts/s/sh index 969ade6..000779b 100755 --- a/scripts/s/sh +++ b/scripts/s/sh @@ -43,7 +43,6 @@ Flags: -backend BACKEND backend override (e.g. ollama, anthropic) -model MODEL model override -agent AGENT agent config name - -e VAR1,VAR2 inject env vars from this shell into the session -help show this help Input at the prompt: @@ -70,7 +69,7 @@ EOF # Parse flags new=0; resume=0; id_flag=; name= -backend=; model=; agent=; cwd=; env= +backend=; model=; agent=; cwd= while [ $# -gt 0 ]; do case $1 in -new) new=1 ;; @@ -81,7 +80,6 @@ while [ $# -gt 0 ]; do -model) model=$2; shift ;; -agent) agent=$2; shift ;; -cwd) cwd=$2; shift ;; - -e) env=$2; shift ;; -help) usage ;; *) die "unknown flag: $1" ;; esac @@ -96,13 +94,6 @@ write_new() { [ -n "$backend" ] && printf 'backend=%s\n' "$backend" [ -n "$model" ] && printf 'model=%s\n' "$model" [ -n "$agent" ] && printf 'agent=%s\n' "$agent" - if [ -n "$env" ]; then - IFS=, read -ra _vars <<< "$env" - for _v in "${_vars[@]}"; do - eval "_val=\$$_v" - [ -n "$_val" ] && printf 'env.%s=%s\n' "$_v" "$_val" - done - fi true } > "$MOUNT/s/new" || die "write s/new" } @@ -154,14 +145,6 @@ fi S=$MOUNT/s/$id chat_off=$(wc -c < "$S/chat" 2>/dev/null || echo 0) -if [ -n "$env" ]; then - IFS=, read -ra _vars <<< "$env" - for _v in "${_vars[@]}"; do - eval "_val=\$$_v" - [ -n "$_val" ] && printf '%s=%s\n' "$_v" "$_val" - done > "$S/env" 2>/dev/null || true -fi - trap ' [ "$(tr -d "[:space:]" < "$S/state" 2>/dev/null)" = "idle" ] && exit printf "\n" >&2; printf "stop\n" > "$S/ctl" diff --git a/tools/elevate_superpowers b/tools/elevate_superpowers new file mode 100755 index 0000000..895b7c0 --- /dev/null +++ b/tools/elevate_superpowers @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +"""Run a command elevated via superpowerd IPC (buffered output). + +Usage: elevate_superpowers + +Requires SUPERPOWERD_SESSION_TOKEN in environment (set by superpowers run-session). +Exits with the elevated command's exit code. +""" +import json +import os +import socket +import sys + + +def _socket_path(): + if p := os.environ.get("SUPERPOWERD_SOCKET"): + return p + if d := os.environ.get("SUPERPOWERD_SOCKET_DIR"): + return d + "/superpowerd.sock" + if x := os.environ.get("XDG_RUNTIME_DIR"): + return x + "/superpowerd/superpowerd.sock" + return f"/run/user/{os.getuid()}/superpowerd/superpowerd.sock" + + +def main(): + token = os.environ.get("SUPERPOWERD_SESSION_TOKEN") + if not token: + print("elevate_superpowers: SUPERPOWERD_SESSION_TOKEN not set", file=sys.stderr) + sys.exit(1) + + if len(sys.argv) < 2: + print("usage: elevate_superpowers ", file=sys.stderr) + sys.exit(1) + + cmd = sys.argv[1] + cwd = os.getcwd() + + sock_path = _socket_path() + sock = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET) + try: + sock.connect(sock_path) + except OSError as e: + print(f"elevate_superpowers: connect {sock_path}: {e}", file=sys.stderr) + sys.exit(1) + + req = json.dumps({ + "jsonrpc": "2.0", + "method": "ExecuteCommand", + "id": 1, + "params": { + "auth": {"session_token": token}, + "command": cmd, + "working_dir": cwd, + "approval_timeout": 7200, + }, + }).encode() + + with sock: + sock.sendall(req) + data = sock.recv(1024 * 1024) + + resp = json.loads(data) + rpc_err = resp.get("error") + if rpc_err: + msg = rpc_err.get("message", str(rpc_err)) if isinstance(rpc_err, dict) else str(rpc_err) + print(f"elevate_superpowers: {msg}", file=sys.stderr) + sys.exit(1) + + result = resp.get("result", {}) + out = result.get("stdout", "") + err = result.get("stderr", "") + if out: + sys.stdout.write(out) + if err: + sys.stderr.write(err) + sys.exit(result.get("exit_code", 0)) + + +if __name__ == "__main__": + main() diff --git a/tui b/tui index 23e2083..bad5ad4 160000 --- a/tui +++ b/tui @@ -1 +1 @@ -Subproject commit 23e2083ff978104263ad60210eb6cfe285cd5496 +Subproject commit bad5ad4fdad72463c8eb3a165ec94aced9082115