xcode-copilot-server 1.0.4 → 2.0.1

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 (102) hide show
  1. package/README.md +56 -29
  2. package/config.json5 +49 -41
  3. package/dist/config.d.ts +9 -4
  4. package/dist/config.js +25 -7
  5. package/dist/config.js.map +1 -1
  6. package/dist/context.d.ts +1 -0
  7. package/dist/conversation-manager.d.ts +32 -0
  8. package/dist/conversation-manager.js +120 -0
  9. package/dist/conversation-manager.js.map +1 -0
  10. package/dist/copilot-service.d.ts +1 -3
  11. package/dist/copilot-service.js +3 -23
  12. package/dist/copilot-service.js.map +1 -1
  13. package/dist/handlers/completions/streaming.d.ts +1 -1
  14. package/dist/handlers/completions/streaming.js +13 -24
  15. package/dist/handlers/completions/streaming.js.map +1 -1
  16. package/dist/handlers/completions.d.ts +2 -2
  17. package/dist/handlers/completions.js +75 -63
  18. package/dist/handlers/completions.js.map +1 -1
  19. package/dist/handlers/errors.d.ts +5 -0
  20. package/dist/handlers/errors.js +10 -0
  21. package/dist/handlers/errors.js.map +1 -0
  22. package/dist/handlers/messages/count-tokens.d.ts +3 -0
  23. package/dist/handlers/messages/count-tokens.js +72 -0
  24. package/dist/handlers/messages/count-tokens.js.map +1 -0
  25. package/dist/handlers/messages/streaming.d.ts +6 -0
  26. package/dist/handlers/messages/streaming.js +274 -0
  27. package/dist/handlers/messages/streaming.js.map +1 -0
  28. package/dist/handlers/messages/tool-result-handler.d.ts +4 -0
  29. package/dist/handlers/messages/tool-result-handler.js +19 -0
  30. package/dist/handlers/messages/tool-result-handler.js.map +1 -0
  31. package/dist/handlers/messages.d.ts +4 -0
  32. package/dist/handlers/messages.js +150 -0
  33. package/dist/handlers/messages.js.map +1 -0
  34. package/dist/handlers/models.d.ts +0 -1
  35. package/dist/handlers/models.js +1 -2
  36. package/dist/handlers/models.js.map +1 -1
  37. package/dist/handlers/session-config.d.ts +15 -0
  38. package/dist/handlers/session-config.js +79 -0
  39. package/dist/handlers/session-config.js.map +1 -0
  40. package/dist/handlers/streaming-utils.d.ts +9 -0
  41. package/dist/handlers/streaming-utils.js +19 -0
  42. package/dist/handlers/streaming-utils.js.map +1 -0
  43. package/dist/index.js +22 -7
  44. package/dist/index.js.map +1 -1
  45. package/dist/logger.d.ts +0 -1
  46. package/dist/logger.js +4 -10
  47. package/dist/logger.js.map +1 -1
  48. package/dist/providers/anthropic.d.ts +5 -0
  49. package/dist/providers/anthropic.js +28 -0
  50. package/dist/providers/anthropic.js.map +1 -0
  51. package/dist/providers/index.d.ts +15 -0
  52. package/dist/providers/index.js +7 -0
  53. package/dist/providers/index.js.map +1 -0
  54. package/dist/providers/openai.d.ts +5 -0
  55. package/dist/providers/openai.js +25 -0
  56. package/dist/providers/openai.js.map +1 -0
  57. package/dist/providers/types.d.ts +7 -0
  58. package/dist/providers/types.js +2 -0
  59. package/dist/providers/types.js.map +1 -0
  60. package/dist/schemas/anthropic.d.ts +140 -0
  61. package/dist/schemas/anthropic.js +58 -0
  62. package/dist/schemas/anthropic.js.map +1 -0
  63. package/dist/schemas/config.d.ts +127 -0
  64. package/dist/schemas/config.js +44 -0
  65. package/dist/schemas/config.js.map +1 -0
  66. package/dist/schemas/openai.d.ts +98 -0
  67. package/dist/schemas/openai.js +76 -0
  68. package/dist/schemas/openai.js.map +1 -0
  69. package/dist/server.d.ts +2 -1
  70. package/dist/server.js +11 -20
  71. package/dist/server.js.map +1 -1
  72. package/dist/tool-bridge/index.d.ts +4 -0
  73. package/dist/tool-bridge/index.js +8 -0
  74. package/dist/tool-bridge/index.js.map +1 -0
  75. package/dist/tool-bridge/reply-tracker.d.ts +10 -0
  76. package/dist/tool-bridge/reply-tracker.js +28 -0
  77. package/dist/tool-bridge/reply-tracker.js.map +1 -0
  78. package/dist/tool-bridge/routes.d.ts +4 -0
  79. package/dist/tool-bridge/routes.js +111 -0
  80. package/dist/tool-bridge/routes.js.map +1 -0
  81. package/dist/tool-bridge/session-lifecycle.d.ts +16 -0
  82. package/dist/tool-bridge/session-lifecycle.js +43 -0
  83. package/dist/tool-bridge/session-lifecycle.js.map +1 -0
  84. package/dist/tool-bridge/state.d.ts +34 -0
  85. package/dist/tool-bridge/state.js +77 -0
  86. package/dist/tool-bridge/state.js.map +1 -0
  87. package/dist/tool-bridge/tool-cache.d.ts +10 -0
  88. package/dist/tool-bridge/tool-cache.js +82 -0
  89. package/dist/tool-bridge/tool-cache.js.map +1 -0
  90. package/dist/tool-bridge/tool-router.d.ts +12 -0
  91. package/dist/tool-bridge/tool-router.js +82 -0
  92. package/dist/tool-bridge/tool-router.js.map +1 -0
  93. package/dist/utils/anthropic-prompt.d.ts +2 -0
  94. package/dist/utils/anthropic-prompt.js +52 -0
  95. package/dist/utils/anthropic-prompt.js.map +1 -0
  96. package/dist/utils/model-resolver.d.ts +3 -0
  97. package/dist/utils/model-resolver.js +45 -0
  98. package/dist/utils/model-resolver.js.map +1 -0
  99. package/dist/utils/prompt.d.ts +2 -14
  100. package/dist/utils/prompt.js +11 -14
  101. package/dist/utils/prompt.js.map +1 -1
  102. package/package.json +5 -4
