axio-transport-codex 0.2.2__tar.gz → 0.3.2__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.
- axio_transport_codex-0.3.2/.gitignore +12 -0
- {axio_transport_codex-0.2.2 → axio_transport_codex-0.3.2}/Makefile +1 -1
- {axio_transport_codex-0.2.2 → axio_transport_codex-0.3.2}/PKG-INFO +4 -1
- {axio_transport_codex-0.2.2 → axio_transport_codex-0.3.2}/pyproject.toml +7 -2
- {axio_transport_codex-0.2.2 → axio_transport_codex-0.3.2}/src/axio_transport_codex/__init__.py +0 -7
- axio_transport_codex-0.3.2/src/axio_transport_codex/settings.py +5 -0
- {axio_transport_codex-0.2.2 → axio_transport_codex-0.3.2}/src/axio_transport_codex/transport.py +2 -1
- axio_transport_codex-0.3.2/src/axio_transport_codex/tui/__init__.py +15 -0
- axio_transport_codex-0.3.2/src/axio_transport_codex/tui/settings.py +74 -0
- {axio_transport_codex-0.2.2 → axio_transport_codex-0.3.2}/uv.lock +1 -1
- axio_transport_codex-0.2.2/src/axio_transport_codex/settings.py +0 -78
- {axio_transport_codex-0.2.2 → axio_transport_codex-0.3.2}/.github/workflows/publish.yml +0 -0
- {axio_transport_codex-0.2.2 → axio_transport_codex-0.3.2}/.github/workflows/tests.yml +0 -0
- {axio_transport_codex-0.2.2 → axio_transport_codex-0.3.2}/LICENSE +0 -0
- {axio_transport_codex-0.2.2 → axio_transport_codex-0.3.2}/README.md +0 -0
- {axio_transport_codex-0.2.2 → axio_transport_codex-0.3.2}/src/axio_transport_codex/oauth.py +0 -0
- {axio_transport_codex-0.2.2 → axio_transport_codex-0.3.2}/tests/test_oauth.py +0 -0
- {axio_transport_codex-0.2.2 → axio_transport_codex-0.3.2}/tests/test_transport.py +0 -0
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: axio-transport-codex
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: ChatGPT (Codex) OAuth transport for Axio using Responses API
|
|
5
|
+
Project-URL: Homepage, https://github.com/axio-agent/axio-transport-codex
|
|
6
|
+
Project-URL: Repository, https://github.com/axio-agent/axio-transport-codex
|
|
5
7
|
License: MIT
|
|
6
8
|
License-File: LICENSE
|
|
9
|
+
Keywords: agent,ai,chatgpt,llm,openai,transport
|
|
7
10
|
Requires-Python: >=3.12
|
|
8
11
|
Requires-Dist: aiohttp>=3.11
|
|
9
12
|
Requires-Dist: axio
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "axio-transport-codex"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.2"
|
|
4
4
|
description = "ChatGPT (Codex) OAuth transport for Axio using Responses API"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
7
7
|
license = {text = "MIT"}
|
|
8
|
+
keywords = ["llm", "agent", "ai", "openai", "chatgpt", "transport"]
|
|
8
9
|
dependencies = ["axio", "aiohttp>=3.11"]
|
|
9
10
|
|
|
10
11
|
[project.optional-dependencies]
|
|
@@ -14,8 +15,12 @@ tui = ["textual>=2.1.0"]
|
|
|
14
15
|
codex = "axio_transport_codex:CodexTransport"
|
|
15
16
|
|
|
16
17
|
[project.entry-points."axio.transport.settings"]
|
|
17
|
-
codex = "axio_transport_codex:CodexSettingsScreen"
|
|
18
|
+
codex = "axio_transport_codex.tui:CodexSettingsScreen"
|
|
18
19
|
|
|
20
|
+
|
|
21
|
+
[project.urls]
|
|
22
|
+
Homepage = "https://github.com/axio-agent/axio-transport-codex"
|
|
23
|
+
Repository = "https://github.com/axio-agent/axio-transport-codex"
|
|
19
24
|
[build-system]
|
|
20
25
|
requires = ["hatchling"]
|
|
21
26
|
build-backend = "hatchling.build"
|
{axio_transport_codex-0.2.2 → axio_transport_codex-0.3.2}/src/axio_transport_codex/__init__.py
RENAMED
|
@@ -3,10 +3,3 @@
|
|
|
3
3
|
from axio_transport_codex.transport import CODEX_MODELS, CodexTransport
|
|
4
4
|
|
|
5
5
|
__all__ = ["CODEX_MODELS", "CodexTransport"]
|
|
6
|
-
|
|
7
|
-
try:
|
|
8
|
-
from axio_transport_codex.settings import CodexSettingsScreen
|
|
9
|
-
|
|
10
|
-
__all__ += ["CodexSettingsScreen"]
|
|
11
|
-
except ImportError:
|
|
12
|
-
pass
|
{axio_transport_codex-0.2.2 → axio_transport_codex-0.3.2}/src/axio_transport_codex/transport.py
RENAMED
|
@@ -19,6 +19,7 @@ from axio.exceptions import StreamError
|
|
|
19
19
|
from axio.messages import Message
|
|
20
20
|
from axio.models import Capability, ModelRegistry, ModelSpec, TransportMeta
|
|
21
21
|
from axio.tool import Tool
|
|
22
|
+
from axio.transport import CompletionTransport
|
|
22
23
|
from axio.types import StopReason, Usage
|
|
23
24
|
|
|
24
25
|
from .oauth import CLIENT_ID, ORIGINATOR, TOKEN_URL, _decode_jwt_payload
|
|
@@ -158,7 +159,7 @@ def _convert_messages(messages: list[Message], system: str) -> tuple[str, list[d
|
|
|
158
159
|
|
|
159
160
|
|
|
160
161
|
@dataclass(slots=True)
|
|
161
|
-
class CodexTransport:
|
|
162
|
+
class CodexTransport(CompletionTransport):
|
|
162
163
|
META: ClassVar[TransportMeta] = TransportMeta(
|
|
163
164
|
label="ChatGPT (Codex)",
|
|
164
165
|
api_key_env="",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""TUI screens for axio-transport-codex (requires textual)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from .settings import CodexSettingsScreen
|
|
7
|
+
|
|
8
|
+
__all__ = ["CodexSettingsScreen"]
|
|
9
|
+
except ImportError as _e:
|
|
10
|
+
import warnings
|
|
11
|
+
|
|
12
|
+
warnings.warn(
|
|
13
|
+
f"axio-transport-codex TUI screens are unavailable: {_e}. Install textual: pip install axio[tui]",
|
|
14
|
+
stacklevel=1,
|
|
15
|
+
)
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Settings screen for ChatGPT (Codex) transport."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from textual.app import ComposeResult
|
|
6
|
+
from textual.binding import Binding
|
|
7
|
+
from textual.containers import Container, Horizontal
|
|
8
|
+
from textual.screen import ModalScreen
|
|
9
|
+
from textual.widgets import Button, Static
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class CodexSettingsScreen(ModalScreen[dict[str, str] | None]):
|
|
13
|
+
"""Sign in / sign out screen for ChatGPT OAuth."""
|
|
14
|
+
|
|
15
|
+
BINDINGS = [Binding("escape", "cancel", "Cancel")]
|
|
16
|
+
CSS = """
|
|
17
|
+
CodexSettingsScreen { align: center middle; }
|
|
18
|
+
#codex-settings {
|
|
19
|
+
width: 70; height: auto; border: heavy $accent;
|
|
20
|
+
background: $panel; padding: 1 2;
|
|
21
|
+
}
|
|
22
|
+
.field-label { margin-top: 1; }
|
|
23
|
+
.settings-buttons { height: auto; margin-top: 1; }
|
|
24
|
+
.settings-buttons Button { margin: 0 1; }
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, settings: dict[str, str]) -> None:
|
|
28
|
+
super().__init__()
|
|
29
|
+
self._settings = settings
|
|
30
|
+
self._signed_in = bool(settings.get("api_key"))
|
|
31
|
+
|
|
32
|
+
def compose(self) -> ComposeResult:
|
|
33
|
+
with Container(id="codex-settings"):
|
|
34
|
+
yield Static("[bold]ChatGPT (Codex) Settings[/]")
|
|
35
|
+
if self._signed_in:
|
|
36
|
+
account = self._settings.get("account_id", "unknown")
|
|
37
|
+
yield Static(f"Signed in (account: {account[:16]}...)", classes="field-label")
|
|
38
|
+
with Horizontal(classes="settings-buttons"):
|
|
39
|
+
yield Button("Sign Out", id="btn-signout", variant="warning")
|
|
40
|
+
yield Button("Cancel", id="btn-cancel")
|
|
41
|
+
else:
|
|
42
|
+
yield Static(
|
|
43
|
+
"Sign in with your ChatGPT account to use this transport.",
|
|
44
|
+
classes="field-label",
|
|
45
|
+
)
|
|
46
|
+
with Horizontal(classes="settings-buttons"):
|
|
47
|
+
yield Button("Sign in with ChatGPT", id="btn-signin", variant="primary")
|
|
48
|
+
yield Button("Cancel", id="btn-cancel")
|
|
49
|
+
|
|
50
|
+
def on_button_pressed(self, event: Button.Pressed) -> None:
|
|
51
|
+
if event.button.id == "btn-signin":
|
|
52
|
+
self.run_worker(self._do_signin(), exclusive=True)
|
|
53
|
+
elif event.button.id == "btn-signout":
|
|
54
|
+
self.dismiss({})
|
|
55
|
+
else:
|
|
56
|
+
self.dismiss(None)
|
|
57
|
+
|
|
58
|
+
async def _do_signin(self) -> None:
|
|
59
|
+
from axio_transport_codex.oauth import run_oauth_flow
|
|
60
|
+
|
|
61
|
+
try:
|
|
62
|
+
tokens = await run_oauth_flow()
|
|
63
|
+
settings: dict[str, str] = {
|
|
64
|
+
"api_key": tokens["access_token"],
|
|
65
|
+
"refresh_token": tokens.get("refresh_token", ""),
|
|
66
|
+
"expires_at": tokens.get("expires_at", ""),
|
|
67
|
+
"account_id": tokens.get("account_id", ""),
|
|
68
|
+
}
|
|
69
|
+
self.dismiss(settings)
|
|
70
|
+
except Exception as exc:
|
|
71
|
+
self.notify(f"Sign-in failed: {exc}", severity="error")
|
|
72
|
+
|
|
73
|
+
def action_cancel(self) -> None:
|
|
74
|
+
self.dismiss(None)
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
"""Textual settings screen for ChatGPT (Codex) transport."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
try:
|
|
6
|
-
from textual.app import ComposeResult
|
|
7
|
-
from textual.binding import Binding
|
|
8
|
-
from textual.containers import Container, Horizontal
|
|
9
|
-
from textual.screen import ModalScreen
|
|
10
|
-
from textual.widgets import Button, Static
|
|
11
|
-
|
|
12
|
-
class CodexSettingsScreen(ModalScreen[dict[str, str] | None]):
|
|
13
|
-
"""Sign in / sign out screen for ChatGPT OAuth."""
|
|
14
|
-
|
|
15
|
-
BINDINGS = [Binding("escape", "cancel", "Cancel")]
|
|
16
|
-
CSS = """
|
|
17
|
-
CodexSettingsScreen { align: center middle; }
|
|
18
|
-
#codex-settings {
|
|
19
|
-
width: 70; height: auto; border: heavy $accent;
|
|
20
|
-
background: $panel; padding: 1 2;
|
|
21
|
-
}
|
|
22
|
-
.field-label { margin-top: 1; }
|
|
23
|
-
.settings-buttons { height: auto; margin-top: 1; }
|
|
24
|
-
.settings-buttons Button { margin: 0 1; }
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
def __init__(self, settings: dict[str, str]) -> None:
|
|
28
|
-
super().__init__()
|
|
29
|
-
self._settings = settings
|
|
30
|
-
self._signed_in = bool(settings.get("api_key"))
|
|
31
|
-
|
|
32
|
-
def compose(self) -> ComposeResult:
|
|
33
|
-
with Container(id="codex-settings"):
|
|
34
|
-
yield Static("[bold]ChatGPT (Codex) Settings[/]")
|
|
35
|
-
if self._signed_in:
|
|
36
|
-
account = self._settings.get("account_id", "unknown")
|
|
37
|
-
yield Static(f"Signed in (account: {account[:16]}...)", classes="field-label")
|
|
38
|
-
with Horizontal(classes="settings-buttons"):
|
|
39
|
-
yield Button("Sign Out", id="btn-signout", variant="warning")
|
|
40
|
-
yield Button("Cancel", id="btn-cancel")
|
|
41
|
-
else:
|
|
42
|
-
yield Static(
|
|
43
|
-
"Sign in with your ChatGPT account to use this transport.",
|
|
44
|
-
classes="field-label",
|
|
45
|
-
)
|
|
46
|
-
with Horizontal(classes="settings-buttons"):
|
|
47
|
-
yield Button("Sign in with ChatGPT", id="btn-signin", variant="primary")
|
|
48
|
-
yield Button("Cancel", id="btn-cancel")
|
|
49
|
-
|
|
50
|
-
def on_button_pressed(self, event: Button.Pressed) -> None:
|
|
51
|
-
if event.button.id == "btn-signin":
|
|
52
|
-
self.run_worker(self._do_signin(), exclusive=True)
|
|
53
|
-
elif event.button.id == "btn-signout":
|
|
54
|
-
self.dismiss({})
|
|
55
|
-
else:
|
|
56
|
-
self.dismiss(None)
|
|
57
|
-
|
|
58
|
-
async def _do_signin(self) -> None:
|
|
59
|
-
from .oauth import run_oauth_flow
|
|
60
|
-
|
|
61
|
-
try:
|
|
62
|
-
tokens = await run_oauth_flow()
|
|
63
|
-
# Map access_token → api_key for registry compatibility
|
|
64
|
-
settings: dict[str, str] = {
|
|
65
|
-
"api_key": tokens["access_token"],
|
|
66
|
-
"refresh_token": tokens.get("refresh_token", ""),
|
|
67
|
-
"expires_at": tokens.get("expires_at", ""),
|
|
68
|
-
"account_id": tokens.get("account_id", ""),
|
|
69
|
-
}
|
|
70
|
-
self.dismiss(settings)
|
|
71
|
-
except Exception as exc:
|
|
72
|
-
self.notify(f"Sign-in failed: {exc}", severity="error")
|
|
73
|
-
|
|
74
|
-
def action_cancel(self) -> None:
|
|
75
|
-
self.dismiss(None)
|
|
76
|
-
|
|
77
|
-
except ImportError:
|
|
78
|
-
pass
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|