@team-agent/installer 0.2.11 → 0.3.1
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 +1204 -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 +1207 -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 +557 -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 +1084 -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 +526 -0
- package/crates/team-agent/src/leader/rediscover.rs +1101 -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 +237 -0
- package/crates/team-agent/src/leader/tests/identity.rs +206 -0
- package/crates/team-agent/src/leader/tests/idle.rs +272 -0
- package/crates/team-agent/src/leader/tests/lease_api.rs +225 -0
- package/crates/team-agent/src/leader/tests/lease_claim.rs +410 -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 +489 -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 +2109 -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 +985 -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 +710 -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 +187 -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 +468 -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 +743 -0
- package/crates/team-agent/src/messaging/helpers.rs +209 -0
- package/crates/team-agent/src/messaging/leader_receiver.rs +329 -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 +553 -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 +578 -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 +659 -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 +765 -0
- package/crates/team-agent/src/tmux_backend.rs +810 -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 +118 -112
- 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,334 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import copy
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import Any
|
|
6
|
-
|
|
7
|
-
from team_agent.errors import ValidationError
|
|
8
|
-
from team_agent.paths import team_workspace
|
|
9
|
-
from team_agent.profiles import AUTH_MODES, known_profiles, load_profile
|
|
10
|
-
from team_agent.rust_core import contains_inline_secret, validate_profile_metadata
|
|
11
|
-
from team_agent.simple_yaml import dumps, loads
|
|
12
|
-
from team_agent.spec import SUPPORTED_PROVIDERS, validate_spec
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
REQUIRED_ROLE_FIELDS = {"name", "role", "provider", "tools"}
|
|
16
|
-
DEFAULT_PROVIDER_MODELS = {
|
|
17
|
-
"codex": "gpt-5.5",
|
|
18
|
-
"claude": "claude-sonnet-4-6",
|
|
19
|
-
"claude_code": "claude-sonnet-4-6",
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def compile_team(team_dir: Path, out_path: Path | None = None) -> dict[str, Any]:
|
|
24
|
-
team_dir = team_dir.resolve()
|
|
25
|
-
workspace = team_workspace(team_dir)
|
|
26
|
-
team_doc = team_dir / "TEAM.md"
|
|
27
|
-
agents_dir = team_dir / "agents"
|
|
28
|
-
if not team_doc.exists():
|
|
29
|
-
raise ValidationError(f"{team_doc}: missing TEAM.md")
|
|
30
|
-
if not agents_dir.exists():
|
|
31
|
-
raise ValidationError(f"{agents_dir}: missing agents directory")
|
|
32
|
-
|
|
33
|
-
profile_names = known_profiles(team_dir)
|
|
34
|
-
team_meta, team_body = _read_front_matter(team_doc)
|
|
35
|
-
default_model = team_meta.get("default_model") or team_meta.get("model")
|
|
36
|
-
provider_models = _provider_model_defaults(team_meta)
|
|
37
|
-
default_auth_mode = team_meta.get("default_auth_mode") or "subscription"
|
|
38
|
-
default_profile = team_meta.get("default_profile")
|
|
39
|
-
agents = []
|
|
40
|
-
routing_rules = []
|
|
41
|
-
startup_order = []
|
|
42
|
-
for role_doc in sorted(agents_dir.glob("*.md")):
|
|
43
|
-
meta, body = _role_doc_meta_for_team(
|
|
44
|
-
role_doc,
|
|
45
|
-
team_meta,
|
|
46
|
-
workspace,
|
|
47
|
-
team_dir,
|
|
48
|
-
profile_names,
|
|
49
|
-
default_auth_mode,
|
|
50
|
-
default_profile,
|
|
51
|
-
provider_models,
|
|
52
|
-
default_model,
|
|
53
|
-
)
|
|
54
|
-
agent_id = str(meta["name"])
|
|
55
|
-
agent = _agent_from_role_doc(meta, body, workspace, agent_id)
|
|
56
|
-
agents.append(agent)
|
|
57
|
-
routing_rules.append({"id": f"route-{agent_id}", "match": {"assignee": [agent_id]}, "assign_to": agent_id, "priority": 10})
|
|
58
|
-
startup_order.append(agent_id)
|
|
59
|
-
if not agents:
|
|
60
|
-
raise ValidationError(f"{agents_dir}: no role docs found")
|
|
61
|
-
|
|
62
|
-
default_agent = agents[0]["id"]
|
|
63
|
-
team_name = str(team_meta.get("name") or team_dir.parent.name or "team-agent-team")
|
|
64
|
-
spec = {
|
|
65
|
-
"version": 1,
|
|
66
|
-
"team": {
|
|
67
|
-
"name": team_name,
|
|
68
|
-
"mode": "supervisor_worker",
|
|
69
|
-
"objective": str(team_meta.get("objective") or team_body.strip() or "Team Agent document-driven team."),
|
|
70
|
-
"workspace": str(workspace),
|
|
71
|
-
},
|
|
72
|
-
"leader": {
|
|
73
|
-
"id": "leader",
|
|
74
|
-
"role": str(team_meta.get("leader_role") or "leader"),
|
|
75
|
-
"provider": str(team_meta.get("provider") or "codex"),
|
|
76
|
-
"model": team_meta.get("model"),
|
|
77
|
-
"tools": ["fs_read", "fs_list", "mcp_team"],
|
|
78
|
-
"context_policy": {
|
|
79
|
-
"keep_user_thread": True,
|
|
80
|
-
"receive_worker_outputs": "business_messages_and_short_summaries",
|
|
81
|
-
"max_worker_result_tokens": 2000,
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
"agents": agents,
|
|
85
|
-
"routing": {"default_assignee": default_agent, "rules": routing_rules},
|
|
86
|
-
"communication": {
|
|
87
|
-
"protocol": "mcp_inbox",
|
|
88
|
-
"topology": "leader_centered",
|
|
89
|
-
"worker_to_worker": bool(team_meta.get("worker_to_worker", True)),
|
|
90
|
-
"ack_timeout_sec": 60,
|
|
91
|
-
"result_format": "result_envelope_v1",
|
|
92
|
-
"message_store": {"sqlite": ".team/runtime/team.db", "mirror_files": ".team/messages"},
|
|
93
|
-
},
|
|
94
|
-
"runtime": {
|
|
95
|
-
"backend": "tmux",
|
|
96
|
-
"display_backend": str(team_meta.get("display_backend") or "adaptive"),
|
|
97
|
-
"session_name": str(team_meta.get("session_name") or f"team-{_slug(team_name)}"),
|
|
98
|
-
"auto_launch": True,
|
|
99
|
-
"require_user_approval_before_launch": True,
|
|
100
|
-
"max_active_agents": min(len(agents), 2),
|
|
101
|
-
"startup_order": startup_order,
|
|
102
|
-
"dangerous_auto_approve": bool(team_meta.get("dangerous_auto_approve", False)),
|
|
103
|
-
"fast": bool(team_meta.get("fast", False)),
|
|
104
|
-
"tick_interval_sec": int(team_meta.get("tick_interval_sec", 2)),
|
|
105
|
-
"push_min_interval_sec": int(team_meta.get("push_min_interval_sec", 60)),
|
|
106
|
-
"stuck_timeout_sec": int(team_meta.get("stuck_timeout_sec", 300)),
|
|
107
|
-
},
|
|
108
|
-
"context": {
|
|
109
|
-
"state_file": "team_state.md",
|
|
110
|
-
"artifact_dir": ".team/artifacts",
|
|
111
|
-
"log_dir": ".team/logs",
|
|
112
|
-
"summarization": {
|
|
113
|
-
"worker_full_logs": "retain_outside_leader_context",
|
|
114
|
-
"state_update": "after_each_result",
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
"tasks": [
|
|
118
|
-
{
|
|
119
|
-
"id": "task_initial",
|
|
120
|
-
"title": "Initial document-driven team task",
|
|
121
|
-
"type": "implementation",
|
|
122
|
-
"assignee": default_agent,
|
|
123
|
-
"deps": [],
|
|
124
|
-
"acceptance": ["Worker reports valid result_envelope_v1"],
|
|
125
|
-
"status": "pending",
|
|
126
|
-
"requires_tools": ["mcp_team"],
|
|
127
|
-
"files": [],
|
|
128
|
-
"risk": "low",
|
|
129
|
-
}
|
|
130
|
-
],
|
|
131
|
-
}
|
|
132
|
-
validate_spec(spec, base_dir=workspace)
|
|
133
|
-
if out_path:
|
|
134
|
-
out_path.write_text(dumps(spec), encoding="utf-8")
|
|
135
|
-
return {"ok": True, "team_dir": str(team_dir), "out": str(out_path) if out_path else None, "spec": spec}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
def compile_role_doc_agent(role_doc: Path, team_dir: Path, agent_id: str | None = None) -> dict[str, Any]:
|
|
139
|
-
meta, body = _read_front_matter(role_doc.resolve())
|
|
140
|
-
return compile_role_entry_agent(role_doc.resolve(), team_dir, meta, body, agent_id)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
def compile_role_entry_agent(
|
|
144
|
-
role_doc: Path,
|
|
145
|
-
team_dir: Path,
|
|
146
|
-
meta: dict[str, Any],
|
|
147
|
-
body: str,
|
|
148
|
-
agent_id: str | None = None,
|
|
149
|
-
) -> dict[str, Any]:
|
|
150
|
-
team_dir = team_dir.resolve()
|
|
151
|
-
workspace = team_workspace(team_dir)
|
|
152
|
-
team_doc = team_dir / "TEAM.md"
|
|
153
|
-
if not team_doc.exists():
|
|
154
|
-
raise ValidationError(f"{team_doc}: missing TEAM.md")
|
|
155
|
-
profile_names = known_profiles(team_dir)
|
|
156
|
-
team_meta, _team_body = _read_front_matter(team_doc)
|
|
157
|
-
meta, body = _role_doc_meta_for_team(
|
|
158
|
-
role_doc,
|
|
159
|
-
team_meta,
|
|
160
|
-
workspace,
|
|
161
|
-
team_dir,
|
|
162
|
-
profile_names,
|
|
163
|
-
team_meta.get("default_auth_mode") or "subscription",
|
|
164
|
-
team_meta.get("default_profile"),
|
|
165
|
-
_provider_model_defaults(team_meta),
|
|
166
|
-
team_meta.get("default_model") or team_meta.get("model"),
|
|
167
|
-
role_meta=meta,
|
|
168
|
-
role_body=body,
|
|
169
|
-
)
|
|
170
|
-
return _agent_from_role_doc(meta, body, workspace, str(agent_id or meta["name"]))
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
def _read_front_matter(path: Path) -> tuple[dict[str, Any], str]:
|
|
174
|
-
text = path.read_text(encoding="utf-8")
|
|
175
|
-
if not text.startswith("---\n"):
|
|
176
|
-
return {}, text
|
|
177
|
-
end = text.find("\n---", 4)
|
|
178
|
-
if end == -1:
|
|
179
|
-
raise ValidationError(f"{path}: unterminated front matter")
|
|
180
|
-
raw = text[4:end]
|
|
181
|
-
body = text[end + 4 :].lstrip("\n")
|
|
182
|
-
data = loads(raw) if raw.strip() else {}
|
|
183
|
-
if not isinstance(data, dict):
|
|
184
|
-
raise ValidationError(f"{path}: front matter must be a YAML object")
|
|
185
|
-
return data, body
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
def _role_doc_meta_for_team(
|
|
189
|
-
role_doc: Path,
|
|
190
|
-
team_meta: dict[str, Any],
|
|
191
|
-
workspace: Path,
|
|
192
|
-
team_dir: Path,
|
|
193
|
-
profile_names: set[str],
|
|
194
|
-
default_auth_mode: Any,
|
|
195
|
-
default_profile: Any,
|
|
196
|
-
provider_models: dict[str, str],
|
|
197
|
-
default_model: Any,
|
|
198
|
-
role_meta: dict[str, Any] | None = None,
|
|
199
|
-
role_body: str | None = None,
|
|
200
|
-
) -> tuple[dict[str, Any], str]:
|
|
201
|
-
meta, body = (role_meta, role_body) if role_meta is not None and role_body is not None else _read_front_matter(role_doc)
|
|
202
|
-
meta = copy.deepcopy(meta)
|
|
203
|
-
if "auth_mode" not in meta and default_auth_mode is not None:
|
|
204
|
-
meta["auth_mode"] = default_auth_mode
|
|
205
|
-
if "profile" not in meta and default_profile is not None:
|
|
206
|
-
meta["profile"] = default_profile
|
|
207
|
-
profile_model = _profile_model(workspace, meta.get("profile"), team_dir / "profiles")
|
|
208
|
-
if "model" not in meta and not (meta.get("auth_mode") == "compatible_api" and profile_model):
|
|
209
|
-
meta["model"] = _default_model_for_provider(meta.get("provider"), provider_models, default_model)
|
|
210
|
-
_validate_role_doc(role_doc, meta, body, profile_names, profile_model)
|
|
211
|
-
return meta, body
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
def _agent_from_role_doc(meta: dict[str, Any], body: str, workspace: Path, agent_id: str) -> dict[str, Any]:
|
|
215
|
-
agent = {
|
|
216
|
-
"id": agent_id,
|
|
217
|
-
"role": str(meta["role"]),
|
|
218
|
-
"provider": str(meta["provider"]),
|
|
219
|
-
"model": str(meta["model"]) if meta.get("model") is not None else None,
|
|
220
|
-
"auth_mode": str(meta["auth_mode"]),
|
|
221
|
-
"working_directory": str(workspace),
|
|
222
|
-
"system_prompt": {"inline": body.strip() or str(meta["role"]), "file": None},
|
|
223
|
-
"tools": _normalize_tools(list(meta["tools"] or [])),
|
|
224
|
-
"permission_mode": "restricted",
|
|
225
|
-
"preferred_for": [agent_id, str(meta["role"])],
|
|
226
|
-
"avoid_for": [],
|
|
227
|
-
"output_contract": {
|
|
228
|
-
"format": "result_envelope_v1",
|
|
229
|
-
"required_fields": ["task_id", "status", "summary", "artifacts"],
|
|
230
|
-
},
|
|
231
|
-
}
|
|
232
|
-
if meta.get("profile"):
|
|
233
|
-
agent["profile"] = str(meta["profile"])
|
|
234
|
-
agent["credential_ref"] = f"profile:{meta['profile']}"
|
|
235
|
-
return agent
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
def _validate_role_doc(
|
|
239
|
-
path: Path,
|
|
240
|
-
meta: dict[str, Any],
|
|
241
|
-
body: str,
|
|
242
|
-
profile_names: set[str],
|
|
243
|
-
profile_model: str | None = None,
|
|
244
|
-
) -> None:
|
|
245
|
-
errors = []
|
|
246
|
-
missing = sorted(REQUIRED_ROLE_FIELDS - set(meta))
|
|
247
|
-
for field in missing:
|
|
248
|
-
errors.append(f"{path}: missing front matter field {field}")
|
|
249
|
-
provider = meta.get("provider")
|
|
250
|
-
if provider not in SUPPORTED_PROVIDERS:
|
|
251
|
-
errors.append(f"{path}: unknown provider {provider!r}")
|
|
252
|
-
auth_mode = meta.get("auth_mode")
|
|
253
|
-
if auth_mode not in AUTH_MODES:
|
|
254
|
-
errors.append(f"{path}: unknown auth_mode {auth_mode!r}")
|
|
255
|
-
profile = meta.get("profile")
|
|
256
|
-
if profile and profile not in profile_names:
|
|
257
|
-
errors.append(f"{path}: unknown profile {profile!r}")
|
|
258
|
-
if auth_mode != "subscription" and not profile:
|
|
259
|
-
errors.append(f"{path}: profile is required when auth_mode is {auth_mode!r}")
|
|
260
|
-
role_model = str(meta.get("model") or "") or None
|
|
261
|
-
if auth_mode == "compatible_api" and role_model and profile_model and role_model != profile_model:
|
|
262
|
-
errors.append(
|
|
263
|
-
f"{path}: role model {role_model!r} does not match profile MODEL {profile_model!r}; "
|
|
264
|
-
"keep the model in one place or make both values identical"
|
|
265
|
-
)
|
|
266
|
-
if not isinstance(meta.get("tools"), list):
|
|
267
|
-
errors.append(f"{path}: tools must be a list")
|
|
268
|
-
if profile:
|
|
269
|
-
profile_check = validate_profile_metadata(
|
|
270
|
-
{
|
|
271
|
-
"provider": provider or "",
|
|
272
|
-
"model": role_model or profile_model or "",
|
|
273
|
-
"auth_mode": auth_mode or "",
|
|
274
|
-
"profile": profile or "",
|
|
275
|
-
"credential_ref": f"profile:{profile}",
|
|
276
|
-
}
|
|
277
|
-
)
|
|
278
|
-
if not profile_check.get("ok"):
|
|
279
|
-
errors.extend(f"{path}: {err}" for err in profile_check.get("errors", []))
|
|
280
|
-
for value in [body, dumps(meta)]:
|
|
281
|
-
if contains_inline_secret(value):
|
|
282
|
-
errors.append(f"{path}: probable inline secret detected; use profile/credential_ref instead")
|
|
283
|
-
break
|
|
284
|
-
if errors:
|
|
285
|
-
raise ValidationError("\n".join(errors))
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
def _normalize_tools(tools: list[Any]) -> list[str]:
|
|
289
|
-
mapping = {"shell": "execute_bash"}
|
|
290
|
-
return [mapping.get(str(tool), str(tool)) for tool in tools]
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
def _profile_model(workspace: Path, profile: Any, profiles_dir: Path | None = None) -> str | None:
|
|
294
|
-
if not profile:
|
|
295
|
-
return None
|
|
296
|
-
values = load_profile(workspace, str(profile), profiles_dir).get("values", {})
|
|
297
|
-
if not isinstance(values, dict):
|
|
298
|
-
return None
|
|
299
|
-
return values.get("MODEL") or values.get("ANTHROPIC_MODEL")
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
def _provider_model_defaults(team_meta: dict[str, Any]) -> dict[str, str]:
|
|
303
|
-
raw = team_meta.get("provider_models") or {}
|
|
304
|
-
if not isinstance(raw, dict):
|
|
305
|
-
return {}
|
|
306
|
-
return {str(provider): str(model) for provider, model in raw.items() if model}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
def _default_model_for_provider(
|
|
310
|
-
provider: Any,
|
|
311
|
-
provider_models: dict[str, str],
|
|
312
|
-
default_model: Any,
|
|
313
|
-
) -> str | None:
|
|
314
|
-
provider_id = str(provider or "")
|
|
315
|
-
if provider_id in provider_models:
|
|
316
|
-
return provider_models[provider_id]
|
|
317
|
-
if provider_id == "claude_code" and "claude" in provider_models:
|
|
318
|
-
return provider_models["claude"]
|
|
319
|
-
if provider_id == "claude" and "claude_code" in provider_models:
|
|
320
|
-
return provider_models["claude_code"]
|
|
321
|
-
if default_model is not None:
|
|
322
|
-
return str(default_model)
|
|
323
|
-
return DEFAULT_PROVIDER_MODELS.get(provider_id)
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
def _slug(value: str) -> str:
|
|
327
|
-
out = []
|
|
328
|
-
for ch in value:
|
|
329
|
-
if ch.isalnum() or ch in {"-", "_"}:
|
|
330
|
-
out.append(ch)
|
|
331
|
-
else:
|
|
332
|
-
out.append("-")
|
|
333
|
-
slug = "".join(out).strip("-_")
|
|
334
|
-
return slug or "team"
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import Any
|
|
4
|
-
|
|
5
|
-
from team_agent.coordinator.lifecycle import (
|
|
6
|
-
coordinator_health,
|
|
7
|
-
coordinator_tick,
|
|
8
|
-
message_store_schema_health,
|
|
9
|
-
start_coordinator,
|
|
10
|
-
stop_coordinator,
|
|
11
|
-
)
|
|
12
|
-
from team_agent.coordinator.metadata import (
|
|
13
|
-
COORDINATOR_PROTOCOL_VERSION,
|
|
14
|
-
coordinator_metadata_ok,
|
|
15
|
-
pid_is_running,
|
|
16
|
-
read_coordinator_metadata,
|
|
17
|
-
write_coordinator_metadata,
|
|
18
|
-
)
|
|
19
|
-
from team_agent.coordinator.paths import (
|
|
20
|
-
coordinator_log_path,
|
|
21
|
-
coordinator_meta_path,
|
|
22
|
-
coordinator_pid_path,
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
__all__ = [
|
|
26
|
-
"COORDINATOR_PROTOCOL_VERSION",
|
|
27
|
-
"coordinator_health",
|
|
28
|
-
"coordinator_log_path",
|
|
29
|
-
"coordinator_meta_path",
|
|
30
|
-
"coordinator_metadata_ok",
|
|
31
|
-
"coordinator_pid_path",
|
|
32
|
-
"coordinator_tick",
|
|
33
|
-
"main",
|
|
34
|
-
"message_store_schema_health",
|
|
35
|
-
"pid_is_running",
|
|
36
|
-
"read_coordinator_metadata",
|
|
37
|
-
"start_coordinator",
|
|
38
|
-
"stop_coordinator",
|
|
39
|
-
"write_coordinator_metadata",
|
|
40
|
-
]
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def __getattr__(name: str) -> Any:
|
|
44
|
-
# Lazy re-export of the daemon entry so the pyproject console_script
|
|
45
|
-
# `team-agent-coordinator = "team_agent.coordinator:main"` keeps
|
|
46
|
-
# resolving after the package split, without triggering the runtime
|
|
47
|
-
# <-> coordinator import cycle that an eager top-level
|
|
48
|
-
# `from team_agent.coordinator.__main__ import main` would cause
|
|
49
|
-
# (runtime imports coordinator/__init__ at module load).
|
|
50
|
-
if name == "main":
|
|
51
|
-
from team_agent.coordinator.__main__ import main as _main
|
|
52
|
-
return _main
|
|
53
|
-
raise AttributeError(f"module 'team_agent.coordinator' has no attribute {name!r}")
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import argparse
|
|
4
|
-
import os
|
|
5
|
-
import signal
|
|
6
|
-
import sys
|
|
7
|
-
import time
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
|
|
10
|
-
from team_agent import runtime
|
|
11
|
-
from team_agent.events import EventLog
|
|
12
|
-
from team_agent.message_store import MessageStore
|
|
13
|
-
from team_agent.spec import load_spec
|
|
14
|
-
from team_agent.state import load_runtime_state
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
STOP = False
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def _stop(_signum, _frame) -> None:
|
|
21
|
-
global STOP
|
|
22
|
-
STOP = True
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def main(argv: list[str] | None = None) -> None:
|
|
26
|
-
parser = argparse.ArgumentParser(description="Team Agent per-workspace coordinator daemon")
|
|
27
|
-
parser.add_argument("--workspace", required=True)
|
|
28
|
-
parser.add_argument("--once", action="store_true")
|
|
29
|
-
parser.add_argument("--tick-interval", type=float)
|
|
30
|
-
args = parser.parse_args(argv)
|
|
31
|
-
workspace = Path(args.workspace).resolve()
|
|
32
|
-
runtime.ensure_workspace_dirs(workspace)
|
|
33
|
-
runtime.coordinator_pid_path(workspace).write_text(str(os.getpid()), encoding="utf-8")
|
|
34
|
-
runtime.write_coordinator_metadata(workspace, os.getpid(), source="boot")
|
|
35
|
-
event_log = EventLog(workspace)
|
|
36
|
-
event_log.write("coordinator.boot", workspace=str(workspace), once=args.once)
|
|
37
|
-
signal.signal(signal.SIGTERM, _stop)
|
|
38
|
-
signal.signal(signal.SIGINT, _stop)
|
|
39
|
-
|
|
40
|
-
interval = args.tick_interval if args.tick_interval is not None else _tick_interval(workspace)
|
|
41
|
-
initial_ppid = os.getppid()
|
|
42
|
-
failure_count = 0
|
|
43
|
-
last_failure_signature: tuple[str, str] | None = None
|
|
44
|
-
while not STOP:
|
|
45
|
-
# Stage 14 (Gap 37b) — orphan self-detection. If our original parent (test harness,
|
|
46
|
-
# shell, or supervisor) died, our ppid is reparented to 1 (or to a launchd shim on
|
|
47
|
-
# macOS). When that happens AND the workspace no longer exists on disk, we are an
|
|
48
|
-
# orphan from a torn-down test environment and must self-terminate so we don't
|
|
49
|
-
# accumulate (today's evidence: 35 orphans pointing at /var/folders/...team-agent-
|
|
50
|
-
# watcher-dedupe-* paths long since cleaned up).
|
|
51
|
-
current_ppid = os.getppid()
|
|
52
|
-
if current_ppid != initial_ppid and current_ppid == 1 and not workspace.exists():
|
|
53
|
-
event_log.write(
|
|
54
|
-
"coordinator.orphan_self_terminate",
|
|
55
|
-
initial_ppid=initial_ppid,
|
|
56
|
-
current_ppid=current_ppid,
|
|
57
|
-
workspace=str(workspace),
|
|
58
|
-
)
|
|
59
|
-
break
|
|
60
|
-
try:
|
|
61
|
-
result = runtime.coordinator_tick(workspace)
|
|
62
|
-
except Exception as exc:
|
|
63
|
-
failure_count += 1
|
|
64
|
-
signature = (type(exc).__name__, str(exc)[:200])
|
|
65
|
-
sleep_sec = min(interval * (2 ** min(failure_count - 1, 5)), 60.0)
|
|
66
|
-
if signature != last_failure_signature:
|
|
67
|
-
last_failure_signature = signature
|
|
68
|
-
event_log.write(
|
|
69
|
-
"coordinator.tick_error",
|
|
70
|
-
error=str(exc),
|
|
71
|
-
exc_type=type(exc).__name__,
|
|
72
|
-
consecutive_failures=failure_count,
|
|
73
|
-
next_sleep_sec=sleep_sec,
|
|
74
|
-
)
|
|
75
|
-
elif failure_count == 1 or failure_count % 12 == 0 or sleep_sec in {40.0, 60.0}:
|
|
76
|
-
event_log.write(
|
|
77
|
-
"coordinator.tick_error",
|
|
78
|
-
error=str(exc),
|
|
79
|
-
exc_type=type(exc).__name__,
|
|
80
|
-
consecutive_failures=failure_count,
|
|
81
|
-
next_sleep_sec=sleep_sec,
|
|
82
|
-
)
|
|
83
|
-
else:
|
|
84
|
-
event_log.write(
|
|
85
|
-
"coordinator.tick_error.suppressed",
|
|
86
|
-
consecutive_failures=failure_count,
|
|
87
|
-
next_sleep_sec=sleep_sec,
|
|
88
|
-
)
|
|
89
|
-
time.sleep(sleep_sec)
|
|
90
|
-
continue
|
|
91
|
-
if failure_count:
|
|
92
|
-
event_log.write("coordinator.tick_recovered", consecutive_failures=failure_count)
|
|
93
|
-
failure_count = 0
|
|
94
|
-
last_failure_signature = None
|
|
95
|
-
if result.get("stop") or args.once:
|
|
96
|
-
break
|
|
97
|
-
time.sleep(interval)
|
|
98
|
-
event_log.write("coordinator.exit", stop=STOP)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
DEFAULT_TICK_INTERVAL_SEC = 5.0 # Stage 14 (Gap 36c) — bumped from 2.0 (2.5x less CPU)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def _tick_interval(workspace: Path) -> float:
|
|
105
|
-
state = load_runtime_state(workspace)
|
|
106
|
-
spec_path = Path(state.get("spec_path", workspace / "team.spec.yaml"))
|
|
107
|
-
if spec_path.exists():
|
|
108
|
-
try:
|
|
109
|
-
spec = load_spec(spec_path)
|
|
110
|
-
return float(spec.get("runtime", {}).get("tick_interval_sec", DEFAULT_TICK_INTERVAL_SEC))
|
|
111
|
-
except Exception:
|
|
112
|
-
pass
|
|
113
|
-
# Ensure schema exists even before launch; this makes doctor/tick diagnostics deterministic.
|
|
114
|
-
MessageStore(workspace)
|
|
115
|
-
return DEFAULT_TICK_INTERVAL_SEC
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if __name__ == "__main__":
|
|
119
|
-
main(sys.argv[1:])
|