phone-a-friend-mcp-server 0.1.2__tar.gz → 0.3.0rc1__tar.gz
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.
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/PKG-INFO +79 -109
- phone_a_friend_mcp_server-0.3.0rc1/README.md +150 -0
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/pyproject.toml +2 -1
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/src/phone_a_friend_mcp_server/config.py +1 -0
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/src/phone_a_friend_mcp_server/tools/fax_tool.py +24 -36
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/src/phone_a_friend_mcp_server/tools/phone_tool.py +24 -29
- phone_a_friend_mcp_server-0.3.0rc1/src/phone_a_friend_mcp_server/utils/__init__.py +1 -0
- phone_a_friend_mcp_server-0.3.0rc1/src/phone_a_friend_mcp_server/utils/context_builder.py +114 -0
- phone_a_friend_mcp_server-0.3.0rc1/tests/test_context_builder.py +167 -0
- phone_a_friend_mcp_server-0.3.0rc1/tests/test_tools.py +169 -0
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/uv.lock +12 -1
- phone_a_friend_mcp_server-0.1.2/README.md +0 -181
- phone_a_friend_mcp_server-0.1.2/tests/test_tools.py +0 -184
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/.gitignore +0 -0
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/.pre-commit-config.yaml +0 -0
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/Dockerfile +0 -0
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/LICENSE +0 -0
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/src/phone_a_friend_mcp_server/__init__.py +0 -0
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/src/phone_a_friend_mcp_server/__main__.py +0 -0
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/src/phone_a_friend_mcp_server/client/__init__.py +0 -0
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/src/phone_a_friend_mcp_server/server.py +0 -0
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/src/phone_a_friend_mcp_server/tools/__init__.py +0 -0
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/src/phone_a_friend_mcp_server/tools/base_tools.py +0 -0
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/src/phone_a_friend_mcp_server/tools/tool_manager.py +0 -0
- {phone_a_friend_mcp_server-0.1.2 → phone_a_friend_mcp_server-0.3.0rc1}/tests/__init__.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: phone-a-friend-mcp-server
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.3.0rc1
|
4
4
|
Summary: MCP Server for Phone-a-Friend assistance
|
5
5
|
Project-URL: GitHub, https://github.com/abhishekbhakat/phone-a-friend-mcp-server
|
6
6
|
Project-URL: Issues, https://github.com/abhishekbhakat/phone-a-friend-mcp-server/issues
|
@@ -17,6 +17,7 @@ Requires-Dist: aiofiles>=24.1.0
|
|
17
17
|
Requires-Dist: aiohttp>=3.12.7
|
18
18
|
Requires-Dist: click>=8.2.1
|
19
19
|
Requires-Dist: mcp>=1.9.2
|
20
|
+
Requires-Dist: pathspec>=0.12.1
|
20
21
|
Requires-Dist: pydantic-ai-slim[anthropic,google,openai]>=0.2.14
|
21
22
|
Requires-Dist: pydantic>=2.11.5
|
22
23
|
Requires-Dist: pyyaml>=6.0.0
|
@@ -46,7 +47,7 @@ This enables AI systems to leverage other AI models as "consultants" for complex
|
|
46
47
|
## Architecture 🏗️
|
47
48
|
|
48
49
|
```
|
49
|
-
Primary AI → Phone-a-Friend MCP → OpenRouter → External AI (
|
50
|
+
Primary AI → Phone-a-Friend MCP → OpenRouter → External AI (O3, Claude, etc.) → Processed Response → Primary AI
|
50
51
|
```
|
51
52
|
|
52
53
|
**Sequential Workflow:**
|
@@ -63,87 +64,105 @@ Primary AI → Phone-a-Friend MCP → OpenRouter → External AI (GPT-4, Claude,
|
|
63
64
|
- Critical decision-making with high stakes
|
64
65
|
- Problems requiring multiple perspectives
|
65
66
|
|
66
|
-
##
|
67
|
+
## Quick Start ⚡
|
67
68
|
|
68
|
-
|
69
|
-
|
70
|
-
git clone https://github.com/abhishekbhakat/phone-a-friend-mcp-server.git
|
71
|
-
cd phone-a-friend-mcp-server
|
72
|
-
```
|
69
|
+
Configure your MCP client (e.g., Claude Desktop) using the JSON block below—no cloning or manual installation required.
|
70
|
+
The `uv` runner will automatically download and execute the server package if it isn't present.
|
73
71
|
|
74
|
-
|
75
|
-
|
76
|
-
|
72
|
+
Add the following JSON configuration to your MCP client and replace `<YOUR_API_KEY>` with your key:
|
73
|
+
|
74
|
+
```json
|
75
|
+
{
|
76
|
+
"mcpServers": {
|
77
|
+
"phone-a-friend": {
|
78
|
+
"command": "uvx",
|
79
|
+
"args": [
|
80
|
+
"phone-a-friend-mcp-server",
|
81
|
+
"--provider", "openai",
|
82
|
+
"--api-key", "<YOUR_API_KEY>"
|
83
|
+
]
|
84
|
+
}
|
85
|
+
}
|
86
|
+
}
|
77
87
|
```
|
88
|
+
> That's it! You can now use the `phone_a_friend` tool in any compatible client. For more options, see the Advanced Configuration section.
|
78
89
|
|
79
|
-
|
90
|
+
## Available Tools 🛠️
|
80
91
|
|
81
|
-
|
82
|
-
|
83
|
-
export OPENROUTER_API_KEY="your-openrouter-key"
|
84
|
-
# OR
|
85
|
-
export OPENAI_API_KEY="your-openai-key"
|
86
|
-
# OR
|
87
|
-
export ANTHROPIC_API_KEY="your-anthropic-key"
|
88
|
-
# OR
|
89
|
-
export GOOGLE_API_KEY="your-google-key"
|
90
|
-
```
|
92
|
+
### phone_a_friend
|
93
|
+
📞 Consult external AI for critical thinking and complex reasoning. Makes API calls to get responses.
|
91
94
|
|
92
|
-
|
93
|
-
|
94
|
-
phone-a-friend-mcp-server --api-key "your-api-key" --provider openai
|
95
|
-
```
|
95
|
+
### fax_a_friend
|
96
|
+
📠 Generate master prompt file for manual AI consultation. Creates file for copy-paste workflow.
|
96
97
|
|
97
|
-
|
98
|
+
**Parameters**
|
98
99
|
|
99
|
-
|
100
|
-
```bash
|
100
|
+
*phone_a_friend*
|
101
101
|
|
102
|
-
|
103
|
-
|
102
|
+
- `all_related_context` (required): General, non-code context such as constraints, tracebacks, or high-level requirements.
|
103
|
+
- `file_list` (required): Array of file paths or glob patterns. **Just pass the paths** – the server automatically reads those files (skips anything in `.gitignore` or non-text/binary) and builds the full code context for the external AI.
|
104
|
+
- `task` (required): A clear, specific description of what you want the external AI to do.
|
104
105
|
|
105
|
-
|
106
|
-
phone-a-friend-mcp-server --temperature 0.4
|
106
|
+
*fax_a_friend*
|
107
107
|
|
108
|
-
|
109
|
-
|
110
|
-
|
108
|
+
- `all_related_context` (required): Same as above.
|
109
|
+
- `file_list` (required): Same as above.
|
110
|
+
- `task` (required): Same as above.
|
111
|
+
- `output_directory` (required): Directory where the generated `fax_a_friend.md` master prompt file will be saved.
|
111
112
|
|
112
|
-
|
113
|
-
```bash
|
113
|
+
## Advanced Configuration 🔧
|
114
114
|
|
115
|
-
|
116
|
-
export PHONE_A_FRIEND_MODEL="your-preferred-model"
|
117
|
-
export PHONE_A_FRIEND_PROVIDER="your-preferred-provider"
|
118
|
-
export PHONE_A_FRIEND_BASE_URL="https://custom-api.example.com"
|
115
|
+
This section covers all configuration options, including environment variables, CLI flags, and model selection.
|
119
116
|
|
120
|
-
|
121
|
-
|
117
|
+
### Providers and API Keys
|
118
|
+
|
119
|
+
The server can be configured via CLI flags or environment variables.
|
120
|
+
|
121
|
+
| Provider | CLI Flag | Environment Variable |
|
122
|
+
| :--- | :--- | :--- |
|
123
|
+
| OpenAI | `--provider openai` | `OPENAI_API_KEY` |
|
124
|
+
| OpenRouter | `--provider openrouter` | `OPENROUTER_API_KEY` |
|
125
|
+
| Anthropic | `--provider anthropic` | `ANTHROPIC_API_KEY` |
|
126
|
+
| Google | `--provider google` | `GOOGLE_API_KEY` |
|
127
|
+
|
128
|
+
**CLI Example:**
|
129
|
+
```bash
|
130
|
+
phone-a-friend-mcp-server --provider openai --api-key "sk-..."
|
122
131
|
```
|
123
132
|
|
124
|
-
|
133
|
+
**Environment Variable Example:**
|
134
|
+
```bash
|
135
|
+
export OPENAI_API_KEY="sk-..."
|
136
|
+
phone-a-friend-mcp-server
|
137
|
+
```
|
125
138
|
|
126
|
-
|
127
|
-
- **OpenAI**: o3
|
128
|
-
- **Anthropic**: Claude 4 Opus
|
129
|
-
- **Google**: Gemini 2.5 Pro Preview 05-06 (automatically set temperature to 0.0)
|
130
|
-
- **OpenRouter**: For other models like Deepseek or Qwen
|
139
|
+
### Model Selection
|
131
140
|
|
132
|
-
You can override the
|
141
|
+
You can override the default model for each provider.
|
133
142
|
|
134
|
-
|
143
|
+
| Provider | Default Model |
|
144
|
+
| :--- | :--- |
|
145
|
+
| **OpenAI** | `o3` |
|
146
|
+
| **Anthropic** | `Claude 4 Opus` |
|
147
|
+
| **Google** | `Gemini 2.5 Pro Preview 05-06` |
|
148
|
+
| **OpenRouter**| `anthropic/claude-4-opus` |
|
135
149
|
|
136
|
-
|
137
|
-
|
150
|
+
**Override with CLI:**
|
151
|
+
```bash
|
152
|
+
phone-a-friend-mcp-server --model "o3"
|
153
|
+
```
|
138
154
|
|
139
|
-
|
140
|
-
|
155
|
+
**Override with Environment Variable:**
|
156
|
+
```bash
|
157
|
+
export PHONE_A_FRIEND_MODEL="o3"
|
158
|
+
```
|
141
159
|
|
142
|
-
|
143
|
-
- `all_related_context` (required): All context related to the problem
|
144
|
-
- `any_additional_context` (optional): Additional helpful context
|
145
|
-
- `task` (required): Specific task or question for the AI
|
160
|
+
### Additional Options
|
146
161
|
|
162
|
+
| Feature | CLI Flag | Environment Variable | Default |
|
163
|
+
| :--- | :--- | :--- | :--- |
|
164
|
+
| **Temperature** | `--temperature 0.5` | `PHONE_A_FRIEND_TEMPERATURE` | `0.4` |
|
165
|
+
| **Base URL** | `--base-url ...` | `PHONE_A_FRIEND_BASE_URL` | Provider default |
|
147
166
|
|
148
167
|
## Use Cases 🎯
|
149
168
|
|
@@ -151,55 +170,6 @@ You can override the auto-selection by setting `PHONE_A_FRIEND_MODEL` environmen
|
|
151
170
|
2. For complex algorithms, data structures, or mathematical computations
|
152
171
|
3. Frontend Development with React, Vue, CSS, or modern frontend frameworks
|
153
172
|
|
154
|
-
## Claude Desktop Configuration 🖥️
|
155
|
-
|
156
|
-
To use Phone-a-Friend MCP server with Claude Desktop, add this configuration to your `claude_desktop_config.json` file:
|
157
|
-
|
158
|
-
### Configuration File Location
|
159
|
-
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
160
|
-
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
161
|
-
|
162
|
-
### Configuration
|
163
|
-
|
164
|
-
**Option 1: Using uv (Recommended)**
|
165
|
-
```json
|
166
|
-
{
|
167
|
-
"mcpServers": {
|
168
|
-
"phone-a-friend": {
|
169
|
-
"command": "uvx",
|
170
|
-
"args": [
|
171
|
-
"--refresh",
|
172
|
-
"phone-a-friend-mcp-server",
|
173
|
-
],
|
174
|
-
"env": {
|
175
|
-
"OPENROUTER_API_KEY": "your-openrouter-api-key",
|
176
|
-
"PHONE_A_FRIEND_MODEL": "anthropic/claude-4-opus",
|
177
|
-
"PHONE_A_FRIEND_TEMPERATURE": "0.4"
|
178
|
-
}
|
179
|
-
}
|
180
|
-
}
|
181
|
-
}
|
182
|
-
```
|
183
|
-
|
184
|
-
### Environment Variables in Configuration
|
185
|
-
|
186
|
-
You can configure different AI providers directly in the Claude Desktop config:
|
187
|
-
|
188
|
-
```json
|
189
|
-
{
|
190
|
-
"mcpServers": {
|
191
|
-
"phone-a-friend": {
|
192
|
-
"command": "phone-a-friend-mcp-server",
|
193
|
-
"env": {
|
194
|
-
"OPENROUTER_API_KEY": "your-openrouter-api-key",
|
195
|
-
"PHONE_A_FRIEND_MODEL": "anthropic/claude-4-opus",
|
196
|
-
"PHONE_A_FRIEND_TEMPERATURE": "0.4"
|
197
|
-
}
|
198
|
-
}
|
199
|
-
}
|
200
|
-
}
|
201
|
-
```
|
202
|
-
|
203
173
|
## License 📄
|
204
174
|
|
205
175
|
MIT License - see LICENSE file for details.
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# Phone-a-Friend MCP Server 🧠📞
|
2
|
+
|
3
|
+
An AI-to-AI consultation system that enables one AI to "phone a friend" (another AI) for critical thinking, long context reasoning, and complex problem solving via OpenRouter.
|
4
|
+
|
5
|
+
## The Problem 🤔
|
6
|
+
|
7
|
+
Sometimes an AI encounters complex problems that require:
|
8
|
+
- **Deep critical thinking** beyond immediate capabilities
|
9
|
+
- **Long context reasoning** with extensive information
|
10
|
+
- **Multi-step analysis** that benefits from external perspective
|
11
|
+
- **Specialized expertise** from different AI models
|
12
|
+
|
13
|
+
## The Solution �
|
14
|
+
|
15
|
+
Phone-a-Friend MCP Server creates a **two-step consultation process**:
|
16
|
+
|
17
|
+
1. **Context + Reasoning**: Package all relevant context and send to external AI for deep analysis
|
18
|
+
2. **Extract Actionable Insights**: Process the reasoning response into usable format for the primary AI
|
19
|
+
|
20
|
+
This enables AI systems to leverage other AI models as "consultants" for complex reasoning tasks.
|
21
|
+
|
22
|
+
## Architecture 🏗️
|
23
|
+
|
24
|
+
```
|
25
|
+
Primary AI → Phone-a-Friend MCP → OpenRouter → External AI (O3, Claude, etc.) → Processed Response → Primary AI
|
26
|
+
```
|
27
|
+
|
28
|
+
**Sequential Workflow:**
|
29
|
+
1. `analyze_context` - Gather and structure all relevant context
|
30
|
+
2. `get_critical_thinking` - Send context to external AI via OpenRouter for reasoning
|
31
|
+
3. `extract_actionable_insights` - Process response into actionable format
|
32
|
+
|
33
|
+
## When to Use 🎯
|
34
|
+
|
35
|
+
**Ideal for:**
|
36
|
+
- Complex multi-step problems requiring deep analysis
|
37
|
+
- Situations needing long context reasoning (>100k tokens)
|
38
|
+
- Cross-domain expertise consultation
|
39
|
+
- Critical decision-making with high stakes
|
40
|
+
- Problems requiring multiple perspectives
|
41
|
+
|
42
|
+
## Quick Start ⚡
|
43
|
+
|
44
|
+
Configure your MCP client (e.g., Claude Desktop) using the JSON block below—no cloning or manual installation required.
|
45
|
+
The `uv` runner will automatically download and execute the server package if it isn't present.
|
46
|
+
|
47
|
+
Add the following JSON configuration to your MCP client and replace `<YOUR_API_KEY>` with your key:
|
48
|
+
|
49
|
+
```json
|
50
|
+
{
|
51
|
+
"mcpServers": {
|
52
|
+
"phone-a-friend": {
|
53
|
+
"command": "uvx",
|
54
|
+
"args": [
|
55
|
+
"phone-a-friend-mcp-server",
|
56
|
+
"--provider", "openai",
|
57
|
+
"--api-key", "<YOUR_API_KEY>"
|
58
|
+
]
|
59
|
+
}
|
60
|
+
}
|
61
|
+
}
|
62
|
+
```
|
63
|
+
> That's it! You can now use the `phone_a_friend` tool in any compatible client. For more options, see the Advanced Configuration section.
|
64
|
+
|
65
|
+
## Available Tools 🛠️
|
66
|
+
|
67
|
+
### phone_a_friend
|
68
|
+
📞 Consult external AI for critical thinking and complex reasoning. Makes API calls to get responses.
|
69
|
+
|
70
|
+
### fax_a_friend
|
71
|
+
📠 Generate master prompt file for manual AI consultation. Creates file for copy-paste workflow.
|
72
|
+
|
73
|
+
**Parameters**
|
74
|
+
|
75
|
+
*phone_a_friend*
|
76
|
+
|
77
|
+
- `all_related_context` (required): General, non-code context such as constraints, tracebacks, or high-level requirements.
|
78
|
+
- `file_list` (required): Array of file paths or glob patterns. **Just pass the paths** – the server automatically reads those files (skips anything in `.gitignore` or non-text/binary) and builds the full code context for the external AI.
|
79
|
+
- `task` (required): A clear, specific description of what you want the external AI to do.
|
80
|
+
|
81
|
+
*fax_a_friend*
|
82
|
+
|
83
|
+
- `all_related_context` (required): Same as above.
|
84
|
+
- `file_list` (required): Same as above.
|
85
|
+
- `task` (required): Same as above.
|
86
|
+
- `output_directory` (required): Directory where the generated `fax_a_friend.md` master prompt file will be saved.
|
87
|
+
|
88
|
+
## Advanced Configuration 🔧
|
89
|
+
|
90
|
+
This section covers all configuration options, including environment variables, CLI flags, and model selection.
|
91
|
+
|
92
|
+
### Providers and API Keys
|
93
|
+
|
94
|
+
The server can be configured via CLI flags or environment variables.
|
95
|
+
|
96
|
+
| Provider | CLI Flag | Environment Variable |
|
97
|
+
| :--- | :--- | :--- |
|
98
|
+
| OpenAI | `--provider openai` | `OPENAI_API_KEY` |
|
99
|
+
| OpenRouter | `--provider openrouter` | `OPENROUTER_API_KEY` |
|
100
|
+
| Anthropic | `--provider anthropic` | `ANTHROPIC_API_KEY` |
|
101
|
+
| Google | `--provider google` | `GOOGLE_API_KEY` |
|
102
|
+
|
103
|
+
**CLI Example:**
|
104
|
+
```bash
|
105
|
+
phone-a-friend-mcp-server --provider openai --api-key "sk-..."
|
106
|
+
```
|
107
|
+
|
108
|
+
**Environment Variable Example:**
|
109
|
+
```bash
|
110
|
+
export OPENAI_API_KEY="sk-..."
|
111
|
+
phone-a-friend-mcp-server
|
112
|
+
```
|
113
|
+
|
114
|
+
### Model Selection
|
115
|
+
|
116
|
+
You can override the default model for each provider.
|
117
|
+
|
118
|
+
| Provider | Default Model |
|
119
|
+
| :--- | :--- |
|
120
|
+
| **OpenAI** | `o3` |
|
121
|
+
| **Anthropic** | `Claude 4 Opus` |
|
122
|
+
| **Google** | `Gemini 2.5 Pro Preview 05-06` |
|
123
|
+
| **OpenRouter**| `anthropic/claude-4-opus` |
|
124
|
+
|
125
|
+
**Override with CLI:**
|
126
|
+
```bash
|
127
|
+
phone-a-friend-mcp-server --model "o3"
|
128
|
+
```
|
129
|
+
|
130
|
+
**Override with Environment Variable:**
|
131
|
+
```bash
|
132
|
+
export PHONE_A_FRIEND_MODEL="o3"
|
133
|
+
```
|
134
|
+
|
135
|
+
### Additional Options
|
136
|
+
|
137
|
+
| Feature | CLI Flag | Environment Variable | Default |
|
138
|
+
| :--- | :--- | :--- | :--- |
|
139
|
+
| **Temperature** | `--temperature 0.5` | `PHONE_A_FRIEND_TEMPERATURE` | `0.4` |
|
140
|
+
| **Base URL** | `--base-url ...` | `PHONE_A_FRIEND_BASE_URL` | Provider default |
|
141
|
+
|
142
|
+
## Use Cases 🎯
|
143
|
+
|
144
|
+
1. In-depth Reasoning for Vibe Coding
|
145
|
+
2. For complex algorithms, data structures, or mathematical computations
|
146
|
+
3. Frontend Development with React, Vue, CSS, or modern frontend frameworks
|
147
|
+
|
148
|
+
## License 📄
|
149
|
+
|
150
|
+
MIT License - see LICENSE file for details.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "phone-a-friend-mcp-server"
|
3
|
-
version = "0.
|
3
|
+
version = "0.3.0rc1"
|
4
4
|
description = "MCP Server for Phone-a-Friend assistance"
|
5
5
|
readme = "README.md"
|
6
6
|
requires-python = ">=3.11"
|
@@ -15,6 +15,7 @@ dependencies = [
|
|
15
15
|
"pydantic-ai-slim[openai,anthropic,google]>=0.2.14",
|
16
16
|
"click>=8.2.1",
|
17
17
|
"pyyaml>=6.0.0",
|
18
|
+
"pathspec>=0.12.1",
|
18
19
|
]
|
19
20
|
classifiers = [
|
20
21
|
"Development Status :: 3 - Alpha",
|
@@ -4,6 +4,7 @@ from typing import Any
|
|
4
4
|
import aiofiles
|
5
5
|
|
6
6
|
from phone_a_friend_mcp_server.tools.base_tools import BaseTool
|
7
|
+
from phone_a_friend_mcp_server.utils.context_builder import build_code_context
|
7
8
|
|
8
9
|
|
9
10
|
class FaxAFriendTool(BaseTool):
|
@@ -35,9 +36,10 @@ refactors, design, migrations.
|
|
35
36
|
|
36
37
|
This tool creates a file for manual AI consultation. After file creation,
|
37
38
|
wait for the user to return with the external AI's response.
|
39
|
+
Replies must be exhaustively detailed. Do **NOT** include files ignored by .gitignore (e.g., *.pyc).
|
38
40
|
|
39
41
|
Hard restrictions:
|
40
|
-
• Generated prompt includes *only* the
|
42
|
+
• Generated prompt includes *only* the context you provide.
|
41
43
|
• No memory, no internet, no tools.
|
42
44
|
• You must spell out every fact it should rely on.
|
43
45
|
|
@@ -83,22 +85,18 @@ replacing <file="…"> blocks as needed. Commentary goes outside those tags."""
|
|
83
85
|
"all_related_context": {
|
84
86
|
"type": "string",
|
85
87
|
"description": (
|
86
|
-
"
|
87
|
-
"
|
88
|
-
|
89
|
-
"- Known constraints (Python version, allowed deps, runtime limits, etc.).\n"
|
90
|
-
"- Any failing test output or traceback.\n"
|
91
|
-
"If it's not here, the friend AI can't use it."
|
88
|
+
"General context for the friend AI. Include known constraints "
|
89
|
+
"(Python version, allowed deps, etc.), failing test output, tracebacks, "
|
90
|
+
"or code snippets for reference. For complete files, use file_list instead."
|
92
91
|
),
|
93
92
|
},
|
94
|
-
"
|
95
|
-
"type": "
|
93
|
+
"file_list": {
|
94
|
+
"type": "array",
|
95
|
+
"items": {"type": "string"},
|
96
96
|
"description": (
|
97
|
-
"Optional
|
98
|
-
"
|
99
|
-
"
|
100
|
-
"- Similar past solutions or reference snippets.\n"
|
101
|
-
"Skip it if there's nothing useful."
|
97
|
+
"Optional but recommended. A list of file paths or glob patterns to be included in the code context. "
|
98
|
+
"The tool will automatically read these files, filter them against .gitignore, and build the context. "
|
99
|
+
"Better and faster than including complete files in all_related_context."
|
102
100
|
),
|
103
101
|
},
|
104
102
|
"task": {
|
@@ -127,24 +125,21 @@ replacing <file="…"> blocks as needed. Commentary goes outside those tags."""
|
|
127
125
|
|
128
126
|
async def run(self, **kwargs) -> dict[str, Any]:
|
129
127
|
all_related_context = kwargs.get("all_related_context", "")
|
130
|
-
|
128
|
+
file_list = kwargs.get("file_list", [])
|
131
129
|
task = kwargs.get("task", "")
|
132
130
|
output_directory = kwargs.get("output_directory", "")
|
133
131
|
|
134
|
-
|
135
|
-
master_prompt = self._create_master_prompt(all_related_context,
|
132
|
+
code_context = build_code_context(file_list)
|
133
|
+
master_prompt = self._create_master_prompt(all_related_context, code_context, task)
|
136
134
|
|
137
135
|
try:
|
138
|
-
# Validate and prepare output directory
|
139
136
|
output_dir = self._prepare_output_directory(output_directory)
|
140
137
|
|
141
|
-
# Create full file path
|
142
138
|
file_path = os.path.join(output_dir, "fax_a_friend.md")
|
143
139
|
|
144
140
|
async with aiofiles.open(file_path, "w", encoding="utf-8") as f:
|
145
141
|
await f.write(master_prompt)
|
146
142
|
|
147
|
-
# Get absolute path for user reference
|
148
143
|
abs_path = os.path.abspath(file_path)
|
149
144
|
|
150
145
|
return {
|
@@ -153,15 +148,15 @@ replacing <file="…"> blocks as needed. Commentary goes outside those tags."""
|
|
153
148
|
"file_name": "fax_a_friend.md",
|
154
149
|
"output_directory": output_dir,
|
155
150
|
"prompt_length": len(master_prompt),
|
156
|
-
"context_length": len(
|
151
|
+
"context_length": len(master_prompt),
|
157
152
|
"task": task,
|
158
153
|
"instructions": self._get_manual_workflow_instructions(abs_path),
|
159
154
|
}
|
160
155
|
|
161
156
|
except Exception as e:
|
162
|
-
return {"status": "failed", "error": str(e), "output_directory": output_directory, "context_length": len(
|
157
|
+
return {"status": "failed", "error": str(e), "output_directory": output_directory, "context_length": len(master_prompt), "task": task}
|
163
158
|
|
164
|
-
def _create_master_prompt(self, all_related_context: str,
|
159
|
+
def _create_master_prompt(self, all_related_context: str, code_context: str, task: str) -> str:
|
165
160
|
"""Create a comprehensive prompt identical to PhoneAFriendTool's version."""
|
166
161
|
|
167
162
|
prompt_parts = [
|
@@ -171,23 +166,19 @@ replacing <file="…"> blocks as needed. Commentary goes outside those tags."""
|
|
171
166
|
"=== TASK ===",
|
172
167
|
task,
|
173
168
|
"",
|
174
|
-
"===
|
169
|
+
"=== GENERAL CONTEXT ===",
|
175
170
|
all_related_context,
|
171
|
+
"",
|
172
|
+
"=== CODE CONTEXT ===",
|
173
|
+
code_context,
|
176
174
|
]
|
177
175
|
|
178
|
-
if any_additional_context.strip():
|
179
|
-
prompt_parts.extend(
|
180
|
-
[
|
181
|
-
"",
|
182
|
-
"=== ADDITIONAL CONTEXT ===",
|
183
|
-
any_additional_context,
|
184
|
-
]
|
185
|
-
)
|
186
|
-
|
187
176
|
prompt_parts.extend(
|
188
177
|
[
|
189
178
|
"",
|
190
179
|
"=== INSTRUCTIONS ===",
|
180
|
+
"- Provide exhaustive, step-by-step reasoning.",
|
181
|
+
"- Never include files matching .gitignore patterns.",
|
191
182
|
"- Analyze the code and requirements step-by-step.",
|
192
183
|
"- Show your reasoning and propose concrete changes.",
|
193
184
|
'- Provide updated code using the XML format (<file_tree> plus <file="…"> blocks).',
|
@@ -204,17 +195,14 @@ replacing <file="…"> blocks as needed. Commentary goes outside those tags."""
|
|
204
195
|
if not output_directory:
|
205
196
|
raise ValueError("output_directory parameter is required")
|
206
197
|
|
207
|
-
# Expand user path (~) and resolve relative paths
|
208
198
|
expanded_path = os.path.expanduser(output_directory)
|
209
199
|
resolved_path = os.path.abspath(expanded_path)
|
210
200
|
|
211
|
-
# Create directory if it doesn't exist
|
212
201
|
try:
|
213
202
|
os.makedirs(resolved_path, exist_ok=True)
|
214
203
|
except OSError as e:
|
215
204
|
raise ValueError(f"Cannot create directory '{resolved_path}': {e}")
|
216
205
|
|
217
|
-
# Check if directory is writable
|
218
206
|
if not os.access(resolved_path, os.W_OK):
|
219
207
|
raise ValueError(f"Directory '{resolved_path}' is not writable")
|
220
208
|
|