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 @@ -38,7 +38,7 @@ client = PromptClient(host="localhost:8443") # token=... if auth is o
prompt = client.get("priompt://acme/onboarding/welcome")

print(prompt.template) # Hi {name}, welcome to {org}!
text = prompt.template.format(name="Sujal", org="Acme")
text = prompt.template.format(name="Ada", org="Acme")
```

What comes back from `get()`:
Expand Down Expand Up @@ -67,7 +67,7 @@ PromptClient(host=None, token=None, tls=False, ca_cert=None,
| --- | --- |
| `host` | `address:port` of the server. Optional if `url` or `PRIOMPT_URL` is set |
| `url` | a full `priompt://<token>@host:port` string; defaults to `PRIOMPT_URL` |
| `token` | sent as `authorization: Bearer <token>`; explicit value wins over the url's token |
| `token` | sent as `authorization: Bearer <token>`; defaults to `PRIOMPT_TOKEN`, then the url's token |
| `tls` / `ca_cert` | use TLS, optionally pinning a CA certificate |
| `cache_ttl` | local cache lifetime in seconds (`0` = off) — repeat `get`s within the TTL never touch the network |
| `nats_url` | endpoint for `subscribe()` |
Expand Down
4 changes: 3 additions & 1 deletion buf.gen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ version: v2
inputs:
- directory: ../proto/proto
plugins:
- remote: buf.build/protocolbuffers/python
# Pinned: v35.x emits gencode for protobuf 7.35, matching the
# protobuf>=7.35 floor in pyproject.toml. A newer plugin raises that floor.
- remote: buf.build/protocolbuffers/python:v35.1
out: .
- remote: buf.build/grpc/python
out: .
7 changes: 5 additions & 2 deletions priompt_sdk/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@ def __init__(
url=None,
):
# One connection string covers local/self-host/cloud: pass url= or set
# PRIOMPT_URL (priompt://<token>@host:port). An explicit host= wins;
# an explicit token= overrides the URL's token.
# PRIOMPT_URL (priompt://<token>@host:port). An explicit host= wins.
# Token precedence: token=, then PRIOMPT_TOKEN, then the URL's token
# (the same order as the priompt CLI).
if token is None:
token = os.environ.get("PRIOMPT_TOKEN") or None
if host is None:
raw = url or os.environ.get("PRIOMPT_URL")
if raw:
Expand Down
4 changes: 2 additions & 2 deletions priompt_sdk/v1/prompt_pb2.py

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

26 changes: 26 additions & 0 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,29 @@ async def connect(url, error_cb=None, **kw):
with pytest.raises(ConnectionError, match="Authorization Violation") as exc:
c.subscribe("priompt://x", lambda *_: None)
assert "WRONG" not in str(exc.value) # the token is not echoed


# --- token resolution: token=, then PRIOMPT_TOKEN, then the URL's token ---

def _bearer(c):
return dict(c._md or [])["authorization"] if c._md else None


def test_reads_priompt_token_env(monkeypatch):
"""#5: the client must read PRIOMPT_TOKEN like the CLI does."""
monkeypatch.delenv("PRIOMPT_URL", raising=False)
monkeypatch.setenv("PRIOMPT_TOKEN", "envtok")
assert _bearer(PromptClient("localhost:1")) == "Bearer envtok"


def test_token_precedence(monkeypatch):
monkeypatch.setenv("PRIOMPT_TOKEN", "envtok")
# PRIOMPT_TOKEN beats the token inside the URL...
assert _bearer(PromptClient(url="priompt://urltok@localhost:1")) == "Bearer envtok"
# ...and an explicit token= beats both.
c = PromptClient(url="priompt://urltok@localhost:1", token="argtok")
assert _bearer(c) == "Bearer argtok"
# Without PRIOMPT_TOKEN, the URL's token is used.
monkeypatch.delenv("PRIOMPT_TOKEN")
assert _bearer(PromptClient(url="priompt://urltok@localhost:1")) == "Bearer urltok"
assert _bearer(PromptClient("localhost:1")) is None
Loading