xcode-copilot-server 2.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -29
- package/config.json5 +13 -8
- package/dist/cli-validators.d.ts +6 -0
- package/dist/cli-validators.js +35 -0
- package/dist/cli-validators.js.map +1 -0
- package/dist/config.d.ts +3 -3
- package/dist/config.js +11 -10
- package/dist/config.js.map +1 -1
- package/dist/conversation-manager.d.ts +2 -1
- package/dist/conversation-manager.js +20 -1
- package/dist/conversation-manager.js.map +1 -1
- package/dist/handlers/responses/streaming.d.ts +6 -0
- package/dist/handlers/responses/streaming.js +265 -0
- package/dist/handlers/responses/streaming.js.map +1 -0
- package/dist/handlers/responses/tool-result-handler.d.ts +4 -0
- package/dist/handlers/responses/tool-result-handler.js +9 -0
- package/dist/handlers/responses/tool-result-handler.js.map +1 -0
- package/dist/handlers/responses.d.ts +4 -0
- package/dist/handlers/responses.js +164 -0
- package/dist/handlers/responses.js.map +1 -0
- package/dist/handlers/streaming-utils.d.ts +1 -0
- package/dist/handlers/streaming-utils.js +3 -0
- package/dist/handlers/streaming-utils.js.map +1 -1
- package/dist/index.js +51 -132
- package/dist/index.js.map +1 -1
- package/dist/logger.js +15 -4
- package/dist/logger.js.map +1 -1
- package/dist/providers/claude/count-tokens.d.ts +3 -0
- package/dist/providers/claude/count-tokens.js +72 -0
- package/dist/providers/claude/count-tokens.js.map +1 -0
- package/dist/providers/claude/handler.d.ts +4 -0
- package/dist/providers/claude/handler.js +150 -0
- package/dist/providers/claude/handler.js.map +1 -0
- package/dist/providers/claude/prompt.d.ts +2 -0
- package/dist/providers/claude/prompt.js +52 -0
- package/dist/providers/claude/prompt.js.map +1 -0
- package/dist/providers/claude/provider.d.ts +5 -0
- package/dist/providers/claude/provider.js +28 -0
- package/dist/providers/claude/provider.js.map +1 -0
- package/dist/providers/claude/schemas.d.ts +140 -0
- package/dist/providers/claude/schemas.js +58 -0
- package/dist/providers/claude/schemas.js.map +1 -0
- package/dist/providers/claude/streaming.d.ts +6 -0
- package/dist/providers/claude/streaming.js +116 -0
- package/dist/providers/claude/streaming.js.map +1 -0
- package/dist/providers/claude/tool-results.d.ts +4 -0
- package/dist/providers/claude/tool-results.js +19 -0
- package/dist/providers/claude/tool-results.js.map +1 -0
- package/dist/providers/codex/handler.d.ts +4 -0
- package/dist/providers/codex/handler.js +164 -0
- package/dist/providers/codex/handler.js.map +1 -0
- package/dist/providers/codex/prompt.d.ts +4 -0
- package/dist/providers/codex/prompt.js +58 -0
- package/dist/providers/codex/prompt.js.map +1 -0
- package/dist/providers/codex/provider.d.ts +5 -0
- package/dist/providers/codex/provider.js +24 -0
- package/dist/providers/codex/provider.js.map +1 -0
- package/dist/providers/codex/schemas.d.ts +122 -0
- package/dist/providers/codex/schemas.js +55 -0
- package/dist/providers/codex/schemas.js.map +1 -0
- package/dist/providers/codex/streaming.d.ts +9 -0
- package/dist/providers/codex/streaming.js +172 -0
- package/dist/providers/codex/streaming.js.map +1 -0
- package/dist/providers/codex/tool-results.d.ts +4 -0
- package/dist/providers/codex/tool-results.js +9 -0
- package/dist/providers/codex/tool-results.js.map +1 -0
- package/dist/providers/codex.d.ts +5 -0
- package/dist/providers/codex.js +24 -0
- package/dist/providers/codex.js.map +1 -0
- package/dist/providers/index.d.ts +6 -1
- package/dist/providers/index.js +5 -3
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/openai/handler.d.ts +4 -0
- package/dist/providers/openai/handler.js +120 -0
- package/dist/providers/openai/handler.js.map +1 -0
- package/dist/providers/openai/models.d.ts +3 -0
- package/dist/providers/openai/models.js +28 -0
- package/dist/providers/openai/models.js.map +1 -0
- package/dist/providers/openai/prompt.d.ts +3 -0
- package/dist/providers/openai/prompt.js +38 -0
- package/dist/providers/openai/prompt.js.map +1 -0
- package/dist/providers/openai/provider.d.ts +5 -0
- package/dist/providers/openai/provider.js +25 -0
- package/dist/providers/openai/provider.js.map +1 -0
- package/dist/providers/openai/schemas.d.ts +98 -0
- package/dist/providers/openai/schemas.js +76 -0
- package/dist/providers/openai/schemas.js.map +1 -0
- package/dist/providers/openai/streaming.d.ts +4 -0
- package/dist/providers/openai/streaming.js +121 -0
- package/dist/providers/openai/streaming.js.map +1 -0
- package/dist/providers/shared/errors.d.ts +5 -0
- package/dist/providers/shared/errors.js +10 -0
- package/dist/providers/shared/errors.js.map +1 -0
- package/dist/providers/shared/model-resolver.d.ts +3 -0
- package/dist/providers/shared/model-resolver.js +45 -0
- package/dist/providers/shared/model-resolver.js.map +1 -0
- package/dist/providers/shared/prompt-utils.d.ts +1 -0
- package/dist/providers/shared/prompt-utils.js +15 -0
- package/dist/providers/shared/prompt-utils.js.map +1 -0
- package/dist/providers/shared/session-config.d.ts +15 -0
- package/dist/providers/shared/session-config.js +98 -0
- package/dist/providers/shared/session-config.js.map +1 -0
- package/dist/providers/shared/streaming-core.d.ts +19 -0
- package/dist/providers/shared/streaming-core.js +176 -0
- package/dist/providers/shared/streaming-core.js.map +1 -0
- package/dist/providers/shared/streaming-utils.d.ts +10 -0
- package/dist/providers/shared/streaming-utils.js +28 -0
- package/dist/providers/shared/streaming-utils.js.map +1 -0
- package/dist/schemas/config.d.ts +19 -1
- package/dist/schemas/config.js +2 -1
- package/dist/schemas/config.js.map +1 -1
- package/dist/schemas/responses.d.ts +122 -0
- package/dist/schemas/responses.js +54 -0
- package/dist/schemas/responses.js.map +1 -0
- package/dist/server.js +1 -2
- package/dist/server.js.map +1 -1
- package/dist/settings-patcher/anthropic.d.ts +5 -0
- package/dist/{settings-patcher.js → settings-patcher/anthropic.js} +3 -7
- package/dist/settings-patcher/anthropic.js.map +1 -0
- package/dist/settings-patcher/claude.d.ts +5 -0
- package/dist/settings-patcher/claude.js +75 -0
- package/dist/settings-patcher/claude.js.map +1 -0
- package/dist/settings-patcher/codex.d.ts +23 -0
- package/dist/settings-patcher/codex.js +114 -0
- package/dist/settings-patcher/codex.js.map +1 -0
- package/dist/settings-patcher/index.d.ts +15 -0
- package/dist/settings-patcher/index.js +9 -0
- package/dist/settings-patcher/index.js.map +1 -0
- package/dist/{settings-patcher.d.ts → settings-patcher/types.d.ts} +1 -5
- package/dist/settings-patcher/types.js +2 -0
- package/dist/settings-patcher/types.js.map +1 -0
- package/dist/startup.d.ts +11 -0
- package/dist/startup.js +154 -0
- package/dist/startup.js.map +1 -0
- package/dist/tool-bridge/constants.d.ts +2 -0
- package/dist/tool-bridge/constants.js +3 -0
- package/dist/tool-bridge/constants.js.map +1 -0
- package/dist/tool-bridge/index.d.ts +1 -0
- package/dist/tool-bridge/index.js +1 -0
- package/dist/tool-bridge/index.js.map +1 -1
- package/dist/tool-bridge/routes.js +2 -1
- package/dist/tool-bridge/routes.js.map +1 -1
- package/dist/tool-bridge/session-lifecycle.js +1 -1
- package/dist/tool-bridge/state.d.ts +1 -1
- package/dist/tool-bridge/tool-cache.d.ts +1 -1
- package/dist/ui.d.ts +36 -0
- package/dist/ui.js +71 -0
- package/dist/ui.js.map +1 -0
- package/dist/utils/responses-prompt.d.ts +4 -0
- package/dist/utils/responses-prompt.js +58 -0
- package/dist/utils/responses-prompt.js.map +1 -0
- package/package.json +3 -1
- package/dist/settings-patcher.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,144 +1,63 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { join, dirname } from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import { Logger } from "./logger.js";
|
|
7
|
+
import { patcherByProxy } from "./settings-patcher/index.js";
|
|
8
|
+
import { parsePort, parseLogLevel, parseProxy } from "./cli-validators.js";
|
|
9
|
+
import { startServer } from "./startup.js";
|
|
10
10
|
const PACKAGE_ROOT = dirname(import.meta.dirname);
|
|
11
11
|
const DEFAULT_CONFIG_PATH = join(PACKAGE_ROOT, "config.json5");
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
Options:
|
|
23
|
-
--port <number> Port to listen on (default: 8080)
|
|
24
|
-
--proxy <provider> API format to expose: ${VALID_PROXIES.join(", ")} (default: openai)
|
|
25
|
-
--log-level <level> Log verbosity: ${VALID_LOG_LEVELS.join(", ")} (default: info)
|
|
26
|
-
--config <path> Path to config file (auto-detected from --cwd, then process cwd, else bundled)
|
|
27
|
-
--cwd <path> Working directory for Copilot sessions (default: process cwd)
|
|
28
|
-
--auto-patch Auto-patch settings.json on start, restore on exit (anthropic mode)
|
|
29
|
-
--patch-settings Patch settings.json to point to this server, then exit
|
|
30
|
-
--restore-settings Restore settings.json from backup, then exit
|
|
31
|
-
--help Show this help message`;
|
|
32
|
-
function parseCliArgs() {
|
|
33
|
-
try {
|
|
34
|
-
return parseArgs({
|
|
35
|
-
options: {
|
|
36
|
-
port: { type: "string", default: "8080" },
|
|
37
|
-
proxy: { type: "string", default: "openai" },
|
|
38
|
-
"log-level": { type: "string", default: "info" },
|
|
39
|
-
config: { type: "string" },
|
|
40
|
-
cwd: { type: "string" },
|
|
41
|
-
"auto-patch": { type: "boolean", default: false },
|
|
42
|
-
"patch-settings": { type: "boolean", default: false },
|
|
43
|
-
"restore-settings": { type: "boolean", default: false },
|
|
44
|
-
help: { type: "boolean", default: false },
|
|
45
|
-
},
|
|
46
|
-
strict: true,
|
|
47
|
-
allowPositionals: false,
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
catch (err) {
|
|
51
|
-
console.error(String(err instanceof Error ? err.message : err));
|
|
52
|
-
console.error(`Run with --help for usage information.`);
|
|
53
|
-
process.exit(1);
|
|
12
|
+
// Can't use a JSON import here because rootDir is src/ and package.json lives at the root
|
|
13
|
+
const { version } = z.object({ version: z.string() }).parse(JSON.parse(await readFile(join(PACKAGE_ROOT, "package.json"), "utf-8")));
|
|
14
|
+
async function patchSettingsCommand(options) {
|
|
15
|
+
const logLevel = parseLogLevel(options.logLevel);
|
|
16
|
+
const logger = new Logger(logLevel);
|
|
17
|
+
const port = parsePort(options.port);
|
|
18
|
+
const proxy = parseProxy(options.proxy);
|
|
19
|
+
const patcher = patcherByProxy[proxy];
|
|
20
|
+
if (!patcher) {
|
|
21
|
+
throw new Error(`No settings patcher for --proxy ${proxy}`);
|
|
54
22
|
}
|
|
23
|
+
await patcher.patch({ port, logger });
|
|
55
24
|
}
|
|
56
|
-
async function
|
|
57
|
-
const
|
|
58
|
-
if (values.help) {
|
|
59
|
-
console.log(USAGE);
|
|
60
|
-
process.exit(0);
|
|
61
|
-
}
|
|
62
|
-
const rawLevel = values["log-level"];
|
|
63
|
-
if (!isLogLevel(rawLevel)) {
|
|
64
|
-
console.error(`Invalid log level "${rawLevel}". Valid: ${VALID_LOG_LEVELS.join(", ")}`);
|
|
65
|
-
process.exit(1);
|
|
66
|
-
}
|
|
67
|
-
const logLevel = rawLevel;
|
|
25
|
+
async function restoreSettingsCommand(options) {
|
|
26
|
+
const logLevel = parseLogLevel(options.logLevel);
|
|
68
27
|
const logger = new Logger(logLevel);
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
if (values["patch-settings"]) {
|
|
75
|
-
await patchSettings({ port, logger });
|
|
76
|
-
process.exit(0);
|
|
77
|
-
}
|
|
78
|
-
if (values["restore-settings"]) {
|
|
79
|
-
await restoreSettings({ logger });
|
|
80
|
-
process.exit(0);
|
|
81
|
-
}
|
|
82
|
-
const proxy = values.proxy;
|
|
83
|
-
if (!isProxy(proxy)) {
|
|
84
|
-
console.error(`Invalid proxy "${proxy}". Valid: ${VALID_PROXIES.join(", ")}`);
|
|
85
|
-
process.exit(1);
|
|
86
|
-
}
|
|
87
|
-
const provider = providers[proxy];
|
|
88
|
-
const configPath = values.config ?? resolveConfigPath(values.cwd, process.cwd(), DEFAULT_CONFIG_PATH);
|
|
89
|
-
const config = await loadConfig(configPath, logger, proxy);
|
|
90
|
-
const cwd = values.cwd;
|
|
91
|
-
const service = new CopilotService({
|
|
92
|
-
logLevel,
|
|
93
|
-
logger,
|
|
94
|
-
cwd,
|
|
95
|
-
});
|
|
96
|
-
logger.info("Booting up Copilot CLI...");
|
|
97
|
-
await service.start();
|
|
98
|
-
logger.info("Copilot CLI is up");
|
|
99
|
-
const auth = await service.getAuthStatus();
|
|
100
|
-
if (!auth.isAuthenticated) {
|
|
101
|
-
logger.error("Not authenticated. Sign in with the Copilot CLI (copilot login) or GitHub CLI (gh auth login), or set a GITHUB_TOKEN environment variable.");
|
|
102
|
-
await service.stop();
|
|
103
|
-
process.exit(1);
|
|
104
|
-
}
|
|
105
|
-
logger.info(`Authenticated as ${auth.login ?? "unknown"} (${auth.authType ?? "unknown"})`);
|
|
106
|
-
const autoPatch = values["auto-patch"];
|
|
107
|
-
if (autoPatch) {
|
|
108
|
-
await patchSettings({ port, logger });
|
|
28
|
+
const proxy = parseProxy(options.proxy);
|
|
29
|
+
const patcher = patcherByProxy[proxy];
|
|
30
|
+
if (!patcher) {
|
|
31
|
+
throw new Error(`No settings patcher for --proxy ${proxy}`);
|
|
109
32
|
}
|
|
110
|
-
|
|
111
|
-
const app = await createServer(ctx, provider);
|
|
112
|
-
await app.listen({ port, host: "127.0.0.1" });
|
|
113
|
-
logger.info(`Listening on http://localhost:${String(port)}`);
|
|
114
|
-
logger.info(`Provider: ${provider.name} (--proxy ${proxy})`);
|
|
115
|
-
logger.info(`Routes: ${provider.routes.join(", ")}`);
|
|
116
|
-
logger.info(`Current working directory: ${service.cwd}`);
|
|
117
|
-
const shutdown = async (signal) => {
|
|
118
|
-
logger.info(`Got ${signal}, shutting down...`);
|
|
119
|
-
if (autoPatch) {
|
|
120
|
-
try {
|
|
121
|
-
await restoreSettings({ logger });
|
|
122
|
-
}
|
|
123
|
-
catch (err) {
|
|
124
|
-
logger.error(`Failed to restore settings.json: ${String(err)}`);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
await app.close();
|
|
128
|
-
const stopPromise = service.stop().then(() => {
|
|
129
|
-
logger.info("Clean shutdown complete");
|
|
130
|
-
});
|
|
131
|
-
const timeoutPromise = new Promise((resolve) => setTimeout(() => {
|
|
132
|
-
logger.warn("Copilot client didn't stop in time, forcing exit");
|
|
133
|
-
resolve();
|
|
134
|
-
}, 3000));
|
|
135
|
-
await Promise.race([stopPromise, timeoutPromise]);
|
|
136
|
-
process.exit(0);
|
|
137
|
-
};
|
|
138
|
-
process.on("SIGINT", () => void shutdown("SIGINT"));
|
|
139
|
-
process.on("SIGTERM", () => void shutdown("SIGTERM"));
|
|
33
|
+
await patcher.restore({ logger });
|
|
140
34
|
}
|
|
141
|
-
|
|
35
|
+
const program = new Command()
|
|
36
|
+
.name("xcode-copilot-server")
|
|
37
|
+
.description("Proxy API server for Xcode, powered by GitHub Copilot")
|
|
38
|
+
.version(version, "-v, --version");
|
|
39
|
+
program
|
|
40
|
+
.option("-p, --port <number>", "port to listen on", "8080")
|
|
41
|
+
.option("--proxy <provider>", "API format: openai, claude, codex", "openai")
|
|
42
|
+
.option("-l, --log-level <level>", "log verbosity", "info")
|
|
43
|
+
.option("-c, --config <path>", "path to config file")
|
|
44
|
+
.option("--cwd <path>", "working directory for Copilot sessions")
|
|
45
|
+
.option("--auto-patch", "auto-patch settings.json on start, restore on exit")
|
|
46
|
+
.action((options) => startServer({ ...options, version, defaultConfigPath: DEFAULT_CONFIG_PATH }));
|
|
47
|
+
program
|
|
48
|
+
.command("patch-settings")
|
|
49
|
+
.description("Patch settings to point to this server, then exit")
|
|
50
|
+
.option("-p, --port <number>", "port to write into settings", "8080")
|
|
51
|
+
.option("--proxy <provider>", "which provider to patch: claude, codex", "claude")
|
|
52
|
+
.option("-l, --log-level <level>", "log verbosity", "info")
|
|
53
|
+
.action((options) => patchSettingsCommand(options));
|
|
54
|
+
program
|
|
55
|
+
.command("restore-settings")
|
|
56
|
+
.description("Restore settings from backup, then exit")
|
|
57
|
+
.option("--proxy <provider>", "which provider to restore: claude, codex", "claude")
|
|
58
|
+
.option("-l, --log-level <level>", "log verbosity", "info")
|
|
59
|
+
.action((options) => restoreSettingsCommand(options));
|
|
60
|
+
program.parseAsync().catch((err) => {
|
|
142
61
|
console.error("Fatal error:", err);
|
|
143
62
|
process.exit(1);
|
|
144
63
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/logger.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bold, dim, red, yellow, cyan, symbols } from "./ui.js";
|
|
1
2
|
export const LEVEL_PRIORITY = {
|
|
2
3
|
none: 0,
|
|
3
4
|
error: 1,
|
|
@@ -6,6 +7,12 @@ export const LEVEL_PRIORITY = {
|
|
|
6
7
|
debug: 4,
|
|
7
8
|
all: 5,
|
|
8
9
|
};
|
|
10
|
+
const LEVEL_STYLE = {
|
|
11
|
+
error: { label: red(bold("ERROR")), symbol: symbols.error },
|
|
12
|
+
warn: { label: yellow(bold("WARN")), symbol: symbols.warn },
|
|
13
|
+
info: { label: cyan("INFO"), symbol: symbols.info },
|
|
14
|
+
debug: { label: dim("DEBUG"), symbol: symbols.debug },
|
|
15
|
+
};
|
|
9
16
|
export class Logger {
|
|
10
17
|
level;
|
|
11
18
|
threshold;
|
|
@@ -15,22 +22,26 @@ export class Logger {
|
|
|
15
22
|
}
|
|
16
23
|
error(msg, ...args) {
|
|
17
24
|
if (this.threshold >= LEVEL_PRIORITY.error) {
|
|
18
|
-
|
|
25
|
+
const { label, symbol } = LEVEL_STYLE.error;
|
|
26
|
+
console.error(`${dim(new Date().toISOString())} ${symbol} ${label} ${msg}`, ...args);
|
|
19
27
|
}
|
|
20
28
|
}
|
|
21
29
|
warn(msg, ...args) {
|
|
22
30
|
if (this.threshold >= LEVEL_PRIORITY.warning) {
|
|
23
|
-
|
|
31
|
+
const { label, symbol } = LEVEL_STYLE.warn;
|
|
32
|
+
console.warn(`${dim(new Date().toISOString())} ${symbol} ${label} ${msg}`, ...args);
|
|
24
33
|
}
|
|
25
34
|
}
|
|
26
35
|
info(msg, ...args) {
|
|
27
36
|
if (this.threshold >= LEVEL_PRIORITY.info) {
|
|
28
|
-
|
|
37
|
+
const { label, symbol } = LEVEL_STYLE.info;
|
|
38
|
+
console.log(`${dim(new Date().toISOString())} ${symbol} ${label} ${msg}`, ...args);
|
|
29
39
|
}
|
|
30
40
|
}
|
|
31
41
|
debug(msg, ...args) {
|
|
32
42
|
if (this.threshold >= LEVEL_PRIORITY.debug) {
|
|
33
|
-
|
|
43
|
+
const { label, symbol } = LEVEL_STYLE.debug;
|
|
44
|
+
console.log(`${dim(new Date().toISOString())} ${symbol} ${label} ${dim(msg)}`, ...args);
|
|
34
45
|
}
|
|
35
46
|
}
|
|
36
47
|
}
|
package/dist/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,GAAG,EAAE,CAAC;CACmC,CAAC;AAI5C,MAAM,OAAO,MAAM;IACR,KAAK,CAAW;IACjB,SAAS,CAAS;IAE1B,YAAY,QAAkB,MAAM;QAClC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,GAAW,EAAE,GAAG,IAAe;QACnC,IAAI,IAAI,CAAC,SAAS,IAAI,cAAc,CAAC,KAAK,EAAE,CAAC;YAC3C,OAAO,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { estimateTokenCount } from "tokenx";
|
|
2
|
+
import { AnthropicMessagesRequestSchema, } from "./schemas.js";
|
|
3
|
+
import { sendAnthropicError } from "../shared/errors.js";
|
|
4
|
+
// The token estimator needs a single string, so we pull all text out of
|
|
5
|
+
// the structured request.
|
|
6
|
+
function extractAllText(req) {
|
|
7
|
+
const parts = [];
|
|
8
|
+
if (req.system != null) {
|
|
9
|
+
if (typeof req.system === "string") {
|
|
10
|
+
parts.push(req.system);
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
for (const block of req.system) {
|
|
14
|
+
parts.push(block.text);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
for (const msg of req.messages) {
|
|
19
|
+
if (typeof msg.content === "string") {
|
|
20
|
+
parts.push(msg.content);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
for (const block of msg.content) {
|
|
24
|
+
switch (block.type) {
|
|
25
|
+
case "text":
|
|
26
|
+
parts.push(block.text);
|
|
27
|
+
break;
|
|
28
|
+
case "tool_use":
|
|
29
|
+
parts.push(block.name);
|
|
30
|
+
parts.push(JSON.stringify(block.input));
|
|
31
|
+
break;
|
|
32
|
+
case "tool_result":
|
|
33
|
+
if (typeof block.content === "string") {
|
|
34
|
+
parts.push(block.content);
|
|
35
|
+
}
|
|
36
|
+
else if (Array.isArray(block.content)) {
|
|
37
|
+
for (const tb of block.content) {
|
|
38
|
+
parts.push(tb.text);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
break;
|
|
42
|
+
default:
|
|
43
|
+
throw block;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (req.tools) {
|
|
49
|
+
for (const tool of req.tools) {
|
|
50
|
+
parts.push(tool.name);
|
|
51
|
+
if (tool.description)
|
|
52
|
+
parts.push(tool.description);
|
|
53
|
+
parts.push(JSON.stringify(tool.input_schema));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return parts.join(" ");
|
|
57
|
+
}
|
|
58
|
+
export function createCountTokensHandler({ logger }) {
|
|
59
|
+
return function handleCountTokens(request, reply) {
|
|
60
|
+
const parseResult = AnthropicMessagesRequestSchema.safeParse(request.body);
|
|
61
|
+
if (!parseResult.success) {
|
|
62
|
+
const firstIssue = parseResult.error.issues[0];
|
|
63
|
+
sendAnthropicError(reply, 400, "invalid_request_error", firstIssue?.message ?? "Invalid request body");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const allText = extractAllText(parseResult.data);
|
|
67
|
+
const inputTokens = estimateTokenCount(allText);
|
|
68
|
+
logger.debug(`Token count estimate: ${String(inputTokens)}`);
|
|
69
|
+
void reply.send({ input_tokens: inputTokens });
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=count-tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"count-tokens.js","sourceRoot":"","sources":["../../../src/providers/claude/count-tokens.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { FastifyRequest, FastifyReply } from "fastify";
|
|
2
|
+
import type { AppContext } from "../../context.js";
|
|
3
|
+
import type { ConversationManager } from "../../conversation-manager.js";
|
|
4
|
+
export declare function createMessagesHandler({ service, logger, config, port }: AppContext, manager: ConversationManager): (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { AnthropicMessagesRequestSchema, extractAnthropicSystem, } from "./schemas.js";
|
|
2
|
+
import { formatAnthropicPrompt } from "./prompt.js";
|
|
3
|
+
import { resolveModel } from "../shared/model-resolver.js";
|
|
4
|
+
import { createSessionConfig } from "../shared/session-config.js";
|
|
5
|
+
import { resolveToolResults } from "./tool-results.js";
|
|
6
|
+
import { handleAnthropicStreaming, startReply } from "./streaming.js";
|
|
7
|
+
import { sendAnthropicError as sendError } from "../shared/errors.js";
|
|
8
|
+
export function createMessagesHandler({ service, logger, config, port }, manager) {
|
|
9
|
+
return async function handleMessages(request, reply) {
|
|
10
|
+
const parseResult = AnthropicMessagesRequestSchema.safeParse(request.body);
|
|
11
|
+
if (!parseResult.success) {
|
|
12
|
+
const firstIssue = parseResult.error.issues[0];
|
|
13
|
+
sendError(reply, 400, "invalid_request_error", firstIssue?.message ?? "Invalid request body");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const req = parseResult.data;
|
|
17
|
+
const existingConv = manager.findByContinuation(req.messages);
|
|
18
|
+
if (existingConv) {
|
|
19
|
+
const state = existingConv.state;
|
|
20
|
+
logger.info(`Continuation for conversation ${existingConv.id} (hasPending=${String(state.hasPending)}, sessionActive=${String(state.sessionActive)})`);
|
|
21
|
+
state.setReply(reply);
|
|
22
|
+
startReply(reply, req.model);
|
|
23
|
+
// TODO: the continuation doesn't own the session so we can't abort it
|
|
24
|
+
// here. The original streaming handler will let it run to idle harmlessly
|
|
25
|
+
// because it guards against null replies, but ideally we'd abort it too.
|
|
26
|
+
reply.raw.on("close", () => {
|
|
27
|
+
if (state.currentReply === reply) {
|
|
28
|
+
logger.info("Client disconnected during continuation");
|
|
29
|
+
state.cleanup();
|
|
30
|
+
state.notifyStreamingDone();
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
resolveToolResults(req.messages, state, logger);
|
|
34
|
+
await state.waitForStreamingDone();
|
|
35
|
+
existingConv.sentMessageCount = req.messages.length;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const { conversation, isReuse } = manager.findForNewRequest();
|
|
39
|
+
const state = conversation.state;
|
|
40
|
+
state.markSessionActive();
|
|
41
|
+
logger.info(isReuse
|
|
42
|
+
? `Reusing primary conversation ${conversation.id}`
|
|
43
|
+
: `New conversation ${conversation.id}`);
|
|
44
|
+
// SDK doesn't support switching models mid-session (github/copilot-sdk#409)
|
|
45
|
+
if (isReuse && conversation.model && conversation.model !== req.model) {
|
|
46
|
+
logger.warn(`Model mismatch: session uses "${conversation.model}" but request sent "${req.model}" (SDK does not support mid-session model switching)`);
|
|
47
|
+
}
|
|
48
|
+
const tools = req.tools;
|
|
49
|
+
const hasTools = !!tools?.length;
|
|
50
|
+
const hasBridge = hasTools && config.toolBridge;
|
|
51
|
+
if (tools?.length) {
|
|
52
|
+
state.cacheTools(tools);
|
|
53
|
+
}
|
|
54
|
+
let prompt;
|
|
55
|
+
try {
|
|
56
|
+
prompt = formatAnthropicPrompt(req.messages.slice(conversation.sentMessageCount), config.excludedFilePatterns);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
sendError(reply, 400, "invalid_request_error", err instanceof Error ? err.message : String(err));
|
|
60
|
+
if (isReuse) {
|
|
61
|
+
state.markSessionInactive();
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
manager.remove(conversation.id);
|
|
65
|
+
}
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
logger.debug(`Prompt (${isReuse ? "incremental" : "full"}): ${String(prompt.length)} chars`);
|
|
69
|
+
if (!isReuse) {
|
|
70
|
+
const systemMessage = extractAnthropicSystem(req.system);
|
|
71
|
+
logger.debug(`System message length: ${String(systemMessage?.length ?? 0)} chars`);
|
|
72
|
+
logger.debug(`Tools in request: ${tools ? String(tools.length) : "0"}`);
|
|
73
|
+
if (tools) {
|
|
74
|
+
logger.debug(`Tool names: ${tools.map((t) => t.name).join(", ")}`);
|
|
75
|
+
}
|
|
76
|
+
let copilotModel = req.model;
|
|
77
|
+
let supportsReasoningEffort = false;
|
|
78
|
+
try {
|
|
79
|
+
const models = await service.listModels();
|
|
80
|
+
const resolved = resolveModel(req.model, models, logger);
|
|
81
|
+
if (!resolved) {
|
|
82
|
+
sendError(reply, 400, "invalid_request_error", `Model "${req.model}" is not available. Available models: ${models.map((m) => m.id).join(", ")}`);
|
|
83
|
+
manager.remove(conversation.id);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
copilotModel = resolved;
|
|
87
|
+
if (config.reasoningEffort) {
|
|
88
|
+
const modelInfo = models.find((m) => m.id === copilotModel);
|
|
89
|
+
supportsReasoningEffort =
|
|
90
|
+
modelInfo?.capabilities.supports.reasoningEffort ?? false;
|
|
91
|
+
if (!supportsReasoningEffort) {
|
|
92
|
+
logger.debug(`Model "${copilotModel}" does not support reasoning effort, ignoring config`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
logger.warn("Failed to list models, passing model through as-is:", err);
|
|
98
|
+
}
|
|
99
|
+
conversation.model = copilotModel;
|
|
100
|
+
if (hasBridge) {
|
|
101
|
+
logger.info("Tool bridge active (in-process MCP)");
|
|
102
|
+
}
|
|
103
|
+
const sessionConfig = createSessionConfig({
|
|
104
|
+
model: copilotModel,
|
|
105
|
+
systemMessage,
|
|
106
|
+
logger,
|
|
107
|
+
config,
|
|
108
|
+
supportsReasoningEffort,
|
|
109
|
+
cwd: service.cwd,
|
|
110
|
+
hasToolBridge: hasBridge,
|
|
111
|
+
port,
|
|
112
|
+
conversationId: conversation.id,
|
|
113
|
+
});
|
|
114
|
+
try {
|
|
115
|
+
conversation.session = await service.createSession(sessionConfig);
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
logger.error("Creating session failed:", err);
|
|
119
|
+
sendError(reply, 500, "api_error", "Failed to create session");
|
|
120
|
+
manager.remove(conversation.id);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (!conversation.session) {
|
|
125
|
+
logger.error("Primary conversation has no session, clearing");
|
|
126
|
+
manager.clearPrimary();
|
|
127
|
+
sendError(reply, 500, "api_error", "Session lost, please retry");
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
state.setReply(reply);
|
|
131
|
+
try {
|
|
132
|
+
logger.info(`Streaming response for conversation ${conversation.id}`);
|
|
133
|
+
await handleAnthropicStreaming(state, conversation.session, prompt, req.model, logger, hasBridge);
|
|
134
|
+
conversation.sentMessageCount = req.messages.length;
|
|
135
|
+
if (conversation.isPrimary && state.hadError) {
|
|
136
|
+
manager.clearPrimary();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
logger.error("Request failed:", err);
|
|
141
|
+
if (conversation.isPrimary) {
|
|
142
|
+
manager.clearPrimary();
|
|
143
|
+
}
|
|
144
|
+
if (!reply.sent) {
|
|
145
|
+
sendError(reply, 500, "api_error", err instanceof Error ? err.message : "Internal error");
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/providers/claude/handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { filterExcludedFiles } from "../shared/prompt-utils.js";
|
|
2
|
+
function extractToolResultText(content) {
|
|
3
|
+
if (content == null)
|
|
4
|
+
return "";
|
|
5
|
+
if (typeof content === "string")
|
|
6
|
+
return content;
|
|
7
|
+
return content.map((b) => b.text).join("");
|
|
8
|
+
}
|
|
9
|
+
function formatBlocks(blocks, role, excludedFilePatterns, parts) {
|
|
10
|
+
for (const block of blocks) {
|
|
11
|
+
switch (block.type) {
|
|
12
|
+
case "text":
|
|
13
|
+
if (!block.text)
|
|
14
|
+
break;
|
|
15
|
+
if (role === "user") {
|
|
16
|
+
parts.push(`[User]: ${filterExcludedFiles(block.text, excludedFilePatterns)}`);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
parts.push(`[Assistant]: ${block.text}`);
|
|
20
|
+
}
|
|
21
|
+
break;
|
|
22
|
+
case "tool_use":
|
|
23
|
+
parts.push(`[Assistant called tool ${block.name} with args: ${JSON.stringify(block.input)}]`);
|
|
24
|
+
break;
|
|
25
|
+
case "tool_result": {
|
|
26
|
+
const text = extractToolResultText(block.content);
|
|
27
|
+
parts.push(`[Tool result for ${block.tool_use_id}]: ${text}`);
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// The Copilot SDK expects a single flat prompt string, so we convert the
|
|
34
|
+
// structured Anthropic messages into that format.
|
|
35
|
+
export function formatAnthropicPrompt(messages, excludedFilePatterns) {
|
|
36
|
+
const parts = [];
|
|
37
|
+
for (const msg of messages) {
|
|
38
|
+
if (typeof msg.content === "string") {
|
|
39
|
+
if (msg.role === "user") {
|
|
40
|
+
parts.push(`[User]: ${filterExcludedFiles(msg.content, excludedFilePatterns)}`);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
parts.push(`[Assistant]: ${msg.content}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
formatBlocks(msg.content, msg.role, excludedFilePatterns, parts);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return parts.join("\n\n");
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../src/providers/claude/prompt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEhE,SAAS,qBAAqB,CAC5B,OAA8D;IAE9D,IAAI,OAAO,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC/B,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,YAAY,CACnB,MAAsB,EACtB,IAA0B,EAC1B,oBAA8B,EAC9B,KAAe;IAEf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,MAAM;gBACT,IAAI,CAAC,KAAK,CAAC,IAAI;oBAAE,MAAM;gBACvB,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;oBACpB,KAAK,CAAC,IAAI,CACR,WAAW,mBAAmB,CAAC,KAAK,CAAC,IAAI,EAAE,oBAAoB,CAAC,EAAE,CACnE,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,IAAI,CAAC,gBAAgB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC3C,CAAC;gBACD,MAAM;YAER,KAAK,UAAU;gBACb,KAAK,CAAC,IAAI,CACR,0BAA0B,KAAK,CAAC,IAAI,eAAe,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAClF,CAAC;gBACF,MAAM;YAER,KAAK,aAAa,CAAC,CAAC,CAAC;gBACnB,MAAM,IAAI,GAAG,qBAAqB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAClD,KAAK,CAAC,IAAI,CAAC,oBAAoB,KAAK,CAAC,WAAW,MAAM,IAAI,EAAE,CAAC,CAAC;gBAC9D,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,yEAAyE;AACzE,kDAAkD;AAClD,MAAM,UAAU,qBAAqB,CACnC,QAA4B,EAC5B,oBAA8B;IAE9B,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACpC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACxB,KAAK,CAAC,IAAI,CACR,WAAW,mBAAmB,CAAC,GAAG,CAAC,OAAO,EAAE,oBAAoB,CAAC,EAAE,CACpE,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,gBAAgB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE,oBAAoB,EAAE,KAAK,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const claudeProvider: {
|
|
2
|
+
name: string;
|
|
3
|
+
routes: string[];
|
|
4
|
+
register(app: import("fastify").FastifyInstance<import("fastify").RawServerDefault, import("node:http").IncomingMessage, import("node:http").ServerResponse<import("node:http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault>, ctx: import("../../context.js").AppContext): void;
|
|
5
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { registerToolBridge } from "../../tool-bridge/index.js";
|
|
2
|
+
import { createMessagesHandler } from "./handler.js";
|
|
3
|
+
import { createCountTokensHandler } from "./count-tokens.js";
|
|
4
|
+
export const claudeProvider = {
|
|
5
|
+
name: "Claude",
|
|
6
|
+
routes: ["POST /v1/messages", "POST /v1/messages/count_tokens"],
|
|
7
|
+
register(app, ctx) {
|
|
8
|
+
app.addHook("onRequest", (request, reply, done) => {
|
|
9
|
+
// MCP routes come from the SDK, not Xcode, so they
|
|
10
|
+
// won't have the claude-cli/ user-agent
|
|
11
|
+
if (request.url.startsWith("/mcp/")) {
|
|
12
|
+
done();
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const ua = request.headers["user-agent"] ?? "";
|
|
16
|
+
if (!ua.startsWith("claude-cli/")) {
|
|
17
|
+
ctx.logger.warn(`Rejected request from unexpected user-agent: ${ua}`);
|
|
18
|
+
void reply.code(403).type("application/json").send('{"error":"Forbidden"}\n');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
done();
|
|
22
|
+
});
|
|
23
|
+
const manager = registerToolBridge(app, ctx.logger);
|
|
24
|
+
app.post("/v1/messages", createMessagesHandler(ctx, manager));
|
|
25
|
+
app.post("/v1/messages/count_tokens", createCountTokensHandler(ctx));
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=provider.js.map
|