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.
Files changed (106) hide show
  1. cubeloop/__init__.py +142 -0
  2. cubeloop/agent/__init__.py +57 -0
  3. cubeloop/agent/_outcome.py +5 -0
  4. cubeloop/agent/_tool_cycle.py +77 -0
  5. cubeloop/agent/agent.py +1318 -0
  6. cubeloop/agent/loop.py +812 -0
  7. cubeloop/agent/tool_decorator.py +205 -0
  8. cubeloop/agent/tools.py +807 -0
  9. cubeloop/agent/types.py +230 -0
  10. cubeloop/checkpointer/__init__.py +28 -0
  11. cubeloop/checkpointer/base.py +124 -0
  12. cubeloop/checkpointer/exceptions.py +134 -0
  13. cubeloop/checkpointer/memory.py +253 -0
  14. cubeloop/checkpointer/mysql/README.md +153 -0
  15. cubeloop/checkpointer/mysql/__init__.py +27 -0
  16. cubeloop/checkpointer/mysql/alembic_helpers.py +249 -0
  17. cubeloop/checkpointer/mysql/checkpointer.py +861 -0
  18. cubeloop/checkpointer/mysql/exceptions.py +19 -0
  19. cubeloop/checkpointer/mysql/models.py +157 -0
  20. cubeloop/checkpointer/postgres/README.md +148 -0
  21. cubeloop/checkpointer/postgres/__init__.py +21 -0
  22. cubeloop/checkpointer/postgres/alembic_helpers.py +181 -0
  23. cubeloop/checkpointer/postgres/checkpointer.py +710 -0
  24. cubeloop/checkpointer/postgres/exceptions.py +17 -0
  25. cubeloop/checkpointer/postgres/models.py +153 -0
  26. cubeloop/checkpointer/sqlite.py +551 -0
  27. cubeloop/cli/__init__.py +1 -0
  28. cubeloop/cli/__main__.py +36 -0
  29. cubeloop/cli/trace/__init__.py +1 -0
  30. cubeloop/cli/trace/commands.py +208 -0
  31. cubeloop/cli/trace/convert.py +305 -0
  32. cubeloop/cli/trace/follow.py +111 -0
  33. cubeloop/cli/trace/loader.py +223 -0
  34. cubeloop/cli/trace/model.py +172 -0
  35. cubeloop/cli/trace/render.py +188 -0
  36. cubeloop/cli/trace/stats.py +89 -0
  37. cubeloop/deferred/__init__.py +11 -0
  38. cubeloop/deferred/_catalog.py +82 -0
  39. cubeloop/deferred/_dispatch_tool.py +75 -0
  40. cubeloop/deferred/_expand_tool.py +76 -0
  41. cubeloop/deferred/middleware.py +448 -0
  42. cubeloop/deferred/types.py +29 -0
  43. cubeloop/errors.py +733 -0
  44. cubeloop/hitl/__init__.py +82 -0
  45. cubeloop/hitl/_trace.py +34 -0
  46. cubeloop/hitl/ask_user.py +127 -0
  47. cubeloop/hitl/binding.py +26 -0
  48. cubeloop/hitl/channel.py +657 -0
  49. cubeloop/hitl/exceptions.py +73 -0
  50. cubeloop/hitl/middleware.py +155 -0
  51. cubeloop/hitl/policy.py +26 -0
  52. cubeloop/hitl/testing.py +66 -0
  53. cubeloop/hitl/types.py +58 -0
  54. cubeloop/mcp/__init__.py +22 -0
  55. cubeloop/mcp/_adapter.py +316 -0
  56. cubeloop/mcp/_tracing.py +432 -0
  57. cubeloop/mcp/http_loader.py +261 -0
  58. cubeloop/mcp/stdio_loader.py +117 -0
  59. cubeloop/mcp/types.py +129 -0
  60. cubeloop/middleware/__init__.py +61 -0
  61. cubeloop/middleware/base.py +312 -0
  62. cubeloop/middleware/compaction/__init__.py +415 -0
  63. cubeloop/middleware/compaction/boundary.py +94 -0
  64. cubeloop/middleware/compaction/pruner.py +72 -0
  65. cubeloop/middleware/compaction/state.py +40 -0
  66. cubeloop/middleware/compaction/summarizer.py +389 -0
  67. cubeloop/middleware/compaction/tokens.py +87 -0
  68. cubeloop/middleware/goal.py +177 -0
  69. cubeloop/middleware/subagents.py +342 -0
  70. cubeloop/middleware/todo.py +779 -0
  71. cubeloop/providers/__init__.py +131 -0
  72. cubeloop/providers/anthropic.py +749 -0
  73. cubeloop/providers/base.py +1060 -0
  74. cubeloop/providers/capability.py +279 -0
  75. cubeloop/providers/fallback.py +605 -0
  76. cubeloop/providers/faux.py +623 -0
  77. cubeloop/providers/images/__init__.py +35 -0
  78. cubeloop/providers/images/base.py +203 -0
  79. cubeloop/providers/images/capability.py +58 -0
  80. cubeloop/providers/images/faux.py +98 -0
  81. cubeloop/providers/images/openai_images.py +280 -0
  82. cubeloop/providers/images/types.py +122 -0
  83. cubeloop/providers/models.py +13 -0
  84. cubeloop/providers/openai.py +812 -0
  85. cubeloop/providers/openai_responses.py +708 -0
  86. cubeloop/providers/reasoning_profiles.py +102 -0
  87. cubeloop/py.typed +0 -0
  88. cubeloop/tracing/__init__.py +65 -0
  89. cubeloop/tracing/content.py +172 -0
  90. cubeloop/tracing/context.py +106 -0
  91. cubeloop/tracing/errors.py +40 -0
  92. cubeloop/tracing/exporters/__init__.py +31 -0
  93. cubeloop/tracing/exporters/jsonl.py +137 -0
  94. cubeloop/tracing/meter.py +413 -0
  95. cubeloop/tracing/recorder.py +1707 -0
  96. cubeloop/tracing/schema.py +200 -0
  97. cubeloop/tracing/tracer.py +871 -0
  98. cubeloop/types.py +28 -0
  99. cubeloop/utils/__init__.py +6 -0
  100. cubeloop/utils/emit.py +10 -0
  101. cubeloop/utils/json_parse.py +209 -0
  102. cubeloop-0.14.0.dist-info/METADATA +483 -0
  103. cubeloop-0.14.0.dist-info/RECORD +106 -0
  104. cubeloop-0.14.0.dist-info/WHEEL +4 -0
  105. cubeloop-0.14.0.dist-info/entry_points.txt +2 -0
  106. 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,5 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Literal
4
+
5
+ RunOutcome = Literal["complete", "suspended", "incomplete", "abandoned"]
@@ -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
+ )