@team-agent/installer 0.4.5 → 0.4.7
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 +6 -1
- package/crates/team-agent/src/cli/status_port.rs +119 -66
- package/crates/team-agent/src/cli/tests/status_send.rs +74 -48
- package/crates/team-agent/src/coordinator/tests/health_sync.rs +6 -1
- package/crates/team-agent/src/coordinator/tick.rs +46 -21
- package/crates/team-agent/src/leader/helpers.rs +1 -22
- package/crates/team-agent/src/lifecycle/launch.rs +34 -17
- package/crates/team-agent/src/lifecycle/profile_launch.rs +1 -11
- package/crates/team-agent/src/lifecycle/restart/agent.rs +160 -0
- package/crates/team-agent/src/lifecycle/restart/common.rs +82 -22
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +108 -50
- package/crates/team-agent/src/lifecycle/restart/selection.rs +23 -0
- package/crates/team-agent/src/lifecycle/tests/core.rs +19 -11
- package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +23 -1
- package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +163 -15
- package/crates/team-agent/src/provider/adapter.rs +217 -377
- package/crates/team-agent/src/provider/adapters/claude.rs +106 -0
- package/crates/team-agent/src/provider/adapters/codex.rs +117 -0
- package/crates/team-agent/src/provider/adapters/copilot.rs +124 -0
- package/crates/team-agent/src/provider/adapters/fake.rs +17 -0
- package/crates/team-agent/src/provider/adapters/mod.rs +27 -0
- package/crates/team-agent/src/provider/mod.rs +6 -0
- package/crates/team-agent/src/provider/session/capture.rs +593 -55
- package/crates/team-agent/src/provider/wire.rs +139 -0
- package/crates/team-agent/src/state/persist.rs +225 -10
- package/package.json +4 -4
- package/skills/team-agent/SKILL.md +6 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
//! Claude / ClaudeCode provider-local command builders + permission helpers.
|
|
2
|
+
//!
|
|
3
|
+
//! Extracted from `provider/adapter.rs` (0.4.x decoupling step 2). Pure
|
|
4
|
+
//! extraction — byte-identical to the original inline forms. Scope kept
|
|
5
|
+
//! small on purpose: base command + permission/disallowed-tool mapping +
|
|
6
|
+
//! launch wrapper. Auth hints (`claude_auth_hint`), capture-related
|
|
7
|
+
//! helpers (`claude_projects_dir_for_cwd`, `encode_claude_projects_dir`,
|
|
8
|
+
//! `rollout_path_has_claude_leader_marker`,
|
|
9
|
+
//! `claude_records_have_leader_marker`), and the context-aware model
|
|
10
|
+
//! resolver (`claude_context_model`) stay in `adapter.rs` because they
|
|
11
|
+
//! depend on adapter-private utilities (capture scanning, `command_on_path`,
|
|
12
|
+
//! `ProfileLaunchContext`). A later step can move those into a session
|
|
13
|
+
//! store / auth descriptor hook.
|
|
14
|
+
|
|
15
|
+
use crate::model::enums::AuthMode;
|
|
16
|
+
use crate::provider::adapter::{
|
|
17
|
+
next_session_token, prompt_needs_native_mcp, BasicProviderAdapter,
|
|
18
|
+
};
|
|
19
|
+
use crate::provider::{McpConfig, ProviderAdapter, ProviderError};
|
|
20
|
+
|
|
21
|
+
pub(crate) fn claude_launch_command(
|
|
22
|
+
adapter: &BasicProviderAdapter,
|
|
23
|
+
auth_mode: AuthMode,
|
|
24
|
+
mcp_config: Option<&McpConfig>,
|
|
25
|
+
system_prompt: Option<&str>,
|
|
26
|
+
model: Option<&str>,
|
|
27
|
+
tools: &[&str],
|
|
28
|
+
) -> Result<Vec<String>, ProviderError> {
|
|
29
|
+
let mut argv = claude_base_command(
|
|
30
|
+
adapter,
|
|
31
|
+
auth_mode,
|
|
32
|
+
mcp_config,
|
|
33
|
+
system_prompt,
|
|
34
|
+
model,
|
|
35
|
+
tools,
|
|
36
|
+
false,
|
|
37
|
+
)?;
|
|
38
|
+
argv.push("--session-id".to_string());
|
|
39
|
+
argv.push(next_session_token());
|
|
40
|
+
Ok(argv)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
pub(crate) fn claude_base_command(
|
|
44
|
+
adapter: &BasicProviderAdapter,
|
|
45
|
+
auth_mode: AuthMode,
|
|
46
|
+
mcp_config: Option<&McpConfig>,
|
|
47
|
+
system_prompt: Option<&str>,
|
|
48
|
+
model: Option<&str>,
|
|
49
|
+
tools: &[&str],
|
|
50
|
+
managed_mcp_config: bool,
|
|
51
|
+
) -> Result<Vec<String>, ProviderError> {
|
|
52
|
+
let mut argv = vec!["claude".to_string()];
|
|
53
|
+
if claude_dangerous_auto_approve(tools) {
|
|
54
|
+
argv.push("--dangerously-skip-permissions".to_string());
|
|
55
|
+
} else {
|
|
56
|
+
argv.push("--permission-mode".to_string());
|
|
57
|
+
argv.push("default".to_string());
|
|
58
|
+
}
|
|
59
|
+
if let Some(model) = model {
|
|
60
|
+
argv.push("--model".to_string());
|
|
61
|
+
argv.push(model.to_string());
|
|
62
|
+
}
|
|
63
|
+
if let Some(prompt) = system_prompt {
|
|
64
|
+
argv.push("--append-system-prompt".to_string());
|
|
65
|
+
argv.push(prompt.to_string());
|
|
66
|
+
}
|
|
67
|
+
if !managed_mcp_config
|
|
68
|
+
&& (mcp_config.is_some()
|
|
69
|
+
|| auth_mode == AuthMode::CompatibleApi
|
|
70
|
+
|| system_prompt.is_some_and(prompt_needs_native_mcp))
|
|
71
|
+
{
|
|
72
|
+
let raw = if let Some(config) = mcp_config {
|
|
73
|
+
serde_json::json!({"mcpServers": config.raw.clone()})
|
|
74
|
+
} else {
|
|
75
|
+
serde_json::json!({"mcpServers": adapter.mcp_config(auth_mode)?.raw})
|
|
76
|
+
};
|
|
77
|
+
argv.push("--mcp-config".to_string());
|
|
78
|
+
argv.push(raw.to_string());
|
|
79
|
+
}
|
|
80
|
+
for tool in claude_disallowed_tools(tools) {
|
|
81
|
+
argv.push("--disallowedTools".to_string());
|
|
82
|
+
argv.push(tool.to_string());
|
|
83
|
+
}
|
|
84
|
+
Ok(argv)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
pub(crate) fn claude_dangerous_auto_approve(tools: &[&str]) -> bool {
|
|
88
|
+
tools.contains(&"dangerous_auto_approve")
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
pub(crate) fn claude_disallowed_tools(tools: &[&str]) -> Vec<&'static str> {
|
|
92
|
+
let mut disallowed = Vec::new();
|
|
93
|
+
if !tools.contains(&"execute_bash") {
|
|
94
|
+
disallowed.push("Bash");
|
|
95
|
+
}
|
|
96
|
+
if !tools.contains(&"fs_read") {
|
|
97
|
+
disallowed.push("Read");
|
|
98
|
+
}
|
|
99
|
+
if !tools.contains(&"fs_write") {
|
|
100
|
+
disallowed.extend(["Edit", "Write", "MultiEdit", "NotebookEdit"]);
|
|
101
|
+
}
|
|
102
|
+
if !tools.contains(&"fs_list") {
|
|
103
|
+
disallowed.extend(["Glob", "Grep"]);
|
|
104
|
+
}
|
|
105
|
+
disallowed
|
|
106
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
//! Codex provider-local command builder + permission/sandbox helpers.
|
|
2
|
+
//!
|
|
3
|
+
//! Extracted from `provider/adapter.rs` (0.4.x decoupling step 2). Pure
|
|
4
|
+
//! extraction — byte-identical to the original inline forms. Shared helper
|
|
5
|
+
//! `json_inline` stays in `adapter.rs` because it is also used by other
|
|
6
|
+
//! sites; this file reaches it via `super::*`.
|
|
7
|
+
|
|
8
|
+
use crate::model::enums::AuthMode;
|
|
9
|
+
use crate::provider::adapter::json_inline;
|
|
10
|
+
use crate::provider::{McpConfig, ProviderCommandOverrides};
|
|
11
|
+
|
|
12
|
+
pub(crate) fn codex_base_command(
|
|
13
|
+
subcommand: Option<&str>,
|
|
14
|
+
_auth_mode: AuthMode,
|
|
15
|
+
mcp_config: Option<&McpConfig>,
|
|
16
|
+
system_prompt: Option<&str>,
|
|
17
|
+
model: Option<&str>,
|
|
18
|
+
tools: &[&str],
|
|
19
|
+
overrides: Option<&ProviderCommandOverrides>,
|
|
20
|
+
) -> Vec<String> {
|
|
21
|
+
let mut argv = vec!["codex".to_string()];
|
|
22
|
+
if let Some(subcommand) = subcommand {
|
|
23
|
+
argv.push(subcommand.to_string());
|
|
24
|
+
}
|
|
25
|
+
argv.extend([
|
|
26
|
+
"--no-alt-screen".to_string(),
|
|
27
|
+
"--disable".to_string(),
|
|
28
|
+
"shell_snapshot".to_string(),
|
|
29
|
+
"--disable".to_string(),
|
|
30
|
+
"apps".to_string(),
|
|
31
|
+
]);
|
|
32
|
+
if let Some(profile) = overrides.and_then(|o| o.codex_profile.as_deref()) {
|
|
33
|
+
argv.push("--profile".to_string());
|
|
34
|
+
argv.push(profile.to_string());
|
|
35
|
+
}
|
|
36
|
+
if codex_dangerous_auto_approve(tools) {
|
|
37
|
+
argv.push("--dangerously-bypass-approvals-and-sandbox".to_string());
|
|
38
|
+
} else {
|
|
39
|
+
argv.push("--sandbox".to_string());
|
|
40
|
+
argv.push(codex_sandbox_mode(tools).to_string());
|
|
41
|
+
argv.push("--ask-for-approval".to_string());
|
|
42
|
+
argv.push("on-request".to_string());
|
|
43
|
+
}
|
|
44
|
+
if let Some(model) = model {
|
|
45
|
+
argv.push("--model".to_string());
|
|
46
|
+
argv.push(model.to_string());
|
|
47
|
+
}
|
|
48
|
+
if let Some(overrides) = overrides {
|
|
49
|
+
for config in &overrides.codex_config {
|
|
50
|
+
argv.push("-c".to_string());
|
|
51
|
+
argv.push(config.clone());
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if let Some(prompt) = system_prompt {
|
|
55
|
+
// codex.py:120 — escape order matters: backslash first, then quote, then newline.
|
|
56
|
+
let escaped = prompt
|
|
57
|
+
.replace('\\', "\\\\")
|
|
58
|
+
.replace('"', "\\\"")
|
|
59
|
+
.replace('\n', "\\n");
|
|
60
|
+
argv.push("-c".to_string());
|
|
61
|
+
argv.push(format!("developer_instructions=\"{escaped}\""));
|
|
62
|
+
}
|
|
63
|
+
if let Some(config) = mcp_config {
|
|
64
|
+
append_codex_mcp_overrides(&mut argv, &config.raw);
|
|
65
|
+
}
|
|
66
|
+
argv
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/// Render an `McpConfig::raw` ({ name: { type, command, args, env: {...} } }) into Codex
|
|
70
|
+
/// `-c mcp_servers.<name>.<field>=...` overrides. JSON values are stringified with serde
|
|
71
|
+
/// so arrays/objects survive (Codex parses the right-hand side as JSON; this is what the
|
|
72
|
+
/// Python golden + the live attached Codex panes do).
|
|
73
|
+
pub(crate) fn append_codex_mcp_overrides(argv: &mut Vec<String>, raw: &serde_json::Value) {
|
|
74
|
+
let Some(servers) = raw.as_object() else {
|
|
75
|
+
return;
|
|
76
|
+
};
|
|
77
|
+
for (name, server) in servers {
|
|
78
|
+
let Some(obj) = server.as_object() else {
|
|
79
|
+
continue;
|
|
80
|
+
};
|
|
81
|
+
for (key, value) in obj {
|
|
82
|
+
if key == "env" {
|
|
83
|
+
if let Some(env) = value.as_object() {
|
|
84
|
+
for (env_key, env_value) in env {
|
|
85
|
+
argv.push("-c".to_string());
|
|
86
|
+
argv.push(format!(
|
|
87
|
+
"mcp_servers.{name}.env.{env_key}={}",
|
|
88
|
+
json_inline(env_value)
|
|
89
|
+
));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
argv.push("-c".to_string());
|
|
95
|
+
argv.push(format!("mcp_servers.{name}.{key}={}", json_inline(value)));
|
|
96
|
+
}
|
|
97
|
+
// Every MCP server gets a 600s tool timeout so long-running
|
|
98
|
+
// team_orchestrator calls (report_result etc.) survive the codex default.
|
|
99
|
+
argv.push("-c".to_string());
|
|
100
|
+
argv.push(format!("mcp_servers.{name}.tool_timeout_sec=600.0"));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
pub(crate) fn codex_dangerous_auto_approve(tools: &[&str]) -> bool {
|
|
105
|
+
tools.contains(&"dangerous_auto_approve")
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
pub(crate) fn codex_sandbox_mode(tools: &[&str]) -> &'static str {
|
|
109
|
+
if tools
|
|
110
|
+
.iter()
|
|
111
|
+
.any(|tool| matches!(*tool, "fs_write" | "execute_bash"))
|
|
112
|
+
{
|
|
113
|
+
"workspace-write"
|
|
114
|
+
} else {
|
|
115
|
+
"read-only"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
//! Copilot provider-local command builders + permission helpers.
|
|
2
|
+
//!
|
|
3
|
+
//! Extracted from `provider/adapter.rs` (0.4.x decoupling step 2). Pure
|
|
4
|
+
//! extraction — byte-identical to the original inline forms. Scope kept
|
|
5
|
+
//! small: base command + resume + permission flags + MCP type→transport
|
|
6
|
+
//! translation. Auth hint (`copilot_auth_hint`) and session store scan
|
|
7
|
+
//! (`scan_copilot_session_store`, `copilot_candidate`) stay in
|
|
8
|
+
//! `adapter.rs` because they depend on `command_on_path` /
|
|
9
|
+
//! `CaptureSessionContext` / sqlite session-store helpers. Step 3 of the
|
|
10
|
+
//! decoupling plan can move those into provider session store hooks.
|
|
11
|
+
|
|
12
|
+
use crate::model::enums::AuthMode;
|
|
13
|
+
use crate::provider::McpConfig;
|
|
14
|
+
|
|
15
|
+
pub(crate) fn copilot_base_command(
|
|
16
|
+
auth_mode: AuthMode,
|
|
17
|
+
mcp_config: Option<&McpConfig>,
|
|
18
|
+
system_prompt: Option<&str>,
|
|
19
|
+
model: Option<&str>,
|
|
20
|
+
tools: &[&str],
|
|
21
|
+
) -> Vec<String> {
|
|
22
|
+
let _ = (auth_mode, system_prompt);
|
|
23
|
+
let mut argv = vec![
|
|
24
|
+
"copilot".to_string(),
|
|
25
|
+
// Noise control trio + disable remote control (防 GitHub web 远控 worker)
|
|
26
|
+
"--no-color".to_string(),
|
|
27
|
+
"--no-auto-update".to_string(),
|
|
28
|
+
"--no-remote".to_string(),
|
|
29
|
+
// P0: disable built-in github-mcp-server. Residual risk covered by
|
|
30
|
+
// spawn-time `copilot mcp list` scan + per-name --disable-mcp-server.
|
|
31
|
+
"--disable-builtin-mcps".to_string(),
|
|
32
|
+
];
|
|
33
|
+
if copilot_dangerous_auto_approve(tools) {
|
|
34
|
+
argv.push("--allow-all".to_string());
|
|
35
|
+
} else {
|
|
36
|
+
for flag in copilot_permission_flags(tools) {
|
|
37
|
+
argv.push(flag);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// mcp_team ∈ canonical → approval-free (whole-server pattern).
|
|
41
|
+
argv.push("--allow-tool".to_string());
|
|
42
|
+
argv.push("team_orchestrator".to_string());
|
|
43
|
+
if let Some(model) = model {
|
|
44
|
+
argv.push("--model".to_string());
|
|
45
|
+
argv.push(model.to_string());
|
|
46
|
+
}
|
|
47
|
+
if let Some(config) = mcp_config {
|
|
48
|
+
// Copilot mcp config schema field is `transport` (stdio|http|sse),
|
|
49
|
+
// not the canonical `type`. McpConfig.raw is canonical; only copilot
|
|
50
|
+
// translates type→transport for --additional-mcp-config.
|
|
51
|
+
argv.push("--additional-mcp-config".to_string());
|
|
52
|
+
argv.push(copilot_translate_mcp_config(&config.raw).to_string());
|
|
53
|
+
}
|
|
54
|
+
argv
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/// Translate `McpConfig.raw` canonical schema (`type`) into the copilot
|
|
58
|
+
/// `mcp add`/`--additional-mcp-config` expected `transport` field
|
|
59
|
+
/// (stdio|http|sse). Only the copilot adapter walks this translation —
|
|
60
|
+
/// claude/codex paths leave canonical schema untouched.
|
|
61
|
+
pub(crate) fn copilot_translate_mcp_config(raw: &serde_json::Value) -> serde_json::Value {
|
|
62
|
+
let Some(servers) = raw.as_object() else {
|
|
63
|
+
return raw.clone();
|
|
64
|
+
};
|
|
65
|
+
let mut translated = serde_json::Map::new();
|
|
66
|
+
for (name, server) in servers {
|
|
67
|
+
let Some(obj) = server.as_object() else {
|
|
68
|
+
translated.insert(name.clone(), server.clone());
|
|
69
|
+
continue;
|
|
70
|
+
};
|
|
71
|
+
let mut out = serde_json::Map::new();
|
|
72
|
+
for (key, value) in obj {
|
|
73
|
+
if key == "type" {
|
|
74
|
+
out.insert("transport".to_string(), value.clone());
|
|
75
|
+
} else {
|
|
76
|
+
out.insert(key.clone(), value.clone());
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
translated.insert(name.clone(), serde_json::Value::Object(out));
|
|
80
|
+
}
|
|
81
|
+
serde_json::Value::Object(translated)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/// Resume path = base + `--resume <sid>` (drop --session-id); kept separate
|
|
85
|
+
/// to avoid the plan accidentally emitting --session-id and --resume in the
|
|
86
|
+
/// same frame.
|
|
87
|
+
pub(crate) fn copilot_base_command_resume(
|
|
88
|
+
auth_mode: AuthMode,
|
|
89
|
+
mcp_config: Option<&McpConfig>,
|
|
90
|
+
system_prompt: Option<&str>,
|
|
91
|
+
model: Option<&str>,
|
|
92
|
+
tools: &[&str],
|
|
93
|
+
) -> Vec<String> {
|
|
94
|
+
copilot_base_command(auth_mode, mcp_config, system_prompt, model, tools)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
pub(crate) fn copilot_dangerous_auto_approve(tools: &[&str]) -> bool {
|
|
98
|
+
tools.contains(&"dangerous_auto_approve")
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/// Granular deny mapping (canonical tool → copilot flag, all via
|
|
102
|
+
/// `--deny-tool <kind>`; help-permissions Tool Permissions has four kinds:
|
|
103
|
+
/// shell/write/mcp/url):
|
|
104
|
+
/// execute_bash ∉ allowed → `--deny-tool 'shell'`
|
|
105
|
+
/// fs_write ∉ allowed → `--deny-tool 'write'`
|
|
106
|
+
/// network ∉ allowed → `--deny-tool 'url'`
|
|
107
|
+
/// fs_read/fs_list have no copilot deny kind (honestly prompt_only).
|
|
108
|
+
pub(crate) fn copilot_permission_flags(tools: &[&str]) -> Vec<String> {
|
|
109
|
+
let mut flags = Vec::new();
|
|
110
|
+
if !tools.contains(&"execute_bash") {
|
|
111
|
+
flags.push("--deny-tool".to_string());
|
|
112
|
+
flags.push("shell".to_string());
|
|
113
|
+
}
|
|
114
|
+
if !tools.contains(&"fs_write") {
|
|
115
|
+
flags.push("--deny-tool".to_string());
|
|
116
|
+
flags.push("write".to_string());
|
|
117
|
+
}
|
|
118
|
+
if !tools.contains(&"network") {
|
|
119
|
+
// `--deny-tool 'url'` (omit domain → match all URLs).
|
|
120
|
+
flags.push("--deny-tool".to_string());
|
|
121
|
+
flags.push("url".to_string());
|
|
122
|
+
}
|
|
123
|
+
flags
|
|
124
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//! Fake provider — scripted worker built into the team-agent CLI itself.
|
|
2
|
+
//! Extracted from `provider/adapter.rs` (0.4.x decoupling step 2).
|
|
3
|
+
|
|
4
|
+
pub(crate) fn fake_worker_command() -> Vec<String> {
|
|
5
|
+
let exe = std::env::current_exe()
|
|
6
|
+
.ok()
|
|
7
|
+
.and_then(|p| p.into_os_string().into_string().ok())
|
|
8
|
+
.unwrap_or_else(|| "team-agent".to_string());
|
|
9
|
+
vec![
|
|
10
|
+
exe,
|
|
11
|
+
"fake-worker".to_string(),
|
|
12
|
+
"--workspace".to_string(),
|
|
13
|
+
"{workspace}".to_string(),
|
|
14
|
+
"--agent-id".to_string(),
|
|
15
|
+
"{agent_id}".to_string(),
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//! Provider-local adapter implementations. Split from the monolithic
|
|
2
|
+
//! `provider/adapter.rs` as 0.4.x decoupling step 2. Each file owns its
|
|
3
|
+
//! provider's command builders, permission/sandbox/auth helpers, and
|
|
4
|
+
//! anything else that varies by provider but doesn't need shared
|
|
5
|
+
//! capture/scan utilities. The `ProviderAdapter` trait and the
|
|
6
|
+
//! `BasicProviderAdapter` registry stay in `adapter.rs`; the trait impl
|
|
7
|
+
//! dispatches into these helpers exactly as the inline forms did.
|
|
8
|
+
//!
|
|
9
|
+
//! Per-file scope:
|
|
10
|
+
//! * `claude` — Claude/ClaudeCode argv, dangerous-skip flag, disallowed
|
|
11
|
+
//! tools mapping, auth hint, model passthrough.
|
|
12
|
+
//! * `codex` — Codex argv, profile/sandbox flags, MCP `-c` injection
|
|
13
|
+
//! with 600s tool_timeout, developer-instructions escaping.
|
|
14
|
+
//! * `copilot` — Copilot argv (no-color/no-remote/disable-builtin-mcps),
|
|
15
|
+
//! allow/deny flag matrix, MCP `type→transport` translation, resume
|
|
16
|
+
//! base, weak auth hint.
|
|
17
|
+
//! * `fake` — Built-in scripted worker exec path.
|
|
18
|
+
//!
|
|
19
|
+
//! Behavior is byte-identical to pre-split. Future steps may move
|
|
20
|
+
//! `pre_spawn_adjust_plan`, `profile_env`, `session_backing_probe`, and
|
|
21
|
+
//! `session_candidates` into provider-owned hooks following the same
|
|
22
|
+
//! per-file layout.
|
|
23
|
+
|
|
24
|
+
pub(crate) mod claude;
|
|
25
|
+
pub(crate) mod codex;
|
|
26
|
+
pub(crate) mod copilot;
|
|
27
|
+
pub(crate) mod fake;
|
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
pub use crate::model::enums::{AuthMode, Provider};
|
|
33
33
|
|
|
34
34
|
pub mod adapter;
|
|
35
|
+
/// 0.4.x decoupling step 2: per-provider command builders + permission/auth
|
|
36
|
+
/// helpers split out of `adapter.rs`. Pure extraction — behavior unchanged.
|
|
37
|
+
pub(crate) mod adapters;
|
|
35
38
|
pub mod approvals;
|
|
36
39
|
pub mod classify;
|
|
37
40
|
pub mod command;
|
|
@@ -40,6 +43,9 @@ pub mod session;
|
|
|
40
43
|
pub mod session_scan;
|
|
41
44
|
pub mod startup_prompt;
|
|
42
45
|
pub mod types;
|
|
46
|
+
/// 0.4.x: provider wire-format helpers — single source of truth for
|
|
47
|
+
/// `Provider` ↔ string conversions (replaces 7 hand-rolled match copies).
|
|
48
|
+
pub(crate) mod wire;
|
|
43
49
|
// helpers 全部原为模块私有(JSONL 解析 / 正则编译),非根可见 → 私有 mod,不参与 re-export。
|
|
44
50
|
mod helpers;
|
|
45
51
|
|