@team-agent/installer 0.2.11 → 0.3.0
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.
- package/Cargo.lock +744 -0
- package/Cargo.toml +34 -0
- package/crates/team-agent/Cargo.toml +33 -0
- package/crates/team-agent/src/cli/adapters.rs +1343 -0
- package/crates/team-agent/src/cli/diagnose.rs +554 -0
- package/crates/team-agent/src/cli/emit.rs +1077 -0
- package/crates/team-agent/src/cli/helpers.rs +88 -0
- package/crates/team-agent/src/cli/leader.rs +216 -0
- package/crates/team-agent/src/cli/mod.rs +1141 -0
- package/crates/team-agent/src/cli/profile.rs +306 -0
- package/crates/team-agent/src/cli/send.rs +215 -0
- package/crates/team-agent/src/cli/status.rs +179 -0
- package/crates/team-agent/src/cli/status_port.rs +502 -0
- package/crates/team-agent/src/cli/tests/base.rs +616 -0
- package/crates/team-agent/src/cli/tests/compile.rs +96 -0
- package/crates/team-agent/src/cli/tests/divergence.rs +509 -0
- package/crates/team-agent/src/cli/tests/lane_c.rs +333 -0
- package/crates/team-agent/src/cli/tests/leader_watch.rs +395 -0
- package/crates/team-agent/src/cli/tests/main_preserved.rs +675 -0
- package/crates/team-agent/src/cli/tests/missing_subcommands.rs +390 -0
- package/crates/team-agent/src/cli/tests/mod.rs +97 -0
- package/crates/team-agent/src/cli/tests/peer_allow.rs +137 -0
- package/crates/team-agent/src/cli/tests/repair_state_byte_lock.rs +302 -0
- package/crates/team-agent/src/cli/tests/run_delegation.rs +305 -0
- package/crates/team-agent/src/cli/tests/status_send.rs +385 -0
- package/crates/team-agent/src/cli/tests/verb_profile.rs +182 -0
- package/crates/team-agent/src/cli/tests/verb_settle.rs +236 -0
- package/crates/team-agent/src/cli/tests/verb_validate.rs +184 -0
- package/crates/team-agent/src/cli/types.rs +605 -0
- package/crates/team-agent/src/compiler/tests.rs +701 -0
- package/crates/team-agent/src/compiler.rs +489 -0
- package/crates/team-agent/src/coordinator/backoff.rs +153 -0
- package/crates/team-agent/src/coordinator/health.rs +436 -0
- package/crates/team-agent/src/coordinator/mod.rs +80 -0
- package/crates/team-agent/src/coordinator/orphan.rs +179 -0
- package/crates/team-agent/src/coordinator/tests/abnormal.rs +255 -0
- package/crates/team-agent/src/coordinator/tests/basics.rs +262 -0
- package/crates/team-agent/src/coordinator/tests/daemon.rs +323 -0
- package/crates/team-agent/src/coordinator/tests/health_sync.rs +263 -0
- package/crates/team-agent/src/coordinator/tests/main_preserved.rs +136 -0
- package/crates/team-agent/src/coordinator/tests/mod.rs +310 -0
- package/crates/team-agent/src/coordinator/tests/spine.rs +261 -0
- package/crates/team-agent/src/coordinator/tests/takeover.rs +227 -0
- package/crates/team-agent/src/coordinator/tests/tick_core.rs +256 -0
- package/crates/team-agent/src/coordinator/tests/watch.rs +167 -0
- package/crates/team-agent/src/coordinator/tick.rs +2032 -0
- package/crates/team-agent/src/coordinator/types.rs +584 -0
- package/crates/team-agent/src/db/migration.rs +716 -0
- package/crates/team-agent/src/db/mod.rs +23 -0
- package/crates/team-agent/src/db/schema.rs +378 -0
- package/crates/team-agent/src/event_log.rs +375 -0
- package/crates/team-agent/src/fake_worker.rs +253 -0
- package/crates/team-agent/src/leader/helpers.rs +190 -0
- package/crates/team-agent/src/leader/inject.rs +33 -0
- package/crates/team-agent/src/leader/lease.rs +1063 -0
- package/crates/team-agent/src/leader/mod.rs +99 -0
- package/crates/team-agent/src/leader/owner_bind.rs +292 -0
- package/crates/team-agent/src/leader/rediscover/tests.rs +525 -0
- package/crates/team-agent/src/leader/rediscover.rs +1099 -0
- package/crates/team-agent/src/leader/start.rs +273 -0
- package/crates/team-agent/src/leader/takeover.rs +235 -0
- package/crates/team-agent/src/leader/tests/basics.rs +183 -0
- package/crates/team-agent/src/leader/tests/byte_findings.rs +234 -0
- package/crates/team-agent/src/leader/tests/identity.rs +206 -0
- package/crates/team-agent/src/leader/tests/idle.rs +271 -0
- package/crates/team-agent/src/leader/tests/lease_api.rs +225 -0
- package/crates/team-agent/src/leader/tests/lease_claim.rs +253 -0
- package/crates/team-agent/src/leader/tests/mod.rs +125 -0
- package/crates/team-agent/src/leader/tests/rediscover.rs +351 -0
- package/crates/team-agent/src/leader/tests/wake_start_owner.rs +204 -0
- package/crates/team-agent/src/leader/types.rs +487 -0
- package/crates/team-agent/src/lib.rs +85 -0
- package/crates/team-agent/src/lifecycle/display.rs +228 -0
- package/crates/team-agent/src/lifecycle/helpers.rs +112 -0
- package/crates/team-agent/src/lifecycle/launch/plan.rs +227 -0
- package/crates/team-agent/src/lifecycle/launch.rs +1833 -0
- package/crates/team-agent/src/lifecycle/mod.rs +62 -0
- package/crates/team-agent/src/lifecycle/restart/agent.rs +533 -0
- package/crates/team-agent/src/lifecycle/restart/common.rs +517 -0
- package/crates/team-agent/src/lifecycle/restart/orchestrator.rs +41 -0
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +268 -0
- package/crates/team-agent/src/lifecycle/restart/remove.rs +780 -0
- package/crates/team-agent/src/lifecycle/restart/selection.rs +208 -0
- package/crates/team-agent/src/lifecycle/restart/team_state.rs +242 -0
- package/crates/team-agent/src/lifecycle/restart.rs +76 -0
- package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +455 -0
- package/crates/team-agent/src/lifecycle/tests/core.rs +989 -0
- package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +583 -0
- package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +933 -0
- package/crates/team-agent/src/lifecycle/tests/main_preserved.rs +265 -0
- package/crates/team-agent/src/lifecycle/tests.rs +27 -0
- package/crates/team-agent/src/lifecycle/types.rs +685 -0
- package/crates/team-agent/src/main.rs +41 -0
- package/crates/team-agent/src/mcp_server/helpers.rs +228 -0
- package/crates/team-agent/src/mcp_server/mod.rs +183 -0
- package/crates/team-agent/src/mcp_server/normalize.rs +312 -0
- package/crates/team-agent/src/mcp_server/tests/golden.rs +283 -0
- package/crates/team-agent/src/mcp_server/tests/normalize.rs +244 -0
- package/crates/team-agent/src/mcp_server/tests/scoped.rs +189 -0
- package/crates/team-agent/src/mcp_server/tests/send.rs +222 -0
- package/crates/team-agent/src/mcp_server/tests/tools.rs +158 -0
- package/crates/team-agent/src/mcp_server/tests/wire.rs +159 -0
- package/crates/team-agent/src/mcp_server/tests.rs +38 -0
- package/crates/team-agent/src/mcp_server/tools.rs +603 -0
- package/crates/team-agent/src/mcp_server/types.rs +421 -0
- package/crates/team-agent/src/mcp_server/wire.rs +388 -0
- package/crates/team-agent/src/message_store.rs +767 -0
- package/crates/team-agent/src/messaging/activity.rs +433 -0
- package/crates/team-agent/src/messaging/delivery.rs +542 -0
- package/crates/team-agent/src/messaging/helpers.rs +209 -0
- package/crates/team-agent/src/messaging/leader_receiver.rs +340 -0
- package/crates/team-agent/src/messaging/mod.rs +147 -0
- package/crates/team-agent/src/messaging/peers.rs +32 -0
- package/crates/team-agent/src/messaging/results.rs +537 -0
- package/crates/team-agent/src/messaging/scheduler.rs +344 -0
- package/crates/team-agent/src/messaging/selftest.rs +100 -0
- package/crates/team-agent/src/messaging/send.rs +582 -0
- package/crates/team-agent/src/messaging/tests/basic.rs +357 -0
- package/crates/team-agent/src/messaging/tests/main_preserved.rs +122 -0
- package/crates/team-agent/src/messaging/tests/mod.rs +293 -0
- package/crates/team-agent/src/messaging/tests/runtime.rs +1422 -0
- package/crates/team-agent/src/messaging/tests/spine.rs +437 -0
- package/crates/team-agent/src/messaging/trust.rs +192 -0
- package/crates/team-agent/src/messaging/types.rs +355 -0
- package/crates/team-agent/src/messaging/watchers.rs +591 -0
- package/crates/team-agent/src/model/enums.rs +311 -0
- package/crates/team-agent/src/model/errors.rs +17 -0
- package/crates/team-agent/src/model/ids.rs +155 -0
- package/crates/team-agent/src/model/mod.rs +22 -0
- package/crates/team-agent/src/model/paths.rs +228 -0
- package/crates/team-agent/src/model/permissions.rs +567 -0
- package/crates/team-agent/src/model/routing.rs +340 -0
- package/crates/team-agent/src/model/spec.rs +680 -0
- package/crates/team-agent/src/model/task_graph.rs +380 -0
- package/crates/team-agent/src/model/testdata/fuzz.golden.yaml +43 -0
- package/crates/team-agent/src/model/testdata/fuzz.yaml +43 -0
- package/crates/team-agent/src/model/testdata/spec_invalid_a.yaml +207 -0
- package/crates/team-agent/src/model/testdata/team.spec.golden.yaml +206 -0
- package/crates/team-agent/src/model/testdata/team.spec.yaml +206 -0
- package/crates/team-agent/src/model/yaml/tests.rs +288 -0
- package/crates/team-agent/src/model/yaml.rs +800 -0
- package/crates/team-agent/src/packaging/install.rs +305 -0
- package/crates/team-agent/src/packaging/migrate.rs +30 -0
- package/crates/team-agent/src/packaging/mod.rs +82 -0
- package/crates/team-agent/src/packaging/repair.rs +24 -0
- package/crates/team-agent/src/packaging/tests.rs +829 -0
- package/crates/team-agent/src/packaging/types.rs +369 -0
- package/crates/team-agent/src/provider/adapter.rs +801 -0
- package/crates/team-agent/src/provider/approvals/mod.rs +2 -0
- package/crates/team-agent/src/provider/approvals/parsing.rs +452 -0
- package/crates/team-agent/src/provider/approvals/runtime_prompts.rs +163 -0
- package/crates/team-agent/src/provider/classify.rs +456 -0
- package/crates/team-agent/src/provider/faults.rs +136 -0
- package/crates/team-agent/src/provider/helpers.rs +41 -0
- package/crates/team-agent/src/provider/mod.rs +53 -0
- package/crates/team-agent/src/provider/startup_prompt.rs +423 -0
- package/crates/team-agent/src/provider/tests/adapter.rs +239 -0
- package/crates/team-agent/src/provider/tests/classify.rs +240 -0
- package/crates/team-agent/src/provider/tests/faults.rs +120 -0
- package/crates/team-agent/src/provider/tests/idle.rs +208 -0
- package/crates/team-agent/src/provider/tests/wire.rs +213 -0
- package/crates/team-agent/src/provider/tests.rs +31 -0
- package/crates/team-agent/src/provider/types.rs +424 -0
- package/crates/team-agent/src/state/identity.rs +656 -0
- package/crates/team-agent/src/state/mod.rs +58 -0
- package/crates/team-agent/src/state/owner_gate.rs +423 -0
- package/crates/team-agent/src/state/persist.rs +712 -0
- package/crates/team-agent/src/state/projection.rs +657 -0
- package/crates/team-agent/src/state/selector.rs +105 -0
- package/crates/team-agent/src/state/testdata/state-rich.canonical.json +133 -0
- package/crates/team-agent/src/tmux_backend/tests.rs +586 -0
- package/crates/team-agent/src/tmux_backend.rs +758 -0
- package/crates/team-agent/src/transport/test_support.rs +252 -0
- package/crates/team-agent/src/transport/tests/behavior.rs +327 -0
- package/crates/team-agent/src/transport/tests/mod.rs +199 -0
- package/crates/team-agent/src/transport/tests/wire.rs +527 -0
- package/crates/team-agent/src/transport.rs +774 -0
- package/npm/install.mjs +90 -106
- package/package.json +15 -13
- package/crates/team-agent-core/Cargo.toml +0 -12
- package/crates/team-agent-core/src/lib.rs +0 -332
- package/crates/team-agent-core/src/main.rs +0 -152
- package/pyproject.toml +0 -18
- package/scripts/install.py +0 -88
- package/scripts/run_regression_tests.py +0 -83
- package/src/team_agent/__init__.py +0 -3
- package/src/team_agent/__main__.py +0 -5
- package/src/team_agent/_legacy_pane_discovery.py +0 -186
- package/src/team_agent/abnormal_track.py +0 -253
- package/src/team_agent/approvals/__init__.py +0 -65
- package/src/team_agent/approvals/constants.py +0 -6
- package/src/team_agent/approvals/parsing.py +0 -176
- package/src/team_agent/approvals/runtime_prompts.py +0 -171
- package/src/team_agent/approvals/status.py +0 -176
- package/src/team_agent/cli/__init__.py +0 -137
- package/src/team_agent/cli/commands.py +0 -481
- package/src/team_agent/cli/e2e.py +0 -202
- package/src/team_agent/cli/helpers.py +0 -226
- package/src/team_agent/cli/parser.py +0 -540
- package/src/team_agent/compiler.py +0 -334
- package/src/team_agent/coordinator/__init__.py +0 -53
- package/src/team_agent/coordinator/__main__.py +0 -119
- package/src/team_agent/coordinator/lifecycle.py +0 -411
- package/src/team_agent/coordinator/metadata.py +0 -61
- package/src/team_agent/coordinator/paths.py +0 -17
- package/src/team_agent/diagnose/__init__.py +0 -48
- package/src/team_agent/diagnose/checks.py +0 -101
- package/src/team_agent/diagnose/comms.py +0 -213
- package/src/team_agent/diagnose/health.py +0 -241
- package/src/team_agent/diagnose/orphan_cleanup.py +0 -364
- package/src/team_agent/diagnose/preflight.py +0 -194
- package/src/team_agent/diagnose/quick_start.py +0 -324
- package/src/team_agent/display/__init__.py +0 -92
- package/src/team_agent/display/adaptive.py +0 -511
- package/src/team_agent/display/backend.py +0 -46
- package/src/team_agent/display/close.py +0 -154
- package/src/team_agent/display/ghostty.py +0 -77
- package/src/team_agent/display/rebuild.py +0 -102
- package/src/team_agent/display/tiling.py +0 -156
- package/src/team_agent/display/worker_window.py +0 -114
- package/src/team_agent/display/workspace.py +0 -382
- package/src/team_agent/errors.py +0 -10
- package/src/team_agent/events.py +0 -84
- package/src/team_agent/fake_worker.py +0 -80
- package/src/team_agent/idle_predicate.py +0 -218
- package/src/team_agent/idle_takeover.py +0 -59
- package/src/team_agent/idle_takeover_wiring.py +0 -114
- package/src/team_agent/launch/__init__.py +0 -41
- package/src/team_agent/launch/bootstrap.py +0 -85
- package/src/team_agent/launch/config.py +0 -106
- package/src/team_agent/launch/core.py +0 -301
- package/src/team_agent/launch/requirements.py +0 -57
- package/src/team_agent/leader/__init__.py +0 -926
- package/src/team_agent/leader_binding.py +0 -183
- package/src/team_agent/lifecycle/__init__.py +0 -5
- package/src/team_agent/lifecycle/agents.py +0 -278
- package/src/team_agent/lifecycle/operations.py +0 -411
- package/src/team_agent/lifecycle/paste_buffer_hygiene.py +0 -39
- package/src/team_agent/lifecycle/start.py +0 -363
- package/src/team_agent/mcp_server/__init__.py +0 -42
- package/src/team_agent/mcp_server/__main__.py +0 -7
- package/src/team_agent/mcp_server/contracts.py +0 -148
- package/src/team_agent/mcp_server/normalize.py +0 -257
- package/src/team_agent/mcp_server/server.py +0 -150
- package/src/team_agent/mcp_server/tools.py +0 -352
- package/src/team_agent/message_store/__init__.py +0 -23
- package/src/team_agent/message_store/agent_health.py +0 -113
- package/src/team_agent/message_store/core.py +0 -497
- package/src/team_agent/message_store/leader_notification_log.py +0 -198
- package/src/team_agent/message_store/result_watchers.py +0 -251
- package/src/team_agent/message_store/schema.py +0 -308
- package/src/team_agent/message_store/schema_migration.py +0 -448
- package/src/team_agent/messaging/__init__.py +0 -1
- package/src/team_agent/messaging/activity_detector.py +0 -262
- package/src/team_agent/messaging/delivery.py +0 -504
- package/src/team_agent/messaging/deps.py +0 -247
- package/src/team_agent/messaging/idle_alerts.py +0 -423
- package/src/team_agent/messaging/internal_delivery.py +0 -46
- package/src/team_agent/messaging/leader.py +0 -497
- package/src/team_agent/messaging/leader_api_errors.py +0 -216
- package/src/team_agent/messaging/leader_panes.py +0 -673
- package/src/team_agent/messaging/owner_bypass.py +0 -29
- package/src/team_agent/messaging/result_delivery.py +0 -539
- package/src/team_agent/messaging/results.py +0 -447
- package/src/team_agent/messaging/scheduler.py +0 -450
- package/src/team_agent/messaging/send.py +0 -532
- package/src/team_agent/messaging/session_drift.py +0 -94
- package/src/team_agent/messaging/tmux_io.py +0 -506
- package/src/team_agent/messaging/tmux_prompt.py +0 -338
- package/src/team_agent/messaging/trust_auto_answer.py +0 -52
- package/src/team_agent/orchestrator/__init__.py +0 -376
- package/src/team_agent/orchestrator/plan.py +0 -122
- package/src/team_agent/orchestrator/state.py +0 -128
- package/src/team_agent/paths.py +0 -45
- package/src/team_agent/permissions.py +0 -123
- package/src/team_agent/profiles/__init__.py +0 -82
- package/src/team_agent/profiles/constants.py +0 -19
- package/src/team_agent/profiles/core.py +0 -407
- package/src/team_agent/profiles/helpers.py +0 -69
- package/src/team_agent/profiles/provider_env.py +0 -188
- package/src/team_agent/profiles/smoke.py +0 -201
- package/src/team_agent/provider_cli/__init__.py +0 -43
- package/src/team_agent/provider_cli/adapter.py +0 -172
- package/src/team_agent/provider_cli/base.py +0 -48
- package/src/team_agent/provider_cli/claude.py +0 -503
- package/src/team_agent/provider_cli/codex.py +0 -336
- package/src/team_agent/provider_cli/copilot.py +0 -8
- package/src/team_agent/provider_cli/fake.py +0 -39
- package/src/team_agent/provider_cli/gemini.py +0 -95
- package/src/team_agent/provider_cli/opencode.py +0 -8
- package/src/team_agent/provider_cli/prompt.py +0 -62
- package/src/team_agent/provider_cli/registry.py +0 -18
- package/src/team_agent/provider_cli/unsupported.py +0 -32
- package/src/team_agent/provider_state/README.md +0 -78
- package/src/team_agent/provider_state/__init__.py +0 -91
- package/src/team_agent/provider_state/claude.py +0 -86
- package/src/team_agent/provider_state/codex.py +0 -84
- package/src/team_agent/provider_state/common.py +0 -207
- package/src/team_agent/provider_state/registry.py +0 -118
- package/src/team_agent/providers.py +0 -163
- package/src/team_agent/quality_gates.py +0 -104
- package/src/team_agent/restart/__init__.py +0 -34
- package/src/team_agent/restart/orchestration.py +0 -554
- package/src/team_agent/restart/selection.py +0 -89
- package/src/team_agent/restart/snapshot.py +0 -70
- package/src/team_agent/routing.py +0 -84
- package/src/team_agent/runtime.py +0 -1243
- package/src/team_agent/rust_core.py +0 -327
- package/src/team_agent/sessions/__init__.py +0 -25
- package/src/team_agent/sessions/capture.py +0 -144
- package/src/team_agent/sessions/inventory.py +0 -44
- package/src/team_agent/sessions/resume.py +0 -135
- package/src/team_agent/simple_yaml.py +0 -236
- package/src/team_agent/spec.py +0 -370
- package/src/team_agent/state.py +0 -693
- package/src/team_agent/status/__init__.py +0 -63
- package/src/team_agent/status/approvals.py +0 -52
- package/src/team_agent/status/compact.py +0 -158
- package/src/team_agent/status/constants.py +0 -18
- package/src/team_agent/status/inbox.py +0 -58
- package/src/team_agent/status/peek.py +0 -117
- package/src/team_agent/status/queries.py +0 -199
- package/src/team_agent/task_graph.py +0 -80
- package/src/team_agent/terminal.py +0 -57
- package/src/team_agent/wake.py +0 -58
- package/src/team_agent/watch/__init__.py +0 -145
|
@@ -1,497 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import json
|
|
4
|
-
import sqlite3
|
|
5
|
-
import time
|
|
6
|
-
import uuid
|
|
7
|
-
from contextlib import closing
|
|
8
|
-
from datetime import datetime, timedelta, timezone
|
|
9
|
-
from pathlib import Path
|
|
10
|
-
from typing import Any, Callable
|
|
11
|
-
|
|
12
|
-
from . import agent_health as _agent_health
|
|
13
|
-
from . import result_watchers as _result_watchers
|
|
14
|
-
from .schema import SCHEMA_VERSION, initialize_schema, utcnow
|
|
15
|
-
from .schema_migration import MANAGED_TABLE_LAYOUTS
|
|
16
|
-
from team_agent.paths import runtime_dir
|
|
17
|
-
from team_agent.spec import validate_result_envelope
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
MESSAGE_SELECT = ", ".join(MANAGED_TABLE_LAYOUTS["messages"])
|
|
21
|
-
RESULT_SELECT = ", ".join(MANAGED_TABLE_LAYOUTS["results"])
|
|
22
|
-
SCHEDULED_EVENT_SELECT = ", ".join(MANAGED_TABLE_LAYOUTS["scheduled_events"])
|
|
23
|
-
DELIVERY_TOKEN_SELECT = ", ".join(MANAGED_TABLE_LAYOUTS["delivery_tokens"])
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def _is_sqlite_locked(exc: sqlite3.OperationalError) -> bool:
|
|
27
|
-
message = str(exc).lower()
|
|
28
|
-
return (
|
|
29
|
-
"database is locked" in message
|
|
30
|
-
or "database table is locked" in message
|
|
31
|
-
or "database schema is locked" in message
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def _with_sqlite_busy_retry(action: Callable[[], None]) -> None:
|
|
36
|
-
delay = 0.05
|
|
37
|
-
for attempt in range(6):
|
|
38
|
-
try:
|
|
39
|
-
action()
|
|
40
|
-
return
|
|
41
|
-
except sqlite3.OperationalError as exc:
|
|
42
|
-
if not _is_sqlite_locked(exc) or attempt == 5:
|
|
43
|
-
raise
|
|
44
|
-
time.sleep(delay)
|
|
45
|
-
delay *= 2
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
class MessageStore:
|
|
49
|
-
SCHEMA_VERSION = SCHEMA_VERSION
|
|
50
|
-
|
|
51
|
-
def __init__(self, workspace: Path):
|
|
52
|
-
self.workspace = workspace
|
|
53
|
-
self.path = runtime_dir(workspace) / "team.db"
|
|
54
|
-
self.path.parent.mkdir(parents=True, exist_ok=True)
|
|
55
|
-
self._init()
|
|
56
|
-
|
|
57
|
-
def connect(self) -> sqlite3.Connection:
|
|
58
|
-
conn = sqlite3.connect(self.path, timeout=30.0, isolation_level=None)
|
|
59
|
-
conn.row_factory = sqlite3.Row
|
|
60
|
-
conn.execute("PRAGMA busy_timeout=30000")
|
|
61
|
-
conn.execute("PRAGMA journal_mode=WAL")
|
|
62
|
-
return conn
|
|
63
|
-
|
|
64
|
-
def _init(self) -> None:
|
|
65
|
-
def initialize() -> None:
|
|
66
|
-
with closing(self.connect()) as conn:
|
|
67
|
-
initialize_schema(conn, self.path)
|
|
68
|
-
|
|
69
|
-
_with_sqlite_busy_retry(initialize)
|
|
70
|
-
|
|
71
|
-
def create_message(
|
|
72
|
-
self,
|
|
73
|
-
task_id: str | None,
|
|
74
|
-
sender: str,
|
|
75
|
-
recipient: str,
|
|
76
|
-
content: str,
|
|
77
|
-
reply_to: str | None = None,
|
|
78
|
-
requires_ack: bool = True,
|
|
79
|
-
artifact_refs: list[dict[str, Any]] | None = None,
|
|
80
|
-
owner_team_id: str | None = None,
|
|
81
|
-
) -> str:
|
|
82
|
-
message_id = f"msg_{uuid.uuid4().hex[:12]}"
|
|
83
|
-
now = utcnow()
|
|
84
|
-
with closing(self.connect()) as conn:
|
|
85
|
-
with conn:
|
|
86
|
-
conn.execute(
|
|
87
|
-
"""
|
|
88
|
-
insert into messages(
|
|
89
|
-
message_id, owner_team_id, task_id, sender, recipient, reply_to, requires_ack,
|
|
90
|
-
status, content, artifact_refs, created_at, updated_at,
|
|
91
|
-
delivered_at, acknowledged_at, error, delivery_attempts
|
|
92
|
-
)
|
|
93
|
-
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
94
|
-
""",
|
|
95
|
-
(
|
|
96
|
-
message_id,
|
|
97
|
-
owner_team_id,
|
|
98
|
-
task_id,
|
|
99
|
-
sender,
|
|
100
|
-
recipient,
|
|
101
|
-
reply_to,
|
|
102
|
-
int(requires_ack),
|
|
103
|
-
"accepted",
|
|
104
|
-
content,
|
|
105
|
-
json.dumps(artifact_refs or []),
|
|
106
|
-
now,
|
|
107
|
-
now,
|
|
108
|
-
None,
|
|
109
|
-
None,
|
|
110
|
-
None,
|
|
111
|
-
0,
|
|
112
|
-
),
|
|
113
|
-
)
|
|
114
|
-
return message_id
|
|
115
|
-
|
|
116
|
-
def mark(self, message_id: str, status: str, error: str | None = None) -> None:
|
|
117
|
-
now = utcnow()
|
|
118
|
-
delivered_at = now if status in {"injected", "visible", "submitted", "submitted_unverified", "delivered"} else None
|
|
119
|
-
acknowledged_at = now if status == "acknowledged" else None
|
|
120
|
-
with closing(self.connect()) as conn:
|
|
121
|
-
with conn:
|
|
122
|
-
conn.execute(
|
|
123
|
-
"""
|
|
124
|
-
update messages
|
|
125
|
-
set status = case
|
|
126
|
-
when status = 'acknowledged'
|
|
127
|
-
and ? in ('injected', 'visible', 'submitted', 'submitted_unverified', 'delivered')
|
|
128
|
-
then status
|
|
129
|
-
else ?
|
|
130
|
-
end,
|
|
131
|
-
updated_at = ?,
|
|
132
|
-
delivered_at = coalesce(?, delivered_at),
|
|
133
|
-
acknowledged_at = coalesce(?, acknowledged_at),
|
|
134
|
-
error = coalesce(?, error)
|
|
135
|
-
where message_id = ?
|
|
136
|
-
""",
|
|
137
|
-
(status, status, now, delivered_at, acknowledged_at, error, message_id),
|
|
138
|
-
)
|
|
139
|
-
if status in {
|
|
140
|
-
"injected",
|
|
141
|
-
"visible",
|
|
142
|
-
"submitted",
|
|
143
|
-
"submitted_unverified",
|
|
144
|
-
"injected_unverified",
|
|
145
|
-
"delivery_blocked",
|
|
146
|
-
"failed",
|
|
147
|
-
}:
|
|
148
|
-
conn.execute(
|
|
149
|
-
"""
|
|
150
|
-
insert into delivery_tokens(
|
|
151
|
-
message_id, unique_token, injected_at, visible_at, failed_at, failure_reason
|
|
152
|
-
)
|
|
153
|
-
values (?, ?, ?, ?, ?, ?)
|
|
154
|
-
on conflict(message_id) do update set
|
|
155
|
-
visible_at = coalesce(excluded.visible_at, delivery_tokens.visible_at),
|
|
156
|
-
failed_at = coalesce(excluded.failed_at, delivery_tokens.failed_at),
|
|
157
|
-
failure_reason = coalesce(excluded.failure_reason, delivery_tokens.failure_reason)
|
|
158
|
-
""",
|
|
159
|
-
(
|
|
160
|
-
message_id,
|
|
161
|
-
message_id,
|
|
162
|
-
now,
|
|
163
|
-
now if status in {"visible", "submitted"} else None,
|
|
164
|
-
now if status in {"failed", "injected_unverified", "delivery_blocked"} else None,
|
|
165
|
-
error if status in {"failed", "injected_unverified", "delivery_blocked"} else None,
|
|
166
|
-
),
|
|
167
|
-
)
|
|
168
|
-
if status == "acknowledged":
|
|
169
|
-
conn.execute(
|
|
170
|
-
"update delivery_tokens set consumed_at = coalesce(consumed_at, ?) where message_id = ?",
|
|
171
|
-
(now, message_id),
|
|
172
|
-
)
|
|
173
|
-
|
|
174
|
-
def defer_delivery(self, message_id: str, status: str, reason: str) -> None:
|
|
175
|
-
now = utcnow()
|
|
176
|
-
with closing(self.connect()) as conn:
|
|
177
|
-
with conn:
|
|
178
|
-
conn.execute(
|
|
179
|
-
"""
|
|
180
|
-
update messages
|
|
181
|
-
set status = ?,
|
|
182
|
-
updated_at = ?,
|
|
183
|
-
error = ?,
|
|
184
|
-
delivery_attempts = delivery_attempts + 1
|
|
185
|
-
where message_id = ?
|
|
186
|
-
""",
|
|
187
|
-
(status, now, reason, message_id),
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
def claim_for_delivery(self, message_id: str) -> bool:
|
|
191
|
-
now = utcnow()
|
|
192
|
-
with closing(self.connect()) as conn:
|
|
193
|
-
with conn:
|
|
194
|
-
result = conn.execute(
|
|
195
|
-
"""
|
|
196
|
-
update messages
|
|
197
|
-
set status = 'target_resolved',
|
|
198
|
-
updated_at = ?,
|
|
199
|
-
delivery_attempts = delivery_attempts + 1
|
|
200
|
-
where message_id = ?
|
|
201
|
-
and status in ('pending', 'accepted', 'queued_until_idle', 'queued_until_start', 'queued_stopped', 'queued_pane_missing')
|
|
202
|
-
""",
|
|
203
|
-
(now, message_id),
|
|
204
|
-
)
|
|
205
|
-
return result.rowcount == 1
|
|
206
|
-
|
|
207
|
-
def fail_timeouts(self, timeout_sec: int, exclude_recipients: set[str] | None = None) -> list[str]:
|
|
208
|
-
cutoff = datetime.now(timezone.utc) - timedelta(seconds=timeout_sec)
|
|
209
|
-
failed: list[str] = []
|
|
210
|
-
exclude_recipients = exclude_recipients or set()
|
|
211
|
-
with closing(self.connect()) as conn:
|
|
212
|
-
with conn:
|
|
213
|
-
rows = conn.execute(
|
|
214
|
-
"select message_id, recipient, updated_at from messages where requires_ack = 1 and status in ('pending','accepted','target_resolved','injected','visible','submitted','delivered')"
|
|
215
|
-
).fetchall()
|
|
216
|
-
for row in rows:
|
|
217
|
-
if row["recipient"] in exclude_recipients:
|
|
218
|
-
continue
|
|
219
|
-
try:
|
|
220
|
-
updated = datetime.fromisoformat(row["updated_at"])
|
|
221
|
-
except ValueError:
|
|
222
|
-
continue
|
|
223
|
-
if updated < cutoff:
|
|
224
|
-
failed.append(row["message_id"])
|
|
225
|
-
conn.execute(
|
|
226
|
-
"update messages set status = ?, updated_at = ?, error = ? where message_id = ?",
|
|
227
|
-
("failed", utcnow(), f"ack timeout after {timeout_sec}s", row["message_id"]),
|
|
228
|
-
)
|
|
229
|
-
return failed
|
|
230
|
-
|
|
231
|
-
def messages(self, owner_team_id: str | None = None) -> list[dict[str, Any]]:
|
|
232
|
-
with closing(self.connect()) as conn:
|
|
233
|
-
if owner_team_id is None:
|
|
234
|
-
rows = conn.execute(f"select {MESSAGE_SELECT} from messages order by created_at").fetchall()
|
|
235
|
-
else:
|
|
236
|
-
rows = conn.execute(
|
|
237
|
-
f"select {MESSAGE_SELECT} from messages where owner_team_id = ? or owner_team_id is null order by created_at",
|
|
238
|
-
(owner_team_id,),
|
|
239
|
-
).fetchall()
|
|
240
|
-
return [dict(row) for row in rows]
|
|
241
|
-
|
|
242
|
-
def inbox(self, agent_id: str, limit: int = 20, owner_team_id: str | None = None) -> list[dict[str, Any]]:
|
|
243
|
-
with closing(self.connect()) as conn:
|
|
244
|
-
if owner_team_id is None:
|
|
245
|
-
rows = conn.execute(
|
|
246
|
-
f"""
|
|
247
|
-
select {MESSAGE_SELECT} from messages
|
|
248
|
-
where sender = ? or recipient = ?
|
|
249
|
-
order by created_at desc
|
|
250
|
-
limit ?
|
|
251
|
-
""",
|
|
252
|
-
(agent_id, agent_id, limit),
|
|
253
|
-
).fetchall()
|
|
254
|
-
else:
|
|
255
|
-
rows = conn.execute(
|
|
256
|
-
f"""
|
|
257
|
-
select {MESSAGE_SELECT} from messages
|
|
258
|
-
where (sender = ? or recipient = ?)
|
|
259
|
-
and (owner_team_id = ? or owner_team_id is null)
|
|
260
|
-
order by created_at desc
|
|
261
|
-
limit ?
|
|
262
|
-
""",
|
|
263
|
-
(agent_id, agent_id, owner_team_id, limit),
|
|
264
|
-
).fetchall()
|
|
265
|
-
return [dict(row) for row in reversed(rows)]
|
|
266
|
-
|
|
267
|
-
def delivery_tokens(self) -> list[dict[str, Any]]:
|
|
268
|
-
with closing(self.connect()) as conn:
|
|
269
|
-
rows = conn.execute(f"select {DELIVERY_TOKEN_SELECT} from delivery_tokens order by injected_at").fetchall()
|
|
270
|
-
return [dict(row) for row in rows]
|
|
271
|
-
|
|
272
|
-
def add_scheduled_event(
|
|
273
|
-
self,
|
|
274
|
-
due_at: str,
|
|
275
|
-
target: str,
|
|
276
|
-
kind: str,
|
|
277
|
-
payload: dict[str, Any],
|
|
278
|
-
owner_team_id: str | None = None,
|
|
279
|
-
) -> int:
|
|
280
|
-
with closing(self.connect()) as conn:
|
|
281
|
-
with conn:
|
|
282
|
-
cur = conn.execute(
|
|
283
|
-
"""
|
|
284
|
-
insert into scheduled_events(owner_team_id, due_at, target, kind, payload_json, status, created_at)
|
|
285
|
-
values (?, ?, ?, ?, ?, 'pending', ?)
|
|
286
|
-
""",
|
|
287
|
-
(owner_team_id, due_at, target, kind, json.dumps(payload, ensure_ascii=False), utcnow()),
|
|
288
|
-
)
|
|
289
|
-
return int(cur.lastrowid)
|
|
290
|
-
|
|
291
|
-
def due_scheduled_events(self, now: str | None = None, owner_team_id: str | None = None) -> list[dict[str, Any]]:
|
|
292
|
-
with closing(self.connect()) as conn:
|
|
293
|
-
if owner_team_id is None:
|
|
294
|
-
rows = conn.execute(
|
|
295
|
-
f"""
|
|
296
|
-
select {SCHEDULED_EVENT_SELECT} from scheduled_events
|
|
297
|
-
where status = 'pending' and due_at <= ?
|
|
298
|
-
order by due_at, id
|
|
299
|
-
""",
|
|
300
|
-
(now or utcnow(),),
|
|
301
|
-
).fetchall()
|
|
302
|
-
else:
|
|
303
|
-
rows = conn.execute(
|
|
304
|
-
f"""
|
|
305
|
-
select {SCHEDULED_EVENT_SELECT} from scheduled_events
|
|
306
|
-
where status = 'pending' and due_at <= ?
|
|
307
|
-
and (owner_team_id = ? or owner_team_id is null)
|
|
308
|
-
order by due_at, id
|
|
309
|
-
""",
|
|
310
|
-
(now or utcnow(), owner_team_id),
|
|
311
|
-
).fetchall()
|
|
312
|
-
return [dict(row) for row in rows]
|
|
313
|
-
|
|
314
|
-
def mark_scheduled_event(self, event_id: int, status: str, result: dict[str, Any]) -> None:
|
|
315
|
-
with closing(self.connect()) as conn:
|
|
316
|
-
with conn:
|
|
317
|
-
conn.execute(
|
|
318
|
-
"""
|
|
319
|
-
update scheduled_events
|
|
320
|
-
set status = ?, fired_at = ?, result_json = ?
|
|
321
|
-
where id = ?
|
|
322
|
-
""",
|
|
323
|
-
(status, utcnow(), json.dumps(result, ensure_ascii=False), event_id),
|
|
324
|
-
)
|
|
325
|
-
|
|
326
|
-
def allow_peer(self, a: str, b: str) -> None:
|
|
327
|
-
now = utcnow()
|
|
328
|
-
pairs = [(a, b), (b, a)]
|
|
329
|
-
with closing(self.connect()) as conn:
|
|
330
|
-
with conn:
|
|
331
|
-
conn.executemany(
|
|
332
|
-
"insert or ignore into peer_allowlist(a, b, created_at) values (?, ?, ?)",
|
|
333
|
-
[(left, right, now) for left, right in pairs],
|
|
334
|
-
)
|
|
335
|
-
|
|
336
|
-
def peer_allowed(self, a: str, b: str) -> bool:
|
|
337
|
-
with closing(self.connect()) as conn:
|
|
338
|
-
row = conn.execute("select 1 from peer_allowlist where a = ? and b = ?", (a, b)).fetchone()
|
|
339
|
-
return row is not None
|
|
340
|
-
|
|
341
|
-
def message_counts(self) -> dict[str, int]:
|
|
342
|
-
counts: dict[str, int] = {}
|
|
343
|
-
with closing(self.connect()) as conn:
|
|
344
|
-
rows = conn.execute("select status, count(*) as n from messages group by status").fetchall()
|
|
345
|
-
for row in rows:
|
|
346
|
-
counts[row["status"]] = row["n"]
|
|
347
|
-
return counts
|
|
348
|
-
|
|
349
|
-
def result_counts(self) -> dict[str, Any]:
|
|
350
|
-
counts: dict[str, Any] = {"total": 0, "uncollected": 0, "collected": 0, "invalid": 0, "by_status": {}}
|
|
351
|
-
with closing(self.connect()) as conn:
|
|
352
|
-
rows = conn.execute("select status, count(*) as n from results group by status").fetchall()
|
|
353
|
-
for row in rows:
|
|
354
|
-
status = row["status"]
|
|
355
|
-
n = row["n"]
|
|
356
|
-
counts["total"] += n
|
|
357
|
-
if status == "collected":
|
|
358
|
-
counts["collected"] += n
|
|
359
|
-
elif status == "invalid":
|
|
360
|
-
counts["invalid"] += n
|
|
361
|
-
else:
|
|
362
|
-
counts["uncollected"] += n
|
|
363
|
-
counts["by_status"][status] = n
|
|
364
|
-
return counts
|
|
365
|
-
|
|
366
|
-
def add_result(self, envelope: dict[str, Any], owner_team_id: str | None = None) -> str:
|
|
367
|
-
validate_result_envelope(envelope)
|
|
368
|
-
result_id = f"res_{uuid.uuid4().hex[:12]}"
|
|
369
|
-
with closing(self.connect()) as conn:
|
|
370
|
-
with conn:
|
|
371
|
-
conn.execute(
|
|
372
|
-
"""
|
|
373
|
-
insert into results(owner_team_id, result_id, task_id, agent_id, envelope, status, created_at)
|
|
374
|
-
values (?, ?, ?, ?, ?, ?, ?)
|
|
375
|
-
""",
|
|
376
|
-
(
|
|
377
|
-
owner_team_id,
|
|
378
|
-
result_id,
|
|
379
|
-
envelope["task_id"],
|
|
380
|
-
envelope["agent_id"],
|
|
381
|
-
json.dumps(envelope, ensure_ascii=False),
|
|
382
|
-
envelope["status"],
|
|
383
|
-
utcnow(),
|
|
384
|
-
),
|
|
385
|
-
)
|
|
386
|
-
return result_id
|
|
387
|
-
|
|
388
|
-
def acknowledge_task_messages(self, task_id: str, agent_id: str, owner_team_id: str | None = None) -> list[str]:
|
|
389
|
-
now = utcnow()
|
|
390
|
-
owner_clause = "and (owner_team_id = ? or owner_team_id is null)" if owner_team_id else ""
|
|
391
|
-
owner_args = (owner_team_id,) if owner_team_id else ()
|
|
392
|
-
with closing(self.connect()) as conn:
|
|
393
|
-
with conn:
|
|
394
|
-
rows = conn.execute(
|
|
395
|
-
f"""
|
|
396
|
-
select message_id from messages
|
|
397
|
-
where task_id = ? and recipient = ? {owner_clause}
|
|
398
|
-
and status in ('pending', 'accepted', 'target_resolved', 'injected', 'visible', 'submitted', 'delivered')
|
|
399
|
-
""",
|
|
400
|
-
(task_id, agent_id, *owner_args),
|
|
401
|
-
).fetchall()
|
|
402
|
-
ids = [row["message_id"] for row in rows]
|
|
403
|
-
conn.execute(
|
|
404
|
-
f"""
|
|
405
|
-
update messages
|
|
406
|
-
set status = 'acknowledged', acknowledged_at = ?, updated_at = ?
|
|
407
|
-
where task_id = ? and recipient = ? {owner_clause}
|
|
408
|
-
and status in ('pending', 'accepted', 'target_resolved', 'injected', 'visible', 'submitted', 'delivered')
|
|
409
|
-
""",
|
|
410
|
-
(now, now, task_id, agent_id, *owner_args),
|
|
411
|
-
)
|
|
412
|
-
return ids
|
|
413
|
-
|
|
414
|
-
def acknowledge_message(self, message_id: str, agent_id: str, owner_team_id: str | None = None) -> list[str]:
|
|
415
|
-
now = utcnow()
|
|
416
|
-
owner_clause = "and (owner_team_id = ? or owner_team_id is null)" if owner_team_id else ""
|
|
417
|
-
owner_args = (owner_team_id,) if owner_team_id else ()
|
|
418
|
-
with closing(self.connect()) as conn:
|
|
419
|
-
with conn:
|
|
420
|
-
row = conn.execute(
|
|
421
|
-
f"""
|
|
422
|
-
select message_id from messages
|
|
423
|
-
where message_id = ? and recipient = ? {owner_clause}
|
|
424
|
-
and status in ('pending', 'accepted', 'target_resolved', 'injected', 'visible', 'submitted', 'delivered')
|
|
425
|
-
""",
|
|
426
|
-
(message_id, agent_id, *owner_args),
|
|
427
|
-
).fetchone()
|
|
428
|
-
if not row:
|
|
429
|
-
return []
|
|
430
|
-
conn.execute(
|
|
431
|
-
f"""
|
|
432
|
-
update messages
|
|
433
|
-
set status = 'acknowledged', acknowledged_at = ?, updated_at = ?
|
|
434
|
-
where message_id = ? and recipient = ? {owner_clause}
|
|
435
|
-
and status in ('pending', 'accepted', 'target_resolved', 'injected', 'visible', 'submitted', 'delivered')
|
|
436
|
-
""",
|
|
437
|
-
(now, now, message_id, agent_id, *owner_args),
|
|
438
|
-
)
|
|
439
|
-
return [message_id]
|
|
440
|
-
|
|
441
|
-
def results(self, uncollected_only: bool = False, owner_team_id: str | None = None) -> list[dict[str, Any]]:
|
|
442
|
-
_ = owner_team_id
|
|
443
|
-
clauses: list[str] = []
|
|
444
|
-
args: list[Any] = []
|
|
445
|
-
if uncollected_only:
|
|
446
|
-
clauses.append("status not in ('collected', 'invalid')")
|
|
447
|
-
where = " where " + " and ".join(clauses) if clauses else ""
|
|
448
|
-
query = f"select {RESULT_SELECT} from results{where} order by created_at"
|
|
449
|
-
with closing(self.connect()) as conn:
|
|
450
|
-
rows = conn.execute(query, args).fetchall()
|
|
451
|
-
return [dict(row) for row in rows]
|
|
452
|
-
|
|
453
|
-
def result_by_id(self, result_id: str) -> dict[str, Any] | None:
|
|
454
|
-
with closing(self.connect()) as conn:
|
|
455
|
-
row = conn.execute(f"select {RESULT_SELECT} from results where result_id = ?", (result_id,)).fetchone()
|
|
456
|
-
return dict(row) if row else None
|
|
457
|
-
|
|
458
|
-
def latest_results(self, limit: int = 5, owner_team_id: str | None = None) -> list[dict[str, Any]]:
|
|
459
|
-
owner_clause = "and owner_team_id = ?" if owner_team_id else ""
|
|
460
|
-
args: tuple[Any, ...] = (owner_team_id, limit) if owner_team_id else (limit,)
|
|
461
|
-
with closing(self.connect()) as conn:
|
|
462
|
-
rows = conn.execute(
|
|
463
|
-
f"""
|
|
464
|
-
select {RESULT_SELECT} from results
|
|
465
|
-
where status != 'invalid' {owner_clause}
|
|
466
|
-
order by created_at desc
|
|
467
|
-
limit ?
|
|
468
|
-
""",
|
|
469
|
-
args,
|
|
470
|
-
).fetchall()
|
|
471
|
-
return [dict(row) for row in reversed(rows)]
|
|
472
|
-
|
|
473
|
-
def mark_result_collected(self, result_id: str) -> None:
|
|
474
|
-
with closing(self.connect()) as conn:
|
|
475
|
-
with conn:
|
|
476
|
-
conn.execute("update results set status = 'collected' where result_id = ?", (result_id,))
|
|
477
|
-
|
|
478
|
-
def mark_result_invalid(self, result_id: str, error: str) -> None:
|
|
479
|
-
with closing(self.connect()) as conn:
|
|
480
|
-
with conn:
|
|
481
|
-
conn.execute(
|
|
482
|
-
"update results set status = 'invalid' where result_id = ?",
|
|
483
|
-
(result_id,),
|
|
484
|
-
)
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
MessageStore.upsert_agent_health = _agent_health.upsert_agent_health
|
|
489
|
-
MessageStore.agent_health = _agent_health.agent_health
|
|
490
|
-
MessageStore.delete_agent_health = _agent_health.delete_agent_health
|
|
491
|
-
MessageStore.gc_agent_health = _agent_health.gc_agent_health
|
|
492
|
-
MessageStore.create_result_watcher = _result_watchers.create_result_watcher
|
|
493
|
-
MessageStore.pending_result_watchers = _result_watchers.pending_result_watchers
|
|
494
|
-
MessageStore.retryable_result_watchers = _result_watchers.retryable_result_watchers
|
|
495
|
-
MessageStore.result_watchers = _result_watchers.result_watchers
|
|
496
|
-
MessageStore.mark_result_watcher = _result_watchers.mark_result_watcher
|
|
497
|
-
MessageStore.requeue_delivery_exhausted_watchers = _result_watchers.requeue_delivery_exhausted_watchers
|