@team-agent/installer 0.2.10 → 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 -83
- package/src/team_agent/coordinator/lifecycle.py +0 -363
- 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 -200
- package/src/team_agent/idle_takeover.py +0 -59
- package/src/team_agent/idle_takeover_wiring.py +0 -111
- 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 -254
- package/src/team_agent/messaging/delivery.py +0 -473
- 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 -457
- 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 -86
- 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 -1239
- 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 -143
- 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 -602
- 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,336 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import json
|
|
4
|
-
import re
|
|
5
|
-
import subprocess
|
|
6
|
-
import time
|
|
7
|
-
from datetime import datetime, timedelta, timezone
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
from typing import Any
|
|
10
|
-
|
|
11
|
-
from team_agent.permissions import resolve_permissions
|
|
12
|
-
from team_agent.provider_cli.adapter import (
|
|
13
|
-
ProviderAdapter,
|
|
14
|
-
ResumeUnavailable,
|
|
15
|
-
agent_model,
|
|
16
|
-
parse_time,
|
|
17
|
-
)
|
|
18
|
-
from team_agent.provider_cli.prompt import compile_system_prompt
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class CodexAdapter(ProviderAdapter):
|
|
22
|
-
provider = "codex"
|
|
23
|
-
command_name = "codex"
|
|
24
|
-
_model_catalog_cache: dict[str, Any] | None = None
|
|
25
|
-
|
|
26
|
-
def build_command(self, agent: dict[str, Any], workspace: Path, mcp_config: dict[str, Any]) -> list[str]:
|
|
27
|
-
cmd = self._base_command(agent, mcp_config, resume=False)
|
|
28
|
-
return cmd
|
|
29
|
-
|
|
30
|
-
def build_resume_command(
|
|
31
|
-
self,
|
|
32
|
-
agent_state: dict[str, Any],
|
|
33
|
-
workspace: Path,
|
|
34
|
-
mcp_config: dict[str, Any] | None = None,
|
|
35
|
-
) -> list[str]:
|
|
36
|
-
_ = workspace
|
|
37
|
-
session_id = agent_state.get("session_id")
|
|
38
|
-
if not session_id:
|
|
39
|
-
raise ResumeUnavailable("codex resume requires session_id")
|
|
40
|
-
agent = dict(agent_state.get("_agent_spec") or agent_state)
|
|
41
|
-
cmd = self._base_command(agent, mcp_config or {}, resume=True)
|
|
42
|
-
cmd.append(str(session_id))
|
|
43
|
-
return cmd
|
|
44
|
-
|
|
45
|
-
def supports_session_fork(self, agent: dict[str, Any] | None = None) -> bool:
|
|
46
|
-
return not agent or agent.get("auth_mode") != "compatible_api"
|
|
47
|
-
|
|
48
|
-
def build_fork_command(
|
|
49
|
-
self,
|
|
50
|
-
agent: dict[str, Any],
|
|
51
|
-
source_session_id: str,
|
|
52
|
-
workspace: Path,
|
|
53
|
-
mcp_config: dict[str, Any],
|
|
54
|
-
) -> list[str]:
|
|
55
|
-
_ = workspace
|
|
56
|
-
if not source_session_id:
|
|
57
|
-
raise ResumeUnavailable("codex fork requires source session_id")
|
|
58
|
-
cmd = self._base_command(agent, mcp_config, resume=False, fork=True)
|
|
59
|
-
cmd.append(str(source_session_id))
|
|
60
|
-
return cmd
|
|
61
|
-
|
|
62
|
-
def capture_session_id(
|
|
63
|
-
self,
|
|
64
|
-
agent_id: str,
|
|
65
|
-
spawn_context: dict[str, Any],
|
|
66
|
-
timeout_s: float = 3.0,
|
|
67
|
-
) -> dict[str, Any] | None:
|
|
68
|
-
_ = agent_id
|
|
69
|
-
cwd = spawn_context.get("cwd")
|
|
70
|
-
if not cwd:
|
|
71
|
-
return None
|
|
72
|
-
start = parse_time(spawn_context.get("spawn_time")) or datetime.now(timezone.utc)
|
|
73
|
-
root = Path(spawn_context.get("sessions_root") or Path.home() / ".codex" / "sessions")
|
|
74
|
-
deadline = time.monotonic() + max(timeout_s, 0.0)
|
|
75
|
-
exclude = {str(item) for item in spawn_context.get("exclude_session_ids", []) if item}
|
|
76
|
-
while True:
|
|
77
|
-
match = find_codex_rollout(root, Path(str(cwd)), start, exclude_session_ids=exclude)
|
|
78
|
-
if match:
|
|
79
|
-
return {
|
|
80
|
-
"session_id": match["session_id"],
|
|
81
|
-
"rollout_path": match["rollout_path"],
|
|
82
|
-
"captured_at": datetime.now(timezone.utc).isoformat(),
|
|
83
|
-
"captured_via": "fs_watch",
|
|
84
|
-
"attribution_confidence": match["confidence"],
|
|
85
|
-
"spawn_cwd": str(cwd),
|
|
86
|
-
}
|
|
87
|
-
if time.monotonic() >= deadline:
|
|
88
|
-
return None
|
|
89
|
-
time.sleep(0.2)
|
|
90
|
-
|
|
91
|
-
def _base_command(
|
|
92
|
-
self,
|
|
93
|
-
agent: dict[str, Any],
|
|
94
|
-
mcp_config: dict[str, Any],
|
|
95
|
-
resume: bool,
|
|
96
|
-
fork: bool = False,
|
|
97
|
-
) -> list[str]:
|
|
98
|
-
prompt = compile_system_prompt(agent)
|
|
99
|
-
cmd = ["codex"]
|
|
100
|
-
if resume:
|
|
101
|
-
cmd.append("resume")
|
|
102
|
-
elif fork:
|
|
103
|
-
cmd.append("fork")
|
|
104
|
-
cmd.extend(["--no-alt-screen", "--disable", "shell_snapshot", "--disable", "apps"])
|
|
105
|
-
profile_overrides = agent.get("_provider_profile", {}).get("command_overrides", {})
|
|
106
|
-
if profile_overrides.get("codex_profile"):
|
|
107
|
-
cmd.extend(["--profile", str(profile_overrides["codex_profile"])])
|
|
108
|
-
if agent.get("_runtime", {}).get("dangerous_auto_approve"):
|
|
109
|
-
cmd.append("--dangerously-bypass-approvals-and-sandbox")
|
|
110
|
-
else:
|
|
111
|
-
tools = set(resolve_permissions(agent)["tools"])
|
|
112
|
-
sandbox = "workspace-write" if {"fs_write", "execute_bash"} & tools else "read-only"
|
|
113
|
-
cmd.extend(["--sandbox", sandbox, "--ask-for-approval", "on-request"])
|
|
114
|
-
model = agent_model(agent)
|
|
115
|
-
if model:
|
|
116
|
-
cmd.extend(["--model", model])
|
|
117
|
-
for config in profile_overrides.get("codex_config", []):
|
|
118
|
-
cmd.extend(["-c", str(config)])
|
|
119
|
-
if prompt:
|
|
120
|
-
escaped = prompt.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\\n")
|
|
121
|
-
cmd.extend(["-c", f'developer_instructions="{escaped}"'])
|
|
122
|
-
for server_name, cfg in mcp_config.items():
|
|
123
|
-
prefix = f"mcp_servers.{server_name}"
|
|
124
|
-
cmd.extend(["-c", f'{prefix}.command="{cfg["command"]}"'])
|
|
125
|
-
args = "[" + ", ".join(json.dumps(str(arg)) for arg in cfg.get("args", [])) + "]"
|
|
126
|
-
cmd.extend(["-c", f"{prefix}.args={args}"])
|
|
127
|
-
for env_key, env_val in cfg.get("env", {}).items():
|
|
128
|
-
cmd.extend(["-c", f'{prefix}.env.{env_key}="{env_val}"'])
|
|
129
|
-
cmd.extend(["-c", f"{prefix}.tool_timeout_sec=600.0"])
|
|
130
|
-
return cmd
|
|
131
|
-
|
|
132
|
-
def auth_hint(self) -> dict[str, Any]:
|
|
133
|
-
if "OPENAI_API_KEY" in __import__("os").environ:
|
|
134
|
-
return {"status": "present", "detail": "OPENAI_API_KEY is set"}
|
|
135
|
-
if Path.home().joinpath(".codex").exists():
|
|
136
|
-
return {"status": "present", "detail": "~/.codex exists; run codex login if startup fails"}
|
|
137
|
-
return {"status": "missing_or_unknown", "detail": "run codex login or set OPENAI_API_KEY"}
|
|
138
|
-
|
|
139
|
-
def status_patterns(self) -> dict[str, str]:
|
|
140
|
-
return {"idle": r"(›|❯|codex>)", "processing": r"•.*esc to interrupt", "error": "Error|Traceback|panic"}
|
|
141
|
-
|
|
142
|
-
def handle_startup_prompts(
|
|
143
|
-
self,
|
|
144
|
-
session_name: str,
|
|
145
|
-
window_name: str,
|
|
146
|
-
checks: int = 30,
|
|
147
|
-
sleep_s: float = 0.5,
|
|
148
|
-
) -> list[dict[str, Any]]:
|
|
149
|
-
handled: list[dict[str, Any]] = []
|
|
150
|
-
target = f"{session_name}:{window_name}"
|
|
151
|
-
for _ in range(max(checks, 0)):
|
|
152
|
-
proc = subprocess.run(
|
|
153
|
-
["tmux", "capture-pane", "-p", "-S", "-", "-t", target],
|
|
154
|
-
text=True,
|
|
155
|
-
capture_output=True,
|
|
156
|
-
timeout=5,
|
|
157
|
-
check=False,
|
|
158
|
-
)
|
|
159
|
-
output = proc.stdout if proc.returncode == 0 else ""
|
|
160
|
-
update = maybe_skip_update_prompt(target, output)
|
|
161
|
-
if update:
|
|
162
|
-
handled.append(update)
|
|
163
|
-
if sleep_s > 0:
|
|
164
|
-
time.sleep(sleep_s)
|
|
165
|
-
continue
|
|
166
|
-
trust_pos = max(
|
|
167
|
-
output.rfind("Do you trust the contents of this directory?"),
|
|
168
|
-
output.rfind("Do you trust the files in this folder?"),
|
|
169
|
-
output.rfind("Do you trust this folder?"),
|
|
170
|
-
)
|
|
171
|
-
ready_pos = max(output.rfind("OpenAI Codex"), output.rfind("›"), output.rfind("codex>"))
|
|
172
|
-
if trust_pos >= 0 and trust_pos > ready_pos:
|
|
173
|
-
subprocess.run(["tmux", "send-keys", "-t", target, "Enter"], check=False)
|
|
174
|
-
handled.append({"prompt": "codex_workspace_trust", "action": "sent_enter"})
|
|
175
|
-
if sleep_s > 0:
|
|
176
|
-
time.sleep(sleep_s)
|
|
177
|
-
continue
|
|
178
|
-
if ready_pos >= 0:
|
|
179
|
-
break
|
|
180
|
-
if sleep_s > 0:
|
|
181
|
-
time.sleep(sleep_s)
|
|
182
|
-
return handled
|
|
183
|
-
|
|
184
|
-
def handle_runtime_prompts(self, session_name: str, window_name: str) -> list[dict[str, Any]]:
|
|
185
|
-
target = f"{session_name}:{window_name}"
|
|
186
|
-
proc = subprocess.run(
|
|
187
|
-
["tmux", "capture-pane", "-p", "-S", "-", "-t", target],
|
|
188
|
-
text=True,
|
|
189
|
-
capture_output=True,
|
|
190
|
-
timeout=5,
|
|
191
|
-
check=False,
|
|
192
|
-
)
|
|
193
|
-
output = proc.stdout if proc.returncode == 0 else ""
|
|
194
|
-
handled = maybe_skip_update_prompt(target, output)
|
|
195
|
-
return [handled] if handled else []
|
|
196
|
-
|
|
197
|
-
def validate_model(self, model: str | None) -> dict[str, Any]:
|
|
198
|
-
if not model:
|
|
199
|
-
return {"ok": True, "status": "model_not_set", "provider": self.provider, "model": model}
|
|
200
|
-
catalog = self._model_catalog()
|
|
201
|
-
if not catalog.get("ok"):
|
|
202
|
-
details = {key: value for key, value in catalog.items() if key != "ok"}
|
|
203
|
-
return {"ok": False, "status": "model_catalog_unavailable", "provider": self.provider, "model": model, **details}
|
|
204
|
-
models = catalog.get("models", [])
|
|
205
|
-
slugs = {str(item.get("slug") or "") for item in models if item.get("slug")}
|
|
206
|
-
if model in slugs:
|
|
207
|
-
return {"ok": True, "status": "model_supported", "provider": self.provider, "model": model}
|
|
208
|
-
slug_by_lower = {slug.lower(): slug for slug in slugs}
|
|
209
|
-
display_to_slug = {
|
|
210
|
-
str(item.get("display_name") or "").lower(): str(item.get("slug"))
|
|
211
|
-
for item in models
|
|
212
|
-
if item.get("display_name") and item.get("slug")
|
|
213
|
-
}
|
|
214
|
-
normalized = model.lower()
|
|
215
|
-
suggested = slug_by_lower.get(normalized) or display_to_slug.get(normalized)
|
|
216
|
-
result = {
|
|
217
|
-
"ok": False,
|
|
218
|
-
"status": "unsupported_model",
|
|
219
|
-
"reason": "model_id_not_found",
|
|
220
|
-
"provider": self.provider,
|
|
221
|
-
"model": model,
|
|
222
|
-
"available_models": sorted(slugs),
|
|
223
|
-
}
|
|
224
|
-
if suggested:
|
|
225
|
-
result["reason"] = "model_id_not_exact"
|
|
226
|
-
result["suggested_model"] = suggested
|
|
227
|
-
return result
|
|
228
|
-
|
|
229
|
-
def _model_catalog(self) -> dict[str, Any]:
|
|
230
|
-
if self._model_catalog_cache is not None:
|
|
231
|
-
return self._model_catalog_cache
|
|
232
|
-
if not self.is_installed():
|
|
233
|
-
return {"ok": False, "reason": "codex_command_missing", "command": self.command_name}
|
|
234
|
-
try:
|
|
235
|
-
proc = subprocess.run(
|
|
236
|
-
[self.command_name, "debug", "models"],
|
|
237
|
-
text=True,
|
|
238
|
-
capture_output=True,
|
|
239
|
-
timeout=12,
|
|
240
|
-
check=False,
|
|
241
|
-
)
|
|
242
|
-
except (OSError, subprocess.TimeoutExpired) as exc:
|
|
243
|
-
return {"ok": False, "reason": "model_catalog_command_failed", "command": "codex debug models", "error": str(exc)}
|
|
244
|
-
if proc.returncode != 0:
|
|
245
|
-
return {
|
|
246
|
-
"ok": False,
|
|
247
|
-
"reason": "model_catalog_command_failed",
|
|
248
|
-
"command": "codex debug models",
|
|
249
|
-
"stderr": proc.stderr.strip(),
|
|
250
|
-
}
|
|
251
|
-
try:
|
|
252
|
-
data = json.loads(proc.stdout or "{}")
|
|
253
|
-
except json.JSONDecodeError as exc:
|
|
254
|
-
return {"ok": False, "reason": "model_catalog_parse_failed", "command": "codex debug models", "error": str(exc)}
|
|
255
|
-
models = data.get("models")
|
|
256
|
-
if not isinstance(models, list):
|
|
257
|
-
return {"ok": False, "reason": "model_catalog_shape_invalid", "command": "codex debug models"}
|
|
258
|
-
self._model_catalog_cache = {"ok": True, "command": "codex debug models", "models": models}
|
|
259
|
-
return self._model_catalog_cache
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
def maybe_skip_update_prompt(target: str, output: str) -> dict[str, Any] | None:
|
|
263
|
-
update_pos = max(output.rfind("Update available!"), output.rfind("Update now"))
|
|
264
|
-
ready_pos = max(output.rfind("OpenAI Codex"), output.rfind("›"), output.rfind("codex>"))
|
|
265
|
-
if update_pos >= 0 and update_pos > ready_pos:
|
|
266
|
-
subprocess.run(["tmux", "send-keys", "-t", target, "Down", "Enter"], check=False)
|
|
267
|
-
return {"prompt": "codex_update_available", "action": "sent_skip"}
|
|
268
|
-
return None
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
def find_codex_rollout(
|
|
272
|
-
root: Path,
|
|
273
|
-
cwd: Path,
|
|
274
|
-
spawn_time: datetime,
|
|
275
|
-
exclude_session_ids: set[str] | None = None,
|
|
276
|
-
) -> dict[str, Any] | None:
|
|
277
|
-
if not root.exists():
|
|
278
|
-
return None
|
|
279
|
-
exclude_session_ids = exclude_session_ids or set()
|
|
280
|
-
lower_bound = spawn_time - timedelta(seconds=2)
|
|
281
|
-
upper_bound = datetime.now(timezone.utc) + timedelta(seconds=5)
|
|
282
|
-
candidates: list[dict[str, Any]] = []
|
|
283
|
-
for path in sorted(root.glob("**/rollout-*.jsonl"), key=lambda p: p.stat().st_mtime, reverse=True)[:1500]:
|
|
284
|
-
meta = read_codex_session_meta(path)
|
|
285
|
-
if not meta:
|
|
286
|
-
continue
|
|
287
|
-
meta_cwd = meta.get("cwd")
|
|
288
|
-
if not meta_cwd:
|
|
289
|
-
continue
|
|
290
|
-
try:
|
|
291
|
-
same_cwd = Path(str(meta_cwd)).resolve() == cwd.resolve()
|
|
292
|
-
except OSError:
|
|
293
|
-
same_cwd = str(meta_cwd) == str(cwd)
|
|
294
|
-
if not same_cwd:
|
|
295
|
-
continue
|
|
296
|
-
ts = parse_time(meta.get("timestamp"))
|
|
297
|
-
if ts and (ts < lower_bound or ts > upper_bound):
|
|
298
|
-
continue
|
|
299
|
-
originator = meta.get("originator")
|
|
300
|
-
origin_ok = originator in {"codex-tui", "codex_exec"}
|
|
301
|
-
session_id = meta.get("id") or rollout_id_from_name(path)
|
|
302
|
-
if not session_id:
|
|
303
|
-
continue
|
|
304
|
-
if str(session_id) in exclude_session_ids:
|
|
305
|
-
continue
|
|
306
|
-
candidates.append(
|
|
307
|
-
{
|
|
308
|
-
"session_id": str(session_id),
|
|
309
|
-
"rollout_path": str(path),
|
|
310
|
-
"timestamp": ts or datetime.fromtimestamp(path.stat().st_mtime, timezone.utc),
|
|
311
|
-
"confidence": "high" if origin_ok and ts else "medium",
|
|
312
|
-
}
|
|
313
|
-
)
|
|
314
|
-
if not candidates:
|
|
315
|
-
return None
|
|
316
|
-
candidates.sort(key=lambda item: item["timestamp"])
|
|
317
|
-
return candidates[0]
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
def read_codex_session_meta(path: Path) -> dict[str, Any] | None:
|
|
321
|
-
try:
|
|
322
|
-
with path.open(encoding="utf-8") as handle:
|
|
323
|
-
first = handle.readline()
|
|
324
|
-
data = json.loads(first)
|
|
325
|
-
except (OSError, json.JSONDecodeError):
|
|
326
|
-
return None
|
|
327
|
-
if "session_meta" in data:
|
|
328
|
-
payload = data.get("session_meta", {}).get("payload")
|
|
329
|
-
else:
|
|
330
|
-
payload = data.get("payload")
|
|
331
|
-
return payload if isinstance(payload, dict) else None
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
def rollout_id_from_name(path: Path) -> str | None:
|
|
335
|
-
match = re.search(r"([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})\.jsonl$", path.name)
|
|
336
|
-
return match.group(1) if match else None
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import sys
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import Any
|
|
6
|
-
|
|
7
|
-
from team_agent.provider_cli.adapter import ProviderAdapter
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class FakeAdapter(ProviderAdapter):
|
|
11
|
-
provider = "fake"
|
|
12
|
-
command_name = sys.executable
|
|
13
|
-
|
|
14
|
-
def build_command(self, agent: dict[str, Any], workspace: Path, mcp_config: dict[str, Any]) -> list[str]:
|
|
15
|
-
return [
|
|
16
|
-
sys.executable,
|
|
17
|
-
"-m",
|
|
18
|
-
"team_agent.fake_worker",
|
|
19
|
-
"--workspace",
|
|
20
|
-
str(workspace),
|
|
21
|
-
"--agent-id",
|
|
22
|
-
agent["id"],
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
def build_resume_command(
|
|
26
|
-
self,
|
|
27
|
-
agent_state: dict[str, Any],
|
|
28
|
-
workspace: Path,
|
|
29
|
-
mcp_config: dict[str, Any] | None = None,
|
|
30
|
-
) -> list[str]:
|
|
31
|
-
agent = dict(agent_state.get("_agent_spec") or agent_state)
|
|
32
|
-
agent.setdefault("id", agent_state.get("agent_id") or agent_state.get("id"))
|
|
33
|
-
return self.build_command(agent, workspace, mcp_config or {})
|
|
34
|
-
|
|
35
|
-
def auth_hint(self) -> dict[str, Any]:
|
|
36
|
-
return {"status": "present", "detail": "fake provider is local test worker"}
|
|
37
|
-
|
|
38
|
-
def status_patterns(self) -> dict[str, str]:
|
|
39
|
-
return {"idle": "TEAM_AGENT_FAKE_READY", "processing": "TEAM_AGENT_FAKE_WORKING", "error": "Traceback"}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import json
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import Any
|
|
6
|
-
|
|
7
|
-
from team_agent.provider_cli.adapter import (
|
|
8
|
-
ProviderAdapter,
|
|
9
|
-
agent_model,
|
|
10
|
-
read_json_object,
|
|
11
|
-
)
|
|
12
|
-
from team_agent.provider_cli.prompt import compile_system_prompt
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class GeminiCliAdapter(ProviderAdapter):
|
|
16
|
-
provider = "gemini_cli"
|
|
17
|
-
command_name = "gemini"
|
|
18
|
-
|
|
19
|
-
def build_command(self, agent: dict[str, Any], workspace: Path, mcp_config: dict[str, Any]) -> list[str]:
|
|
20
|
-
prompt = compile_system_prompt(agent)
|
|
21
|
-
cmd = ["gemini"]
|
|
22
|
-
if agent.get("_runtime", {}).get("dangerous_auto_approve"):
|
|
23
|
-
cmd.extend(["--yolo", "--sandbox", "false"])
|
|
24
|
-
model = agent_model(agent)
|
|
25
|
-
if model:
|
|
26
|
-
cmd.extend(["--model", model])
|
|
27
|
-
if prompt:
|
|
28
|
-
cmd.extend(["-i", prompt])
|
|
29
|
-
return cmd
|
|
30
|
-
|
|
31
|
-
def install_mcp(self, workspace: Path, agent_id: str, config: dict[str, Any]) -> Path:
|
|
32
|
-
path = super().install_mcp(workspace, agent_id, config)
|
|
33
|
-
self._register_mcp_servers(path, config)
|
|
34
|
-
return path
|
|
35
|
-
|
|
36
|
-
def cleanup_mcp(self, workspace: Path, agent_id: str, mcp_path: Path | None = None) -> None:
|
|
37
|
-
path = mcp_path or workspace / ".team" / "runtime" / "mcp" / f"{agent_id}.json"
|
|
38
|
-
self._restore_mcp_servers(path)
|
|
39
|
-
|
|
40
|
-
def _register_mcp_servers(self, mcp_path: Path, config: dict[str, Any]) -> None:
|
|
41
|
-
settings_path = Path.home() / ".gemini" / "settings.json"
|
|
42
|
-
settings_path.parent.mkdir(parents=True, exist_ok=True)
|
|
43
|
-
settings = read_json_object(settings_path)
|
|
44
|
-
mcp_servers = settings.setdefault("mcpServers", {})
|
|
45
|
-
if not isinstance(mcp_servers, dict):
|
|
46
|
-
raise ValueError(f"{settings_path}: mcpServers must be an object")
|
|
47
|
-
|
|
48
|
-
backup = {
|
|
49
|
-
"settings_path": str(settings_path),
|
|
50
|
-
"servers": {name: mcp_servers.get(name) for name in config},
|
|
51
|
-
}
|
|
52
|
-
gemini_backup_path(mcp_path).write_text(json.dumps(backup, indent=2), encoding="utf-8")
|
|
53
|
-
|
|
54
|
-
for name, server in config.items():
|
|
55
|
-
mcp_servers[name] = {
|
|
56
|
-
"command": server["command"],
|
|
57
|
-
"args": server.get("args", []),
|
|
58
|
-
"env": server.get("env", {}),
|
|
59
|
-
}
|
|
60
|
-
settings_path.write_text(json.dumps(settings, indent=2), encoding="utf-8")
|
|
61
|
-
|
|
62
|
-
def _restore_mcp_servers(self, mcp_path: Path) -> None:
|
|
63
|
-
backup_path = gemini_backup_path(mcp_path)
|
|
64
|
-
if not backup_path.exists():
|
|
65
|
-
return
|
|
66
|
-
backup = json.loads(backup_path.read_text(encoding="utf-8"))
|
|
67
|
-
settings_path = Path(backup["settings_path"])
|
|
68
|
-
settings = read_json_object(settings_path)
|
|
69
|
-
mcp_servers = settings.setdefault("mcpServers", {})
|
|
70
|
-
if not isinstance(mcp_servers, dict):
|
|
71
|
-
raise ValueError(f"{settings_path}: mcpServers must be an object")
|
|
72
|
-
for name, previous in backup.get("servers", {}).items():
|
|
73
|
-
if previous is None:
|
|
74
|
-
mcp_servers.pop(name, None)
|
|
75
|
-
else:
|
|
76
|
-
mcp_servers[name] = previous
|
|
77
|
-
settings_path.write_text(json.dumps(settings, indent=2), encoding="utf-8")
|
|
78
|
-
backup_path.unlink(missing_ok=True)
|
|
79
|
-
|
|
80
|
-
def auth_hint(self) -> dict[str, Any]:
|
|
81
|
-
if "GEMINI_API_KEY" in __import__("os").environ:
|
|
82
|
-
return {"status": "present", "detail": "GEMINI_API_KEY is set"}
|
|
83
|
-
if Path.home().joinpath(".gemini").exists():
|
|
84
|
-
return {"status": "present", "detail": "~/.gemini exists; run gemini to verify OAuth"}
|
|
85
|
-
return {"status": "missing_or_unknown", "detail": "run gemini OAuth setup or set GEMINI_API_KEY"}
|
|
86
|
-
|
|
87
|
-
def status_patterns(self) -> dict[str, str]:
|
|
88
|
-
return {"idle": r"\*\s+Type your message", "processing": r"\(esc to cancel", "error": "Error|APIError|Traceback"}
|
|
89
|
-
|
|
90
|
-
def exit_text(self) -> str:
|
|
91
|
-
return "\x04"
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
def gemini_backup_path(mcp_path: Path) -> Path:
|
|
95
|
-
return mcp_path.with_suffix(".gemini-backup.json")
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from typing import Any
|
|
5
|
-
|
|
6
|
-
from team_agent.permissions import resolve_permissions
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
TEAMMATE_SYSTEM_PROMPT = """# Team Agent Teammate Runtime Contract
|
|
10
|
-
|
|
11
|
-
You are a teammate in a Team Agent runtime, not the user's primary assistant.
|
|
12
|
-
The user normally talks to the team lead. Plain text you write in this worker
|
|
13
|
-
session is local to this session and is not a team message.
|
|
14
|
-
|
|
15
|
-
Use Team Agent MCP tools for team-visible coordination:
|
|
16
|
-
- Send progress, blockers, permission needs, tool failures, scope changes, and
|
|
17
|
-
long-running status updates with team_orchestrator.send_message(to='leader',
|
|
18
|
-
content='<short message>').
|
|
19
|
-
- Send to another teammate by agent id when coordination is useful, or use
|
|
20
|
-
to='*' to notify every other team member. The runtime resolves only this team
|
|
21
|
-
and excludes your own worker.
|
|
22
|
-
- When the task is complete, call team_orchestrator.report_result exactly once.
|
|
23
|
-
- Do not pass sender, task_id, agent_id, schema_version, or ack fields unless
|
|
24
|
-
doing a low-level compatibility diagnostic. The MCP runtime fills protocol
|
|
25
|
-
fields from the current worker and task state.
|
|
26
|
-
|
|
27
|
-
If you are blocked or cannot continue, message the leader promptly instead of
|
|
28
|
-
waiting silently. If work takes several minutes, send a short progress update.
|
|
29
|
-
"""
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def compile_system_prompt(agent: dict[str, Any]) -> str:
|
|
33
|
-
prompt_cfg = agent.get("system_prompt", {})
|
|
34
|
-
identity = (
|
|
35
|
-
f"You are Team Agent worker `{agent.get('id')}` with role `{agent.get('role')}`. "
|
|
36
|
-
"When asked about your role or identity, answer with this Team Agent worker identity first, "
|
|
37
|
-
"not only the generic provider product identity."
|
|
38
|
-
)
|
|
39
|
-
chunks: list[str] = [identity, TEAMMATE_SYSTEM_PROMPT]
|
|
40
|
-
if prompt_cfg.get("inline"):
|
|
41
|
-
chunks.append(str(prompt_cfg["inline"]))
|
|
42
|
-
if prompt_cfg.get("file"):
|
|
43
|
-
chunks.append(Path(prompt_cfg["file"]).read_text(encoding="utf-8"))
|
|
44
|
-
contract = agent.get("output_contract", {})
|
|
45
|
-
if contract.get("format") == "result_envelope_v1":
|
|
46
|
-
chunks.append(
|
|
47
|
-
"For progress or blockers, call team_orchestrator.send_message(to='leader', content='<short message>'); "
|
|
48
|
-
"for teammate coordination, send to another agent id or to='*' for every other team member. "
|
|
49
|
-
"do not pass sender, task_id, or requires_ack because the MCP runtime fills protocol fields. "
|
|
50
|
-
"the runtime injects it into the attached Codex leader pane when the leader has run attach-leader. "
|
|
51
|
-
"If no leader is attached, the tool returns a fallback/failed result instead of completion. "
|
|
52
|
-
"Final completion must call team_orchestrator.report_result exactly once with a short summary "
|
|
53
|
-
"and optional status/changes/tests; MCP fills schema_version, task_id, and agent_id."
|
|
54
|
-
)
|
|
55
|
-
perms = resolve_permissions(agent)
|
|
56
|
-
if perms["has_prompt_only"]:
|
|
57
|
-
prompt_only = [e["tool"] for e in perms["resolved_tools"] if e["enforcement"] == "prompt_only"]
|
|
58
|
-
chunks.append(
|
|
59
|
-
"Permission note: these tools are prompt-only for this provider and not hard-enforced: "
|
|
60
|
-
+ ", ".join(prompt_only)
|
|
61
|
-
)
|
|
62
|
-
return "\n\n".join(chunk for chunk in chunks if chunk)
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from team_agent.provider_cli.base import ProviderCliSocket
|
|
4
|
-
from team_agent.provider_cli.copilot import CopilotCliPlug
|
|
5
|
-
from team_agent.provider_cli.opencode import OpenCodeCliPlug
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
PLUG_TYPES = {
|
|
9
|
-
"opencode": OpenCodeCliPlug,
|
|
10
|
-
"copilot": CopilotCliPlug,
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def build_plug(provider: str) -> ProviderCliSocket:
|
|
15
|
-
try:
|
|
16
|
-
return PLUG_TYPES[provider]()
|
|
17
|
-
except KeyError as exc:
|
|
18
|
-
raise KeyError(f"Unsupported provider plug: {provider}") from exc
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import Any
|
|
4
|
-
|
|
5
|
-
from team_agent.provider_cli.base import ProviderCapabilityError, ProviderStartupInput
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class UnsupportedCliPlug:
|
|
9
|
-
provider = ""
|
|
10
|
-
command_name = ""
|
|
11
|
-
|
|
12
|
-
def build_command(self, startup: ProviderStartupInput) -> list[str]:
|
|
13
|
-
_ = startup
|
|
14
|
-
self._unsupported("start")
|
|
15
|
-
|
|
16
|
-
def build_resume_command(self, startup: ProviderStartupInput) -> list[str]:
|
|
17
|
-
_ = startup
|
|
18
|
-
self._unsupported("resume")
|
|
19
|
-
|
|
20
|
-
def build_fork_command(self, startup: ProviderStartupInput, source_session_id: str) -> list[str]:
|
|
21
|
-
_ = startup, source_session_id
|
|
22
|
-
self._unsupported("fork_or_branch")
|
|
23
|
-
|
|
24
|
-
def capture_session_id(self, startup: ProviderStartupInput, timeout_s: float = 3.0) -> dict[str, Any] | None:
|
|
25
|
-
_ = startup, timeout_s
|
|
26
|
-
return None
|
|
27
|
-
|
|
28
|
-
def cleanup(self, startup: ProviderStartupInput) -> None:
|
|
29
|
-
_ = startup
|
|
30
|
-
|
|
31
|
-
def _unsupported(self, capability: str) -> Any:
|
|
32
|
-
raise ProviderCapabilityError(self.provider, capability, "provider plug exists but is not implemented yet")
|