@team-agent/installer 0.5.106 → 0.5.107

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 (29) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/crates/team-agent/src/cli/tests/base.rs +112 -225
  4. package/crates/team-agent/src/compiler/tests.rs +46 -59
  5. package/crates/team-agent/src/leader/tests/byte_findings.rs +1 -14
  6. package/crates/team-agent/src/lifecycle/launch/pi_mcp.rs +57 -173
  7. package/crates/team-agent/src/lifecycle/launch/pi_mcp_extension.js +226 -0
  8. package/crates/team-agent/src/lifecycle/launch/quick_start.rs +0 -37
  9. package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +0 -9
  10. package/crates/team-agent/src/lifecycle/tests/fixtures/pi_native_mcp_host.mjs +71 -0
  11. package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +0 -66
  12. package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +0 -392
  13. package/crates/team-agent/src/lifecycle/tests/lifecycle_lock.rs +0 -5
  14. package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +2 -361
  15. package/crates/team-agent/src/lifecycle/tests/pi_dual_entry_red.rs +1 -16
  16. package/crates/team-agent/src/lifecycle/tests/pi_executable_mcp_red.rs +20 -112
  17. package/crates/team-agent/src/lifecycle/tests/pi_fork_session_inheritance_red.rs +1 -12
  18. package/crates/team-agent/src/lifecycle/tests/pi_native_mcp_capability_red.rs +546 -0
  19. package/crates/team-agent/src/lifecycle/tests.rs +1 -0
  20. package/crates/team-agent/src/lifecycle/worker_command_context.rs +11 -54
  21. package/crates/team-agent/src/messaging/tests/wave2.rs +2 -302
  22. package/crates/team-agent/src/model/name_similarity.rs +52 -67
  23. package/crates/team-agent/src/model/task_graph.rs +37 -124
  24. package/crates/team-agent/src/model/yaml/tests.rs +46 -165
  25. package/crates/team-agent/src/provider/tests/adapter.rs +0 -20
  26. package/crates/team-agent/src/provider/tests/classify.rs +106 -198
  27. package/crates/team-agent/src/tmux_backend/tests.rs +178 -501
  28. package/crates/team-agent/src/transport/tests/wire.rs +0 -55
  29. package/package.json +4 -4
@@ -4,11 +4,11 @@ use std::sync::atomic::{AtomicU32, Ordering};
4
4
 
5
5
  use crate::lifecycle::launch::launch_with_transport_in_workspace;
6
6
  use crate::lifecycle::launch::pi_mcp::{
7
- PiAdapterIdentity, PiExecutableChain, PiExecutableFileType, PiMaterializeRequest,
8
- PiSessionScope, PiWrapperRequest, materialize_pi_plan, materialize_pi_resume_plan,
7
+ PiExecutableChain, PiExecutableFileType, PiMaterializeRequest, PiSessionScope,
8
+ PiWrapperRequest, materialize_pi_plan, materialize_pi_resume_plan,
9
9
  parse_pi_list_models_table, pi_seat_paths, resolve_pi_executable_chain,
10
- validate_pi_adapter_identity, validate_pi_executable_chain, validate_pi_wrapper_source,
11
- write_pi_wrapper, write_pi_wrapper_with_publish,
10
+ validate_pi_executable_chain, validate_pi_wrapper_source, write_pi_wrapper,
11
+ write_pi_wrapper_with_publish,
12
12
  };
13
13
  use crate::lifecycle::start_agent_with_transport;
14
14
  use crate::model::enums::ProviderEffort;
@@ -20,8 +20,6 @@ use crate::transport::test_support::OfflineTransport;
20
20
  mod hermetic_guard;
21
21
  use hermetic_guard::HermeticTestEnv;
22
22
 
