chatgpt-plan-auth 1.0.0__tar.gz
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.
- chatgpt_plan_auth-1.0.0/.github/workflows/publish.yml +33 -0
- chatgpt_plan_auth-1.0.0/.gitignore +8 -0
- chatgpt_plan_auth-1.0.0/LICENSE +21 -0
- chatgpt_plan_auth-1.0.0/PKG-INFO +128 -0
- chatgpt_plan_auth-1.0.0/README.md +107 -0
- chatgpt_plan_auth-1.0.0/pyproject.toml +33 -0
- chatgpt_plan_auth-1.0.0/src/chatgpt_plan_auth/__init__.py +77 -0
- chatgpt_plan_auth-1.0.0/src/chatgpt_plan_auth/auth.py +560 -0
- chatgpt_plan_auth-1.0.0/src/chatgpt_plan_auth/catalog.py +94 -0
- chatgpt_plan_auth-1.0.0/src/chatgpt_plan_auth/client.py +84 -0
- chatgpt_plan_auth-1.0.0/src/chatgpt_plan_auth/const.py +167 -0
- chatgpt_plan_auth-1.0.0/src/chatgpt_plan_auth/errors.py +15 -0
- chatgpt_plan_auth-1.0.0/src/chatgpt_plan_auth/py.typed +0 -0
- chatgpt_plan_auth-1.0.0/src/chatgpt_plan_auth/requests.py +101 -0
- chatgpt_plan_auth-1.0.0/tests/conftest.py +128 -0
- chatgpt_plan_auth-1.0.0/tests/test_auth.py +498 -0
- chatgpt_plan_auth-1.0.0/tests/test_catalog.py +235 -0
- chatgpt_plan_auth-1.0.0/tests/test_client.py +95 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Trusted publishing: no API token anywhere. One-time setup on PyPI:
|
|
4
|
+
# 1. https://pypi.org/manage/account/publishing/ -> "Add a new pending publisher"
|
|
5
|
+
# PyPI Project Name: chatgpt-plan-auth
|
|
6
|
+
# Owner: guberm
|
|
7
|
+
# Repository name: chatgpt-plan-auth
|
|
8
|
+
# Workflow name: publish.yml
|
|
9
|
+
# Environment name: (leave empty)
|
|
10
|
+
# 2. Push a tag: git tag v1.0.0 && git push origin v1.0.0
|
|
11
|
+
# After the first release the publisher is no longer "pending".
|
|
12
|
+
|
|
13
|
+
on:
|
|
14
|
+
push:
|
|
15
|
+
tags:
|
|
16
|
+
- "v*"
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
publish:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
permissions:
|
|
22
|
+
id-token: write # required for trusted publishing
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- name: Install uv
|
|
27
|
+
uses: astral-sh/setup-uv@v5
|
|
28
|
+
|
|
29
|
+
- name: Build
|
|
30
|
+
run: uv build
|
|
31
|
+
|
|
32
|
+
- name: Publish
|
|
33
|
+
run: uv publish
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Michael Guber
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: chatgpt-plan-auth
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Sign in with ChatGPT (ChatGPT plan usage) for locally hosted apps
|
|
5
|
+
Author-email: Michael Guber <michael@guber.dev>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: chatgpt,oauth,openai,pkce,siwc
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Typing :: Typed
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Requires-Dist: httpx>=0.27
|
|
14
|
+
Provides-Extra: dev
|
|
15
|
+
Requires-Dist: openai>=1.40; extra == 'dev'
|
|
16
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
17
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
18
|
+
Provides-Extra: openai
|
|
19
|
+
Requires-Dist: openai>=1.40; extra == 'openai'
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# chatgpt-plan-auth
|
|
23
|
+
|
|
24
|
+
Sign in with ChatGPT (ChatGPT plan usage) for locally hosted, open-source apps.
|
|
25
|
+
|
|
26
|
+
Implements the SIWC OAuth flow documented at
|
|
27
|
+
<https://developers.openai.com/siwc/token-sharing-open-source/>: register a
|
|
28
|
+
dynamic client, authorize with PKCE, exchange the code for tokens, keep them
|
|
29
|
+
refreshed and rotated, read the plan's model catalog, and shape Responses API
|
|
30
|
+
requests for the plan usage route. The access token is used as the bearer token
|
|
31
|
+
against `https://api.openai.com/v1` instead of an API key.
|
|
32
|
+
|
|
33
|
+
The library is a straight extraction of Home Assistant core's
|
|
34
|
+
`openai_conversation/chatgpt_auth.py` (the reviewer's point: deep knowledge of
|
|
35
|
+
an external system belongs in a library, not in core). It carries no Home
|
|
36
|
+
Assistant imports, no `hass`, no config-entry or storage knowledge, and no
|
|
37
|
+
crypto dependency.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install chatgpt-plan-auth # protocol only: httpx
|
|
41
|
+
pip install chatgpt-plan-auth[openai] # + the OpenAI SDK client wrapper
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## What lives where
|
|
45
|
+
|
|
46
|
+
| Module | Contents |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| `chatgpt_plan_auth.const` | endpoints, `dynamic_agent_client`, scopes, the `ext_agent_host_id` scheme, rejected params/tools lists, model suggestions |
|
|
49
|
+
| `chatgpt_plan_auth.auth` | authorization URL + PKCE/state/nonce, callback parsing, token requests, code exchange, ID token claim validation, credentials, token lifecycle |
|
|
50
|
+
| `chatgpt_plan_auth.catalog` | plan model catalog fetch/parse and the suggestion fallback |
|
|
51
|
+
| `chatgpt_plan_auth.requests` | `shape_request_for_subscription`, `subscription_error_message` |
|
|
52
|
+
| `chatgpt_plan_auth.client` | httpx auth flow and `openai.AsyncOpenAI` subclass (extra: `openai`) |
|
|
53
|
+
|
|
54
|
+
Everything is caller-driven: no Home Assistant, no global session, no storage.
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import httpx
|
|
58
|
+
from chatgpt_plan_auth import (
|
|
59
|
+
ChatGPTCredentials, ChatGPTAuth, async_exchange_code, create_authorization_request,
|
|
60
|
+
create_ext_agent_host_id, parse_callback_url,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
host_id = create_ext_agent_host_id() # generate once, persist it yourself
|
|
64
|
+
request = create_authorization_request(client_id=None, ext_agent_host_id=host_id)
|
|
65
|
+
# send the user to request.url, then read the loopback address bar (any machine):
|
|
66
|
+
params = parse_callback_url(callback_url)
|
|
67
|
+
async with httpx.AsyncClient() as client:
|
|
68
|
+
credentials = await async_exchange_code(
|
|
69
|
+
client, params["code"], request=request,
|
|
70
|
+
callback_client_id=params.get("client_id"), callback_state=params.get("state"),
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# Later, per request:
|
|
74
|
+
auth = ChatGPTAuth(credentials, client=client, on_update=save) # `save` persists rotation
|
|
75
|
+
token = await auth.async_get_access_token()
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Errors: `ChatGPTPlanAuthFatalError` means the stored refresh token can never be
|
|
79
|
+
used again (start your re-authentication flow); any other
|
|
80
|
+
`ChatGPTPlanAuthError` is transient. With the `openai` extra,
|
|
81
|
+
`ChatGPTSubscriptionClient(auth, http_client=...)` attaches the token per
|
|
82
|
+
request and retries once on a 401.
|
|
83
|
+
|
|
84
|
+
## Deliberate simplification: no ID token signature verification
|
|
85
|
+
|
|
86
|
+
`/.well-known/jwks.json` is never fetched, RSA keys are never parsed and no JWT
|
|
87
|
+
or crypto dependency is carried — the JWKS helpers and their cache from core are
|
|
88
|
+
gone.
|
|
89
|
+
|
|
90
|
+
Rationale: the ID token arrives directly from the provider's
|
|
91
|
+
TLS-authenticated token endpoint in the same response as the code exchange. That
|
|
92
|
+
is the trust model Home Assistant's own OAuth2 flow uses, and it is exactly the
|
|
93
|
+
dependency-heavy part the core reviewer objected to. A signature check adds
|
|
94
|
+
nothing there: anyone able to forge the token response could equally forge the
|
|
95
|
+
signature.
|
|
96
|
+
|
|
97
|
+
What is still verified on every code exchange:
|
|
98
|
+
|
|
99
|
+
- `iss` is `https://auth.openai.com`
|
|
100
|
+
- `aud` contains the client id the code was exchanged with
|
|
101
|
+
- `exp` is in the future
|
|
102
|
+
- `nonce` equals the nonce of that authorization attempt
|
|
103
|
+
- the callback `state` equals the state of that authorization attempt
|
|
104
|
+
|
|
105
|
+
Token endpoint errors (`invalid_grant`, `invalid_client`, `token_expired`, ...)
|
|
106
|
+
still surface as fatal errors and never invalidate good credentials.
|
|
107
|
+
|
|
108
|
+
If you need signature verification — or you cannot trust your network path to
|
|
109
|
+
the token endpoint — verify the ID token against the JWKS in your application
|
|
110
|
+
before calling `validate_id_token`.
|
|
111
|
+
|
|
112
|
+
## Out of scope (stays in the consuming application)
|
|
113
|
+
|
|
114
|
+
- Home Assistant: config-entry inspection/storage, `Store` for the host id, the
|
|
115
|
+
HA http client, config-flow and reauth steps.
|
|
116
|
+
- Application branding: pass `agent_name_hint` (defaults to
|
|
117
|
+
`chatgpt-plan-auth`).
|
|
118
|
+
- Persisting credentials: the library returns plain mappings
|
|
119
|
+
(`ChatGPTCredentials.as_entry_data()`), nothing is written to disk.
|
|
120
|
+
|
|
121
|
+
## Tests
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
uv run --with pytest-asyncio --with openai python -m pytest tests -q
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
All network access is a fake `httpx.MockTransport`; no test touches the network
|
|
128
|
+
and no test needs key material.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# chatgpt-plan-auth
|
|
2
|
+
|
|
3
|
+
Sign in with ChatGPT (ChatGPT plan usage) for locally hosted, open-source apps.
|
|
4
|
+
|
|
5
|
+
Implements the SIWC OAuth flow documented at
|
|
6
|
+
<https://developers.openai.com/siwc/token-sharing-open-source/>: register a
|
|
7
|
+
dynamic client, authorize with PKCE, exchange the code for tokens, keep them
|
|
8
|
+
refreshed and rotated, read the plan's model catalog, and shape Responses API
|
|
9
|
+
requests for the plan usage route. The access token is used as the bearer token
|
|
10
|
+
against `https://api.openai.com/v1` instead of an API key.
|
|
11
|
+
|
|
12
|
+
The library is a straight extraction of Home Assistant core's
|
|
13
|
+
`openai_conversation/chatgpt_auth.py` (the reviewer's point: deep knowledge of
|
|
14
|
+
an external system belongs in a library, not in core). It carries no Home
|
|
15
|
+
Assistant imports, no `hass`, no config-entry or storage knowledge, and no
|
|
16
|
+
crypto dependency.
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install chatgpt-plan-auth # protocol only: httpx
|
|
20
|
+
pip install chatgpt-plan-auth[openai] # + the OpenAI SDK client wrapper
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## What lives where
|
|
24
|
+
|
|
25
|
+
| Module | Contents |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| `chatgpt_plan_auth.const` | endpoints, `dynamic_agent_client`, scopes, the `ext_agent_host_id` scheme, rejected params/tools lists, model suggestions |
|
|
28
|
+
| `chatgpt_plan_auth.auth` | authorization URL + PKCE/state/nonce, callback parsing, token requests, code exchange, ID token claim validation, credentials, token lifecycle |
|
|
29
|
+
| `chatgpt_plan_auth.catalog` | plan model catalog fetch/parse and the suggestion fallback |
|
|
30
|
+
| `chatgpt_plan_auth.requests` | `shape_request_for_subscription`, `subscription_error_message` |
|
|
31
|
+
| `chatgpt_plan_auth.client` | httpx auth flow and `openai.AsyncOpenAI` subclass (extra: `openai`) |
|
|
32
|
+
|
|
33
|
+
Everything is caller-driven: no Home Assistant, no global session, no storage.
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
import httpx
|
|
37
|
+
from chatgpt_plan_auth import (
|
|
38
|
+
ChatGPTCredentials, ChatGPTAuth, async_exchange_code, create_authorization_request,
|
|
39
|
+
create_ext_agent_host_id, parse_callback_url,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
host_id = create_ext_agent_host_id() # generate once, persist it yourself
|
|
43
|
+
request = create_authorization_request(client_id=None, ext_agent_host_id=host_id)
|
|
44
|
+
# send the user to request.url, then read the loopback address bar (any machine):
|
|
45
|
+
params = parse_callback_url(callback_url)
|
|
46
|
+
async with httpx.AsyncClient() as client:
|
|
47
|
+
credentials = await async_exchange_code(
|
|
48
|
+
client, params["code"], request=request,
|
|
49
|
+
callback_client_id=params.get("client_id"), callback_state=params.get("state"),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# Later, per request:
|
|
53
|
+
auth = ChatGPTAuth(credentials, client=client, on_update=save) # `save` persists rotation
|
|
54
|
+
token = await auth.async_get_access_token()
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Errors: `ChatGPTPlanAuthFatalError` means the stored refresh token can never be
|
|
58
|
+
used again (start your re-authentication flow); any other
|
|
59
|
+
`ChatGPTPlanAuthError` is transient. With the `openai` extra,
|
|
60
|
+
`ChatGPTSubscriptionClient(auth, http_client=...)` attaches the token per
|
|
61
|
+
request and retries once on a 401.
|
|
62
|
+
|
|
63
|
+
## Deliberate simplification: no ID token signature verification
|
|
64
|
+
|
|
65
|
+
`/.well-known/jwks.json` is never fetched, RSA keys are never parsed and no JWT
|
|
66
|
+
or crypto dependency is carried — the JWKS helpers and their cache from core are
|
|
67
|
+
gone.
|
|
68
|
+
|
|
69
|
+
Rationale: the ID token arrives directly from the provider's
|
|
70
|
+
TLS-authenticated token endpoint in the same response as the code exchange. That
|
|
71
|
+
is the trust model Home Assistant's own OAuth2 flow uses, and it is exactly the
|
|
72
|
+
dependency-heavy part the core reviewer objected to. A signature check adds
|
|
73
|
+
nothing there: anyone able to forge the token response could equally forge the
|
|
74
|
+
signature.
|
|
75
|
+
|
|
76
|
+
What is still verified on every code exchange:
|
|
77
|
+
|
|
78
|
+
- `iss` is `https://auth.openai.com`
|
|
79
|
+
- `aud` contains the client id the code was exchanged with
|
|
80
|
+
- `exp` is in the future
|
|
81
|
+
- `nonce` equals the nonce of that authorization attempt
|
|
82
|
+
- the callback `state` equals the state of that authorization attempt
|
|
83
|
+
|
|
84
|
+
Token endpoint errors (`invalid_grant`, `invalid_client`, `token_expired`, ...)
|
|
85
|
+
still surface as fatal errors and never invalidate good credentials.
|
|
86
|
+
|
|
87
|
+
If you need signature verification — or you cannot trust your network path to
|
|
88
|
+
the token endpoint — verify the ID token against the JWKS in your application
|
|
89
|
+
before calling `validate_id_token`.
|
|
90
|
+
|
|
91
|
+
## Out of scope (stays in the consuming application)
|
|
92
|
+
|
|
93
|
+
- Home Assistant: config-entry inspection/storage, `Store` for the host id, the
|
|
94
|
+
HA http client, config-flow and reauth steps.
|
|
95
|
+
- Application branding: pass `agent_name_hint` (defaults to
|
|
96
|
+
`chatgpt-plan-auth`).
|
|
97
|
+
- Persisting credentials: the library returns plain mappings
|
|
98
|
+
(`ChatGPTCredentials.as_entry_data()`), nothing is written to disk.
|
|
99
|
+
|
|
100
|
+
## Tests
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
uv run --with pytest-asyncio --with openai python -m pytest tests -q
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
All network access is a fake `httpx.MockTransport`; no test touches the network
|
|
107
|
+
and no test needs key material.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "chatgpt-plan-auth"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Sign in with ChatGPT (ChatGPT plan usage) for locally hosted apps"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [{ name = "Michael Guber", email = "michael@guber.dev" }]
|
|
13
|
+
keywords = ["chatgpt", "oauth", "openai", "pkce", "siwc"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"License :: OSI Approved :: MIT License",
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Typing :: Typed",
|
|
18
|
+
]
|
|
19
|
+
dependencies = ["httpx>=0.27"]
|
|
20
|
+
|
|
21
|
+
[project.optional-dependencies]
|
|
22
|
+
# The OpenAI SDK wrapper (`chatgpt_plan_auth.client`). The protocol code in
|
|
23
|
+
# `auth`, `catalog` and `requests` never imports it.
|
|
24
|
+
openai = ["openai>=1.40"]
|
|
25
|
+
dev = ["pytest>=8", "pytest-asyncio>=0.23", "openai>=1.40"]
|
|
26
|
+
|
|
27
|
+
[tool.hatch.build.targets.wheel]
|
|
28
|
+
packages = ["src/chatgpt_plan_auth"]
|
|
29
|
+
|
|
30
|
+
[tool.pytest.ini_options]
|
|
31
|
+
asyncio_mode = "auto"
|
|
32
|
+
pythonpath = ["tests"]
|
|
33
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Sign in with ChatGPT (ChatGPT plan usage) for locally hosted apps.
|
|
2
|
+
|
|
3
|
+
Implements the OAuth flow documented at
|
|
4
|
+
https://developers.openai.com/siwc/token-sharing-open-source/: register a
|
|
5
|
+
dynamic client, authorize with PKCE, exchange the code for tokens, refresh and
|
|
6
|
+
rotate them, read the plan's model catalog, and shape Responses API requests
|
|
7
|
+
for the plan usage route.
|
|
8
|
+
|
|
9
|
+
The protocol code needs only :mod:`httpx`. The OpenAI SDK wrapper
|
|
10
|
+
(:mod:`chatgpt_plan_auth.client`) needs the ``openai`` extra.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from .auth import (
|
|
14
|
+
AuthorizationRequest,
|
|
15
|
+
ChatGPTCredentials,
|
|
16
|
+
ChatGPTAuth,
|
|
17
|
+
async_exchange_code,
|
|
18
|
+
async_token_request,
|
|
19
|
+
create_authorization_request,
|
|
20
|
+
create_ext_agent_host_id,
|
|
21
|
+
credentials_from_token,
|
|
22
|
+
parse_callback_url,
|
|
23
|
+
validate_id_token,
|
|
24
|
+
)
|
|
25
|
+
from .catalog import (
|
|
26
|
+
async_get_subscription_models,
|
|
27
|
+
async_get_subscription_models_for_credentials,
|
|
28
|
+
subscription_model_options,
|
|
29
|
+
)
|
|
30
|
+
from .const import (
|
|
31
|
+
AUTH_METHOD_CHATGPT,
|
|
32
|
+
AUTHORIZE_URL,
|
|
33
|
+
CLIENT_ID_PREFIX,
|
|
34
|
+
DYNAMIC_AGENT_CLIENT,
|
|
35
|
+
MODELS_URL,
|
|
36
|
+
PLAN_SCOPE,
|
|
37
|
+
REDIRECT_URI,
|
|
38
|
+
RESOURCE,
|
|
39
|
+
SCOPE,
|
|
40
|
+
SUBSCRIPTION_MODEL_SUGGESTIONS,
|
|
41
|
+
TOKEN_URL,
|
|
42
|
+
)
|
|
43
|
+
from .errors import ChatGPTPlanAuthError, ChatGPTPlanAuthFatalError
|
|
44
|
+
from .requests import shape_request_for_subscription, subscription_error_message
|
|
45
|
+
|
|
46
|
+
__version__ = "1.0.0"
|
|
47
|
+
|
|
48
|
+
__all__ = [
|
|
49
|
+
"AUTH_METHOD_CHATGPT",
|
|
50
|
+
"AUTHORIZE_URL",
|
|
51
|
+
"CLIENT_ID_PREFIX",
|
|
52
|
+
"DYNAMIC_AGENT_CLIENT",
|
|
53
|
+
"MODELS_URL",
|
|
54
|
+
"PLAN_SCOPE",
|
|
55
|
+
"REDIRECT_URI",
|
|
56
|
+
"RESOURCE",
|
|
57
|
+
"SCOPE",
|
|
58
|
+
"SUBSCRIPTION_MODEL_SUGGESTIONS",
|
|
59
|
+
"TOKEN_URL",
|
|
60
|
+
"AuthorizationRequest",
|
|
61
|
+
"ChatGPTCredentials",
|
|
62
|
+
"ChatGPTAuth",
|
|
63
|
+
"ChatGPTPlanAuthError",
|
|
64
|
+
"ChatGPTPlanAuthFatalError",
|
|
65
|
+
"async_exchange_code",
|
|
66
|
+
"async_get_subscription_models",
|
|
67
|
+
"async_get_subscription_models_for_credentials",
|
|
68
|
+
"async_token_request",
|
|
69
|
+
"create_authorization_request",
|
|
70
|
+
"create_ext_agent_host_id",
|
|
71
|
+
"credentials_from_token",
|
|
72
|
+
"parse_callback_url",
|
|
73
|
+
"shape_request_for_subscription",
|
|
74
|
+
"subscription_error_message",
|
|
75
|
+
"subscription_model_options",
|
|
76
|
+
"validate_id_token",
|
|
77
|
+
]
|