cubeloop 0.14.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.
- cubeloop/__init__.py +142 -0
- cubeloop/agent/__init__.py +57 -0
- cubeloop/agent/_outcome.py +5 -0
- cubeloop/agent/_tool_cycle.py +77 -0
- cubeloop/agent/agent.py +1318 -0
- cubeloop/agent/loop.py +812 -0
- cubeloop/agent/tool_decorator.py +205 -0
- cubeloop/agent/tools.py +807 -0
- cubeloop/agent/types.py +230 -0
- cubeloop/checkpointer/__init__.py +28 -0
- cubeloop/checkpointer/base.py +124 -0
- cubeloop/checkpointer/exceptions.py +134 -0
- cubeloop/checkpointer/memory.py +253 -0
- cubeloop/checkpointer/mysql/README.md +153 -0
- cubeloop/checkpointer/mysql/__init__.py +27 -0
- cubeloop/checkpointer/mysql/alembic_helpers.py +249 -0
- cubeloop/checkpointer/mysql/checkpointer.py +861 -0
- cubeloop/checkpointer/mysql/exceptions.py +19 -0
- cubeloop/checkpointer/mysql/models.py +157 -0
- cubeloop/checkpointer/postgres/README.md +148 -0
- cubeloop/checkpointer/postgres/__init__.py +21 -0
- cubeloop/checkpointer/postgres/alembic_helpers.py +181 -0
- cubeloop/checkpointer/postgres/checkpointer.py +710 -0
- cubeloop/checkpointer/postgres/exceptions.py +17 -0
- cubeloop/checkpointer/postgres/models.py +153 -0
- cubeloop/checkpointer/sqlite.py +551 -0
- cubeloop/cli/__init__.py +1 -0
- cubeloop/cli/__main__.py +36 -0
- cubeloop/cli/trace/__init__.py +1 -0
- cubeloop/cli/trace/commands.py +208 -0
- cubeloop/cli/trace/convert.py +305 -0
- cubeloop/cli/trace/follow.py +111 -0
- cubeloop/cli/trace/loader.py +223 -0
- cubeloop/cli/trace/model.py +172 -0
- cubeloop/cli/trace/render.py +188 -0
- cubeloop/cli/trace/stats.py +89 -0
- cubeloop/deferred/__init__.py +11 -0
- cubeloop/deferred/_catalog.py +82 -0
- cubeloop/deferred/_dispatch_tool.py +75 -0
- cubeloop/deferred/_expand_tool.py +76 -0
- cubeloop/deferred/middleware.py +448 -0
- cubeloop/deferred/types.py +29 -0
- cubeloop/errors.py +733 -0
- cubeloop/hitl/__init__.py +82 -0
- cubeloop/hitl/_trace.py +34 -0
- cubeloop/hitl/ask_user.py +127 -0
- cubeloop/hitl/binding.py +26 -0
- cubeloop/hitl/channel.py +657 -0
- cubeloop/hitl/exceptions.py +73 -0
- cubeloop/hitl/middleware.py +155 -0
- cubeloop/hitl/policy.py +26 -0
- cubeloop/hitl/testing.py +66 -0
- cubeloop/hitl/types.py +58 -0
- cubeloop/mcp/__init__.py +22 -0
- cubeloop/mcp/_adapter.py +316 -0
- cubeloop/mcp/_tracing.py +432 -0
- cubeloop/mcp/http_loader.py +261 -0
- cubeloop/mcp/stdio_loader.py +117 -0
- cubeloop/mcp/types.py +129 -0
- cubeloop/middleware/__init__.py +61 -0
- cubeloop/middleware/base.py +312 -0
- cubeloop/middleware/compaction/__init__.py +415 -0
- cubeloop/middleware/compaction/boundary.py +94 -0
- cubeloop/middleware/compaction/pruner.py +72 -0
- cubeloop/middleware/compaction/state.py +40 -0
- cubeloop/middleware/compaction/summarizer.py +389 -0
- cubeloop/middleware/compaction/tokens.py +87 -0
- cubeloop/middleware/goal.py +177 -0
- cubeloop/middleware/subagents.py +342 -0
- cubeloop/middleware/todo.py +779 -0
- cubeloop/providers/__init__.py +131 -0
- cubeloop/providers/anthropic.py +749 -0
- cubeloop/providers/base.py +1060 -0
- cubeloop/providers/capability.py +279 -0
- cubeloop/providers/fallback.py +605 -0
- cubeloop/providers/faux.py +623 -0
- cubeloop/providers/images/__init__.py +35 -0
- cubeloop/providers/images/base.py +203 -0
- cubeloop/providers/images/capability.py +58 -0
- cubeloop/providers/images/faux.py +98 -0
- cubeloop/providers/images/openai_images.py +280 -0
- cubeloop/providers/images/types.py +122 -0
- cubeloop/providers/models.py +13 -0
- cubeloop/providers/openai.py +812 -0
- cubeloop/providers/openai_responses.py +708 -0
- cubeloop/providers/reasoning_profiles.py +102 -0
- cubeloop/py.typed +0 -0
- cubeloop/tracing/__init__.py +65 -0
- cubeloop/tracing/content.py +172 -0
- cubeloop/tracing/context.py +106 -0
- cubeloop/tracing/errors.py +40 -0
- cubeloop/tracing/exporters/__init__.py +31 -0
- cubeloop/tracing/exporters/jsonl.py +137 -0
- cubeloop/tracing/meter.py +413 -0
- cubeloop/tracing/recorder.py +1707 -0
- cubeloop/tracing/schema.py +200 -0
- cubeloop/tracing/tracer.py +871 -0
- cubeloop/types.py +28 -0
- cubeloop/utils/__init__.py +6 -0
- cubeloop/utils/emit.py +10 -0
- cubeloop/utils/json_parse.py +209 -0
- cubeloop-0.14.0.dist-info/METADATA +483 -0
- cubeloop-0.14.0.dist-info/RECORD +106 -0
- cubeloop-0.14.0.dist-info/WHEEL +4 -0
- cubeloop-0.14.0.dist-info/entry_points.txt +2 -0
- cubeloop-0.14.0.dist-info/licenses/LICENSE +21 -0
cubeloop/__init__.py
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""cubepi — Pythonic async-native agent framework."""
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import PackageNotFoundError, version as _pkg_version
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
__version__ = _pkg_version("cubeloop")
|
|
7
|
+
except PackageNotFoundError: # pragma: no cover — non-installed checkout
|
|
8
|
+
__version__ = "0.0.0+unknown"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
from cubeloop.agent import (
|
|
12
|
+
Agent,
|
|
13
|
+
AgentState,
|
|
14
|
+
AgentTool,
|
|
15
|
+
AgentToolResult,
|
|
16
|
+
run_agent_loop,
|
|
17
|
+
run_agent_loop_continue,
|
|
18
|
+
tool,
|
|
19
|
+
)
|
|
20
|
+
from cubeloop.middleware import Middleware, compose_middleware
|
|
21
|
+
from cubeloop.providers import (
|
|
22
|
+
AssistantMessage,
|
|
23
|
+
BaseProvider,
|
|
24
|
+
BoundModel,
|
|
25
|
+
DEFAULT_TRIGGER_ERRORS,
|
|
26
|
+
FallbackBoundModel,
|
|
27
|
+
Message,
|
|
28
|
+
MessageStream,
|
|
29
|
+
Model,
|
|
30
|
+
Provider,
|
|
31
|
+
ReasoningControl,
|
|
32
|
+
ReasoningEffort,
|
|
33
|
+
ReasoningMode,
|
|
34
|
+
ReasoningSummary,
|
|
35
|
+
StreamEvent,
|
|
36
|
+
StreamOptions,
|
|
37
|
+
TextContent,
|
|
38
|
+
ToolCall,
|
|
39
|
+
ToolDefinition,
|
|
40
|
+
ToolResultMessage,
|
|
41
|
+
UserMessage,
|
|
42
|
+
is_synthetic_message,
|
|
43
|
+
synthetic_user_message,
|
|
44
|
+
)
|
|
45
|
+
from cubeloop.errors import (
|
|
46
|
+
ContentFiltered,
|
|
47
|
+
ContextLengthExceeded,
|
|
48
|
+
ModelNotFound,
|
|
49
|
+
ProviderAuthFailed,
|
|
50
|
+
ProviderBadRequest,
|
|
51
|
+
ProviderError,
|
|
52
|
+
ProviderUnavailable,
|
|
53
|
+
RateLimited,
|
|
54
|
+
)
|
|
55
|
+
from cubeloop.providers.capability import (
|
|
56
|
+
CapabilityDescriptor,
|
|
57
|
+
CapabilityWarning,
|
|
58
|
+
PayloadPreview,
|
|
59
|
+
ReasoningCapability,
|
|
60
|
+
TemperatureSpec,
|
|
61
|
+
apply_reasoning_control,
|
|
62
|
+
lint_capability,
|
|
63
|
+
preview_payload,
|
|
64
|
+
)
|
|
65
|
+
from cubeloop.providers.images import (
|
|
66
|
+
AssistantImages,
|
|
67
|
+
BaseImagesProvider,
|
|
68
|
+
ImagesAborted,
|
|
69
|
+
ImagesCapabilityDescriptor,
|
|
70
|
+
ImagesContext,
|
|
71
|
+
ImagesCost,
|
|
72
|
+
ImagesModel,
|
|
73
|
+
ImagesOptions,
|
|
74
|
+
ImagesProvider,
|
|
75
|
+
SizeSpec,
|
|
76
|
+
)
|
|
77
|
+
from cubeloop.types import JsonObject, JsonValue, StructuredObject, StructuredValue
|
|
78
|
+
|
|
79
|
+
__all__ = [
|
|
80
|
+
"__version__",
|
|
81
|
+
"Agent",
|
|
82
|
+
"AgentState",
|
|
83
|
+
"AgentTool",
|
|
84
|
+
"AgentToolResult",
|
|
85
|
+
"AssistantImages",
|
|
86
|
+
"AssistantMessage",
|
|
87
|
+
"BaseImagesProvider",
|
|
88
|
+
"BaseProvider",
|
|
89
|
+
"BoundModel",
|
|
90
|
+
"CapabilityDescriptor",
|
|
91
|
+
"ContentFiltered",
|
|
92
|
+
"ContextLengthExceeded",
|
|
93
|
+
"DEFAULT_TRIGGER_ERRORS",
|
|
94
|
+
"FallbackBoundModel",
|
|
95
|
+
"ImagesAborted",
|
|
96
|
+
"ImagesCapabilityDescriptor",
|
|
97
|
+
"ImagesContext",
|
|
98
|
+
"ImagesCost",
|
|
99
|
+
"ImagesModel",
|
|
100
|
+
"ImagesOptions",
|
|
101
|
+
"ImagesProvider",
|
|
102
|
+
"JsonObject",
|
|
103
|
+
"JsonValue",
|
|
104
|
+
"Message",
|
|
105
|
+
"MessageStream",
|
|
106
|
+
"Middleware",
|
|
107
|
+
"Model",
|
|
108
|
+
"ModelNotFound",
|
|
109
|
+
"Provider",
|
|
110
|
+
"ProviderAuthFailed",
|
|
111
|
+
"ProviderBadRequest",
|
|
112
|
+
"ProviderError",
|
|
113
|
+
"ProviderUnavailable",
|
|
114
|
+
"RateLimited",
|
|
115
|
+
"ReasoningCapability",
|
|
116
|
+
"ReasoningControl",
|
|
117
|
+
"ReasoningEffort",
|
|
118
|
+
"ReasoningMode",
|
|
119
|
+
"ReasoningSummary",
|
|
120
|
+
"SizeSpec",
|
|
121
|
+
"StreamEvent",
|
|
122
|
+
"StreamOptions",
|
|
123
|
+
"StructuredObject",
|
|
124
|
+
"StructuredValue",
|
|
125
|
+
"TemperatureSpec",
|
|
126
|
+
"TextContent",
|
|
127
|
+
"ToolCall",
|
|
128
|
+
"ToolDefinition",
|
|
129
|
+
"ToolResultMessage",
|
|
130
|
+
"UserMessage",
|
|
131
|
+
"CapabilityWarning",
|
|
132
|
+
"PayloadPreview",
|
|
133
|
+
"apply_reasoning_control",
|
|
134
|
+
"is_synthetic_message",
|
|
135
|
+
"lint_capability",
|
|
136
|
+
"preview_payload",
|
|
137
|
+
"synthetic_user_message",
|
|
138
|
+
"compose_middleware",
|
|
139
|
+
"run_agent_loop",
|
|
140
|
+
"run_agent_loop_continue",
|
|
141
|
+
"tool",
|
|
142
|
+
]
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from cubeloop.agent.agent import Agent, AgentState
|
|
2
|
+
from cubeloop.agent.loop import run_agent_loop, run_agent_loop_continue
|
|
3
|
+
from cubeloop.agent.tool_decorator import tool
|
|
4
|
+
from cubeloop.agent.tools import execute_tool_calls
|
|
5
|
+
from cubeloop.agent.types import (
|
|
6
|
+
AfterToolCallContext,
|
|
7
|
+
AfterToolCallResult,
|
|
8
|
+
AgentContext,
|
|
9
|
+
AgentEndEvent,
|
|
10
|
+
AgentEvent,
|
|
11
|
+
AgentListener,
|
|
12
|
+
AgentStartEvent,
|
|
13
|
+
AgentTool,
|
|
14
|
+
AgentToolResult,
|
|
15
|
+
BeforeToolCallContext,
|
|
16
|
+
BeforeToolCallResult,
|
|
17
|
+
MessageEndEvent,
|
|
18
|
+
MessageStartEvent,
|
|
19
|
+
MessageUpdateEvent,
|
|
20
|
+
ShouldStopAfterTurnContext,
|
|
21
|
+
ToolExecutionEndEvent,
|
|
22
|
+
ToolExecutionStartEvent,
|
|
23
|
+
ToolExecutionUpdateEvent,
|
|
24
|
+
TurnEndEvent,
|
|
25
|
+
TurnStartEvent,
|
|
26
|
+
)
|
|
27
|
+
from cubeloop.utils import emit_event
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
"Agent",
|
|
31
|
+
"AgentState",
|
|
32
|
+
"run_agent_loop",
|
|
33
|
+
"run_agent_loop_continue",
|
|
34
|
+
"execute_tool_calls",
|
|
35
|
+
"AfterToolCallContext",
|
|
36
|
+
"AfterToolCallResult",
|
|
37
|
+
"AgentContext",
|
|
38
|
+
"AgentEndEvent",
|
|
39
|
+
"AgentEvent",
|
|
40
|
+
"AgentListener",
|
|
41
|
+
"AgentStartEvent",
|
|
42
|
+
"AgentTool",
|
|
43
|
+
"AgentToolResult",
|
|
44
|
+
"BeforeToolCallContext",
|
|
45
|
+
"BeforeToolCallResult",
|
|
46
|
+
"MessageEndEvent",
|
|
47
|
+
"MessageStartEvent",
|
|
48
|
+
"MessageUpdateEvent",
|
|
49
|
+
"ShouldStopAfterTurnContext",
|
|
50
|
+
"ToolExecutionEndEvent",
|
|
51
|
+
"ToolExecutionStartEvent",
|
|
52
|
+
"ToolExecutionUpdateEvent",
|
|
53
|
+
"TurnEndEvent",
|
|
54
|
+
"TurnStartEvent",
|
|
55
|
+
"emit_event",
|
|
56
|
+
"tool",
|
|
57
|
+
]
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Pre-completion tool-cycle invariant — spec §3.6.2.
|
|
2
|
+
|
|
3
|
+
For each AssistantMessage with ToolCall blocks {c1..cK}, the K-message
|
|
4
|
+
window immediately following MUST be all ToolResultMessages whose
|
|
5
|
+
tool_call_id MULTISET equals {c1..cK} — no extras, no missing, no
|
|
6
|
+
duplicates beyond what the assistant emitted, and no other
|
|
7
|
+
AssistantMessage or UserMessage may appear in that window.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from collections import Counter
|
|
13
|
+
|
|
14
|
+
from cubeloop.providers.base import (
|
|
15
|
+
AssistantMessage,
|
|
16
|
+
Message,
|
|
17
|
+
ToolCall,
|
|
18
|
+
ToolResultMessage,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ToolCycleViolation(ValueError):
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
*,
|
|
26
|
+
kind: str,
|
|
27
|
+
assistant_index: int,
|
|
28
|
+
expected: Counter,
|
|
29
|
+
got: Counter,
|
|
30
|
+
) -> None:
|
|
31
|
+
super().__init__(
|
|
32
|
+
f"tool-cycle violation [{kind}] at assistant index "
|
|
33
|
+
f"{assistant_index}: expected {dict(expected)}, "
|
|
34
|
+
f"got {dict(got)}"
|
|
35
|
+
)
|
|
36
|
+
self.kind = kind
|
|
37
|
+
self.assistant_index = assistant_index
|
|
38
|
+
self.expected = expected
|
|
39
|
+
self.got = got
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def check_tool_cycle(messages: list[Message]) -> None:
|
|
43
|
+
for i, m in enumerate(messages):
|
|
44
|
+
if not isinstance(m, AssistantMessage):
|
|
45
|
+
continue
|
|
46
|
+
call_ids = [c.id for c in m.content if isinstance(c, ToolCall)]
|
|
47
|
+
if not call_ids:
|
|
48
|
+
continue
|
|
49
|
+
expected = Counter(call_ids)
|
|
50
|
+
k = len(call_ids)
|
|
51
|
+
window = messages[i + 1 : i + 1 + k]
|
|
52
|
+
if len(window) < k:
|
|
53
|
+
raise ToolCycleViolation(
|
|
54
|
+
kind="incomplete-window",
|
|
55
|
+
assistant_index=i,
|
|
56
|
+
expected=expected,
|
|
57
|
+
got=Counter(),
|
|
58
|
+
)
|
|
59
|
+
for w in window:
|
|
60
|
+
if not isinstance(w, ToolResultMessage):
|
|
61
|
+
raise ToolCycleViolation(
|
|
62
|
+
kind="non-tool-result-in-window",
|
|
63
|
+
assistant_index=i,
|
|
64
|
+
expected=expected,
|
|
65
|
+
got=Counter(),
|
|
66
|
+
)
|
|
67
|
+
got = Counter(
|
|
68
|
+
w.tool_call_id for w in window if isinstance(w, ToolResultMessage)
|
|
69
|
+
)
|
|
70
|
+
# Multiset equality — catches duplicates the spec rejects.
|
|
71
|
+
if got != expected:
|
|
72
|
+
raise ToolCycleViolation(
|
|
73
|
+
kind="multiset-mismatch",
|
|
74
|
+
assistant_index=i,
|
|
75
|
+
expected=expected,
|
|
76
|
+
got=got,
|
|
77
|
+
)
|