tsugite-codex-cli 0.18.0__tar.gz → 0.19.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.
- {tsugite_codex_cli-0.18.0 → tsugite_codex_cli-0.19.0}/.gitignore +16 -4
- {tsugite_codex_cli-0.18.0 → tsugite_codex_cli-0.19.0}/PKG-INFO +2 -2
- {tsugite_codex_cli-0.18.0 → tsugite_codex_cli-0.19.0}/pyproject.toml +2 -2
- {tsugite_codex_cli-0.18.0 → tsugite_codex_cli-0.19.0}/tsugite_codex_cli/provider.py +17 -1
- {tsugite_codex_cli-0.18.0 → tsugite_codex_cli-0.19.0}/tsugite_codex_cli/__init__.py +0 -0
- {tsugite_codex_cli-0.18.0 → tsugite_codex_cli-0.19.0}/tsugite_codex_cli/auth.py +0 -0
|
@@ -15,8 +15,8 @@ dist/
|
|
|
15
15
|
downloads/
|
|
16
16
|
eggs/
|
|
17
17
|
.eggs/
|
|
18
|
-
lib/
|
|
19
|
-
lib64/
|
|
18
|
+
/lib/
|
|
19
|
+
/lib64/
|
|
20
20
|
parts/
|
|
21
21
|
sdist/
|
|
22
22
|
var/
|
|
@@ -176,9 +176,21 @@ docs-old/
|
|
|
176
176
|
docs/design/
|
|
177
177
|
examples/*
|
|
178
178
|
!examples/tsugite-example-plugin/
|
|
179
|
-
agents/
|
|
179
|
+
/agents/
|
|
180
180
|
.claude/
|
|
181
181
|
.tsugite/
|
|
182
182
|
benchmarks/
|
|
183
183
|
docker-compose.test.yml
|
|
184
|
-
#### TODO ^^^
|
|
184
|
+
#### TODO ^^^
|
|
185
|
+
|
|
186
|
+
plugins/tsugite-daemon/frontend/node_modules/
|
|
187
|
+
# Vite dep-optimizer cache. Normally under node_modules/.vite, but lands at the
|
|
188
|
+
# cwd's `.vite/` when vite/vitest is run from the repo root, so ignore it anywhere.
|
|
189
|
+
.vite/
|
|
190
|
+
# Built web UI - generated by `mise run web-build`; the wheel bundles it via
|
|
191
|
+
# hatch `artifacts`, git never carries it.
|
|
192
|
+
plugins/tsugite-daemon/tsugite_daemon/web/
|
|
193
|
+
# Re-include frontend source that generic lib/ rules (incl. contributors' global
|
|
194
|
+
# gitignores with Python-style `lib/`) would otherwise silently exclude.
|
|
195
|
+
!plugins/tsugite-daemon/frontend/src/lib/
|
|
196
|
+
!plugins/tsugite-daemon/frontend/src/lib/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tsugite-codex-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.19.0
|
|
4
4
|
Summary: Tsugite plugin: ChatGPT subscription auth via Codex CLI token store
|
|
5
5
|
Author: Justyn Shull
|
|
6
6
|
Requires-Python: >=3.11
|
|
7
|
-
Requires-Dist: tsugite-cli==0.
|
|
7
|
+
Requires-Dist: tsugite-cli==0.19.0
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "tsugite-codex-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.19.0"
|
|
4
4
|
description = "Tsugite plugin: ChatGPT subscription auth via Codex CLI token store"
|
|
5
5
|
authors = [{ name = "Justyn Shull" }]
|
|
6
6
|
requires-python = ">=3.11"
|
|
7
7
|
dependencies = [
|
|
8
|
-
"tsugite-cli==0.
|
|
8
|
+
"tsugite-cli==0.19.0",
|
|
9
9
|
]
|
|
10
10
|
|
|
11
11
|
[project.entry-points."tsugite.providers"]
|
|
@@ -88,7 +88,7 @@ def _normalise_kwargs(kwargs: dict) -> dict:
|
|
|
88
88
|
if key == "max_tokens":
|
|
89
89
|
body["max_output_tokens"] = value
|
|
90
90
|
elif key == "reasoning_effort":
|
|
91
|
-
body["reasoning"] = {"effort": value}
|
|
91
|
+
body["reasoning"] = {"effort": value, "summary": "auto"}
|
|
92
92
|
elif key == "response_format":
|
|
93
93
|
body["text"] = {"format": value}
|
|
94
94
|
elif key in {"temperature", "top_p", "stop", "presence_penalty", "frequency_penalty"}:
|
|
@@ -107,10 +107,16 @@ def _build_usage(usage_in: dict | None) -> Usage:
|
|
|
107
107
|
total_tokens = int(total) if total is not None else input_tokens + output_tokens
|
|
108
108
|
details = usage_in.get("output_tokens_details") or {}
|
|
109
109
|
reasoning_tokens = details.get("reasoning_tokens")
|
|
110
|
+
# The Responses API reports the cached prompt prefix (a subset of input_tokens)
|
|
111
|
+
# under input_tokens_details.cached_tokens - the input-side mirror of
|
|
112
|
+
# output_tokens_details.reasoning_tokens above.
|
|
113
|
+
input_details = usage_in.get("input_tokens_details") or {}
|
|
114
|
+
cached_tokens = input_details.get("cached_tokens")
|
|
110
115
|
return Usage(
|
|
111
116
|
prompt_tokens=input_tokens,
|
|
112
117
|
completion_tokens=output_tokens,
|
|
113
118
|
total_tokens=total_tokens,
|
|
119
|
+
cached_tokens=int(cached_tokens) if cached_tokens is not None else None,
|
|
114
120
|
reasoning_tokens=int(reasoning_tokens) if reasoning_tokens is not None else None,
|
|
115
121
|
)
|
|
116
122
|
|
|
@@ -120,6 +126,7 @@ class CodexCliProvider:
|
|
|
120
126
|
|
|
121
127
|
# Stateless across calls (auth refresh is internal), so the registry can cache one instance.
|
|
122
128
|
cacheable = True
|
|
129
|
+
models_are_definitive = True # CLI exposes a fixed model set; unlisted ids are typos
|
|
123
130
|
|
|
124
131
|
def __init__(self, name: str = "codex_cli"):
|
|
125
132
|
self.name = name
|
|
@@ -178,6 +185,11 @@ class CodexCliProvider:
|
|
|
178
185
|
if stream:
|
|
179
186
|
body["stream"] = True
|
|
180
187
|
body.update(_normalise_kwargs(kwargs))
|
|
188
|
+
# Reasoning summaries are opt-in on the Responses API: without
|
|
189
|
+
# `reasoning.summary` no reasoning_summary_text deltas are ever sent,
|
|
190
|
+
# so the UI can never show thinking. Ask for them even when no effort
|
|
191
|
+
# override is set (the codex CLI itself always sends both).
|
|
192
|
+
body.setdefault("reasoning", {}).setdefault("summary", "auto")
|
|
181
193
|
return body
|
|
182
194
|
|
|
183
195
|
@staticmethod
|
|
@@ -279,6 +291,10 @@ class CodexCliProvider:
|
|
|
279
291
|
delta = event.get("delta") or ""
|
|
280
292
|
if delta:
|
|
281
293
|
yield StreamChunk(reasoning_content=delta)
|
|
294
|
+
elif etype == "response.reasoning_summary_part.done":
|
|
295
|
+
# Summary parts are separate paragraphs; without a break the
|
|
296
|
+
# accumulated markdown runs them together (**a****b**).
|
|
297
|
+
yield StreamChunk(reasoning_content="\n\n")
|
|
282
298
|
elif etype == "response.completed":
|
|
283
299
|
response_obj = event.get("response") or {}
|
|
284
300
|
usage = _build_usage(response_obj.get("usage"))
|
|
File without changes
|
|
File without changes
|