xcode-copilot-server 3.0.0 → 3.1.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 (118) hide show
  1. package/dist/cli-validators.d.ts +2 -0
  2. package/dist/cli-validators.js +8 -1
  3. package/dist/cli-validators.js.map +1 -1
  4. package/dist/config.js +1 -1
  5. package/dist/config.js.map +1 -1
  6. package/dist/index.js +48 -2
  7. package/dist/index.js.map +1 -1
  8. package/dist/launchd/agent.d.ts +52 -0
  9. package/dist/launchd/agent.js +185 -0
  10. package/dist/launchd/agent.js.map +1 -0
  11. package/dist/launchd/index.d.ts +4 -0
  12. package/dist/launchd/index.js +3 -0
  13. package/dist/launchd/index.js.map +1 -0
  14. package/dist/launchd/socket.d.ts +5 -0
  15. package/dist/launchd/socket.js +31 -0
  16. package/dist/launchd/socket.js.map +1 -0
  17. package/dist/launchd-agent.d.ts +50 -0
  18. package/dist/launchd-agent.js +175 -0
  19. package/dist/launchd-agent.js.map +1 -0
  20. package/dist/launchd-socket.d.ts +5 -0
  21. package/dist/launchd-socket.js +33 -0
  22. package/dist/launchd-socket.js.map +1 -0
  23. package/dist/startup.d.ts +2 -0
  24. package/dist/startup.js +47 -5
  25. package/dist/startup.js.map +1 -1
  26. package/dist/stats.d.ts +48 -0
  27. package/dist/stats.js +68 -0
  28. package/dist/stats.js.map +1 -0
  29. package/dist/status-line.d.ts +11 -0
  30. package/dist/status-line.js +101 -0
  31. package/dist/status-line.js.map +1 -0
  32. package/package.json +8 -5
  33. package/LICENSE +0 -21
  34. package/README.md +0 -269
  35. package/dist/config-schema.d.ts +0 -85
  36. package/dist/config-schema.js +0 -38
  37. package/dist/config-schema.js.map +0 -1
  38. package/dist/handlers/completions/session-config.d.ts +0 -12
  39. package/dist/handlers/completions/session-config.js +0 -63
  40. package/dist/handlers/completions/session-config.js.map +0 -1
  41. package/dist/handlers/completions/streaming.d.ts +0 -4
  42. package/dist/handlers/completions/streaming.js +0 -121
  43. package/dist/handlers/completions/streaming.js.map +0 -1
  44. package/dist/handlers/completions.d.ts +0 -4
  45. package/dist/handlers/completions.js +0 -120
  46. package/dist/handlers/completions.js.map +0 -1
  47. package/dist/handlers/errors.d.ts +0 -5
  48. package/dist/handlers/errors.js +0 -10
  49. package/dist/handlers/errors.js.map +0 -1
  50. package/dist/handlers/messages/count-tokens.d.ts +0 -3
  51. package/dist/handlers/messages/count-tokens.js +0 -72
  52. package/dist/handlers/messages/count-tokens.js.map +0 -1
  53. package/dist/handlers/messages/streaming.d.ts +0 -6
  54. package/dist/handlers/messages/streaming.js +0 -274
  55. package/dist/handlers/messages/streaming.js.map +0 -1
  56. package/dist/handlers/messages/tool-result-handler.d.ts +0 -4
  57. package/dist/handlers/messages/tool-result-handler.js +0 -19
  58. package/dist/handlers/messages/tool-result-handler.js.map +0 -1
  59. package/dist/handlers/messages.d.ts +0 -4
  60. package/dist/handlers/messages.js +0 -150
  61. package/dist/handlers/messages.js.map +0 -1
  62. package/dist/handlers/models.d.ts +0 -3
  63. package/dist/handlers/models.js +0 -28
  64. package/dist/handlers/models.js.map +0 -1
  65. package/dist/handlers/responses/streaming.d.ts +0 -6
  66. package/dist/handlers/responses/streaming.js +0 -265
  67. package/dist/handlers/responses/streaming.js.map +0 -1
  68. package/dist/handlers/responses/tool-result-handler.d.ts +0 -4
  69. package/dist/handlers/responses/tool-result-handler.js +0 -9
  70. package/dist/handlers/responses/tool-result-handler.js.map +0 -1
  71. package/dist/handlers/responses.d.ts +0 -4
  72. package/dist/handlers/responses.js +0 -164
  73. package/dist/handlers/responses.js.map +0 -1
  74. package/dist/handlers/session-config.d.ts +0 -15
  75. package/dist/handlers/session-config.js +0 -79
  76. package/dist/handlers/session-config.js.map +0 -1
  77. package/dist/handlers/streaming-utils.d.ts +0 -10
  78. package/dist/handlers/streaming-utils.js +0 -22
  79. package/dist/handlers/streaming-utils.js.map +0 -1
  80. package/dist/providers/anthropic.d.ts +0 -5
  81. package/dist/providers/anthropic.js +0 -28
  82. package/dist/providers/anthropic.js.map +0 -1
  83. package/dist/providers/codex.d.ts +0 -5
  84. package/dist/providers/codex.js +0 -24
  85. package/dist/providers/codex.js.map +0 -1
  86. package/dist/providers/openai.d.ts +0 -5
  87. package/dist/providers/openai.js +0 -25
  88. package/dist/providers/openai.js.map +0 -1
  89. package/dist/schemas/anthropic.d.ts +0 -140
  90. package/dist/schemas/anthropic.js +0 -58
  91. package/dist/schemas/anthropic.js.map +0 -1
  92. package/dist/schemas/openai.d.ts +0 -98
  93. package/dist/schemas/openai.js +0 -76
  94. package/dist/schemas/openai.js.map +0 -1
  95. package/dist/schemas/responses.d.ts +0 -122
  96. package/dist/schemas/responses.js +0 -54
  97. package/dist/schemas/responses.js.map +0 -1
  98. package/dist/schemas.d.ts +0 -49
  99. package/dist/schemas.js +0 -75
  100. package/dist/schemas.js.map +0 -1
  101. package/dist/settings-patcher/anthropic.d.ts +0 -5
  102. package/dist/settings-patcher/anthropic.js +0 -75
  103. package/dist/settings-patcher/anthropic.js.map +0 -1
  104. package/dist/types.d.ts +0 -83
  105. package/dist/types.js +0 -2
  106. package/dist/types.js.map +0 -1
  107. package/dist/utils/anthropic-prompt.d.ts +0 -2
  108. package/dist/utils/anthropic-prompt.js +0 -52
  109. package/dist/utils/anthropic-prompt.js.map +0 -1
  110. package/dist/utils/model-resolver.d.ts +0 -3
  111. package/dist/utils/model-resolver.js +0 -45
  112. package/dist/utils/model-resolver.js.map +0 -1
  113. package/dist/utils/prompt.d.ts +0 -3
  114. package/dist/utils/prompt.js +0 -50
  115. package/dist/utils/prompt.js.map +0 -1
  116. package/dist/utils/responses-prompt.d.ts +0 -4
  117. package/dist/utils/responses-prompt.js +0 -58
  118. package/dist/utils/responses-prompt.js.map +0 -1
