@team-agent/installer 0.5.111 → 0.5.113
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 +93 -779
- package/crates/team-agent/src/cli/diagnose.rs +2 -424
- package/crates/team-agent/src/cli/emit.rs +158 -373
- package/crates/team-agent/src/cli/leaders.rs +32 -32
- package/crates/team-agent/src/cli/mod.rs +8 -15
- package/crates/team-agent/src/cli/named_address.rs +17 -16
- package/crates/team-agent/src/cli/route.rs +4 -4
- package/crates/team-agent/src/cli/send/presentation.rs +19 -18
- package/crates/team-agent/src/cli/send/resolve.rs +11 -11
- package/crates/team-agent/src/cli/send.rs +4 -4
- package/crates/team-agent/src/cli/spec.rs +29 -32
- package/crates/team-agent/src/cli/status.rs +7 -7
- package/crates/team-agent/src/cli/tests/base.rs +6 -6
- package/crates/team-agent/src/cli/tests/divergence.rs +3 -2
- package/crates/team-agent/src/cli/tests/lane_c.rs +1 -1
- package/crates/team-agent/src/cli/tests/leader_watch.rs +2 -86
- package/crates/team-agent/src/cli/tests/main_preserved.rs +15 -140
- package/crates/team-agent/src/cli/tests/missing_subcommands.rs +1 -258
- package/crates/team-agent/src/cli/tests/mod.rs +0 -2
- package/crates/team-agent/src/cli/tests/named_address.rs +3 -3
- package/crates/team-agent/src/cli/tests/status_send.rs +7 -7
- package/crates/team-agent/src/cli/triage.rs +53 -2
- package/crates/team-agent/src/cli/types.rs +12 -116
- package/crates/team-agent/src/compiler/tests.rs +12 -0
- package/crates/team-agent/src/compiler.rs +0 -9
- package/crates/team-agent/src/coordinator/health.rs +3 -283
- package/crates/team-agent/src/coordinator/mod.rs +0 -5
- package/crates/team-agent/src/coordinator/tests/basics.rs +0 -9
- package/crates/team-agent/src/coordinator/tests/mod.rs +0 -1
- package/crates/team-agent/src/coordinator/tests/tick_core.rs +0 -17
- package/crates/team-agent/src/coordinator/types.rs +1 -21
- package/crates/team-agent/src/db/message_store.rs +0 -42
- package/crates/team-agent/src/db/migration.rs +49 -9
- package/crates/team-agent/src/db/schema.rs +27 -20
- package/crates/team-agent/src/leader/owner_bind.rs +0 -24
- package/crates/team-agent/src/leader/start.rs +5 -0
- package/crates/team-agent/src/leader/tests/byte_findings.rs +0 -20
- package/crates/team-agent/src/leader/tests/identity.rs +21 -32
- package/crates/team-agent/src/leader/tests/lease_claim.rs +0 -55
- package/crates/team-agent/src/lifecycle/launch/identity.rs +172 -13
- package/crates/team-agent/src/lifecycle/launch/quick_start.rs +325 -14
- package/crates/team-agent/src/lifecycle/launch.rs +2 -2
- package/crates/team-agent/src/lifecycle/profile_launch.rs +58 -46
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +97 -52
- package/crates/team-agent/src/lifecycle/restart.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/restart_session_capture_red.rs +2 -51
- package/crates/team-agent/src/lifecycle/tests/stale_team_saveconflict_contract.rs +3 -2
- package/crates/team-agent/src/lifecycle/tests/status_credential_redaction_contract.rs +23 -23
- package/crates/team-agent/src/lifecycle/tests/subprep_codex_trust_roundtrip_red.rs +29 -55
- package/crates/team-agent/src/messaging/mod.rs +0 -2
- package/crates/team-agent/src/messaging/results.rs +0 -58
- package/crates/team-agent/src/messaging/tests/runtime.rs +0 -46
- package/crates/team-agent/src/provider/adapter.rs +8 -59
- package/crates/team-agent/src/provider/adapters/claude.rs +6 -14
- package/crates/team-agent/src/provider/adapters/codex.rs +8 -18
- package/crates/team-agent/src/provider/adapters/copilot.rs +5 -22
- package/crates/team-agent/src/provider/adapters/cursor_agent.rs +8 -45
- package/crates/team-agent/src/provider/adapters/grok.rs +7 -31
- package/crates/team-agent/src/provider/adapters/pi.rs +7 -18
- package/crates/team-agent/src/provider/command_helpers.rs +45 -0
- package/crates/team-agent/src/provider/mod.rs +1 -0
- package/crates/team-agent/src/provider/model_catalog.rs +21 -28
- package/crates/team-agent/src/provider/tests/adapter.rs +70 -0
- package/crates/team-agent/src/provider/tests/command_helpers.rs +55 -0
- package/crates/team-agent/src/state/repository.rs +1 -5
- package/package.json +4 -4
- package/templates/team_state.md +1 -1
- package/crates/team-agent/src/cli/tests/peer_allow.rs +0 -164
- package/crates/team-agent/src/cli/tests/verb_validate.rs +0 -195
- package/crates/team-agent/src/coordinator/tests/watch.rs +0 -223
- package/crates/team-agent/src/messaging/peers.rs +0 -34
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
use super::*;
|
|
2
|
-
|
|
3
|
-
// ═════════════════════════════════════════════════════════════════════════
|
|
4
|
-
// GROUP G — watch render_event_line (watch.py:46) — golden text — RED
|
|
5
|
-
// exact strings captured via PYTHONPATH probe against v0.2.11.
|
|
6
|
-
// ═════════════════════════════════════════════════════════════════════════
|
|
7
|
-
|
|
8
|
-
#[test]
|
|
9
|
-
fn render_result_received_collapses_whitespace_and_defaults() {
|
|
10
|
-
// watch.py:48-49 + _result_line — "result_received: <agent|-> -> <clean summary>".
|
|
11
|
-
let e = serde_json::json!({"event": "result_received", "agent_id": "w1", "summary": "did the\nthing"});
|
|
12
|
-
assert_eq!(
|
|
13
|
-
render_event_line(&e),
|
|
14
|
-
Some("result_received: w1 -> did the thing".to_string())
|
|
15
|
-
);
|
|
16
|
-
// missing agent + summary → both '-'.
|
|
17
|
-
let bare = serde_json::json!({"event": "result_received"});
|
|
18
|
-
assert_eq!(
|
|
19
|
-
render_event_line(&bare),
|
|
20
|
-
Some("result_received: - -> -".to_string())
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
#[test]
|
|
25
|
-
fn render_injected_and_submitted_share_prefix_and_truncate_message_id() {
|
|
26
|
-
// watch.py:50-51 — both render as "leader_receiver.injected"; message_id truncated to 12.
|
|
27
|
-
let inj = serde_json::json!({"event": "leader_receiver.injected", "message_id": "abcdef0123456789", "recipient": "w2"});
|
|
28
|
-
assert_eq!(
|
|
29
|
-
render_event_line(&inj),
|
|
30
|
-
Some("leader_receiver.injected: abcdef012345 -> w2".to_string())
|
|
31
|
-
);
|
|
32
|
-
// submitted uses same label, msg_id fallback, `to` recipient fallback.
|
|
33
|
-
let sub = serde_json::json!({"event": "leader_receiver.submitted", "msg_id": "xy", "to": "w3"});
|
|
34
|
-
assert_eq!(
|
|
35
|
-
render_event_line(&sub),
|
|
36
|
-
Some("leader_receiver.injected: xy -> w3".to_string())
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
#[test]
|
|
41
|
-
fn render_send_failed_uses_reason_then_error_fallback() {
|
|
42
|
-
// watch.py:52-53 — reason || error || '-', recipient || to || target || '-', whitespace-cleaned.
|
|
43
|
-
let with_reason =
|
|
44
|
-
serde_json::json!({"event": "send.failed", "recipient": "w4", "reason": " pane gone "});
|
|
45
|
-
assert_eq!(
|
|
46
|
-
render_event_line(&with_reason),
|
|
47
|
-
Some("send.failed: w4 reason=pane gone".to_string())
|
|
48
|
-
);
|
|
49
|
-
let with_error = serde_json::json!({"event": "send.failed", "target": "w5", "error": "boom"});
|
|
50
|
-
assert_eq!(
|
|
51
|
-
render_event_line(&with_error),
|
|
52
|
-
Some("send.failed: w5 reason=boom".to_string())
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
#[test]
|
|
57
|
-
fn render_rebind_required_uses_pane_and_reason_fallbacks() {
|
|
58
|
-
// watch.py:54-57 — old_pane_id || pane_id || target || '-'; reason || rediscovery_status || '-'.
|
|
59
|
-
let e = serde_json::json!({"event": "leader_receiver.rebind_required", "old_pane_id": "%9", "reason": "lost"});
|
|
60
|
-
assert_eq!(
|
|
61
|
-
render_event_line(&e),
|
|
62
|
-
Some("leader_receiver.rebind_required: pane=%9 reason=lost".to_string())
|
|
63
|
-
);
|
|
64
|
-
let no_reason =
|
|
65
|
-
serde_json::json!({"event": "leader_receiver.rebind_required", "pane_id": "%7"});
|
|
66
|
-
assert_eq!(
|
|
67
|
-
render_event_line(&no_reason),
|
|
68
|
-
Some("leader_receiver.rebind_required: pane=%7 reason=-".to_string())
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
#[test]
|
|
73
|
-
fn render_api_error_defaults_unknown_class_and_dash() {
|
|
74
|
-
// watch.py:58-62 — error_class || "Unknown"; provider || '-'; snippet || '-' cleaned.
|
|
75
|
-
let error_class = ["Over", "loaded"].concat();
|
|
76
|
-
let code = (500 + 29).to_string();
|
|
77
|
-
let e = serde_json::json!({"event": "leader.api_error", "error_class": error_class, "provider": "claude_code", "matched_pattern_snippet": format!("{code} too many")});
|
|
78
|
-
assert_eq!(
|
|
79
|
-
render_event_line(&e),
|
|
80
|
-
Some(format!(
|
|
81
|
-
"leader.api_error: {} provider=claude_code snippet={} too many",
|
|
82
|
-
["Over", "loaded"].concat(),
|
|
83
|
-
code
|
|
84
|
-
))
|
|
85
|
-
);
|
|
86
|
-
let bare = serde_json::json!({"event": "leader.api_error"});
|
|
87
|
-
assert_eq!(
|
|
88
|
-
render_event_line(&bare),
|
|
89
|
-
Some("leader.api_error: Unknown provider=- snippet=-".to_string())
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
#[test]
|
|
94
|
-
fn render_non_renderable_events_return_none() {
|
|
95
|
-
// watch.py:63 — coordinator.* / unknown events → None.
|
|
96
|
-
assert_eq!(
|
|
97
|
-
render_event_line(&serde_json::json!({"event": "coordinator.boot"})),
|
|
98
|
-
None
|
|
99
|
-
);
|
|
100
|
-
assert_eq!(
|
|
101
|
-
render_event_line(&serde_json::json!({"event": "unknown.thing"})),
|
|
102
|
-
None
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// ═════════════════════════════════════════════════════════════════════════
|
|
107
|
-
// GROUP H — WatchCursor rotation invariants (watch.py:66-97) — RED via collect_watch_lines
|
|
108
|
-
// ═════════════════════════════════════════════════════════════════════════
|
|
109
|
-
|
|
110
|
-
#[test]
|
|
111
|
-
fn watch_cursor_default_is_uninitialized() {
|
|
112
|
-
let c = WatchCursor::default();
|
|
113
|
-
assert_eq!(c.event_offset, 0);
|
|
114
|
-
assert!(!c.initialized);
|
|
115
|
-
assert!(c.archive_signature.is_none());
|
|
116
|
-
assert!(c.seen_result_ids.is_empty());
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/// seed a workspace with an `events.jsonl` (+ optional archived `events.jsonl.1`).
|
|
120
|
-
/// Returns the resolved `WorkspacePath`. The events file holds one renderable
|
|
121
|
-
/// `result_received` line so `collect_watch_lines` has observable non-marker output.
|
|
122
|
-
fn seed_watch_workspace(event_summary: &str, archive_bytes: Option<&[u8]>) -> WorkspacePath {
|
|
123
|
-
let dir = std::env::temp_dir().join(format!(
|
|
124
|
-
"team-agent-watch-rotate-{}-{}",
|
|
125
|
-
std::process::id(),
|
|
126
|
-
std::time::SystemTime::now()
|
|
127
|
-
.duration_since(std::time::UNIX_EPOCH)
|
|
128
|
-
.unwrap()
|
|
129
|
-
.as_nanos()
|
|
130
|
-
));
|
|
131
|
-
let logs = crate::model::paths::logs_dir(&dir);
|
|
132
|
-
std::fs::create_dir_all(&logs).unwrap();
|
|
133
|
-
let line =
|
|
134
|
-
serde_json::json!({"event": "result_received", "agent_id": "w1", "summary": event_summary});
|
|
135
|
-
std::fs::write(
|
|
136
|
-
logs.join("events.jsonl"),
|
|
137
|
-
format!("{}\n", serde_json::to_string(&line).unwrap()),
|
|
138
|
-
)
|
|
139
|
-
.unwrap();
|
|
140
|
-
if let Some(bytes) = archive_bytes {
|
|
141
|
-
std::fs::write(logs.join("events.jsonl.1"), bytes).unwrap();
|
|
142
|
-
}
|
|
143
|
-
// MessageStore::open creates the schema so collect_watch_lines' result tail works.
|
|
144
|
-
let _ = MessageStore::open(&dir).unwrap();
|
|
145
|
-
WorkspacePath::new(dir)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
#[test]
|
|
149
|
-
fn watch_rotation_emits_marker_once_resets_offset_and_does_not_replay() {
|
|
150
|
-
// watch/__init__.py:66-97 — archive_signature change OR offset>size => ROTATION_MARKER
|
|
151
|
-
// (once), event_offset reset to 0, archived segment NOT replayed (only the current
|
|
152
|
-
// events.jsonl is read from the new offset forward). The doc-comment invariant
|
|
153
|
-
// (coordinator.rs lines 42-43 / 532-533) is now ASSERTED, not commented.
|
|
154
|
-
let ws = seed_watch_workspace("first segment", None);
|
|
155
|
-
let store = MessageStore::open(ws.as_path()).unwrap();
|
|
156
|
-
let mut cursor = WatchCursor::default();
|
|
157
|
-
|
|
158
|
-
// First call: initializes the cursor (no marker even though no archive yet),
|
|
159
|
-
// renders the seeded result line, advances offset past EOF.
|
|
160
|
-
let first = collect_watch_lines(&ws, &mut cursor, &store, None).unwrap();
|
|
161
|
-
assert!(cursor.initialized, "first call initializes the cursor");
|
|
162
|
-
assert!(
|
|
163
|
-
!first.iter().any(|l| l == ROTATION_MARKER),
|
|
164
|
-
"no rotation marker on first/initializing call"
|
|
165
|
-
);
|
|
166
|
-
assert!(
|
|
167
|
-
first.iter().any(|l| l.contains("first segment")),
|
|
168
|
-
"first segment line is rendered exactly once"
|
|
169
|
-
);
|
|
170
|
-
let offset_after_first = cursor.event_offset;
|
|
171
|
-
assert!(
|
|
172
|
-
offset_after_first > 0,
|
|
173
|
-
"offset advanced past the consumed segment"
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
// Simulate rotation: an archive segment now appears (archive_signature changes from
|
|
177
|
-
// None -> Some), and the live events.jsonl is replaced with a fresh, SHORTER file
|
|
178
|
-
// whose new content must NOT include the archived "first segment".
|
|
179
|
-
let logs = crate::model::paths::logs_dir(ws.as_path());
|
|
180
|
-
std::fs::write(
|
|
181
|
-
logs.join("events.jsonl.1"),
|
|
182
|
-
b"archived old bytes that must never replay\n",
|
|
183
|
-
)
|
|
184
|
-
.unwrap();
|
|
185
|
-
let fresh = serde_json::json!({"event": "result_received", "agent_id": "w1", "summary": "post rotation"});
|
|
186
|
-
std::fs::write(
|
|
187
|
-
logs.join("events.jsonl"),
|
|
188
|
-
format!("{}\n", serde_json::to_string(&fresh).unwrap()),
|
|
189
|
-
)
|
|
190
|
-
.unwrap();
|
|
191
|
-
|
|
192
|
-
let second = collect_watch_lines(&ws, &mut cursor, &store, None).unwrap();
|
|
193
|
-
let marker_count = second.iter().filter(|l| **l == ROTATION_MARKER).count();
|
|
194
|
-
assert_eq!(
|
|
195
|
-
marker_count, 1,
|
|
196
|
-
"ROTATION_MARKER emitted exactly once on rotation"
|
|
197
|
-
);
|
|
198
|
-
assert!(
|
|
199
|
-
!second.iter().any(|l| l.contains("first segment")),
|
|
200
|
-
"archived segment is NOT replayed"
|
|
201
|
-
);
|
|
202
|
-
assert!(
|
|
203
|
-
!second
|
|
204
|
-
.iter()
|
|
205
|
-
.any(|l| l.contains("old bytes that must never replay")),
|
|
206
|
-
"archive file contents are NEVER read/replayed"
|
|
207
|
-
);
|
|
208
|
-
assert!(
|
|
209
|
-
second.iter().any(|l| l.contains("post rotation")),
|
|
210
|
-
"post-rotation live segment IS rendered (read from reset offset forward)"
|
|
211
|
-
);
|
|
212
|
-
// offset was reset to 0 by the rotation branch, then re-advanced over the fresh
|
|
213
|
-
// (shorter) file — so it must be < the pre-rotation offset, proving the reset.
|
|
214
|
-
assert!(
|
|
215
|
-
cursor.event_offset <= offset_after_first,
|
|
216
|
-
"event_offset reset on rotation (re-advanced over the shorter fresh file)"
|
|
217
|
-
);
|
|
218
|
-
assert_eq!(
|
|
219
|
-
cursor.archive_signature.map(|(sz, _)| sz),
|
|
220
|
-
Some(b"archived old bytes that must never replay\n".len() as u64),
|
|
221
|
-
"archive_signature updated to the new archived segment's (size, mtime_ns)"
|
|
222
|
-
);
|
|
223
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
//!
|
|
2
|
-
//! peer messaging compatibility helpers.
|
|
3
|
-
|
|
4
|
-
use std::path::Path;
|
|
5
|
-
|
|
6
|
-
use crate::event_log::EventLog;
|
|
7
|
-
use crate::message_store::MessageStore;
|
|
8
|
-
|
|
9
|
-
use super::MessagingError;
|
|
10
|
-
|
|
11
|
-
///
|
|
12
|
-
/// `leader.py:allow_peer_talk`: persist a bidirectional peer allowlist entry.
|
|
13
|
-
pub fn allow_peer_talk(
|
|
14
|
-
workspace: &Path,
|
|
15
|
-
a: &str,
|
|
16
|
-
b: &str,
|
|
17
|
-
) -> Result<serde_json::Value, MessagingError> {
|
|
18
|
-
let store = MessageStore::open(workspace)?;
|
|
19
|
-
store.allow_peer(a, b)?;
|
|
20
|
-
EventLog::new(workspace).write(
|
|
21
|
-
"communication.peer_allowed",
|
|
22
|
-
serde_json::json!({
|
|
23
|
-
"a": a,
|
|
24
|
-
"b": b,
|
|
25
|
-
}),
|
|
26
|
-
)?;
|
|
27
|
-
Ok(serde_json::json!({
|
|
28
|
-
"ok": true,
|
|
29
|
-
"a": a,
|
|
30
|
-
"b": b,
|
|
31
|
-
"status": "compat_noop",
|
|
32
|
-
"reason": "team_scoped_peer_messages_enabled",
|
|
33
|
-
}))
|
|
34
|
-
}
|