@team-agent/installer 0.5.28 → 0.5.31
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 +1 -1
- package/Cargo.toml +1 -1
- package/crates/team-agent/src/cli/adapters.rs +24 -4
- package/crates/team-agent/src/cli/diagnose.rs +1 -1
- package/crates/team-agent/src/cli/emit.rs +211 -59
- package/crates/team-agent/src/cli/mod.rs +45 -19
- package/crates/team-agent/src/cli/send.rs +19 -20
- package/crates/team-agent/src/cli/spec.rs +222 -0
- package/crates/team-agent/src/cli/status.rs +29 -0
- package/crates/team-agent/src/cli/status_port.rs +36 -4
- package/crates/team-agent/src/leader/lease.rs +166 -27
- package/crates/team-agent/src/lifecycle/launch.rs +6 -1
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +94 -2
- package/crates/team-agent/src/state/mod.rs +1 -0
- package/crates/team-agent/src/state/repository.rs +387 -0
- package/crates/team-agent/src/topology.rs +130 -5
- package/package.json +4 -4
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
//! C1 command registry: one catalog for help visibility, known-command gates,
|
|
2
|
+
//! suggestion candidates, and command-tier governance.
|
|
3
|
+
|
|
4
|
+
#![allow(dead_code)]
|
|
5
|
+
|
|
6
|
+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
7
|
+
pub(crate) enum CommandTier {
|
|
8
|
+
Core,
|
|
9
|
+
Guided,
|
|
10
|
+
Secondary,
|
|
11
|
+
DevInternal,
|
|
12
|
+
CompatHidden,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
16
|
+
pub(crate) enum CommandCategory {
|
|
17
|
+
Start,
|
|
18
|
+
Daily,
|
|
19
|
+
TeamLifecycle,
|
|
20
|
+
WorkerLifecycle,
|
|
21
|
+
GuidedRecovery,
|
|
22
|
+
Setup,
|
|
23
|
+
Observe,
|
|
24
|
+
Dev,
|
|
25
|
+
Compat,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
29
|
+
pub(crate) enum CommandKind {
|
|
30
|
+
Dispatch(DispatchKind),
|
|
31
|
+
LeaderPassthrough { provider: &'static str },
|
|
32
|
+
SpecOnlyAlias { alias_of: &'static str },
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
36
|
+
pub(crate) enum TokenUsage {
|
|
37
|
+
No,
|
|
38
|
+
Yes,
|
|
39
|
+
Conditional,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
43
|
+
pub(crate) enum DispatchKind {
|
|
44
|
+
Init,
|
|
45
|
+
QuickStart,
|
|
46
|
+
Compile,
|
|
47
|
+
Send,
|
|
48
|
+
FallbackSendLeader,
|
|
49
|
+
FallbackReportResult,
|
|
50
|
+
AllowPeerTalk,
|
|
51
|
+
Status,
|
|
52
|
+
Stop,
|
|
53
|
+
Shutdown,
|
|
54
|
+
Restart,
|
|
55
|
+
RestartAgent,
|
|
56
|
+
StartAgent,
|
|
57
|
+
StopAgent,
|
|
58
|
+
ResetAgent,
|
|
59
|
+
AddAgent,
|
|
60
|
+
ForkAgent,
|
|
61
|
+
RemoveAgent,
|
|
62
|
+
StuckList,
|
|
63
|
+
StuckCancel,
|
|
64
|
+
AcknowledgeIdle,
|
|
65
|
+
Takeover,
|
|
66
|
+
ClaimLeader,
|
|
67
|
+
AttachLeader,
|
|
68
|
+
AttachAppServerLeader,
|
|
69
|
+
Identity,
|
|
70
|
+
Approvals,
|
|
71
|
+
Inbox,
|
|
72
|
+
Doctor,
|
|
73
|
+
Watch,
|
|
74
|
+
Sessions,
|
|
75
|
+
Leaders,
|
|
76
|
+
Validate,
|
|
77
|
+
InstallSkill,
|
|
78
|
+
Profile,
|
|
79
|
+
ValidateResult,
|
|
80
|
+
Collect,
|
|
81
|
+
Settle,
|
|
82
|
+
RepairState,
|
|
83
|
+
Diagnose,
|
|
84
|
+
Preflight,
|
|
85
|
+
WaitReady,
|
|
86
|
+
E2e,
|
|
87
|
+
Peek,
|
|
88
|
+
Coordinator,
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
pub(crate) const ALL_DISPATCH_KINDS: &[DispatchKind] = &[
|
|
92
|
+
DispatchKind::Init,
|
|
93
|
+
DispatchKind::QuickStart,
|
|
94
|
+
DispatchKind::Compile,
|
|
95
|
+
DispatchKind::Send,
|
|
96
|
+
DispatchKind::FallbackSendLeader,
|
|
97
|
+
DispatchKind::FallbackReportResult,
|
|
98
|
+
DispatchKind::AllowPeerTalk,
|
|
99
|
+
DispatchKind::Status,
|
|
100
|
+
DispatchKind::Stop,
|
|
101
|
+
DispatchKind::Shutdown,
|
|
102
|
+
DispatchKind::Restart,
|
|
103
|
+
DispatchKind::RestartAgent,
|
|
104
|
+
DispatchKind::StartAgent,
|
|
105
|
+
DispatchKind::StopAgent,
|
|
106
|
+
DispatchKind::ResetAgent,
|
|
107
|
+
DispatchKind::AddAgent,
|
|
108
|
+
DispatchKind::ForkAgent,
|
|
109
|
+
DispatchKind::RemoveAgent,
|
|
110
|
+
DispatchKind::StuckList,
|
|
111
|
+
DispatchKind::StuckCancel,
|
|
112
|
+
DispatchKind::AcknowledgeIdle,
|
|
113
|
+
DispatchKind::Takeover,
|
|
114
|
+
DispatchKind::ClaimLeader,
|
|
115
|
+
DispatchKind::AttachLeader,
|
|
116
|
+
DispatchKind::AttachAppServerLeader,
|
|
117
|
+
DispatchKind::Identity,
|
|
118
|
+
DispatchKind::Approvals,
|
|
119
|
+
DispatchKind::Inbox,
|
|
120
|
+
DispatchKind::Doctor,
|
|
121
|
+
DispatchKind::Watch,
|
|
122
|
+
DispatchKind::Sessions,
|
|
123
|
+
DispatchKind::Leaders,
|
|
124
|
+
DispatchKind::Validate,
|
|
125
|
+
DispatchKind::InstallSkill,
|
|
126
|
+
DispatchKind::Profile,
|
|
127
|
+
DispatchKind::ValidateResult,
|
|
128
|
+
DispatchKind::Collect,
|
|
129
|
+
DispatchKind::Settle,
|
|
130
|
+
DispatchKind::RepairState,
|
|
131
|
+
DispatchKind::Diagnose,
|
|
132
|
+
DispatchKind::Preflight,
|
|
133
|
+
DispatchKind::WaitReady,
|
|
134
|
+
DispatchKind::E2e,
|
|
135
|
+
DispatchKind::Peek,
|
|
136
|
+
DispatchKind::Coordinator,
|
|
137
|
+
];
|
|
138
|
+
|
|
139
|
+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
140
|
+
pub(crate) struct GovernanceNote {
|
|
141
|
+
pub(crate) decision: &'static str,
|
|
142
|
+
pub(crate) reason: &'static str,
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
146
|
+
pub(crate) struct CommandSpec {
|
|
147
|
+
pub(crate) name: &'static str,
|
|
148
|
+
pub(crate) tier: CommandTier,
|
|
149
|
+
pub(crate) category: CommandCategory,
|
|
150
|
+
pub(crate) kind: CommandKind,
|
|
151
|
+
pub(crate) summary: &'static str,
|
|
152
|
+
pub(crate) usage: &'static str,
|
|
153
|
+
pub(crate) default_help: bool,
|
|
154
|
+
pub(crate) command_help: bool,
|
|
155
|
+
pub(crate) suggestion_index: bool,
|
|
156
|
+
pub(crate) token_usage: TokenUsage,
|
|
157
|
+
pub(crate) alias_of: Option<&'static str>,
|
|
158
|
+
pub(crate) sunset: Option<&'static str>,
|
|
159
|
+
pub(crate) action: Option<&'static str>,
|
|
160
|
+
pub(crate) governance: Option<GovernanceNote>,
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
#[rustfmt::skip]
|
|
164
|
+
pub(crate) const COMMAND_SPECS: &[CommandSpec] = &[
|
|
165
|
+
CommandSpec { name: "quick-start", tier: CommandTier::Core, category: CommandCategory::Start, kind: CommandKind::Dispatch(DispatchKind::QuickStart), summary: "start or attach a team from TEAM.md", usage: "usage: team-agent quick-start [TEAMDIR] [--workspace WORKSPACE] [--name NAME] [--team-id TEAM|--team TEAM] [--yes] [--no-display] [--backend tmux|conpty] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::Conditional, alias_of: None, sunset: None, action: None, governance: None },
|
|
166
|
+
CommandSpec { name: "send", tier: CommandTier::Core, category: CommandCategory::Daily, kind: CommandKind::Dispatch(DispatchKind::Send), summary: "send a message/task", usage: "usage: team-agent send TARGET MESSAGE... [--workspace WORKSPACE] [--team TEAM] [--targets AGENTS] [--to-name NAME] [--pane PANE] [--task TASK] [--sender SENDER] [--watch-result] [--requires-ack|--no-ack] [--no-wait] [--timeout SECONDS] [--confirm-human] [--message-id ID] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::Conditional, alias_of: None, sunset: None, action: None, governance: None },
|
|
167
|
+
CommandSpec { name: "status", tier: CommandTier::Core, category: CommandCategory::Daily, kind: CommandKind::Dispatch(DispatchKind::Status), summary: "show current team status", usage: "usage: team-agent status [AGENT] [--workspace WORKSPACE] [--team TEAM] [--summary|--json] [--detail]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
168
|
+
CommandSpec { name: "collect", tier: CommandTier::Core, category: CommandCategory::Daily, kind: CommandKind::Dispatch(DispatchKind::Collect), summary: "collect reported results", usage: "usage: team-agent collect [--workspace WORKSPACE] [--team TEAM] [--result-file FILE] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
169
|
+
CommandSpec { name: "restart", tier: CommandTier::Core, category: CommandCategory::TeamLifecycle, kind: CommandKind::Dispatch(DispatchKind::Restart), summary: "restart the selected team", usage: "usage: team-agent restart [WORKSPACE] [--team TEAM] [--allow-fresh] [--session-converge-deadline SECONDS] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::Conditional, alias_of: None, sunset: None, action: None, governance: None },
|
|
170
|
+
CommandSpec { name: "shutdown", tier: CommandTier::Core, category: CommandCategory::TeamLifecycle, kind: CommandKind::Dispatch(DispatchKind::Shutdown), summary: "stop the selected team", usage: "usage: team-agent shutdown [--workspace WORKSPACE] [--team TEAM] [--keep-logs] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
171
|
+
CommandSpec { name: "add-agent", tier: CommandTier::Core, category: CommandCategory::WorkerLifecycle, kind: CommandKind::Dispatch(DispatchKind::AddAgent), summary: "add a worker", usage: "usage: team-agent add-agent AGENT --role-file FILE [--workspace WORKSPACE] [--team TEAM] [--no-display] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::Conditional, alias_of: None, sunset: None, action: None, governance: None },
|
|
172
|
+
CommandSpec { name: "start-agent", tier: CommandTier::Core, category: CommandCategory::WorkerLifecycle, kind: CommandKind::Dispatch(DispatchKind::StartAgent), summary: "start an existing worker", usage: "usage: team-agent start-agent AGENT [--workspace WORKSPACE] [--team TEAM] [--force] [--allow-fresh] [--no-display] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::Conditional, alias_of: None, sunset: None, action: None, governance: None },
|
|
173
|
+
CommandSpec { name: "stop-agent", tier: CommandTier::Core, category: CommandCategory::WorkerLifecycle, kind: CommandKind::Dispatch(DispatchKind::StopAgent), summary: "stop a worker", usage: "usage: team-agent stop-agent AGENT [--workspace WORKSPACE] [--team TEAM] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
174
|
+
CommandSpec { name: "reset-agent", tier: CommandTier::Core, category: CommandCategory::WorkerLifecycle, kind: CommandKind::Dispatch(DispatchKind::ResetAgent), summary: "reset a worker session", usage: "usage: team-agent reset-agent AGENT [--workspace WORKSPACE] [--team TEAM] [--discard-session] [--no-display] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::Conditional, alias_of: None, sunset: None, action: None, governance: None },
|
|
175
|
+
CommandSpec { name: "diagnose", tier: CommandTier::Core, category: CommandCategory::Observe, kind: CommandKind::Dispatch(DispatchKind::Diagnose), summary: "inspect this workspace runtime and suggested repairs", usage: "usage: team-agent diagnose [--workspace WORKSPACE] [--team TEAM] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
176
|
+
CommandSpec { name: "claim-leader", tier: CommandTier::Guided, category: CommandCategory::GuidedRecovery, kind: CommandKind::Dispatch(DispatchKind::ClaimLeader), summary: "bind this pane when diagnose reports rebind_required", usage: "usage: team-agent claim-leader [--workspace WORKSPACE] [--team TEAM] [--confirm] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
177
|
+
CommandSpec { name: "takeover", tier: CommandTier::Guided, category: CommandCategory::GuidedRecovery, kind: CommandKind::Dispatch(DispatchKind::Takeover), summary: "replace a live leader binding with explicit consent", usage: "usage: team-agent takeover [--workspace WORKSPACE] [--team TEAM] [--confirm] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
178
|
+
CommandSpec { name: "attach-leader", tier: CommandTier::Guided, category: CommandCategory::GuidedRecovery, kind: CommandKind::Dispatch(DispatchKind::AttachLeader), summary: "bind an external leader pane", usage: "usage: team-agent attach-leader [--workspace WORKSPACE] [--team TEAM] [--pane PANE] [--provider PROVIDER] [--confirm] [--json]", default_help: true, command_help: true, suggestion_index: true, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
179
|
+
|
|
180
|
+
CommandSpec { name: "codex", tier: CommandTier::Core, category: CommandCategory::Start, kind: CommandKind::LeaderPassthrough { provider: "codex" }, summary: "launch a Codex leader", usage: "usage: team-agent codex [provider args...]", default_help: false, command_help: true, suggestion_index: true, token_usage: TokenUsage::Yes, alias_of: None, sunset: None, action: None, governance: None },
|
|
181
|
+
CommandSpec { name: "claude", tier: CommandTier::Core, category: CommandCategory::Start, kind: CommandKind::LeaderPassthrough { provider: "claude" }, summary: "launch a Claude leader", usage: "usage: team-agent claude [provider args...]", default_help: false, command_help: true, suggestion_index: true, token_usage: TokenUsage::Yes, alias_of: None, sunset: None, action: None, governance: None },
|
|
182
|
+
CommandSpec { name: "copilot", tier: CommandTier::Core, category: CommandCategory::Start, kind: CommandKind::LeaderPassthrough { provider: "copilot" }, summary: "launch a Copilot leader", usage: "usage: team-agent copilot [provider args...]", default_help: false, command_help: true, suggestion_index: true, token_usage: TokenUsage::Yes, alias_of: None, sunset: None, action: None, governance: None },
|
|
183
|
+
|
|
184
|
+
CommandSpec { name: "init", tier: CommandTier::CompatHidden, category: CommandCategory::Compat, kind: CommandKind::Dispatch(DispatchKind::Init), summary: "legacy bootstrap command", usage: "usage: team-agent init [--workspace WORKSPACE] [--force] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: Some("quick-start"), sunset: Some("C2"), action: Some("use `team-agent quick-start`"), governance: None },
|
|
185
|
+
CommandSpec { name: "start", tier: CommandTier::CompatHidden, category: CommandCategory::Compat, kind: CommandKind::SpecOnlyAlias { alias_of: "quick-start" }, summary: "legacy start alias", usage: "usage: team-agent start [TEAMDIR] [--yes] [--fresh] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::Conditional, alias_of: Some("quick-start"), sunset: Some("C2"), action: Some("use `team-agent quick-start` or `team-agent restart`"), governance: None },
|
|
186
|
+
CommandSpec { name: "stop", tier: CommandTier::CompatHidden, category: CommandCategory::Compat, kind: CommandKind::Dispatch(DispatchKind::Stop), summary: "legacy shutdown alias", usage: "usage: team-agent stop [--workspace WORKSPACE] [--team TEAM] [--keep-logs] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: Some("shutdown"), sunset: Some("C2"), action: Some("use `team-agent shutdown`"), governance: None },
|
|
187
|
+
CommandSpec { name: "restart-agent", tier: CommandTier::CompatHidden, category: CommandCategory::Compat, kind: CommandKind::Dispatch(DispatchKind::RestartAgent), summary: "legacy reset-agent alias", usage: "usage: team-agent restart-agent AGENT [--workspace WORKSPACE] [--team TEAM] [--discard-session] [--no-display] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::Conditional, alias_of: Some("reset-agent"), sunset: Some("C2"), action: Some("use `team-agent reset-agent`"), governance: None },
|
|
188
|
+
CommandSpec { name: "fallback-send-leader", tier: CommandTier::CompatHidden, category: CommandCategory::Compat, kind: CommandKind::Dispatch(DispatchKind::FallbackSendLeader), summary: "legacy leader send fallback", usage: "usage: team-agent fallback-send-leader --workspace WORKSPACE --team TEAM --sender AGENT --message-id ID --content TEXT --primary-error ERROR [--task TASK] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: Some("C2"), action: Some("use `team-agent send` and `team-agent diagnose`"), governance: None },
|
|
189
|
+
CommandSpec { name: "fallback-report-result", tier: CommandTier::CompatHidden, category: CommandCategory::Compat, kind: CommandKind::Dispatch(DispatchKind::FallbackReportResult), summary: "legacy report_result fallback", usage: "usage: team-agent fallback-report-result --workspace WORKSPACE --team TEAM --agent-id AGENT --task-id TASK --result-json JSON --primary-error ERROR [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: Some("C2"), action: Some("use `team-agent collect` or MCP `report_result`"), governance: None },
|
|
190
|
+
CommandSpec { name: "settle", tier: CommandTier::CompatHidden, category: CommandCategory::Compat, kind: CommandKind::Dispatch(DispatchKind::Settle), summary: "legacy settle helper", usage: "usage: team-agent settle [--workspace WORKSPACE] [--team TEAM] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: Some("C2"), action: Some("use `team-agent collect`"), governance: None },
|
|
191
|
+
CommandSpec { name: "validate-result", tier: CommandTier::CompatHidden, category: CommandCategory::Compat, kind: CommandKind::Dispatch(DispatchKind::ValidateResult), summary: "legacy result validation helper", usage: "usage: team-agent validate-result [ENVELOPE] [--file FILE|--result JSON] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: Some("C2"), action: Some("use report_result validation through normal `team-agent collect` flow"), governance: None },
|
|
192
|
+
CommandSpec { name: "stuck-list", tier: CommandTier::CompatHidden, category: CommandCategory::Compat, kind: CommandKind::Dispatch(DispatchKind::StuckList), summary: "legacy stuck alert listing", usage: "usage: team-agent stuck-list [--workspace WORKSPACE] [--team TEAM] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: Some("C2"), action: Some("use `team-agent diagnose`"), governance: None },
|
|
193
|
+
CommandSpec { name: "stuck-cancel", tier: CommandTier::CompatHidden, category: CommandCategory::Compat, kind: CommandKind::Dispatch(DispatchKind::StuckCancel), summary: "legacy stuck alert suppression", usage: "usage: team-agent stuck-cancel AGENT [--workspace WORKSPACE] [--alert-type stuck|idle_fallback|cross_worker_deadlock|all] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: Some("C2"), action: Some("use the concrete notification action or `team-agent diagnose`"), governance: None },
|
|
194
|
+
CommandSpec { name: "acknowledge-idle", tier: CommandTier::CompatHidden, category: CommandCategory::Compat, kind: CommandKind::Dispatch(DispatchKind::AcknowledgeIdle), summary: "legacy idle acknowledgement", usage: "usage: team-agent acknowledge-idle [--workspace WORKSPACE] [--team TEAM] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: Some("C2"), action: Some("use the concrete idle notification action or `team-agent diagnose`"), governance: None },
|
|
195
|
+
|
|
196
|
+
CommandSpec { name: "repair-state", tier: CommandTier::Guided, category: CommandCategory::GuidedRecovery, kind: CommandKind::Dispatch(DispatchKind::RepairState), summary: "guided state repair helper", usage: "usage: team-agent repair-state --task TASK --status STATUS [SUMMARY] [--assignee AGENT] [--workspace WORKSPACE] [--team TEAM] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
197
|
+
CommandSpec { name: "leaders", tier: CommandTier::Secondary, category: CommandCategory::Observe, kind: CommandKind::Dispatch(DispatchKind::Leaders), summary: "inspect registered host leaders", usage: "usage: team-agent leaders [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
198
|
+
CommandSpec { name: "doctor", tier: CommandTier::Secondary, category: CommandCategory::Setup, kind: CommandKind::Dispatch(DispatchKind::Doctor), summary: "run host maintenance checks", usage: "usage: team-agent doctor [SPEC] [--workspace WORKSPACE] [--team TEAM] [--gate orphans|comms] [--comms] [--fix] [--fix-schema] [--cleanup-orphans] [--confirm] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
199
|
+
CommandSpec { name: "attach-app-server-leader", tier: CommandTier::Guided, category: CommandCategory::GuidedRecovery, kind: CommandKind::Dispatch(DispatchKind::AttachAppServerLeader), summary: "bind an app-server leader receiver", usage: "usage: team-agent attach-app-server-leader [--workspace WORKSPACE] [--team TEAM] --socket unix:///path.sock --thread-id THREAD_ID [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
200
|
+
CommandSpec { name: "remove-agent", tier: CommandTier::Secondary, category: CommandCategory::WorkerLifecycle, kind: CommandKind::Dispatch(DispatchKind::RemoveAgent), summary: "remove a worker", usage: "usage: team-agent remove-agent AGENT [--workspace WORKSPACE] [--team TEAM] [--from-spec] [--confirm] [--force] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
201
|
+
CommandSpec { name: "fork-agent", tier: CommandTier::Secondary, category: CommandCategory::WorkerLifecycle, kind: CommandKind::Dispatch(DispatchKind::ForkAgent), summary: "fork a worker", usage: "usage: team-agent fork-agent SOURCE_AGENT --as AGENT [--label LABEL] [--workspace WORKSPACE] [--team TEAM] [--no-display] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::Conditional, alias_of: None, sunset: None, action: None, governance: None },
|
|
202
|
+
CommandSpec { name: "allow-peer-talk", tier: CommandTier::Secondary, category: CommandCategory::Setup, kind: CommandKind::Dispatch(DispatchKind::AllowPeerTalk), summary: "allow direct worker peer talk", usage: "usage: team-agent allow-peer-talk A B [--workspace WORKSPACE] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: Some(GovernanceNote { decision: "secondary", reason: "capability/config surface" }) },
|
|
203
|
+
CommandSpec { name: "approvals", tier: CommandTier::Secondary, category: CommandCategory::Observe, kind: CommandKind::Dispatch(DispatchKind::Approvals), summary: "inspect provider approval state", usage: "usage: team-agent approvals [AGENT] [--workspace WORKSPACE] [--team TEAM] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: Some(GovernanceNote { decision: "secondary", reason: "approval diagnostics" }) },
|
|
204
|
+
CommandSpec { name: "profile", tier: CommandTier::Secondary, category: CommandCategory::Setup, kind: CommandKind::Dispatch(DispatchKind::Profile), summary: "manage provider profiles", usage: "usage: team-agent profile COMMAND NAME [--workspace WORKSPACE] [--team TEAM] [--auth-mode MODE] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: Some(GovernanceNote { decision: "secondary", reason: "provider/profile setup" }) },
|
|
205
|
+
CommandSpec { name: "install-skill", tier: CommandTier::Secondary, category: CommandCategory::Setup, kind: CommandKind::Dispatch(DispatchKind::InstallSkill), summary: "install or uninstall Team Agent skills", usage: "usage: team-agent install-skill (--source DIR | --uninstall) [--target codex|claude|copilot|all] [--dest DIR] [--dry-run] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: Some(GovernanceNote { decision: "secondary", reason: "capability setup" }) },
|
|
206
|
+
CommandSpec { name: "inbox", tier: CommandTier::Secondary, category: CommandCategory::Observe, kind: CommandKind::Dispatch(DispatchKind::Inbox), summary: "inspect queued messages", usage: "usage: team-agent inbox AGENT [--workspace WORKSPACE] [--team TEAM] [--limit N] [--since CURSOR] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
207
|
+
|
|
208
|
+
CommandSpec { name: "identity", tier: CommandTier::DevInternal, category: CommandCategory::Dev, kind: CommandKind::Dispatch(DispatchKind::Identity), summary: "inspect identity metadata", usage: "usage: team-agent identity [--workspace WORKSPACE] [--team TEAM] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
209
|
+
CommandSpec { name: "watch", tier: CommandTier::DevInternal, category: CommandCategory::Dev, kind: CommandKind::Dispatch(DispatchKind::Watch), summary: "watch event logs", usage: "usage: team-agent watch [--workspace WORKSPACE] [--team TEAM]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
210
|
+
CommandSpec { name: "sessions", tier: CommandTier::DevInternal, category: CommandCategory::Dev, kind: CommandKind::Dispatch(DispatchKind::Sessions), summary: "inspect session inventory", usage: "usage: team-agent sessions [--workspace WORKSPACE] [--team TEAM] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
211
|
+
CommandSpec { name: "compile", tier: CommandTier::DevInternal, category: CommandCategory::Dev, kind: CommandKind::Dispatch(DispatchKind::Compile), summary: "compile a team spec", usage: "usage: team-agent compile --team TEAM [--out FILE] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
212
|
+
CommandSpec { name: "validate", tier: CommandTier::DevInternal, category: CommandCategory::Dev, kind: CommandKind::Dispatch(DispatchKind::Validate), summary: "validate a team spec", usage: "usage: team-agent validate [SPEC] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
213
|
+
CommandSpec { name: "preflight", tier: CommandTier::DevInternal, category: CommandCategory::Dev, kind: CommandKind::Dispatch(DispatchKind::Preflight), summary: "run preflight checks", usage: "usage: team-agent preflight [TEAMDIR] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
214
|
+
CommandSpec { name: "wait-ready", tier: CommandTier::DevInternal, category: CommandCategory::Dev, kind: CommandKind::Dispatch(DispatchKind::WaitReady), summary: "wait for runtime readiness", usage: "usage: team-agent wait-ready [--workspace WORKSPACE] [--team TEAM] [--timeout SECONDS] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
215
|
+
CommandSpec { name: "e2e", tier: CommandTier::DevInternal, category: CommandCategory::Dev, kind: CommandKind::Dispatch(DispatchKind::E2e), summary: "run e2e harness", usage: "usage: team-agent e2e [--workspace WORKSPACE] [--providers LIST] [--real] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::Yes, alias_of: None, sunset: None, action: None, governance: None },
|
|
216
|
+
CommandSpec { name: "peek", tier: CommandTier::DevInternal, category: CommandCategory::Dev, kind: CommandKind::Dispatch(DispatchKind::Peek), summary: "capture low-level terminal output", usage: "usage: team-agent peek AGENT [--workspace WORKSPACE] [--tail N|--head N] [--search TEXT] [--allow-raw-screen] [--json]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
217
|
+
CommandSpec { name: "coordinator", tier: CommandTier::DevInternal, category: CommandCategory::Dev, kind: CommandKind::Dispatch(DispatchKind::Coordinator), summary: "run the coordinator daemon", usage: "usage: team-agent coordinator [--workspace WORKSPACE] [--once] [--tick-interval SECONDS]", default_help: false, command_help: true, suggestion_index: false, token_usage: TokenUsage::No, alias_of: None, sunset: None, action: None, governance: None },
|
|
218
|
+
];
|
|
219
|
+
|
|
220
|
+
pub(crate) fn command_spec(name: &str) -> Option<&'static CommandSpec> {
|
|
221
|
+
COMMAND_SPECS.iter().find(|spec| spec.name == name)
|
|
222
|
+
}
|
|
@@ -32,6 +32,17 @@ pub fn agent_summary_counts(agents: &Value, health: &Value) -> SummaryCounts {
|
|
|
32
32
|
return counts;
|
|
33
33
|
};
|
|
34
34
|
for (agent_id, agent) in agent_map {
|
|
35
|
+
if let Some(bucket) = stale_agent_bucket(agent) {
|
|
36
|
+
match bucket {
|
|
37
|
+
SummaryBucket::Stopped => counts.stopped += 1,
|
|
38
|
+
SummaryBucket::Unknown => counts.unknown += 1,
|
|
39
|
+
SummaryBucket::Running
|
|
40
|
+
| SummaryBucket::Busy
|
|
41
|
+
| SummaryBucket::Idle
|
|
42
|
+
| SummaryBucket::Failed => {}
|
|
43
|
+
}
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
35
46
|
let raw = agent
|
|
36
47
|
.get("status")
|
|
37
48
|
.and_then(Value::as_str)
|
|
@@ -53,6 +64,21 @@ pub fn agent_summary_counts(agents: &Value, health: &Value) -> SummaryCounts {
|
|
|
53
64
|
counts
|
|
54
65
|
}
|
|
55
66
|
|
|
67
|
+
fn stale_agent_bucket(agent: &Value) -> Option<SummaryBucket> {
|
|
68
|
+
if agent.get("stale").and_then(Value::as_bool) != Some(true) {
|
|
69
|
+
return None;
|
|
70
|
+
}
|
|
71
|
+
if agent
|
|
72
|
+
.get("stale_reason")
|
|
73
|
+
.and_then(Value::as_str)
|
|
74
|
+
.is_some_and(|reason| !reason.is_empty())
|
|
75
|
+
{
|
|
76
|
+
Some(SummaryBucket::Stopped)
|
|
77
|
+
} else {
|
|
78
|
+
Some(SummaryBucket::Unknown)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
56
82
|
/// `_interaction_counts`(`commands.py:292-306`):遍历 agents 的 `interacted` 字段。
|
|
57
83
|
pub fn interaction_counts(agents: &Value) -> InteractionCounts {
|
|
58
84
|
let mut counts = InteractionCounts::default();
|
|
@@ -165,6 +191,9 @@ fn csv_agent_status(
|
|
|
165
191
|
agent: &Value,
|
|
166
192
|
health: Option<&serde_json::Map<String, Value>>,
|
|
167
193
|
) -> &'static str {
|
|
194
|
+
if stale_agent_bucket(agent).is_some() {
|
|
195
|
+
return "错误";
|
|
196
|
+
}
|
|
168
197
|
let raw = agent
|
|
169
198
|
.get("status")
|
|
170
199
|
.and_then(Value::as_str)
|
|
@@ -34,12 +34,13 @@ use rusqlite::params;
|
|
|
34
34
|
// backlog>0 才挂 down-hint(anti-nag)。auto-recovery 不做(user 已裁)。
|
|
35
35
|
let coordinator_running = coordinator_status_running(&health);
|
|
36
36
|
let undelivered_backlog = count_undelivered_backlog(&conn, owner_team_id)?;
|
|
37
|
+
let session_name = state.get("session_name").cloned().unwrap_or(Value::Null);
|
|
38
|
+
let tmux_present = tmux_session_present(workspace, state, session_name.as_str());
|
|
37
39
|
let runtime_block = build_runtime_status_block(
|
|
38
40
|
coordinator_running,
|
|
39
41
|
undelivered_backlog,
|
|
42
|
+
!tmux_present,
|
|
40
43
|
);
|
|
41
|
-
let session_name = state.get("session_name").cloned().unwrap_or(Value::Null);
|
|
42
|
-
let tmux_present = tmux_session_present(workspace, state, session_name.as_str());
|
|
43
44
|
let agents = enrich_agents(state.get("agents"), tmux_present);
|
|
44
45
|
let tasks = state
|
|
45
46
|
.get("tasks")
|
|
@@ -458,6 +459,9 @@ use rusqlite::params;
|
|
|
458
459
|
"stale_reason".to_string(),
|
|
459
460
|
Value::String(reason.to_string()),
|
|
460
461
|
);
|
|
462
|
+
if !tmux_session_present {
|
|
463
|
+
downgrade_stale_agent(&mut enriched);
|
|
464
|
+
}
|
|
461
465
|
}
|
|
462
466
|
out.insert(agent_id.clone(), Value::Object(enriched));
|
|
463
467
|
}
|
|
@@ -469,6 +473,25 @@ use rusqlite::params;
|
|
|
469
473
|
Value::Object(out)
|
|
470
474
|
}
|
|
471
475
|
|
|
476
|
+
fn downgrade_stale_agent(agent: &mut Map<String, Value>) {
|
|
477
|
+
let raw = agent
|
|
478
|
+
.get("status")
|
|
479
|
+
.and_then(Value::as_str)
|
|
480
|
+
.unwrap_or("")
|
|
481
|
+
.to_ascii_lowercase();
|
|
482
|
+
if matches!(raw.as_str(), "running" | "busy" | "working" | "idle") {
|
|
483
|
+
agent.insert("status".to_string(), Value::String("stopped".to_string()));
|
|
484
|
+
}
|
|
485
|
+
let worker_state = agent
|
|
486
|
+
.get("worker_state")
|
|
487
|
+
.and_then(Value::as_str)
|
|
488
|
+
.unwrap_or("")
|
|
489
|
+
.to_ascii_uppercase();
|
|
490
|
+
if matches!(worker_state.as_str(), "RUNNING" | "BUSY" | "PROBABLY_IDLE") {
|
|
491
|
+
agent.insert("worker_state".to_string(), Value::String("DEAD".to_string()));
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
472
495
|
fn stale_reason_for_agent(agent: &Value, tmux_session_present: bool) -> Option<&'static str> {
|
|
473
496
|
let pane_dead = !tmux_session_present && agent_has_pane_fact(agent);
|
|
474
497
|
let process_dead =
|
|
@@ -1093,14 +1116,23 @@ use rusqlite::params;
|
|
|
1093
1116
|
/// B-5 / 036b N38 — status 出口的 runtime 块:把 coordinator_health 与
|
|
1094
1117
|
/// undelivered backlog 合体暴露。down-hint 只在【coordinator 不在跑 ∧ 有 backlog】
|
|
1095
1118
|
/// 两条件同时满足才挂(anti-nag);健康状态下不挂提示。auto-recovery 不做。
|
|
1096
|
-
fn build_runtime_status_block(
|
|
1119
|
+
fn build_runtime_status_block(
|
|
1120
|
+
coordinator_running: bool,
|
|
1121
|
+
undelivered: i64,
|
|
1122
|
+
tmux_session_missing: bool,
|
|
1123
|
+
) -> Value {
|
|
1097
1124
|
let mut runtime = serde_json::Map::new();
|
|
1098
1125
|
runtime.insert(
|
|
1099
1126
|
"coordinator".to_string(),
|
|
1100
1127
|
json!({"ok": coordinator_running}),
|
|
1101
1128
|
);
|
|
1102
1129
|
runtime.insert("undelivered".to_string(), json!(undelivered));
|
|
1103
|
-
if
|
|
1130
|
+
if tmux_session_missing {
|
|
1131
|
+
runtime.insert(
|
|
1132
|
+
"hint".to_string(),
|
|
1133
|
+
json!("tmux session missing — run team-agent restart"),
|
|
1134
|
+
);
|
|
1135
|
+
} else if !coordinator_running && undelivered > 0 {
|
|
1104
1136
|
runtime.insert(
|
|
1105
1137
|
"hint".to_string(),
|
|
1106
1138
|
json!(format!(
|