monkeybot 2.1.1__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.
- monkeybot/__init__.py +3 -0
- monkeybot/cli/__init__.py +3 -0
- monkeybot/cli/__main__.py +8 -0
- monkeybot/cli/audio_io.py +8 -0
- monkeybot/cli/gateway_manager.py +17 -0
- monkeybot/cli/main.py +22 -0
- monkeybot/cli/push_to_talk.py +12 -0
- monkeybot/cli/realtime_client.py +13 -0
- monkeybot/core/__init__.py +19 -0
- monkeybot/core/attachments/__init__.py +22 -0
- monkeybot/core/attachments/catalog.py +62 -0
- monkeybot/core/attachments/config.py +52 -0
- monkeybot/core/attachments/freeze.py +158 -0
- monkeybot/core/attachments/resolve.py +70 -0
- monkeybot/core/attachments/store.py +180 -0
- monkeybot/core/attachments/text.py +72 -0
- monkeybot/core/attachments/tools.py +54 -0
- monkeybot/core/bootstrap.py +242 -0
- monkeybot/core/config/__init__.py +71 -0
- monkeybot/core/config/realtime_config.py +150 -0
- monkeybot/core/config/runtime_env.py +262 -0
- monkeybot/core/config/settings.py +341 -0
- monkeybot/core/config/validation.py +249 -0
- monkeybot/core/config/yaml_loader.py +45 -0
- monkeybot/core/context/__init__.py +781 -0
- monkeybot/core/context/campaign_context.py +8 -0
- monkeybot/core/context/common.py +14 -0
- monkeybot/core/context/curator.py +255 -0
- monkeybot/core/context/epoch.py +226 -0
- monkeybot/core/context/memory_prompt.py +222 -0
- monkeybot/core/context/tool_output_policy.py +270 -0
- monkeybot/core/context/tool_result_ingress.py +290 -0
- monkeybot/core/context/tool_shapers.py +361 -0
- monkeybot/core/hooks/__init__.py +261 -0
- monkeybot/core/llm/__init__.py +4 -0
- monkeybot/core/llm/provider.py +296 -0
- monkeybot/core/llm/realtime_provider.py +203 -0
- monkeybot/core/llm/usage.py +57 -0
- monkeybot/core/logging_utils.py +24 -0
- monkeybot/core/mcp/__init__.py +1 -0
- monkeybot/core/mcp/mcp_client.py +1215 -0
- monkeybot/core/mcp/ports_mcp.py +109 -0
- monkeybot/core/memory/__init__.py +24 -0
- monkeybot/core/memory/hook.py +413 -0
- monkeybot/core/memory/index_format.py +104 -0
- monkeybot/core/memory/integrity.py +180 -0
- monkeybot/core/memory/organizer.py +270 -0
- monkeybot/core/memory/storage_ops.py +139 -0
- monkeybot/core/memory/subsystem.py +91 -0
- monkeybot/core/messages/__init__.py +16 -0
- monkeybot/core/messages/convert_provider.py +41 -0
- monkeybot/core/messages/tool_integrity.py +262 -0
- monkeybot/core/messages/transform_context.py +84 -0
- monkeybot/core/path_safety.py +11 -0
- monkeybot/core/persistence/__init__.py +17 -0
- monkeybot/core/persistence/backends.py +236 -0
- monkeybot/core/persistence/db.py +28 -0
- monkeybot/core/persistence/durable_runs.py +286 -0
- monkeybot/core/persistence/firestore.py +658 -0
- monkeybot/core/persistence/firestore_scheduled_loops.py +336 -0
- monkeybot/core/persistence/history.py +156 -0
- monkeybot/core/persistence/postgres.py +895 -0
- monkeybot/core/persistence/runs.py +76 -0
- monkeybot/core/persistence/scheduled_loops.py +435 -0
- monkeybot/core/persistence/session_turn_locks.py +94 -0
- monkeybot/core/persistence/sqlite.py +218 -0
- monkeybot/core/persistence/sqlite_backend.py +74 -0
- monkeybot/core/persistence/thread_summary.py +61 -0
- monkeybot/core/persistence/transcript.py +194 -0
- monkeybot/core/persistence/usage.py +149 -0
- monkeybot/core/prompts/__init__.py +1 -0
- monkeybot/core/prompts/harness_prompt.py +197 -0
- monkeybot/core/prompts/prompt.py +215 -0
- monkeybot/core/runtime/__init__.py +1 -0
- monkeybot/core/runtime/context_budget.py +267 -0
- monkeybot/core/runtime/events.py +819 -0
- monkeybot/core/runtime/input_admission.py +154 -0
- monkeybot/core/runtime/loop.py +2374 -0
- monkeybot/core/runtime/provider_stream_mapper.py +159 -0
- monkeybot/core/runtime/realtime_loop.py +654 -0
- monkeybot/core/runtime/utterance_buffer.py +179 -0
- monkeybot/core/subagents/__init__.py +1 -0
- monkeybot/core/subagents/subagent_proto.py +331 -0
- monkeybot/core/subagents/subagent_worker.py +441 -0
- monkeybot/core/subagents/worker_pool.py +403 -0
- monkeybot/core/testing/__init__.py +1 -0
- monkeybot/core/testing/mocks_provider.py +86 -0
- monkeybot/core/testing/mocks_realtime_provider.py +137 -0
- monkeybot/core/tools/__init__.py +1 -0
- monkeybot/core/tools/core_tool_executor.py +1548 -0
- monkeybot/core/tools/inspector.py +226 -0
- monkeybot/core/tools/loop_inspector.py +45 -0
- monkeybot/core/tools/patch.py +480 -0
- monkeybot/core/tools/permission.py +284 -0
- monkeybot/core/tools/sandbox_executor.py +255 -0
- monkeybot/core/tools/spill_inventory.py +35 -0
- monkeybot/core/tools/terminal.py +381 -0
- monkeybot/core/tools/text_normalize.py +25 -0
- monkeybot/core/tools/types.py +33 -0
- monkeybot/core/tools/workspace_service.py +710 -0
- monkeybot/core/tools/workspace_tools.py +116 -0
- monkeybot/core/types/__init__.py +1 -0
- monkeybot/core/types/content_blocks.py +644 -0
- monkeybot/core/types/interfaces.py +156 -0
- monkeybot/core/types/types_tools.py +29 -0
- monkeybot/core/workspace/__init__.py +8 -0
- monkeybot/core/workspace/factory.py +45 -0
- monkeybot/core/workspace/gcs.py +130 -0
- monkeybot/core/workspace/local.py +162 -0
- monkeybot/core/workspace/protocol.py +45 -0
- monkeybot/core/workspace/s3.py +151 -0
- monkeybot/core/workspace_layout.py +27 -0
- monkeybot/gateway/__init__.py +1 -0
- monkeybot/gateway/bootstrap.py +18 -0
- monkeybot/gateway/main.py +47 -0
- monkeybot/gateway/realtime/__init__.py +31 -0
- monkeybot/gateway/realtime/app.py +321 -0
- monkeybot/gateway/realtime/deps.py +52 -0
- monkeybot/gateway/realtime/errors.py +81 -0
- monkeybot/gateway/realtime/guardrails.py +88 -0
- monkeybot/gateway/realtime/manager.py +77 -0
- monkeybot/gateway/realtime/metrics.py +144 -0
- monkeybot/gateway/realtime/routes.py +864 -0
- monkeybot/gateway/realtime/session.py +232 -0
- monkeybot/gateway/realtime/wire.py +412 -0
- monkeybot/gateway/realtime_main.py +49 -0
- monkeybot/gateway/sse/__init__.py +1 -0
- monkeybot/gateway/sse/app.py +733 -0
- monkeybot/gateway/sse/loop_port.py +31 -0
- monkeybot/gateway/sse/models.py +177 -0
- monkeybot/gateway/sse/reply_body.py +91 -0
- monkeybot/gateway/sse/routes.py +1101 -0
- monkeybot/gateway/sse/scheduler_routes.py +200 -0
- monkeybot/gateway/sse/scheduler_wiring.py +96 -0
- monkeybot/gateway/sse/session_bus.py +226 -0
- monkeybot/gateway/sse/sse.py +46 -0
- monkeybot/gateway/sse/workspace_layout.py +7 -0
- monkeybot/observability/__init__.py +220 -0
- monkeybot/observability/_state.py +10 -0
- monkeybot/observability/instrumentation.py +153 -0
- monkeybot/observability/propagation.py +65 -0
- monkeybot/observability/spans.py +455 -0
- monkeybot/providers/__init__.py +19 -0
- monkeybot/providers/_openai_compat.py +450 -0
- monkeybot/providers/_utils.py +473 -0
- monkeybot/providers/bedrock.py +145 -0
- monkeybot/providers/claude.py +125 -0
- monkeybot/providers/gemini.py +677 -0
- monkeybot/providers/gemini_live.py +398 -0
- monkeybot/providers/huggingface.py +129 -0
- monkeybot/providers/nvidia.py +104 -0
- monkeybot/providers/ollama.py +152 -0
- monkeybot/providers/openai.py +127 -0
- monkeybot/providers/pricing.py +60 -0
- monkeybot/providers/sampling.py +44 -0
- monkeybot/providers/vertex_claude.py +148 -0
- monkeybot/scaffold/__init__.py +33 -0
- monkeybot/scheduler/__init__.py +13 -0
- monkeybot/scheduler/__main__.py +4 -0
- monkeybot/scheduler/engine.py +333 -0
- monkeybot/scheduler/http_invoker.py +61 -0
- monkeybot/scheduler/interval.py +77 -0
- monkeybot/scheduler/tick_result.py +34 -0
- monkeybot/scheduler/worker.py +87 -0
- monkeybot/subagents/__init__.py +1 -0
- monkeybot/subagents/worker/__init__.py +1 -0
- monkeybot/subagents/worker/__main__.py +22 -0
- monkeybot/web_search/__init__.py +82 -0
- monkeybot/web_search/backends/__init__.py +5 -0
- monkeybot/web_search/backends/duckduckgo.py +32 -0
- monkeybot/web_search/backends/firecrawl.py +43 -0
- monkeybot/web_search/backends/tavily.py +45 -0
- monkeybot/web_search/protocol.py +25 -0
- monkeybot/web_search/tool.py +56 -0
- monkeybot-2.1.1.dist-info/METADATA +318 -0
- monkeybot-2.1.1.dist-info/RECORD +178 -0
- monkeybot-2.1.1.dist-info/WHEEL +4 -0
- monkeybot-2.1.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""Steer and follow-up input queues for mid-turn and idle admission.
|
|
2
|
+
|
|
3
|
+
Two queues, intentionally separate from HITL ``ToolConfirmationRequest``:
|
|
4
|
+
|
|
5
|
+
* **Steer** — inject user text at the next safe loop boundary (after the current
|
|
6
|
+
tool batch / before the next provider call) while a turn is in flight.
|
|
7
|
+
* **Follow-up** — FIFO prompts drained when the session would otherwise go idle
|
|
8
|
+
(after ``TurnComplete`` / lock release).
|
|
9
|
+
|
|
10
|
+
Gateway routes enqueue; the agent loop and gateway drain.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
from collections import deque
|
|
17
|
+
from dataclasses import dataclass
|
|
18
|
+
|
|
19
|
+
from monkeybot.core.types.content_blocks import ContentBlock, Text
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class AdmissionQueueFullError(Exception):
|
|
23
|
+
"""Raised when a steer or follow-up queue is at capacity."""
|
|
24
|
+
|
|
25
|
+
def __init__(self, queue: str, max_size: int) -> None:
|
|
26
|
+
super().__init__(f"{queue} queue is full (max {max_size})")
|
|
27
|
+
self.queue = queue
|
|
28
|
+
self.max_size = max_size
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _queue_limit(env_name: str, default: int) -> int:
|
|
32
|
+
raw = os.environ.get(env_name)
|
|
33
|
+
if raw is None or raw.strip() == "":
|
|
34
|
+
return default
|
|
35
|
+
try:
|
|
36
|
+
return max(1, int(raw))
|
|
37
|
+
except ValueError:
|
|
38
|
+
return default
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass(frozen=True)
|
|
42
|
+
class FollowUpItem:
|
|
43
|
+
"""One queued prompt waiting for an idle session.
|
|
44
|
+
|
|
45
|
+
``first_lock_fail_at_ms`` is set when a drain attempt fails to acquire the
|
|
46
|
+
durable session turn lock; used to bound how long we retry before dropping.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
request_id: str
|
|
50
|
+
content: list[ContentBlock]
|
|
51
|
+
first_lock_fail_at_ms: int | None = None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class InputAdmission:
|
|
55
|
+
"""Per-session steer + follow-up queues."""
|
|
56
|
+
|
|
57
|
+
def __init__(
|
|
58
|
+
self,
|
|
59
|
+
*,
|
|
60
|
+
max_steer: int | None = None,
|
|
61
|
+
max_follow_up: int | None = None,
|
|
62
|
+
) -> None:
|
|
63
|
+
self.max_steer = (
|
|
64
|
+
max_steer
|
|
65
|
+
if max_steer is not None
|
|
66
|
+
else _queue_limit("MONKEYBOT_STEER_QUEUE_MAX", 8)
|
|
67
|
+
)
|
|
68
|
+
self.max_follow_up = (
|
|
69
|
+
max_follow_up
|
|
70
|
+
if max_follow_up is not None
|
|
71
|
+
else _queue_limit("MONKEYBOT_FOLLOW_UP_QUEUE_MAX", 16)
|
|
72
|
+
)
|
|
73
|
+
self._steer: deque[list[ContentBlock]] = deque()
|
|
74
|
+
self._follow_up: deque[FollowUpItem] = deque()
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def steer_depth(self) -> int:
|
|
78
|
+
return len(self._steer)
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def follow_up_depth(self) -> int:
|
|
82
|
+
return len(self._follow_up)
|
|
83
|
+
|
|
84
|
+
def enqueue_steer(self, content: list[ContentBlock]) -> int:
|
|
85
|
+
"""Append steer content; return 0-based queue position.
|
|
86
|
+
|
|
87
|
+
Raises:
|
|
88
|
+
AdmissionQueueFullError: when at capacity.
|
|
89
|
+
ValueError: when ``content`` is empty.
|
|
90
|
+
"""
|
|
91
|
+
if not content:
|
|
92
|
+
raise ValueError("steer content must be non-empty")
|
|
93
|
+
if len(self._steer) >= self.max_steer:
|
|
94
|
+
raise AdmissionQueueFullError("steer", self.max_steer)
|
|
95
|
+
self._steer.append(list(content))
|
|
96
|
+
return len(self._steer) - 1
|
|
97
|
+
|
|
98
|
+
def enqueue_follow_up(
|
|
99
|
+
self, request_id: str, content: list[ContentBlock]
|
|
100
|
+
) -> int:
|
|
101
|
+
"""Append a follow-up prompt; return 0-based queue position."""
|
|
102
|
+
if not request_id.strip():
|
|
103
|
+
raise ValueError("follow-up request_id must be non-empty")
|
|
104
|
+
if not content:
|
|
105
|
+
raise ValueError("follow-up content must be non-empty")
|
|
106
|
+
if len(self._follow_up) >= self.max_follow_up:
|
|
107
|
+
raise AdmissionQueueFullError("follow_up", self.max_follow_up)
|
|
108
|
+
self._follow_up.append(FollowUpItem(request_id=request_id, content=list(content)))
|
|
109
|
+
return len(self._follow_up) - 1
|
|
110
|
+
|
|
111
|
+
def pop_steer(self) -> list[ContentBlock] | None:
|
|
112
|
+
"""Take the oldest steer message, or ``None`` if empty."""
|
|
113
|
+
if not self._steer:
|
|
114
|
+
return None
|
|
115
|
+
return self._steer.popleft()
|
|
116
|
+
|
|
117
|
+
def pop_follow_up(self) -> FollowUpItem | None:
|
|
118
|
+
"""Take the oldest follow-up, or ``None`` if empty."""
|
|
119
|
+
if not self._follow_up:
|
|
120
|
+
return None
|
|
121
|
+
return self._follow_up.popleft()
|
|
122
|
+
|
|
123
|
+
def requeue_follow_up_front(self, item: FollowUpItem) -> None:
|
|
124
|
+
"""Put a follow-up back at the front (failed lock acquire)."""
|
|
125
|
+
self._follow_up.appendleft(item)
|
|
126
|
+
|
|
127
|
+
def clear_steer(self) -> None:
|
|
128
|
+
"""Drop pending steer injections (e.g. on cancel)."""
|
|
129
|
+
self._steer.clear()
|
|
130
|
+
|
|
131
|
+
def clear_all(self) -> None:
|
|
132
|
+
"""Drop steer and follow-up queues (session teardown)."""
|
|
133
|
+
self._steer.clear()
|
|
134
|
+
self._follow_up.clear()
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def preview_text(content: list[ContentBlock], *, limit: int = 200) -> str:
|
|
138
|
+
"""Short plain-text preview for observability events."""
|
|
139
|
+
parts: list[str] = []
|
|
140
|
+
for block in content:
|
|
141
|
+
if isinstance(block, Text) and block.text.strip():
|
|
142
|
+
parts.append(block.text.strip())
|
|
143
|
+
joined = " ".join(parts).strip()
|
|
144
|
+
if len(joined) <= limit:
|
|
145
|
+
return joined
|
|
146
|
+
return joined[: limit - 1] + "…"
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
__all__ = [
|
|
150
|
+
"AdmissionQueueFullError",
|
|
151
|
+
"FollowUpItem",
|
|
152
|
+
"InputAdmission",
|
|
153
|
+
"preview_text",
|
|
154
|
+
]
|