@team-agent/installer 0.5.64 → 0.5.65

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.
Files changed (34) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/crates/team-agent/src/cli/adapters.rs +5 -0
  4. package/crates/team-agent/src/cli/emit.rs +15 -0
  5. package/crates/team-agent/src/cli/mod.rs +9 -8
  6. package/crates/team-agent/src/cli/send/presentation.rs +1 -0
  7. package/crates/team-agent/src/cli/spec.rs +3 -0
  8. package/crates/team-agent/src/cli/tests/mod.rs +31 -0
  9. package/crates/team-agent/src/cli/tests/status_send.rs +13 -3
  10. package/crates/team-agent/src/cli/types.rs +7 -0
  11. package/crates/team-agent/src/coordinator/health.rs +17 -0
  12. package/crates/team-agent/src/coordinator/steps/abnormal.rs +55 -2
  13. package/crates/team-agent/src/db/migration.rs +2 -1
  14. package/crates/team-agent/src/db/schema.rs +16 -8
  15. package/crates/team-agent/src/leader/lease.rs +1 -2
  16. package/crates/team-agent/src/leader/start.rs +8 -8
  17. package/crates/team-agent/src/lifecycle/restart/common.rs +3 -3
  18. package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +3 -3
  19. package/crates/team-agent/src/lifecycle/tests/startup_latency_contract.rs +10 -6
  20. package/crates/team-agent/src/lifecycle/tests.rs +11 -5
  21. package/crates/team-agent/src/mcp_server/helpers.rs +1 -0
  22. package/crates/team-agent/src/messaging/delivery.rs +29 -0
  23. package/crates/team-agent/src/messaging/helpers.rs +2 -0
  24. package/crates/team-agent/src/messaging/leader_receiver.rs +12 -0
  25. package/crates/team-agent/src/messaging/mod.rs +2 -0
  26. package/crates/team-agent/src/messaging/results.rs +5 -0
  27. package/crates/team-agent/src/messaging/send.rs +9 -0
  28. package/crates/team-agent/src/messaging/tests/runtime.rs +32 -0
  29. package/crates/team-agent/src/messaging/types.rs +2 -0
  30. package/crates/team-agent/src/messaging/wait.rs +366 -0
  31. package/crates/team-agent/src/messaging/watchers.rs +153 -6
  32. package/crates/team-agent/src/tmux_backend.rs +16 -12
  33. package/crates/team-agent/src/transport.rs +11 -11
  34. package/package.json +4 -4
@@ -74,6 +74,7 @@ pub fn deliver_stored_message(
74
74
  stage: None,
75
75
  reason: None,
76
76
  channel: None,
77
+ ack_forced_off: false,
77
78
  })
78
79
  }
79
80
 
@@ -181,6 +182,7 @@ pub fn deliver_pending_message(
181
182
  stage: None,
182
183
  reason: None,
183
184
  channel: None,
185
+ ack_forced_off: false,
184
186
  });
185
187
  }
186
188
  let message = message_for_delivery(store, message_id)?;
@@ -194,6 +196,7 @@ pub fn deliver_pending_message(
194
196
  stage: None,
195
197
  reason: Some(DeliveryRefusal::UnknownRecipient),
196
198
  channel: None,
199
+ ack_forced_off: false,
197
200
  });
198
201
  };
199
202
  let mut canonical_owner_team_id = message.owner_team_id.clone();
@@ -281,6 +284,7 @@ pub fn deliver_pending_message(
281
284
  stage: None,
282
285
  reason: Some(DeliveryRefusal::MessageAlreadyClaimed),
283
286
  channel: None,
287
+ ack_forced_off: false,
284
288
  });
285
289
  };
286
290
  if message.recipient == "leader" {
@@ -310,6 +314,7 @@ pub fn deliver_pending_message(
310
314
  stage: None,
311
315
  reason: Some(DeliveryRefusal::LeaderNotAttached),
312
316
  channel: Some("rebind_required".to_string()),
317
+ ack_forced_off: false,
313
318
  });
314
319
  };
