codex-python-sdk 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.
- codex_python_sdk/__init__.py +57 -0
- codex_python_sdk/_shared.py +99 -0
- codex_python_sdk/async_client.py +1313 -0
- codex_python_sdk/errors.py +18 -0
- codex_python_sdk/examples/__init__.py +2 -0
- codex_python_sdk/examples/demo_smoke.py +304 -0
- codex_python_sdk/factory.py +25 -0
- codex_python_sdk/policy.py +636 -0
- codex_python_sdk/renderer.py +607 -0
- codex_python_sdk/sync_client.py +333 -0
- codex_python_sdk/types.py +48 -0
- codex_python_sdk-0.1.0.dist-info/METADATA +274 -0
- codex_python_sdk-0.1.0.dist-info/RECORD +17 -0
- codex_python_sdk-0.1.0.dist-info/WHEEL +5 -0
- codex_python_sdk-0.1.0.dist-info/entry_points.txt +2 -0
- codex_python_sdk-0.1.0.dist-info/licenses/LICENSE +21 -0
- codex_python_sdk-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio as asyncio
|
|
4
|
+
|
|
5
|
+
from .async_client import (
|
|
6
|
+
DEFAULT_APP_SERVER_ARGS,
|
|
7
|
+
DEFAULT_CLI_COMMAND,
|
|
8
|
+
AsyncCodexAgenticClient,
|
|
9
|
+
)
|
|
10
|
+
from .errors import (
|
|
11
|
+
AppServerConnectionError,
|
|
12
|
+
CodexAgenticError,
|
|
13
|
+
NotAuthenticatedError,
|
|
14
|
+
SessionNotFoundError,
|
|
15
|
+
)
|
|
16
|
+
from .factory import create_async_client, create_client
|
|
17
|
+
from .policy import (
|
|
18
|
+
DEFAULT_POLICY_RUBRIC,
|
|
19
|
+
DefaultPolicyEngine,
|
|
20
|
+
LlmRubricPolicyEngine,
|
|
21
|
+
PolicyContext,
|
|
22
|
+
PolicyEngine,
|
|
23
|
+
PolicyJudgeConfig,
|
|
24
|
+
PolicyRubric,
|
|
25
|
+
RuleBasedPolicyEngine,
|
|
26
|
+
build_policy_engine_from_rubric,
|
|
27
|
+
)
|
|
28
|
+
from .renderer import ExecStyleRenderer, render_exec_style_events
|
|
29
|
+
from .sync_client import CodexAgenticClient
|
|
30
|
+
from .types import AgentResponse, ResponseEvent
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"AgentResponse",
|
|
34
|
+
"AppServerConnectionError",
|
|
35
|
+
"AsyncCodexAgenticClient",
|
|
36
|
+
"CodexAgenticClient",
|
|
37
|
+
"CodexAgenticError",
|
|
38
|
+
"DEFAULT_APP_SERVER_ARGS",
|
|
39
|
+
"DEFAULT_CLI_COMMAND",
|
|
40
|
+
"ExecStyleRenderer",
|
|
41
|
+
"DEFAULT_POLICY_RUBRIC",
|
|
42
|
+
"DefaultPolicyEngine",
|
|
43
|
+
"LlmRubricPolicyEngine",
|
|
44
|
+
"NotAuthenticatedError",
|
|
45
|
+
"PolicyContext",
|
|
46
|
+
"PolicyEngine",
|
|
47
|
+
"PolicyJudgeConfig",
|
|
48
|
+
"PolicyRubric",
|
|
49
|
+
"ResponseEvent",
|
|
50
|
+
"RuleBasedPolicyEngine",
|
|
51
|
+
"SessionNotFoundError",
|
|
52
|
+
"asyncio",
|
|
53
|
+
"build_policy_engine_from_rubric",
|
|
54
|
+
"create_async_client",
|
|
55
|
+
"create_client",
|
|
56
|
+
"render_exec_style_events",
|
|
57
|
+
]
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from datetime import datetime, timezone
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def utc_now() -> str:
|
|
8
|
+
return datetime.now(tz=timezone.utc).isoformat()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def first_nonempty_text(value: Any) -> str | None:
|
|
12
|
+
if isinstance(value, str):
|
|
13
|
+
text = value.strip()
|
|
14
|
+
return text or None
|
|
15
|
+
if isinstance(value, list):
|
|
16
|
+
out: list[str] = []
|
|
17
|
+
for item in value:
|
|
18
|
+
text = first_nonempty_text(item)
|
|
19
|
+
if text:
|
|
20
|
+
out.append(text)
|
|
21
|
+
if out:
|
|
22
|
+
return "\n".join(out)
|
|
23
|
+
return None
|
|
24
|
+
if isinstance(value, dict):
|
|
25
|
+
for key in ("message", "text", "delta", "error", "content"):
|
|
26
|
+
if key in value:
|
|
27
|
+
text = first_nonempty_text(value.get(key))
|
|
28
|
+
if text:
|
|
29
|
+
return text
|
|
30
|
+
for nested in value.values():
|
|
31
|
+
if isinstance(nested, (dict, list)):
|
|
32
|
+
text = first_nonempty_text(nested)
|
|
33
|
+
if text:
|
|
34
|
+
return text
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def token_usage_total_tokens(value: Any) -> int | None:
|
|
39
|
+
if not isinstance(value, dict):
|
|
40
|
+
return None
|
|
41
|
+
total = value.get("totalTokens")
|
|
42
|
+
if isinstance(total, int):
|
|
43
|
+
return total
|
|
44
|
+
total = value.get("total_tokens")
|
|
45
|
+
if isinstance(total, int):
|
|
46
|
+
return total
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def token_usage_summary(token_usage: dict[str, Any]) -> str | None:
|
|
51
|
+
last = token_usage.get("last")
|
|
52
|
+
total = token_usage.get("total")
|
|
53
|
+
last_total = token_usage_total_tokens(last)
|
|
54
|
+
total_total = token_usage_total_tokens(total)
|
|
55
|
+
if last_total is None and total_total is None:
|
|
56
|
+
return None
|
|
57
|
+
if last_total is None:
|
|
58
|
+
return f"total={total_total}"
|
|
59
|
+
if total_total is None:
|
|
60
|
+
return f"last={last_total}"
|
|
61
|
+
return f"last={last_total}, total={total_total}"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def diff_change_counts(diff: str) -> tuple[int, int]:
|
|
65
|
+
added = 0
|
|
66
|
+
removed = 0
|
|
67
|
+
for line in diff.splitlines():
|
|
68
|
+
if line.startswith("+++") or line.startswith("---"):
|
|
69
|
+
continue
|
|
70
|
+
if line.startswith("+"):
|
|
71
|
+
added += 1
|
|
72
|
+
elif line.startswith("-"):
|
|
73
|
+
removed += 1
|
|
74
|
+
return added, removed
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def turn_plan_summary(params: dict[str, Any]) -> str | None:
|
|
78
|
+
plan = params.get("plan")
|
|
79
|
+
if not isinstance(plan, list):
|
|
80
|
+
return first_nonempty_text(params.get("explanation"))
|
|
81
|
+
|
|
82
|
+
status_counts: dict[str, int] = {}
|
|
83
|
+
for item in plan:
|
|
84
|
+
if not isinstance(item, dict):
|
|
85
|
+
continue
|
|
86
|
+
status = item.get("status")
|
|
87
|
+
if isinstance(status, str):
|
|
88
|
+
status_counts[status] = status_counts.get(status, 0) + 1
|
|
89
|
+
|
|
90
|
+
parts: list[str] = []
|
|
91
|
+
explanation = params.get("explanation")
|
|
92
|
+
if isinstance(explanation, str) and explanation.strip():
|
|
93
|
+
parts.append(explanation.strip())
|
|
94
|
+
parts.append(f"steps={len(plan)}")
|
|
95
|
+
for status in ("inProgress", "pending", "completed"):
|
|
96
|
+
if status in status_counts:
|
|
97
|
+
parts.append(f"{status}={status_counts[status]}")
|
|
98
|
+
return ", ".join(parts)
|
|
99
|
+
|