@team-agent/installer 0.5.113 → 0.5.115
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 +252 -84
- package/Cargo.toml +3 -1
- package/crates/team-agent/Cargo.toml +3 -0
- package/crates/team-agent/src/cli/adapters.rs +28 -15
- package/crates/team-agent/src/cli/diagnose.rs +36 -13
- package/crates/team-agent/src/cli/emit.rs +57 -22
- package/crates/team-agent/src/cli/leader.rs +16 -0
- package/crates/team-agent/src/cli/leader_prompt.rs +261 -0
- package/crates/team-agent/src/cli/mod.rs +157 -8
- package/crates/team-agent/src/cli/models.rs +119 -18
- package/crates/team-agent/src/cli/spec.rs +7 -1
- package/crates/team-agent/src/cli/status_port/brief.rs +268 -101
- package/crates/team-agent/src/cli/tests/base.rs +88 -0
- package/crates/team-agent/src/cli/tests/status_send.rs +2 -0
- package/crates/team-agent/src/compiler.rs +66 -18
- package/crates/team-agent/src/contract_runtime/backend.rs +959 -0
- package/crates/team-agent/src/contract_runtime/commands.rs +245 -0
- package/crates/team-agent/src/contract_runtime/config.rs +340 -0
- package/crates/team-agent/src/contract_runtime/config_tests.rs +56 -0
- package/crates/team-agent/src/contract_runtime/discovery.rs +383 -0
- package/crates/team-agent/src/contract_runtime/forward.rs +229 -0
- package/crates/team-agent/src/contract_runtime/framework.rs +294 -0
- package/crates/team-agent/src/contract_runtime/mcp.rs +396 -0
- package/crates/team-agent/src/contract_runtime/mod.rs +16 -0
- package/crates/team-agent/src/contract_runtime/prompt.rs +216 -0
- package/crates/team-agent/src/contract_runtime/pump.rs +269 -0
- package/crates/team-agent/src/contract_runtime/registry.rs +197 -0
- package/crates/team-agent/src/contract_runtime/workspace.rs +160 -0
- package/crates/team-agent/src/coordinator/tick.rs +26 -8
- package/crates/team-agent/src/leader/mod.rs +1 -0
- package/crates/team-agent/src/leader/prompt.rs +906 -0
- package/crates/team-agent/src/leader/start.rs +353 -21
- package/crates/team-agent/src/leader/tests/mod.rs +2 -0
- package/crates/team-agent/src/leader/tests/prompt_contract.rs +268 -0
- package/crates/team-agent/src/leader/types.rs +6 -0
- package/crates/team-agent/src/lib.rs +4 -0
- package/crates/team-agent/src/lifecycle/launch/quick_start.rs +571 -389
- package/crates/team-agent/src/lifecycle/launch/spawn.rs +38 -9
- package/crates/team-agent/src/lifecycle/launch/state_projection.rs +15 -0
- package/crates/team-agent/src/lifecycle/launch.rs +45 -28
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +23 -1
- package/crates/team-agent/src/lifecycle/restart/selection.rs +34 -0
- package/crates/team-agent/src/lifecycle/role_config.rs +17 -1
- package/crates/team-agent/src/lifecycle/types.rs +4 -1
- package/crates/team-agent/src/lifecycle/worker_command_context.rs +37 -27
- package/crates/team-agent/src/main.rs +6 -0
- package/crates/team-agent/src/messaging/delivery.rs +50 -1
- package/crates/team-agent/src/messaging/send.rs +10 -0
- package/crates/team-agent/src/messaging/tests/leader_inject_acceptance.rs +131 -0
- package/crates/team-agent/src/model/spec.rs +24 -12
- package/crates/team-agent/src/state/persist.rs +73 -0
- package/package.json +4 -4
|
@@ -77,6 +77,131 @@ fn tmux_leader_submit_without_provider_receipt_stays_pending_then_accepts_same_r
|
|
|
77
77
|
assert!(case.delivery_consumed_at(&message_id).is_some());
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
fn pi_receipt_case(tag: &str) -> (Case, serde_json::Value) {
|
|
81
|
+
let mut case = Case::new_without_rollout(tag);
|
|
82
|
+
let root = case.workspace.join("pi-sessions");
|
|
83
|
+
std::fs::create_dir_all(&root).unwrap();
|
|
84
|
+
case.rollout = root.join("not-derived-from-the-session-id.jsonl");
|
|
85
|
+
let receiver = &mut case.state["leader_receiver"];
|
|
86
|
+
receiver["provider"] = serde_json::json!("pi");
|
|
87
|
+
receiver["tmux_socket"] = serde_json::json!(case.workspace.join("fixture-tmux.sock"));
|
|
88
|
+
receiver["leader_session_uuid"] = serde_json::json!("team-owner-not-native-id");
|
|
89
|
+
receiver["owner_epoch"] = serde_json::json!(1);
|
|
90
|
+
receiver["native_session"] = serde_json::json!({
|
|
91
|
+
"expected_session_id": "native-pi-session",
|
|
92
|
+
"provider_projects_root": root,
|
|
93
|
+
"spawn_cwd": case.workspace,
|
|
94
|
+
"spawned_at": "2026-10-10T03:59:07Z",
|
|
95
|
+
"pane_id": "%leader",
|
|
96
|
+
"tmux_socket": receiver["tmux_socket"],
|
|
97
|
+
"leader_session_uuid": "team-owner-not-native-id",
|
|
98
|
+
"owner_epoch": 1,
|
|
99
|
+
});
|
|
100
|
+
crate::state::persist::save_runtime_state(&case.workspace, &case.state).unwrap();
|
|
101
|
+
let header = serde_json::json!({
|
|
102
|
+
"type": "session", "version": 3, "id": "native-pi-session",
|
|
103
|
+
"cwd": case.workspace, "timestamp": "2026-10-10T03:59:08Z",
|
|
104
|
+
});
|
|
105
|
+
(case, header)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
#[test]
|
|
109
|
+
fn pi_leader_receipt_binds_exact_header_and_consumes_without_reinjection() {
|
|
110
|
+
let (case, header) = pi_receipt_case("pi-native-receipt");
|
|
111
|
+
let endpoint = case.state["leader_receiver"]["tmux_socket"].as_str().unwrap();
|
|
112
|
+
assert!(Path::new(endpoint).is_absolute());
|
|
113
|
+
let unbound = crate::messaging::resolve_live_leader_channel(
|
|
114
|
+
&case.workspace,
|
|
115
|
+
&case.state["leader_receiver"],
|
|
116
|
+
&RecordingTransport::new(""),
|
|
117
|
+
);
|
|
118
|
+
assert!(
|
|
119
|
+
matches!(
|
|
120
|
+
unbound,
|
|
121
|
+
crate::messaging::LeaderChannelResolution::Unbound(
|
|
122
|
+
crate::messaging::LeaderChannelUnbound::EndpointMismatch
|
|
123
|
+
)
|
|
124
|
+
),
|
|
125
|
+
"{unbound:?}"
|
|
126
|
+
);
|
|
127
|
+
let transport = RecordingTransport {
|
|
128
|
+
endpoint: Some(endpoint.to_string()),
|
|
129
|
+
..RecordingTransport::new("")
|
|
130
|
+
};
|
|
131
|
+
let message_id = case.seed_message("Pi receipt canary");
|
|
132
|
+
std::fs::write(&case.rollout, format!("{header}\n")).unwrap();
|
|
133
|
+
let first = deliver_pending_message(
|
|
134
|
+
&case.workspace,
|
|
135
|
+
&case.store,
|
|
136
|
+
&transport,
|
|
137
|
+
&message_id,
|
|
138
|
+
&case.event_log,
|
|
139
|
+
&case.state,
|
|
140
|
+
)
|
|
141
|
+
.unwrap();
|
|
142
|
+
assert!(first.ok, "{first:?}");
|
|
143
|
+
assert_eq!(
|
|
144
|
+
case.message_status(&message_id),
|
|
145
|
+
"submitted_pending_acceptance"
|
|
146
|
+
);
|
|
147
|
+
assert_eq!(transport.inject_count(), 1);
|
|
148
|
+
|
|
149
|
+
let received = serde_json::json!({
|
|
150
|
+
"type": "message", "message": {"role": "user", "content": [
|
|
151
|
+
{"type": "text", "text": format!("5535 [team-agent-token:{message_id}]")}
|
|
152
|
+
]}
|
|
153
|
+
});
|
|
154
|
+
std::fs::write(&case.rollout, format!("{header}\n{received}\n")).unwrap();
|
|
155
|
+
let second = deliver_pending_message(
|
|
156
|
+
&case.workspace,
|
|
157
|
+
&case.store,
|
|
158
|
+
&transport,
|
|
159
|
+
&message_id,
|
|
160
|
+
&case.event_log,
|
|
161
|
+
&case.state,
|
|
162
|
+
)
|
|
163
|
+
.unwrap();
|
|
164
|
+
assert!(second.ok, "{second:?}");
|
|
165
|
+
assert_eq!(case.message_status(&message_id), "delivered");
|
|
166
|
+
assert!(case.delivery_consumed_at(&message_id).is_some());
|
|
167
|
+
assert_eq!(transport.inject_count(), 1);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
#[test]
|
|
171
|
+
fn pi_leader_receipt_refuses_missing_ambiguous_stale_and_other_owner_backing() {
|
|
172
|
+
use crate::messaging::delivery::{observe_leader_receipt, LeaderReceiptObservation::*};
|
|
173
|
+
let (mut case, header) = pi_receipt_case("pi-native-receipt-fences");
|
|
174
|
+
let old = case.workspace.join("old-leader.jsonl");
|
|
175
|
+
std::fs::write(&old, "[team-agent-token:canary]").unwrap();
|
|
176
|
+
case.state["leader"] = serde_json::json!({"rollout_path": old});
|
|
177
|
+
// An old root leader receipt cannot substitute for this native session.
|
|
178
|
+
assert_eq!(observe_leader_receipt(&case.state, "canary"), SourceUnavailable);
|
|
179
|
+
for (field, value) in [
|
|
180
|
+
("id", serde_json::json!("another-session")),
|
|
181
|
+
("cwd", serde_json::json!(case.workspace.join("other"))),
|
|
182
|
+
("timestamp", serde_json::json!("2026-10-10T03:59:06Z")),
|
|
183
|
+
] {
|
|
184
|
+
let mut wrong = header.clone();
|
|
185
|
+
wrong[field] = value;
|
|
186
|
+
std::fs::write(&case.rollout, format!("{wrong}\n[team-agent-token:canary]\n")).unwrap();
|
|
187
|
+
assert_eq!(observe_leader_receipt(&case.state, "canary"), SourceUnavailable);
|
|
188
|
+
}
|
|
189
|
+
std::fs::write(&case.rollout, format!("{header}\n")).unwrap();
|
|
190
|
+
assert_eq!(observe_leader_receipt(&case.state, "canary"), TokenAbsent);
|
|
191
|
+
let duplicate = case.rollout.with_file_name("duplicate.jsonl");
|
|
192
|
+
std::fs::write(&duplicate, format!("{header}\n[team-agent-token:canary]\n")).unwrap();
|
|
193
|
+
assert_eq!(observe_leader_receipt(&case.state, "canary"), SourceUnavailable);
|
|
194
|
+
std::fs::remove_file(duplicate).unwrap();
|
|
195
|
+
for key in ["pane_id", "tmux_socket", "leader_session_uuid", "owner_epoch"] {
|
|
196
|
+
let mut moved = case.state.clone();
|
|
197
|
+
moved["leader_receiver"][key] = serde_json::json!("changed");
|
|
198
|
+
assert_eq!(observe_leader_receipt(&moved, "canary"), SourceUnavailable);
|
|
199
|
+
}
|
|
200
|
+
case.state["leader_receiver"]["native_session"]["provider_projects_root"] =
|
|
201
|
+
serde_json::Value::Null;
|
|
202
|
+
assert_eq!(observe_leader_receipt(&case.state, "canary"), SourceUnavailable);
|
|
203
|
+
}
|
|
204
|
+
|
|
80
205
|
#[test]
|
|
81
206
|
fn attached_leader_mailbox_is_rechecked_by_the_normal_delivery_tick() {
|
|
82
207
|
let case = Case::new("mailbox");
|
|
@@ -428,6 +553,7 @@ impl Case {
|
|
|
428
553
|
struct RecordingTransport {
|
|
429
554
|
injects: Arc<AtomicUsize>,
|
|
430
555
|
capture: Arc<Mutex<String>>,
|
|
556
|
+
endpoint: Option<String>,
|
|
431
557
|
}
|
|
432
558
|
|
|
433
559
|
impl RecordingTransport {
|
|
@@ -435,6 +561,7 @@ impl RecordingTransport {
|
|
|
435
561
|
Self {
|
|
436
562
|
injects: Arc::new(AtomicUsize::new(0)),
|
|
437
563
|
capture: Arc::new(Mutex::new(capture.to_string())),
|
|
564
|
+
endpoint: None,
|
|
438
565
|
}
|
|
439
566
|
}
|
|
440
567
|
|
|
@@ -444,6 +571,10 @@ impl RecordingTransport {
|
|
|
444
571
|
}
|
|
445
572
|
|
|
446
573
|
impl Transport for RecordingTransport {
|
|
574
|
+
fn tmux_endpoint(&self) -> Option<String> {
|
|
575
|
+
self.endpoint.clone()
|
|
576
|
+
}
|
|
577
|
+
|
|
447
578
|
fn kind(&self) -> BackendKind {
|
|
448
579
|
BackendKind::Tmux
|
|
449
580
|
}
|
|
@@ -16,8 +16,8 @@ use crate::model::enums::TaskStatus;
|
|
|
16
16
|
use crate::model::errors::ModelError;
|
|
17
17
|
use crate::model::ids::TaskId;
|
|
18
18
|
use crate::model::task_graph::{find_dependency_cycle, TaskNode};
|
|
19
|
-
use crate::model::yaml::Value as Yaml;
|
|
20
19
|
use crate::model::yaml;
|
|
20
|
+
use crate::model::yaml::Value as Yaml;
|
|
21
21
|
use crate::provider::wire::parse_canonical_provider;
|
|
22
22
|
|
|
23
23
|
const LEGACY_DISPLAY_KEY: &str = concat!("display", "_backend");
|
|
@@ -733,10 +733,13 @@ fn semantic_errors(spec: &Yaml, base_dir: &Path) -> Vec<String> {
|
|
|
733
733
|
|
|
734
734
|
for (idx, agent) in agents.iter().enumerate() {
|
|
735
735
|
let provider = agent.get("provider");
|
|
736
|
-
if !provider
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
736
|
+
if !provider.and_then(Yaml::as_str).is_some_and(|p| {
|
|
737
|
+
#[cfg(unix)]
|
|
738
|
+
if crate::contract_runtime::registry::descriptor(p).is_some() {
|
|
739
|
+
return true;
|
|
740
|
+
}
|
|
741
|
+
parse_canonical_provider(p).is_some()
|
|
742
|
+
}) {
|
|
740
743
|
e.push(format!(
|
|
741
744
|
"/agents/{idx}/provider: unknown provider {}",
|
|
742
745
|
py_repr(provider)
|
|
@@ -1066,7 +1069,11 @@ mod tests {
|
|
|
1066
1069
|
.iter()
|
|
1067
1070
|
.filter(|m| m.starts_with("/agents/dangerously_skip_permissions: missing"))
|
|
1068
1071
|
.collect();
|
|
1069
|
-
assert_eq!(
|
|
1072
|
+
assert_eq!(
|
|
1073
|
+
missing.len(),
|
|
1074
|
+
1,
|
|
1075
|
+
"exactly one missing-field error, got: {errors:#?}"
|
|
1076
|
+
);
|
|
1070
1077
|
assert!(
|
|
1071
1078
|
missing[0].contains("`codex_implementer`"),
|
|
1072
1079
|
"must name the role id, got: {}",
|
|
@@ -1083,7 +1090,11 @@ mod tests {
|
|
|
1083
1090
|
#[test]
|
|
1084
1091
|
fn test_invalid_dangerously_type_rejected() {
|
|
1085
1092
|
let text = include_str!("testdata/team.spec.yaml");
|
|
1086
|
-
let bad = text.replacen(
|
|
1093
|
+
let bad = text.replacen(
|
|
1094
|
+
" dangerously_skip_permissions: false\n",
|
|
1095
|
+
" dangerously_skip_permissions: \"yes\"\n",
|
|
1096
|
+
1,
|
|
1097
|
+
);
|
|
1087
1098
|
assert_ne!(text, bad, "fixture must contain the field");
|
|
1088
1099
|
let spec = yaml::loads(&bad).unwrap();
|
|
1089
1100
|
let errors = all_spec_errors(&spec);
|
|
@@ -1091,7 +1102,11 @@ mod tests {
|
|
|
1091
1102
|
.iter()
|
|
1092
1103
|
.filter(|m| m.starts_with("/agents/dangerously_skip_permissions: must be a boolean"))
|
|
1093
1104
|
.collect();
|
|
1094
|
-
assert_eq!(
|
|
1105
|
+
assert_eq!(
|
|
1106
|
+
type_errs.len(),
|
|
1107
|
+
1,
|
|
1108
|
+
"exactly one type error, got: {errors:#?}"
|
|
1109
|
+
);
|
|
1095
1110
|
assert!(
|
|
1096
1111
|
type_errs[0].contains("`codex_implementer`"),
|
|
1097
1112
|
"must name the role id, got: {}",
|
|
@@ -1139,10 +1154,7 @@ mod tests {
|
|
|
1139
1154
|
// 缺失 role frontmatter 值时编译为安全默认 false;此处锁定公共编译入口的结果。
|
|
1140
1155
|
#[test]
|
|
1141
1156
|
fn test_all_7_triggers_use_compiled_default_bypass() {
|
|
1142
|
-
let team = std::env::temp_dir().join(format!(
|
|
1143
|
-
"ta-spec-7trigger-{}",
|
|
1144
|
-
std::process::id()
|
|
1145
|
-
));
|
|
1157
|
+
let team = std::env::temp_dir().join(format!("ta-spec-7trigger-{}", std::process::id()));
|
|
1146
1158
|
let _ = std::fs::remove_dir_all(&team);
|
|
1147
1159
|
std::fs::create_dir_all(team.join("agents")).unwrap();
|
|
1148
1160
|
std::fs::write(
|
|
@@ -1333,6 +1333,15 @@ fn lifecycle_placeholder(agent: &Value) -> bool {
|
|
|
1333
1333
|
}
|
|
1334
1334
|
|
|
1335
1335
|
fn lifecycle_peer_snapshot_is_stale(incoming: &Value, latest: &Value) -> bool {
|
|
1336
|
+
// A save that omitted a not-yet-spawned peer can carry roster_stub's
|
|
1337
|
+
// metadata-only row into a later save. It has neither status nor epoch;
|
|
1338
|
+
// it must not conflict with the peer that has since started.
|
|
1339
|
+
if incoming.get("status").is_none_or(Value::is_null)
|
|
1340
|
+
&& live_topology_fields(incoming).is_empty()
|
|
1341
|
+
&& latest.get("status").and_then(Value::as_str) == Some("running")
|
|
1342
|
+
{
|
|
1343
|
+
return true;
|
|
1344
|
+
}
|
|
1336
1345
|
// A concurrent clone/restart can have promoted its peer to `running`
|
|
1337
1346
|
// while its capture tuple is still pending. That row is still a
|
|
1338
1347
|
// lifecycle snapshot, not a completed topology observation; preserving
|
|
@@ -2643,6 +2652,70 @@ mod tests {
|
|
|
2643
2652
|
assert!(saved["agents"].get("f2").is_some());
|
|
2644
2653
|
}
|
|
2645
2654
|
|
|
2655
|
+
#[test]
|
|
2656
|
+
fn lifecycle_authority_preserves_peer_that_started_after_roster_stub_snapshot() {
|
|
2657
|
+
let ws = temp_ws();
|
|
2658
|
+
write_state(
|
|
2659
|
+
&ws,
|
|
2660
|
+
&json!({
|
|
2661
|
+
"session_name": "team-a",
|
|
2662
|
+
"active_team_key": "team-a",
|
|
2663
|
+
"agents": {"f1": {"provider": "claude", "status": "starting"}}
|
|
2664
|
+
}),
|
|
2665
|
+
);
|
|
2666
|
+
// f2 loaded before f1's reservation. Persist carries the still-unspawned
|
|
2667
|
+
// f1 forward as an actual roster stub, not a fabricated test shape.
|
|
2668
|
+
let incoming = json!({
|
|
2669
|
+
"session_name": "team-a",
|
|
2670
|
+
"active_team_key": "team-a",
|
|
2671
|
+
"agents": {"f2": {"provider": "claude", "status": "starting"}}
|
|
2672
|
+
});
|
|
2673
|
+
save_runtime_state_with_lifecycle_topology_authority(&ws, &incoming, "team-a", &["f2"])
|
|
2674
|
+
.unwrap();
|
|
2675
|
+
let mut stale = read_state(&ws);
|
|
2676
|
+
assert!(stale["agents"]["f1"].get("status").is_none());
|
|
2677
|
+
assert!(live_topology_fields(&stale["agents"]["f1"]).is_empty());
|
|
2678
|
+
|
|
2679
|
+
// f1 starts after f2 takes its snapshot; capture is not complete yet.
|
|
2680
|
+
let mut started = stale.clone();
|
|
2681
|
+
started["agents"]["f1"] = json!({
|
|
2682
|
+
"provider": "claude",
|
|
2683
|
+
"status": "running",
|
|
2684
|
+
"pane_id": "%1",
|
|
2685
|
+
"pane_pid": 101,
|
|
2686
|
+
"window": "f1",
|
|
2687
|
+
"spawned_at": "2026-10-11T05:55:20Z",
|
|
2688
|
+
"spawn_epoch": 1,
|
|
2689
|
+
"_pending_session_id": "session-f1"
|
|
2690
|
+
});
|
|
2691
|
+
normalize_agent_session_state(&mut started);
|
|
2692
|
+
save_runtime_state_with_lifecycle_topology_authority(&ws, &started, "team-a", &["f1"])
|
|
2693
|
+
.unwrap();
|
|
2694
|
+
let latest = read_state(&ws);
|
|
2695
|
+
stale["agents"]["f2"] = json!({
|
|
2696
|
+
"provider": "claude",
|
|
2697
|
+
"status": "running",
|
|
2698
|
+
"pane_id": "%2",
|
|
2699
|
+
"pane_pid": 102,
|
|
2700
|
+
"window": "f2",
|
|
2701
|
+
"spawned_at": "2026-10-11T05:55:21Z",
|
|
2702
|
+
"spawn_epoch": 1,
|
|
2703
|
+
"_pending_session_id": "session-f2"
|
|
2704
|
+
});
|
|
2705
|
+
|
|
2706
|
+
// Ordinary writers still cannot overwrite the live peer from a stub.
|
|
2707
|
+
assert!(matches!(
|
|
2708
|
+
save_runtime_state(&ws, &stale),
|
|
2709
|
+
Err(StateError::SaveConflict(_))
|
|
2710
|
+
));
|
|
2711
|
+
assert_eq!(read_state(&ws), latest);
|
|
2712
|
+
save_runtime_state_with_lifecycle_topology_authority(&ws, &stale, "team-a", &["f2"])
|
|
2713
|
+
.unwrap();
|
|
2714
|
+
let saved = read_state(&ws);
|
|
2715
|
+
assert_eq!(saved["agents"]["f1"], latest["agents"]["f1"]);
|
|
2716
|
+
assert_eq!(saved["agents"]["f2"], stale["agents"]["f2"]);
|
|
2717
|
+
}
|
|
2718
|
+
|
|
2646
2719
|
#[test]
|
|
2647
2720
|
fn lifecycle_authority_preserves_complete_latest_row_for_starting_peer() {
|
|
2648
2721
|
let ws = temp_ws();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@team-agent/installer",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.115",
|
|
4
4
|
"description": "npx installer for Team Agent",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"codex",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"team-agent-installer": "npm/install.mjs"
|
|
21
21
|
},
|
|
22
22
|
"optionalDependencies": {
|
|
23
|
-
"@team-agent/cli-darwin-arm64": "0.5.
|
|
24
|
-
"@team-agent/cli-darwin-x64": "0.5.
|
|
25
|
-
"@team-agent/cli-linux-x64": "0.5.
|
|
23
|
+
"@team-agent/cli-darwin-arm64": "0.5.115",
|
|
24
|
+
"@team-agent/cli-darwin-x64": "0.5.115",
|
|
25
|
+
"@team-agent/cli-linux-x64": "0.5.115"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"postinstall": "node npm/bincheck.mjs",
|