@@ -0,0 +1,175 @@
1
+ // Manage a macOS launchd agent for xcode-copilot-server with socket activation.
2
+ //
3
+ // install-agent: generates a plist, writes it to ~/Library/LaunchAgents/,
4
+ // loads it via launchctl, and optionally patches Xcode settings.
5
+ //
6
+ // uninstall-agent: reads the existing plist to detect configuration,
7
+ // unloads it, deletes it, and restores settings if needed.
8
+ import { existsSync } from "node:fs";
9
+ import { readFile, writeFile, unlink, mkdir } from "node:fs/promises";
10
+ import { execFile as execFileCb } from "node:child_process";
11
+ import { promisify } from "node:util";
12
+ import { dirname, join, resolve } from "node:path";
13
+ import { homedir } from "node:os";
14
+ import plist, {} from "plist";
15
+ import { patcherByProxy } from "./settings-patcher/index.js";
16
+ const execFileAsync = promisify(execFileCb);
17
+ async function defaultExec(cmd, args) {
18
+ const { stdout } = await execFileAsync(cmd, args);
19
+ return stdout;
20
+ }
21
+ export const AGENT_LABEL = "com.xcode-copilot-server";
22
+ export function defaultPlistPath() {
23
+ return join(homedir(), "Library/LaunchAgents", `${AGENT_LABEL}.plist`);
24
+ }
25
+ export function defaultLogPaths() {
26
+ const dir = join(homedir(), "Library/Logs");
27
+ return {
28
+ out: join(dir, "xcode-copilot-server.out.log"),
29
+ err: join(dir, "xcode-copilot-server.err.log"),
30
+ };
31
+ }
32
+ export function generatePlist(options) {
33
+ const args = [
34
+ options.nodePath,
35
+ options.entryPoint,
36
+ "--launchd",
37
+ "--proxy", options.proxy,
38
+ "--port", String(options.port),
39
+ "--log-level", options.logLevel,
40
+ ];
41
+ if (options.config) {
42
+ args.push("--config", options.config);
43
+ }
44
+ if (options.cwd) {
45
+ args.push("--cwd", options.cwd);
46
+ }
47
+ if (options.autoPatch) {
48
+ args.push("--auto-patch");
49
+ }
50
+ const logPaths = options.logPaths ?? defaultLogPaths();
51
+ const envVars = { ...options.environmentVariables };
52
+ // Always pass PATH so node can find dependencies
53
+ if (!envVars["PATH"] && process.env["PATH"]) {
54
+ envVars["PATH"] = process.env["PATH"];
55
+ }
56
+ // Pass GITHUB_TOKEN if set (needed for auth)
57
+ if (!envVars["GITHUB_TOKEN"] && process.env["GITHUB_TOKEN"]) {
58
+ envVars["GITHUB_TOKEN"] = process.env["GITHUB_TOKEN"];
59
+ }
60
+ const hasEnv = Object.keys(envVars).length > 0;
61
+ const obj = {
62
+ Label: AGENT_LABEL,
63
+ ProgramArguments: args,
64
+ Sockets: {
65
+ Listeners: {
66
+ SockServiceName: String(options.port),
67
+ SockNodeName: "127.0.0.1",
68
+ SockFamily: "IPv4",
69
+ SockType: "stream",
70
+ },
71
+ },
72
+ StandardOutPath: logPaths.out,
73
+ StandardErrorPath: logPaths.err,
74
+ ...(hasEnv ? { EnvironmentVariables: envVars } : {}),
75
+ };
76
+ return plist.build(obj) + "\n";
77
+ }
78
+ export function parsePlistArgs(plistContent) {
79
+ let parsed;
80
+ try {
81
+ parsed = plist.parse(plistContent);
82
+ }
83
+ catch {
84
+ return { proxy: null, autoPatch: false };
85
+ }
86
+ const args = parsed["ProgramArguments"];
87
+ if (!Array.isArray(args)) {
88
+ return { proxy: null, autoPatch: false };
89
+ }
90
+ let proxy = null;
91
+ let autoPatch = false;
92
+ for (let i = 0; i < args.length; i++) {
93
+ if (args[i] === "--proxy" && i + 1 < args.length) {
94
+ const value = args[i + 1];
95
+ if (value === "openai" || value === "claude" || value === "codex") {
96
+ proxy = value;
97
+ }
98
+ }
99
+ if (args[i] === "--auto-patch") {
100
+ autoPatch = true;
101
+ }
102
+ }
103
+ return { proxy, autoPatch };
104
+ }
105
+ export async function installAgent(options) {
106
+ const { port, proxy, logLevel, logger, autoPatch = false, } = options;
107
+ const exec = options.exec ?? defaultExec;
108
+ const plistPath = options.plistPath ?? defaultPlistPath();
109
+ const nodePath = options.nodePath ?? process.execPath;
110
+ const entryPoint = options.entryPoint ?? resolve(dirname(import.meta.dirname), "dist/index.js");
111
+ // Unload existing agent (ignore errors on first install)
112
+ if (existsSync(plistPath)) {
113
+ try {
114
+ await exec("launchctl", ["unload", plistPath]);
115
+ }
116
+ catch {
117
+ // Not loaded or doesn't exist yet — that's fine
118
+ }
119
+ }
120
+ const plistXml = generatePlist({
121
+ nodePath,
122
+ entryPoint,
123
+ port,
124
+ proxy,
125
+ logLevel,
126
+ config: options.config,
127
+ cwd: options.cwd,
128
+ autoPatch,
129
+ });
130
+ // Ensure ~/Library/LaunchAgents/ exists
131
+ await mkdir(dirname(plistPath), { recursive: true });
132
+ await writeFile(plistPath, plistXml, "utf-8");
133
+ await exec("launchctl", ["load", plistPath]);
134
+ // Patch settings if requested
135
+ if (autoPatch) {
136
+ const patcher = patcherByProxy[proxy];
137
+ if (patcher) {
138
+ await patcher.patch({ port, logger });
139
+ }
140
+ }
141
+ const logPaths = defaultLogPaths();
142
+ logger.info(`Launchd agent installed: ${AGENT_LABEL}`);
143
+ logger.info(` Port: ${String(port)}, Proxy: ${proxy}`);
144
+ logger.info(` Plist: ${plistPath}`);
145
+ logger.info(` Logs: ${logPaths.out}`);
146
+ }
147
+ export async function uninstallAgent(options) {
148
+ const { logger } = options;
149
+ const exec = options.exec ?? defaultExec;
150
+ const plistPath = options.plistPath ?? defaultPlistPath();
151
+ if (!existsSync(plistPath)) {
152
+ throw new Error(`No launchd agent found at ${plistPath}`);
153
+ }
154
+ // Read plist to detect auto-patch and proxy before removing
155
+ const plistContent = await readFile(plistPath, "utf-8");
156
+ const parsed = parsePlistArgs(plistContent);
157
+ // Unload the agent
158
+ try {
159
+ await exec("launchctl", ["unload", plistPath]);
160
+ }
161
+ catch (err) {
162
+ logger.warn(`launchctl unload failed: ${String(err)}`);
163
+ }
164
+ // Delete the plist
165
+ await unlink(plistPath);
166
+ // Restore settings if auto-patch was enabled
167
+ if (parsed.autoPatch && parsed.proxy) {
168
+ const patcher = patcherByProxy[parsed.proxy];
169
+ if (patcher) {
170
+ await patcher.restore({ logger });
171
+ }
172
+ }
173
+ logger.info(`Launchd agent uninstalled: ${AGENT_LABEL}`);
174
+ }
175
+ //# sourceMappingURL=launchd-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launchd-agent.js","sourceRoot":"","sources":["../src/launchd-agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export type NativeActivateFn = (name: string) => number[];
2
+ export interface ActivateSocketOptions {
3
+ nativeActivate?: NativeActivateFn;
4
+ }
5
+ export declare function activateSocket(name: string, options?: ActivateSocketOptions): number[];
@@ -0,0 +1,33 @@
1
+ // Wrapper around macOS launch_activate_socket() for launchd socket activation.
2
+ //
3
+ // When launchd starts a process via socket activation, the listening socket(s)
4
+ // are held by launchd and must be "checked out" via launch_activate_socket().
5
+ // This module uses koffi (FFI) to call that C function from JavaScript.
6
+ import koffi from "koffi";
7
+ function defaultNativeActivate(name) {
8
+ const lib = koffi.load("/usr/lib/libSystem.B.dylib");
9
+ const launch_activate_socket = lib.func("int launch_activate_socket(const char *name, _Out_ int **fds, _Out_ size_t *cnt)");
10
+ const fdsOut = [null];
11
+ const cntOut = [0];
12
+ const ret = launch_activate_socket(name, fdsOut, cntOut);
13
+ if (ret !== 0) {
14
+ const messages = {
15
+ 3: "Socket name not found in launchd job (ESRCH)",
16
+ 2: "No socket with that name (ENOENT)",
17
+ };
18
+ const msg = messages[ret] ?? `errno ${String(ret)}`;
19
+ throw new Error(`launch_activate_socket failed: ${msg}`);
20
+ }
21
+ const cnt = cntOut[0];
22
+ if (cnt === 0) {
23
+ return [];
24
+ }
25
+ const ptr = fdsOut[0];
26
+ const fds = koffi.decode(ptr, "int", cnt);
27
+ return fds;
28
+ }
29
+ export function activateSocket(name, options) {
30
+ const activate = options?.nativeActivate ?? defaultNativeActivate;
31
+ return activate(name);
32
+ }
33
+ //# sourceMappingURL=launchd-socket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launchd-socket.js","sourceRoot":"","sources":["../src/launchd-socket.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,EAAE;AACF,+EAA+E;AAC/E,8EAA8E;AAC9E,wEAAwE;AAExE,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,SAAS,qBAAqB,CAAC,IAAY;IACzC,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IAErD,MAAM,sBAAsB,GAAG,GAAG,CAAC,IAAI,CACrC,kFAAkF,CACnF,CAAC;IAEF,MAAM,MAAM,GAAc,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAEnB,MAAM,GAAG,GAAG,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAW,CAAC;IAEnE,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;QACd,MAAM,QAAQ,GAA2B;YACvC,CAAC,EAAE,8CAA8C;YACjD,CAAC,EAAE,mCAAmC;SACvC,CAAC;QACF,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,SAAS,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,kCAAkC,GAAG,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAW,CAAC;IAChC,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;QACd,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACtB,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAa,CAAC;IACtD,OAAO,GAAG,CAAC;AACb,CAAC;AAMD,MAAM,UAAU,cAAc,CAC5B,IAAY,EACZ,OAA+B;IAE/B,MAAM,QAAQ,GAAG,OAAO,EAAE,cAAc,IAAI,qBAAqB,CAAC;IAClE,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC"}
package/dist/startup.d.ts CHANGED
@@ -7,5 +7,7 @@ export interface StartOptions {
7
7
  config?: string;
8
8
  cwd?: string;
9
9
  autoPatch?: true;
10
+ launchd?: true;
11
+ idleTimeout?: string;
10
12
  }
