@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,382 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import hashlib
|
|
4
|
-
import re
|
|
5
|
-
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
6
|
-
from typing import Any
|
|
7
|
-
|
|
8
|
-
from team_agent.events import EventLog
|
|
9
|
-
from team_agent.display.ghostty import (
|
|
10
|
-
ghostty_app_exists,
|
|
11
|
-
ghostty_attach_args,
|
|
12
|
-
ghostty_display_session_name,
|
|
13
|
-
ghostty_pids_by_title,
|
|
14
|
-
prepare_ghostty_display_session,
|
|
15
|
-
)
|
|
16
|
-
from team_agent.display.tiling import (
|
|
17
|
-
DISPLAY_PANES_PER_WINDOW,
|
|
18
|
-
display_pane_title,
|
|
19
|
-
display_window_name,
|
|
20
|
-
prepare_tmux_attached_panes,
|
|
21
|
-
set_tmux_display_pane_title,
|
|
22
|
-
tmux_attach_pane_command,
|
|
23
|
-
tmux_stdout_last_line as _tmux_stdout_last_line,
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
GHOSTTY_WORKSPACE_PANES_PER_WINDOW = DISPLAY_PANES_PER_WINDOW
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def open_ghostty_workspace(
|
|
31
|
-
workspace,
|
|
32
|
-
session_name: str,
|
|
33
|
-
jobs: list[tuple[str, dict[str, Any]]],
|
|
34
|
-
event_log: EventLog,
|
|
35
|
-
) -> dict[str, dict[str, Any]]:
|
|
36
|
-
from team_agent.runtime import run_cmd
|
|
37
|
-
_ = workspace
|
|
38
|
-
if not ghostty_app_exists():
|
|
39
|
-
return ghostty_workspace_blocked(jobs, event_log, "ghostty_app_missing")
|
|
40
|
-
aggregator_session = ghostty_workspace_aggregator_name(session_name)
|
|
41
|
-
linked_results = prepare_ghostty_workspace_linked_sessions(session_name, jobs)
|
|
42
|
-
displays: dict[str, dict[str, Any]] = {}
|
|
43
|
-
linked_jobs: list[tuple[str, dict[str, Any], str]] = []
|
|
44
|
-
for agent_id, agent in jobs:
|
|
45
|
-
linked = linked_results.get(agent_id, {})
|
|
46
|
-
linked_session = linked.get("linked_session") or ghostty_display_session_name(session_name, agent_id)
|
|
47
|
-
if linked.get("ok"):
|
|
48
|
-
linked_jobs.append((agent_id, agent, linked_session))
|
|
49
|
-
continue
|
|
50
|
-
displays.update(
|
|
51
|
-
ghostty_workspace_blocked(
|
|
52
|
-
[(agent_id, agent)],
|
|
53
|
-
event_log,
|
|
54
|
-
linked.get("reason", "display_session_create_failed"),
|
|
55
|
-
aggregator_session=aggregator_session,
|
|
56
|
-
linked_sessions={agent_id: linked_session},
|
|
57
|
-
error=linked.get("error"),
|
|
58
|
-
target=f"{session_name}:{agent_id}",
|
|
59
|
-
)
|
|
60
|
-
)
|
|
61
|
-
if not linked_jobs:
|
|
62
|
-
return displays
|
|
63
|
-
prepared = prepare_ghostty_workspace_aggregator(aggregator_session, linked_jobs)
|
|
64
|
-
if not prepared["ok"]:
|
|
65
|
-
kill_ghostty_workspace_linked_sessions([linked_session for _agent_id, _agent, linked_session in linked_jobs])
|
|
66
|
-
displays.update(
|
|
67
|
-
ghostty_workspace_blocked(
|
|
68
|
-
[(agent_id, agent) for agent_id, agent, _linked_session in linked_jobs],
|
|
69
|
-
event_log,
|
|
70
|
-
prepared["reason"],
|
|
71
|
-
aggregator_session=aggregator_session,
|
|
72
|
-
linked_sessions={agent_id: linked_session for agent_id, _agent, linked_session in linked_jobs},
|
|
73
|
-
error=prepared.get("error"),
|
|
74
|
-
target=prepared.get("target"),
|
|
75
|
-
)
|
|
76
|
-
)
|
|
77
|
-
return displays
|
|
78
|
-
title = f"team-agent:{session_name}:workspace"
|
|
79
|
-
launch_args = ghostty_attach_args(aggregator_session, title)
|
|
80
|
-
proc = run_cmd(launch_args, timeout=10)
|
|
81
|
-
if proc.returncode != 0:
|
|
82
|
-
run_cmd(["tmux", "kill-session", "-t", aggregator_session], timeout=10)
|
|
83
|
-
kill_ghostty_workspace_linked_sessions([linked_session for _agent_id, _agent, linked_session in linked_jobs])
|
|
84
|
-
displays.update(
|
|
85
|
-
ghostty_workspace_blocked(
|
|
86
|
-
[(agent_id, agent) for agent_id, agent, _linked_session in linked_jobs],
|
|
87
|
-
event_log,
|
|
88
|
-
"open Ghostty.app failed",
|
|
89
|
-
aggregator_session=aggregator_session,
|
|
90
|
-
linked_sessions={agent_id: linked_session for agent_id, _agent, linked_session in linked_jobs},
|
|
91
|
-
error=proc.stderr.strip() or proc.stdout.strip(),
|
|
92
|
-
)
|
|
93
|
-
)
|
|
94
|
-
return displays
|
|
95
|
-
pids = ghostty_pids_by_title(title, wait_s=3.0)
|
|
96
|
-
panes = {pane["agent_id"]: pane for pane in prepared["panes"]}
|
|
97
|
-
for agent_id, agent, linked_session in linked_jobs:
|
|
98
|
-
pane = panes.get(agent_id, {})
|
|
99
|
-
display = {
|
|
100
|
-
"backend": "ghostty_workspace",
|
|
101
|
-
"status": "opened",
|
|
102
|
-
"title": title,
|
|
103
|
-
"pane_title": pane.get("title") or ghostty_workspace_pane_title(agent),
|
|
104
|
-
"target": f"{session_name}:{agent_id}",
|
|
105
|
-
"linked_session": linked_session,
|
|
106
|
-
"aggregator_session": aggregator_session,
|
|
107
|
-
"display_session": aggregator_session,
|
|
108
|
-
"workspace_window": pane.get("window_name"),
|
|
109
|
-
"pane_id": pane.get("pane_id"),
|
|
110
|
-
"launch_args": launch_args,
|
|
111
|
-
"pid": pids[0] if pids else None,
|
|
112
|
-
"pids": pids,
|
|
113
|
-
"tty": None,
|
|
114
|
-
"fallback": "tmux_headless",
|
|
115
|
-
"note": "Ghostty opens one aggregator tmux session; each pane attaches to a distinct linked session pinned to one base worker window, so runtime injection remains session:agent_id addressed.",
|
|
116
|
-
}
|
|
117
|
-
event_log.write("display.ghostty_workspace", agent_id=agent_id, **display)
|
|
118
|
-
displays[agent_id] = display
|
|
119
|
-
return displays
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def ghostty_workspace_blocked(
|
|
123
|
-
jobs: list[tuple[str, dict[str, Any]]],
|
|
124
|
-
event_log: EventLog,
|
|
125
|
-
reason: str,
|
|
126
|
-
aggregator_session: str | None = None,
|
|
127
|
-
linked_sessions: dict[str, str] | None = None,
|
|
128
|
-
error: str | None = None,
|
|
129
|
-
target: str | None = None,
|
|
130
|
-
) -> dict[str, dict[str, Any]]:
|
|
131
|
-
displays: dict[str, dict[str, Any]] = {}
|
|
132
|
-
for agent_id, _agent in jobs:
|
|
133
|
-
linked_session = (linked_sessions or {}).get(agent_id)
|
|
134
|
-
display = {
|
|
135
|
-
"backend": "ghostty_workspace",
|
|
136
|
-
"status": "blocked",
|
|
137
|
-
"reason": reason,
|
|
138
|
-
"error": error,
|
|
139
|
-
"target": target or f"{agent_id}",
|
|
140
|
-
"linked_session": linked_session,
|
|
141
|
-
"aggregator_session": aggregator_session,
|
|
142
|
-
"display_session": aggregator_session,
|
|
143
|
-
"fallback": "tmux_headless",
|
|
144
|
-
}
|
|
145
|
-
event_log.write("display.ghostty_workspace_blocked", agent_id=agent_id, **display)
|
|
146
|
-
displays[agent_id] = display
|
|
147
|
-
return displays
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
def ghostty_workspace_aggregator_name(session_name: str) -> str:
|
|
151
|
-
raw = f"{session_name}:workspace"
|
|
152
|
-
digest = hashlib.sha1(raw.encode("utf-8")).hexdigest()[:8]
|
|
153
|
-
safe_session = re.sub(r"[^A-Za-z0-9_.-]", "_", session_name)[:80].strip("._-") or "team"
|
|
154
|
-
return f"{safe_session}__display__workspace__{digest}"
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
def ghostty_workspace_window_name(index: int) -> str:
|
|
158
|
-
return display_window_name(index)
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
def ghostty_workspace_pane_command(linked_session: str) -> str:
|
|
162
|
-
return tmux_attach_pane_command(linked_session)
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
def ghostty_workspace_pane_title(agent: dict[str, Any]) -> str:
|
|
166
|
-
return display_pane_title(agent)
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
def prepare_ghostty_workspace_linked_sessions(
|
|
170
|
-
session_name: str,
|
|
171
|
-
jobs: list[tuple[str, dict[str, Any]]],
|
|
172
|
-
) -> dict[str, dict[str, Any]]:
|
|
173
|
-
def prepare(agent_id: str) -> dict[str, Any]:
|
|
174
|
-
linked_session = ghostty_display_session_name(session_name, agent_id)
|
|
175
|
-
result = prepare_ghostty_display_session(session_name, agent_id, linked_session)
|
|
176
|
-
result["linked_session"] = linked_session
|
|
177
|
-
return result
|
|
178
|
-
|
|
179
|
-
if len(jobs) == 1:
|
|
180
|
-
agent_id, _agent = jobs[0]
|
|
181
|
-
return {agent_id: prepare(agent_id)}
|
|
182
|
-
results: dict[str, dict[str, Any]] = {}
|
|
183
|
-
max_workers = min(4, len(jobs))
|
|
184
|
-
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
|
185
|
-
futures = {executor.submit(prepare, agent_id): agent_id for agent_id, _agent in jobs}
|
|
186
|
-
for future in as_completed(futures):
|
|
187
|
-
agent_id = futures[future]
|
|
188
|
-
try:
|
|
189
|
-
results[agent_id] = future.result()
|
|
190
|
-
except Exception as exc:
|
|
191
|
-
results[agent_id] = {
|
|
192
|
-
"ok": False,
|
|
193
|
-
"reason": "display_session_create_exception",
|
|
194
|
-
"error": str(exc),
|
|
195
|
-
"linked_session": ghostty_display_session_name(session_name, agent_id),
|
|
196
|
-
}
|
|
197
|
-
return results
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
def prepare_ghostty_workspace_aggregator(
|
|
201
|
-
aggregator_session: str,
|
|
202
|
-
linked_jobs: list[tuple[str, dict[str, Any], str]],
|
|
203
|
-
) -> dict[str, Any]:
|
|
204
|
-
from team_agent.runtime import _tmux_session_exists, run_cmd
|
|
205
|
-
if _tmux_session_exists(aggregator_session):
|
|
206
|
-
proc = run_cmd(["tmux", "kill-session", "-t", aggregator_session], timeout=10)
|
|
207
|
-
if proc.returncode != 0:
|
|
208
|
-
return {"ok": False, "reason": "display_session_cleanup_failed", "error": proc.stderr.strip()}
|
|
209
|
-
prepared = prepare_tmux_attached_panes(
|
|
210
|
-
aggregator_session,
|
|
211
|
-
linked_jobs,
|
|
212
|
-
window_name_for_index=ghostty_workspace_window_name,
|
|
213
|
-
create_first_as_session=True,
|
|
214
|
-
panes_per_window=GHOSTTY_WORKSPACE_PANES_PER_WINDOW,
|
|
215
|
-
cleanup_session=aggregator_session,
|
|
216
|
-
enable_mouse=True,
|
|
217
|
-
select_first_window=True,
|
|
218
|
-
reason_map={
|
|
219
|
-
"create_session": "display_session_create_failed",
|
|
220
|
-
"create_window": "display_session_window_create_failed",
|
|
221
|
-
"title": "display_session_pane_title_failed",
|
|
222
|
-
"remain": "display_session_remain_on_exit_failed",
|
|
223
|
-
"split": "display_session_split_failed",
|
|
224
|
-
"layout": "display_session_layout_failed",
|
|
225
|
-
"mouse": "display_session_mouse_failed",
|
|
226
|
-
},
|
|
227
|
-
)
|
|
228
|
-
if prepared.get("ok"):
|
|
229
|
-
prepared["aggregator_session"] = aggregator_session
|
|
230
|
-
return prepared
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
def set_ghostty_workspace_pane_title(pane_id: str, title: str) -> dict[str, Any]:
|
|
234
|
-
return set_tmux_display_pane_title(pane_id, title, "display_session_pane_title_failed")
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
def open_ghostty_workspace_agent_display(
|
|
238
|
-
session_name: str,
|
|
239
|
-
agent_id: str,
|
|
240
|
-
agent: dict[str, Any],
|
|
241
|
-
previous_display: dict[str, Any],
|
|
242
|
-
event_log: EventLog,
|
|
243
|
-
) -> dict[str, Any]:
|
|
244
|
-
from team_agent.runtime import _tmux_session_exists, run_cmd
|
|
245
|
-
if not ghostty_app_exists():
|
|
246
|
-
return ghostty_workspace_blocked(
|
|
247
|
-
[(agent_id, agent)],
|
|
248
|
-
event_log,
|
|
249
|
-
"ghostty_app_missing",
|
|
250
|
-
aggregator_session=ghostty_workspace_aggregator_name(session_name),
|
|
251
|
-
linked_sessions={agent_id: ghostty_display_session_name(session_name, agent_id)},
|
|
252
|
-
target=f"{session_name}:{agent_id}",
|
|
253
|
-
)[agent_id]
|
|
254
|
-
aggregator_session = str(
|
|
255
|
-
previous_display.get("aggregator_session")
|
|
256
|
-
or previous_display.get("display_session")
|
|
257
|
-
or ghostty_workspace_aggregator_name(session_name)
|
|
258
|
-
)
|
|
259
|
-
linked_session = ghostty_display_session_name(session_name, agent_id)
|
|
260
|
-
prepared = prepare_ghostty_display_session(session_name, agent_id, linked_session)
|
|
261
|
-
if not prepared["ok"]:
|
|
262
|
-
return ghostty_workspace_blocked(
|
|
263
|
-
[(agent_id, agent)],
|
|
264
|
-
event_log,
|
|
265
|
-
prepared["reason"],
|
|
266
|
-
aggregator_session=aggregator_session,
|
|
267
|
-
linked_sessions={agent_id: linked_session},
|
|
268
|
-
error=prepared.get("error"),
|
|
269
|
-
target=f"{session_name}:{agent_id}",
|
|
270
|
-
)[agent_id]
|
|
271
|
-
if not _tmux_session_exists(aggregator_session):
|
|
272
|
-
return ghostty_workspace_partial_update_display(
|
|
273
|
-
session_name,
|
|
274
|
-
agent_id,
|
|
275
|
-
agent,
|
|
276
|
-
event_log,
|
|
277
|
-
reason="aggregator_session_missing",
|
|
278
|
-
note="pane refresh requires full team restart",
|
|
279
|
-
)
|
|
280
|
-
|
|
281
|
-
pane_title = ghostty_workspace_pane_title(agent)
|
|
282
|
-
command = ghostty_workspace_pane_command(linked_session)
|
|
283
|
-
pane_id = str(previous_display.get("pane_id") or "")
|
|
284
|
-
workspace_window = str(previous_display.get("workspace_window") or ghostty_workspace_window_name(0))
|
|
285
|
-
refreshed = False
|
|
286
|
-
if pane_id:
|
|
287
|
-
proc = run_cmd(["tmux", "respawn-pane", "-k", "-t", pane_id, command], timeout=10)
|
|
288
|
-
refreshed = proc.returncode == 0
|
|
289
|
-
if not refreshed:
|
|
290
|
-
proc = run_cmd(
|
|
291
|
-
[
|
|
292
|
-
"tmux",
|
|
293
|
-
"split-window",
|
|
294
|
-
"-t",
|
|
295
|
-
f"{aggregator_session}:{workspace_window}",
|
|
296
|
-
"-h",
|
|
297
|
-
"-P",
|
|
298
|
-
"-F",
|
|
299
|
-
"#{pane_id}",
|
|
300
|
-
command,
|
|
301
|
-
],
|
|
302
|
-
timeout=10,
|
|
303
|
-
)
|
|
304
|
-
if proc.returncode != 0:
|
|
305
|
-
return ghostty_workspace_partial_update_display(
|
|
306
|
-
session_name,
|
|
307
|
-
agent_id,
|
|
308
|
-
agent,
|
|
309
|
-
event_log,
|
|
310
|
-
reason="aggregator_pane_refresh_failed",
|
|
311
|
-
note=proc.stderr.strip() or "pane refresh requires full team restart",
|
|
312
|
-
)
|
|
313
|
-
pane_id = _tmux_stdout_last_line(proc.stdout) or pane_id
|
|
314
|
-
title_result = set_ghostty_workspace_pane_title(pane_id, pane_title)
|
|
315
|
-
if not title_result["ok"]:
|
|
316
|
-
return ghostty_workspace_partial_update_display(
|
|
317
|
-
session_name,
|
|
318
|
-
agent_id,
|
|
319
|
-
agent,
|
|
320
|
-
event_log,
|
|
321
|
-
reason=title_result["reason"],
|
|
322
|
-
note=title_result.get("error") or "pane refresh requires full team restart",
|
|
323
|
-
)
|
|
324
|
-
run_cmd(["tmux", "select-layout", "-t", f"{aggregator_session}:{workspace_window}", "even-horizontal"], timeout=10)
|
|
325
|
-
title = str(previous_display.get("title") or f"team-agent:{session_name}:workspace")
|
|
326
|
-
pids = [int(pid) for pid in previous_display.get("pids", []) if str(pid).isdigit()]
|
|
327
|
-
display = {
|
|
328
|
-
"backend": "ghostty_workspace",
|
|
329
|
-
"status": "opened",
|
|
330
|
-
"title": title,
|
|
331
|
-
"pane_title": pane_title,
|
|
332
|
-
"target": f"{session_name}:{agent_id}",
|
|
333
|
-
"linked_session": linked_session,
|
|
334
|
-
"aggregator_session": aggregator_session,
|
|
335
|
-
"display_session": aggregator_session,
|
|
336
|
-
"workspace_window": workspace_window,
|
|
337
|
-
"pane_id": pane_id,
|
|
338
|
-
"pid": pids[0] if pids else None,
|
|
339
|
-
"pids": pids,
|
|
340
|
-
"tty": None,
|
|
341
|
-
"fallback": "tmux_headless",
|
|
342
|
-
"note": "Refreshed this worker's Ghostty workspace pane by respawning it against a distinct linked session.",
|
|
343
|
-
}
|
|
344
|
-
event_log.write("display.ghostty_workspace", agent_id=agent_id, **display)
|
|
345
|
-
return display
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
def ghostty_workspace_partial_update_display(
|
|
349
|
-
session_name: str,
|
|
350
|
-
agent_id: str,
|
|
351
|
-
agent: dict[str, Any],
|
|
352
|
-
event_log: EventLog,
|
|
353
|
-
reason: str = "partial_update_requires_team_restart",
|
|
354
|
-
note: str = "pane refresh requires full team restart",
|
|
355
|
-
) -> dict[str, Any]:
|
|
356
|
-
aggregator_session = ghostty_workspace_aggregator_name(session_name)
|
|
357
|
-
display = {
|
|
358
|
-
"backend": "ghostty_workspace",
|
|
359
|
-
"status": "blocked",
|
|
360
|
-
"reason": reason,
|
|
361
|
-
"target": f"{session_name}:{agent_id}",
|
|
362
|
-
"linked_session": ghostty_display_session_name(session_name, agent_id),
|
|
363
|
-
"aggregator_session": aggregator_session,
|
|
364
|
-
"display_session": aggregator_session,
|
|
365
|
-
"pane_title": ghostty_workspace_pane_title(agent),
|
|
366
|
-
"fallback": "tmux_headless",
|
|
367
|
-
"note": note,
|
|
368
|
-
"action": "restart the team to rebuild the Ghostty workspace layout",
|
|
369
|
-
}
|
|
370
|
-
event_log.write("display.ghostty_workspace_partial_update", agent_id=agent_id, **display)
|
|
371
|
-
return display
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
def kill_ghostty_workspace_linked_sessions(linked_sessions: list[str]) -> list[str]:
|
|
375
|
-
from team_agent.runtime import _tmux_session_exists, run_cmd
|
|
376
|
-
killed: list[str] = []
|
|
377
|
-
for linked_session in dict.fromkeys(linked_sessions):
|
|
378
|
-
if _tmux_session_exists(linked_session):
|
|
379
|
-
proc = run_cmd(["tmux", "kill-session", "-t", linked_session], timeout=10)
|
|
380
|
-
if proc.returncode == 0:
|
|
381
|
-
killed.append(linked_session)
|
|
382
|
-
return killed
|
package/src/team_agent/errors.py
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
class TeamAgentError(Exception):
|
|
2
|
-
"""Base exception for user-facing Team Agent errors."""
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class ValidationError(TeamAgentError):
|
|
6
|
-
"""Spec or result envelope validation failed."""
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class RuntimeError(TeamAgentError):
|
|
10
|
-
"""Runtime operation failed."""
|
package/src/team_agent/events.py
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import json
|
|
4
|
-
import os
|
|
5
|
-
from datetime import datetime, timezone
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
from typing import Any
|
|
8
|
-
|
|
9
|
-
from team_agent.paths import logs_dir
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
# Stage 14 (Gap 36a) — bounded retention. 5 MB cap × 5 archives = 25 MB worst-case.
|
|
13
|
-
# Mac mini 2026-05-26 evidence: events.jsonl grew to 28 MB / 128k lines in one day with
|
|
14
|
-
# unbounded retention; coordinator's tick-time scan over the file was a ~22% CPU hot path.
|
|
15
|
-
# Rotation keeps the current segment small so reads are cheap; archives preserve forensic
|
|
16
|
-
# history but are NOT consulted by hot-path scans.
|
|
17
|
-
EVENT_LOG_ROTATE_BYTES = 5 * 1024 * 1024
|
|
18
|
-
EVENT_LOG_ARCHIVE_KEEP = 5
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class EventLog:
|
|
22
|
-
def __init__(self, workspace: Path):
|
|
23
|
-
self.workspace = workspace
|
|
24
|
-
self.path = logs_dir(workspace) / "events.jsonl"
|
|
25
|
-
self.path.parent.mkdir(parents=True, exist_ok=True)
|
|
26
|
-
|
|
27
|
-
def write(self, event_type: str, **fields: Any) -> dict[str, Any]:
|
|
28
|
-
event = {
|
|
29
|
-
"ts": datetime.now(timezone.utc).isoformat(),
|
|
30
|
-
"event": event_type,
|
|
31
|
-
**fields,
|
|
32
|
-
}
|
|
33
|
-
self._maybe_rotate()
|
|
34
|
-
with self.path.open("a", encoding="utf-8") as f:
|
|
35
|
-
f.write(json.dumps(event, ensure_ascii=False, sort_keys=True) + "\n")
|
|
36
|
-
return event
|
|
37
|
-
|
|
38
|
-
def tail(self, limit: int = 20) -> list[dict[str, Any]]:
|
|
39
|
-
# Hot-path scan reads only the current segment. Archives are forensic; if a
|
|
40
|
-
# caller genuinely needs longer history it can iterate _archive_paths explicitly.
|
|
41
|
-
if not self.path.exists():
|
|
42
|
-
return []
|
|
43
|
-
lines = self.path.read_text(encoding="utf-8").splitlines()[-limit:]
|
|
44
|
-
out: list[dict[str, Any]] = []
|
|
45
|
-
for line in lines:
|
|
46
|
-
try:
|
|
47
|
-
out.append(json.loads(line))
|
|
48
|
-
except json.JSONDecodeError:
|
|
49
|
-
out.append({"raw": line})
|
|
50
|
-
return out
|
|
51
|
-
|
|
52
|
-
def _maybe_rotate(self) -> None:
|
|
53
|
-
try:
|
|
54
|
-
size = self.path.stat().st_size
|
|
55
|
-
except FileNotFoundError:
|
|
56
|
-
return
|
|
57
|
-
if size < EVENT_LOG_ROTATE_BYTES:
|
|
58
|
-
return
|
|
59
|
-
# Shift archives: events.jsonl.4 → .5, .3 → .4, …, .1 → .2, current → .1
|
|
60
|
-
# Drop the oldest if it would overflow the keep budget.
|
|
61
|
-
oldest = self._archive_path(EVENT_LOG_ARCHIVE_KEEP)
|
|
62
|
-
if oldest.exists():
|
|
63
|
-
try:
|
|
64
|
-
oldest.unlink()
|
|
65
|
-
except OSError:
|
|
66
|
-
pass
|
|
67
|
-
for idx in range(EVENT_LOG_ARCHIVE_KEEP - 1, 0, -1):
|
|
68
|
-
src = self._archive_path(idx)
|
|
69
|
-
dst = self._archive_path(idx + 1)
|
|
70
|
-
if src.exists():
|
|
71
|
-
try:
|
|
72
|
-
os.replace(src, dst)
|
|
73
|
-
except OSError:
|
|
74
|
-
pass
|
|
75
|
-
try:
|
|
76
|
-
os.replace(self.path, self._archive_path(1))
|
|
77
|
-
except OSError:
|
|
78
|
-
pass
|
|
79
|
-
|
|
80
|
-
def _archive_path(self, index: int) -> Path:
|
|
81
|
-
return self.path.with_name(f"{self.path.name}.{index}")
|
|
82
|
-
|
|
83
|
-
def _archive_paths(self) -> list[Path]:
|
|
84
|
-
return [self._archive_path(i) for i in range(1, EVENT_LOG_ARCHIVE_KEEP + 1)]
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import argparse
|
|
4
|
-
import json
|
|
5
|
-
import re
|
|
6
|
-
import sys
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
|
|
9
|
-
from team_agent.runtime import report_result
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def main() -> None:
|
|
13
|
-
parser = argparse.ArgumentParser()
|
|
14
|
-
parser.add_argument("--workspace", required=True)
|
|
15
|
-
parser.add_argument("--agent-id", required=True)
|
|
16
|
-
args = parser.parse_args()
|
|
17
|
-
workspace = Path(args.workspace)
|
|
18
|
-
print(f"TEAM_AGENT_FAKE_READY agent={args.agent_id}", flush=True)
|
|
19
|
-
rendered_message: list[str] | None = None
|
|
20
|
-
for line in sys.stdin:
|
|
21
|
-
line = line.strip()
|
|
22
|
-
if not line:
|
|
23
|
-
if rendered_message is not None:
|
|
24
|
-
rendered_message.append("")
|
|
25
|
-
continue
|
|
26
|
-
print(f"TEAM_AGENT_FAKE_WORKING agent={args.agent_id}", flush=True)
|
|
27
|
-
if line.startswith("TEAM_AGENT_MESSAGE "):
|
|
28
|
-
payload = json.loads(line.removeprefix("TEAM_AGENT_MESSAGE "))
|
|
29
|
-
_report_fake_result(workspace, args.agent_id, payload)
|
|
30
|
-
elif line.startswith("Team Agent message from "):
|
|
31
|
-
rendered_message = [line]
|
|
32
|
-
elif rendered_message is not None:
|
|
33
|
-
rendered_message.append(line)
|
|
34
|
-
if line.startswith("[team-agent-token:"):
|
|
35
|
-
payload = _parse_rendered_message(rendered_message)
|
|
36
|
-
_report_fake_result(workspace, args.agent_id, payload)
|
|
37
|
-
rendered_message = None
|
|
38
|
-
print(f"TEAM_AGENT_FAKE_READY agent={args.agent_id}", flush=True)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def _parse_rendered_message(lines: list[str]) -> dict[str, str | None]:
|
|
42
|
-
header = lines[0]
|
|
43
|
-
match = re.match(r"Team Agent message from (?P<sender>[^:]+?)(?: for (?P<task_id>[^:]+))?:$", header)
|
|
44
|
-
token_line = next((line for line in lines if line.startswith("[team-agent-token:")), "[team-agent-token:manual]")
|
|
45
|
-
token = token_line.removeprefix("[team-agent-token:").removesuffix("]")
|
|
46
|
-
content_lines = [line for line in lines[1:] if not line.startswith("[team-agent-token:")]
|
|
47
|
-
content = "\n".join(content_lines).strip()
|
|
48
|
-
return {
|
|
49
|
-
"message_id": token,
|
|
50
|
-
"task_id": match.group("task_id") if match else None,
|
|
51
|
-
"from": match.group("sender") if match else "leader",
|
|
52
|
-
"content": content,
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def _report_fake_result(workspace: Path, agent_id: str, payload: dict) -> None:
|
|
57
|
-
task_id = payload.get("task_id") or "manual"
|
|
58
|
-
envelope = {
|
|
59
|
-
"schema_version": "result_envelope_v1",
|
|
60
|
-
"task_id": task_id,
|
|
61
|
-
"agent_id": agent_id,
|
|
62
|
-
"status": "success",
|
|
63
|
-
"summary": f"Fake worker handled message {payload['message_id']}",
|
|
64
|
-
"changes": [],
|
|
65
|
-
"tests": [{"command": "fake-provider", "status": "passed"}],
|
|
66
|
-
"risks": [],
|
|
67
|
-
"artifacts": [
|
|
68
|
-
{
|
|
69
|
-
"path": str(workspace / ".team" / "logs" / f"{agent_id}.scrollback"),
|
|
70
|
-
"description": "tmux scrollback for fake worker",
|
|
71
|
-
}
|
|
72
|
-
],
|
|
73
|
-
"next_actions": [],
|
|
74
|
-
}
|
|
75
|
-
report_result(workspace, envelope)
|
|
76
|
-
print(json.dumps(envelope), flush=True)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if __name__ == "__main__":
|
|
80
|
-
main()
|