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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +147 -0
  3. package/config.json5 +49 -0
  4. package/dist/config-schema.d.ts +85 -0
  5. package/dist/config-schema.js +38 -0
  6. package/dist/config-schema.js.map +1 -0
  7. package/dist/config.d.ts +7 -0
  8. package/dist/config.js +64 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/context.d.ts +8 -0
  11. package/dist/context.js +2 -0
  12. package/dist/context.js.map +1 -0
  13. package/dist/copilot-service.d.ts +19 -0
  14. package/dist/copilot-service.js +49 -0
  15. package/dist/copilot-service.js.map +1 -0
  16. package/dist/handlers/completions/session-config.d.ts +12 -0
  17. package/dist/handlers/completions/session-config.js +63 -0
  18. package/dist/handlers/completions/session-config.js.map +1 -0
  19. package/dist/handlers/completions/streaming.d.ts +4 -0
  20. package/dist/handlers/completions/streaming.js +132 -0
  21. package/dist/handlers/completions/streaming.js.map +1 -0
  22. package/dist/handlers/completions.d.ts +4 -0
  23. package/dist/handlers/completions.js +106 -0
  24. package/dist/handlers/completions.js.map +1 -0
  25. package/dist/handlers/models.d.ts +4 -0
  26. package/dist/handlers/models.js +29 -0
  27. package/dist/handlers/models.js.map +1 -0
  28. package/dist/index.d.ts +2 -0
  29. package/dist/index.js +96 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/logger.d.ts +19 -0
  32. package/dist/logger.js +43 -0
  33. package/dist/logger.js.map +1 -0
  34. package/dist/schemas.d.ts +49 -0
  35. package/dist/schemas.js +75 -0
  36. package/dist/schemas.js.map +1 -0
  37. package/dist/server.d.ts +3 -0
  38. package/dist/server.js +41 -0
  39. package/dist/server.js.map +1 -0
  40. package/dist/types.d.ts +83 -0
  41. package/dist/types.js +2 -0
  42. package/dist/types.js.map +1 -0
  43. package/dist/utils/prompt.d.ts +10 -0
  44. package/dist/utils/prompt.js +48 -0
  45. package/dist/utils/prompt.js.map +1 -0
  46. package/package.json +48 -0
  47. 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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"}
@@ -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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"}
@@ -0,0 +1,8 @@
1
+ import type { CopilotService } from "./copilot-service.js";
2
+ import type { ServerConfig } from "./config.js";
3
+ import type { Logger } from "./logger.js";
4
+ export interface AppContext {
5
+ service: CopilotService;
6
+ logger: Logger;
7
+ config: ServerConfig;
8
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=context.js.map
@@ -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>;