diff --git a/example.py b/example.py deleted file mode 100644 index 4732859d..00000000 --- a/example.py +++ /dev/null @@ -1,37 +0,0 @@ -import os - -import openai - -client = openai.OpenAI( - api_key=os.environ["CASHU_TOKEN"], - base_url=os.environ.get("ROUTSTR_API_URL", "https://api.routstr.com/v1"), - # base_url="http://roustrjfsdgfiueghsklchg.onion/v1", - # client=httpx.AsyncClient( - # proxies={"http": "socks5://localhost:9050"}, - # ), # to use onion proxy (tor) -) -history: list = [] - - -def chat() -> None: - while True: - user_msg = {"role": "user", "content": input("\nYou: ")} - history.append(user_msg) - ai_msg = {"role": "assistant", "content": ""} - - for chunk in client.chat.completions.create( - model=os.environ.get("MODEL", "openai/gpt-4o-mini"), - messages=history, - stream=True, - ): - if len(chunk.choices) > 0: - content = chunk.choices[0].delta.content - if content is not None: - ai_msg["content"] += content - print(content, end="", flush=True) - print() - history.append(ai_msg) - - -if __name__ == "__main__": - chat() diff --git a/examples/balance/check_balance.py b/examples/balance/check_balance.py new file mode 100644 index 00000000..5a2a7c25 --- /dev/null +++ b/examples/balance/check_balance.py @@ -0,0 +1,11 @@ +import os + +import httpx + +# Use your Cashu token or API key as the Bearer token, +# cashu token is hashed on the server and acts as an Temporary API key +headers = {"Authorization": f"Bearer {os.environ.get('TOKEN')}"} +base_url = os.environ.get("API_URL", "https://api.routstr.com/v1") + +resp = httpx.get(f"{base_url}/balance/info", headers=headers) +print(resp.json()) diff --git a/examples/balance/create_balance.py b/examples/balance/create_balance.py new file mode 100644 index 00000000..14206696 --- /dev/null +++ b/examples/balance/create_balance.py @@ -0,0 +1,14 @@ +import os +import httpx + +# Send a Cashu token to the /create endpoint to get a persistent API key +token = os.environ.get("TOKEN") +if not token: + print("Please set TOKEN environment variable with a Cashu token") + exit(1) + +base_url = os.environ.get("API_URL", "https://api.routstr.com/v1") + +resp = httpx.get(f"{base_url}/balance/create", params={"initial_balance_token": token}) + +print(resp.json()) diff --git a/examples/balance/refund_balance.py b/examples/balance/refund_balance.py new file mode 100644 index 00000000..da785d45 --- /dev/null +++ b/examples/balance/refund_balance.py @@ -0,0 +1,11 @@ +import os +import httpx + +# Use your Cashu token or API key as the Bearer token +headers = {"Authorization": f"Bearer {os.environ.get('TOKEN')}"} +base_url = os.environ.get("API_URL", "https://api.routstr.com/v1") + +resp = httpx.post(f"{base_url}/balance/refund", headers=headers) + +print("Refund successful!") +print(resp.json()) diff --git a/examples/balance/topup_balance.py b/examples/balance/topup_balance.py new file mode 100644 index 00000000..ccdbe77e --- /dev/null +++ b/examples/balance/topup_balance.py @@ -0,0 +1,15 @@ +import os +import httpx + +# Use your Cashu token or API key as the Bearer token +headers = {"Authorization": f"Bearer {os.environ.get('TOKEN')}"} +base_url = os.environ.get("API_URL", "https://api.routstr.com/v1") + +# The Cashu token to top up with +cashu_token = input("Enter Cashu token to top up: ") + +resp = httpx.post( + f"{base_url}/balance/topup", headers=headers, json={"cashu_token": cashu_token} +) + +print(resp.json()) diff --git a/examples/chat_completions.py b/examples/chat_completions.py new file mode 100644 index 00000000..f7b4b9a4 --- /dev/null +++ b/examples/chat_completions.py @@ -0,0 +1,15 @@ +import os + +from openai import OpenAI + +client = OpenAI( + api_key=os.environ.get("TOKEN"), + base_url=os.environ.get("API_URL", "https://api.routstr.com/v1"), +) + +response = client.chat.completions.create( + model=os.environ.get("MODEL", "gpt-5-nano"), + messages=[{"role": "user", "content": "Hello!"}], +) + +print(response.choices[0].message.content) diff --git a/examples/list_models.py b/examples/list_models.py new file mode 100644 index 00000000..8aba55e3 --- /dev/null +++ b/examples/list_models.py @@ -0,0 +1,19 @@ +import os + +import httpx +from openai import OpenAI + +client = OpenAI( + api_key=os.environ.get("TOKEN", ""), + base_url=os.environ.get("API_URL", "https://api.routstr.com/v1"), +) + +for model in client.models.list(): + print(model.id) + +# OR + +models = httpx.get( + f"{client.base_url}/v1/models", + headers={"Authorization": f"Bearer {client.api_key}"}, +).json() diff --git a/examples/responses/conversation.py b/examples/responses/conversation.py new file mode 100644 index 00000000..91814a0c --- /dev/null +++ b/examples/responses/conversation.py @@ -0,0 +1,30 @@ +import os +from openai import OpenAI + +client = OpenAI( + api_key=os.environ.get("TOKEN"), + base_url=os.environ.get("API_URL", "https://api.routstr.com/v1"), +) + +conversation = [] + +# First turn +response1 = client.responses.create( # type: ignore + model="o4-mini", + input="Hi, my name is Alice.", + conversation=conversation, +) +print("Response 1:", response1.output) + +# Note: The 'conversation' parameter might need to be constructed differently +# depending on exact SDK/API spec. Typically, you pass back the previous turn's data. +# Assuming the SDK manages or returns a conversation object/ID: +# conversation.append(response1) + +# Second turn - demonstrating intent, actual implementation depends on strict API spec +# response2 = client.responses.create( +# model="openai/gpt-4o-mini", +# input="What is my name?", +# conversation=conversation, +# ) +# print("Response 2:", response2.output) diff --git a/examples/responses/create.py b/examples/responses/create.py new file mode 100644 index 00000000..aa2625ad --- /dev/null +++ b/examples/responses/create.py @@ -0,0 +1,16 @@ +import os +from openai import OpenAI + +# The OpenAI SDK handles the 'responses' endpoint if it's updated to the latest version +# and the base_url points to a compatible proxy like Routstr. +client = OpenAI( + api_key=os.environ.get("TOKEN"), + base_url=os.environ.get("API_URL", "https://api.routstr.com/v1"), +) + +response = client.responses.create( + model="gpt-5-mini", + input="Tell me a three sentence bedtime story about a unicorn.", +) + +print(response.output) diff --git a/examples/responses/streaming.py b/examples/responses/streaming.py new file mode 100644 index 00000000..b22d1c6c --- /dev/null +++ b/examples/responses/streaming.py @@ -0,0 +1,20 @@ +import os +from openai import OpenAI + +client = OpenAI( + api_key=os.environ.get("TOKEN"), + base_url=os.environ.get("API_URL", "https://api.routstr.com/v1"), +) + +stream = client.responses.create( + model="gpt-5-nano", + input="Write a short poem about rust.", + stream=True, +) + +for event in stream: + # Note: Depending on the SDK version and response structure, + # you might access event.output_delta or similar fields + print(event, end="", flush=True) + +print() diff --git a/examples/responses/streaming_response.py b/examples/responses/streaming_response.py new file mode 100644 index 00000000..a133cee3 --- /dev/null +++ b/examples/responses/streaming_response.py @@ -0,0 +1,19 @@ +import os +from openai import OpenAI + +client = OpenAI( + api_key=os.environ.get("TOKEN"), + base_url=os.environ.get("API_URL", "https://api.routstr.com/v1"), +) + +stream = client.responses.create( + model="claude-4.5-sonnet", + input="Write a short poem about rust.", + stream=True, +) + +for event in stream: + # Note: Depending on the SDK version and response structure, + # you might access event.output_delta or similar fields + print(event, end="", flush=True) +print() diff --git a/examples/responses/web_search.py b/examples/responses/web_search.py new file mode 100644 index 00000000..f91fd12c --- /dev/null +++ b/examples/responses/web_search.py @@ -0,0 +1,15 @@ +import os +from openai import OpenAI + +client = OpenAI( + api_key=os.environ.get("TOKEN"), + base_url=os.environ.get("API_URL", "https://api.routstr.com/v1"), +) + +response = client.responses.create( + model="gpt-5-mini", + input="What is the latest news about AI?", + tools=[{"type": "web_search"}], # type: ignore +) + +print(response.output) diff --git a/examples/streaming.py b/examples/streaming.py new file mode 100644 index 00000000..3c0bacf2 --- /dev/null +++ b/examples/streaming.py @@ -0,0 +1,28 @@ +import os + +from openai import OpenAI + +client = OpenAI( + api_key=os.environ.get("TOKEN"), + base_url=os.environ.get("API_URL", "https://api.routstr.com/v1"), +) + +messages = [] +while True: + messages.append({"role": "user", "content": input("\nYou: ")}) + + stream = client.chat.completions.create( + model=os.environ.get("MODEL", "gpt-5.1-mini"), + messages=messages, # type: ignore + stream=True, + ) + + print("AI: ", end="") + response_content = "" + for chunk in stream: + if content := chunk.choices[0].delta.content: # type: ignore + print(content, end="", flush=True) + response_content += content + print() + + messages.append({"role": "assistant", "content": response_content}) diff --git a/examples/tor.py b/examples/tor.py new file mode 100644 index 00000000..e69b9c28 --- /dev/null +++ b/examples/tor.py @@ -0,0 +1,19 @@ +import os +import httpx +from openai import OpenAI + +# Requires `pip install "httpx[socks]"` and a running Tor proxy on port 9050 +client = OpenAI( + api_key=os.environ.get("TOKEN"), + base_url=os.environ.get("ONION_URL", "http://roustrjfsdgfiueghsklchg.onion/v1"), + http_client=httpx.Client(proxies="socks5://localhost:9050"), +) + +print( + client.chat.completions.create( + model="openai/gpt-4o-mini", + messages=[{"role": "user", "content": "Hello from Tor!"}], + ) + .choices[0] + .message.content +) diff --git a/pyproject.toml b/pyproject.toml index a25cbbaf..0aa4e101 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,6 +73,7 @@ packages = ["routstr"] [tool.ruff.lint] select = ["E", "F", "I"] ignore = ["E501"] +exclude = ["examples"] [tool.mypy] python_version = "3.11"