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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ That's it. Every response is verified before you see it — check the
on the body). Streaming works too; it's verified before the first token replays.

Useful commands: `og-veil test` (send a one-off prompt to check the path),
`og-veil stop`, `og-veil status`, `og-veil endpoint` (re-prints the env vars),
`og-veil update`, `og-veil logout`.
`og-veil stop`, `og-veil status`, `og-veil env` (re-prints the env vars),
`og-veil models` (list available models), `og-veil update`, `og-veil logout`.

### Use it with Hermes Agent

Expand Down
16 changes: 13 additions & 3 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""CLI wiring: first-run login, session reuse, background-by-default, endpoint, update."""
"""CLI wiring: first-run login, session reuse, background-by-default, env, models, update."""

from __future__ import annotations

Expand Down Expand Up @@ -58,13 +58,23 @@ def test_setup_with_yes_starts_background():
assert result.exit_code == 0


def test_endpoint_prints_env_vars():
def test_env_prints_env_vars():
with mock.patch("veil.daemon.running_pid", return_value=4321):
result = CliRunner().invoke(cli.main, ["endpoint"])
result = CliRunner().invoke(cli.main, ["env"])
assert "OPENAI_BASE_URL=http://127.0.0.1:11434/v1" in result.output
assert result.exit_code == 0


def test_models_lists_known_models():
result = CliRunner().invoke(cli.main, ["models"])
assert result.exit_code == 0
# Should print at least one model name derived from the SDK's TEE_LLM enum.
from opengradient import TEE_LLM

sample = next(iter(TEE_LLM)).value.split("/", 1)[1]
assert sample in result.output


def test_test_command_posts_prompt_to_localhost_and_prints_reply():
resp = mock.MagicMock(
status_code=200,
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion veil/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""OpenGradient Local — self-verifying private-inference proxy for AI agents.
"""OpenGradient Veil — self-verifying private-inference proxy for AI agents.

Point any OpenAI-compatible SDK at this process (one env var) and prompts are
routed through OpenGradient's decentralized network of attestable AWS Nitro TEE
Expand Down
35 changes: 26 additions & 9 deletions veil/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

The common path is a single command: run ``og-veil`` and it logs you in on first
use, then starts the local server in the background. Individual steps (``serve``,
``login``, ``stop``, ``status``, ``endpoint``, ``test``, ``update``, ``logout``)
are available on their own too.
``login``, ``stop``, ``status``, ``env``, ``models``, ``test``, ``update``,
``logout``) are available on their own too.
"""

from __future__ import annotations
Expand All @@ -21,7 +21,7 @@
@click.option("-v", "--verbose", is_flag=True, help="Enable debug logging.")
@click.pass_context
def main(ctx: click.Context, verbose: bool) -> None:
"""OpenGradient Local — drop-in, self-verifying private inference for AI agents.
"""OpenGradient Veil — drop-in, self-verifying private inference for AI agents.

Run with no command to do everything: set up on first run, then start the server.
"""
Expand Down Expand Up @@ -157,11 +157,11 @@ def _start_server(config: ServerConfig, *, foreground: bool) -> None:
# Already running — surface that clearly rather than erroring out.
existing = running_pid()
if existing:
click.secho(f"OpenGradient Local is already running (pid {existing}).", fg="yellow")
click.secho(f"OpenGradient Veil is already running (pid {existing}).", fg="yellow")
click.echo(" Stop it with: og-veil stop")
return
raise click.ClickException(str(exc))
click.secho(f"✓ OpenGradient Local running in the background (pid {pid}).", fg="green")
click.secho(f"✓ OpenGradient Veil running in the background (pid {pid}).", fg="green")
click.echo(f" Base URL : {config.advertised_base_url()}")
click.echo(f" Logs : {log_path()}")
click.echo(" Stop : og-veil stop")
Expand All @@ -179,19 +179,36 @@ def stop() -> None:
click.secho(f"✓ Stopped background server (pid {pid}).", fg="green")


@main.command()
def endpoint() -> None:
"""Print the env vars to point your agent at OpenGradient Local."""
@main.command(name="env")
def env_cmd() -> None:
"""Print the env vars to point your agent at OpenGradient Veil."""
from veil.daemon import running_pid

config = ServerConfig.from_env()
click.echo("Point your agent at OpenGradient Local (one env var change):")
click.echo("Point your agent at OpenGradient Veil (one env var change):")
click.secho(f" export OPENAI_BASE_URL={config.advertised_base_url()}", bold=True)
click.echo(" export OPENAI_API_KEY=og-veil # ignored; your Chat session authenticates")
if running_pid() is None:
click.echo("\nThe server isn't running yet — start it with `og-veil`.")


@main.command()
def models() -> None:
"""List the models available through OpenGradient Veil.

Derived from the SDK's canonical ``TEE_LLM`` enum — the same source the
local server uses for ``GET /v1/models`` — so it stays in sync with the
network as models are added or retired.
"""
from opengradient import TEE_LLM

# Each enum value is ``provider/model``; agents send the bare model name.
names = sorted(m.value.split("/", 1)[1] for m in TEE_LLM)
click.echo("Models available through OpenGradient Veil:")
for name in names:
click.echo(f" {name}")


@main.command(name="login")
@click.option("--app-url", default=DEFAULT_APP_URL, show_default=True, help="Chat app web origin.")
@click.option("--no-browser", is_flag=True, help="Don't open a browser; print the URL instead.")
Expand Down
2 changes: 1 addition & 1 deletion veil/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def serve(config: ServerConfig) -> None:
app = create_app(gateway)
tee = gateway.active_tee
print(
f"OpenGradient Local listening on http://{config.host}:{config.port}\n"
f"OpenGradient Veil listening on http://{config.host}:{config.port}\n"
f" Verified TEE: {tee.tee_id if tee else '?'} ({tee.endpoint if tee else '?'})\n"
f" Signed in as: {session.user_email or 'unknown'}\n\n"
f"Point your agent at it (OpenAI SDK):\n"
Expand Down
Loading