315
320
  if let Some(outcome) = leader_receiver_transport_conflict_outcome(
@@ -340,6 +345,7 @@ pub fn deliver_pending_message(
340
345
  stage: None,
341
346
  reason: None,
342
347
  channel: Some("rebind_required".to_string()),
348
+ ack_forced_off: false,
343
349
  });
344
350
  }
345
351
  crate::messaging::LeaderChannelResolution::Unbound(reason) => {
@@ -378,6 +384,7 @@ pub fn deliver_pending_message(
378
384
  stage: None,
379
385
  reason: Some(refusal),
380
386
  channel: Some("rebind_required".to_string()),
387
+ ack_forced_off: false,
381
388
  });
382
389
  }
383
390
  }
@@ -424,6 +431,7 @@ pub fn deliver_pending_message(
424
431
  stage: None,
425
432
  reason: None,
426
433
  channel: None,
434
+ ack_forced_off: false,
427
435
  });
428
436
  }
429
437
  };
@@ -471,6 +479,7 @@ pub fn deliver_pending_message(
471
479
  stage: Some(DeliveryStage::TrustAutoAnswerDismissalWait),
472
480
  reason: None,
473
481
  channel: None,
482
+ ack_forced_off: false,
474
483
  });
475
484
  }
476
485
  let rendered = render_message(
@@ -528,6 +537,7 @@ pub fn deliver_pending_message(
528
537
  stage: None,
529
538
  reason: Some(DeliveryRefusal::LeaderNotAttached),
530
539
  channel: Some("rebind_required".to_string()),
540
+ ack_forced_off: false,
531
541
  });
532
542
  }
533
543
  if transport_error_is_target_missing(&error) {
@@ -571,6 +581,7 @@ pub fn deliver_pending_message(
571
581
  stage: Some(DeliveryStage::Inject),
572
582
  reason: None,
573
583
  channel: None,
584
+ ack_forced_off: false,
574
585
  });
575
586
  }
576
587
  store.mark(message_id, "target_resolved", Some(&reason))?;
@@ -583,6 +594,7 @@ pub fn deliver_pending_message(
583
594
  stage: Some(DeliveryStage::Inject),
584
595
  reason: None,
585
596
  channel: None,
597
+ ack_forced_off: false,
586
598
  });
587
599
  }
588
600
  };
@@ -642,6 +654,7 @@ pub fn deliver_pending_message(
642
654
  stage: Some(DeliveryStage::Submit),
643
655
  reason: None,
644
656
  channel: None,
657
+ ack_forced_off: false,
645
658
  });
646
659
  }
647
660
  store.mark(message_id, "submitted_unverified", Some(&reason))?;
@@ -654,6 +667,7 @@ pub fn deliver_pending_message(
654
667
  stage: Some(DeliveryStage::Submit),
655
668
  reason: None,
656
669
  channel: None,
670
+ ack_forced_off: false,
657
671
  });
658
672
  }
659
673
  // S1-CAPTURE-001 (0.4.8, CR M4 Claude phase-1): for Claude/ClaudeCode
@@ -718,6 +732,7 @@ pub fn deliver_pending_message(
718
732
  stage: Some(DeliveryStage::Submit),
719
733
  reason: None,
720
734
  channel: None,
735
+ ack_forced_off: false,
721
736
  });
722
737
  }
723
738
  }
@@ -766,6 +781,7 @@ pub fn deliver_pending_message(
766
781
  stage: None,
767
782
  reason: None,
768
783
  channel: None,
784
+ ack_forced_off: false,
769
785
  };
770
786
  stamp_first_send_at_if_leader_to_worker_scoped(
771
787
  workspace,
@@ -847,6 +863,7 @@ pub(crate) fn mark_worker_target_missing(
847
863
  stage: Some(DeliveryStage::Inject),
848
864
  reason: Some(DeliveryRefusal::TmuxTargetMissing),
849
865
  channel: Some("delivery_blocked".to_string()),
866
+ ack_forced_off: false,
850
867
  })
851
868
  }
852
869
 
@@ -1000,6 +1017,7 @@ fn deliver_leader_via_app_server(
1000
1017
  stage: None,
1001
1018
  reason: None,
1002
1019
  channel: Some("codex_app_server".to_string()),
1020
+ ack_forced_off: false,
1003
1021
  })
1004
1022
  }