11
13
  export declare function startServer(options: StartOptions): Promise<void>;
package/dist/startup.js CHANGED
@@ -7,8 +7,9 @@ import { createServer } from "./server.js";
7
7
  import { Logger } from "./logger.js";
8
8
  import { providers } from "./providers/index.js";
9
9
  import { patcherByProxy } from "./settings-patcher/index.js";
10
- import { parsePort, parseLogLevel, parseProxy, validateAutoPatch, } from "./cli-validators.js";
10
+ import { parsePort, parseLogLevel, parseProxy, parseIdleTimeout, validateAutoPatch, } from "./cli-validators.js";
11
11
  import { bold, dim, createSpinner, printBanner } from "./ui.js";
12
+ import { activateSocket } from "./launchd/index.js";
12
13
  const AGENTS_DIR = join(homedir(), "Library/Developer/Xcode/CodingAssistant/Agents/Versions");
13
14
  const AGENT_BINARY_NAMES = {
14
15
  claude: "claude",
@@ -39,8 +40,12 @@ export async function startServer(options) {
39
40
  const logger = new Logger(logLevel);
40
41
  const port = parsePort(options.port);
41
42
  const proxy = parseProxy(options.proxy);
42
- const autoPatch = options.autoPatch === true;
43
- validateAutoPatch(proxy, autoPatch);
43
+ const idleTimeoutMinutes = options.idleTimeout ? parseIdleTimeout(options.idleTimeout) : 0;
44
+ const launchdMode = options.launchd === true;
45
+ const autoPatch = options.autoPatch === true && !launchdMode;
46
+ if (!launchdMode) {
47
+ validateAutoPatch(proxy, options.autoPatch === true);
48
+ }
44
49
  const provider = providers[proxy];
45
50
  const configPath = options.config ?? resolveConfigPath(options.cwd, process.cwd(), options.defaultConfigPath);
46
51
  const config = await loadConfig(configPath, logger, proxy);
@@ -50,7 +55,7 @@ export async function startServer(options) {
50
55
  logger,
51
56
  cwd,
52
57
  });
53
- const quiet = logLevel === "none";
58
+ const quiet = logLevel === "none" || launchdMode;
54
59
  if (!quiet) {
55
60
  console.log();
56
61
  console.log(` ${bold("xcode-copilot-server")} ${dim(`v${options.version}`)}`);
@@ -85,10 +90,30 @@ export async function startServer(options) {
85
90
  }
86
91
  const ctx = { service, logger, config, port };
87
92
  const app = await createServer(ctx, provider);
93
+ // Register hooks before listen as Fastify forbids addHook after listen.
94
+ let lastActivity = Date.now();
95
+ if (idleTimeoutMinutes > 0) {
96
+ app.addHook("onResponse", () => {
97
+ lastActivity = Date.now();
98
+ });
99
+ }
88
100
  const listenSpinner = quiet ? null : createSpinner(`Starting server on port ${String(port)}...`);
89
101
  const prevPinoLevel = app.log.level;
90
102
  app.log.level = "silent";
91
- await app.listen({ port, host: "127.0.0.1" });
103
+ if (launchdMode) {
104
+ const fds = activateSocket("Listeners");
105
+ const fd = fds[0];
106
+ if (fd === undefined) {
107
+ throw new Error("launch_activate_socket returned no file descriptors");
108
+ }
109
+ // TODO: Remove cast when Fastify types add fd support
110
+ // @ts-expect-error Fastify supports listen({ fd }) at runtime but the types don't include it yet
111
+ await app.listen({ fd });
112
+ logger.info(`Listening via launchd socket activation (fd ${String(fd)}, port ${String(port)})`);
113
+ }
114
+ else {
115
+ await app.listen({ port, host: "127.0.0.1" });
116
+ }
92
117
  app.log.level = prevPinoLevel;
93
118
  listenSpinner?.succeed(`Listening on ${bold(`http://localhost:${String(port)}`)}`);
94
119
  if (!quiet) {
@@ -142,7 +167,11 @@ export async function startServer(options) {
142
167
  await Promise.race([stopPromise, timeoutPromise]);
143
168
  process.exit(0);
144
169
  };
170
+ let shuttingDown = false;
145
171
  const onSignal = (signal) => {
172
+ if (shuttingDown)
173
+ return;
174
+ shuttingDown = true;
146
175
  shutdown(signal).catch((err) => {
147
176
  console.error("Shutdown error:", err);
148
177
  process.exit(1);
@@ -150,5 +179,18 @@ export async function startServer(options) {
150
179
  };
151
180
  process.on("SIGINT", () => { onSignal("SIGINT"); });
152
181
  process.on("SIGTERM", () => { onSignal("SIGTERM"); });
182
+ if (idleTimeoutMinutes > 0) {
183
+ const idleMs = idleTimeoutMinutes * 60_000;
184
+ const checkInterval = Math.min(idleMs, 60_000);
185
+ const timer = setInterval(() => {
186
+ if (Date.now() - lastActivity >= idleMs) {
187
+ clearInterval(timer);
188
+ logger.info(`Idle for ${String(idleTimeoutMinutes)} minute(s), shutting down`);
189
+ onSignal("idle-timeout");
190
+ }
191
+ }, checkInterval);
192
+ // Don't let the timer alone keep the process alive
193
+ timer.unref();
194
+ }
153
195
  }
154
196
  //# sourceMappingURL=startup.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"startup.js","sourceRoot":"","sources":["../src/startup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"startup.js","sourceRoot":"","sources":["../src/startup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ export interface UsageData {
2
+ model: string;
3
+ inputTokens?: number;
4
+ outputTokens?: number;
5
+ cacheReadTokens?: number;
6
+ cacheWriteTokens?: number;
7
+ cost?: number;
8
+ duration?: number;
9
+ }
10
+ export interface ModelMetricsSnapshot {
11
+ requests: number;
12
+ cost: number;
13
+ inputTokens: number;
14
+ outputTokens: number;
15
+ cacheReadTokens: number;
16
+ cacheWriteTokens: number;
17
+ }
18
+ export interface StatsSnapshot {
19
+ requests: number;
20
+ sessions: number;
21
+ inputTokens: number;
22
+ outputTokens: number;
23
+ cacheReadTokens: number;
24
+ cacheWriteTokens: number;
25
+ totalCost: number;
26
+ apiDurationMs: number;
27
+ errors: number;
28
+ uptimeMs: number;
29
+ modelMetrics: Record<string, ModelMetricsSnapshot>;
30
+ }
31
+ export declare class Stats {
32
+ requests: number;
33
+ sessions: number;
34
+ inputTokens: number;
35
+ outputTokens: number;
36
+ cacheReadTokens: number;
37
+ cacheWriteTokens: number;
38
+ totalCost: number;
39
+ apiDurationMs: number;
40
+ errors: number;
41
+ private startTime;
42
+ private byModel;
43
+ recordUsage(data: UsageData): void;
44
+ recordRequest(): void;
45
+ recordSession(): void;
46
+ recordError(): void;
47
+ snapshot(): StatsSnapshot;
48
+ }
package/dist/stats.js ADDED
@@ -0,0 +1,68 @@
1
+ export class Stats {
2
+ requests = 0;
3
+ sessions = 0;
4
+ inputTokens = 0;
5
+ outputTokens = 0;
6
+ cacheReadTokens = 0;
7
+ cacheWriteTokens = 0;
8
+ totalCost = 0;
9
+ apiDurationMs = 0;
10
+ errors = 0;
11
+ startTime = Date.now();
12
+ byModel = new Map();
13
+ recordUsage(data) {
14
+ const input = data.inputTokens ?? 0;
15
+ const output = data.outputTokens ?? 0;
16
+ const cacheRead = data.cacheReadTokens ?? 0;
17
+ const cacheWrite = data.cacheWriteTokens ?? 0;
18
+ const cost = data.cost ?? 0;
19
+ const duration = data.duration ?? 0;
20
+ this.inputTokens += input;
21
+ this.outputTokens += output;
22
+ this.cacheReadTokens += cacheRead;
23
+ this.cacheWriteTokens += cacheWrite;
24
+ this.totalCost += cost;
25
+ this.apiDurationMs += duration;
26
+ const { model } = data;
27
+ const existing = this.byModel.get(model);
28
+ if (existing) {
29
+ existing.requests++;
30
+ existing.cost += cost;
31
+ existing.inputTokens += input;
32
+ existing.outputTokens += output;
33
+ existing.cacheReadTokens += cacheRead;
34
+ existing.cacheWriteTokens += cacheWrite;
35
+ }
36
+ else {
37
+ this.byModel.set(model, {
38
+ requests: 1, cost, inputTokens: input, outputTokens: output,
39
+ cacheReadTokens: cacheRead, cacheWriteTokens: cacheWrite,
40
+ });
41
+ }
42
+ }
43
+ recordRequest() {
44
+ this.requests++;
45
+ }
46
+ recordSession() {
47
+ this.sessions++;
48
+ }
49
+ recordError() {
50
+ this.errors++;
51
+ }
52
+ snapshot() {
53
+ return {
54
+ requests: this.requests,
55
+ sessions: this.sessions,
56
+ inputTokens: this.inputTokens,
57
+ outputTokens: this.outputTokens,
58
+ cacheReadTokens: this.cacheReadTokens,
59
+ cacheWriteTokens: this.cacheWriteTokens,
60
+ totalCost: this.totalCost,
61
+ apiDurationMs: this.apiDurationMs,
62
+ errors: this.errors,
63
+ uptimeMs: Date.now() - this.startTime,
64
+ modelMetrics: Object.fromEntries(this.byModel),
65
+ };
66
+ }
67
+ }
68
+ //# sourceMappingURL=stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.js","sourceRoot":"","sources":["../src/stats.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { StatsSnapshot } from "./stats.js";
2
+ export declare class StatusLine {
3
+ private lastContent;
4
+ private visible;
5
+ private resizeHandler;
6
+ constructor();
7
+ clearLine(): void;
8
+ update(snap: StatsSnapshot): void;
9
+ redraw(): void;
10
+ clear(): void;
11
+ }
@@ -0,0 +1,101 @@
1
+ import readline from "node:readline";
2
+ import { dim } from "./ui.js";
3
+ function formatTokenCount(n) {
4
+ if (n >= 1_000_000)
5
+ return `${(n / 1_000_000).toFixed(1)}M`;
6
+ if (n >= 1_000)
7
+ return `${(n / 1_000).toFixed(1)}k`;
8
+ return String(n);
9
+ }
10
+ function formatUptime(ms) {
11
+ const totalSeconds = Math.floor(ms / 1000);
12
+ const hours = Math.floor(totalSeconds / 3600);
13
+ const minutes = Math.floor((totalSeconds % 3600) / 60);
14
+ const seconds = totalSeconds % 60;
15
+ if (hours > 0)
16
+ return `${String(hours)}h ${String(minutes)}m`;
17
+ if (minutes > 0)
18
+ return `${String(minutes)}m ${String(seconds)}s`;
19
+ return `${String(seconds)}s`;
20
+ }
21
+ function formatCost(cost) {
22
+ if (cost === 0)
23
+ return "$0";
24
+ if (cost < 0.01)
25
+ return `$${cost.toFixed(4)}`;
26
+ return `$${cost.toFixed(2)}`;
27
+ }
28
+ function buildContent(snap) {
29
+ const parts = [];
30
+ parts.push(`${String(snap.requests)} request${snap.requests !== 1 ? "s" : ""}`);
31
+ if (snap.inputTokens > 0 || snap.outputTokens > 0) {
32
+ parts.push(`${formatTokenCount(snap.inputTokens)} in`);
33
+ parts.push(`${formatTokenCount(snap.outputTokens)} out`);
34
+ }
35
+ if (snap.cacheReadTokens > 0) {
36
+ parts.push(`${formatTokenCount(snap.cacheReadTokens)} cached`);
37
+ }
38
+ if (snap.totalCost > 0) {
39
+ parts.push(formatCost(snap.totalCost));
40
+ }
41
+ parts.push(`${formatUptime(snap.uptimeMs)} uptime`);
42
+ return parts.join(dim(" │ "));
43
+ }
44
+ // ANSI codes mess up width calculations for right-alignment
45
+ // eslint-disable-next-line no-control-regex
46
+ const ANSI_RE = /\x1B\[[0-9;]*m/g;
47
+ function stripAnsi(s) {
48
+ return s.replace(ANSI_RE, "");
49
+ }
50
+ // When visible, cursor sits above the status line so log output goes in the right place.
51
+ // clearLine() and redraw() both maintain this — the status is 1 line below the cursor.
52
+ export class StatusLine {
53
+ lastContent = "";
54
+ visible = false;
55
+ resizeHandler = null;
56
+ constructor() {
57
+ this.resizeHandler = () => {
58
+ this.clearLine();
59
+ this.redraw();
60
+ };
61
+ process.stdout.on("resize", this.resizeHandler);
62
+ }
63
+ clearLine() {
64
+ if (!this.visible)
65
+ return;
66
+ readline.moveCursor(process.stdout, 0, 1);
67
+ readline.cursorTo(process.stdout, 0);
68
+ readline.clearLine(process.stdout, 0);
69
+ readline.moveCursor(process.stdout, 0, -1);
70
+ this.visible = false;
71
+ }
72
+ update(snap) {
73
+ this.lastContent = buildContent(snap);
74
+ this.clearLine();
75
+ this.redraw();
76
+ }
77
+ redraw() {
78
+ if (!this.lastContent)
79
+ return;
80
+ const cols = process.stdout.columns;
81
+ const visibleLen = stripAnsi(this.lastContent).length;
82
+ const pad = Math.max(0, cols - visibleLen - 2);
83
+ process.stdout.write(`\n${" ".repeat(pad)}${dim(this.lastContent)}`);
84
+ // Put cursor back above so log output lands in the right spot
85
+ readline.moveCursor(process.stdout, 0, -1);
86
+ readline.cursorTo(process.stdout, 0);
87
+ this.visible = true;
88
+ }
89
+ clear() {
90
+ if (this.resizeHandler) {
91
+ process.stdout.off("resize", this.resizeHandler);
92
+ this.resizeHandler = null;
93
+ }
94
+ if (!this.visible)
95
+ return;
96
+ this.clearLine();
97
+ this.visible = false;
98
+ this.lastContent = "";
99
+ }
100
+ }
101
+ //# sourceMappingURL=status-line.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-line.js","sourceRoot":"","sources":["../src/status-line.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xcode-copilot-server",
3
- "version": "3.0.0",
3
+ "version": "3.1.1",
4
4
  "description": "OpenAI-compatible proxy API server for Xcode, powered by GitHub Copilot",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -31,21 +31,24 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@fastify/cors": "11.2.0",
34
- "@github/copilot-sdk": "0.1.23",
34
+ "@github/copilot-sdk": "0.1.24",
35
35
  "commander": "14.0.3",
36
36
  "fastify": "5.7.4",
37
37
  "json5": "2.2.3",
38
+ "koffi": "2.15.1",
38
39
  "picocolors": "1.1.1",
40
+ "plist": "3.1.0",
39
41
  "tokenx": "1.3.0",
40
42
  "zod": "4.3.6"
41
43
  },
42
44
  "devDependencies": {
43
- "@eslint/js": "9.39.2",
45
+ "@eslint/js": "10.0.1",
44
46
  "@types/node": "25.2.3",
45
- "eslint": "9.39.2",
47
+ "@types/plist": "^3.0.5",
48
+ "eslint": "10.0.0",
46
49
  "tsx": "4.21.0",
47
50
  "typescript": "5.9.3",
48
- "typescript-eslint": "8.55.0",
51
+ "typescript-eslint": "8.56.0",
49
52
  "vitest": "4.0.18"
50
53
  }
51
54
  }