cortex-agent-sdk 0.2.1__tar.gz → 0.3.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.1 → cortex_agent_sdk-0.3.0}/PKG-INFO +27 -9
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/README.md +25 -5
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/pyproject.toml +2 -5
- cortex_agent_sdk-0.3.0/src/cortex_agent_sdk/capabilities.py +62 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/.gitignore +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/LICENSE +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/__init__.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/errores/__init__.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/errores/catalogo.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/errores/excepcion.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/py.typed +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/redis/__init__.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/redis/scripts.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/redis/store.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/sessions/__init__.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/sessions/codec.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/sessions/memory.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/sessions/models.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/sessions/store.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cortex-agent-sdk
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: Sesiones
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Sesiones y capacidades puntuales para agentes multiprovider con Pydantic AI
|
|
5
5
|
Project-URL: Repository, https://github.com/epok200/cortex_agent_sdk
|
|
6
6
|
Project-URL: Issues, https://github.com/epok200/cortex_agent_sdk/issues
|
|
7
7
|
Author: EPOK
|
|
@@ -17,8 +17,6 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
17
17
|
Classifier: Typing :: Typed
|
|
18
18
|
Requires-Python: >=3.13
|
|
19
19
|
Requires-Dist: pydantic-ai-slim[google,openai]<3,>=2.27
|
|
20
|
-
Provides-Extra: all
|
|
21
|
-
Requires-Dist: redis>=8.1.0; extra == 'all'
|
|
22
20
|
Provides-Extra: openai
|
|
23
21
|
Provides-Extra: redis
|
|
24
22
|
Requires-Dist: redis>=8.1.0; extra == 'redis'
|
|
@@ -26,13 +24,13 @@ Description-Content-Type: text/markdown
|
|
|
26
24
|
|
|
27
25
|
# Cortex Agent SDK
|
|
28
26
|
|
|
29
|
-
Cortex agrega sesiones Memory y Redis
|
|
30
|
-
Pydantic AI.
|
|
27
|
+
Cortex agrega sesiones Memory y Redis, junto con capacidades puntuales que Pydantic AI no incluye,
|
|
28
|
+
a agentes multiprovider construidos directamente con Pydantic AI.
|
|
31
29
|
|
|
32
30
|
No implementa otro loop, otra capa de tools ni otra API de agentes. Pydantic AI conserva el control
|
|
33
31
|
de providers, modelos, tools, tipado, `RunContext`, hooks, límites, approvals, outputs, usage e
|
|
34
|
-
historial. Cortex
|
|
35
|
-
|
|
32
|
+
historial. Cortex aporta persistencia conversacional con un turno activo por sesión y capacidades
|
|
33
|
+
opcionales construidas sobre sus hooks públicos.
|
|
36
34
|
|
|
37
35
|
> Cortex Agent SDK está en alfa. La API puede cambiar antes de la versión `1.0.0`.
|
|
38
36
|
|
|
@@ -138,6 +136,25 @@ agent = Agent(model)
|
|
|
138
136
|
|
|
139
137
|
El context manager de `Agent` administra el transporte del provider.
|
|
140
138
|
|
|
139
|
+
## Fallback del resultado de una tool
|
|
140
|
+
|
|
141
|
+
Pydantic AI reintenta cuando un modelo termina sin texto. Para tools cuyo resultado ya es una
|
|
142
|
+
respuesta completa, Cortex puede reutilizar el último resultado exitoso del mismo run:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from pydantic_ai import Agent
|
|
146
|
+
|
|
147
|
+
from cortex_agent_sdk.capabilities import last_tool_result_fallback
|
|
148
|
+
|
|
149
|
+
agent = Agent(
|
|
150
|
+
"openai-responses:gpt-5.6-luna",
|
|
151
|
+
capabilities=[last_tool_result_fallback({"confirmar_agenda"})],
|
|
152
|
+
)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
La aplicación conserva la decisión sobre las tools elegibles. La capacidad no usa resultados
|
|
156
|
+
fallidos, vacíos ni pertenecientes a otro run, y no reemplaza texto o nuevas llamadas del modelo.
|
|
157
|
+
|
|
141
158
|
## Migración desde el runtime anterior
|
|
142
159
|
|
|
143
160
|
| Antes | Ahora |
|
|
@@ -151,7 +168,7 @@ El context manager de `Agent` administra el transporte del provider.
|
|
|
151
168
|
| `AgentHooks` | `pydantic_ai.capabilities.Hooks` |
|
|
152
169
|
| `turn_finished` | `Hooks(after_run=...)` |
|
|
153
170
|
| `history_transform` | `Hooks(before_model_request=...)` |
|
|
154
|
-
| `fallback_answer` |
|
|
171
|
+
| `fallback_answer` | `last_tool_result_fallback(...)` opcional |
|
|
155
172
|
| `AgentOptions` | `UsageLimits`, settings del modelo y argumentos de `Agent` |
|
|
156
173
|
| `AgentResult.text` | `AgentRunResult.output` |
|
|
157
174
|
| `SessionStore.acquire` | `SessionStore.turn` + `Session.replace` |
|
|
@@ -166,6 +183,7 @@ Pydantic AI.
|
|
|
166
183
|
- `cortex_agent_sdk.sessions.SessionStore`
|
|
167
184
|
- `cortex_agent_sdk.sessions.MemorySessionStore`
|
|
168
185
|
- `cortex_agent_sdk.redis.RedisSessionStore`
|
|
186
|
+
- `cortex_agent_sdk.capabilities.last_tool_result_fallback`
|
|
169
187
|
- `cortex_agent_sdk.errores.AppError`
|
|
170
188
|
- `cortex_agent_sdk.errores.CodigoError`
|
|
171
189
|
- `cortex_agent_sdk.errores.Severidad`
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Cortex Agent SDK
|
|
2
2
|
|
|
3
|
-
Cortex agrega sesiones Memory y Redis
|
|
4
|
-
Pydantic AI.
|
|
3
|
+
Cortex agrega sesiones Memory y Redis, junto con capacidades puntuales que Pydantic AI no incluye,
|
|
4
|
+
a agentes multiprovider construidos directamente con Pydantic AI.
|
|
5
5
|
|
|
6
6
|
No implementa otro loop, otra capa de tools ni otra API de agentes. Pydantic AI conserva el control
|
|
7
7
|
de providers, modelos, tools, tipado, `RunContext`, hooks, límites, approvals, outputs, usage e
|
|
8
|
-
historial. Cortex
|
|
9
|
-
|
|
8
|
+
historial. Cortex aporta persistencia conversacional con un turno activo por sesión y capacidades
|
|
9
|
+
opcionales construidas sobre sus hooks públicos.
|
|
10
10
|
|
|
11
11
|
> Cortex Agent SDK está en alfa. La API puede cambiar antes de la versión `1.0.0`.
|
|
12
12
|
|
|
@@ -112,6 +112,25 @@ agent = Agent(model)
|
|
|
112
112
|
|
|
113
113
|
El context manager de `Agent` administra el transporte del provider.
|
|
114
114
|
|
|
115
|
+
## Fallback del resultado de una tool
|
|
116
|
+
|
|
117
|
+
Pydantic AI reintenta cuando un modelo termina sin texto. Para tools cuyo resultado ya es una
|
|
118
|
+
respuesta completa, Cortex puede reutilizar el último resultado exitoso del mismo run:
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
from pydantic_ai import Agent
|
|
122
|
+
|
|
123
|
+
from cortex_agent_sdk.capabilities import last_tool_result_fallback
|
|
124
|
+
|
|
125
|
+
agent = Agent(
|
|
126
|
+
"openai-responses:gpt-5.6-luna",
|
|
127
|
+
capabilities=[last_tool_result_fallback({"confirmar_agenda"})],
|
|
128
|
+
)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
La aplicación conserva la decisión sobre las tools elegibles. La capacidad no usa resultados
|
|
132
|
+
fallidos, vacíos ni pertenecientes a otro run, y no reemplaza texto o nuevas llamadas del modelo.
|
|
133
|
+
|
|
115
134
|
## Migración desde el runtime anterior
|
|
116
135
|
|
|
117
136
|
| Antes | Ahora |
|
|
@@ -125,7 +144,7 @@ El context manager de `Agent` administra el transporte del provider.
|
|
|
125
144
|
| `AgentHooks` | `pydantic_ai.capabilities.Hooks` |
|
|
126
145
|
| `turn_finished` | `Hooks(after_run=...)` |
|
|
127
146
|
| `history_transform` | `Hooks(before_model_request=...)` |
|
|
128
|
-
| `fallback_answer` |
|
|
147
|
+
| `fallback_answer` | `last_tool_result_fallback(...)` opcional |
|
|
129
148
|
| `AgentOptions` | `UsageLimits`, settings del modelo y argumentos de `Agent` |
|
|
130
149
|
| `AgentResult.text` | `AgentRunResult.output` |
|
|
131
150
|
| `SessionStore.acquire` | `SessionStore.turn` + `Session.replace` |
|
|
@@ -140,6 +159,7 @@ Pydantic AI.
|
|
|
140
159
|
- `cortex_agent_sdk.sessions.SessionStore`
|
|
141
160
|
- `cortex_agent_sdk.sessions.MemorySessionStore`
|
|
142
161
|
- `cortex_agent_sdk.redis.RedisSessionStore`
|
|
162
|
+
- `cortex_agent_sdk.capabilities.last_tool_result_fallback`
|
|
143
163
|
- `cortex_agent_sdk.errores.AppError`
|
|
144
164
|
- `cortex_agent_sdk.errores.CodigoError`
|
|
145
165
|
- `cortex_agent_sdk.errores.Severidad`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "cortex-agent-sdk"
|
|
3
|
-
version = "0.
|
|
4
|
-
description = "Sesiones
|
|
3
|
+
version = "0.3.0"
|
|
4
|
+
description = "Sesiones y capacidades puntuales para agentes multiprovider con Pydantic AI"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "Apache-2.0"
|
|
7
7
|
requires-python = ">=3.13"
|
|
@@ -26,9 +26,6 @@ Issues = "https://github.com/epok200/cortex_agent_sdk/issues"
|
|
|
26
26
|
|
|
27
27
|
[project.optional-dependencies]
|
|
28
28
|
openai = []
|
|
29
|
-
all = [
|
|
30
|
-
"redis>=8.1.0",
|
|
31
|
-
]
|
|
32
29
|
redis = [
|
|
33
30
|
"redis>=8.1.0",
|
|
34
31
|
]
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Capacidades opcionales para agentes Pydantic AI."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Collection
|
|
4
|
+
from dataclasses import replace
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from pydantic_ai import ModelResponse, RunContext, TextPart
|
|
8
|
+
from pydantic_ai.capabilities.hooks import Hooks
|
|
9
|
+
from pydantic_ai.messages import ModelRequest, ToolReturnPart
|
|
10
|
+
from pydantic_ai.models import ModelRequestContext
|
|
11
|
+
|
|
12
|
+
__all__ = ["last_tool_result_fallback"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def last_tool_result_fallback(tool_names: str | Collection[str]) -> Hooks[Any]:
|
|
16
|
+
"""Usa el último resultado elegible si el modelo termina sin texto."""
|
|
17
|
+
if isinstance(tool_names, str):
|
|
18
|
+
eligible_tools = frozenset((tool_names,))
|
|
19
|
+
else:
|
|
20
|
+
eligible_tools = frozenset(tool_names)
|
|
21
|
+
|
|
22
|
+
def use_last_tool_result(
|
|
23
|
+
ctx: RunContext[Any],
|
|
24
|
+
*,
|
|
25
|
+
request_context: ModelRequestContext,
|
|
26
|
+
response: ModelResponse,
|
|
27
|
+
) -> ModelResponse:
|
|
28
|
+
if response.finish_reason not in {None, "stop"}:
|
|
29
|
+
return response
|
|
30
|
+
if response.text and response.text.strip():
|
|
31
|
+
return response
|
|
32
|
+
if response.tool_calls:
|
|
33
|
+
return response
|
|
34
|
+
|
|
35
|
+
result = _last_tool_result(request_context, ctx.run_id, eligible_tools)
|
|
36
|
+
if result is None:
|
|
37
|
+
return response
|
|
38
|
+
return replace(response, parts=[*response.parts, TextPart(result)])
|
|
39
|
+
|
|
40
|
+
return Hooks(after_model_request=use_last_tool_result)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _last_tool_result(
|
|
44
|
+
request_context: ModelRequestContext,
|
|
45
|
+
run_id: str | None,
|
|
46
|
+
tool_names: Collection[str],
|
|
47
|
+
) -> str | None:
|
|
48
|
+
if run_id is None:
|
|
49
|
+
return None
|
|
50
|
+
for message in reversed(request_context.messages):
|
|
51
|
+
if not isinstance(message, ModelRequest) or message.run_id != run_id:
|
|
52
|
+
continue
|
|
53
|
+
for part in reversed(message.parts):
|
|
54
|
+
if (
|
|
55
|
+
isinstance(part, ToolReturnPart)
|
|
56
|
+
and part.outcome == "success"
|
|
57
|
+
and part.tool_name in tool_names
|
|
58
|
+
and isinstance(part.content, str)
|
|
59
|
+
and part.content.strip()
|
|
60
|
+
):
|
|
61
|
+
return part.content
|
|
62
|
+
return None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|