1005
1023
  Err(error) => app_server_delivery_failure(
@@ -1045,6 +1063,7 @@ fn app_server_delivery_failure(
1045
1063
  stage: None,
1046
1064
  reason: Some(DeliveryRefusal::RecipientBusy),
1047
1065
  channel: Some("leader_busy".to_string()),
1066
+ ack_forced_off: false,
1048
1067
  })
1049
1068
  }
1050
1069
  crate::codex_app_server::AppServerError::ThreadStale { expected, actual } => {
@@ -1083,6 +1102,7 @@ fn app_server_delivery_failure(
1083
1102
  stage: None,
1084
1103
  reason: Some(DeliveryRefusal::MissingPermissions),
1085
1104
  channel: Some("codex_app_server".to_string()),
1105
+ ack_forced_off: false,
1086
1106
  })
1087
1107
  }
1088
1108
  crate::codex_app_server::AppServerError::ProtocolMismatch(_)
@@ -1134,6 +1154,7 @@ fn rebind_required_outcome(message_id: &str, action: &str) -> DeliveryOutcome {
1134
1154
  stage: None,
1135
1155
  reason: Some(DeliveryRefusal::LeaderNotAttached),
1136
1156
  channel: Some("rebind_required".to_string()),
1157
+ ack_forced_off: false,
1137
1158
  }
1138
1159
  }
1139
1160
 
@@ -1536,6 +1557,7 @@ fn leader_receiver_transport_conflict_outcome(
1536
1557
  stage: None,
1537
1558
  reason: Some(DeliveryRefusal::LeaderNotAttached),
1538
1559
  channel: Some("rebind_required".to_string()),
1560
+ ack_forced_off: false,
1539
1561
  }));
1540
1562
  }
1541
1563
  }
@@ -2106,6 +2128,7 @@ fn leader_acceptance_pending_outcome(message_id: &str, status: &str) -> Delivery
2106
2128
  stage: Some(DeliveryStage::Submit),
2107
2129
  reason: None,
2108
2130
  channel: Some("leader_acceptance_pending".to_string()),
2131
+ ack_forced_off: false,
2109
2132
  }
2110
2133
  }
2111
2134
 
@@ -2119,6 +2142,7 @@ pub(crate) fn leader_receipt_source_unavailable_outcome(message_id: &str) -> Del
2119
2142
  stage: Some(DeliveryStage::Submit),
2120
2143
  reason: None,
2121
2144
  channel: Some("leader_receipt_source_unavailable".to_string()),
2145
+ ack_forced_off: false,
2122
2146
  }
2123
2147
  }
2124
2148
 
@@ -2159,6 +2183,7 @@ fn observe_pending_leader_acceptance(
2159
2183
  stage: None,
2160
2184
  reason: None,
2161
2185
  channel: Some("leader_receiver".to_string()),
2186
+ ack_forced_off: false,
2162
2187
  })
2163
2188
  }
2164
2189
 
@@ -2188,6 +2213,7 @@ pub fn handle_trust_retry_needed(
2188
2213
  stage: Some(DeliveryStage::TrustAutoAnswerDismissalWait),
2189
2214
  reason: None,
2190
2215
  channel: None,
2216
+ ack_forced_off: false,
2191
2217
  });
2192
2218
  }
2193
2219
  let next_attempt = payload.attempt.saturating_add(1);
@@ -2227,6 +2253,7 @@ pub fn handle_trust_retry_needed(
2227
2253
  stage: Some(DeliveryStage::TrustAutoAnswerDismissalWait),
2228
2254
  reason: None,
2229
2255
  channel: None,
2256
+ ack_forced_off: false,
2230
2257
  })
2231
2258
  }
2232
2259
 
@@ -2723,6 +2750,7 @@ fn refuse_owner_team_resolution(
2723
2750
  stage: None,
2724
2751
  reason: Some(refusal),
2725
2752
  channel: Some("owner_team_resolution".to_string()),
2753
+ ack_forced_off: false,
2726
2754
  })
2727
2755
  }
2728
2756
 
