diff --git a/README.md b/README.md index 7848fd3..2383d04 100644 --- a/README.md +++ b/README.md @@ -59,24 +59,26 @@ The full `secrets.json` stays on the host. `agent-secrets.json` goes into the co ccc-server --secrets secrets.json ``` -Environment variables: +Server environment variables: | Variable | Default | Description | |----------|---------|-------------| | `CONDUIT_PORT` | `3015` | Port to listen on | +| `CONDUIT_BIND` | `127.0.0.1` | Address to bind to | | `CONDUIT_ROOT` | `/workspace` | Workspace root for path resolution | ### Client (container / agent) ```bash -ccc-client --secrets agent-secrets.json --user agent '{"action": "list-actions"}' +ccc-client --secrets agent-secrets.json --user agent --url http://192.168.2.99:3015 '{"action": "list-actions"}' ccc-client --secrets agent-secrets.json --user agent '{"action": "edit-file", "filename": "/workspace/foo.mjs"}' ``` -`--secrets` and `--user` can also be set via environment variables: +`--secrets`, `--user`, and `--url` can also be set via environment variables: ```bash export CCC_SECRETS=/path/to/agent-secrets.json export CCC_USER=agent +export CONDUIT_URL=http://192.168.2.99:3015 ccc-client '{"action": "list-actions"}' ``` @@ -89,7 +91,7 @@ ccc-client '{"action": "edit-file",' '"filename": "/workspace/foo.mjs"}' ### Queue manager (host) ```bash -ccc-queue --secrets secrets.json --user user +ccc-queue --secrets secrets.json --user user --url http://192.168.2.99:3015 ``` Opens an interactive TUI showing pending actions: @@ -108,7 +110,12 @@ Opens an interactive TUI showing pending actions: [y] approve [n] deny [r] refresh [q] quit ``` -Supports `CCC_SECRETS` and `CCC_USER` env vars the same as the client. +Client environment variables: +| Variable | Default | Description | +|----------|---------|-------------| +| `CCC_SECRETS` | — | Path to secrets file | +| `CCC_USER` | — | Username to authenticate as | +| `CONDUIT_URL` | `http://localhost:3015` | Server URL | --- diff --git a/bin/ccc-queue.mjs b/bin/ccc-queue.mjs index 22cc290..d3a39cb 100755 --- a/bin/ccc-queue.mjs +++ b/bin/ccc-queue.mjs @@ -5,8 +5,8 @@ import { create_conduit_client } from '../client/conduit.mjs'; const POLL_INTERVAL = 2000; -const { username, secret } = load_client_config(process.argv); -const client = create_conduit_client(username, secret); +const { username, secret, url } = load_client_config(process.argv); +const client = create_conduit_client(username, secret, url); const screen = blessed.screen({ smartCSR: true, diff --git a/client/conduit.mjs b/client/conduit.mjs index 63e0954..3d7078a 100644 --- a/client/conduit.mjs +++ b/client/conduit.mjs @@ -3,16 +3,16 @@ import { sign_request } from "./auth.mjs"; -const BASE_URL = process.env.CONDUIT_URL || "http://localhost:3015"; +const DEFAULT_URL = 'http://localhost:3015'; -export function create_conduit_client(username, secret) { +export function create_conduit_client(username, secret, base_url = process.env.CONDUIT_URL || DEFAULT_URL) { function auth_headers(body_string) { return sign_request(secret, username, body_string); } async function call_action(action, params = {}) { const body_string = JSON.stringify({ action, ...params }); - const res = await fetch(`${BASE_URL}/action`, { + const res = await fetch(`${base_url}/action`, { method: "POST", headers: { "Content-Type": "application/json", ...auth_headers(body_string) }, body: body_string, @@ -25,14 +25,14 @@ export function create_conduit_client(username, secret) { } async function get_queue() { - const res = await fetch(`${BASE_URL}/queue`, { + const res = await fetch(`${base_url}/queue`, { headers: auth_headers(''), }); return res.json(); } async function resolve_queue_item(id, decision) { - const res = await fetch(`${BASE_URL}/queue/${id}/${decision}`, { + const res = await fetch(`${base_url}/queue/${id}/${decision}`, { method: 'POST', headers: auth_headers(''), }); diff --git a/client/config.mjs b/client/config.mjs index c7e87bf..f9460d0 100644 --- a/client/config.mjs +++ b/client/config.mjs @@ -1,12 +1,15 @@ // Resolve client config from CLI args or environment variables. -// Precedence: CLI args > env vars > error +// Precedence: CLI args > env vars > defaults // // Env vars: -// CCC_SECRETS path to secrets file -// CCC_USER username to authenticate as +// CCC_SECRETS path to secrets file +// CCC_USER username to authenticate as +// CONDUIT_URL server URL import { readFileSync } from 'fs'; +const DEFAULT_URL = 'http://localhost:3015'; + function get_arg(argv, flag) { const i = argv.indexOf(flag); return i !== -1 ? argv[i + 1] : null; @@ -15,6 +18,7 @@ function get_arg(argv, flag) { export function load_client_config(argv) { const secrets_path = get_arg(argv, '--secrets') || process.env.CCC_SECRETS; const username = get_arg(argv, '--user') || process.env.CCC_USER; + const url = get_arg(argv, '--url') || process.env.CONDUIT_URL || DEFAULT_URL; if (!secrets_path) { console.error('Secrets file required: --secrets or CCC_SECRETS='); @@ -39,14 +43,14 @@ export function load_client_config(argv) { process.exit(1); } - return { username, secret: user_entry.secret }; + return { username, secret: user_entry.secret, url }; } export function get_remaining(argv) { const result = []; let i = 2; while (i < argv.length) { - if (argv[i] === '--secrets' || argv[i] === '--user') { + if (argv[i] === '--secrets' || argv[i] === '--user' || argv[i] === '--url') { i += 2; } else { result.push(argv[i]); diff --git a/client/index.mjs b/client/index.mjs index 8a6b64b..629ce1b 100644 --- a/client/index.mjs +++ b/client/index.mjs @@ -7,11 +7,9 @@ import { sign_request } from './auth.mjs'; import { load_client_config, get_remaining } from './config.mjs'; -const BASE_URL = process.env.CONDUIT_URL || 'http://localhost:3015'; - -async function call_action(payload, username, secret) { +async function call_action(payload, username, secret, url) { const body_string = JSON.stringify(payload); - const res = await fetch(`${BASE_URL}/action`, { + const res = await fetch(`${url}/action`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...sign_request(secret, username, body_string) }, body: body_string, @@ -21,7 +19,7 @@ async function call_action(payload, username, secret) { } async function main() { - const { username, secret } = load_client_config(process.argv); + const { username, secret, url } = load_client_config(process.argv); const remaining = get_remaining(process.argv); if (!remaining.length) { @@ -37,7 +35,7 @@ async function main() { process.exit(1); } - const { status, body } = await call_action(payload, username, secret); + const { status, body } = await call_action(payload, username, secret, url); console.log(JSON.stringify(body, null, 2)); process.exit(status >= 400 ? 1 : 0); }