xcode-copilot-server 3.4.0 → 3.4.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.
- package/dist/banner.d.ts +4 -4
- package/dist/banner.js +45 -12
- package/dist/banner.js.map +1 -1
- package/dist/bridge-constants.d.ts +2 -0
- package/dist/bridge-constants.js +3 -0
- package/dist/bridge-constants.js.map +1 -0
- package/dist/cli-validators.d.ts +0 -1
- package/dist/cli-validators.js +2 -2
- package/dist/cli-validators.js.map +1 -1
- package/dist/config-schema.d.ts +107 -0
- package/dist/config-schema.js +53 -0
- package/dist/config-schema.js.map +1 -0
- package/dist/config.d.ts +3 -28
- package/dist/config.js +23 -62
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +1 -1
- package/dist/conversation-manager.d.ts +9 -4
- package/dist/conversation-manager.js +44 -61
- package/dist/conversation-manager.js.map +1 -1
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/launchd/agent.d.ts +5 -9
- package/dist/launchd/agent.js +13 -12
- package/dist/launchd/agent.js.map +1 -1
- package/dist/launchd/index.d.ts +3 -3
- package/dist/launchd/index.js +1 -1
- package/dist/launchd/index.js.map +1 -1
- package/dist/launchd/socket.d.ts +2 -1
- package/dist/providers/claude/provider.js +40 -64
- package/dist/providers/claude/provider.js.map +1 -1
- package/dist/providers/claude/streaming.d.ts +10 -1
- package/dist/providers/claude/streaming.js +7 -3
- package/dist/providers/claude/streaming.js.map +1 -1
- package/dist/providers/claude/tool-results.js +1 -1
- package/dist/providers/claude/tool-results.js.map +1 -1
- package/dist/providers/codex/provider.js +28 -60
- package/dist/providers/codex/provider.js.map +1 -1
- package/dist/providers/codex/streaming.d.ts +12 -3
- package/dist/providers/codex/streaming.js +6 -6
- package/dist/providers/codex/streaming.js.map +1 -1
- package/dist/providers/codex/tool-results.js +1 -1
- package/dist/providers/codex/tool-results.js.map +1 -1
- package/dist/providers/index.d.ts +4 -23
- package/dist/providers/index.js +1 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/names.d.ts +4 -0
- package/dist/providers/names.js +7 -0
- package/dist/providers/names.js.map +1 -0
- package/dist/providers/openai/provider.js +5 -14
- package/dist/providers/openai/provider.js.map +1 -1
- package/dist/providers/shared/continuation.d.ts +10 -0
- package/dist/providers/shared/continuation.js +18 -0
- package/dist/providers/shared/continuation.js.map +1 -0
- package/dist/providers/shared/prompt-utils.d.ts +0 -11
- package/dist/providers/shared/prompt-utils.js +0 -11
- package/dist/providers/shared/prompt-utils.js.map +1 -1
- package/dist/providers/shared/session-config.d.ts +12 -3
- package/dist/providers/shared/session-config.js +24 -7
- package/dist/providers/shared/session-config.js.map +1 -1
- package/dist/providers/shared/streaming-core.d.ts +12 -2
- package/dist/providers/shared/streaming-core.js +183 -161
- package/dist/providers/shared/streaming-core.js.map +1 -1
- package/dist/providers/shared/streaming-orchestrator.d.ts +11 -0
- package/dist/providers/shared/streaming-orchestrator.js +11 -0
- package/dist/providers/shared/streaming-orchestrator.js.map +1 -0
- package/dist/providers/shared/user-agent-guard.d.ts +3 -0
- package/dist/providers/shared/user-agent-guard.js +17 -0
- package/dist/providers/shared/user-agent-guard.js.map +1 -0
- package/dist/settings-patcher/claude.d.ts +1 -2
- package/dist/settings-patcher/claude.js +35 -13
- package/dist/settings-patcher/claude.js.map +1 -1
- package/dist/settings-patcher/codex.d.ts +1 -20
- package/dist/settings-patcher/codex.js +58 -31
- package/dist/settings-patcher/codex.js.map +1 -1
- package/dist/settings-patcher/index.d.ts +2 -15
- package/dist/settings-patcher/index.js +15 -36
- package/dist/settings-patcher/index.js.map +1 -1
- package/dist/settings-patcher/types.d.ts +21 -0
- package/dist/settings-patcher/url-utils.d.ts +1 -0
- package/dist/settings-patcher/url-utils.js +6 -0
- package/dist/settings-patcher/url-utils.js.map +1 -0
- package/dist/shutdown.d.ts +16 -0
- package/dist/shutdown.js +53 -0
- package/dist/shutdown.js.map +1 -0
- package/dist/startup.js +65 -139
- package/dist/startup.js.map +1 -1
- package/dist/tool-bridge/constants.d.ts +4 -2
- package/dist/tool-bridge/constants.js +4 -2
- package/dist/tool-bridge/constants.js.map +1 -1
- package/dist/tool-bridge/index.d.ts +2 -2
- package/dist/tool-bridge/index.js +6 -5
- package/dist/tool-bridge/index.js.map +1 -1
- package/dist/tool-bridge/routes.d.ts +2 -2
- package/dist/tool-bridge/routes.js +24 -22
- package/dist/tool-bridge/routes.js.map +1 -1
- package/dist/tool-bridge/session-lifecycle.js +6 -3
- package/dist/tool-bridge/session-lifecycle.js.map +1 -1
- package/dist/tool-bridge/state.d.ts +4 -25
- package/dist/tool-bridge/state.js +6 -65
- package/dist/tool-bridge/state.js.map +1 -1
- package/dist/tool-bridge/tool-router.d.ts +1 -0
- package/dist/tool-bridge/tool-router.js +26 -19
- package/dist/tool-bridge/tool-router.js.map +1 -1
- package/dist/utils/child-process.d.ts +2 -0
- package/dist/utils/child-process.js +8 -0
- package/dist/utils/child-process.js.map +1 -0
- package/dist/utils/type-guards.d.ts +2 -0
- package/dist/utils/type-guards.js +7 -0
- package/dist/utils/type-guards.js.map +1 -0
- package/package.json +1 -1
package/dist/startup.js
CHANGED
|
@@ -1,39 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
import { CopilotService, createServer, Logger, Stats, bold, dim, createSpinner, printUsageSummary, } from "copilot-sdk-proxy";
|
|
1
|
+
import { CopilotService, createServer, Logger, Stats, bold, dim, createSpinner, } from "copilot-sdk-proxy";
|
|
5
2
|
import { loadConfig, loadAllProviderConfigs, resolveConfigPath } from "./config.js";
|
|
6
3
|
import { providers, createAutoProvider } from "./providers/index.js";
|
|
7
|
-
import { patchSettings
|
|
4
|
+
import { patchSettings } from "./settings-patcher/index.js";
|
|
8
5
|
import { parsePort, parseLogLevel, parseProxyMode, parseIdleTimeout, validateAutoPatch, } from "./cli-validators.js";
|
|
9
6
|
import { activateSocket } from "./launchd/index.js";
|
|
10
7
|
import { printProxyBanner } from "./banner.js";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
claude: "claude",
|
|
14
|
-
codex: "codex",
|
|
15
|
-
};
|
|
16
|
-
function findAgentBinary(proxy) {
|
|
17
|
-
const binaryName = AGENT_BINARY_NAMES[proxy];
|
|
18
|
-
if (!binaryName)
|
|
19
|
-
return null;
|
|
20
|
-
if (!existsSync(AGENTS_DIR))
|
|
21
|
-
return null;
|
|
22
|
-
let versions;
|
|
23
|
-
try {
|
|
24
|
-
versions = readdirSync(AGENTS_DIR);
|
|
25
|
-
}
|
|
26
|
-
catch {
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
for (const version of versions) {
|
|
30
|
-
const binaryPath = join(AGENTS_DIR, version, binaryName);
|
|
31
|
-
if (existsSync(binaryPath))
|
|
32
|
-
return binaryPath;
|
|
33
|
-
}
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
export async function startServer(options) {
|
|
8
|
+
import { registerShutdownHandlers } from "./shutdown.js";
|
|
9
|
+
function parseOptions(options) {
|
|
37
10
|
const logLevel = parseLogLevel(options.logLevel);
|
|
38
11
|
const logger = new Logger(logLevel);
|
|
39
12
|
const port = parsePort(options.port);
|
|
@@ -48,28 +21,24 @@ export async function startServer(options) {
|
|
|
48
21
|
validateAutoPatch(proxyMode, options.autoPatch === true);
|
|
49
22
|
}
|
|
50
23
|
const configPath = options.config ?? resolveConfigPath(options.cwd, process.cwd(), options.defaultConfigPath);
|
|
51
|
-
const cwd = options.cwd;
|
|
52
|
-
let provider;
|
|
53
|
-
let config;
|
|
54
|
-
let allConfigs;
|
|
55
|
-
if (isAuto) {
|
|
56
|
-
allConfigs = await loadAllProviderConfigs(configPath, logger);
|
|
57
|
-
provider = createAutoProvider(allConfigs.providers);
|
|
58
|
-
config = allConfigs.shared;
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
config = await loadConfig(configPath, logger, proxyMode);
|
|
62
|
-
provider = providers[proxyMode];
|
|
63
|
-
}
|
|
64
|
-
const service = new CopilotService({
|
|
65
|
-
logLevel,
|
|
66
|
-
logger,
|
|
67
|
-
cwd,
|
|
68
|
-
});
|
|
69
24
|
const quiet = logLevel === "none" || launchdMode;
|
|
25
|
+
return { port, proxyMode, logLevel, logger, quiet, launchdMode, shouldPatch, idleTimeoutMinutes, configPath, cwd: options.cwd };
|
|
26
|
+
}
|
|
27
|
+
async function loadProvider(parsed) {
|
|
28
|
+
const { proxyMode, configPath, logger } = parsed;
|
|
29
|
+
if (proxyMode === "auto") {
|
|
30
|
+
const allConfigs = await loadAllProviderConfigs(configPath, logger);
|
|
31
|
+
return { provider: createAutoProvider(allConfigs.providers), config: allConfigs.shared, allConfigs };
|
|
32
|
+
}
|
|
33
|
+
const config = await loadConfig(configPath, logger, proxyMode);
|
|
34
|
+
return { provider: providers[proxyMode], config };
|
|
35
|
+
}
|
|
36
|
+
async function initializeService(parsed, version) {
|
|
37
|
+
const { logLevel, logger, quiet, cwd } = parsed;
|
|
38
|
+
const service = new CopilotService({ logLevel, logger, cwd });
|
|
70
39
|
if (!quiet) {
|
|
71
40
|
console.log();
|
|
72
|
-
console.log(` ${bold("xcode-copilot-server")} ${dim(`v${
|
|
41
|
+
console.log(` ${bold("xcode-copilot-server")} ${dim(`v${version}`)}`);
|
|
73
42
|
console.log();
|
|
74
43
|
}
|
|
75
44
|
const bootSpinner = quiet ? null : createSpinner("Initialising Copilot SDK...");
|
|
@@ -79,31 +48,16 @@ export async function startServer(options) {
|
|
|
79
48
|
const auth = await service.getAuthStatus();
|
|
80
49
|
if (!auth.isAuthenticated) {
|
|
81
50
|
authSpinner?.fail("Not authenticated");
|
|
82
|
-
logger.error("Sign in with the Copilot CLI (copilot login) or GitHub CLI (gh auth login), or set a GITHUB_TOKEN environment variable.");
|
|
83
51
|
await service.stop();
|
|
84
|
-
|
|
52
|
+
throw new Error("Not authenticated. Sign in with the Copilot CLI (copilot login) or GitHub CLI (gh auth login), or set a GITHUB_TOKEN environment variable.");
|
|
85
53
|
}
|
|
86
54
|
const login = auth.login ?? "unknown";
|
|
87
55
|
const authType = auth.authType ?? "unknown";
|
|
88
56
|
authSpinner?.succeed(`Authenticated as ${bold(login)} ${dim(`(${authType})`)}`);
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
patchSpinner?.succeed("Settings patched");
|
|
94
|
-
}
|
|
95
|
-
catch (err) {
|
|
96
|
-
patchSpinner?.fail(`Failed to patch settings: ${String(err)}`);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
const stats = new Stats();
|
|
100
|
-
const ctx = { service, logger, config, port, stats };
|
|
101
|
-
const app = await createServer(ctx, provider);
|
|
102
|
-
// Must register hooks before listen() because Fastify freezes the instance after that
|
|
103
|
-
let lastActivity = Date.now();
|
|
104
|
-
app.addHook("onResponse", () => {
|
|
105
|
-
lastActivity = Date.now();
|
|
106
|
-
});
|
|
57
|
+
return service;
|
|
58
|
+
}
|
|
59
|
+
async function bindAndListen(app, parsed) {
|
|
60
|
+
const { port, quiet, launchdMode, logger } = parsed;
|
|
107
61
|
const listenSpinner = quiet ? null : createSpinner(`Starting server on port ${String(port)}...`);
|
|
108
62
|
const prevPinoLevel = app.log.level;
|
|
109
63
|
app.log.level = "silent";
|
|
@@ -113,39 +67,27 @@ export async function startServer(options) {
|
|
|
113
67
|
if (fd === undefined) {
|
|
114
68
|
throw new Error("launch_activate_socket returned no file descriptors");
|
|
115
69
|
}
|
|
116
|
-
// TODO: Remove cast when Fastify types add fd support
|
|
117
|
-
// @ts-expect-error Fastify supports listen({ fd }) at runtime but the types don't include it yet
|
|
118
70
|
await app.listen({ fd });
|
|
119
71
|
logger.info(`Listening via launchd socket activation (fd ${String(fd)}, port ${String(port)})`);
|
|
120
72
|
}
|
|
121
73
|
else {
|
|
74
|
+
// 127.0.0.1 binding is the auth boundary. Only local processes can reach the server.
|
|
122
75
|
await app.listen({ port, host: "127.0.0.1" });
|
|
123
76
|
}
|
|
124
77
|
app.log.level = prevPinoLevel;
|
|
125
78
|
listenSpinner?.succeed(`Listening on ${bold(`http://localhost:${String(port)}`)}`);
|
|
79
|
+
}
|
|
80
|
+
function printBanner(parsed, provider, service, config, allConfigs) {
|
|
81
|
+
const { proxyMode, shouldPatch, quiet, configPath, logger } = parsed;
|
|
126
82
|
if (!quiet) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
else {
|
|
137
|
-
const binaryName = AGENT_BINARY_NAMES[proxyMode];
|
|
138
|
-
printProxyBanner({
|
|
139
|
-
providerName: provider.name,
|
|
140
|
-
proxyFlag: proxyMode,
|
|
141
|
-
routes: provider.routes,
|
|
142
|
-
cwd: service.cwd,
|
|
143
|
-
autoPatch: shouldPatch,
|
|
144
|
-
agentPath: binaryName ? findAgentBinary(proxyMode) : undefined,
|
|
145
|
-
agentBinaryName: binaryName,
|
|
146
|
-
agentsDir: AGENTS_DIR,
|
|
147
|
-
});
|
|
148
|
-
}
|
|
83
|
+
printProxyBanner({
|
|
84
|
+
providerName: proxyMode === "auto" ? "Auto" : provider.name,
|
|
85
|
+
proxyFlag: proxyMode === "auto" ? "auto" : proxyMode,
|
|
86
|
+
routes: provider.routes,
|
|
87
|
+
cwd: service.cwd,
|
|
88
|
+
autoPatch: shouldPatch,
|
|
89
|
+
logger,
|
|
90
|
+
});
|
|
149
91
|
}
|
|
150
92
|
logger.debug(`Config loaded from ${configPath}`);
|
|
151
93
|
const mcpCount = allConfigs
|
|
@@ -155,53 +97,37 @@ export async function startServer(options) {
|
|
|
155
97
|
? "all CLI tools allowed"
|
|
156
98
|
: `${String(config.allowedCliTools.length)} allowed CLI tool(s)`;
|
|
157
99
|
logger.debug(`${String(mcpCount)} MCP server(s), ${cliToolsSummary}`);
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
100
|
+
}
|
|
101
|
+
export async function startServer(options) {
|
|
102
|
+
const parsed = parseOptions(options);
|
|
103
|
+
const { port, proxyMode, logger, shouldPatch, quiet } = parsed;
|
|
104
|
+
const { provider, config, allConfigs } = await loadProvider(parsed);
|
|
105
|
+
const service = await initializeService(parsed, options.version);
|
|
106
|
+
if (shouldPatch) {
|
|
107
|
+
const patchSpinner = quiet ? null : createSpinner("Patching settings...");
|
|
108
|
+
try {
|
|
109
|
+
await patchSettings(proxyMode, port, logger);
|
|
110
|
+
patchSpinner?.succeed("Settings patched");
|
|
166
111
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
logger.
|
|
170
|
-
});
|
|
171
|
-
const timeoutPromise = new Promise((resolve) => setTimeout(() => {
|
|
172
|
-
logger.warn("Copilot client didn't stop in time, forcing exit");
|
|
173
|
-
resolve();
|
|
174
|
-
}, 3000));
|
|
175
|
-
await Promise.race([stopPromise, timeoutPromise]);
|
|
176
|
-
if (!quiet) {
|
|
177
|
-
printUsageSummary(stats.snapshot());
|
|
112
|
+
catch (err) {
|
|
113
|
+
patchSpinner?.fail(`Failed to patch settings: ${String(err)}`);
|
|
114
|
+
logger.warn(`Settings patching failed (continuing without patch): ${String(err)}`);
|
|
178
115
|
}
|
|
179
|
-
process.exit(0);
|
|
180
|
-
};
|
|
181
|
-
let shuttingDown = false;
|
|
182
|
-
const onSignal = (signal) => {
|
|
183
|
-
if (shuttingDown)
|
|
184
|
-
return;
|
|
185
|
-
shuttingDown = true;
|
|
186
|
-
shutdown(signal).catch((err) => {
|
|
187
|
-
console.error("Shutdown error:", err);
|
|
188
|
-
process.exit(1);
|
|
189
|
-
});
|
|
190
|
-
};
|
|
191
|
-
process.on("SIGINT", () => { onSignal("SIGINT"); });
|
|
192
|
-
process.on("SIGTERM", () => { onSignal("SIGTERM"); });
|
|
193
|
-
if (idleTimeoutMinutes > 0) {
|
|
194
|
-
const idleMs = idleTimeoutMinutes * 60_000;
|
|
195
|
-
const checkInterval = Math.min(idleMs, 60_000);
|
|
196
|
-
const timer = setInterval(() => {
|
|
197
|
-
if (Date.now() - lastActivity >= idleMs) {
|
|
198
|
-
clearInterval(timer);
|
|
199
|
-
logger.info(`Idle for ${String(idleTimeoutMinutes)} minute(s), shutting down`);
|
|
200
|
-
onSignal("idle-timeout");
|
|
201
|
-
}
|
|
202
|
-
}, checkInterval);
|
|
203
|
-
// Don't let the timer alone keep the process alive
|
|
204
|
-
timer.unref();
|
|
205
116
|
}
|
|
117
|
+
const stats = new Stats();
|
|
118
|
+
const ctx = { service, logger, config, port, stats };
|
|
119
|
+
const app = await createServer(ctx, provider);
|
|
120
|
+
let lastActivity = Date.now();
|
|
121
|
+
app.addHook("onResponse", () => {
|
|
122
|
+
lastActivity = Date.now();
|
|
123
|
+
});
|
|
124
|
+
await bindAndListen(app, parsed);
|
|
125
|
+
printBanner(parsed, provider, service, config, allConfigs);
|
|
126
|
+
registerShutdownHandlers({
|
|
127
|
+
app, service, logger, stats,
|
|
128
|
+
shouldPatch, proxyMode, quiet,
|
|
129
|
+
lastActivityRef: () => lastActivity,
|
|
130
|
+
idleTimeoutMinutes: parsed.idleTimeoutMinutes,
|
|
131
|
+
});
|
|
206
132
|
}
|
|
207
133
|
//# sourceMappingURL=startup.js.map
|
package/dist/startup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"startup.js","sourceRoot":"","sources":["../src/startup.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"startup.js","sourceRoot":"","sources":["../src/startup.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
export declare const
|
|
1
|
+
export declare const JSONRPC_PARSE_ERROR = -32700;
|
|
2
|
+
export declare const JSONRPC_INVALID_PARAMS = -32602;
|
|
3
|
+
export declare const JSONRPC_METHOD_NOT_FOUND = -32601;
|
|
4
|
+
export declare const JSONRPC_INTERNAL_ERROR = -32603;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
export const
|
|
2
|
-
export const
|
|
1
|
+
export const JSONRPC_PARSE_ERROR = -32700;
|
|
2
|
+
export const JSONRPC_INVALID_PARAMS = -32602;
|
|
3
|
+
export const JSONRPC_METHOD_NOT_FOUND = -32601;
|
|
4
|
+
export const JSONRPC_INTERNAL_ERROR = -32603;
|
|
3
5
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/tool-bridge/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/tool-bridge/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAK,CAAC;AAC1C,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,KAAK,CAAC;AAC7C,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,KAAK,CAAC;AAC/C,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,KAAK,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { FastifyInstance } from "fastify";
|
|
2
2
|
import type { Logger } from "copilot-sdk-proxy";
|
|
3
3
|
import { ConversationManager } from "../conversation-manager.js";
|
|
4
|
-
export { BRIDGE_SERVER_NAME, BRIDGE_TOOL_PREFIX } from "
|
|
5
|
-
export declare function registerToolBridgeRoutes(app: FastifyInstance, manager: ConversationManager, logger: Logger): void;
|
|
4
|
+
export { BRIDGE_SERVER_NAME, BRIDGE_TOOL_PREFIX } from "../bridge-constants.js";
|
|
6
5
|
export declare function registerToolBridge(app: FastifyInstance, logger: Logger): ConversationManager;
|
|
6
|
+
export declare function resolveToolBridgeManager(app: FastifyInstance, existing: ConversationManager | undefined, logger: Logger): ConversationManager;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { ConversationManager } from "../conversation-manager.js";
|
|
2
2
|
import { registerRoutes } from "./routes.js";
|
|
3
|
-
export { BRIDGE_SERVER_NAME, BRIDGE_TOOL_PREFIX } from "
|
|
4
|
-
export function registerToolBridgeRoutes(app, manager, logger) {
|
|
5
|
-
registerRoutes(app, manager, logger);
|
|
6
|
-
}
|
|
3
|
+
export { BRIDGE_SERVER_NAME, BRIDGE_TOOL_PREFIX } from "../bridge-constants.js";
|
|
7
4
|
export function registerToolBridge(app, logger) {
|
|
8
5
|
const manager = new ConversationManager(logger);
|
|
9
|
-
|
|
6
|
+
registerRoutes(app, manager, logger);
|
|
10
7
|
return manager;
|
|
11
8
|
}
|
|
9
|
+
// Auto mode uses a shared manager; standalone mode creates one per provider.
|
|
10
|
+
export function resolveToolBridgeManager(app, existing, logger) {
|
|
11
|
+
return existing ?? registerToolBridge(app, logger);
|
|
12
|
+
}
|
|
12
13
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tool-bridge/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tool-bridge/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEhF,MAAM,UAAU,kBAAkB,CAAC,GAAoB,EAAE,MAAc;IACrE,MAAM,OAAO,GAAG,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAChD,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,wBAAwB,CACtC,GAAoB,EACpB,QAAyC,EACzC,MAAc;IAEd,OAAO,QAAQ,IAAI,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AACrD,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { FastifyInstance } from "fastify";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ToolStateProvider } from "../conversation-manager.js";
|
|
3
3
|
import type { Logger } from "copilot-sdk-proxy";
|
|
4
|
-
export declare function registerRoutes(app: FastifyInstance,
|
|
4
|
+
export declare function registerRoutes(app: FastifyInstance, stateProvider: ToolStateProvider, logger: Logger): void;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { BRIDGE_SERVER_NAME } from "
|
|
2
|
+
import { BRIDGE_SERVER_NAME } from "../bridge-constants.js";
|
|
3
|
+
import { isRecord } from "../utils/type-guards.js";
|
|
4
|
+
import { JSONRPC_PARSE_ERROR, JSONRPC_INVALID_PARAMS, JSONRPC_METHOD_NOT_FOUND, JSONRPC_INTERNAL_ERROR, } from "./constants.js";
|
|
3
5
|
const JsonRpcRequestSchema = z.object({
|
|
4
6
|
jsonrpc: z.literal("2.0"),
|
|
5
7
|
id: z.union([z.number(), z.string()]).optional(),
|
|
@@ -14,17 +16,14 @@ function jsonRpcError(id, code, message) {
|
|
|
14
16
|
}
|
|
15
17
|
// Pinned to the version the Copilot SDK's MCP client actually speaks
|
|
16
18
|
const PROTOCOL_VERSION = "2024-11-05";
|
|
17
|
-
// Xcode
|
|
18
|
-
//
|
|
19
|
-
// the model as "xcode-bridge-mcp__xcode-tools__XcodeRead" which is ugly
|
|
20
|
-
// and wastes tokens.
|
|
19
|
+
// Strip Xcode's MCP prefix so the model sees clean tool names instead of
|
|
20
|
+
// double-prefixed ones like "xcode-bridge-mcp__xcode-tools__XcodeRead".
|
|
21
21
|
const MCP_TOOL_PREFIX = /^mcp__[^_]+__/;
|
|
22
22
|
function stripMCPToolPrefix(name) {
|
|
23
23
|
return name.replace(MCP_TOOL_PREFIX, "");
|
|
24
24
|
}
|
|
25
|
-
export function registerRoutes(app,
|
|
26
|
-
// The SDK opens
|
|
27
|
-
// messages. We don't push anything, so we just keep it open.
|
|
25
|
+
export function registerRoutes(app, stateProvider, logger) {
|
|
26
|
+
// The SDK opens this SSE stream after initialize. We don't push anything, just keep it open.
|
|
28
27
|
app.get("/mcp/:convId", (request, reply) => {
|
|
29
28
|
const { convId } = request.params;
|
|
30
29
|
logger.debug(`MCP ${convId}: SSE stream opened`);
|
|
@@ -41,12 +40,12 @@ export function registerRoutes(app, manager, logger) {
|
|
|
41
40
|
const { convId } = request.params;
|
|
42
41
|
const parsed = JsonRpcRequestSchema.safeParse(request.body);
|
|
43
42
|
if (!parsed.success) {
|
|
44
|
-
return reply.send(jsonRpcError(
|
|
43
|
+
return reply.send(jsonRpcError(null, JSONRPC_PARSE_ERROR, "Parse error"));
|
|
45
44
|
}
|
|
46
45
|
const msg = parsed.data;
|
|
47
46
|
logger.debug(`MCP ${convId}: method="${msg.method}", id=${String(msg.id)}`);
|
|
48
|
-
// JSON-RPC notifications have no id, so there's nothing to respond to
|
|
49
47
|
if (msg.id === undefined) {
|
|
48
|
+
logger.debug(`MCP ${convId}: notification method="${msg.method}", ignoring`);
|
|
50
49
|
return reply.status(202).send();
|
|
51
50
|
}
|
|
52
51
|
const { id, method, params } = msg;
|
|
@@ -58,12 +57,12 @@ export function registerRoutes(app, manager, logger) {
|
|
|
58
57
|
serverInfo: { name: BRIDGE_SERVER_NAME, version: "1.0.0" },
|
|
59
58
|
}));
|
|
60
59
|
case "tools/list": {
|
|
61
|
-
const state =
|
|
60
|
+
const state = stateProvider.getState(convId);
|
|
62
61
|
if (!state) {
|
|
63
62
|
logger.warn(`MCP ${convId} tools/list: conversation not found`);
|
|
64
|
-
return reply.send(jsonRpcError(id,
|
|
63
|
+
return reply.send(jsonRpcError(id, JSONRPC_INTERNAL_ERROR, "Conversation not found"));
|
|
65
64
|
}
|
|
66
|
-
const tools = state.getCachedTools().map((t) => ({
|
|
65
|
+
const tools = state.toolCache.getCachedTools().map((t) => ({
|
|
67
66
|
name: stripMCPToolPrefix(t.name),
|
|
68
67
|
description: t.description,
|
|
69
68
|
inputSchema: t.input_schema,
|
|
@@ -72,17 +71,19 @@ export function registerRoutes(app, manager, logger) {
|
|
|
72
71
|
return reply.send(jsonRpcResult(id, { tools }));
|
|
73
72
|
}
|
|
74
73
|
case "tools/call": {
|
|
75
|
-
const state =
|
|
74
|
+
const state = stateProvider.getState(convId);
|
|
76
75
|
if (!state) {
|
|
77
76
|
logger.warn(`MCP ${convId} tools/call: conversation not found`);
|
|
78
|
-
return reply.send(jsonRpcError(id,
|
|
77
|
+
return reply.send(jsonRpcError(id, JSONRPC_INTERNAL_ERROR, "Conversation not found"));
|
|
79
78
|
}
|
|
80
|
-
const
|
|
81
|
-
const
|
|
79
|
+
const rawName = params?.["name"];
|
|
80
|
+
const name = typeof rawName === "string" ? rawName : undefined;
|
|
81
|
+
const rawArgs = params?.["arguments"];
|
|
82
|
+
const args = isRecord(rawArgs) ? rawArgs : {};
|
|
82
83
|
if (!name) {
|
|
83
|
-
return reply.send(jsonRpcError(id,
|
|
84
|
+
return reply.send(jsonRpcError(id, JSONRPC_INVALID_PARAMS, "Missing tool name"));
|
|
84
85
|
}
|
|
85
|
-
const resolved = state.resolveToolName(name);
|
|
86
|
+
const resolved = state.toolCache.resolveToolName(name);
|
|
86
87
|
if (resolved !== name) {
|
|
87
88
|
logger.info(`MCP ${convId} tools/call: name="${name}" resolved to "${resolved}", args=${JSON.stringify(args)}`);
|
|
88
89
|
}
|
|
@@ -91,7 +92,7 @@ export function registerRoutes(app, manager, logger) {
|
|
|
91
92
|
}
|
|
92
93
|
try {
|
|
93
94
|
const result = await new Promise((resolve, reject) => {
|
|
94
|
-
state.registerMCPRequest(resolved, resolve, reject);
|
|
95
|
+
state.toolRouter.registerMCPRequest(resolved, resolve, reject);
|
|
95
96
|
});
|
|
96
97
|
logger.info(`MCP ${convId} tools/call resolved: name="${name}"`);
|
|
97
98
|
return await reply.send(jsonRpcResult(id, {
|
|
@@ -99,13 +100,14 @@ export function registerRoutes(app, manager, logger) {
|
|
|
99
100
|
}));
|
|
100
101
|
}
|
|
101
102
|
catch (err) {
|
|
103
|
+
logger.debug(`MCP ${convId} tools/call error details:`, err);
|
|
102
104
|
const message = err instanceof Error ? err.message : String(err);
|
|
103
105
|
logger.error(`MCP ${convId} tools/call error: ${message}`);
|
|
104
|
-
return reply.send(jsonRpcError(id,
|
|
106
|
+
return reply.send(jsonRpcError(id, JSONRPC_INTERNAL_ERROR, message));
|
|
105
107
|
}
|
|
106
108
|
}
|
|
107
109
|
default:
|
|
108
|
-
return reply.send(jsonRpcError(id,
|
|
110
|
+
return reply.send(jsonRpcError(id, JSONRPC_METHOD_NOT_FOUND, `Method not found: ${method}`));
|
|
109
111
|
}
|
|
110
112
|
});
|
|
111
113
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/tool-bridge/routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/tool-bridge/routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,9 @@ export class SessionLifecycle {
|
|
|
13
13
|
return this._hadError;
|
|
14
14
|
}
|
|
15
15
|
markSessionActive() {
|
|
16
|
+
// Clear leftover entries from abandoned tool cycles so they don't
|
|
17
|
+
// sit at the front of the FIFO queue and bind to wrong call IDs.
|
|
18
|
+
this.toolRouter.rejectAll("New session cycle");
|
|
16
19
|
this._sessionActive = true;
|
|
17
20
|
}
|
|
18
21
|
markSessionErrored() {
|
|
@@ -23,9 +26,9 @@ export class SessionLifecycle {
|
|
|
23
26
|
}
|
|
24
27
|
markSessionInactive() {
|
|
25
28
|
this._sessionActive = false;
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
+
// Don't reject expected entries here. handler-core's finally block
|
|
30
|
+
// calls this before the MCP tools/call request arrives, so rejecting
|
|
31
|
+
// would wipe entries the bridge still needs. cleanup() handles that.
|
|
29
32
|
this.fireSessionEnd();
|
|
30
33
|
}
|
|
31
34
|
cleanup() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-lifecycle.js","sourceRoot":"","sources":["../../src/tool-bridge/session-lifecycle.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,gBAAgB;IACV,UAAU,CAAa;IAChC,cAAc,GAAG,KAAK,CAAC;IACvB,SAAS,GAAG,KAAK,CAAC;IAClB,aAAa,GAAwB,IAAI,CAAC;IAElD,YAAY,UAAsB;QAChC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;IAC7B,CAAC;IAED,kBAAkB;QAChB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,YAAY,CAAC,QAAoB;QAC/B,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;IAChC,CAAC;IAED,mBAAmB;QACjB,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"session-lifecycle.js","sourceRoot":"","sources":["../../src/tool-bridge/session-lifecycle.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,gBAAgB;IACV,UAAU,CAAa;IAChC,cAAc,GAAG,KAAK,CAAC;IACvB,SAAS,GAAG,KAAK,CAAC;IAClB,aAAa,GAAwB,IAAI,CAAC;IAElD,YAAY,UAAsB;QAChC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,iBAAiB;QACf,kEAAkE;QAClE,iEAAiE;QACjE,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;QAC/C,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;IAC7B,CAAC;IAED,kBAAkB;QAChB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,YAAY,CAAC,QAAoB;QAC/B,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;IAChC,CAAC;IAED,mBAAmB;QACjB,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;QAC5B,mEAAmE;QACnE,qEAAqE;QACrE,qEAAqE;QACrE,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAED,OAAO;QACL,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;QAC5B,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAC7C,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAEO,cAAc;QACpB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC5B,CAAC;IACH,CAAC;CACF"}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { FastifyReply } from "fastify";
|
|
2
|
-
import type { AnthropicToolDefinition } from "copilot-sdk-proxy";
|
|
3
1
|
import { ToolCache } from "./tool-cache.js";
|
|
4
2
|
import { ToolRouter } from "./tool-router.js";
|
|
5
3
|
import { ReplyTracker } from "./reply-tracker.js";
|
|
@@ -7,28 +5,9 @@ import { SessionLifecycle } from "./session-lifecycle.js";
|
|
|
7
5
|
export declare class ToolBridgeState {
|
|
8
6
|
readonly toolCache: ToolCache;
|
|
9
7
|
readonly toolRouter: ToolRouter;
|
|
10
|
-
readonly
|
|
8
|
+
readonly replies: ReplyTracker;
|
|
11
9
|
readonly session: SessionLifecycle;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
normalizeArgs(toolName: string, args: Record<string, unknown>): Record<string, unknown>;
|
|
16
|
-
hasPendingToolCall(toolCallId: string): boolean;
|
|
17
|
-
hasExpectedTool(name: string): boolean;
|
|
18
|
-
registerExpected(toolCallId: string, toolName: string): void;
|
|
19
|
-
registerMCPRequest(name: string, resolve: (result: string) => void, reject: (err: Error) => void): void;
|
|
20
|
-
resolveToolCall(toolCallId: string, result: string): boolean;
|
|
21
|
-
get hasPending(): boolean;
|
|
22
|
-
get currentReply(): FastifyReply | null;
|
|
23
|
-
setReply(reply: FastifyReply): void;
|
|
24
|
-
clearReply(): void;
|
|
25
|
-
notifyStreamingDone(): void;
|
|
26
|
-
waitForStreamingDone(): Promise<void>;
|
|
27
|
-
get sessionActive(): boolean;
|
|
28
|
-
get hadError(): boolean;
|
|
29
|
-
markSessionActive(): void;
|
|
30
|
-
markSessionErrored(): void;
|
|
31
|
-
markSessionInactive(): void;
|
|
32
|
-
onSessionEnd(callback: () => void): void;
|
|
33
|
-
cleanup(): void;
|
|
10
|
+
private _filteredTools;
|
|
11
|
+
get filteredTools(): unknown[] | undefined;
|
|
12
|
+
setFilteredTools(tools: unknown[]): void;
|
|
34
13
|
}
|