Metadata-Version: 2.4
Name: devpilot-agent
Version: 0.2.0
Summary: A lightweight agent runtime that turns any machine into an AI-agent-ready compute target
Author: Joe Robinson
License-Expression: Apache-2.0
Project-URL: Repository, https://github.com/joerob-msft/agent-runtime
Project-URL: Documentation, https://github.com/joerob-msft/agent-runtime#readme
Keywords: ai,agent,runtime,acp,copilot,remote-execution
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Build Tools
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: terminal
Requires-Dist: pywinpty>=2.0; extra == "terminal"
Requires-Dist: websockets>=14.0; extra == "terminal"
Dynamic: license-file

# agent-runtime

A lightweight agent runtime that turns any machine into an AI-agent-ready compute target. Zero dependencies. Self-updating. Works with any ACP-compatible coding agent.

## What is this?

**agent-runtime** is a sidecar you install on any machine (Dev Box, VM, cloud instance) to make it remotely controllable by AI coding agents. It provides:

- **Async command server** — `POST /exec` → job ID, `GET /jobs/{id}` → poll for results
- **WebSocket terminal** — interactive ConPTY sessions over WebSocket (xterm.js compatible)
- **ACP client** — structured Agent Client Protocol communication with any ACP agent
- **Self-updating** — `POST /update` triggers graceful upgrade via pip
- **Devtunnel integration** — persistent tunnels, token rotation, challenge-code registration
- **API key auth** — auto-generated keys, persisted across restarts

## Install

```bash
# Core (zero dependencies)
pip install devpilot-agent

# With interactive terminal support (Windows)
pip install devpilot-agent[terminal]
```

## Quick Start

```bash
# Start the server
agent-server

# Start on a custom port
agent-server --port 9090

# Start with devtunnel + auto-registration
agent-server --wrapper --tunnel --register https://your-dashboard.example.com

# Start with self-update wrapper
agent-server --wrapper
```

## API

### Command Execution

```bash
# Submit a command
curl -X POST http://localhost:8585/exec \
  -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"command": "echo hello", "workdir": "/path/to/repo", "timeout": 300}'
# → {"jobId": "abc123", "status": "pending"}

# Poll for results
curl http://localhost:8585/jobs/abc123 -H "X-API-Key: $KEY"
# → {"status": "completed", "exitCode": 0, "stdout": "hello\n", ...}

# Nudge a stalled process (writes to stdin)
curl -X POST http://localhost:8585/jobs/abc123/nudge -H "X-API-Key: $KEY"
```

### ACP Mode

Submit commands in ACP mode for structured output from any ACP-compatible agent:

```bash
curl -X POST http://localhost:8585/exec \
  -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "acp",
    "agent": "copilot --acp --stdio",
    "prompt": "Implement the login feature",
    "workdir": "/path/to/repo"
  }'
```

ACP responses include structured events, tool calls, and session IDs instead of raw stdout.

### Health Check

```bash
curl http://localhost:8585/health
# → {"status": "ok", "version": "0.1.0", "acp_supported": true, ...}
```

## ACP Client (Standalone)

The headless ACP client can be used independently for driving any ACP agent from Python:

```python
from agent_runtime.acp_client import run_acp_session_sync, HeadlessApprovePolicy

result = run_acp_session_sync(
    agent_cmd=["copilot", "--acp", "--stdio"],
    prompt="Refactor the auth module",
    workdir="/path/to/repo",
    timeout=600,
    permission_policy=HeadlessApprovePolicy("/path/to/repo"),
)

print(result.output_text)       # Agent's response
print(result.session_id)        # For session continuity
print(result.tool_calls)        # Structured tool call data
print(result.stop_reason)       # "end_turn", "timeout", "error"
```

## Architecture

```
┌─────────────────────────────────────────────────────┐
│  Your Orchestrator / Dashboard / CI                  │
│  (any HTTP client)                                   │
└────────┬─────────────────────┬──────────────────────┘
         │ HTTP                 │ WebSocket
         ▼                     ▼
┌─────────────────────────────────────────────────────┐
│  agent-runtime (on the target machine)               │
│                                                      │
│  ┌───────────────────┐  ┌─────────────────────────┐ │
│  │ Command Server     │  │ Terminal Server          │ │
│  │ :8585              │  │ :8586 (WebSocket)        │ │
│  │                    │  │                          │ │
│  │ POST /exec         │  │ ConPTY ↔ xterm.js       │ │
│  │ GET /jobs/{id}     │  │ JSON input/raw output    │ │
│  │ POST /nudge        │  │ Resize, idle timeout     │ │
│  │ POST /update       │  │ Max 2 sessions           │ │
│  └───────────────────┘  └─────────────────────────┘ │
│                                                      │
│  ┌─────────────────────────────────────────────────┐ │
│  │ ACP Client (headless)                            │ │
│  │ JSON-RPC over stdio → any ACP agent              │ │
│  │ Permission policies, session continuity          │ │
│  └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
```

## Key Design Decisions

- **Zero runtime dependencies** — stdlib-only Python. Terminal extras are opt-in.
- **Async job pattern** — fire-and-forget commands avoid tunnel timeout issues.
- **Self-updating** — exit code 42 triggers pip upgrade + restart via the wrapper loop.
- **Security** — auto-generated API keys, workdir-scoped permission policies, path traversal protection.

## Configuration

| Environment Variable | Default | Description |
|---------------------|---------|-------------|
| `DEVPILOT_AGENT_API_KEY` | auto-generated | API key for authenticating requests |
| `DEVPILOT_TUNNEL_URL` | — | Devtunnel URL (set automatically with `--tunnel`) |
| `DEVPILOT_TUNNEL_TOKEN` | — | Devtunnel access token |

## License

Apache 2.0 — see [LICENSE](LICENSE) for details.

## Releasing

Releases are automated via GitHub Actions. When a version tag is pushed,
CI runs tests → builds the wheel → publishes to PyPI using Trusted Publisher (OIDC).

```bash
# 1. Create a release branch
git checkout -b release/v0.2.0

# 2. Bump version in agent_runtime/__init__.py
#    __version__ = "0.2.0"

# 3. Commit and push
git add agent_runtime/__init__.py
git commit -m "Bump version to 0.2.0"
git push origin release/v0.2.0

# 4. Merge to main (via PR or direct push)
git checkout main
git merge release/v0.2.0
git push origin main

# 5. Tag and push — this triggers the PyPI publish
git tag v0.2.0
git push origin v0.2.0
```

The publish workflow: runs tests (Windows, Python 3.11-3.13) → builds sdist + wheel → publishes to PyPI.

**First-time setup** (one-time on pypi.org):
1. Go to `pypi.org/manage/project/devpilot-agent/settings/publishing/`
2. Add trusted publisher: owner=`joerob-msft`, repo=`agent-runtime`, workflow=`publish.yml`, environment=`pypi`
3. Create a `pypi` environment in GitHub repo settings (Settings → Environments → New)