23
- const PACKAGE_DIGEST: &str = "ce8b8b6154e83e9732c58bd993e7ed69390617616f4f0e7330274d5ee9e2f620";
24
- const INDEX_DIGEST: &str = "16d260ac25b66346baab6ecef76680324336953bafc7be8cf95b3df5c611b89e";
25
23
  const CATALOG_DIGEST: &str = "726cedb6c3f6fe80a0d7b98918d8ed5063695e01f510a48f46c4bad5daab49fe";
26
24
  static NEXT_ROOT: AtomicU32 = AtomicU32::new(0);
27
25
  const PI_WRAPPER_CHILD: &str = "TEAM_AGENT_TEST_PI_WRAPPER_CHILD";
@@ -88,25 +86,6 @@ fn temp_root(label: &str) -> PathBuf {
88
86
  root
89
87
  }
90
88
 
91
- fn adapter_identity(root: &Path) -> PiAdapterIdentity {
92
- let package_root = root.join("pi-mcp-adapter");
93
- std::fs::create_dir_all(&package_root).expect("create adapter package root");
94
- let package_json = package_root.join("package.json");
95
- let index_ts = package_root.join("index.ts");
96
- std::fs::write(&package_json, b"{}").expect("write adapter package receipt");
97
- std::fs::write(&index_ts, b"export const createMcpAdapter = () => {};\n")
98
- .expect("write loadable adapter entry");
99
- PiAdapterIdentity {
100
- package_name: "pi-mcp-adapter".to_string(),
101
- version: "2.30.0".to_string(),
102
- extension_entry: "./index.ts".to_string(),
103
- package_json,
104
- index_ts,
105
- package_json_sha256: PACKAGE_DIGEST.to_string(),
106
- index_ts_sha256: INDEX_DIGEST.to_string(),
107
- }
108
- }
109
-
110
89
  fn mcp_config(candidate: &Path, workspace: &Path, agent_id: &str) -> McpConfig {
111
90
  McpConfig {
112
91
  raw: serde_json::json!({
@@ -126,8 +105,7 @@ fn mcp_config(candidate: &Path, workspace: &Path, agent_id: &str) -> McpConfig {
126
105
  }
127
106
 
128
107
  #[test]
129
- fn pi_executable_chain_freezes_wrapper_real_binary_catalog_and_plugin_identity() {
130
- let root = temp_root("executable-chain");
108
+ fn pi_executable_chain_freezes_wrapper_real_binary_and_catalog() {
131
109
  let chain = PiExecutableChain {
132
110
  path_entry: PathBuf::from("/Users/fixture/.local/bin/pi"),
133
111
  path_entry_type: PiExecutableFileType::Wrapper,
@@ -137,7 +115,6 @@ fn pi_executable_chain_freezes_wrapper_real_binary_catalog_and_plugin_identity()
137
115
  ),
138
116
  pi_version: "0.84.3".to_string(),
139
117
  catalog_sha256: CATALOG_DIGEST.to_string(),
140
- adapter: adapter_identity(&root),
141
118
  };
142
119
  validate_pi_executable_chain(&chain).expect("the protocol-capable wrapper chain is valid");
143
120
 
@@ -169,17 +146,9 @@ fn pi_executable_chain_freezes_wrapper_real_binary_catalog_and_plugin_identity()
169
146
  "a direct Homebrew binary must not replace the verified PATH wrapper launch entry"
170
147
  );
171
148
 
172
- let mut wrong_plugin = chain;
173
- wrong_plugin.adapter.version = "2.31.0".to_string();
174
- wrong_plugin.adapter.package_json_sha256 = "11".repeat(32);
175
- wrong_plugin.adapter.index_ts_sha256 = "22".repeat(32);
176
- validate_pi_executable_chain(&wrong_plugin)
177
- .expect("adapter version and content digests are diagnostic observations only");
178
-
179
149
  assert!(parse_pi_list_models_table(b"provider model\nopenai-codex gpt-5.6-luna\n").is_ok());
180
150
  assert!(parse_pi_list_models_table(b"provider model\n").is_err());
181
151
  assert!(parse_pi_list_models_table(b"provider model\nmalformed\n").is_err());
182
- std::fs::remove_dir_all(root).expect("remove executable chain fixture");
183
152
  }
184
153
 
185
154
  #[test]
@@ -189,15 +158,10 @@ fn pi_standard_npm_symlink_is_a_verified_launch_entry() {
189
158
  let root = temp_root("npm-symlink");
190
159
  let bin = root.join("bin");
191
160
  let later_bin = root.join("later-bin");
192
- let package_root = root.join("pi-mcp-adapter");
193
161
  std::fs::create_dir_all(&bin).expect("create bin");
194
162
  std::fs::create_dir_all(&later_bin).expect("create later bin");
195
- std::fs::create_dir_all(&package_root).expect("create adapter root");
196
163
  let real = root.join("cli.js");
197
- let script = format!(
198
- "#!/bin/sh\ncase \"$1\" in\n --version) printf '0.84.4\\n' ;;\n --list-models) printf 'provider model\\nteam-agent qwen3.8-27b\\n' ;;\n list) printf 'npm:pi-mcp-adapter\\n{}\\n' ;;\n *) exit 64 ;;\nesac\n",
199
- package_root.display()
200
- );
164
+ let script = "#!/bin/sh\ncase \"$1\" in\n --version) printf '0.84.4\\n' ;;\n --list-models) printf 'provider model\\nteam-agent qwen3.8-27b\\n' ;;\n list) exit 64 ;;\n *) exit 64 ;;\nesac\n";
201
165
  std::fs::write(&real, &script).expect("write protocol-capable Pi entry");
202
166
  std::fs::set_permissions(&real, std::fs::Permissions::from_mode(0o755))
203
167
  .expect("make Pi entry executable");
@@ -205,16 +169,6 @@ fn pi_standard_npm_symlink_is_a_verified_launch_entry() {
205
169
  std::fs::write(later_bin.join("pi"), script).expect("write later Pi wrapper");
206
170
  std::fs::set_permissions(later_bin.join("pi"), std::fs::Permissions::from_mode(0o755))
207
171
  .expect("make later Pi wrapper executable");
208
- std::fs::write(
209
- package_root.join("package.json"),
210
- br#"{"name":"pi-mcp-adapter","version":"2.30.0","pi":{"extensions":["./index.ts"]}}"#,
211
- )
212
- .expect("write adapter package");
213
- std::fs::write(
214
- package_root.join("index.ts"),
215
- b"export const createMcpAdapter = () => {};\n",
216
- )
217
- .expect("write adapter entry");
218
172
  unsafe {
219
173
  std::env::set_var(
220
174
  "PATH",
@@ -236,34 +190,6 @@ fn pi_standard_npm_symlink_is_a_verified_launch_entry() {
236
190
  });
237
191
  }
238
192
 
239
- #[test]
240
- fn pi_adapter_detector_requires_exact_2_30_0_entry_and_digest() {
241
- let root = temp_root("adapter-identity");
242
- let exact = adapter_identity(&root);
243
- validate_pi_adapter_identity(&exact).expect("protocol-capable adapter identity");
244
-
245
- let mut wrong_name = exact.clone();
246
- wrong_name.package_name = "pi-mcp-adapter-fork".to_string();
247
- assert!(validate_pi_adapter_identity(&wrong_name).is_err());
248
-
249
- let mut missing_entry = exact.clone();
250
- missing_entry.extension_entry.clear();
251
- missing_entry.index_ts = PathBuf::new();
252
- assert!(validate_pi_adapter_identity(&missing_entry).is_err());
253
-
254
- let mut unloadable_entry = exact.clone();
255
- unloadable_entry.index_ts = root.join("pi-mcp-adapter/missing.ts");
256
- assert!(validate_pi_adapter_identity(&unloadable_entry).is_err());
257
-
258
- let mut newer_observation = exact;
259
- newer_observation.version = "9.7.3".to_string();
260
- newer_observation.package_json_sha256 = "11".repeat(32);
261
- newer_observation.index_ts_sha256 = "22".repeat(32);
262
- validate_pi_adapter_identity(&newer_observation)
263
- .expect("version and digests do not define adapter protocol capability");
264
- std::fs::remove_dir_all(root).expect("remove adapter identity fixture");
265
- }
266
-
267
193
  #[test]
268
194
  fn pi_wrapper_is_atomic_per_seat_and_embeds_exact_candidate() {
269
195
  run_process_isolated(PI_WRAPPER_CHILD, PI_WRAPPER_TEST, || {
@@ -281,11 +207,9 @@ fn pi_wrapper_is_atomic_body(hermetic: &HermeticTestEnv) {
281
207
  .expect("create candidate parent");
282
208
  std::fs::write(&candidate, b"candidate").expect("write candidate fixture");
283
209
  let destination = workspace.join(".team/runtime/pi/team-a/worker-a/team-mcp.ts");
284
- let adapter = adapter_identity(&root);
285
210
 
286
211
  let written = write_pi_wrapper(PiWrapperRequest {
287
212
  destination: &destination,
288
- adapter: &adapter,
289
213
  candidate_executable: &candidate,
290
214
  mcp_config: &mcp_config(&candidate, &workspace, "worker-a"),
291
215
  team_id: "team-a",
@@ -308,8 +232,12 @@ fn pi_wrapper_is_atomic_body(hermetic: &HermeticTestEnv) {
308
232
  assert!(source.contains(candidate.to_string_lossy().as_ref()));
309
233
  assert!(source.contains("TEAM_AGENT_ID") && source.contains("worker-a"));
310
234
  assert!(source.contains("TEAM_AGENT_OWNER_TEAM_ID") && source.contains("team-a"));
311
- assert!(source.contains("pi-mcp-adapter:runtime-register:v1"));
235
+ assert!(source.contains("pi.registerMcpServer(alias"));
236
+ assert!(source.contains("pi.unregisterMcpServer(alias"));
237
+ assert!(source.contains("toolExposure"));
312
238
  assert!(source.contains("session_start") && source.contains("session_shutdown"));
239
+ assert!(!source.contains("pi-mcp-adapter"));
240
+ assert!(!source.contains("MCP_RUNTIME_REGISTER_EVENT"));
313
241
  assert!(source.contains("includeTools"));
314
242
  assert!(source.contains("send_message") && source.contains("report_result"));
315
243
  assert!(!source.contains("createMcpAdapter"));
@@ -322,7 +250,6 @@ fn pi_wrapper_is_atomic_body(hermetic: &HermeticTestEnv) {
322
250
  let other_destination = workspace.join(".team/runtime/pi/team-a/worker-b/team-mcp.ts");
323
251
  write_pi_wrapper(PiWrapperRequest {
324
252
  destination: &other_destination,
325
- adapter: &adapter,
326
253
  candidate_executable: &candidate,
327
254
  mcp_config: &mcp_config(&candidate, &workspace, "worker-b"),
328
255
  team_id: "team-a",
@@ -363,10 +290,8 @@ fn pi_leader_wrapper_materializes_from_empty_unicode_wsl_workspace() {
363
290
  );
364
291
 
365
292
  let paths = pi_seat_paths(&workspace, "current", "leader");
366
- let adapter = adapter_identity(&root);
367
293
  let written = write_pi_wrapper(PiWrapperRequest {
368
294
  destination: &paths.wrapper,
369
- adapter: &adapter,
370
295
  candidate_executable: &candidate,
371
296
  mcp_config: &mcp_config(&candidate, &workspace, "leader"),
372
297
  team_id: "current",
@@ -383,7 +308,7 @@ fn pi_leader_wrapper_materializes_from_empty_unicode_wsl_workspace() {
383
308
  "leader runtime root must be created recursively"
384
309
  );
385
310
  let source = std::fs::read_to_string(&written).expect("read complete leader wrapper");
386
- validate_pi_wrapper_source(&source, &adapter, &candidate)
311
+ validate_pi_wrapper_source(&source, &candidate)
387
312
  .expect("published leader wrapper must be complete and valid");
388
313
  assert!(source.contains("TEAM_AGENT_ID") && source.contains("leader"));
389
314
  assert!(source.contains("TEAM_AGENT_OWNER_TEAM_ID") && source.contains("current"));
@@ -427,11 +352,9 @@ fn pi_wrapper_publish_needs_no_final_path_metadata_lookup() {
427
352
  let paths = pi_seat_paths(&workspace, "current", "leader");
428
353
  let published_parent = paths.runtime_root.clone();
429
354
  let hidden_parent = published_parent.with_file_name("leader-after-rename");
430
- let adapter = adapter_identity(&root);
431
355
  write_pi_wrapper_with_publish(
432
356
  PiWrapperRequest {
433
357
  destination: &paths.wrapper,
434
- adapter: &adapter,
435
358
  candidate_executable: &candidate,
436
359
  mcp_config: &mcp_config(&candidate, &workspace, "leader"),
437
360
  team_id: "current",
@@ -490,10 +413,8 @@ fn pi_wrapper_import_failure_body(hermetic: &HermeticTestEnv) {
490
413
  .expect("write malicious ambient config");
491
414
 
492
415
  let destination = workspace.join(".team/runtime/pi/team-a/worker-a/team-mcp.ts");
493
- let adapter = adapter_identity(&root);
494
416
  write_pi_wrapper(PiWrapperRequest {
495
417
  destination: &destination,
496
- adapter: &adapter,
497
418
  candidate_executable: &candidate,
498
419
  mcp_config: &mcp_config(&candidate, &workspace, "worker-a"),
499
420
  team_id: "team-a",
@@ -504,14 +425,16 @@ fn pi_wrapper_import_failure_body(hermetic: &HermeticTestEnv) {
504
425
  .expect("runtime wrapper leaves ambient config to direct Pi");
505
426
  let source = std::fs::read_to_string(&destination).expect("wrapper source");
506
427
  assert!(!source.contains("ambient-evil"));
507
- validate_pi_wrapper_source(&source, &adapter, &candidate)
428
+ validate_pi_wrapper_source(&source, &candidate)
508
429
  .expect("runtime registration and exact candidate");
430
+ assert!(source.contains("pi.registerMcpServer(alias"));
509
431
  assert!(!source.contains("createMcpAdapter"));
432
+ assert!(!source.contains("pi-mcp-adapter"));
510
433
  assert!(!source.contains("--mcp-config"));
511
434
 
512
- let missing_proxy_tools = source.replace("\"includeTools\"", "\"missingTools\"");
513
- validate_pi_wrapper_source(&missing_proxy_tools, &adapter, &candidate)
514
- .expect_err("wrapper without the MCP proxy tool allowlist must refuse");
435
+ let other_candidate = root.join("candidate/other-team-agent");
436
+ validate_pi_wrapper_source(&source, &other_candidate)
437
+ .expect_err("wrapper bound to a different candidate must refuse");
515
438
 
516
439
  std::fs::remove_dir_all(root).expect("remove wrapper fixture");
517
440
  }
@@ -528,29 +451,14 @@ fn pi_materializer_and_worker_routes_use_the_recorded_scope() {
528
451
  fn pi_materializer_and_worker_routes_body(hermetic: &HermeticTestEnv) {
529
452
  let fixture_root = hermetic.root().join("materializer-fixture");
530
453
  let bin = fixture_root.join("bin");
531
- let adapter_root = fixture_root.join("pi-mcp-adapter");
532
454
  let candidate = fixture_root.join("candidate/team-agent");
533
455
  let real = fixture_root.join("pi-real");
534
456
  std::fs::create_dir_all(&bin).expect("create Pi fixture bin");
535
- std::fs::create_dir_all(&adapter_root).expect("create Pi adapter fixture");
536
457
  std::fs::create_dir_all(candidate.parent().expect("candidate parent"))
537
458
  .expect("create candidate parent");
538
459
  std::fs::write(&candidate, b"candidate").expect("write candidate fixture");
539
- std::fs::write(
540
- adapter_root.join("package.json"),
541
- br#"{"name":"pi-mcp-adapter","version":"2.30.0","pi":{"extensions":["./index.ts"]}}"#,
542
- )
543
- .expect("write adapter package");
544
- std::fs::write(
545
- adapter_root.join("index.ts"),
546
- b"export const createMcpAdapter = () => {};\n",
547
- )
548
- .expect("write adapter entry");
549
- let pi_script = format!(
550
- "#!/bin/sh\ncase \"${{1-}}\" in\n --version) printf '0.84.4\\n' ;;\n --list-models) printf 'provider model\\nteam-agent qwen3.8-27b\\n' ;;\n list) printf 'npm:pi-mcp-adapter\\n{}\\n' ;;\n *) exit 0 ;;\nesac\n",
551
- adapter_root.display()
552
- );
553
- std::fs::write(&real, &pi_script).expect("write Pi real fixture");
460
+ let pi_script = "#!/bin/sh\ncase \"${1-}\" in\n --version) printf '0.84.4\\n' ;;\n --list-models) printf 'provider model\\nteam-agent qwen3.8-27b\\n' ;;\n list) exit 64 ;;\n *) exit 0 ;;\nesac\n";
461
+ std::fs::write(&real, pi_script).expect("write Pi real fixture");
554
462
  std::fs::set_permissions(&real, std::fs::Permissions::from_mode(0o755))
555
463
  .expect("make Pi real fixture executable");
556
464
  std::os::unix::fs::symlink(&real, bin.join("pi")).expect("create Pi PATH symlink");
@@ -47,25 +47,14 @@ impl PathEnvGuard {
47
47
  fn with_fake_pi(root: &Path) -> Self {
48
48
  let wrapper_bin = root.join("bin/wrapper");
49
49
  let real_bin = root.join("bin/real");
50
- let package_root = root.join("node_modules/pi-mcp-adapter");
51
50
  fs::create_dir_all(&wrapper_bin).expect("create fake wrapper bin");
52
51
  fs::create_dir_all(&real_bin).expect("create fake real bin");
53
- fs::create_dir_all(&package_root).expect("create fake adapter package");
54
52
  let wrapper = wrapper_bin.join("pi");
55
- let wrapper_script = format!(
56
- "#!/bin/sh\ncase \"$1\" in\n--version) echo 0.87.1 ;;\n--list-models) printf 'provider model\\nteam-agent qwen3.8-27b\\n' ;;\nlist) printf 'npm:pi-mcp-adapter\\n{}\\n' ;;\nesac\nexit 0\n",
57
- package_root.display()
58
- );
53
+ let wrapper_script = "#!/bin/sh\ncase \"$1\" in\n--version) echo 0.87.1 ;;\n--list-models) printf 'provider model\\nteam-agent qwen3.8-27b\\n' ;;\nlist) exit 64 ;;\nesac\nexit 0\n";
59
54
  fs::write(&wrapper, wrapper_script).expect("write offline Pi wrapper");
60
55
  let real = real_bin.join("pi");
61
56
  fs::write(&real, "#!/bin/sh\necho 0.87.1\nexit 0\n")
62
57
  .expect("write offline Pi real-binary stand-in");
63
- let package =
64
- json!({"name":"pi-mcp-adapter","version":"0.1.0","pi":{"extensions":["./index.ts"]}});
65
- fs::write(package_root.join("package.json"), package.to_string())
66
- .expect("write offline adapter package metadata");
67
- fs::write(package_root.join("index.ts"), "export {};\n")
68
- .expect("write offline adapter extension entry");
69
58
  for pi in [&wrapper, &real] {
70
59
  let mut permissions = fs::metadata(pi).expect("fake Pi metadata").permissions();
71
60
  permissions.set_mode(0o755);