@team-agent/installer 0.3.29 → 0.3.30
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/lifecycle/profile_launch.rs +1 -3
- package/crates/team-agent/src/messaging/delivery.rs +7 -11
- package/crates/team-agent/src/messaging/leader_receiver.rs +4 -9
- package/crates/team-agent/src/messaging/tests/e23.rs +5 -0
- package/crates/team-agent/src/messaging/tests/runtime.rs +50 -22
- package/crates/team-agent/src/tmux_backend/tests.rs +12 -22
- package/crates/team-agent/src/tmux_backend.rs +43 -39
- package/package.json +4 -4
package/Cargo.lock
CHANGED
package/Cargo.toml
CHANGED
|
@@ -157,9 +157,7 @@ fn prepare_profile_launch(
|
|
|
157
157
|
let mut claude_projects_root = None;
|
|
158
158
|
let mut managed_mcp_config = false;
|
|
159
159
|
|
|
160
|
-
if matches!(agent.provider, Provider::Claude | Provider::ClaudeCode)
|
|
161
|
-
&& agent.auth_mode == AuthMode::CompatibleApi
|
|
162
|
-
{
|
|
160
|
+
if matches!(agent.provider, Provider::Claude | Provider::ClaudeCode) {
|
|
163
161
|
let dir = compatible_claude_config_dir(workspace, &agent.id)?;
|
|
164
162
|
if let Some(config) = mcp_config {
|
|
165
163
|
ensure_compatible_claude_mcp_config(&dir, workspace, config)?;
|
|
@@ -382,13 +382,13 @@ pub fn deliver_pending_message(
|
|
|
382
382
|
};
|
|
383
383
|
let submit_verified = inject_submit_verified(&inject_report);
|
|
384
384
|
let readback_verified = pane_readback_verified(&inject_report);
|
|
385
|
-
//
|
|
386
|
-
//
|
|
387
|
-
//
|
|
385
|
+
// Leader pane: inject success is delivery proof. Worker pane: post-submit
|
|
386
|
+
// evidence is the delivery proof; stale Phase-1 readback must not veto it
|
|
387
|
+
// and cannot independently prove the current Enter submitted.
|
|
388
388
|
let verified = if is_leader_recipient {
|
|
389
389
|
true
|
|
390
390
|
} else {
|
|
391
|
-
submit_verified
|
|
391
|
+
submit_verified
|
|
392
392
|
};
|
|
393
393
|
if !verified {
|
|
394
394
|
let reason = if !readback_verified {
|
|
@@ -507,13 +507,9 @@ pub(crate) fn inject_submit_verified(report: &InjectReport) -> bool {
|
|
|
507
507
|
}
|
|
508
508
|
}
|
|
509
509
|
|
|
510
|
-
/// U1 #7 step-2: pane-readback gate.
|
|
511
|
-
///
|
|
512
|
-
///
|
|
513
|
-
/// verified when BOTH the submit succeeded AND the token was read back as visible.
|
|
514
|
-
/// `CaptureMissingToken` → readback failed → not delivered (degraded/unverified). All
|
|
515
|
-
/// other inject_verification variants (incl. token-less payloads, empty sends, new
|
|
516
|
-
/// pasted-content prompt) are not readback-negative and pass this gate.
|
|
510
|
+
/// U1 #7 step-2: pane-readback gate. `CaptureMissingToken` is negative readback
|
|
511
|
+
/// evidence, but 0.3.30 submit evidence can supersede it: consumption or
|
|
512
|
+
/// post-submit token observation proves the message reached the pane.
|
|
517
513
|
/// 0.3.27: promoted to pub(crate) for leader_receiver.rs verification gate.
|
|
518
514
|
pub(crate) fn pane_readback_verified(report: &InjectReport) -> bool {
|
|
519
515
|
!matches!(
|
|
@@ -393,17 +393,12 @@ pub fn deliver_to_leader_fallback_pane(
|
|
|
393
393
|
|
|
394
394
|
match inject_result {
|
|
395
395
|
Ok(report) => {
|
|
396
|
-
// 0.3.
|
|
397
|
-
//
|
|
398
|
-
//
|
|
399
|
-
// deliver_pending_message uses (delivery.rs:376-381):
|
|
400
|
-
// (a) inject_submit_verified — Enter was accepted by the TUI
|
|
401
|
-
// (b) pane_readback_verified — token was visible in the pane
|
|
402
|
-
// Both must pass to mark delivered; otherwise degrade to
|
|
403
|
-
// submitted_unverified (loud, not silent).
|
|
396
|
+
// 0.3.30: submit verification is enough for fallback-pane
|
|
397
|
+
// delivery. Readback is retained for diagnostics when submit
|
|
398
|
+
// itself is unverified.
|
|
404
399
|
let submit_ok = super::delivery::inject_submit_verified(&report);
|
|
405
400
|
let readback_ok = super::delivery::pane_readback_verified(&report);
|
|
406
|
-
if submit_ok
|
|
401
|
+
if submit_ok {
|
|
407
402
|
store.mark(message_id, "delivered", None)?;
|
|
408
403
|
event_log.write(
|
|
409
404
|
"leader_receiver.fallback_pane_submitted",
|
|
@@ -6,6 +6,11 @@ fn e23_fallback_pane_has_single_shared_noisy_surface() {
|
|
|
6
6
|
assert!(leader_receiver.contains("leader_receiver.fallback_pane_submitted"));
|
|
7
7
|
assert!(leader_receiver.contains("leader_receiver.fallback_pane_failed"));
|
|
8
8
|
assert!(leader_receiver.contains("delivered_via=fallback_pane"));
|
|
9
|
+
assert!(
|
|
10
|
+
leader_receiver.contains("if submit_ok {")
|
|
11
|
+
&& !leader_receiver.contains("submit_ok && readback_ok"),
|
|
12
|
+
"fallback pane delivery must accept submit_ok alone; stale readback must not veto it"
|
|
13
|
+
);
|
|
9
14
|
assert!(
|
|
10
15
|
leader_receiver.find("if primary_ok").unwrap()
|
|
11
16
|
< leader_receiver
|
|
@@ -1269,7 +1269,9 @@ fn fire_due_scheduled_events_fires_each_scheduled_kind() {
|
|
|
1269
1269
|
);
|
|
1270
1270
|
}
|
|
1271
1271
|
|
|
1272
|
-
struct UnverifiedInjectTransport
|
|
1272
|
+
struct UnverifiedInjectTransport {
|
|
1273
|
+
readback_visible: bool,
|
|
1274
|
+
}
|
|
1273
1275
|
impl Transport for UnverifiedInjectTransport {
|
|
1274
1276
|
fn kind(&self) -> BackendKind {
|
|
1275
1277
|
BackendKind::Tmux
|
|
@@ -1303,7 +1305,11 @@ impl Transport for UnverifiedInjectTransport {
|
|
|
1303
1305
|
) -> Result<InjectReport, TransportError> {
|
|
1304
1306
|
Ok(InjectReport {
|
|
1305
1307
|
stage_reached: crate::transport::InjectStage::Submit,
|
|
1306
|
-
inject_verification:
|
|
1308
|
+
inject_verification: if self.readback_visible {
|
|
1309
|
+
crate::transport::InjectVerification::CaptureContainsToken
|
|
1310
|
+
} else {
|
|
1311
|
+
crate::transport::InjectVerification::CaptureMissingToken
|
|
1312
|
+
},
|
|
1307
1313
|
submit_verification:
|
|
1308
1314
|
crate::transport::SubmitVerification::PastedContentPromptStillPresentAfterSubmit,
|
|
1309
1315
|
turn_verification: crate::transport::TurnVerification::NotYetObserved,
|
|
@@ -1441,12 +1447,8 @@ impl Transport for FailingInjectTransport {
|
|
|
1441
1447
|
}
|
|
1442
1448
|
}
|
|
1443
1449
|
|
|
1444
|
-
//
|
|
1445
|
-
//
|
|
1446
|
-
// the step-1 tmux_backend readback) must NOT be counted delivered, even when the SUBMIT
|
|
1447
|
-
// itself verified. Today the delivery gate only consulted submit_verification → a silent
|
|
1448
|
-
// paste-drop reported delivered (false green). This transport returns a verified submit
|
|
1449
|
-
// (KeySentAfterVisibleToken) but a missing-token readback.
|
|
1450
|
+
// 0.3.30: submit evidence supersedes stale readback. This transport returns a
|
|
1451
|
+
// verified submit but a missing-token readback.
|
|
1450
1452
|
struct ReadbackMissingTransport;
|
|
1451
1453
|
impl Transport for ReadbackMissingTransport {
|
|
1452
1454
|
fn kind(&self) -> BackendKind {
|
|
@@ -1507,7 +1509,7 @@ impl Transport for ReadbackMissingTransport {
|
|
|
1507
1509
|
}
|
|
1508
1510
|
|
|
1509
1511
|
#[test]
|
|
1510
|
-
fn
|
|
1512
|
+
fn deliver_pending_submit_verified_overrides_missing_readback() {
|
|
1511
1513
|
let ws = tmp_ws("readbackmiss");
|
|
1512
1514
|
let store = store_for(&ws);
|
|
1513
1515
|
let log = EventLog::new(&ws);
|
|
@@ -1532,23 +1534,47 @@ fn deliver_pending_readback_missing_token_is_not_delivered() {
|
|
|
1532
1534
|
.unwrap();
|
|
1533
1535
|
|
|
1534
1536
|
assert!(
|
|
1535
|
-
|
|
1536
|
-
"
|
|
1537
|
-
must NOT be delivered — readback gate catches the silent paste drop"
|
|
1537
|
+
out.ok,
|
|
1538
|
+
"0.3.30: submit-verified delivery must not be vetoed by stale CaptureMissingToken readback"
|
|
1538
1539
|
);
|
|
1539
|
-
|
|
1540
|
+
assert_eq!(
|
|
1540
1541
|
out.message_status.0, "delivered",
|
|
1541
|
-
"
|
|
1542
|
+
"0.3.30: submit evidence is stronger than readback"
|
|
1542
1543
|
);
|
|
1543
|
-
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
#[test]
|
|
1547
|
+
fn deliver_pending_submit_unverified_is_not_saved_by_readback() {
|
|
1548
|
+
let ws = tmp_ws("readbacksaves");
|
|
1549
|
+
let store = store_for(&ws);
|
|
1550
|
+
let log = EventLog::new(&ws);
|
|
1551
|
+
let state = serde_json::json!({
|
|
1552
|
+
"session_name": "team-readbacksaves",
|
|
1553
|
+
"leader_receiver": {"pane_id": "%leader"},
|
|
1554
|
+
"agents": {"w1": {"provider": "fake", "pane_id": "%1"}}
|
|
1555
|
+
});
|
|
1556
|
+
crate::state::persist::save_runtime_state(&ws, &state).unwrap();
|
|
1557
|
+
let message_id = store
|
|
1558
|
+
.create_message(None, "leader", "w1", "ping", None, false, None)
|
|
1559
|
+
.unwrap();
|
|
1560
|
+
|
|
1561
|
+
let out = deliver_pending_message(
|
|
1562
|
+
&ws,
|
|
1563
|
+
&store,
|
|
1564
|
+
&UnverifiedInjectTransport {
|
|
1565
|
+
readback_visible: true,
|
|
1566
|
+
},
|
|
1567
|
+
&message_id,
|
|
1568
|
+
&log,
|
|
1569
|
+
&state,
|
|
1570
|
+
)
|
|
1571
|
+
.unwrap();
|
|
1572
|
+
|
|
1544
1573
|
assert!(
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
.and_then(serde_json::Value::as_str)
|
|
1548
|
-
.map(|r| r.contains("pane_readback_unverified"))
|
|
1549
|
-
.unwrap_or(false)),
|
|
1550
|
-
"U1 #7: the failure reason must name pane_readback_unverified (loud, not silent); got {events:?}"
|
|
1574
|
+
!out.ok,
|
|
1575
|
+
"0.3.30: positive readback alone must not mark delivered when submit is unverified"
|
|
1551
1576
|
);
|
|
1577
|
+
assert_ne!(out.message_status.0, "delivered");
|
|
1552
1578
|
}
|
|
1553
1579
|
|
|
1554
1580
|
#[test]
|
|
@@ -1569,7 +1595,9 @@ fn deliver_pending_exhausted_unverified_send_emits_failed_event() {
|
|
|
1569
1595
|
let out = deliver_pending_message(
|
|
1570
1596
|
&ws,
|
|
1571
1597
|
&store,
|
|
1572
|
-
&UnverifiedInjectTransport
|
|
1598
|
+
&UnverifiedInjectTransport {
|
|
1599
|
+
readback_visible: false,
|
|
1600
|
+
},
|
|
1573
1601
|
&message_id,
|
|
1574
1602
|
&log,
|
|
1575
1603
|
&state,
|
|
@@ -623,21 +623,11 @@ CaptureMissingToken, not the static CaptureContainsToken false-positive"
|
|
|
623
623
|
// no longer in the bottom 5 lines of the pane = composer cleared).
|
|
624
624
|
// ═════════════════════════════════════════════════════════════════════════════
|
|
625
625
|
|
|
626
|
-
///
|
|
627
|
-
///
|
|
628
|
-
///
|
|
629
|
-
/// report `SubmitConsumptionUnverified`, NOT
|
|
630
|
-
/// `EnterSentWithoutPlaceholderCheck`. Otherwise delivery emits delivered
|
|
631
|
-
/// + message.delivered (假阳) even though the worker never consumed it.
|
|
632
|
-
/// 0.3.28-final E55 truth source: grace fallback DELETED.
|
|
633
|
-
/// `consumed=Some(false)` (token still in bottom 5 after all retries)
|
|
634
|
-
/// MUST report SubmitConsumptionUnverified unconditionally. Pre-final
|
|
635
|
-
/// returned EnterSentWithoutPlaceholderCheck when Phase-1 saw the token
|
|
636
|
-
/// at all (token_visible_for_report=Some(true)) — but Phase-1 visibility
|
|
637
|
-
/// only proves the paste LANDED, not that the provider CONSUMED it.
|
|
638
|
-
/// That masked E55 busy-agent false positives as delivered=true.
|
|
626
|
+
/// 0.3.30 false-negative fix: token seen during post-submit consumption
|
|
627
|
+
/// polling proves the paste landed after Enter was sent. If it never
|
|
628
|
+
/// scrolls away, that is slow provider output, not transport failure.
|
|
639
629
|
#[test]
|
|
640
|
-
fn
|
|
630
|
+
fn e46_post_submit_matched_token_without_scroll_is_verified() {
|
|
641
631
|
let token_text = "Team Agent message from leader:\n\nhi\n\n[team-agent-token:msg_red1]";
|
|
642
632
|
let (be, _rec) = backend_with(MockResp::Out(ok(token_text)), vec![]);
|
|
643
633
|
let report = be
|
|
@@ -648,19 +638,19 @@ CaptureMissingToken, not the static CaptureContainsToken false-positive"
|
|
|
648
638
|
true,
|
|
649
639
|
)
|
|
650
640
|
.expect("inject runs");
|
|
651
|
-
// 0.3.28-final: no grace fallback. Token visible + not consumed →
|
|
652
|
-
// SubmitConsumptionUnverified (delivery treats as not delivered).
|
|
653
641
|
assert_eq!(
|
|
654
642
|
report.submit_verification,
|
|
655
|
-
SubmitVerification::
|
|
656
|
-
"0.3.
|
|
657
|
-
|
|
658
|
-
this as EnterSentWithoutPlaceholderCheck caused E55 false \
|
|
659
|
-
positives (paste landed but busy agent never consumed). \
|
|
660
|
-
Got {:?}",
|
|
643
|
+
SubmitVerification::EnterSentWithoutPlaceholderCheck,
|
|
644
|
+
"0.3.30: post-submit matched=true is delivery proof even when \
|
|
645
|
+
the token stays in the bottom capture window. Got {:?}",
|
|
661
646
|
report.submit_verification
|
|
662
647
|
);
|
|
663
648
|
assert_eq!(report.turn_verification, TurnVerification::NotYetObserved);
|
|
649
|
+
let diagnostics = report.submit_diagnostics.expect("diagnostics");
|
|
650
|
+
assert!(
|
|
651
|
+
diagnostics.attempts_detail.iter().any(|obs| obs.matched),
|
|
652
|
+
"the positive verdict must be backed by a post-submit matched observation"
|
|
653
|
+
);
|
|
664
654
|
}
|
|
665
655
|
|
|
666
656
|
#[test]
|
|
@@ -1492,6 +1492,7 @@ impl Transport for TmuxBackend {
|
|
|
1492
1492
|
let mut consumption_attempts: u32 = 0;
|
|
1493
1493
|
let mut consumed: Option<bool> = None;
|
|
1494
1494
|
let mut attempts_detail: Vec<SubmitAttemptObservation> = Vec::new();
|
|
1495
|
+
let mut any_attempt_matched = false;
|
|
1495
1496
|
|
|
1496
1497
|
let poll_consumption = !payload.skip_consumption_poll();
|
|
1497
1498
|
if !poll_consumption {
|
|
@@ -1511,12 +1512,16 @@ impl Transport for TmuxBackend {
|
|
|
1511
1512
|
if attempt > 0 {
|
|
1512
1513
|
if let Some(m) = marker {
|
|
1513
1514
|
if let Ok(cap) = self.capture(target, CaptureRange::Tail(40)) {
|
|
1514
|
-
|
|
1515
|
+
let obs = submit_attempt_observation(
|
|
1515
1516
|
attempt_index,
|
|
1516
1517
|
&cap,
|
|
1517
1518
|
marker,
|
|
1518
1519
|
attempt_start.elapsed().as_millis() as u64,
|
|
1519
|
-
)
|
|
1520
|
+
);
|
|
1521
|
+
if obs.matched {
|
|
1522
|
+
any_attempt_matched = true;
|
|
1523
|
+
}
|
|
1524
|
+
attempts_detail.push(obs);
|
|
1520
1525
|
if !token_in_bottom_n(&cap.text, m, 15) {
|
|
1521
1526
|
consumed = Some(true);
|
|
1522
1527
|
break;
|
|
@@ -1561,12 +1566,16 @@ impl Transport for TmuxBackend {
|
|
|
1561
1566
|
std::thread::sleep(Duration::from_millis(100));
|
|
1562
1567
|
match self.capture(target, CaptureRange::Tail(40)) {
|
|
1563
1568
|
Ok(cap) => {
|
|
1564
|
-
|
|
1569
|
+
let obs = submit_attempt_observation(
|
|
1565
1570
|
attempt_index,
|
|
1566
1571
|
&cap,
|
|
1567
1572
|
marker,
|
|
1568
1573
|
attempt_start.elapsed().as_millis() as u64,
|
|
1569
|
-
)
|
|
1574
|
+
);
|
|
1575
|
+
if obs.matched {
|
|
1576
|
+
any_attempt_matched = true;
|
|
1577
|
+
}
|
|
1578
|
+
attempts_detail.push(obs);
|
|
1570
1579
|
if !token_in_bottom_n(&cap.text, m, 15) {
|
|
1571
1580
|
found_consumed = true;
|
|
1572
1581
|
break;
|
|
@@ -1592,45 +1601,40 @@ impl Transport for TmuxBackend {
|
|
|
1592
1601
|
|
|
1593
1602
|
let submit_verification = match consumed {
|
|
1594
1603
|
Some(true) => SubmitVerification::EnterSentWithoutPlaceholderCheck,
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
// bottom 15 lines. That is a genuine consumption failure
|
|
1598
|
-
// unless a provider busy marker proves the TUI is already
|
|
1599
|
-
// processing the turn and simply has not scrolled yet;
|
|
1600
|
-
// it MUST NOT be masked. Pre-final used a grace fallback
|
|
1601
|
-
// that returned EnterSentWithoutPlaceholderCheck whenever
|
|
1602
|
-
// token_visible_for_report=Some(true) — but Phase-1 token
|
|
1603
|
-
// visibility only proves the paste landed, NOT that the
|
|
1604
|
-
// provider consumed it. The fallback caused
|
|
1605
|
-
// delivered=true under E55 (busy-agent paste-landed-not-
|
|
1606
|
-
// consumed false positive). Do not restore that grace
|
|
1607
|
-
// fallback; only a live busy-state signal upgrades this to
|
|
1608
|
-
// EnterSentWithoutPlaceholderCheck.
|
|
1609
|
-
Some(false) => match self.capture(target, CaptureRange::Tail(15)) {
|
|
1610
|
-
Ok(cap) => {
|
|
1611
|
-
attempts_detail.push(submit_attempt_observation(
|
|
1612
|
-
consumption_attempts.max(1),
|
|
1613
|
-
&cap,
|
|
1614
|
-
marker,
|
|
1615
|
-
inject_start.elapsed().as_millis() as u64,
|
|
1616
|
-
));
|
|
1617
|
-
let busy = provider_busy_signal_in_tail(&cap.text);
|
|
1604
|
+
Some(false) => {
|
|
1605
|
+
if any_attempt_matched {
|
|
1618
1606
|
eprintln!(
|
|
1619
|
-
"team-agent submit consumption
|
|
1607
|
+
"team-agent submit consumption: consumed=false any_attempt_matched=true -> verified"
|
|
1620
1608
|
);
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1609
|
+
SubmitVerification::EnterSentWithoutPlaceholderCheck
|
|
1610
|
+
} else {
|
|
1611
|
+
match self.capture(target, CaptureRange::Tail(15)) {
|
|
1612
|
+
Ok(cap) => {
|
|
1613
|
+
attempts_detail.push(submit_attempt_observation(
|
|
1614
|
+
consumption_attempts.max(1),
|
|
1615
|
+
&cap,
|
|
1616
|
+
marker,
|
|
1617
|
+
inject_start.elapsed().as_millis() as u64,
|
|
1618
|
+
));
|
|
1619
|
+
let busy = provider_busy_signal_in_tail(&cap.text);
|
|
1620
|
+
eprintln!(
|
|
1621
|
+
"team-agent submit consumption fallback: consumed=false any_attempt_matched=false busy_state={busy}"
|
|
1622
|
+
);
|
|
1623
|
+
if busy {
|
|
1624
|
+
SubmitVerification::EnterSentWithoutPlaceholderCheck
|
|
1625
|
+
} else {
|
|
1626
|
+
SubmitVerification::SubmitConsumptionUnverified
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
Err(err) => {
|
|
1630
|
+
eprintln!(
|
|
1631
|
+
"team-agent submit consumption fallback: consumed=false busy_capture_error={err}"
|
|
1632
|
+
);
|
|
1633
|
+
SubmitVerification::SubmitConsumptionUnverified
|
|
1634
|
+
}
|
|
1625
1635
|
}
|
|
1626
1636
|
}
|
|
1627
|
-
|
|
1628
|
-
eprintln!(
|
|
1629
|
-
"team-agent submit consumption fallback: consumed=false busy_capture_error={err}"
|
|
1630
|
-
);
|
|
1631
|
-
SubmitVerification::SubmitConsumptionUnverified
|
|
1632
|
-
}
|
|
1633
|
-
},
|
|
1637
|
+
}
|
|
1634
1638
|
None => submit_verification_for_key(submit),
|
|
1635
1639
|
};
|
|
1636
1640
|
let total_elapsed_ms = inject_start.elapsed().as_millis() as u64;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@team-agent/installer",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.30",
|
|
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.3.
|
|
24
|
-
"@team-agent/cli-darwin-x64": "0.3.
|
|
25
|
-
"@team-agent/cli-linux-x64": "0.3.
|
|
23
|
+
"@team-agent/cli-darwin-arm64": "0.3.30",
|
|
24
|
+
"@team-agent/cli-darwin-x64": "0.3.30",
|
|
25
|
+
"@team-agent/cli-linux-x64": "0.3.30"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"postinstall": "node npm/bincheck.mjs",
|