@team-agent/installer 0.5.114 → 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.
@@ -24,6 +24,36 @@ use super::common::*;
24
24
  use super::*;
25
25
  use crate::provider::wire::{parse_canonical_provider, requires_resume_backing};
26
26
 
27
+ #[cfg(all(test, unix))]
28
+ mod contract_route_tests {
29
+ use super::*;
30
+
31
+ #[test]
32
+ fn contract_seats_never_enter_legacy_resume_or_fresh_classification() {
33
+ let state = serde_json::json!({"agents": {
34
+ "cursor": {"provider":"cursor","status":"running","session_id":"native-cursor"},
35
+ "kiro": {"provider":"kiro","status":"running","session_id":"native-kiro"},
36
+ }});
37
+ for allow_fresh in [false, true] {
38
+ let plan = classify_restart_plan(&state, allow_fresh).unwrap();
39
+ assert!(plan.decisions.is_empty());
40
+ assert!(plan.unresumable.is_empty());
41
+ }
42
+ }
43
+
44
+ #[test]
45
+ fn mixed_team_retains_legacy_classification_without_native_codex_fallback() {
46
+ let state = serde_json::json!({"agents": {
47
+ "native": {"provider":"cursor","status":"running","session_id":"native-id"},
48
+ "legacy": {"provider":"pi","status":"stopped"},
49
+ }});
50
+ let plan = classify_restart_plan(&state, false).unwrap();
51
+ assert_eq!(plan.decisions.len(), 1);
52
+ assert_eq!(plan.decisions[0].agent_id.as_str(), "legacy");
53
+ assert_eq!(plan.decisions[0].restart_mode, StartMode::Fresh);
54
+ }
55
+ }
56
+
27
57
  /// ---
28
58
  /// purpose: 定出该席位这次的启动模式
29
59
  /// params:
@@ -283,6 +313,10 @@ pub(crate) fn classify_restart_plan_with_resume_validation(
283
313
  };
284
314
 
285
315
  for (worker_id, agent) in agents {
316
+ // Contract resumes are admitted against their canonical native store,
317
+ // not this legacy enum's unknown-provider Codex default.
318
+ #[cfg(unix)]
319
+ if crate::contract_runtime::framework::is_contract(agent) { continue; }
286
320
  if agent
287
321
  .get("status")
288
322
  .and_then(|v| v.as_str())
@@ -486,7 +486,7 @@ fn raw_line_end(text: &str, start: usize) -> (usize, usize) {
486
486
  }
487
487
  }
488
488
 
489
- fn patched_role(
489
+ pub(crate) fn patched_role(
490
490
  text: &str,
491
491
  agent_id: &AgentId,
492
492
  patch: &RoleConfigPatch,
@@ -775,6 +775,22 @@ impl RoleSnapshot {
775
775
  }
776
776
  }
777
777
 
778
+ /// Compare-and-replace a role only after its complete native plan is admitted.
779
+ /// No rollback of a live/uncertain native generation is implied by this write.
780
+ pub(crate) fn commit_contract_role(
781
+ path: &Path,
782
+ expected: &str,
783
+ replacement: &str,
784
+ ) -> Result<(), LifecycleError> {
785
+ if read_text(path)? != expected {
786
+ return Err(LifecycleError::RequirementUnmet("role source changed during admission".into()));
787
+ }
788
+ if expected != replacement {
789
+ atomic_write(path, replacement.as_bytes())?;
790
+ }
791
+ Ok(())
792
+ }
793
+
778
794
  fn atomic_write(path: &Path, bytes: &[u8]) -> Result<(), LifecycleError> {
779
795
  static NEXT: AtomicU64 = AtomicU64::new(0);
780
796
  if let Some(parent) = path.parent() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-agent/installer",
3
- "version": "0.5.114",
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.114",
24
- "@team-agent/cli-darwin-x64": "0.5.114",
25
- "@team-agent/cli-linux-x64": "0.5.114"
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",