@@ -2779,6 +2807,7 @@ pub fn retry_injection_after_trust_auto_answer(
2779
2807
  stage: Some(DeliveryStage::TrustAutoAnswerDismissalWait),
2780
2808
  reason: None,
2781
2809
  channel: None,
2810
+ ack_forced_off: false,
2782
2811
  })
2783
2812
  }
2784
2813
 
@@ -294,6 +294,7 @@ pub(crate) fn fail_leader_delivery(
294
294
  stage: None,
295
295
  reason: Some(reason),
296
296
  channel: Some("fallback_log".to_string()),
297
+ ack_forced_off: false,
297
298
  });
298
299
  };
299
300
  store.mark(&message_id, "failed", error)?;
@@ -310,6 +311,7 @@ pub(crate) fn fail_leader_delivery(
310
311
  stage: None,
311
312
  reason: Some(reason),
312
313
  channel: Some("fallback_inbox".to_string()),
314
+ ack_forced_off: false,
313
315
  })
314
316
  }
315
317
 
@@ -133,6 +133,7 @@ pub fn send_to_leader_receiver_with_presentation(
133
133
  stage: None,
134
134
  reason: Some(DeliveryRefusal::Duplicate),
135
135
  channel: Some("leader_receiver".to_string()),
136
+ ack_forced_off: requires_ack,
136
137
  });
137
138
  }
138
139
  PersistResolution::Persisted(persisted) => persisted.message_id,
@@ -174,6 +175,7 @@ pub fn send_to_leader_receiver_with_presentation(
174
175
  stage: None,
175
176
  reason: None,
176
177
  channel: Some("leader_receiver".to_string()),
178
+ ack_forced_off: requires_ack,
177
179
  });
178
180
  }
179
181
  }
@@ -210,6 +212,7 @@ pub fn send_to_leader_receiver_with_presentation(
210
212
  stage: None,
211
213
  reason: None,
212
214
  channel: Some("leader_receiver".to_string()),
215
+ ack_forced_off: requires_ack,
213
216
  })
214
217
  }
215
218
 
@@ -255,6 +258,7 @@ pub fn deliver_to_leader_fallback_pane(
255
258
  stage: None,
256
259
  reason: None,
257
260
  channel: Some("leader_receiver".to_string()),
261
+ ack_forced_off: false,
258
262
  });
259
263
  }
260
264
 
@@ -269,6 +273,7 @@ pub fn deliver_to_leader_fallback_pane(
269
273
  stage: None,
270
274
  reason: None,
271
275
  channel: Some("leader_receiver".to_string()),
276
+ ack_forced_off: false,
272
277
  });
273
278
  }
274
279
 
@@ -310,6 +315,7 @@ pub fn deliver_to_leader_fallback_pane(
310
315
  stage: None,
311
316
  reason: Some(DeliveryRefusal::LeaderNotAttached),
312
317
  channel: Some("fallback_pane".to_string()),
318
+ ack_forced_off: false,
313
319
  });
314
320
  };
315
321
 
@@ -383,6 +389,7 @@ pub fn deliver_to_leader_fallback_pane(
383
389
  stage: None,
384
390
  reason: Some(DeliveryRefusal::LeaderNotAttached),
385
391
  channel: Some("rebind_required".to_string()),
392
+ ack_forced_off: false,
386
393
  });
387
394
  };
388
395
  let target = Target::Pane(PaneId::new(channel.pane_id));
@@ -435,6 +442,7 @@ pub fn deliver_to_leader_fallback_pane(
435
442
  stage: Some(DeliveryStage::Submit),
436
443
  reason: None,
437
444
  channel: Some("leader_acceptance_pending".to_string()),
445
+ ack_forced_off: false,
438
446
  });
439
447
  }
440
448
  super::delivery::LeaderReceiptObservation::TokenObserved => {}
@@ -461,6 +469,7 @@ pub fn deliver_to_leader_fallback_pane(
461
469
  stage: None,
462
470
  reason: None,
463
471
  channel: Some("fallback_pane".to_string()),
472
+ ack_forced_off: false,
464
473
  })
465
474
  } else {
466
475
  let reason = format!(
@@ -486,6 +495,7 @@ pub fn deliver_to_leader_fallback_pane(
486
495
  stage: Some(DeliveryStage::Submit),
487
496
  reason: None,
488
497
  channel: Some("fallback_pane".to_string()),
498
+ ack_forced_off: false,
489
499
  })
490
500
  }
