@bexelbie/phone-a-friend 0.1.0 → 0.2.0
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/README.md +56 -37
- package/dist/git.d.ts +1 -1
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +7 -3
- package/dist/git.js.map +1 -1
- package/dist/index.js +33 -13
- package/dist/index.js.map +1 -1
- package/dist/util.d.ts +5 -2
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +22 -5
- package/dist/util.js.map +1 -1
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ GitHub Copilot CLI does not provide a way to retrieve just the agent's final res
|
|
|
28
28
|
|
|
29
29
|
## Prerequisites
|
|
30
30
|
|
|
31
|
-
- **Node.js** >=
|
|
31
|
+
- **Node.js** >= 22.0.0
|
|
32
32
|
- **GitHub Copilot CLI** — installed, configured, and authenticated. See [About GitHub Copilot in the CLI](https://docs.github.com/en/copilot/github-copilot-in-the-cli/about-github-copilot-in-the-cli) for setup instructions.
|
|
33
33
|
- **Git** — for worktree management
|
|
34
34
|
- A **git repository** to work in (the tool operates on git repos)
|
|
@@ -39,54 +39,24 @@ Verify Copilot CLI is working:
|
|
|
39
39
|
copilot --help
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
##
|
|
42
|
+
## Setup
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
In VS Code, open the Command Palette and run `MCP: Add Server...`, select `npm Package`, and enter `@bexelbie/phone-a-friend`.
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
git clone https://github.com/YOUR_USERNAME/phone-a-friend.git
|
|
48
|
-
cd phone-a-friend
|
|
49
|
-
npm install
|
|
50
|
-
npm run build
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### As an npm package
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
npm install -g @bexelbie/phone-a-friend
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## Configuration
|
|
60
|
-
|
|
61
|
-
Add to your VS Code MCP configuration (`.vscode/mcp.json` in your workspace, or user-level via `MCP: Open User Configuration`):
|
|
62
|
-
|
|
63
|
-
```json
|
|
64
|
-
{
|
|
65
|
-
"servers": {
|
|
66
|
-
"phoneAFriend": {
|
|
67
|
-
"type": "stdio",
|
|
68
|
-
"command": "node",
|
|
69
|
-
"args": ["/absolute/path/to/phone-a-friend/dist/index.js"]
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
Or if installed globally via npm:
|
|
46
|
+
Or add it manually to `.vscode/mcp.json` (workspace) or via `MCP: Open User Configuration` (global):
|
|
76
47
|
|
|
77
48
|
```json
|
|
78
49
|
{
|
|
79
50
|
"servers": {
|
|
80
|
-
"
|
|
51
|
+
"phone-a-friend": {
|
|
81
52
|
"type": "stdio",
|
|
82
|
-
"command": "
|
|
53
|
+
"command": "npx",
|
|
54
|
+
"args": ["@bexelbie/phone-a-friend"]
|
|
83
55
|
}
|
|
84
56
|
}
|
|
85
57
|
}
|
|
86
58
|
```
|
|
87
59
|
|
|
88
|
-
See [Use MCP servers in VS Code](https://code.visualstudio.com/docs/copilot/customization/mcp-servers) for details on MCP server configuration.
|
|
89
|
-
|
|
90
60
|
## Usage
|
|
91
61
|
|
|
92
62
|
Once configured, the `phone_a_friend` tool is available in GitHub Copilot Chat. You tell the agent what you want, and the agent decides how to use the tool — constructing the prompt, choosing the model, including context, and applying the returned diff.
|
|
@@ -150,11 +120,13 @@ You can direct the model to pass any model name directly — GitHub Copilot CLI
|
|
|
150
120
|
| `prompt` | Yes | The task or question for the other model. Include relevant context. |
|
|
151
121
|
| `model` | Yes | Which AI model to use (see list above). |
|
|
152
122
|
| `working_directory` | Yes | Git repo directory to work in. Must be inside a git repository. Always pass this explicitly — the server's own working directory is not the user's workspace. |
|
|
123
|
+
| `mode` | No | `"default"` returns the response and a unified diff of file changes. `"query"` discards all file changes and returns only the response — use for reviews, analysis, or questions. Default: `"default"`. |
|
|
153
124
|
|
|
154
125
|
## Safety
|
|
155
126
|
|
|
156
127
|
- **Push protection**: The CLI is invoked with `--deny-tool 'shell(git push*)'` which blocks all push attempts at the tool level. The prompt also instructs the agent not to push.
|
|
157
128
|
- **Worktree isolation**: All work happens in a temporary git worktree. Your working tree is never modified directly.
|
|
129
|
+
- **Query mode**: When `mode` is `"query"`, all file changes in the worktree are discarded. The subagent is instructed that the repo is read-only. No git diff is returned.
|
|
158
130
|
- **Automatic cleanup**: Worktrees are removed after each invocation, even on errors.
|
|
159
131
|
- **No secrets exposure**: The subagent has the same access as `copilot` CLI running locally — no additional permissions are granted.
|
|
160
132
|
|
|
@@ -168,12 +140,59 @@ You can direct the model to pass any model name directly — GitHub Copilot CLI
|
|
|
168
140
|
## Development
|
|
169
141
|
|
|
170
142
|
```bash
|
|
143
|
+
git clone https://github.com/bexelbie/phone-a-friend.git
|
|
144
|
+
cd phone-a-friend
|
|
171
145
|
npm install
|
|
172
146
|
npm run build # Compile TypeScript
|
|
173
147
|
npm test # Run tests
|
|
174
148
|
npm run dev # Watch mode for development
|
|
175
149
|
```
|
|
176
150
|
|
|
151
|
+
### Testing a local build in VS Code
|
|
152
|
+
|
|
153
|
+
If you have phone-a-friend installed globally (via `npx @bexelbie/phone-a-friend`), you need to point VS Code at your local build instead. Update your MCP configuration (`.vscode/mcp.json` or user-level `mcp.json`) to use `node` with the local dist path:
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"servers": {
|
|
158
|
+
"phone-a-friend": {
|
|
159
|
+
"type": "stdio",
|
|
160
|
+
"command": "node",
|
|
161
|
+
"args": [
|
|
162
|
+
"/absolute/path/to/phone-a-friend/dist/index.js"
|
|
163
|
+
],
|
|
164
|
+
"env": {}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Replace `/absolute/path/to/phone-a-friend` with the actual path to your clone.
|
|
171
|
+
|
|
172
|
+
After changing the config:
|
|
173
|
+
|
|
174
|
+
1. Build your changes: `npm run build`
|
|
175
|
+
2. In VS Code, open the Command Palette and run `MCP: List Servers`
|
|
176
|
+
3. Select `phone-a-friend` and choose `Restart Server` to pick up the new code
|
|
177
|
+
4. Test in Copilot Chat — the tool will now use your local build
|
|
178
|
+
|
|
179
|
+
When you're done testing, revert the MCP config back to `npx`:
|
|
180
|
+
|
|
181
|
+
```json
|
|
182
|
+
{
|
|
183
|
+
"servers": {
|
|
184
|
+
"phone-a-friend": {
|
|
185
|
+
"type": "stdio",
|
|
186
|
+
"command": "npx",
|
|
187
|
+
"args": [
|
|
188
|
+
"@bexelbie/phone-a-friend"
|
|
189
|
+
],
|
|
190
|
+
"env": {}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
177
196
|
## License
|
|
178
197
|
|
|
179
198
|
MIT
|
package/dist/git.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export declare function getHeadSha(dir: string): Promise<string>;
|
|
|
33
33
|
* against the given base SHA (the original commit before the agent ran).
|
|
34
34
|
* This ensures committed changes are also captured.
|
|
35
35
|
*/
|
|
36
|
-
export declare function captureChanges(worktreePath: string, baseSha: string): Promise<string>;
|
|
36
|
+
export declare function captureChanges(worktreePath: string, baseSha: string): Promise<string | null>;
|
|
37
37
|
/**
|
|
38
38
|
* Reads and removes the message-in-a-bottle response file.
|
|
39
39
|
*/
|
package/dist/git.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO7D;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO7D;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO7D;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO7D;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA4C/C;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO7D;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAsBxB;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CASxB"}
|
package/dist/git.js
CHANGED
|
@@ -102,7 +102,10 @@ export async function runCopilotCli(worktreePath, prompt, model) {
|
|
|
102
102
|
resolvePromise({ exitCode: code ?? 1, stderr });
|
|
103
103
|
});
|
|
104
104
|
child.on("error", (err) => {
|
|
105
|
-
|
|
105
|
+
const message = err.code === "ENOENT"
|
|
106
|
+
? "Copilot CLI not found. Install it (https://docs.github.com/en/copilot/github-copilot-in-the-cli) and ensure 'copilot' is on your PATH."
|
|
107
|
+
: err.message;
|
|
108
|
+
resolvePromise({ exitCode: 1, stderr: message });
|
|
106
109
|
});
|
|
107
110
|
});
|
|
108
111
|
}
|
|
@@ -131,8 +134,9 @@ export async function captureChanges(worktreePath, baseSha) {
|
|
|
131
134
|
const { stdout } = await execFileAsync("git", ["diff", "--staged", baseSha], { cwd: worktreePath, maxBuffer: 10 * 1024 * 1024 });
|
|
132
135
|
return stdout;
|
|
133
136
|
}
|
|
134
|
-
catch {
|
|
135
|
-
|
|
137
|
+
catch (err) {
|
|
138
|
+
console.error(`[phone-a-friend] diff capture failed in ${worktreePath}:`, err instanceof Error ? err.message : err);
|
|
139
|
+
return null;
|
|
136
140
|
}
|
|
137
141
|
}
|
|
138
142
|
/**
|
package/dist/git.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -2,15 +2,18 @@
|
|
|
2
2
|
// ABOUTME: MCP server that invokes Copilot CLI with a different model.
|
|
3
3
|
// ABOUTME: Enables cross-model subagent calls from VS Code Copilot Chat.
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
|
+
import { createRequire } from "node:module";
|
|
5
6
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
7
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
8
|
import { z } from "zod";
|
|
8
|
-
import { RESPONSE_FILENAME, AVAILABLE_MODELS, wrapPrompt, generateWorktreePath, promptSizeWarning, } from "./util.js";
|
|
9
|
+
import { RESPONSE_FILENAME, AVAILABLE_MODELS, TOOL_MODES, wrapPrompt, generateWorktreePath, promptSizeWarning, } from "./util.js";
|
|
9
10
|
import { isGitRepo, getGitRoot, createWorktree, removeWorktree, runCopilotCli, getHeadSha, captureChanges, readAndRemoveResponse, } from "./git.js";
|
|
11
|
+
const require = createRequire(import.meta.url);
|
|
12
|
+
const { version } = require("../package.json");
|
|
10
13
|
// --- MCP Server Setup ---
|
|
11
14
|
const server = new McpServer({
|
|
12
15
|
name: "phone-a-friend",
|
|
13
|
-
version
|
|
16
|
+
version,
|
|
14
17
|
});
|
|
15
18
|
server.registerTool("phone_a_friend", {
|
|
16
19
|
title: "Phone a Friend",
|
|
@@ -24,6 +27,7 @@ server.registerTool("phone_a_friend", {
|
|
|
24
27
|
"- The user wants a specific model for a subtask (e.g., a faster model for simple work, or a different vendor)\n" +
|
|
25
28
|
"- The user mentions \"phone a friend\", \"subagent\", or \"different model\"\n" +
|
|
26
29
|
"- The user wants to delegate a focused coding task to another model and get the changes back as a diff\n" +
|
|
30
|
+
"- Use mode \"query\" when you only want the agent's analysis — reviews, explanations, architectural assessments — not file changes\n" +
|
|
27
31
|
"\n\nWhen NOT to use this tool:\n" +
|
|
28
32
|
"- The current model can handle the task directly — don't add round-trip overhead for no benefit\n" +
|
|
29
33
|
"- The task requires seeing uncommitted changes and the user hasn't provided the file contents\n" +
|
|
@@ -49,9 +53,17 @@ server.registerTool("phone_a_friend", {
|
|
|
49
53
|
"repository. Always pass this explicitly using the workspace " +
|
|
50
54
|
"path from your conversation context — the server's own working " +
|
|
51
55
|
"directory is not the user's workspace."),
|
|
56
|
+
mode: z
|
|
57
|
+
.enum(TOOL_MODES)
|
|
58
|
+
.optional()
|
|
59
|
+
.default("default")
|
|
60
|
+
.describe('"default" returns the agent response and a unified diff of file changes. ' +
|
|
61
|
+
'"query" discards all file changes and returns only the agent response — ' +
|
|
62
|
+
"use for reviews, analysis, or questions where you don't need code changes."),
|
|
52
63
|
}),
|
|
53
|
-
}, async ({ prompt, model, working_directory }) => {
|
|
64
|
+
}, async ({ prompt, model, working_directory, mode }) => {
|
|
54
65
|
const workDir = resolve(working_directory);
|
|
66
|
+
const toolMode = mode ?? "default";
|
|
55
67
|
// Validate git repo
|
|
56
68
|
if (!(await isGitRepo(workDir))) {
|
|
57
69
|
return {
|
|
@@ -73,12 +85,10 @@ server.registerTool("phone_a_friend", {
|
|
|
73
85
|
// even if the agent commits during its run.
|
|
74
86
|
const baseSha = await getHeadSha(worktreePath);
|
|
75
87
|
// Run the CLI agent
|
|
76
|
-
const wrappedPrompt = wrapPrompt(prompt);
|
|
88
|
+
const wrappedPrompt = wrapPrompt(prompt, toolMode);
|
|
77
89
|
const { exitCode, stderr } = await runCopilotCli(worktreePath, wrappedPrompt, model);
|
|
78
90
|
// Read the response file before diffing
|
|
79
91
|
const response = await readAndRemoveResponse(worktreePath, RESPONSE_FILENAME);
|
|
80
|
-
// Capture all file changes
|
|
81
|
-
const diff = await captureChanges(worktreePath, baseSha);
|
|
82
92
|
// Build result
|
|
83
93
|
const parts = [];
|
|
84
94
|
if (response) {
|
|
@@ -89,11 +99,21 @@ server.registerTool("phone_a_friend", {
|
|
|
89
99
|
"*No response file was created. The agent may have failed " +
|
|
90
100
|
"to follow the message-in-a-bottle instructions.*");
|
|
91
101
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
102
|
+
// Capture and include file changes only in default mode
|
|
103
|
+
if (toolMode === "default") {
|
|
104
|
+
const diff = await captureChanges(worktreePath, baseSha);
|
|
105
|
+
if (diff === null) {
|
|
106
|
+
parts.push("## File Changes\n\n" +
|
|
107
|
+
"**Warning:** Diff capture failed (output may have exceeded the " +
|
|
108
|
+
"10 MB buffer limit). The agent may have made changes that are " +
|
|
109
|
+
"not shown here.");
|
|
110
|
+
}
|
|
111
|
+
else if (diff.trim()) {
|
|
112
|
+
parts.push("## File Changes (unified diff)\n\n```diff\n" + diff + "\n```");
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
parts.push("## File Changes\n\nNo file changes were made.");
|
|
116
|
+
}
|
|
97
117
|
}
|
|
98
118
|
if (exitCode !== 0) {
|
|
99
119
|
parts.push(`## Warnings\n\nCopilot CLI exited with code ${exitCode}.` +
|
|
@@ -112,8 +132,8 @@ server.registerTool("phone_a_friend", {
|
|
|
112
132
|
try {
|
|
113
133
|
await removeWorktree(gitRoot, worktreePath);
|
|
114
134
|
}
|
|
115
|
-
catch {
|
|
116
|
-
|
|
135
|
+
catch (err) {
|
|
136
|
+
console.error(`[phone-a-friend] worktree cleanup failed for ${worktreePath}:`, err instanceof Error ? err.message : err);
|
|
117
137
|
}
|
|
118
138
|
}
|
|
119
139
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,uEAAuE;AACvE,yEAAyE;AAEzE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/util.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
export declare const TOOL_MODES: readonly ["default", "query"];
|
|
2
|
+
export type ToolMode = (typeof TOOL_MODES)[number];
|
|
1
3
|
export declare const RESPONSE_FILENAME = ".paf-response.md";
|
|
2
4
|
export declare const AVAILABLE_MODELS: readonly ["claude-sonnet-4.5", "claude-haiku-4.5", "claude-opus-4.6", "claude-opus-4.6-fast", "claude-opus-4.5", "claude-sonnet-4", "gemini-3-pro-preview", "gpt-5.3-codex", "gpt-5.2-codex", "gpt-5.2", "gpt-5.1-codex-max", "gpt-5.1-codex", "gpt-5.1", "gpt-5", "gpt-5.1-codex-mini", "gpt-5-mini", "gpt-4.1"];
|
|
3
5
|
/**
|
|
4
6
|
* Wraps the user's prompt with instructions for the subagent about
|
|
5
|
-
* the message-in-a-bottle response file and
|
|
7
|
+
* the message-in-a-bottle response file and operating constraints.
|
|
8
|
+
* In query mode, tells the subagent changes will be discarded.
|
|
6
9
|
*/
|
|
7
|
-
export declare function wrapPrompt(userPrompt: string): string;
|
|
10
|
+
export declare function wrapPrompt(userPrompt: string, mode?: ToolMode): string;
|
|
8
11
|
/**
|
|
9
12
|
* Generates a unique worktree path based on timestamp and random suffix.
|
|
10
13
|
*/
|
package/dist/util.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,iBAAiB,qBAAqB,CAAC;AAEpD,eAAO,MAAM,gBAAgB,mTAkBnB,CAAC;AAEX
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,UAAU,+BAAgC,CAAC;AACxD,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,eAAO,MAAM,iBAAiB,qBAAqB,CAAC;AAEpD,eAAO,MAAM,gBAAgB,mTAkBnB,CAAC;AAEX;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,GAAE,QAAoB,GAAG,MAAM,CAgCjF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAI5D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,eAAO,MAAM,6BAA6B,QAAY,CAAC;AAIvD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAY/D"}
|
package/dist/util.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// ABOUTME: Pure utility functions for prompt wrapping and path generation.
|
|
2
2
|
// ABOUTME: Separated from server startup so tests can import without side effects.
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
+
export const TOOL_MODES = ["default", "query"];
|
|
4
5
|
export const RESPONSE_FILENAME = ".paf-response.md";
|
|
5
6
|
export const AVAILABLE_MODELS = [
|
|
6
7
|
"claude-sonnet-4.5",
|
|
@@ -23,20 +24,36 @@ export const AVAILABLE_MODELS = [
|
|
|
23
24
|
];
|
|
24
25
|
/**
|
|
25
26
|
* Wraps the user's prompt with instructions for the subagent about
|
|
26
|
-
* the message-in-a-bottle response file and
|
|
27
|
+
* the message-in-a-bottle response file and operating constraints.
|
|
28
|
+
* In query mode, tells the subagent changes will be discarded.
|
|
27
29
|
*/
|
|
28
|
-
export function wrapPrompt(userPrompt) {
|
|
30
|
+
export function wrapPrompt(userPrompt, mode = "default") {
|
|
31
|
+
if (mode === "query") {
|
|
32
|
+
return `## CRITICAL INSTRUCTIONS — READ BEFORE DOING ANYTHING
|
|
33
|
+
|
|
34
|
+
You are operating as a subagent inside an isolated git worktree for reference only. Any file changes you make will be discarded. Focus on analysis and your written response.
|
|
35
|
+
|
|
36
|
+
1. **Do NOT modify files.** Any changes will be thrown away. The repository is available for you to read, not to edit.
|
|
37
|
+
2. **When you are finished**, write your complete final response to the file \`${RESPONSE_FILENAME}\` in the repository root. This file is your ONLY communication channel back to the calling agent. Include:
|
|
38
|
+
- Your analysis or answer
|
|
39
|
+
- Any important findings or decisions
|
|
40
|
+
- Any warnings or caveats
|
|
41
|
+
3. You MUST create the \`${RESPONSE_FILENAME}\` file. It is how you report back.
|
|
42
|
+
|
|
43
|
+
## YOUR TASK
|
|
44
|
+
|
|
45
|
+
${userPrompt}`;
|
|
46
|
+
}
|
|
29
47
|
return `## CRITICAL INSTRUCTIONS — READ BEFORE DOING ANYTHING
|
|
30
48
|
|
|
31
49
|
You are operating as a subagent inside an isolated git worktree. Follow these rules:
|
|
32
50
|
|
|
33
51
|
1. **NEVER push to any remote.** Do not run \`git push\` under any circumstances.
|
|
34
|
-
2. **
|
|
35
|
-
3. **When you are finished**, write your complete final response to the file \`${RESPONSE_FILENAME}\` in the repository root. This file is your ONLY communication channel back to the calling agent. Include:
|
|
52
|
+
2. **When you are finished**, write your complete final response to the file \`${RESPONSE_FILENAME}\` in the repository root. This file is your ONLY communication channel back to the calling agent. Include:
|
|
36
53
|
- A summary of what you did
|
|
37
54
|
- Any important findings or decisions
|
|
38
55
|
- Any warnings or caveats
|
|
39
|
-
|
|
56
|
+
3. You MUST create the \`${RESPONSE_FILENAME}\` file even if you made no code changes. It is how you report back.
|
|
40
57
|
|
|
41
58
|
## YOUR TASK
|
|
42
59
|
|
package/dist/util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,mFAAmF;AAEnF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AAEpD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,mBAAmB;IACnB,kBAAkB;IAClB,iBAAiB;IACjB,sBAAsB;IACtB,iBAAiB;IACjB,iBAAiB;IACjB,sBAAsB;IACtB,eAAe;IACf,eAAe;IACf,SAAS;IACT,mBAAmB;IACnB,eAAe;IACf,SAAS;IACT,OAAO;IACP,oBAAoB;IACpB,YAAY;IACZ,SAAS;CACD,CAAC;AAEX
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,mFAAmF;AAEnF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,SAAS,EAAE,OAAO,CAAU,CAAC;AAGxD,MAAM,CAAC,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AAEpD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,mBAAmB;IACnB,kBAAkB;IAClB,iBAAiB;IACjB,sBAAsB;IACtB,iBAAiB;IACjB,iBAAiB;IACjB,sBAAsB;IACtB,eAAe;IACf,eAAe;IACf,SAAS;IACT,mBAAmB;IACnB,eAAe;IACf,SAAS;IACT,OAAO;IACP,oBAAoB;IACpB,YAAY;IACZ,SAAS;CACD,CAAC;AAEX;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,UAAkB,EAAE,OAAiB,SAAS;IACvE,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO;;;;;iFAKsE,iBAAiB;;;;2BAIvE,iBAAiB;;;;EAI1C,UAAU,EAAE,CAAC;IACb,CAAC;IAED,OAAO;;;;;iFAKwE,iBAAiB;;;;2BAIvE,iBAAiB;;;;EAI1C,UAAU,EAAE,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,SAAS,IAAI,MAAM,EAAE,CAAC,CAAC;AACnE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,CAAS;IACnC,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;AACzC,CAAC;AAED,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,QAAQ;AAEhE,MAAM,eAAe,GAAG,mDAAmD,CAAC;AAE5E;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,IAAI,MAAM,CAAC,MAAM,GAAG,6BAA6B,EAAE,CAAC;QAClD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAChD,OAAO,CACL,kEAAkE,MAAM,MAAM;QAC9E,+EAA+E;QAC/E,6EAA6E;QAC7E,gFAAgF;QAChF,YAAY,eAAe,EAAE,CAC9B,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bexelbie/phone-a-friend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "MCP server that lets VS Code Copilot Chat invoke Copilot CLI with a different model",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/bexelbie/phone-a-friend"
|
|
8
|
+
},
|
|
5
9
|
"type": "module",
|
|
6
10
|
"main": "dist/index.js",
|
|
7
11
|
"bin": {
|
|
@@ -27,10 +31,11 @@
|
|
|
27
31
|
],
|
|
28
32
|
"license": "MIT",
|
|
29
33
|
"engines": {
|
|
30
|
-
"node": ">=
|
|
34
|
+
"node": ">=22.0.0"
|
|
31
35
|
},
|
|
32
36
|
"dependencies": {
|
|
33
|
-
"@modelcontextprotocol/sdk": "^1.26.0"
|
|
37
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
38
|
+
"zod": "^4.3.6"
|
|
34
39
|
},
|
|
35
40
|
"devDependencies": {
|
|
36
41
|
"@types/node": "^22.0.0",
|