@team-agent/installer 0.5.85 → 0.5.89
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/cli/adapters.rs +2 -2
- package/crates/team-agent/src/cli/emit.rs +56 -12
- package/crates/team-agent/src/cli/mod.rs +0 -1
- package/crates/team-agent/src/cli/status_port/brief.rs +187 -7
- package/crates/team-agent/src/compiler/tests.rs +13 -24
- package/crates/team-agent/src/compiler.rs +5 -57
- package/crates/team-agent/src/leader/start.rs +0 -2
- package/crates/team-agent/src/lifecycle/launch/add_agent.rs +0 -1
- package/crates/team-agent/src/lifecycle/launch/add_agent_state.rs +0 -1
- package/crates/team-agent/src/lifecycle/launch/agent_state.rs +0 -6
- package/crates/team-agent/src/lifecycle/launch/identity.rs +39 -22
- package/crates/team-agent/src/lifecycle/launch/layout.rs +0 -1
- package/crates/team-agent/src/lifecycle/launch/leader_context.rs +0 -1
- package/crates/team-agent/src/lifecycle/launch/mcp_config.rs +0 -58
- package/crates/team-agent/src/lifecycle/launch/ownership.rs +0 -1
- package/crates/team-agent/src/lifecycle/launch/pi_mcp.rs +0 -3
- package/crates/team-agent/src/lifecycle/launch/quick_start.rs +14 -24
- package/crates/team-agent/src/lifecycle/launch/quick_start_transport.rs +0 -1
- package/crates/team-agent/src/lifecycle/launch/readiness.rs +0 -1
- package/crates/team-agent/src/lifecycle/launch/spawn.rs +5 -9
- package/crates/team-agent/src/lifecycle/launch/spec_state.rs +0 -1
- package/crates/team-agent/src/lifecycle/launch/state_projection.rs +0 -1
- package/crates/team-agent/src/lifecycle/launch/worker_env.rs +0 -1
- package/crates/team-agent/src/lifecycle/launch.rs +0 -9
- package/crates/team-agent/src/lifecycle/restart/common.rs +5 -9
- package/crates/team-agent/src/lifecycle/tests/b0_reader_hideone_audit_contract.rs +3 -3
- package/crates/team-agent/src/lifecycle/tests/claude_compatible_config_red.rs +1 -3
- package/crates/team-agent/src/lifecycle/tests/clone_agent_preserves_source_tools.rs +42 -46
- package/crates/team-agent/src/lifecycle/tests/copilot_provider_red.rs +30 -44
- package/crates/team-agent/src/lifecycle/tests/core_034_real_red.rs +32 -77
- package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +2 -13
- package/crates/team-agent/src/lifecycle/tests/pi_catalog_red.rs +0 -1
- package/crates/team-agent/src/lifecycle/tests/pi_command_red.rs +0 -2
- package/crates/team-agent/src/lifecycle/tests/pi_compiler_red.rs +14 -85
- package/crates/team-agent/src/lifecycle/tests/pi_dual_entry_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/pi_executable_mcp_red.rs +0 -5
- package/crates/team-agent/src/lifecycle/tests/pi_session_delivery_red.rs +0 -1
- package/crates/team-agent/src/lifecycle/tests/restart_rebind_hotfix_252_red.rs +4 -4
- package/crates/team-agent/src/lifecycle/tests.rs +0 -1
- package/crates/team-agent/src/lifecycle/types.rs +0 -10
- package/crates/team-agent/src/lifecycle/worker_command_context.rs +4 -248
- package/crates/team-agent/src/model/enums.rs +17 -38
- package/crates/team-agent/src/model/mod.rs +0 -1
- package/crates/team-agent/src/model/spec.rs +31 -91
- package/crates/team-agent/src/provider/adapter.rs +48 -50
- package/crates/team-agent/src/provider/adapters/claude.rs +5 -30
- package/crates/team-agent/src/provider/adapters/codex.rs +5 -25
- package/crates/team-agent/src/provider/adapters/copilot.rs +8 -41
- package/crates/team-agent/src/provider/adapters/cursor_agent.rs +4 -8
- package/crates/team-agent/src/provider/adapters/grok.rs +5 -58
- package/crates/team-agent/src/provider/adapters/mod.rs +5 -7
- package/crates/team-agent/src/provider/adapters/pi.rs +1 -56
- package/crates/team-agent/src/provider/bypass_flags.rs +1 -2
- package/crates/team-agent/src/provider/session/capture.rs +4 -4
- package/crates/team-agent/src/provider/tests/adapter.rs +7 -24
- package/crates/team-agent/src/provider/types.rs +1 -1
- package/crates/team-agent/src/provider/wire.rs +1 -1
- package/package.json +4 -4
- package/schemas/team.schema.json +4 -9
- package/crates/team-agent/src/lifecycle/tests/g1_silent_faces.rs +0 -784
- package/crates/team-agent/src/model/permissions.rs +0 -721
|
@@ -37,7 +37,7 @@ fn bin() -> &'static str {
|
|
|
37
37
|
|
|
38
38
|
#[test]
|
|
39
39
|
#[serial(env)]
|
|
40
|
-
fn
|
|
40
|
+
fn claude_worker_spawn_argv_uses_compiled_prompt_without_tool_restrictions() {
|
|
41
41
|
let _hermetic = enter_hermetic("core034-claude-argv");
|
|
42
42
|
let _ancestry = EnvGuard::set(
|
|
43
43
|
"TEAM_AGENT_TEST_PROCESS_ANCESTRY_ARGV_JSON",
|
|
@@ -80,7 +80,6 @@ fn claude_worker_spawn_argv_uses_compiled_prompt_and_resolved_role_tools() {
|
|
|
80
80
|
"send_message(to='leader'",
|
|
81
81
|
"report_result exactly once",
|
|
82
82
|
"ROLE BODY SENTINEL",
|
|
83
|
-
"Permission note",
|
|
84
83
|
] {
|
|
85
84
|
if !prompt.contains(marker) {
|
|
86
85
|
failures.push(format!("B2 missing compiled prompt marker {marker:?}"));
|
|
@@ -90,31 +89,15 @@ fn claude_worker_spawn_argv_uses_compiled_prompt_and_resolved_role_tools() {
|
|
|
90
89
|
failures.push("B2 prompt collapsed to the bare role label".to_string());
|
|
91
90
|
}
|
|
92
91
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
"Bash",
|
|
96
|
-
"Read",
|
|
97
|
-
"Edit",
|
|
98
|
-
"Write",
|
|
99
|
-
"MultiEdit",
|
|
100
|
-
"NotebookEdit",
|
|
101
|
-
"Glob",
|
|
102
|
-
"Grep",
|
|
103
|
-
] {
|
|
104
|
-
if disallowed.iter().any(|tool| tool == forbidden) {
|
|
105
|
-
failures.push(format!(
|
|
106
|
-
"B1 declared capability still disallowed via --disallowedTools {forbidden:?}"
|
|
107
|
-
));
|
|
108
|
-
}
|
|
92
|
+
if argv_has_flag(&spawn.argv, "--disallowedTools") {
|
|
93
|
+
failures.push("B1 Claude argv must not derive --disallowedTools from tools metadata".to_string());
|
|
109
94
|
}
|
|
110
95
|
if argv_has_flag(&spawn.argv, "--allowedTools") {
|
|
111
|
-
failures.push(
|
|
112
|
-
"B1 Python parity violated: Claude argv must not switch to --allowedTools".to_string(),
|
|
113
|
-
);
|
|
96
|
+
failures.push("B1 Claude argv must not derive --allowedTools from tools metadata".to_string());
|
|
114
97
|
}
|
|
115
98
|
assert!(
|
|
116
99
|
failures.is_empty(),
|
|
117
|
-
"B1/B2 worker argv contract failed:\n{}\nprompt={prompt:?}\
|
|
100
|
+
"B1/B2 worker argv contract failed:\n{}\nprompt={prompt:?}\nargv={:?}",
|
|
118
101
|
failures.join("\n"),
|
|
119
102
|
spawn.argv
|
|
120
103
|
);
|
|
@@ -122,7 +105,7 @@ fn claude_worker_spawn_argv_uses_compiled_prompt_and_resolved_role_tools() {
|
|
|
122
105
|
|
|
123
106
|
#[test]
|
|
124
107
|
#[serial(env)]
|
|
125
|
-
fn
|
|
108
|
+
fn claude_control_role_does_not_derive_native_tool_restrictions() {
|
|
126
109
|
let _hermetic = enter_hermetic("core034-claude-control");
|
|
127
110
|
let _ancestry = EnvGuard::set(
|
|
128
111
|
"TEAM_AGENT_TEST_PROCESS_ANCESTRY_ARGV_JSON",
|
|
@@ -156,29 +139,21 @@ fn claude_control_role_without_native_tools_still_disallows_native_tools() {
|
|
|
156
139
|
.expect("quick-start should record the control worker command");
|
|
157
140
|
|
|
158
141
|
let spawn = transport.single_spawn();
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
"
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
"
|
|
166
|
-
"
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
] {
|
|
170
|
-
assert!(
|
|
171
|
-
disallowed.iter().any(|tool| tool == expected),
|
|
172
|
-
"B1 negative case: mcp_team-only control roles must still disallow native Claude tools; \
|
|
173
|
-
missing={expected} disallowed={disallowed:?}\nargv={:?}",
|
|
174
|
-
spawn.argv
|
|
175
|
-
);
|
|
176
|
-
}
|
|
142
|
+
assert!(
|
|
143
|
+
!argv_has_flag(&spawn.argv, "--disallowedTools"),
|
|
144
|
+
"B1 control role must not derive native-tool restrictions from tools metadata; argv={:?}",
|
|
145
|
+
spawn.argv
|
|
146
|
+
);
|
|
147
|
+
assert!(
|
|
148
|
+
!argv_has_flag(&spawn.argv, "--allowedTools"),
|
|
149
|
+
"B1 control role must not derive an allowlist from tools metadata; argv={:?}",
|
|
150
|
+
spawn.argv
|
|
151
|
+
);
|
|
177
152
|
}
|
|
178
153
|
|
|
179
154
|
#[test]
|
|
180
155
|
#[serial(env)]
|
|
181
|
-
fn
|
|
156
|
+
fn restart_claude_worker_does_not_derive_tool_restrictions_when_runtime_state_has_no_raw_tools() {
|
|
182
157
|
let _hermetic = enter_hermetic("core034-restart-tools");
|
|
183
158
|
let _ancestry = EnvGuard::set(
|
|
184
159
|
"TEAM_AGENT_TEST_PROCESS_ANCESTRY_ARGV_JSON",
|
|
@@ -215,34 +190,20 @@ fn restart_claude_worker_resolves_tools_from_spec_when_runtime_state_has_no_raw_
|
|
|
215
190
|
let report = restart_with_transport(&ws, true, Some("restarttools"), &restart_transport)
|
|
216
191
|
.expect("restart should reach worker command construction");
|
|
217
192
|
let spawn = restart_transport.single_spawn();
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
"Edit",
|
|
224
|
-
"Write",
|
|
225
|
-
"MultiEdit",
|
|
226
|
-
"NotebookEdit",
|
|
227
|
-
"Glob",
|
|
228
|
-
"Grep",
|
|
229
|
-
] {
|
|
230
|
-
assert!(
|
|
231
|
-
!disallowed.iter().any(|tool| tool == forbidden),
|
|
232
|
-
"B1 restart contract: when runtime state lacks raw tools, restart must resolve tools from the selected spec/role through resolve_permissions. \
|
|
233
|
-
{forbidden} must not be disallowed for this role; disallowed={disallowed:?}\nargv={:?}\nreport={report:?}",
|
|
234
|
-
spawn.argv
|
|
235
|
-
);
|
|
236
|
-
}
|
|
193
|
+
assert!(
|
|
194
|
+
!argv_has_flag(&spawn.argv, "--disallowedTools"),
|
|
195
|
+
"B1 restart must not derive native-tool restrictions from tools metadata; argv={:?} report={report:?}",
|
|
196
|
+
spawn.argv
|
|
197
|
+
);
|
|
237
198
|
assert!(
|
|
238
199
|
!argv_has_flag(&spawn.argv, "--allowedTools"),
|
|
239
|
-
"B1
|
|
200
|
+
"B1 restart must not derive an allowlist from tools metadata; argv={:?} report={report:?}",
|
|
240
201
|
spawn.argv
|
|
241
202
|
);
|
|
242
203
|
}
|
|
243
204
|
|
|
244
205
|
#[test]
|
|
245
|
-
fn
|
|
206
|
+
fn worker_command_context_uses_single_prompt_without_permission_sources() {
|
|
246
207
|
let crate_root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
|
247
208
|
let src_root = crate_root.join("src");
|
|
248
209
|
let launch = composite_source::composite_source("src/lifecycle/launch.rs");
|
|
@@ -276,10 +237,9 @@ fn worker_command_context_uses_single_prompt_and_permission_sources() {
|
|
|
276
237
|
&& all_src.contains("runtime_contract_section")
|
|
277
238
|
&& all_src.contains("identity_section")
|
|
278
239
|
&& all_src.contains("role_body")
|
|
279
|
-
&& all_src.contains("output_contract")
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
(runtime_contract_section, identity_section, role_body, output_contract, permission_notes)."
|
|
240
|
+
&& all_src.contains("output_contract"),
|
|
241
|
+
"B2 grep guard: worker command construction needs one compiled prompt helper with the CR-approved four sections \
|
|
242
|
+
(runtime_contract_section, identity_section, role_body, output_contract)."
|
|
283
243
|
);
|
|
284
244
|
assert!(
|
|
285
245
|
!command_sources.contains("system_prompt: role"),
|
|
@@ -296,8 +256,9 @@ fn worker_command_context_uses_single_prompt_and_permission_sources() {
|
|
|
296
256
|
);
|
|
297
257
|
|
|
298
258
|
assert!(
|
|
299
|
-
|
|
300
|
-
|
|
259
|
+
!command_sources.contains("resolve_permissions")
|
|
260
|
+
&& !command_sources.contains("resolved_tool_strings"),
|
|
261
|
+
"B1 grep guard: command construction must not derive argv restrictions from tools metadata."
|
|
301
262
|
);
|
|
302
263
|
assert!(
|
|
303
264
|
!command_sources.contains("worker_tool_refs(agent_tool_strings")
|
|
@@ -305,8 +266,8 @@ fn worker_command_context_uses_single_prompt_and_permission_sources() {
|
|
|
305
266
|
"B1 grep guard: command construction must not raw-pass agent.tools/tool_refs into ProviderCommandContext."
|
|
306
267
|
);
|
|
307
268
|
assert!(
|
|
308
|
-
adapter.contains("--disallowedTools") && !adapter.contains("--allowedTools"),
|
|
309
|
-
"B1
|
|
269
|
+
!adapter.contains("--disallowedTools") && !adapter.contains("--allowedTools"),
|
|
270
|
+
"B1 provider adapter must not derive Claude tool restrictions from tools metadata."
|
|
310
271
|
);
|
|
311
272
|
assert!(
|
|
312
273
|
!adapter.contains("resolve_permissions"),
|
|
@@ -837,12 +798,6 @@ fn flag_value(argv: &[String], flag: &str) -> Option<String> {
|
|
|
837
798
|
.find_map(|pair| (pair[0] == flag).then(|| pair[1].clone()))
|
|
838
799
|
}
|
|
839
800
|
|
|
840
|
-
fn flag_values(argv: &[String], flag: &str) -> Vec<String> {
|
|
841
|
-
argv.windows(2)
|
|
842
|
-
.filter_map(|pair| (pair[0] == flag).then(|| pair[1].clone()))
|
|
843
|
-
.collect()
|
|
844
|
-
}
|
|
845
|
-
|
|
846
801
|
fn argv_has_flag(argv: &[String], flag: &str) -> bool {
|
|
847
802
|
argv.iter().any(|arg| arg == flag)
|
|
848
803
|
}
|
|
@@ -520,8 +520,8 @@ fn launch_dry_run_resolves_real_plan_not_stub_error() {
|
|
|
520
520
|
Ok(report) => {
|
|
521
521
|
assert!(report.dry_run, "dry_run launch must report dry_run=true");
|
|
522
522
|
assert!(
|
|
523
|
-
!report.routes.is_empty()
|
|
524
|
-
"dry_run launch must resolve a real route
|
|
523
|
+
!report.routes.is_empty(),
|
|
524
|
+
"dry_run launch must resolve a real route plan from the compiled spec"
|
|
525
525
|
);
|
|
526
526
|
}
|
|
527
527
|
// any OTHER Err (a real requirement/transport error) still proves the stub is gone.
|
|
@@ -3210,7 +3210,6 @@ fn quick_start_running_agent_state_shape_after_spawn_is_golden() {
|
|
|
3210
3210
|
"profile",
|
|
3211
3211
|
"window",
|
|
3212
3212
|
"mcp_config",
|
|
3213
|
-
"permissions",
|
|
3214
3213
|
"effective_approval_policy",
|
|
3215
3214
|
// 0.5.66 bypass 单源:fresh spawn 记录运行面 bypass 值(restart drift 挡板)。
|
|
3216
3215
|
"as_launched_dangerously_skip_permissions",
|
|
@@ -3239,16 +3238,6 @@ fn quick_start_running_agent_state_shape_after_spawn_is_golden() {
|
|
|
3239
3238
|
.join(".team/runtime/mcp/implementer.json")
|
|
3240
3239
|
.to_string_lossy())
|
|
3241
3240
|
);
|
|
3242
|
-
assert_eq!(
|
|
3243
|
-
agent["permissions"],
|
|
3244
|
-
json!({
|
|
3245
|
-
"agent_id": "implementer",
|
|
3246
|
-
"provider": "codex",
|
|
3247
|
-
"tools": ["mcp_team"],
|
|
3248
|
-
"resolved_tools": [{"tool": "mcp_team", "enforcement": "prompt_only"}],
|
|
3249
|
-
"has_prompt_only": true
|
|
3250
|
-
})
|
|
3251
|
-
);
|
|
3252
3241
|
assert!(agent["session_id"].is_null());
|
|
3253
3242
|
assert!(agent["rollout_path"].is_null());
|
|
3254
3243
|
assert!(agent["captured_at"].is_null());
|
|
@@ -91,7 +91,6 @@ fn command_for_model(model: &str) -> Vec<String> {
|
|
|
91
91
|
model: Some(model),
|
|
92
92
|
effort: Some(ProviderEffort::Medium),
|
|
93
93
|
system_prompt: "worker contract",
|
|
94
|
-
tool_categories: &["mcp_team"],
|
|
95
94
|
session_dir: Some(Path::new("/workspace/.team/runtime/pi/t1/w1/sessions")),
|
|
96
95
|
session: PiSessionSelector::Fresh {
|
|
97
96
|
session_id: "716ba0cb-c491-4471-b41a-43c8d5e1f05a",
|
|
@@ -10,7 +10,6 @@ fn request(session: PiSessionSelector<'static>) -> PiCommandRequest<'static> {
|
|
|
10
10
|
model: Some("team-agent/qwen3.8-27b"),
|
|
11
11
|
effort: Some(ProviderEffort::High),
|
|
12
12
|
system_prompt: "frozen worker prompt",
|
|
13
|
-
tool_categories: &["mcp_team", "fs_read", "fs_write", "execute_bash"],
|
|
14
13
|
session_dir: Some(Path::new(
|
|
15
14
|
"/workspace/.team/runtime/pi/team-a/worker-a/sessions",
|
|
16
15
|
)),
|
|
@@ -38,7 +37,6 @@ fn leader_request() -> PiCommandRequest<'static> {
|
|
|
38
37
|
model: None,
|
|
39
38
|
effort: None,
|
|
40
39
|
system_prompt: "frozen leader prompt",
|
|
41
|
-
tool_categories: &["mcp_team", "fs_read", "fs_write", "execute_bash"],
|
|
42
40
|
session_dir: None,
|
|
43
41
|
session: PiSessionSelector::Fresh {
|
|
44
42
|
session_id: "da8c3622-2378-4d05-a26c-e826a6ef6d63",
|
|
@@ -6,9 +6,7 @@ use crate::lifecycle::launch::pi_mcp::{parse_pi_list_models_table, select_exact_
|
|
|
6
6
|
use crate::model::enums::ProviderEffort;
|
|
7
7
|
use crate::model::yaml::Value;
|
|
8
8
|
use crate::model::ModelError;
|
|
9
|
-
use crate::provider::adapters::pi::{
|
|
10
|
-
build_pi_command_argv, pi_tool_mapping, PiCommandRequest, PiSessionSelector, PiToolMapping,
|
|
11
|
-
};
|
|
9
|
+
use crate::provider::adapters::pi::{build_pi_command_argv, PiCommandRequest, PiSessionSelector};
|
|
12
10
|
|
|
13
11
|
const CATALOG: &[u8] = include_bytes!("fixtures/pi_list_models_g0.stdout.txt");
|
|
14
12
|
static NEXT_ROLE: AtomicU32 = AtomicU32::new(0);
|
|
@@ -51,13 +49,12 @@ fn compile_error(result: Result<CompiledRole, ModelError>) -> ModelError {
|
|
|
51
49
|
}
|
|
52
50
|
}
|
|
53
51
|
|
|
54
|
-
fn command(
|
|
52
|
+
fn command(_tools: &[&str], effort: ProviderEffort, model: &str) -> Result<Vec<String>, String> {
|
|
55
53
|
build_pi_command_argv(PiCommandRequest {
|
|
56
54
|
extension: Path::new("/workspace/.team/runtime/pi/t1/pi-worker/team-mcp.ts"),
|
|
57
55
|
model: Some(model),
|
|
58
56
|
effort: Some(effort),
|
|
59
57
|
system_prompt: "Pi worker contract.",
|
|
60
|
-
tool_categories: tools,
|
|
61
58
|
session_dir: Some(Path::new(
|
|
62
59
|
"/workspace/.team/runtime/pi/t1/pi-worker/sessions",
|
|
63
60
|
)),
|
|
@@ -70,24 +67,22 @@ fn command(tools: &[&str], effort: ProviderEffort, model: &str) -> Result<Vec<St
|
|
|
70
67
|
}
|
|
71
68
|
|
|
72
69
|
#[test]
|
|
73
|
-
fn
|
|
70
|
+
fn pi_role_ignores_tools_and_preserves_provider_defaults() {
|
|
74
71
|
let positive = compile_pi_role(&valid_role_with(""));
|
|
75
72
|
assert!(positive.is_ok(), "fully explicit Pi role must compile");
|
|
76
73
|
|
|
77
|
-
let
|
|
74
|
+
let missing_tools = valid_role_with("").replace(
|
|
75
|
+
"tools:\n - mcp_team\n - fs_read\n - fs_list\n - fs_write\n - execute_bash\n",
|
|
76
|
+
"",
|
|
77
|
+
);
|
|
78
|
+
compile_pi_role(&missing_tools).expect("omitted tools metadata must compile");
|
|
78
79
|
let unqualified =
|
|
79
80
|
valid_role_with("").replace("model: team-agent/qwen3.8-27b", "model: qwen3.8-27b");
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
("
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
let error = compile_error(compile_pi_role(&role));
|
|
86
|
-
assert!(
|
|
87
|
-
error.to_string().to_ascii_lowercase().contains(label),
|
|
88
|
-
"error must name {label}; got {error}"
|
|
89
|
-
);
|
|
90
|
-
}
|
|
81
|
+
let error = compile_error(compile_pi_role(&unqualified));
|
|
82
|
+
assert!(
|
|
83
|
+
error.to_string().to_ascii_lowercase().contains("qualified exact model"),
|
|
84
|
+
"error must name qualified model; got {error}"
|
|
85
|
+
);
|
|
91
86
|
|
|
92
87
|
let defaults = valid_role_with("")
|
|
93
88
|
.replace("model: team-agent/qwen3.8-27b\n", "")
|
|
@@ -195,42 +190,7 @@ fn pi_max_effort_is_supported_without_model_suffix() {
|
|
|
195
190
|
}
|
|
196
191
|
|
|
197
192
|
#[test]
|
|
198
|
-
fn
|
|
199
|
-
assert_eq!(pi_tool_mapping("mcp_team"), PiToolMapping::Mcp);
|
|
200
|
-
assert_eq!(
|
|
201
|
-
pi_tool_mapping("fs_read"),
|
|
202
|
-
PiToolMapping::Builtin(&["read"])
|
|
203
|
-
);
|
|
204
|
-
assert_eq!(
|
|
205
|
-
pi_tool_mapping("fs_list"),
|
|
206
|
-
PiToolMapping::Builtin(&["grep", "find", "ls"])
|
|
207
|
-
);
|
|
208
|
-
assert_eq!(
|
|
209
|
-
pi_tool_mapping("fs_write"),
|
|
210
|
-
PiToolMapping::Builtin(&["edit", "write"])
|
|
211
|
-
);
|
|
212
|
-
assert_eq!(
|
|
213
|
-
pi_tool_mapping("execute_bash"),
|
|
214
|
-
PiToolMapping::Builtin(&["bash"])
|
|
215
|
-
);
|
|
216
|
-
|
|
217
|
-
for unsupported in ["git_diff", "network", "provider_builtin", "not_a_tool"] {
|
|
218
|
-
assert_eq!(
|
|
219
|
-
pi_tool_mapping(unsupported),
|
|
220
|
-
PiToolMapping::Unsupported,
|
|
221
|
-
"unknown categories must not silently broaden to bash"
|
|
222
|
-
);
|
|
223
|
-
assert!(
|
|
224
|
-
command(
|
|
225
|
-
&["mcp_team", unsupported],
|
|
226
|
-
ProviderEffort::Medium,
|
|
227
|
-
"team-agent/qwen3.8-27b"
|
|
228
|
-
)
|
|
229
|
-
.is_err(),
|
|
230
|
-
"unsupported tool must refuse the command: {unsupported}"
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
|
|
193
|
+
fn pi_role_command_ignores_legacy_tool_metadata() {
|
|
234
194
|
let argv = command(
|
|
235
195
|
&["mcp_team", "fs_write", "fs_read", "fs_list", "execute_bash"],
|
|
236
196
|
ProviderEffort::Medium,
|
|
@@ -242,34 +202,3 @@ fn pi_role_tools_validate_team_capabilities_without_replacing_direct_pi_tools()
|
|
|
242
202
|
"role tools validate Team Agent capabilities but must not replace direct Pi tools: {argv:?}"
|
|
243
203
|
);
|
|
244
204
|
}
|
|
245
|
-
|
|
246
|
-
#[test]
|
|
247
|
-
fn pi_role_rejects_unsupported_categories_during_compile() {
|
|
248
|
-
compile_pi_role(&valid_role_with("")).expect("supported Pi tools must compile");
|
|
249
|
-
|
|
250
|
-
for unsupported in ["git_diff", "network", "provider_builtin"] {
|
|
251
|
-
let role = valid_role_with("").replace(
|
|
252
|
-
" - execute_bash\n",
|
|
253
|
-
&format!(" - execute_bash\n - {unsupported}\n"),
|
|
254
|
-
);
|
|
255
|
-
let error = compile_error(compile_pi_role(&role)).to_string();
|
|
256
|
-
assert!(
|
|
257
|
-
error.contains(&format!("Pi does not support Team Agent tool category {unsupported:?}")),
|
|
258
|
-
"compile must reject {unsupported} before launch preparation: {error}"
|
|
259
|
-
);
|
|
260
|
-
assert!(
|
|
261
|
-
error.contains("remove it from the role's tools"),
|
|
262
|
-
"compile error must provide an actionable fix: {error}"
|
|
263
|
-
);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
let alias = valid_role_with("").replace(
|
|
267
|
-
" - execute_bash\n",
|
|
268
|
-
" - execute_bash\n - \"@builtin\"\n",
|
|
269
|
-
);
|
|
270
|
-
let error = compile_error(compile_pi_role(&alias)).to_string();
|
|
271
|
-
assert!(
|
|
272
|
-
error.contains("Pi does not support Team Agent tool category \"provider_builtin\""),
|
|
273
|
-
"@builtin must use the same Pi capability contract: {error}"
|
|
274
|
-
);
|
|
275
|
-
}
|
|
@@ -572,7 +572,6 @@ fn pi_materializer_and_worker_routes_body(hermetic: &HermeticTestEnv) {
|
|
|
572
572
|
model: None,
|
|
573
573
|
effort: None,
|
|
574
574
|
system_prompt: "native leader fixture",
|
|
575
|
-
tool_categories: &["mcp_team"],
|
|
576
575
|
team_mcp_tools: &["send_message"],
|
|
577
576
|
mcp_config: &native_config,
|
|
578
577
|
session_scope: PiSessionScope::NativeDefault,
|
|
@@ -605,7 +604,6 @@ fn pi_materializer_and_worker_routes_body(hermetic: &HermeticTestEnv) {
|
|
|
605
604
|
model: Some("team-agent/qwen3.8-27b"),
|
|
606
605
|
effort: Some(ProviderEffort::Medium),
|
|
607
606
|
system_prompt: "isolated worker fixture",
|
|
608
|
-
tool_categories: &["mcp_team"],
|
|
609
607
|
team_mcp_tools: &["send_message"],
|
|
610
608
|
mcp_config: &isolated_config,
|
|
611
609
|
session_scope: PiSessionScope::Isolated,
|
|
@@ -633,7 +631,6 @@ fn pi_materializer_and_worker_routes_body(hermetic: &HermeticTestEnv) {
|
|
|
633
631
|
model: None,
|
|
634
632
|
effort: None,
|
|
635
633
|
system_prompt: "isolated resume fixture",
|
|
636
|
-
tool_categories: &["mcp_team"],
|
|
637
634
|
team_mcp_tools: &["send_message"],
|
|
638
635
|
mcp_config: &isolated_config,
|
|
639
636
|
session_scope: PiSessionScope::Isolated,
|
|
@@ -664,7 +661,6 @@ fn pi_materializer_and_worker_routes_body(hermetic: &HermeticTestEnv) {
|
|
|
664
661
|
model: None,
|
|
665
662
|
effort: None,
|
|
666
663
|
system_prompt: "native resume fixture",
|
|
667
|
-
tool_categories: &["mcp_team"],
|
|
668
664
|
team_mcp_tools: &["send_message"],
|
|
669
665
|
mcp_config: &native_config,
|
|
670
666
|
session_scope: PiSessionScope::NativeDefault,
|
|
@@ -699,7 +695,6 @@ fn pi_materializer_and_worker_routes_body(hermetic: &HermeticTestEnv) {
|
|
|
699
695
|
model: None,
|
|
700
696
|
effort: None,
|
|
701
697
|
system_prompt: "isolated negative resume fixture",
|
|
702
|
-
tool_categories: &["mcp_team"],
|
|
703
698
|
team_mcp_tools: &["send_message"],
|
|
704
699
|
mcp_config: &isolated_config,
|
|
705
700
|
session_scope: PiSessionScope::Isolated,
|
|
@@ -58,7 +58,6 @@ fn resume_argv(path: &Path) -> Result<Vec<String>, ProviderError> {
|
|
|
58
58
|
model: Some("team-agent/qwen3.8-27b"),
|
|
59
59
|
effort: Some(ProviderEffort::Medium),
|
|
60
60
|
system_prompt: "worker contract",
|
|
61
|
-
tool_categories: &["mcp_team"],
|
|
62
61
|
session_dir: Some(Path::new(
|
|
63
62
|
"/workspace/.team/runtime/pi/team-a/worker-a/sessions",
|
|
64
63
|
)),
|
|
@@ -901,13 +901,13 @@ impl ProviderAdapter for StaticCaptureAdapter {
|
|
|
901
901
|
Ok(vec!["fake".to_string()])
|
|
902
902
|
}
|
|
903
903
|
|
|
904
|
-
fn
|
|
904
|
+
fn build_command_with_permissions(
|
|
905
905
|
&self,
|
|
906
906
|
auth_mode: AuthMode,
|
|
907
907
|
mcp_config: Option<&McpConfig>,
|
|
908
908
|
system_prompt: Option<&str>,
|
|
909
909
|
model: Option<&str>,
|
|
910
|
-
|
|
910
|
+
_dangerously_skip_permissions: bool,
|
|
911
911
|
) -> Result<Vec<String>, ProviderError> {
|
|
912
912
|
self.build_command(auth_mode, mcp_config, system_prompt, model)
|
|
913
913
|
}
|
|
@@ -959,7 +959,7 @@ impl ProviderAdapter for StaticCaptureAdapter {
|
|
|
959
959
|
mcp_config: Option<&McpConfig>,
|
|
960
960
|
_system_prompt: Option<&str>,
|
|
961
961
|
_model: Option<&str>,
|
|
962
|
-
|
|
962
|
+
_dangerously_skip_permissions: bool,
|
|
963
963
|
) -> Result<Vec<String>, ProviderError> {
|
|
964
964
|
self.build_resume_command(session_id, auth_mode, mcp_config)
|
|
965
965
|
}
|
|
@@ -980,7 +980,7 @@ impl ProviderAdapter for StaticCaptureAdapter {
|
|
|
980
980
|
mcp_config: Option<&McpConfig>,
|
|
981
981
|
_system_prompt: Option<&str>,
|
|
982
982
|
_model: Option<&str>,
|
|
983
|
-
|
|
983
|
+
_dangerously_skip_permissions: bool,
|
|
984
984
|
) -> Result<Vec<String>, ProviderError> {
|
|
985
985
|
self.fork(session_id, auth_mode, mcp_config)
|
|
986
986
|
}
|
|
@@ -64,7 +64,6 @@ mod cursor_require_explicit_model_red;
|
|
|
64
64
|
mod cursor_restart_resume_red;
|
|
65
65
|
mod display_adaptive_red;
|
|
66
66
|
mod f032_startup_prompt_best_effort_red;
|
|
67
|
-
mod g1_silent_faces;
|
|
68
67
|
mod grok_effort_argv_red;
|
|
69
68
|
mod grok_mcp_overlay_red;
|
|
70
69
|
mod grok_require_explicit_model_red;
|
|
@@ -540,8 +540,6 @@ pub struct LaunchReport {
|
|
|
540
540
|
pub tmux_endpoint: Option<String>,
|
|
541
541
|
/// 路由决策(每 task 一条;`routing.decision` 事件)。
|
|
542
542
|
pub routes: Vec<RoutingDecision>,
|
|
543
|
-
/// 权限摘要(每 agent 一条)。
|
|
544
|
-
pub permissions: Vec<PermissionSummary>,
|
|
545
543
|
/// leader receiver(attach 成功时;经 step10 leader::attach_leader_to_state)。
|
|
546
544
|
pub leader_receiver_attached: bool,
|
|
547
545
|
pub leader_bind_stage: Option<String>,
|
|
@@ -577,14 +575,6 @@ pub struct RoutingDecision {
|
|
|
577
575
|
pub manual_override: bool,
|
|
578
576
|
}
|
|
579
577
|
|
|
580
|
-
/// 权限摘要(`resolve_permissions(agent)` 的 typed 版)。**PLACEHOLDER 字段**:
|
|
581
|
-
/// 实际形状由 step6 compiler 的 `resolve_permissions` 决定,集成时映射。
|
|
582
|
-
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
583
|
-
pub struct PermissionSummary {
|
|
584
|
-
pub agent_id: AgentId,
|
|
585
|
-
pub raw: serde_json::Value,
|
|
586
|
-
}
|
|
587
|
-
|
|
588
578
|
/// BUG-7 (0.3.1): quick-start cannot honestly report "ready" before the workers'
|
|
589
579
|
/// MCP tool sets have actually loaded — provider-side schema rejections (codex
|
|
590
580
|
/// invalid_function_parameters etc.) happen AFTER spawn and silently disable the
|