491
501
  }
@@ -527,6 +537,7 @@ pub fn deliver_to_leader_fallback_pane(
527
537
  stage: None,
528
538
  reason: Some(DeliveryRefusal::TmuxTargetMissing),
529
539
  channel: Some(channel),
540
+ ack_forced_off: false,
530
541
  })
531
542
  }
532
543
  }
@@ -718,5 +729,6 @@ pub fn enqueue_leader_mailbox_until_attach(
718
729
  stage: None,
719
730
  reason: None,
720
731
  channel: Some("leader_mailbox".to_string()),
732
+ ack_forced_off: false,
721
733
  })
722
734
  }
@@ -76,6 +76,7 @@ pub mod selftest;
76
76
  pub mod send;
77
77
  pub mod trust;
78
78
  pub mod types;
79
+ pub mod wait;
79
80
  pub mod watchers;
80
81
 
81
82
  // ── re-export: 保持 `crate::messaging::X` 与 test `super::X` 解析不变 ──────────
@@ -118,6 +119,7 @@ pub use types::{
118
119
  TrustRetryPayload, WatcherNotice, WorkerRuntimeState, RESULT_DELIVERY_MAX_ATTEMPTS,
119
120
  SEND_RETRY_MAX_ATTEMPTS, TRUST_RETRY_BACKOFF_SECONDS, TRUST_RETRY_MAX_ATTEMPTS,
120
121
  };
122
+ pub use wait::{wait_for_result, WaitResult};
121
123
  pub use watchers::{
122
124
  format_result_watcher_notification, requeue_after_claim_leader,
123
125
  requeue_delivery_exhausted_watchers, result_id_from_text, retry_result_deliveries,
@@ -842,6 +842,7 @@ fn report_result_for_owner_team_inner(
842
842
  return Ok(serde_json::Value::Object(out));
843
843
  }
844
844
  let event_log = EventLog::new(workspace);
845
+ super::watchers::notify_fifo_result_watchers(&conn, &event_log, task_id, &result_id)?;
845
846
  if presentation.effective_sink != super::presentation::PresentationSink::Leader {
846
847
  event_log.write(
847
848
  "presentation.stored_without_live_inject",
@@ -938,6 +939,7 @@ fn report_result_for_owner_team_inner(
938
939
  stage: None,
939
940
  reason: Some(crate::messaging::DeliveryRefusal::LeaderNotAttached),
940
941
  channel: Some("codex_app_server".to_string()),
942
+ ack_forced_off: false,
941
943
  }
942
944
  }
943
945
  Err(error) => {
@@ -1002,6 +1004,7 @@ fn report_result_for_owner_team_inner(
1002
1004
  stage: None,
1003
1005
  reason: None,
1004
1006
  channel: Some("leader_receiver".to_string()),
1007
+ ack_forced_off: false,
1005
1008
  };
1006
1009
  break;
1007
1010
  }
@@ -1031,6 +1034,7 @@ fn report_result_for_owner_team_inner(
1031
1034
  stage: None,
1032
1035
  reason: None,
1033
1036
  channel: Some("leader_receiver".to_string()),
1037
+ ack_forced_off: false,
1034
1038
  };
1035
1039
  break;
1036
1040
  }
@@ -1046,6 +1050,7 @@ fn report_result_for_owner_team_inner(
1046
1050
  stage: None,
1047
1051
  reason: None,
1048
1052
  channel: Some("leader_receiver".to_string()),
1053
+ ack_forced_off: false,
1049
1054
  };
1050
1055
  break;
1051
1056
  }
@@ -214,6 +214,7 @@ pub fn send_message(
214
214
  stage: None,
215
215
  reason: Some(crate::messaging::DeliveryRefusal::EmptyTargetList),
216
216
  channel: None,
217
+ ack_forced_off: false,
217
218
  });
218
219
  }
219
220
  MessageTarget::Fanout(recipients) => {
@@ -351,6 +352,7 @@ pub fn send_message(
351
352
  stage: None,
352
353
  reason: None,
353
354
  channel: None,
355
+ ack_forced_off: false,
354
356
  })
