Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions proxy-server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions proxy-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
},
"dependencies": {
"commander": "14.0.3",
"copilot-sdk-proxy": "4.0.3",
"copilot-sdk-proxy": "4.0.4",
"fastify": "5.8.2",
"json5": "2.2.3",
"koffi": "2.15.2",
Expand All @@ -44,7 +44,7 @@
"devDependencies": {
"@types/node": "25.5.0",
"@types/plist": "3.0.5",
"llm-mock-server": "1.0.3",
"llm-mock-server": "1.0.4",
"oxfmt": "0.40.0",
"oxlint": "1.55.0",
"patch-package": "8.0.1",
Expand Down
11 changes: 5 additions & 6 deletions proxy-server/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
MS_PER_MINUTE,
} from "./config-schema.js";
import type { ServerConfig } from "./config-schema.js";
import { isErrnoException } from "./utils/type-guards.js";
import { isErrnoException, errorMessage } from "./utils/type-guards.js";

function resolveServerPaths(
servers: Record<string, MCPServer>,
Expand Down Expand Up @@ -73,7 +73,7 @@ async function parseConfigFile(
return null;
}
throw new Error(
`Failed to read config file at ${absolutePath}: ${err instanceof Error ? err.message : String(err)}`,
`Failed to read config file at ${absolutePath}: ${errorMessage(err)}`,
{ cause: err },
);
}
Expand All @@ -82,10 +82,9 @@ async function parseConfigFile(
try {
raw = JSON5.parse(text);
} catch (err) {
throw new Error(
`Failed to parse config file: ${err instanceof Error ? err.message : String(err)}`,
{ cause: err },
);
throw new Error(`Failed to parse config file: ${errorMessage(err)}`, {
cause: err,
});
}

if (!raw || typeof raw !== "object") {
Expand Down
8 changes: 4 additions & 4 deletions proxy-server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from "./cli-validators.js";
import { startServer, type StartOptions } from "./startup.js";
import { installAgent, uninstallAgent } from "./launchd/index.js";
import { errorMessage } from "./utils/type-guards.js";

const PACKAGE_ROOT = dirname(import.meta.dirname);
const DEFAULT_CONFIG_PATH = join(PACKAGE_ROOT, "config.json5");
Expand All @@ -26,10 +27,9 @@ try {
);
version = z.object({ version: z.string() }).parse(raw).version;
} catch (err) {
throw new Error(
`Failed to read package.json: ${err instanceof Error ? err.message : String(err)}`,
{ cause: err },
);
throw new Error(`Failed to read package.json: ${errorMessage(err)}`, {
cause: err,
});
}

interface PatchOptions {
Expand Down
2 changes: 0 additions & 2 deletions proxy-server/src/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import { registerToolBridge } from "../tool-bridge/index.js";
import { PROVIDER_NAMES } from "copilot-sdk-proxy";
import type { ProviderName } from "copilot-sdk-proxy";

export type { ProviderName, ProviderMode } from "copilot-sdk-proxy";

export const providers: Record<ProviderName, Provider> = {
openai: openaiProvider,
claude: claudeProvider,
Expand Down
1 change: 0 additions & 1 deletion proxy-server/src/providers/names.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export { PROVIDER_NAMES } from "copilot-sdk-proxy";
export type { ProviderName, ProviderMode } from "copilot-sdk-proxy";
import type { ProviderName } from "copilot-sdk-proxy";

export const UA_PREFIXES: Record<ProviderName, string> = {
Expand Down
6 changes: 3 additions & 3 deletions proxy-server/src/providers/shared/session-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { ServerConfig } from "../../config-schema.js";
import {
BRIDGE_SERVER_NAME,
BRIDGE_TOOL_PREFIX,
} from "../../bridge-constants.js";
} from "../../tool-bridge/bridge-constants.js";

const SDK_BUILT_IN_TOOLS: string[] = [
// shell
Expand Down Expand Up @@ -43,7 +43,7 @@ interface SessionConfigOptions extends BaseSessionConfigOptions {
}

interface ToolBridgeContext {
tools: unknown[] | undefined;
tools: readonly unknown[] | undefined;
config: ServerConfig;
logger: Logger;
}
Expand All @@ -65,7 +65,7 @@ function resolveToolBridge({

interface ProviderContext {
conversationId: string;
tools: unknown[] | undefined;
tools: readonly unknown[] | undefined;
config: ServerConfig;
logger: Logger;
port: number;
Expand Down
10 changes: 8 additions & 2 deletions proxy-server/src/providers/shared/streaming-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type {
import { createCommonEventHandler } from "copilot-sdk-proxy";
import type { ToolBridgeState } from "../../tool-bridge/state.js";
import { isRecord } from "../../utils/type-guards.js";
import { BRIDGE_TOOL_PREFIX } from "../../bridge-constants.js";
import { BRIDGE_TOOL_PREFIX } from "../../tool-bridge/bridge-constants.js";

// Xcode sends tool names without the bridge prefix.
function stripBridgePrefix(name: string): string {
Expand Down Expand Up @@ -226,10 +226,16 @@ class StreamingHandler {
if (this.sessionDone) return;
this.logger.error("Failed to send prompt:", err);
this.sessionDone = true;
this.state.session.markSessionErrored();
this.state.session.markSessionInactive();
const r = this.getReply();
if (r) {
this.protocol.sendFailed(r);
}
this.protocol.teardown();
this.protocol.reset();
this.finishStream(r);
this.unsubscribe();
this.finishStream(this.getReply());
});
}
}
4 changes: 2 additions & 2 deletions proxy-server/src/settings-patcher/claude.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import type {
import { extractLocalhostPort } from "./url-utils.js";

// Claude agent requires ANTHROPIC_AUTH_TOKEN to connect, but any value works for the local proxy.
const DUMMY_AUTH_TOKEN = "xcode-copilot";
const PLACEHOLDER_AUTH_VALUE = "xcode-copilot";

function defaultSettingsPaths(): SettingsPaths {
const dir = join(
Expand Down Expand Up @@ -104,7 +104,7 @@ export async function patchClaudeSettings(
settings.env = {
...settings.env,
ANTHROPIC_BASE_URL: `http://localhost:${String(options.port)}`,
ANTHROPIC_AUTH_TOKEN: options.authToken ?? DUMMY_AUTH_TOKEN,
ANTHROPIC_AUTH_TOKEN: options.authToken ?? PLACEHOLDER_AUTH_VALUE,
};

await writeFile(p.file, JSON.stringify(settings, null, 2) + "\n", "utf-8");
Expand Down
2 changes: 1 addition & 1 deletion proxy-server/src/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ interface ParsedOptions {
cwd: string | undefined;
}

function parseOptions(options: StartOptions): ParsedOptions {
export function parseOptions(options: StartOptions): ParsedOptions {
const logLevel = parseLogLevel(options.logLevel);
const logger = new Logger(logLevel);
const port = parsePort(options.port);
Expand Down
2 changes: 0 additions & 2 deletions proxy-server/src/tool-bridge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import type { Logger } from "copilot-sdk-proxy";
import { ConversationManager } from "../conversation-manager.js";
import { registerRoutes } from "./routes.js";

export { BRIDGE_SERVER_NAME, BRIDGE_TOOL_PREFIX } from "../bridge-constants.js";

export function registerToolBridge(
app: FastifyInstance,
logger: Logger,
Expand Down
Loading
Loading