cortex-agent-sdk 0.1.0__tar.gz → 0.2.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.
- cortex_agent_sdk-0.2.0/PKG-INFO +180 -0
- cortex_agent_sdk-0.2.0/README.md +152 -0
- {cortex_agent_sdk-0.1.0 → cortex_agent_sdk-0.2.0}/pyproject.toml +7 -16
- cortex_agent_sdk-0.2.0/src/cortex_agent_sdk/__init__.py +5 -0
- {cortex_agent_sdk-0.1.0 → cortex_agent_sdk-0.2.0}/src/cortex_agent_sdk/errores/__init__.py +2 -0
- cortex_agent_sdk-0.2.0/src/cortex_agent_sdk/errores/catalogo.py +18 -0
- {cortex_agent_sdk-0.1.0 → cortex_agent_sdk-0.2.0}/src/cortex_agent_sdk/errores/excepcion.py +1 -4
- {cortex_agent_sdk-0.1.0 → cortex_agent_sdk-0.2.0}/src/cortex_agent_sdk/redis/__init__.py +2 -0
- {cortex_agent_sdk-0.1.0 → cortex_agent_sdk-0.2.0}/src/cortex_agent_sdk/redis/scripts.py +3 -18
- cortex_agent_sdk-0.2.0/src/cortex_agent_sdk/redis/store.py +355 -0
- cortex_agent_sdk-0.2.0/src/cortex_agent_sdk/sessions/__init__.py +5 -0
- cortex_agent_sdk-0.2.0/src/cortex_agent_sdk/sessions/codec.py +16 -0
- cortex_agent_sdk-0.2.0/src/cortex_agent_sdk/sessions/memory.py +132 -0
- cortex_agent_sdk-0.2.0/src/cortex_agent_sdk/sessions/models.py +21 -0
- cortex_agent_sdk-0.2.0/src/cortex_agent_sdk/sessions/store.py +17 -0
- cortex_agent_sdk-0.1.0/PKG-INFO +0 -139
- cortex_agent_sdk-0.1.0/README.md +0 -105
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/__init__.py +0 -16
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/agent.py +0 -712
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/control.py +0 -159
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/engine.py +0 -154
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/errores/catalogo.py +0 -35
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/gateway.py +0 -22
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/google/__init__.py +0 -1
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/history/__init__.py +0 -2
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/history/models.py +0 -154
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/history/pipeline.py +0 -53
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/history/transform.py +0 -16
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/hooks.py +0 -102
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/immutable.py +0 -75
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/lifecycle.py +0 -67
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/openai/__init__.py +0 -3
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/openai/engine.py +0 -311
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/openai/models.py +0 -57
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/openai/options.py +0 -19
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/postgres/__init__.py +0 -1
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/postgres/store.py +0 -468
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/redis/store.py +0 -308
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/results.py +0 -34
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/runtime.py +0 -39
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/sessions/__init__.py +0 -4
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/sessions/codec.py +0 -27
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/sessions/lease.py +0 -85
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/sessions/memory.py +0 -186
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/sessions/models.py +0 -70
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/sessions/store.py +0 -38
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/tools/__init__.py +0 -1
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/tools/approval.py +0 -20
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/tools/contracts.py +0 -323
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/tools/decorators.py +0 -151
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/tools/execution.py +0 -233
- cortex_agent_sdk-0.1.0/src/cortex_agent_sdk/tools/models.py +0 -81
- {cortex_agent_sdk-0.1.0 → cortex_agent_sdk-0.2.0}/.gitignore +0 -0
- {cortex_agent_sdk-0.1.0 → cortex_agent_sdk-0.2.0}/LICENSE +0 -0
- {cortex_agent_sdk-0.1.0 → cortex_agent_sdk-0.2.0}/src/cortex_agent_sdk/py.typed +0 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cortex-agent-sdk
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Sesiones Memory y Redis para agentes construidos con Pydantic AI
|
|
5
|
+
Project-URL: Repository, https://github.com/epok200/cortex_agent_sdk
|
|
6
|
+
Project-URL: Issues, https://github.com/epok200/cortex_agent_sdk/issues
|
|
7
|
+
Author: EPOK
|
|
8
|
+
License-Expression: Apache-2.0
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: agents,pydantic-ai,redis,sessions
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
Requires-Python: >=3.13
|
|
19
|
+
Requires-Dist: pydantic-ai-slim<3,>=2.27
|
|
20
|
+
Provides-Extra: all
|
|
21
|
+
Requires-Dist: pydantic-ai-slim[openai]<3,>=2.27; extra == 'all'
|
|
22
|
+
Requires-Dist: redis>=8.1.0; extra == 'all'
|
|
23
|
+
Provides-Extra: openai
|
|
24
|
+
Requires-Dist: pydantic-ai-slim[openai]<3,>=2.27; extra == 'openai'
|
|
25
|
+
Provides-Extra: redis
|
|
26
|
+
Requires-Dist: redis>=8.1.0; extra == 'redis'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# Cortex Agent SDK
|
|
30
|
+
|
|
31
|
+
Cortex agrega sesiones Memory y Redis a agentes construidos directamente con Pydantic AI.
|
|
32
|
+
|
|
33
|
+
No implementa otro loop, otra capa de tools ni otra API de agentes. Pydantic AI conserva el control
|
|
34
|
+
de providers, modelos, tools, tipado, `RunContext`, hooks, límites, approvals, outputs, usage e
|
|
35
|
+
historial. Cortex sólo cubre la pieza que Pydantic AI no incluye: persistencia conversacional con un
|
|
36
|
+
turno activo por sesión.
|
|
37
|
+
|
|
38
|
+
> Cortex Agent SDK está en alfa. La API puede cambiar antes de la versión `1.0.0`.
|
|
39
|
+
|
|
40
|
+
## Requisitos
|
|
41
|
+
|
|
42
|
+
- Python `>=3.13`.
|
|
43
|
+
- Pydantic AI `>=2.27,<3`, instalado por Cortex en su variante slim.
|
|
44
|
+
|
|
45
|
+
## Instalación
|
|
46
|
+
|
|
47
|
+
Sesiones en memoria:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
uv add cortex-agent-sdk
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
OpenAI Responses:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
uv add "cortex-agent-sdk[openai]"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
OpenAI Responses y Redis:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
uv add "cortex-agent-sdk[openai,redis]"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Uso
|
|
66
|
+
|
|
67
|
+
El agente es el `Agent` nativo de Pydantic AI. El store entrega el historial bajo exclusión y lo
|
|
68
|
+
guarda cuando `session.replace(...)` marca un resultado completo.
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
import asyncio
|
|
72
|
+
|
|
73
|
+
from pydantic_ai import Agent
|
|
74
|
+
|
|
75
|
+
from cortex_agent_sdk.sessions import MemorySessionStore
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
async def main() -> None:
|
|
79
|
+
agent = Agent("openai-responses:gpt-5.6-luna")
|
|
80
|
+
sessions = MemorySessionStore()
|
|
81
|
+
|
|
82
|
+
async with agent, sessions:
|
|
83
|
+
async with sessions.turn("usuario:42") as session:
|
|
84
|
+
result = await agent.run(
|
|
85
|
+
"Recuerda que mi color favorito es verde.",
|
|
86
|
+
message_history=session.messages,
|
|
87
|
+
conversation_id=session.session_id,
|
|
88
|
+
)
|
|
89
|
+
session.replace(result.all_messages())
|
|
90
|
+
|
|
91
|
+
print(result.output)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
asyncio.run(main())
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`replace()` es explícito por diseño:
|
|
98
|
+
|
|
99
|
+
- Si no se llama, el store no modifica el historial.
|
|
100
|
+
- Si el bloque termina con una excepción, el store no guarda el reemplazo.
|
|
101
|
+
- Si guardar falla, la excepción se propaga.
|
|
102
|
+
|
|
103
|
+
## Redis
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from cortex_agent_sdk.redis import RedisSessionStore
|
|
107
|
+
|
|
108
|
+
sessions = RedisSessionStore(
|
|
109
|
+
"redis://localhost:6379/0",
|
|
110
|
+
key_prefix="mi-producto:sesiones:v1",
|
|
111
|
+
ttl_seconds=86_400,
|
|
112
|
+
)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Redis mantiene un lease renovable durante todo el turno. Mientras conserva el lease, dos procesos no
|
|
116
|
+
pueden usar la misma sesión al mismo tiempo y las sesiones distintas siguen siendo concurrentes. Si
|
|
117
|
+
la renovación falla, Cortex interrumpe el turno propietario y no guarda como owner obsoleto. El
|
|
118
|
+
historial se serializa con `ModelMessagesTypeAdapter`, el formato público de Pydantic AI.
|
|
119
|
+
|
|
120
|
+
Al cambiar desde el runtime anterior, usa un prefix nuevo. Los formatos no son compatibles y Cortex
|
|
121
|
+
no intenta convertir el historial legacy.
|
|
122
|
+
|
|
123
|
+
## Endpoint compatible con OpenAI
|
|
124
|
+
|
|
125
|
+
Pydantic AI puede conectarse directamente. Para un endpoint que no debe reintentar peticiones,
|
|
126
|
+
configura el provider una vez:
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from pydantic_ai import Agent
|
|
130
|
+
from pydantic_ai.models.openai import OpenAIResponsesModel
|
|
131
|
+
from pydantic_ai.providers.openai import OpenAIProvider
|
|
132
|
+
|
|
133
|
+
provider = OpenAIProvider(
|
|
134
|
+
base_url="https://example.com/v1",
|
|
135
|
+
api_key="...",
|
|
136
|
+
)
|
|
137
|
+
provider.client.max_retries = 0
|
|
138
|
+
model = OpenAIResponsesModel("gpt-5.6-luna", provider=provider)
|
|
139
|
+
agent = Agent(model)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
El context manager de `Agent` administra el transporte del provider.
|
|
143
|
+
|
|
144
|
+
## Migración desde el runtime anterior
|
|
145
|
+
|
|
146
|
+
| Antes | Ahora |
|
|
147
|
+
|---|---|
|
|
148
|
+
| `cortex_agent_sdk.Agent` | `pydantic_ai.Agent` |
|
|
149
|
+
| `OpenAIEngine` | `OpenAIResponsesModel` + `OpenAIProvider` |
|
|
150
|
+
| `OpenAICompatibleGateway` | `OpenAIProvider(base_url=..., api_key=...)` |
|
|
151
|
+
| `OpenAIOptions` | `OpenAIResponsesModelSettings` y argumentos de `Agent.run` |
|
|
152
|
+
| `@tool` e `Injected` | tools nativas + `RunContext[Deps]` |
|
|
153
|
+
| `ToolBinding` | `FunctionToolset` o tools preparadas por run |
|
|
154
|
+
| `AgentHooks` | `pydantic_ai.capabilities.Hooks` |
|
|
155
|
+
| `turn_finished` | `Hooks(after_run=...)` |
|
|
156
|
+
| `history_transform` | `Hooks(before_model_request=...)` |
|
|
157
|
+
| `fallback_answer` | política local del producto sobre `AgentRunResult` |
|
|
158
|
+
| `AgentOptions` | `UsageLimits`, settings del modelo y argumentos de `Agent` |
|
|
159
|
+
| `AgentResult.text` | `AgentRunResult.output` |
|
|
160
|
+
| `SessionStore.acquire` | `SessionStore.turn` + `Session.replace` |
|
|
161
|
+
| `agent.reset_session(id)` | `store.reset(id)` |
|
|
162
|
+
|
|
163
|
+
No se ofrece una capa de compatibilidad. Mantenerla volvería a duplicar la API y el runtime de
|
|
164
|
+
Pydantic AI.
|
|
165
|
+
|
|
166
|
+
## Superficie pública
|
|
167
|
+
|
|
168
|
+
- `cortex_agent_sdk.sessions.Session`
|
|
169
|
+
- `cortex_agent_sdk.sessions.SessionStore`
|
|
170
|
+
- `cortex_agent_sdk.sessions.MemorySessionStore`
|
|
171
|
+
- `cortex_agent_sdk.redis.RedisSessionStore`
|
|
172
|
+
- `cortex_agent_sdk.errores.AppError`
|
|
173
|
+
- `cortex_agent_sdk.errores.CodigoError`
|
|
174
|
+
- `cortex_agent_sdk.errores.Severidad`
|
|
175
|
+
|
|
176
|
+
El loop, tools, hooks, approvals, modelos y resultados se importan desde `pydantic_ai`.
|
|
177
|
+
|
|
178
|
+
## Licencia
|
|
179
|
+
|
|
180
|
+
Apache License 2.0.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Cortex Agent SDK
|
|
2
|
+
|
|
3
|
+
Cortex agrega sesiones Memory y Redis a agentes construidos directamente con Pydantic AI.
|
|
4
|
+
|
|
5
|
+
No implementa otro loop, otra capa de tools ni otra API de agentes. Pydantic AI conserva el control
|
|
6
|
+
de providers, modelos, tools, tipado, `RunContext`, hooks, límites, approvals, outputs, usage e
|
|
7
|
+
historial. Cortex sólo cubre la pieza que Pydantic AI no incluye: persistencia conversacional con un
|
|
8
|
+
turno activo por sesión.
|
|
9
|
+
|
|
10
|
+
> Cortex Agent SDK está en alfa. La API puede cambiar antes de la versión `1.0.0`.
|
|
11
|
+
|
|
12
|
+
## Requisitos
|
|
13
|
+
|
|
14
|
+
- Python `>=3.13`.
|
|
15
|
+
- Pydantic AI `>=2.27,<3`, instalado por Cortex en su variante slim.
|
|
16
|
+
|
|
17
|
+
## Instalación
|
|
18
|
+
|
|
19
|
+
Sesiones en memoria:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
uv add cortex-agent-sdk
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
OpenAI Responses:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
uv add "cortex-agent-sdk[openai]"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
OpenAI Responses y Redis:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
uv add "cortex-agent-sdk[openai,redis]"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Uso
|
|
38
|
+
|
|
39
|
+
El agente es el `Agent` nativo de Pydantic AI. El store entrega el historial bajo exclusión y lo
|
|
40
|
+
guarda cuando `session.replace(...)` marca un resultado completo.
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
import asyncio
|
|
44
|
+
|
|
45
|
+
from pydantic_ai import Agent
|
|
46
|
+
|
|
47
|
+
from cortex_agent_sdk.sessions import MemorySessionStore
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
async def main() -> None:
|
|
51
|
+
agent = Agent("openai-responses:gpt-5.6-luna")
|
|
52
|
+
sessions = MemorySessionStore()
|
|
53
|
+
|
|
54
|
+
async with agent, sessions:
|
|
55
|
+
async with sessions.turn("usuario:42") as session:
|
|
56
|
+
result = await agent.run(
|
|
57
|
+
"Recuerda que mi color favorito es verde.",
|
|
58
|
+
message_history=session.messages,
|
|
59
|
+
conversation_id=session.session_id,
|
|
60
|
+
)
|
|
61
|
+
session.replace(result.all_messages())
|
|
62
|
+
|
|
63
|
+
print(result.output)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
asyncio.run(main())
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`replace()` es explícito por diseño:
|
|
70
|
+
|
|
71
|
+
- Si no se llama, el store no modifica el historial.
|
|
72
|
+
- Si el bloque termina con una excepción, el store no guarda el reemplazo.
|
|
73
|
+
- Si guardar falla, la excepción se propaga.
|
|
74
|
+
|
|
75
|
+
## Redis
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from cortex_agent_sdk.redis import RedisSessionStore
|
|
79
|
+
|
|
80
|
+
sessions = RedisSessionStore(
|
|
81
|
+
"redis://localhost:6379/0",
|
|
82
|
+
key_prefix="mi-producto:sesiones:v1",
|
|
83
|
+
ttl_seconds=86_400,
|
|
84
|
+
)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Redis mantiene un lease renovable durante todo el turno. Mientras conserva el lease, dos procesos no
|
|
88
|
+
pueden usar la misma sesión al mismo tiempo y las sesiones distintas siguen siendo concurrentes. Si
|
|
89
|
+
la renovación falla, Cortex interrumpe el turno propietario y no guarda como owner obsoleto. El
|
|
90
|
+
historial se serializa con `ModelMessagesTypeAdapter`, el formato público de Pydantic AI.
|
|
91
|
+
|
|
92
|
+
Al cambiar desde el runtime anterior, usa un prefix nuevo. Los formatos no son compatibles y Cortex
|
|
93
|
+
no intenta convertir el historial legacy.
|
|
94
|
+
|
|
95
|
+
## Endpoint compatible con OpenAI
|
|
96
|
+
|
|
97
|
+
Pydantic AI puede conectarse directamente. Para un endpoint que no debe reintentar peticiones,
|
|
98
|
+
configura el provider una vez:
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from pydantic_ai import Agent
|
|
102
|
+
from pydantic_ai.models.openai import OpenAIResponsesModel
|
|
103
|
+
from pydantic_ai.providers.openai import OpenAIProvider
|
|
104
|
+
|
|
105
|
+
provider = OpenAIProvider(
|
|
106
|
+
base_url="https://example.com/v1",
|
|
107
|
+
api_key="...",
|
|
108
|
+
)
|
|
109
|
+
provider.client.max_retries = 0
|
|
110
|
+
model = OpenAIResponsesModel("gpt-5.6-luna", provider=provider)
|
|
111
|
+
agent = Agent(model)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
El context manager de `Agent` administra el transporte del provider.
|
|
115
|
+
|
|
116
|
+
## Migración desde el runtime anterior
|
|
117
|
+
|
|
118
|
+
| Antes | Ahora |
|
|
119
|
+
|---|---|
|
|
120
|
+
| `cortex_agent_sdk.Agent` | `pydantic_ai.Agent` |
|
|
121
|
+
| `OpenAIEngine` | `OpenAIResponsesModel` + `OpenAIProvider` |
|
|
122
|
+
| `OpenAICompatibleGateway` | `OpenAIProvider(base_url=..., api_key=...)` |
|
|
123
|
+
| `OpenAIOptions` | `OpenAIResponsesModelSettings` y argumentos de `Agent.run` |
|
|
124
|
+
| `@tool` e `Injected` | tools nativas + `RunContext[Deps]` |
|
|
125
|
+
| `ToolBinding` | `FunctionToolset` o tools preparadas por run |
|
|
126
|
+
| `AgentHooks` | `pydantic_ai.capabilities.Hooks` |
|
|
127
|
+
| `turn_finished` | `Hooks(after_run=...)` |
|
|
128
|
+
| `history_transform` | `Hooks(before_model_request=...)` |
|
|
129
|
+
| `fallback_answer` | política local del producto sobre `AgentRunResult` |
|
|
130
|
+
| `AgentOptions` | `UsageLimits`, settings del modelo y argumentos de `Agent` |
|
|
131
|
+
| `AgentResult.text` | `AgentRunResult.output` |
|
|
132
|
+
| `SessionStore.acquire` | `SessionStore.turn` + `Session.replace` |
|
|
133
|
+
| `agent.reset_session(id)` | `store.reset(id)` |
|
|
134
|
+
|
|
135
|
+
No se ofrece una capa de compatibilidad. Mantenerla volvería a duplicar la API y el runtime de
|
|
136
|
+
Pydantic AI.
|
|
137
|
+
|
|
138
|
+
## Superficie pública
|
|
139
|
+
|
|
140
|
+
- `cortex_agent_sdk.sessions.Session`
|
|
141
|
+
- `cortex_agent_sdk.sessions.SessionStore`
|
|
142
|
+
- `cortex_agent_sdk.sessions.MemorySessionStore`
|
|
143
|
+
- `cortex_agent_sdk.redis.RedisSessionStore`
|
|
144
|
+
- `cortex_agent_sdk.errores.AppError`
|
|
145
|
+
- `cortex_agent_sdk.errores.CodigoError`
|
|
146
|
+
- `cortex_agent_sdk.errores.Severidad`
|
|
147
|
+
|
|
148
|
+
El loop, tools, hooks, approvals, modelos y resultados se importan desde `pydantic_ai`.
|
|
149
|
+
|
|
150
|
+
## Licencia
|
|
151
|
+
|
|
152
|
+
Apache License 2.0.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "cortex-agent-sdk"
|
|
3
|
-
version = "0.
|
|
4
|
-
description = "
|
|
3
|
+
version = "0.2.0"
|
|
4
|
+
description = "Sesiones Memory y Redis para agentes construidos con Pydantic AI"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "Apache-2.0"
|
|
7
7
|
requires-python = ">=3.13"
|
|
8
8
|
authors = [{ name = "EPOK" }]
|
|
9
|
-
keywords = ["agents", "
|
|
9
|
+
keywords = ["agents", "pydantic-ai", "redis", "sessions"]
|
|
10
10
|
classifiers = [
|
|
11
11
|
"Development Status :: 3 - Alpha",
|
|
12
12
|
"Intended Audience :: Developers",
|
|
@@ -17,8 +17,7 @@ classifiers = [
|
|
|
17
17
|
"Typing :: Typed",
|
|
18
18
|
]
|
|
19
19
|
dependencies = [
|
|
20
|
-
"
|
|
21
|
-
"pydantic>=2.13,<3",
|
|
20
|
+
"pydantic-ai-slim>=2.27,<3",
|
|
22
21
|
]
|
|
23
22
|
|
|
24
23
|
[project.urls]
|
|
@@ -27,27 +26,19 @@ Issues = "https://github.com/epok200/cortex_agent_sdk/issues"
|
|
|
27
26
|
|
|
28
27
|
[project.optional-dependencies]
|
|
29
28
|
openai = [
|
|
30
|
-
"openai>=2.
|
|
31
|
-
]
|
|
32
|
-
gateway = [
|
|
33
|
-
"openai>=2.52,<3",
|
|
29
|
+
"pydantic-ai-slim[openai]>=2.27,<3",
|
|
34
30
|
]
|
|
35
31
|
all = [
|
|
36
|
-
"
|
|
37
|
-
"openai>=2.52,<3",
|
|
32
|
+
"pydantic-ai-slim[openai]>=2.27,<3",
|
|
38
33
|
"redis>=8.1.0",
|
|
39
34
|
]
|
|
40
35
|
redis = [
|
|
41
36
|
"redis>=8.1.0",
|
|
42
37
|
]
|
|
43
|
-
postgres = [
|
|
44
|
-
"asyncpg>=0.31.0",
|
|
45
|
-
]
|
|
46
38
|
|
|
47
39
|
[dependency-groups]
|
|
48
40
|
dev = [
|
|
49
|
-
"
|
|
50
|
-
"openai>=2.52,<3",
|
|
41
|
+
"pydantic-ai-slim[openai]>=2.27,<3",
|
|
51
42
|
"pyright>=1.1.408",
|
|
52
43
|
"pytest>=9.0",
|
|
53
44
|
"pytest-asyncio>=1.3",
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from enum import StrEnum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Severidad(StrEnum):
|
|
5
|
+
INFO = "INFO"
|
|
6
|
+
WARNING = "WARNING"
|
|
7
|
+
ERROR = "ERROR"
|
|
8
|
+
CRITICAL = "CRITICAL"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CodigoError(StrEnum):
|
|
12
|
+
UNKNOWN = "UNKNOWN"
|
|
13
|
+
CONFIG_INVALIDA = "CONFIG_INVALIDA"
|
|
14
|
+
RECURSO_CERRADO = "RECURSO_CERRADO"
|
|
15
|
+
SESION_OCUPADA = "SESION_OCUPADA"
|
|
16
|
+
SESION_LEASE_PERDIDO = "SESION_LEASE_PERDIDO"
|
|
17
|
+
SESION_INVALIDA = "SESION_INVALIDA"
|
|
18
|
+
SESION_STORE_FALLO = "SESION_STORE_FALLO"
|
|
@@ -2,18 +2,15 @@ from cortex_agent_sdk.errores.catalogo import CodigoError, Severidad
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class AppError(Exception):
|
|
5
|
-
"""Error
|
|
5
|
+
"""Error de Cortex con código estable."""
|
|
6
6
|
|
|
7
7
|
def __init__(
|
|
8
8
|
self,
|
|
9
9
|
codigo: CodigoError,
|
|
10
10
|
detalle: str,
|
|
11
11
|
severidad: Severidad = Severidad.ERROR,
|
|
12
|
-
mensaje_seguro: str | None = None,
|
|
13
12
|
) -> None:
|
|
14
13
|
self.codigo = codigo
|
|
15
14
|
self.detalle = detalle
|
|
16
15
|
self.severidad = severidad
|
|
17
|
-
self.mensaje_seguro = mensaje_seguro
|
|
18
16
|
super().__init__(f"[{codigo.value}] {detalle}")
|
|
19
|
-
|
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
ACQUIRE = """
|
|
2
|
-
if redis.call('
|
|
3
|
-
local token = redis.call('incr', KEYS[2])
|
|
4
|
-
redis.call('psetex', KEYS[1], ARGV[2], ARGV[1] .. ':' .. token)
|
|
5
|
-
return token
|
|
6
|
-
end
|
|
7
|
-
return 0
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
VERIFY = """
|
|
11
|
-
if redis.call('get', KEYS[1]) == ARGV[1] then
|
|
2
|
+
if redis.call('set', KEYS[1], ARGV[1], 'NX', 'PX', ARGV[2]) then
|
|
12
3
|
return 1
|
|
13
4
|
end
|
|
14
5
|
return 0
|
|
@@ -26,7 +17,7 @@ LOAD = """
|
|
|
26
17
|
if redis.call('get', KEYS[1]) ~= ARGV[1] then
|
|
27
18
|
return {0}
|
|
28
19
|
end
|
|
29
|
-
local payload = redis.call('
|
|
20
|
+
local payload = redis.call('get', KEYS[2])
|
|
30
21
|
if payload then
|
|
31
22
|
redis.call('pexpire', KEYS[2], ARGV[2])
|
|
32
23
|
return {1, payload}
|
|
@@ -38,12 +29,7 @@ SAVE = """
|
|
|
38
29
|
if redis.call('get', KEYS[1]) ~= ARGV[1] then
|
|
39
30
|
return 0
|
|
40
31
|
end
|
|
41
|
-
|
|
42
|
-
if current ~= tonumber(ARGV[2]) then
|
|
43
|
-
return -1
|
|
44
|
-
end
|
|
45
|
-
redis.call('hset', KEYS[2], 'version', ARGV[3], 'payload', ARGV[4])
|
|
46
|
-
redis.call('pexpire', KEYS[2], ARGV[5])
|
|
32
|
+
redis.call('psetex', KEYS[2], ARGV[3], ARGV[2])
|
|
47
33
|
return 1
|
|
48
34
|
"""
|
|
49
35
|
|
|
@@ -62,4 +48,3 @@ if redis.call('get', KEYS[1]) == ARGV[1] then
|
|
|
62
48
|
end
|
|
63
49
|
return 0
|
|
64
50
|
"""
|
|
65
|
-
|