355
357
  }
356
358
 
@@ -404,6 +406,7 @@ fn persist_stored_only_send(
404
406
  stage: None,
405
407
  reason: None,
406
408
  channel: Some(presentation.effective_sink.as_str().to_string()),
409
+ ack_forced_off: false,
407
410
  })
408
411
  }
409
412
 
@@ -451,6 +454,7 @@ fn refused_outcome_with_id(reason: DeliveryRefusal, message_id: Option<String>)
451
454
  stage: None,
452
455
  reason: Some(reason),
453
456
  channel: None,
457
+ ack_forced_off: false,
454
458
  }
455
459
  }
456
460
 
@@ -467,6 +471,7 @@ fn refused_outcome_with_verification(
467
471
  stage: None,
468
472
  reason: Some(reason),
469
473
  channel: None,
474
+ ack_forced_off: false,
470
475
  }
471
476
  }
472
477
 
@@ -549,6 +554,7 @@ fn coordinator_unavailable_outcome(
549
554
  stage: None,
550
555
  reason: Some(DeliveryRefusal::CoordinatorUnavailable),
551
556
  channel: Some("coordinator_unavailable".to_string()),
557
+ ack_forced_off: false,
552
558
  },
553
559
  }))
554
560
  }
@@ -573,6 +579,7 @@ fn rebind_required_outcome_with_verification(
573
579
  stage: None,
574
580
  reason: Some(DeliveryRefusal::LeaderNotAttached),
575
581
  channel: Some("rebind_required".to_string()),
582
+ ack_forced_off: false,
576
583
  }
577
584
  }
578
585
 
@@ -804,6 +811,7 @@ pub(crate) fn session_drift_refusal(
804
811
  stage: None,
805
812
  reason: Some(DeliveryRefusal::SessionDrift),
806
813
  channel: None,
814
+ ack_forced_off: false,
807
815
  }))
808
816
  }
809
817
 
@@ -924,5 +932,6 @@ fn fanout_send(
924
932
  } else {
925
933
  channel_label.to_string()
926
934
  }),
935
+ ack_forced_off: false,
927
936
  })
928
937
  }
@@ -709,6 +709,38 @@ fn report_result_invalid_envelope_errors_validation() {
709
709
  );
710
710
  }
711
711
 
712
+ #[test]
713
+ fn leader_receiver_reports_requires_ack_forced_off() {
714
+ let ws = tmp_ws("ack-forced-off");
715
+ let log = EventLog::new(&ws);
716
+ let state = json(serde_json::json!({
717
+ "active_team_key": "team-a",
718
+ "teams": {"team-a": {}}
719
+ }));
720
+
721
+ let outcome = send_to_leader_receiver(
722
+ &ws,
723
+ &state,
724
+ "leader",
725
+ "ack contract probe",
726
+ None,
727
+ "worker",
728
+ true,
729
+ None,
730
+ &log,
731
+ )
732
+ .unwrap();
733
+
734
+ let value = crate::mcp_server::helpers::delivery_outcome_value(&outcome);
735
+ assert_eq!(
736
+ value
737
+ .get("ack_forced_off")
738
+ .and_then(serde_json::Value::as_bool),
739
+ Some(true),
740
+ "requires_ack=true must report that the unavailable ack guarantee was forced off"
741
+ );
742
+ }
743
+
712
744
  // ════════════════════════════════════════════════════════════════════════
713
745
  // GROUP N — notify_result_watchers dedupe (exactly-once, Gap 32/38).
714
746
  // result_delivery.py:38-132. superseded for duplicate watchers same result.
@@ -295,6 +295,8 @@ pub enum PaneWidthQuery {
295
295
  #[derive(Debug, Clone, PartialEq, Eq)]
296
296
  pub struct DeliveryOutcome {
297
297
  pub ok: bool,
298
+ /// Whether a caller-requested ack guarantee was unavailable and forced off.
299
+ pub ack_forced_off: bool,
298
300
  /// 投递层结果态 (≠ 行态)。
299
301
  pub status: DeliveryStatus,
300
302
  /// step 7 `messages.status` 行态原文 (shadow;leader 集成时收口为 step 7 enum)。