package/README.md CHANGED
@@ -1,14 +1,17 @@
1
1
  # xcode-copilot-server [![npm version](https://img.shields.io/npm/v/xcode-copilot-server)](https://www.npmjs.com/package/xcode-copilot-server)
2
2
 
3
- An OpenAI-compatible proxy API server that lets you use GitHub Copilot in Xcode.
3
+ A proxy API server that lets you use GitHub Copilot in Xcode, either as a custom model provider (OpenAI mode) or as the backend for Claude Agent (Anthropic mode).
4
4
 
5
5
  ## Why
6
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.
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, there's no built-in way to use it.
8
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://github.com/github/copilot-sdk) and exposing it as an OpenAI-compatible API that Xcode can talk to.
9
+ This server bridges the gap by wrapping the [GitHub Copilot SDK](https://github.com/github/copilot-sdk) and exposing it as an API that Xcode can talk to. It supports two modes:
10
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.
11
+ - **OpenAI mode** (default): This exposes an OpenAI-compatible API so Xcode can use Copilot as a custom model provider. Xcode handles tool execution directly.
12
+ - **Anthropic mode**: This exposes an Anthropic-compatible API so Xcode can use Copilot as the proxy for Claude Agent. A built-in tool bridge intercepts tool calls from the Copilot session and routes them back to Xcode for execution.
13
+
14
+ Both modes connect to Xcode's built-in MCP tools (via `xcrun mcpbridge`), giving Copilot access to your project's build logs, indexes and other context. This requires Xcode 26.3 or later.
12
15
 
13
16
  ## Installation
14
17
 
@@ -37,45 +40,56 @@ xcode-copilot-server [options]
37
40
 
38
41
  Options:
39
42
  --port <number> Port to listen on (default: 8080)
43
+ --proxy <provider> API format to expose: openai, anthropic (default: openai)
40
44
  --log-level <level> Log verbosity: none, error, warning, info, debug, all (default: info)
41
45
  --config <path> Path to config file (default: bundled config.json5)
42
46
  --cwd <path> Working directory for Copilot sessions (default: process cwd)
43
47
  --help Show help
44
48
  ```
45
49
 
46
- The server listens on `http://localhost:8080` by default and exposes two routes:
50
+ The `--proxy` flag determines which API the server exposes:
47
51
 
48
- - `GET /v1/models` — lists available models from your Copilot subscription
49
- - `POST /v1/chat/completions` — handles chat completion requests (streaming)
52
+ | Mode | Flag | Routes |
53
+ |-----------|----------------------------|-------------------------------------------------------|
54
+ | OpenAI | `--proxy openai` (default) | `GET /v1/models`, `POST /v1/chat/completions` |
55
+ | Anthropic | `--proxy anthropic` | `POST /v1/messages`, `POST /v1/messages/count_tokens` |
50
56
 
51
57
  ## Xcode integration
52
58
 
59
+ ### OpenAI mode (custom model provider)
60
+
53
61
  1. Start the server: `xcode-copilot-server`
54
62
  2. Open Xcode and go to Settings > Intelligence > Add a provider
55
63
  3. Select "Locally hosted" and set the port to 8080 (or the port that you've chosen)
56
64
  4. Give it a description e.g. "Copilot"
57
65
  5. Save
58
66
 
59
- That's it!
67
+ To enable tool calling, select the provider and enable "Allow tools" under "Advanced". To connect Xcode's MCP tools (Xcode 26.3+), enable "Xcode Tools" under "Model Context Protocol".
60
68
 
61
- ### Tool calling
69
+ ### Anthropic mode (Claude Agent)
62
70
 
63
- There's an additional step if you want to use tool calling:
71
+ 1. Open Xcode and go to Settings > Intelligence > Anthropic > Claude Agent
72
+ 2. Enable Claude Agent and sign in with an API key (the key can be any random text, since the calls are proxied through the server)
73
+ 3. Create a `settings.json` file at `~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig/`:
64
74
 
65
- 1. Open Xcode and go to Settings > Intelligence
66
- 2. Select the provider (e.g. "Copilot" from above)
67
- 3. Enable "Allow tools" under "Advanced"
75
+ ```json
76
+ {
77
+ "env": {
78
+ "ANTHROPIC_BASE_URL": "http://localhost:8080",
79
+ "ANTHROPIC_AUTH_TOKEN": "12345"
80
+ }
81
+ }
82
+ ```
68
83
 
69
- ### MCP
84
+ Set the port to match your `--port` flag (default 8080). The auth token can be any non-empty string.
70
85
 
71
- There's an additional step if you want to use Xcode MCP server (requires Xcode 26.3+):
86
+ 4. Start the server: `xcode-copilot-server --proxy anthropic`
72
87
 
73
- 1. Open Xcode and go to Settings > Intelligence
74
- 2. Enable "Xcode Tools" under "Model Context Protocol"
88
+ The tool bridge is enabled by default in Anthropic mode (`toolBridge: true` in the config). It intercepts tool calls from the Copilot session and forwards them to Xcode, so Claude Agent can read files, search code, and make edits through the IDE.
75
89
 
76
90
  ### Agent skills
77
91
 
78
- The underlying Copilot CLI session can access and invoke [Agent skills](https://docs.github.com/en/copilot/customizing-copilot/extending-copilot-coding-agent-with-agent-skills), which are folders of instructions, scripts, and resources that improve Copilot's performance on specialised tasks. Skills which are stored in your repository (`.github/skills/` or `.claude/skills/`) and personal skills in your home directory (`~/.copilot/skills/` or `~/.claude/skills/`) are automatically available.
92
+ The underlying Copilot CLI session can access and invoke [Agent skills](https://docs.github.com/en/copilot/customizing-copilot/extending-copilot-coding-agent-with-agent-skills), which are folders of instructions, scripts, and resources that improve Copilot's performance on specialised tasks. Skills stored in your repository (`.github/skills/` or `.claude/skills/`) and personal skills in your home directory (`~/.copilot/skills/` or `~/.claude/skills/`) are automatically available.
79
93
 
80
94
  ## Configuration
81
95
 
@@ -85,21 +99,34 @@ The server reads its configuration from a `config.json5` file. By default, it us
85
99
  xcode-copilot-server --config ./my-config.json5
86
100
  ```
87
101
 
88
- The config file uses [JSON5](https://json5.org/) format, which supports comments and trailing commas:
102
+ The config file uses [JSON5](https://json5.org/) format, which supports comments and trailing commas. The `--proxy` flag determines which provider section (`openai` or `anthropic`) is used at runtime:
89
103
 
90
104
  ```json5
91
105
  {
92
- // MCP servers to register with the Copilot session.
93
- // The bundled config includes Xcode's mcpbridge by default.
94
- mcpServers: {
95
- xcode: {
96
- type: "local",
97
- command: "node",
98
- args: ["./scripts/mcpbridge-proxy.mjs"],
99
- allowedTools: ["*"],
106
+ openai: {
107
+ // No tool bridge needed, as Xcode drives tool execution directly.
108
+ toolBridge: false,
109
+
110
+ mcpServers: {
111
+ // Proxies Apple's xcrun mcpbridge (Xcode 26.3+).
112
+ xcode: {
113
+ type: "local",
114
+ command: "node",
115
+ args: ["./scripts/mcpbridge-proxy.mjs"],
116
+ allowedTools: ["*"],
117
+ },
100
118
  },
101
119
  },
102
120
 
121
+ anthropic: {
122
+ // Intercepts tool calls and forwards them to Xcode so Claude Agent
123
+ // can drive tool execution through the IDE.
124
+ toolBridge: true,
125
+
126
+ // No MCP servers needed, as Claude Agent handles tools natively.
127
+ mcpServers: {},
128
+ },
129
+
103
130
  // Built-in CLI tools allowlist.
104
131
  // ["*"] to allow all, [] to deny all, or a list of specific tool names.
105
132
  //
@@ -109,7 +136,7 @@ The config file uses [JSON5](https://json5.org/) format, which supports comments
109
136
  allowedCliTools: [],
110
137
 
111
138
  // Maximum request body size in MiB.
112
- bodyLimitMiB: 4,
139
+ bodyLimitMiB: 10,
113
140
 
114
141
  // Filename patterns to filter out from search results in the prompt.
115
142
  //
@@ -131,7 +158,7 @@ The config file uses [JSON5](https://json5.org/) format, which supports comments
131
158
 
132
159
  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:
133
160
 
134
- - 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.
161
+ - The server binds to `127.0.0.1`, so it's only reachable from your machine. Incoming requests are checked for expected user-agent headers (`Xcode/` in OpenAI mode, `claude-cli/` in Anthropic mode), 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 the expected client is talking to the server.
135
162
 
136
163
  - 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"`.
137
164
 
package/config.json5 CHANGED
@@ -1,60 +1,68 @@
1
1
  // Server configuration for xcode-copilot-server.
2
2
  // Edit this file to add MCP servers, control tool access, and set permissions.
3
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.
4
+ // Tool permissions are checked across all allowlists, so if the same tool name
5
+ // exists in both CLI and MCP tools then they can't have different permissions.
6
6
 
7
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: ["*"],
8
+ // Provider-specific settings. The active --proxy flag determines which
9
+ // section is used at runtime.
10
+
11
+ openai: {
12
+ // No tool bridge needed for OpenAI because Xcode drives tool execution
13
+ // directly. TODO: will need this for Codex Agent support.
14
+ toolBridge: false,
15
+
16
+ mcpServers: {
17
+ // Proxies Apple's xcrun mcpbridge (Xcode 26.3+). The script exits
18
+ // gracefully if mcpbridge isn't installed, so safe to leave enabled.
19
+ xcode: {
20
+ type: "local",
21
+ command: "node",
22
+ args: ["./scripts/mcpbridge-proxy.mjs"],
23
+ allowedTools: ["*"],
24
+ },
17
25
  },
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
  },
26
27
 
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
28
+ anthropic: {
29
+ // Normally the Copilot CLI executes tool calls (file reads, edits, etc.)
30
+ // on its own. This shim intercepts those calls and forwards them to Xcode
31
+ // so Claude Agent can drive tool execution through the IDE instead.
32
+ // Set to false or remove to disable the tool bridge.
33
+ toolBridge: true,
34
+
35
+ // No MCP servers needed, because Claude Agent handles tools natively.
36
+ mcpServers: {},
37
+ },
38
+
39
+ // Built-in Copilot CLI tools allowlist (glob, grep, bash, etc). Use ["*"] to allow
40
+ // all, [] to deny all, or list specific tools like ["glob", "grep"].
31
41
  //
32
- // This is empty by default because Xcode should be the one handling operations
33
- // like searching, reading, and editing files. The model tells Xcode what to
34
- // change and Xcode applies those changes through its own UI, keeping everything
35
- // in sync. If CLI tools are enabled, the Copilot session may perform those
36
- // operations itself (e.g. writing files via bash), bypassing Xcode and leaving
37
- // its UI out of sync with what actually happened on disk.
42
+ // This is empty by default because Xcode should be the one handling
43
+ // operations like searching, reading, and editing files. The model tells
44
+ // Xcode what to change and Xcode applies those changes through its own UI,
45
+ // keeping everything in sync. If CLI tools are enabled, the Copilot session
46
+ // may perform those operations itself (e.g. writing files via bash),
47
+ // bypassing Xcode and potentially leaving its UI out of sync with what actually
48
+ // happened on disk.
38
49
  allowedCliTools: [],
39
50
 
40
51
  // Maximum request body size in MiB.
41
- bodyLimitMiB: 4,
52
+ bodyLimitMiB: 10,
42
53
 
43
- // Filename patterns to filter out from search results in the prompt.
44
- // Code blocks whose filename contains any of these (case-insensitive) are stripped.
45
- //
46
- // Xcode's search results can include full file contents for every match, which can
47
- // bloat the prompt with irrelevant code. Add patterns here to strip those files
48
- // before they reach the model (e.g. ["mock", "generated"]).
54
+ // Filename patterns to filter out from search results in the prompt. Xcode's
55
+ // search results can include full file contents for every match, which can
56
+ // bloat the prompt with irrelevant code. Add patterns here to strip those
57
+ // files before they reach the model, e.g. ["mock", "generated"].
49
58
  excludedFilePatterns: [],
50
59
 
51
- // Reasoning effort for models that support it.
52
- // E.g: "low", "medium", "high", "xhigh"
60
+ // Reasoning effort for models that support it, e.g. "low", "medium", "high",
61
+ // "xhigh".
53
62
  reasoningEffort: "xhigh",
54
63
 
55
- // Auto-approve permission requests.
56
- // - true: approve all
57
- // - false: deny all
58
- // - ["read", "mcp"]: approve only listed kinds (e.g: "read", "write", "shell", "mcp", "url")
64
+ // Auto-approve permission requests. Set to true to approve all, false to deny
65
+ // all, or pass an array of specific kinds to approve, e.g.
66
+ // ["read", "write", "shell", "mcp", "url"].
59
67
  autoApprovePermissions: ["read", "mcp"],
60
68
  }
package/dist/config.d.ts CHANGED
@@ -1,7 +1,12 @@
1
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"> & {
2
+ import { type MCPServer, type RawServerConfig } from "./schemas/config.js";
3
+ export type { MCPLocalServer, MCPRemoteServer, MCPServer, ApprovalRule, ReasoningEffort, } from "./schemas/config.js";
4
+ export type ServerConfig = Omit<RawServerConfig, "bodyLimitMiB" | "openai" | "anthropic"> & {
5
+ toolBridge: boolean;
6
+ mcpServers: Record<string, MCPServer>;
5
7
  bodyLimit: number;
6
8
  };
7
- export declare function loadConfig(configPath: string, logger: Logger): Promise<ServerConfig>;
9
+ import type { ProxyName } from "./providers/index.js";
10
+ export type { ProxyName };
11
+ export declare function resolveConfigPath(projectCwd: string | undefined, processCwd: string, defaultPath: string): string;
12
+ export declare function loadConfig(configPath: string, logger: Logger, proxy: ProxyName): Promise<ServerConfig>;
package/dist/config.js CHANGED
@@ -2,12 +2,13 @@ import { existsSync } from "node:fs";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import { resolve, dirname, isAbsolute } from "node:path";
4
4
  import JSON5 from "json5";
5
- import { ServerConfigSchema, } from "./config-schema.js";
5
+ import { ServerConfigSchema, } from "./schemas/config.js";
6
6
  const DEFAULT_CONFIG = {
7
+ toolBridge: false,
7
8
  mcpServers: {},
8
9
  allowedCliTools: [],
9
10
  excludedFilePatterns: [],
10
- bodyLimit: 4 * 1024 * 1024, // 4 MiB
11
+ bodyLimit: 10 * 1024 * 1024, // 10 MiB
11
12
  autoApprovePermissions: ["read", "mcp"],
12
13
  };
13
14
  function resolveServerPaths(servers, configDir) {
@@ -23,7 +24,18 @@ function resolveServerPaths(servers, configDir) {
23
24
  : server,
24
25
  ]));
25
26
  }
26
- export async function loadConfig(configPath, logger) {
27
+ export function resolveConfigPath(projectCwd, processCwd, defaultPath) {
28
+ if (projectCwd) {
29
+ const projectConfig = resolve(projectCwd, "config.json5");
30
+ if (existsSync(projectConfig))
31
+ return projectConfig;
32
+ }
33
+ const localConfig = resolve(processCwd, "config.json5");
34
+ if (existsSync(localConfig))
35
+ return localConfig;
36
+ return defaultPath;
37
+ }
38
+ export async function loadConfig(configPath, logger, proxy) {
27
39
  const absolutePath = isAbsolute(configPath)
28
40
  ? configPath
29
41
  : resolve(process.cwd(), configPath);
@@ -52,11 +64,17 @@ export async function loadConfig(configPath, logger) {
52
64
  const path = firstError.path.join(".");
53
65
  throw new Error(`Invalid config${path ? ` at "${path}"` : ""}: ${firstError.message}`);
54
66
  }
55
- const { bodyLimitMiB, ...rest } = parseResult.data;
67
+ const configDir = dirname(absolutePath);
68
+ const parsed = parseResult.data;
69
+ const provider = parsed[proxy];
56
70
  const config = {
57
- ...rest,
58
- bodyLimit: bodyLimitMiB * 1024 * 1024,
59
- mcpServers: resolveServerPaths(parseResult.data.mcpServers, dirname(absolutePath)),
71
+ allowedCliTools: parsed.allowedCliTools,
72
+ excludedFilePatterns: parsed.excludedFilePatterns,
73
+ autoApprovePermissions: parsed.autoApprovePermissions,
74
+ reasoningEffort: parsed.reasoningEffort,
75
+ bodyLimit: parsed.bodyLimitMiB * 1024 * 1024,
76
+ toolBridge: provider.toolBridge,
77
+ mcpServers: resolveServerPaths(provider.mcpServers, configDir),
60
78
  };
61
79
  const cliToolsSummary = config.allowedCliTools.includes("*")
62
80
  ? "all CLI tools allowed"
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/context.d.ts CHANGED
@@ -5,4 +5,5 @@ export interface AppContext {
5
5
  service: CopilotService;
6
6
  logger: Logger;
7
7
  config: ServerConfig;
8
+ port: number;
8
9
  }
@@ -0,0 +1,32 @@
1
+ import type { CopilotSession } from "@github/copilot-sdk";
2
+ import { ToolBridgeState } from "./tool-bridge/state.js";
3
+ import type { AnthropicMessage } from "./schemas/anthropic.js";
4
+ import type { Logger } from "./logger.js";
5
+ export interface Conversation {
6
+ id: string;
7
+ state: ToolBridgeState;
8
+ session: CopilotSession | null;
9
+ sentMessageCount: number;
10
+ isPrimary: boolean;
11
+ model: string | null;
12
+ }
13
+ export declare class ConversationManager {
14
+ private readonly conversations;
15
+ private readonly logger;
16
+ private primaryId;
17
+ constructor(logger: Logger);
18
+ create(options?: {
19
+ isPrimary?: boolean;
20
+ }): Conversation;
21
+ getPrimary(): Conversation | null;
22
+ clearPrimary(): void;
23
+ findForNewRequest(): {
24
+ conversation: Conversation;
25
+ isReuse: boolean;
26
+ };
27
+ findByContinuation(messages: AnthropicMessage[]): Conversation | undefined;
28
+ findByExpectedTool(name: string): ToolBridgeState | undefined;
29
+ getState(convId: string): ToolBridgeState | undefined;
30
+ remove(convId: string): void;
31
+ get size(): number;
32
+ }
@@ -0,0 +1,120 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { ToolBridgeState } from "./tool-bridge/state.js";
3
+ export class ConversationManager {
4
+ conversations = new Map();
5
+ logger;
6
+ primaryId = null;
7
+ constructor(logger) {
8
+ this.logger = logger;
9
+ }
10
+ create(options) {
11
+ const id = randomUUID();
12
+ const isPrimary = options?.isPrimary ?? false;
13
+ const state = new ToolBridgeState();
14
+ const conversation = {
15
+ id,
16
+ state,
17
+ session: null,
18
+ sentMessageCount: 0,
19
+ isPrimary,
20
+ model: null,
21
+ };
22
+ this.conversations.set(id, conversation);
23
+ if (!isPrimary) {
24
+ state.onSessionEnd(() => {
25
+ this.logger.debug(`Conversation ${id} session ended, removing`);
26
+ this.conversations.delete(id);
27
+ });
28
+ }
29
+ if (isPrimary) {
30
+ this.primaryId = id;
31
+ }
32
+ this.logger.debug(`Created conversation ${id} (primary=${String(isPrimary)}, active: ${String(this.conversations.size)})`);
33
+ return conversation;
34
+ }
35
+ getPrimary() {
36
+ if (!this.primaryId)
37
+ return null;
38
+ return this.conversations.get(this.primaryId) ?? null;
39
+ }
40
+ clearPrimary() {
41
+ if (this.primaryId) {
42
+ const conv = this.conversations.get(this.primaryId);
43
+ if (conv) {
44
+ conv.state.cleanup();
45
+ this.conversations.delete(this.primaryId);
46
+ this.logger.debug(`Cleared primary conversation ${this.primaryId} (active: ${String(this.conversations.size)})`);
47
+ }
48
+ this.primaryId = null;
49
+ }
50
+ }
51
+ findForNewRequest() {
52
+ const primary = this.getPrimary();
53
+ if (primary) {
54
+ if (primary.state.sessionActive || !primary.session) {
55
+ this.logger.debug(`Primary ${primary.id} is unavailable, creating isolated conversation`);
56
+ return { conversation: this.create(), isReuse: false };
57
+ }
58
+ this.logger.debug(`Reusing primary conversation ${primary.id}`);
59
+ return { conversation: primary, isReuse: true };
60
+ }
61
+ return { conversation: this.create({ isPrimary: true }), isReuse: false };
62
+ }
63
+ findByContinuation(messages) {
64
+ const lastMsg = messages[messages.length - 1];
65
+ if (!lastMsg || lastMsg.role !== "user" || typeof lastMsg.content === "string") {
66
+ return undefined;
67
+ }
68
+ const toolUseIds = [];
69
+ for (const block of lastMsg.content) {
70
+ if (block.type === "tool_result") {
71
+ toolUseIds.push(block.tool_use_id);
72
+ }
73
+ }
74
+ if (toolUseIds.length === 0)
75
+ return undefined;
76
+ for (const [, conv] of this.conversations) {
77
+ for (const toolUseId of toolUseIds) {
78
+ if (conv.state.hasPendingToolCall(toolUseId)) {
79
+ this.logger.debug(`Continuation matched conversation ${conv.id} via tool_use_id ${toolUseId}`);
80
+ return conv;
81
+ }
82
+ }
83
+ }
84
+ // the model sometimes retries a tool after an internal failure so the
85
+ // tool_use_id won't match anything, but we can still route by session
86
+ for (const [, conv] of this.conversations) {
87
+ if (conv.state.sessionActive) {
88
+ this.logger.debug(`Continuation matched conversation ${conv.id} via sessionActive fallback`);
89
+ return conv;
90
+ }
91
+ }
92
+ return undefined;
93
+ }
94
+ findByExpectedTool(name) {
95
+ for (const [, conv] of this.conversations) {
96
+ if (conv.state.hasExpectedTool(name)) {
97
+ return conv.state;
98
+ }
99
+ }
100
+ return undefined;
101
+ }
102
+ getState(convId) {
103
+ return this.conversations.get(convId)?.state;
104
+ }
105
+ remove(convId) {
106
+ const conv = this.conversations.get(convId);
107
+ if (conv) {
108
+ conv.state.cleanup();
109
+ this.conversations.delete(convId);
110
+ if (convId === this.primaryId) {
111
+ this.primaryId = null;
112
+ }
113
+ this.logger.debug(`Removed conversation ${convId} (active: ${String(this.conversations.size)})`);
114
+ }
115
+ }
116
+ get size() {
117
+ return this.conversations.size;
118
+ }
119
+ }
120
+ //# sourceMappingURL=conversation-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-manager.js","sourceRoot":"","sources":["../src/conversation-manager.ts"],"names":[],"mappings":"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"}
@@ -8,13 +8,11 @@ export interface CopilotServiceOptions {
8
8
  export declare class CopilotService {
9
9
  readonly cwd: string;
10
10
  private client;
11
- private session;
12
- private sessionPromise;
13
11
  private logger;
14
12
  constructor(options?: CopilotServiceOptions);
15
13
  start(): Promise<void>;
16
14
  stop(): Promise<void>;
17
15
  getAuthStatus(): Promise<GetAuthStatusResponse>;
18
16
  listModels(): Promise<ModelInfo[]>;
19
- getSession(config: SessionConfig): Promise<CopilotSession>;
17
+ createSession(config: SessionConfig): Promise<CopilotSession>;
20
18
  }
@@ -2,8 +2,6 @@ import { CopilotClient, } from "@github/copilot-sdk";
2
2
  export class CopilotService {
3
3
  cwd;
4
4
  client;
5
- session = null;
6
- sessionPromise = null;
7
5
  logger;
8
6
  constructor(options = {}) {
9
7
  this.cwd = options.cwd ?? process.cwd();
@@ -18,11 +16,6 @@ export class CopilotService {
18
16
  await this.client.start();
19
17
  }
20
18
  async stop() {
21
- if (this.session) {
22
- await this.session.destroy();
23
- this.session = null;
24
- }
25
- this.sessionPromise = null;
26
19
  await this.client.stop();
27
20
  }
28
21
  async getAuthStatus() {
@@ -31,22 +24,9 @@ export class CopilotService {
31
24
  async listModels() {
32
25
  return this.client.listModels();
33
26
  }
34
- async getSession(config) {
35
- if (this.session) {
36
- return this.session;
37
- }
38
- if (!this.sessionPromise) {
39
- this.sessionPromise = this.client.createSession(config).then((s) => {
40
- this.session = s;
41
- this.sessionPromise = null;
42
- this.logger?.info("Session created");
43
- return s;
44
- }, (err) => {
45
- this.sessionPromise = null;
46
- throw err;
47
- });
48
- }
49
- return this.sessionPromise;
27
+ async createSession(config) {
28
+ this.logger?.info("Creating session");
29
+ return this.client.createSession(config);
50
30
  }
51
31
  }
52
32
  //# sourceMappingURL=copilot-service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"copilot-service.js","sourceRoot":"","sources":["../src/copilot-service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,GAKd,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,aAAa;QACjB,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;IACrC,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"}
1
+ {"version":3,"file":"copilot-service.js","sourceRoot":"","sources":["../src/copilot-service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,GAKd,MAAM,qBAAqB,CAAC;AAS7B,MAAM,OAAO,cAAc;IAChB,GAAG,CAAS;IACb,MAAM,CAAgB;IACtB,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,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,MAAqB;QACvC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;CACF"}
@@ -1,4 +1,4 @@
1
1
  import type { FastifyReply } from "fastify";
2
2
  import type { CopilotSession } from "@github/copilot-sdk";
3
3
  import type { Logger } from "../../logger.js";
4
- export declare function handleStreaming(reply: FastifyReply, session: CopilotSession, prompt: string, model: string, logger: Logger): Promise<void>;
4
+ export declare function handleStreaming(reply: FastifyReply, session: CopilotSession, prompt: string, model: string, logger: Logger): Promise<boolean>;