xcode-copilot-server 1.0.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/LICENSE +21 -0
- package/README.md +147 -0
- package/config.json5 +49 -0
- package/dist/config-schema.d.ts +85 -0
- package/dist/config-schema.js +38 -0
- package/dist/config-schema.js.map +1 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.js +64 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +8 -0
- package/dist/context.js +2 -0
- package/dist/context.js.map +1 -0
- package/dist/copilot-service.d.ts +19 -0
- package/dist/copilot-service.js +49 -0
- package/dist/copilot-service.js.map +1 -0
- package/dist/handlers/completions/session-config.d.ts +12 -0
- package/dist/handlers/completions/session-config.js +63 -0
- package/dist/handlers/completions/session-config.js.map +1 -0
- package/dist/handlers/completions/streaming.d.ts +4 -0
- package/dist/handlers/completions/streaming.js +132 -0
- package/dist/handlers/completions/streaming.js.map +1 -0
- package/dist/handlers/completions.d.ts +4 -0
- package/dist/handlers/completions.js +106 -0
- package/dist/handlers/completions.js.map +1 -0
- package/dist/handlers/models.d.ts +4 -0
- package/dist/handlers/models.js +29 -0
- package/dist/handlers/models.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +96 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +19 -0
- package/dist/logger.js +43 -0
- package/dist/logger.js.map +1 -0
- package/dist/schemas.d.ts +49 -0
- package/dist/schemas.js +75 -0
- package/dist/schemas.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +41 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +83 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/prompt.d.ts +10 -0
- package/dist/utils/prompt.js +48 -0
- package/dist/utils/prompt.js.map +1 -0
- package/package.json +48 -0
- package/scripts/mcpbridge-proxy.mjs +73 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Suyash Srijan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# xcode-copilot-server
|
|
2
|
+
|
|
3
|
+
An OpenAI-compatible proxy API server that lets you use GitHub Copilot in Xcode.
|
|
4
|
+
|
|
5
|
+
## Why
|
|
6
|
+
|
|
7
|
+
Xcode 26 added support for third-party LLM providers, but it only supports ChatGPT and Claude out of the box. If you have a GitHub Copilot subscription and want to use it in Xcode, that's not possible as there's no built-in option for it.
|
|
8
|
+
|
|
9
|
+
However, Xcode does let you add a custom model provider, as long as it exposes an OpenAI-compatible API. GitHub Copilot doesn't do that, but this server helps bridges the gap by wrapping the [GitHub Copilot SDK](https://www.npmjs.com/package/@github/copilot-sdk) and exposing it as an OpenAI-compatible API that Xcode can talk to.
|
|
10
|
+
|
|
11
|
+
It also connects to Xcode's built-in MCP tools (via `xcrun mcpbridge`), giving Copilot access to your project's build logs, indexes and other context that Xcode provides. This requires Xcode 26.3 or later.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
You need [Node.js](https://nodejs.org) 25.6.0 or later.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -g xcode-copilot-server
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or run it directly:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx xcode-copilot-server
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
xcode-copilot-server [options]
|
|
31
|
+
|
|
32
|
+
Options:
|
|
33
|
+
--port <number> Port to listen on (default: 8080)
|
|
34
|
+
--log-level <level> Log verbosity: none, error, warning, info, debug, all (default: info)
|
|
35
|
+
--config <path> Path to config file (default: bundled config.json5)
|
|
36
|
+
--cwd <path> Working directory for Copilot sessions (default: process cwd)
|
|
37
|
+
--help Show help
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The server listens on `http://localhost:8080` by default and exposes two routes:
|
|
41
|
+
|
|
42
|
+
- `GET /v1/models` — lists available models from your Copilot subscription
|
|
43
|
+
- `POST /v1/chat/completions` — handles chat completion requests (streaming)
|
|
44
|
+
|
|
45
|
+
You will need to be signed in to GitHub Copilot through the [Copilot CLI](https://docs.github.com/en/copilot/using-github-copilot/using-github-copilot-in-the-command-line).
|
|
46
|
+
|
|
47
|
+
## Xcode integration
|
|
48
|
+
|
|
49
|
+
1. Start the server: `xcode-copilot-server`
|
|
50
|
+
2. Open Xcode and go to Settings > Intelligence > Add a provider
|
|
51
|
+
3. Select "Locally hosted" and set the port to 8080 (or the port that you've chosen)
|
|
52
|
+
4. Give it a description e.g. "Copilot"
|
|
53
|
+
5. Save
|
|
54
|
+
|
|
55
|
+
That's it!
|
|
56
|
+
|
|
57
|
+
### Tool calling
|
|
58
|
+
|
|
59
|
+
There's an additional step if you want to use tool calling:
|
|
60
|
+
|
|
61
|
+
1. Open Xcode and go to Settings > Intelligence
|
|
62
|
+
2. Select the provider (e.g. "Copilot" from above)
|
|
63
|
+
3. Enable "Allow tools" under "Advanced"
|
|
64
|
+
|
|
65
|
+
### MCP
|
|
66
|
+
|
|
67
|
+
There's an additional step if you want to use Xcode MCP server (requires Xcode 26.3+):
|
|
68
|
+
|
|
69
|
+
1. Open Xcode and go to Settings > Intelligence
|
|
70
|
+
2. Enable "Xcode Tools" under "Model Context Protocol"
|
|
71
|
+
|
|
72
|
+
## Configuration
|
|
73
|
+
|
|
74
|
+
The server reads its configuration from a `config.json5` file. By default, it uses the bundled one, but you can point to your own with `--config`:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
xcode-copilot-server --config ./my-config.json5
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The config file uses [JSON5](https://json5.org/) format, which supports comments and trailing commas:
|
|
81
|
+
|
|
82
|
+
```json5
|
|
83
|
+
{
|
|
84
|
+
// MCP servers to register with the Copilot session.
|
|
85
|
+
// The bundled config includes Xcode's mcpbridge by default.
|
|
86
|
+
mcpServers: {
|
|
87
|
+
xcode: {
|
|
88
|
+
type: "local",
|
|
89
|
+
command: "node",
|
|
90
|
+
args: ["./scripts/mcpbridge-proxy.mjs"],
|
|
91
|
+
allowedTools: ["*"],
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
// Built-in CLI tools allowlist.
|
|
96
|
+
// ["*"] to allow all, [] to deny all, or a list of specific tool names.
|
|
97
|
+
allowedCliTools: [],
|
|
98
|
+
|
|
99
|
+
// Maximum request body size in MiB.
|
|
100
|
+
bodyLimitMiB: 4,
|
|
101
|
+
|
|
102
|
+
// Filename patterns to filter out from search results in the prompt.
|
|
103
|
+
excludedFilePatterns: [],
|
|
104
|
+
|
|
105
|
+
// Reasoning effort for models that support it: "low", "medium", "high", "xhigh"
|
|
106
|
+
reasoningEffort: "xhigh",
|
|
107
|
+
|
|
108
|
+
// Auto-approve MCP permission requests.
|
|
109
|
+
// true to approve all, false to deny all,
|
|
110
|
+
// or an array of kinds: "read", "write", "shell", "mcp", "url"
|
|
111
|
+
autoApprovePermissions: ["read", "mcp"],
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Security
|
|
116
|
+
|
|
117
|
+
This server acts as a local proxy between Xcode and GitHub Copilot. It's designed to run on your machine and isn't intended to be exposed to the internet or shared networks. So, here's what you should know:
|
|
118
|
+
|
|
119
|
+
- The server binds to `127.0.0.1`, so it's only reachable from your machine, not from your local network or the internet. Incoming requests are checked for Xcode's user-agent, which means casual or accidental connections from other tools will be rejected. This isn't a strong security boundary since user-agent headers can be trivially spoofed, but it helps ensure only Xcode is talking to the server.
|
|
120
|
+
|
|
121
|
+
- The bundled config sets `autoApprovePermissions` to `["read", "mcp"]`, which lets the Copilot session read files and call MCP tools without prompting. Writes, shell commands, and URL fetches are denied by default. You can set it to `true` to approve everything, `false` to deny everything, or pick specific kinds from `"read"`, `"write"`, `"shell"`, `"mcp"`, and `"url"`.
|
|
122
|
+
|
|
123
|
+
- MCP servers defined in the config are spawned as child processes. The bundled config uses `xcrun mcpbridge`, which is an Apple-signed binary. If you add your own MCP servers, make sure you trust the commands you're configuring.
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
MIT License
|
|
128
|
+
|
|
129
|
+
Copyright (c) 2026 Suyash Srijan
|
|
130
|
+
|
|
131
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
132
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
133
|
+
in the Software without restriction, including without limitation the rights
|
|
134
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
135
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
136
|
+
furnished to do so, subject to the following conditions:
|
|
137
|
+
|
|
138
|
+
The above copyright notice and this permission notice shall be included in all
|
|
139
|
+
copies or substantial portions of the Software.
|
|
140
|
+
|
|
141
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
142
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
143
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
144
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
145
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
146
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
147
|
+
SOFTWARE.
|
package/config.json5
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Server configuration for xcode-copilot-server.
|
|
2
|
+
// Edit this file to add MCP servers, control tool access, and set permissions.
|
|
3
|
+
//
|
|
4
|
+
// Note: The Tool permissions are checked across all allowlists. If the same tool name
|
|
5
|
+
// exists in both CLI and MCP tools, then they cannot have different permissions.
|
|
6
|
+
|
|
7
|
+
{
|
|
8
|
+
// MCP servers to register with the Copilot CLI session.
|
|
9
|
+
// Each key is a server name, where the value follows the Copilot SDK MCPServerConfig shape.
|
|
10
|
+
// Relative paths in "args" are resolved relative to this file's directory.
|
|
11
|
+
mcpServers: {
|
|
12
|
+
xcode: {
|
|
13
|
+
type: "local",
|
|
14
|
+
command: "node",
|
|
15
|
+
args: ["./scripts/mcpbridge-proxy.mjs"],
|
|
16
|
+
allowedTools: ["*"],
|
|
17
|
+
},
|
|
18
|
+
// Example: add another MCP server
|
|
19
|
+
// myServer: {
|
|
20
|
+
// type: "local",
|
|
21
|
+
// command: "my-mcp-binary",
|
|
22
|
+
// args: ["--some-flag"],
|
|
23
|
+
// allowedTools: ["*"],
|
|
24
|
+
// },
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
// Built-in CLI tools allowlist (glob, grep, bash, etc)
|
|
28
|
+
// - ["*"]: allow all CLI tools
|
|
29
|
+
// - []: deny all CLI tools
|
|
30
|
+
// - ["glob", "grep"]: allow only specific CLI tools
|
|
31
|
+
allowedCliTools: [],
|
|
32
|
+
|
|
33
|
+
// Maximum request body size in MiB.
|
|
34
|
+
bodyLimitMiB: 4,
|
|
35
|
+
|
|
36
|
+
// Filename patterns to filter out from search results in the prompt.
|
|
37
|
+
// Code blocks whose filename contains any of these (case-insensitive) are stripped.
|
|
38
|
+
excludedFilePatterns: [],
|
|
39
|
+
|
|
40
|
+
// Reasoning effort for models that support it.
|
|
41
|
+
// E.g: "low", "medium", "high", "xhigh"
|
|
42
|
+
reasoningEffort: "xhigh",
|
|
43
|
+
|
|
44
|
+
// Auto-approve MCP permission requests.
|
|
45
|
+
// - true: approve all
|
|
46
|
+
// - false: deny all
|
|
47
|
+
// - ["read", "mcp"]: approve only listed kinds (e.g: "read", "write", "shell", "mcp", "url")
|
|
48
|
+
autoApprovePermissions: ["read", "mcp"],
|
|
49
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
declare const MCPLocalServerSchema: z.ZodObject<{
|
|
3
|
+
type: z.ZodUnion<readonly [z.ZodLiteral<"local">, z.ZodLiteral<"stdio">]>;
|
|
4
|
+
command: z.ZodString;
|
|
5
|
+
args: z.ZodArray<z.ZodString>;
|
|
6
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
7
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
8
|
+
allowedTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
9
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
10
|
+
}, z.core.$strip>;
|
|
11
|
+
declare const MCPRemoteServerSchema: z.ZodObject<{
|
|
12
|
+
type: z.ZodUnion<readonly [z.ZodLiteral<"http">, z.ZodLiteral<"sse">]>;
|
|
13
|
+
url: z.ZodURL;
|
|
14
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
15
|
+
allowedTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
16
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
17
|
+
}, z.core.$strip>;
|
|
18
|
+
declare const MCPServerSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
19
|
+
type: z.ZodUnion<readonly [z.ZodLiteral<"local">, z.ZodLiteral<"stdio">]>;
|
|
20
|
+
command: z.ZodString;
|
|
21
|
+
args: z.ZodArray<z.ZodString>;
|
|
22
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
23
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
24
|
+
allowedTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
25
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
26
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
27
|
+
type: z.ZodUnion<readonly [z.ZodLiteral<"http">, z.ZodLiteral<"sse">]>;
|
|
28
|
+
url: z.ZodURL;
|
|
29
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
30
|
+
allowedTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
31
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
32
|
+
}, z.core.$strip>]>;
|
|
33
|
+
declare const ApprovalRuleSchema: z.ZodUnion<readonly [z.ZodBoolean, z.ZodArray<z.ZodEnum<{
|
|
34
|
+
url: "url";
|
|
35
|
+
read: "read";
|
|
36
|
+
write: "write";
|
|
37
|
+
shell: "shell";
|
|
38
|
+
mcp: "mcp";
|
|
39
|
+
}>>]>;
|
|
40
|
+
declare const ReasoningEffortSchema: z.ZodEnum<{
|
|
41
|
+
low: "low";
|
|
42
|
+
medium: "medium";
|
|
43
|
+
high: "high";
|
|
44
|
+
xhigh: "xhigh";
|
|
45
|
+
}>;
|
|
46
|
+
export type MCPLocalServer = z.infer<typeof MCPLocalServerSchema>;
|
|
47
|
+
export type MCPRemoteServer = z.infer<typeof MCPRemoteServerSchema>;
|
|
48
|
+
export type MCPServer = z.infer<typeof MCPServerSchema>;
|
|
49
|
+
export type ApprovalRule = z.infer<typeof ApprovalRuleSchema>;
|
|
50
|
+
export type ReasoningEffort = z.infer<typeof ReasoningEffortSchema>;
|
|
51
|
+
export declare const ServerConfigSchema: z.ZodObject<{
|
|
52
|
+
mcpServers: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
53
|
+
type: z.ZodUnion<readonly [z.ZodLiteral<"local">, z.ZodLiteral<"stdio">]>;
|
|
54
|
+
command: z.ZodString;
|
|
55
|
+
args: z.ZodArray<z.ZodString>;
|
|
56
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
57
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
58
|
+
allowedTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
59
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
60
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
61
|
+
type: z.ZodUnion<readonly [z.ZodLiteral<"http">, z.ZodLiteral<"sse">]>;
|
|
62
|
+
url: z.ZodURL;
|
|
63
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
64
|
+
allowedTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
65
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
66
|
+
}, z.core.$strip>]>>>;
|
|
67
|
+
allowedCliTools: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
68
|
+
excludedFilePatterns: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
69
|
+
bodyLimitMiB: z.ZodDefault<z.ZodNumber>;
|
|
70
|
+
reasoningEffort: z.ZodOptional<z.ZodEnum<{
|
|
71
|
+
low: "low";
|
|
72
|
+
medium: "medium";
|
|
73
|
+
high: "high";
|
|
74
|
+
xhigh: "xhigh";
|
|
75
|
+
}>>;
|
|
76
|
+
autoApprovePermissions: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodArray<z.ZodEnum<{
|
|
77
|
+
url: "url";
|
|
78
|
+
read: "read";
|
|
79
|
+
write: "write";
|
|
80
|
+
shell: "shell";
|
|
81
|
+
mcp: "mcp";
|
|
82
|
+
}>>]>>;
|
|
83
|
+
}, z.core.$strip>;
|
|
84
|
+
export type RawServerConfig = z.infer<typeof ServerConfigSchema>;
|
|
85
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const MCPLocalServerSchema = z.object({
|
|
3
|
+
type: z.union([z.literal("local"), z.literal("stdio")]),
|
|
4
|
+
command: z.string().min(1, "MCP server command cannot be empty"),
|
|
5
|
+
args: z.array(z.string()),
|
|
6
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
7
|
+
cwd: z.string().optional(),
|
|
8
|
+
allowedTools: z.array(z.string()).optional(),
|
|
9
|
+
timeout: z.number().positive().optional(),
|
|
10
|
+
});
|
|
11
|
+
const MCPRemoteServerSchema = z.object({
|
|
12
|
+
type: z.union([z.literal("http"), z.literal("sse")]),
|
|
13
|
+
url: z.url(),
|
|
14
|
+
headers: z.record(z.string(), z.string()).optional(),
|
|
15
|
+
allowedTools: z.array(z.string()).optional(),
|
|
16
|
+
timeout: z.number().positive().optional(),
|
|
17
|
+
});
|
|
18
|
+
const MCPServerSchema = z.union([MCPLocalServerSchema, MCPRemoteServerSchema]);
|
|
19
|
+
const VALID_PERMISSION_KINDS = ["read", "write", "shell", "mcp", "url"];
|
|
20
|
+
const ApprovalRuleSchema = z.union([
|
|
21
|
+
z.boolean(),
|
|
22
|
+
z.array(z.enum(VALID_PERMISSION_KINDS)),
|
|
23
|
+
]);
|
|
24
|
+
const VALID_REASONING_EFFORTS = ["low", "medium", "high", "xhigh"];
|
|
25
|
+
const ReasoningEffortSchema = z.enum(VALID_REASONING_EFFORTS);
|
|
26
|
+
export const ServerConfigSchema = z.object({
|
|
27
|
+
mcpServers: z.record(z.string(), MCPServerSchema).default({}),
|
|
28
|
+
allowedCliTools: z.array(z.string()).default([]),
|
|
29
|
+
excludedFilePatterns: z.array(z.string()).default([]),
|
|
30
|
+
bodyLimitMiB: z
|
|
31
|
+
.number()
|
|
32
|
+
.positive()
|
|
33
|
+
.max(100, "bodyLimitMiB cannot exceed 100")
|
|
34
|
+
.default(4),
|
|
35
|
+
reasoningEffort: ReasoningEffortSchema.optional(),
|
|
36
|
+
autoApprovePermissions: ApprovalRuleSchema.default(["read", "mcp"]),
|
|
37
|
+
});
|
|
38
|
+
//# sourceMappingURL=config-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-schema.js","sourceRoot":"","sources":["../src/config-schema.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Logger } from "./logger.js";
|
|
2
|
+
import { type RawServerConfig } from "./config-schema.js";
|
|
3
|
+
export type { MCPLocalServer, MCPRemoteServer, MCPServer, ApprovalRule, ReasoningEffort, } from "./config-schema.js";
|
|
4
|
+
export type ServerConfig = Omit<RawServerConfig, "bodyLimitMiB"> & {
|
|
5
|
+
bodyLimit: number;
|
|
6
|
+
};
|
|
7
|
+
export declare function loadConfig(configPath: string, logger: Logger): Promise<ServerConfig>;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { resolve, dirname, isAbsolute } from "node:path";
|
|
4
|
+
import JSON5 from "json5";
|
|
5
|
+
import { ServerConfigSchema, } from "./config-schema.js";
|
|
6
|
+
const DEFAULT_CONFIG = {
|
|
7
|
+
mcpServers: {},
|
|
8
|
+
allowedCliTools: [],
|
|
9
|
+
excludedFilePatterns: [],
|
|
10
|
+
bodyLimit: 4 * 1024 * 1024, // 4 MiB
|
|
11
|
+
autoApprovePermissions: ["read", "mcp"],
|
|
12
|
+
};
|
|
13
|
+
function resolveServerPaths(servers, configDir) {
|
|
14
|
+
return Object.fromEntries(Object.entries(servers).map(([name, server]) => [
|
|
15
|
+
name,
|
|
16
|
+
"args" in server
|
|
17
|
+
? {
|
|
18
|
+
...server,
|
|
19
|
+
args: server.args.map((arg) => arg.startsWith("./") || arg.startsWith("../")
|
|
20
|
+
? resolve(configDir, arg)
|
|
21
|
+
: arg),
|
|
22
|
+
}
|
|
23
|
+
: server,
|
|
24
|
+
]));
|
|
25
|
+
}
|
|
26
|
+
export async function loadConfig(configPath, logger) {
|
|
27
|
+
const absolutePath = isAbsolute(configPath)
|
|
28
|
+
? configPath
|
|
29
|
+
: resolve(process.cwd(), configPath);
|
|
30
|
+
if (!existsSync(absolutePath)) {
|
|
31
|
+
logger.warn(`No config file at ${absolutePath}, using defaults`);
|
|
32
|
+
return DEFAULT_CONFIG;
|
|
33
|
+
}
|
|
34
|
+
logger.info(`Reading config from ${absolutePath}`);
|
|
35
|
+
const text = await readFile(absolutePath, "utf-8");
|
|
36
|
+
let raw;
|
|
37
|
+
try {
|
|
38
|
+
raw = JSON5.parse(text);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
throw new Error(`Failed to parse config file: ${err instanceof Error ? err.message : String(err)}`);
|
|
42
|
+
}
|
|
43
|
+
if (!raw || typeof raw !== "object") {
|
|
44
|
+
throw new Error("Config file must contain a JSON5 object");
|
|
45
|
+
}
|
|
46
|
+
const parseResult = ServerConfigSchema.safeParse(raw);
|
|
47
|
+
if (!parseResult.success) {
|
|
48
|
+
const firstError = parseResult.error.issues[0];
|
|
49
|
+
if (!firstError) {
|
|
50
|
+
throw new Error("Invalid config: validation failed");
|
|
51
|
+
}
|
|
52
|
+
const path = firstError.path.join(".");
|
|
53
|
+
throw new Error(`Invalid config${path ? ` at "${path}"` : ""}: ${firstError.message}`);
|
|
54
|
+
}
|
|
55
|
+
const { bodyLimitMiB, ...rest } = parseResult.data;
|
|
56
|
+
const config = {
|
|
57
|
+
...rest,
|
|
58
|
+
bodyLimit: bodyLimitMiB * 1024 * 1024,
|
|
59
|
+
mcpServers: resolveServerPaths(parseResult.data.mcpServers, dirname(absolutePath)),
|
|
60
|
+
};
|
|
61
|
+
logger.info(`Loaded ${String(Object.keys(config.mcpServers).length)} MCP server(s) and ${String(config.allowedCliTools.length)} allowed CLI tool(s)`);
|
|
62
|
+
return config;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type CopilotSession, type SessionConfig, type ModelInfo } from "@github/copilot-sdk";
|
|
2
|
+
import type { LogLevel, Logger } from "./logger.js";
|
|
3
|
+
export interface CopilotServiceOptions {
|
|
4
|
+
logLevel?: LogLevel | undefined;
|
|
5
|
+
logger?: Logger | undefined;
|
|
6
|
+
cwd?: string | undefined;
|
|
7
|
+
}
|
|
8
|
+
export declare class CopilotService {
|
|
9
|
+
readonly cwd: string;
|
|
10
|
+
private client;
|
|
11
|
+
private session;
|
|
12
|
+
private sessionPromise;
|
|
13
|
+
private logger;
|
|
14
|
+
constructor(options?: CopilotServiceOptions);
|
|
15
|
+
start(): Promise<void>;
|
|
16
|
+
stop(): Promise<void>;
|
|
17
|
+
listModels(): Promise<ModelInfo[]>;
|
|
18
|
+
getSession(config: SessionConfig): Promise<CopilotSession>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { CopilotClient, } from "@github/copilot-sdk";
|
|
2
|
+
export class CopilotService {
|
|
3
|
+
cwd;
|
|
4
|
+
client;
|
|
5
|
+
session = null;
|
|
6
|
+
sessionPromise = null;
|
|
7
|
+
logger;
|
|
8
|
+
constructor(options = {}) {
|
|
9
|
+
this.cwd = options.cwd ?? process.cwd();
|
|
10
|
+
this.logger = options.logger;
|
|
11
|
+
this.client = new CopilotClient({
|
|
12
|
+
logLevel: options.logLevel ?? "error",
|
|
13
|
+
cwd: this.cwd,
|
|
14
|
+
env: Object.fromEntries(Object.entries(process.env).filter((e) => e[1] != null)),
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
async start() {
|
|
18
|
+
await this.client.start();
|
|
19
|
+
}
|
|
20
|
+
async stop() {
|
|
21
|
+
if (this.session) {
|
|
22
|
+
await this.session.destroy();
|
|
23
|
+
this.session = null;
|
|
24
|
+
}
|
|
25
|
+
this.sessionPromise = null;
|
|
26
|
+
await this.client.stop();
|
|
27
|
+
}
|
|
28
|
+
async listModels() {
|
|
29
|
+
return this.client.listModels();
|
|
30
|
+
}
|
|
31
|
+
async getSession(config) {
|
|
32
|
+
if (this.session) {
|
|
33
|
+
return this.session;
|
|
34
|
+
}
|
|
35
|
+
if (!this.sessionPromise) {
|
|
36
|
+
this.sessionPromise = this.client.createSession(config).then((s) => {
|
|
37
|
+
this.session = s;
|
|
38
|
+
this.sessionPromise = null;
|
|
39
|
+
this.logger?.info("Session created");
|
|
40
|
+
return s;
|
|
41
|
+
}, (err) => {
|
|
42
|
+
this.sessionPromise = null;
|
|
43
|
+
throw err;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return this.sessionPromise;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=copilot-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilot-service.js","sourceRoot":"","sources":["../src/copilot-service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,GAId,MAAM,qBAAqB,CAAC;AAS7B,MAAM,OAAO,cAAc;IAChB,GAAG,CAAS;IACb,MAAM,CAAgB;IACtB,OAAO,GAA0B,IAAI,CAAC;IACtC,cAAc,GAAmC,IAAI,CAAC;IACtD,MAAM,CAAqB;IAEnC,YAAY,UAAiC,EAAE;QAC7C,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACxC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,IAAI,aAAa,CAAC;YAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,OAAO;YACrC,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,GAAG,EAAE,MAAM,CAAC,WAAW,CACrB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAyB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAC/E;SACF,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,CAAC;QACD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAqB;QACpC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC,OAAO,CAAC;QACtB,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACzB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,CAC1D,CAAC,CAAC,EAAE,EAAE;gBACJ,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;gBACjB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;gBAC3B,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;gBACrC,OAAO,CAAC,CAAC;YACX,CAAC,EACD,CAAC,GAAY,EAAE,EAAE;gBACf,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;gBAC3B,MAAM,GAAG,CAAC;YACZ,CAAC,CACF,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;CACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SessionConfig } from "@github/copilot-sdk";
|
|
2
|
+
import type { ServerConfig } from "../../config.js";
|
|
3
|
+
import type { Logger } from "../../logger.js";
|
|
4
|
+
export interface SessionConfigOptions {
|
|
5
|
+
model: string;
|
|
6
|
+
systemMessage?: string | undefined;
|
|
7
|
+
logger: Logger;
|
|
8
|
+
config: ServerConfig;
|
|
9
|
+
supportsReasoningEffort: boolean;
|
|
10
|
+
cwd?: string | undefined;
|
|
11
|
+
}
|
|
12
|
+
export declare function createSessionConfig({ model, systemMessage, logger, config, supportsReasoningEffort, cwd, }: SessionConfigOptions): SessionConfig;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
function isApproved(rule, kind) {
|
|
2
|
+
if (typeof rule === "boolean")
|
|
3
|
+
return rule;
|
|
4
|
+
return rule.some((k) => k === kind);
|
|
5
|
+
}
|
|
6
|
+
export function createSessionConfig({ model, systemMessage, logger, config, supportsReasoningEffort, cwd, }) {
|
|
7
|
+
return {
|
|
8
|
+
model,
|
|
9
|
+
streaming: true,
|
|
10
|
+
infiniteSessions: { enabled: true },
|
|
11
|
+
workingDirectory: cwd ?? process.cwd(),
|
|
12
|
+
...(systemMessage && {
|
|
13
|
+
systemMessage: {
|
|
14
|
+
mode: "replace",
|
|
15
|
+
content: systemMessage,
|
|
16
|
+
},
|
|
17
|
+
}),
|
|
18
|
+
mcpServers: Object.fromEntries(Object.entries(config.mcpServers).map(([name, server]) => [
|
|
19
|
+
name,
|
|
20
|
+
{ ...server, tools: ["*"] },
|
|
21
|
+
])),
|
|
22
|
+
...(config.allowedCliTools.length > 0 && {
|
|
23
|
+
availableTools: config.allowedCliTools,
|
|
24
|
+
}),
|
|
25
|
+
...(config.reasoningEffort && supportsReasoningEffort && {
|
|
26
|
+
reasoningEffort: config.reasoningEffort,
|
|
27
|
+
}),
|
|
28
|
+
onUserInputRequest: (request) => {
|
|
29
|
+
logger.debug(`User input requested: "${request.question}"`);
|
|
30
|
+
return Promise.resolve({
|
|
31
|
+
answer: "User input is not available. Ask your question in your response instead.",
|
|
32
|
+
wasFreeform: true,
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
onPermissionRequest: (request) => {
|
|
36
|
+
const approved = isApproved(config.autoApprovePermissions, request.kind);
|
|
37
|
+
logger.debug(`Permission "${request.kind}": ${approved ? "approved" : "denied"}`);
|
|
38
|
+
return Promise.resolve(approved
|
|
39
|
+
? { kind: "approved" }
|
|
40
|
+
: { kind: "denied-by-rules" });
|
|
41
|
+
},
|
|
42
|
+
hooks: {
|
|
43
|
+
onPreToolUse: (input) => {
|
|
44
|
+
const toolName = input.toolName;
|
|
45
|
+
if (config.allowedCliTools.includes("*") ||
|
|
46
|
+
config.allowedCliTools.includes(toolName)) {
|
|
47
|
+
logger.debug(`Tool "${toolName}": allowed (CLI)`);
|
|
48
|
+
return Promise.resolve({ permissionDecision: "allow" });
|
|
49
|
+
}
|
|
50
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
51
|
+
const allowlist = server.allowedTools ?? [];
|
|
52
|
+
if (allowlist.includes("*") || allowlist.includes(toolName)) {
|
|
53
|
+
logger.debug(`Tool "${toolName}": allowed (${serverName})`);
|
|
54
|
+
return Promise.resolve({ permissionDecision: "allow" });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
logger.debug(`Tool "${toolName}": denied (not in any allowlist)`);
|
|
58
|
+
return Promise.resolve({ permissionDecision: "deny" });
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=session-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-config.js","sourceRoot":"","sources":["../../../src/handlers/completions/session-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { FastifyReply } from "fastify";
|
|
2
|
+
import type { CopilotSession } from "@github/copilot-sdk";
|
|
3
|
+
import type { Logger } from "../../logger.js";
|
|
4
|
+
export declare function handleStreaming(reply: FastifyReply, session: CopilotSession, prompt: string, model: string, logger: Logger): Promise<void>;
|