unrestrictable 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,92 @@
1
+ """Python client for Unrestrictable: uncensored AI chat, images and video on one prepaid key.
2
+
3
+ The API speaks the OpenAI format, so the official `openai` SDK works against it as-is. When the package is installed
4
+ with the [openai] extra, openai_client() returns one pointed at the right base URL.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ import os
11
+ import urllib.error
12
+ import urllib.request
13
+
14
+ __version__ = "0.1.0"
15
+
16
+ BASE_URL = "https://api.unrestrictable.ai/v1"
17
+ API_KEY_ENV = "UNRESTRICTABLE_API_KEY"
18
+
19
+
20
+ class UnrestrictableError(RuntimeError):
21
+ """An error response from the API, with its HTTP status and body."""
22
+
23
+ def __init__(self, status: int, body: str) -> None:
24
+ super().__init__(f"Unrestrictable API {status}: {body[:500]}")
25
+ self.status = status
26
+ self.body = body
27
+
28
+
29
+ def _key(api_key: str | None) -> str:
30
+ key = api_key or os.environ.get(API_KEY_ENV, "")
31
+ if not key:
32
+ raise ValueError(
33
+ f"No API key. Set {API_KEY_ENV} or pass api_key=. "
34
+ "Get one at https://app.unrestrictable.ai/console"
35
+ )
36
+ return key
37
+
38
+
39
+ def _request(path: str, api_key: str | None, method: str = "GET", body: dict | None = None) -> dict:
40
+ url = BASE_URL + path
41
+ data = json.dumps(body).encode() if body is not None else None
42
+ req = urllib.request.Request(
43
+ url,
44
+ data=data,
45
+ method=method,
46
+ headers={
47
+ "Authorization": f"Bearer {_key(api_key)}",
48
+ "Content-Type": "application/json",
49
+ "User-Agent": "unrestrictable-python/0.1.0",
50
+ },
51
+ )
52
+ try:
53
+ with urllib.request.urlopen(req, timeout=120) as r:
54
+ return json.load(r)
55
+ except urllib.error.HTTPError as e: # the API's own error body is the useful part
56
+ raise UnrestrictableError(e.code, e.read().decode("utf-8", "replace")) from None
57
+
58
+
59
+ def models(api_key: str | None = None) -> list[dict]:
60
+ """Every model this key may call, with the developer's name. No key needed for the public list."""
61
+ url = BASE_URL + "/models"
62
+ req = urllib.request.Request(url, headers={"User-Agent": "unrestrictable-python/0.1.0"})
63
+ with urllib.request.urlopen(req, timeout=60) as r:
64
+ return json.load(r).get("data", [])
65
+
66
+
67
+ def catalog(api_key: str | None = None) -> dict:
68
+ """The public catalog: every model, its price per million tokens and the endpoints it answers. No key needed."""
69
+ req = urllib.request.Request(BASE_URL + "/catalog", headers={"User-Agent": "unrestrictable-python/0.1.0"})
70
+ with urllib.request.urlopen(req, timeout=60) as r:
71
+ return json.load(r)
72
+
73
+
74
+ def chat(model: str, prompt: str, api_key: str | None = None, **params) -> str:
75
+ """One turn, returned as text. `params` go into the request body (temperature, max_tokens, ...)."""
76
+ body = {"model": model, "messages": [{"role": "user", "content": prompt}], **params}
77
+ answer = _request("/chat/completions", api_key, "POST", body)
78
+ return answer["choices"][0]["message"]["content"]
79
+
80
+
81
+ def openai_client(api_key: str | None = None):
82
+ """An openai.OpenAI client pointed at Unrestrictable. Needs the [openai] extra."""
83
+ from openai import OpenAI
84
+
85
+ return OpenAI(base_url=BASE_URL, api_key=_key(api_key))
86
+
87
+
88
+ def anthropic_client(api_key: str | None = None):
89
+ """An anthropic.Anthropic client pointed at Unrestrictable. Needs the [anthropic] extra."""
90
+ from anthropic import Anthropic
91
+
92
+ return Anthropic(base_url=BASE_URL, api_key=_key(api_key))
@@ -0,0 +1,111 @@
1
+ Metadata-Version: 2.4
2
+ Name: unrestrictable
3
+ Version: 0.1.0
4
+ Summary: Python client for Unrestrictable: uncensored AI chat, images and video on one prepaid key, through the OpenAI and Anthropic SDKs.
5
+ Author-email: Uplink Switch LLC <hello@unrestrictable.ai>
6
+ License: MIT
7
+ Project-URL: Homepage, https://unrestrictable.ai
8
+ Project-URL: Models, https://unrestrictable.ai/models
9
+ Project-URL: Media, https://unrestrictable.ai/media
10
+ Project-URL: Pricing, https://unrestrictable.ai/pricing
11
+ Project-URL: UncensoredLLM, https://uncensoredllm.ai
12
+ Project-URL: PentestLLM, https://pentestllm.ai
13
+ Project-URL: RelaySwitch, https://relayswitch.io
14
+ Project-URL: UplinkSwitch, https://uplinkswitch.ai
15
+ Keywords: ai,uncensored,llm,api,openai-compatible,anthropic,image-generation,video-generation
16
+ Classifier: Development Status :: 4 - Beta
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Classifier: Topic :: Software Development :: Libraries
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Provides-Extra: openai
25
+ Requires-Dist: openai>=1.40; extra == "openai"
26
+ Provides-Extra: anthropic
27
+ Requires-Dist: anthropic>=0.34; extra == "anthropic"
28
+ Provides-Extra: all
29
+ Requires-Dist: openai>=1.40; extra == "all"
30
+ Requires-Dist: anthropic>=0.34; extra == "all"
31
+ Dynamic: license-file
32
+
33
+ # unrestrictable
34
+
35
+ Python client for [Unrestrictable](https://unrestrictable.ai): uncensored AI chat, images and video, with no ID, no phone and no prompt logs. Try it free with no sign-up, then pay by card, WeChat Pay or crypto from $10. The API speaks the OpenAI and Anthropic formats, so you keep the official SDKs.
36
+
37
+ ```bash
38
+ pip install "unrestrictable[openai]" # or [anthropic], or [all]
39
+ export UNRESTRICTABLE_API_KEY="..."
40
+ ```
41
+
42
+ Get a key at [app.unrestrictable.ai/console](https://app.unrestrictable.ai/console). Credit is prepaid from $10, with no subscription.
43
+
44
+ ## OpenAI SDK
45
+
46
+ ```python
47
+ import unrestrictable
48
+
49
+ client = unrestrictable.openai_client()
50
+ reply = client.chat.completions.create(
51
+ model="glm-5.3-uncensored",
52
+ messages=[{"role": "user", "content": "Say hi in five words."}],
53
+ )
54
+ print(reply.choices[0].message.content)
55
+ ```
56
+
57
+ ## Anthropic SDK
58
+
59
+ ```python
60
+ import unrestrictable
61
+
62
+ client = unrestrictable.anthropic_client()
63
+ msg = client.messages.create(
64
+ model="deepseek-v4-pro-uncensored",
65
+ max_tokens=200,
66
+ messages=[{"role": "user", "content": "Say hi in five words."}],
67
+ )
68
+ print(msg.content[0].text)
69
+ ```
70
+
71
+ ## No SDK at all
72
+
73
+ ```python
74
+ import unrestrictable
75
+
76
+ print(unrestrictable.chat("glm-5.3-uncensored", "Say hi in five words."))
77
+ ```
78
+
79
+ ## Prices, no key needed
80
+
81
+ ```python
82
+ import unrestrictable
83
+
84
+ for m in unrestrictable.models():
85
+ p = m["pricing"]
86
+ print(f'{m["id"]:<40} ${p["input"]}/${p["output"]} per 1M tokens')
87
+ ```
88
+
89
+ The public catalog at [api.unrestrictable.ai/v1/catalog](https://api.unrestrictable.ai/v1/catalog) carries every model, every price and every endpoint with no key and no rate limit worth worrying about.
90
+
91
+ ## Without this package
92
+
93
+ Set `OPENAI_BASE_URL` or `ANTHROPIC_BASE_URL` to `https://api.unrestrictable.ai/v1` and use your key.
94
+
95
+ - Chat in the browser, no key: [unrestrictable.ai/chat](https://unrestrictable.ai/chat)
96
+ - Models and prices: [unrestrictable.ai/models](https://unrestrictable.ai/models)
97
+ - Images and video: [unrestrictable.ai/media](https://unrestrictable.ai/media)
98
+ - Daily real-model check: [unrestrictable.ai/proof](https://unrestrictable.ai/proof)
99
+
100
+ Run by Uplink Switch LLC.
101
+
102
+ ## Sister sites
103
+
104
+ The same gateway, sold each on its own key and console:
105
+
106
+ - [UncensoredLLM](https://uncensoredllm.ai): the uncensored and abliterated builds as an API, priced per token.
107
+ - [PentestLLM](https://pentestllm.ai): uncensored AI for hacking and pentesting.
108
+ - [RelaySwitch](https://relayswitch.io): one API key for coding agents, paid by card or crypto.
109
+ - [UplinkSwitch](https://uplinkswitch.ai): the gateway itself: one key and one base URL for every model.
110
+
111
+ All of them: [UplinkSwitch](https://uplinkswitch.ai) for every model, [UncensoredLLM](https://uncensoredllm.ai) for abliterated builds, [Unrestrictable](https://unrestrictable.ai) for chat in the browser, [PentestLLM](https://pentestllm.ai) for security work, [RelaySwitch](https://relayswitch.io) for coding agents.
@@ -0,0 +1,6 @@
1
+ unrestrictable/__init__.py,sha256=Bdp94g6-mPU6I3CJNfiLlPV01g4u98ePeJFwTgfixX8,3467
2
+ unrestrictable-0.1.0.dist-info/licenses/LICENSE,sha256=C2_RBVnAJ42gW7RtTKadkuVLxoGLhq3j7Tu2gWuGIo4,50
3
+ unrestrictable-0.1.0.dist-info/METADATA,sha256=F6aoBrQRdBxaMqSYm5hN4fATQJ6kiTnZNsAWcpQyjPE,4338
4
+ unrestrictable-0.1.0.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
5
+ unrestrictable-0.1.0.dist-info/top_level.txt,sha256=8qc9m3gRgT7nS2MY7Uq2FIsZATE2a_GVzxCHlU_1rLc,15
6
+ unrestrictable-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.2.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Uplink Switch LLC
@@ -0,0 +1 @@
1
+ unrestrictable