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.
Files changed (153) hide show
  1. package/README.md +94 -29
  2. package/config.json5 +13 -8
  3. package/dist/cli-validators.d.ts +6 -0
  4. package/dist/cli-validators.js +35 -0
  5. package/dist/cli-validators.js.map +1 -0
  6. package/dist/config.d.ts +3 -3
  7. package/dist/config.js +11 -10
  8. package/dist/config.js.map +1 -1
  9. package/dist/conversation-manager.d.ts +2 -1
  10. package/dist/conversation-manager.js +20 -1
  11. package/dist/conversation-manager.js.map +1 -1
  12. package/dist/handlers/responses/streaming.d.ts +6 -0
  13. package/dist/handlers/responses/streaming.js +265 -0
  14. package/dist/handlers/responses/streaming.js.map +1 -0
  15. package/dist/handlers/responses/tool-result-handler.d.ts +4 -0
  16. package/dist/handlers/responses/tool-result-handler.js +9 -0
  17. package/dist/handlers/responses/tool-result-handler.js.map +1 -0
  18. package/dist/handlers/responses.d.ts +4 -0
  19. package/dist/handlers/responses.js +164 -0
  20. package/dist/handlers/responses.js.map +1 -0
  21. package/dist/handlers/streaming-utils.d.ts +1 -0
  22. package/dist/handlers/streaming-utils.js +3 -0
  23. package/dist/handlers/streaming-utils.js.map +1 -1
  24. package/dist/index.js +51 -132
  25. package/dist/index.js.map +1 -1
  26. package/dist/logger.js +15 -4
  27. package/dist/logger.js.map +1 -1
  28. package/dist/providers/claude/count-tokens.d.ts +3 -0
  29. package/dist/providers/claude/count-tokens.js +72 -0
  30. package/dist/providers/claude/count-tokens.js.map +1 -0
  31. package/dist/providers/claude/handler.d.ts +4 -0
  32. package/dist/providers/claude/handler.js +150 -0
  33. package/dist/providers/claude/handler.js.map +1 -0
  34. package/dist/providers/claude/prompt.d.ts +2 -0
  35. package/dist/providers/claude/prompt.js +52 -0
  36. package/dist/providers/claude/prompt.js.map +1 -0
  37. package/dist/providers/claude/provider.d.ts +5 -0
  38. package/dist/providers/claude/provider.js +28 -0
  39. package/dist/providers/claude/provider.js.map +1 -0
  40. package/dist/providers/claude/schemas.d.ts +140 -0
  41. package/dist/providers/claude/schemas.js +58 -0
  42. package/dist/providers/claude/schemas.js.map +1 -0
  43. package/dist/providers/claude/streaming.d.ts +6 -0
  44. package/dist/providers/claude/streaming.js +116 -0
  45. package/dist/providers/claude/streaming.js.map +1 -0
  46. package/dist/providers/claude/tool-results.d.ts +4 -0
  47. package/dist/providers/claude/tool-results.js +19 -0
  48. package/dist/providers/claude/tool-results.js.map +1 -0
  49. package/dist/providers/codex/handler.d.ts +4 -0
  50. package/dist/providers/codex/handler.js +164 -0
  51. package/dist/providers/codex/handler.js.map +1 -0
  52. package/dist/providers/codex/prompt.d.ts +4 -0
  53. package/dist/providers/codex/prompt.js +58 -0
  54. package/dist/providers/codex/prompt.js.map +1 -0
  55. package/dist/providers/codex/provider.d.ts +5 -0
  56. package/dist/providers/codex/provider.js +24 -0
  57. package/dist/providers/codex/provider.js.map +1 -0
  58. package/dist/providers/codex/schemas.d.ts +122 -0
  59. package/dist/providers/codex/schemas.js +55 -0
  60. package/dist/providers/codex/schemas.js.map +1 -0
  61. package/dist/providers/codex/streaming.d.ts +9 -0
  62. package/dist/providers/codex/streaming.js +172 -0
  63. package/dist/providers/codex/streaming.js.map +1 -0
  64. package/dist/providers/codex/tool-results.d.ts +4 -0
  65. package/dist/providers/codex/tool-results.js +9 -0
  66. package/dist/providers/codex/tool-results.js.map +1 -0
  67. package/dist/providers/codex.d.ts +5 -0
  68. package/dist/providers/codex.js +24 -0
  69. package/dist/providers/codex.js.map +1 -0
  70. package/dist/providers/index.d.ts +6 -1
  71. package/dist/providers/index.js +5 -3
  72. package/dist/providers/index.js.map +1 -1
  73. package/dist/providers/openai/handler.d.ts +4 -0
  74. package/dist/providers/openai/handler.js +120 -0
  75. package/dist/providers/openai/handler.js.map +1 -0
  76. package/dist/providers/openai/models.d.ts +3 -0
  77. package/dist/providers/openai/models.js +28 -0
  78. package/dist/providers/openai/models.js.map +1 -0
  79. package/dist/providers/openai/prompt.d.ts +3 -0
  80. package/dist/providers/openai/prompt.js +38 -0
  81. package/dist/providers/openai/prompt.js.map +1 -0
  82. package/dist/providers/openai/provider.d.ts +5 -0
  83. package/dist/providers/openai/provider.js +25 -0
  84. package/dist/providers/openai/provider.js.map +1 -0
  85. package/dist/providers/openai/schemas.d.ts +98 -0
  86. package/dist/providers/openai/schemas.js +76 -0
  87. package/dist/providers/openai/schemas.js.map +1 -0
  88. package/dist/providers/openai/streaming.d.ts +4 -0
  89. package/dist/providers/openai/streaming.js +121 -0
  90. package/dist/providers/openai/streaming.js.map +1 -0
  91. package/dist/providers/shared/errors.d.ts +5 -0
  92. package/dist/providers/shared/errors.js +10 -0
  93. package/dist/providers/shared/errors.js.map +1 -0
  94. package/dist/providers/shared/model-resolver.d.ts +3 -0
  95. package/dist/providers/shared/model-resolver.js +45 -0
  96. package/dist/providers/shared/model-resolver.js.map +1 -0
  97. package/dist/providers/shared/prompt-utils.d.ts +1 -0
  98. package/dist/providers/shared/prompt-utils.js +15 -0
  99. package/dist/providers/shared/prompt-utils.js.map +1 -0
  100. package/dist/providers/shared/session-config.d.ts +15 -0
  101. package/dist/providers/shared/session-config.js +98 -0
  102. package/dist/providers/shared/session-config.js.map +1 -0
  103. package/dist/providers/shared/streaming-core.d.ts +19 -0
  104. package/dist/providers/shared/streaming-core.js +176 -0
  105. package/dist/providers/shared/streaming-core.js.map +1 -0
  106. package/dist/providers/shared/streaming-utils.d.ts +10 -0
  107. package/dist/providers/shared/streaming-utils.js +28 -0
  108. package/dist/providers/shared/streaming-utils.js.map +1 -0
  109. package/dist/schemas/config.d.ts +19 -1
  110. package/dist/schemas/config.js +2 -1
  111. package/dist/schemas/config.js.map +1 -1
  112. package/dist/schemas/responses.d.ts +122 -0
  113. package/dist/schemas/responses.js +54 -0
  114. package/dist/schemas/responses.js.map +1 -0
  115. package/dist/server.js +1 -2
  116. package/dist/server.js.map +1 -1
  117. package/dist/settings-patcher/anthropic.d.ts +5 -0
  118. package/dist/{settings-patcher.js → settings-patcher/anthropic.js} +3 -7
  119. package/dist/settings-patcher/anthropic.js.map +1 -0
  120. package/dist/settings-patcher/claude.d.ts +5 -0
  121. package/dist/settings-patcher/claude.js +75 -0
  122. package/dist/settings-patcher/claude.js.map +1 -0
  123. package/dist/settings-patcher/codex.d.ts +23 -0
  124. package/dist/settings-patcher/codex.js +114 -0
  125. package/dist/settings-patcher/codex.js.map +1 -0
  126. package/dist/settings-patcher/index.d.ts +15 -0
  127. package/dist/settings-patcher/index.js +9 -0
  128. package/dist/settings-patcher/index.js.map +1 -0
  129. package/dist/{settings-patcher.d.ts → settings-patcher/types.d.ts} +1 -5
  130. package/dist/settings-patcher/types.js +2 -0
  131. package/dist/settings-patcher/types.js.map +1 -0
  132. package/dist/startup.d.ts +11 -0
  133. package/dist/startup.js +154 -0
  134. package/dist/startup.js.map +1 -0
  135. package/dist/tool-bridge/constants.d.ts +2 -0
  136. package/dist/tool-bridge/constants.js +3 -0
  137. package/dist/tool-bridge/constants.js.map +1 -0
  138. package/dist/tool-bridge/index.d.ts +1 -0
  139. package/dist/tool-bridge/index.js +1 -0
  140. package/dist/tool-bridge/index.js.map +1 -1
  141. package/dist/tool-bridge/routes.js +2 -1
  142. package/dist/tool-bridge/routes.js.map +1 -1
  143. package/dist/tool-bridge/session-lifecycle.js +1 -1
  144. package/dist/tool-bridge/state.d.ts +1 -1
  145. package/dist/tool-bridge/tool-cache.d.ts +1 -1
  146. package/dist/ui.d.ts +36 -0
  147. package/dist/ui.js +71 -0
  148. package/dist/ui.js.map +1 -0
  149. package/dist/utils/responses-prompt.d.ts +4 -0
  150. package/dist/utils/responses-prompt.js +58 -0
  151. package/dist/utils/responses-prompt.js.map +1 -0
  152. package/package.json +3 -1
  153. package/dist/settings-patcher.js.map +0 -1
@@ -0,0 +1,28 @@
1
+ import { currentTimestamp } from "./schemas.js";
2
+ export function createModelsHandler({ service, logger }) {
3
+ return async function handleModels(_request, reply) {
4
+ try {
5
+ const models = await service.listModels();
6
+ const response = {
7
+ object: "list",
8
+ data: models.map((m) => ({
9
+ id: m.id,
10
+ object: "model",
11
+ created: currentTimestamp(),
12
+ owned_by: "github-copilot",
13
+ })),
14
+ };
15
+ reply.send(response);
16
+ }
17
+ catch (err) {
18
+ logger.error("Couldn't fetch models:", err);
19
+ reply.status(500).send({
20
+ error: {
21
+ message: "Failed to list models",
22
+ type: "api_error",
23
+ },
24
+ });
25
+ }
26
+ };
27
+ }
28
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../../src/providers/openai/models.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,UAAU,mBAAmB,CAAC,EAAE,OAAO,EAAE,MAAM,EAAc;IACjE,OAAO,KAAK,UAAU,YAAY,CAChC,QAAwB,EACxB,KAAmB;QAEnB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;YAE1C,MAAM,QAAQ,GAAG;gBACf,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACvB,EAAE,EAAE,CAAC,CAAC,EAAE;oBACR,MAAM,EAAE,OAAgB;oBACxB,OAAO,EAAE,gBAAgB,EAAE;oBAC3B,QAAQ,EAAE,gBAAgB;iBAC3B,CAAC,CAAC;aACqB,CAAC;YAE3B,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC;YAC5C,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACrB,KAAK,EAAE;oBACL,OAAO,EAAE,uBAAuB;oBAChC,IAAI,EAAE,WAAW;iBAClB;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type ChatCompletionMessage } from "./schemas.js";
2
+ export { filterExcludedFiles } from "../shared/prompt-utils.js";
3
+ export declare function formatPrompt(messages: ChatCompletionMessage[], excludedFilePatterns: string[]): string;
@@ -0,0 +1,38 @@
1
+ import { extractContentText } from "./schemas.js";
2
+ import { filterExcludedFiles } from "../shared/prompt-utils.js";
3
+ export { filterExcludedFiles } from "../shared/prompt-utils.js";
4
+ // System/developer messages are skipped because they're passed separately via
5
+ // SessionConfig.systemMessage.
6
+ export function formatPrompt(messages, excludedFilePatterns) {
7
+ const parts = [];
8
+ for (const msg of messages) {
9
+ const content = extractContentText(msg.content);
10
+ switch (msg.role) {
11
+ case "system":
12
+ case "developer":
13
+ continue;
14
+ case "user":
15
+ parts.push(`[User]: ${filterExcludedFiles(content, excludedFilePatterns)}`);
16
+ break;
17
+ case "assistant":
18
+ if (content) {
19
+ parts.push(`[Assistant]: ${content}`);
20
+ }
21
+ if (msg.tool_calls) {
22
+ for (const tc of msg.tool_calls) {
23
+ parts.push(`[Assistant called tool ${tc.function.name} with args: ${tc.function.arguments}]`);
24
+ }
25
+ }
26
+ break;
27
+ case "tool":
28
+ parts.push(`[Tool result for ${msg.tool_call_id ?? "unknown"}]: ${content}`);
29
+ break;
30
+ case undefined:
31
+ break;
32
+ default:
33
+ throw msg.role;
34
+ }
35
+ }
36
+ return parts.join("\n\n");
37
+ }
38
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../src/providers/openai/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA8B,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEhE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEhE,8EAA8E;AAC9E,+BAA+B;AAC/B,MAAM,UAAU,YAAY,CAC1B,QAAiC,EACjC,oBAA8B;IAE9B,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEhD,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YACjB,KAAK,QAAQ,CAAC;YACd,KAAK,WAAW;gBACd,SAAS;YAEX,KAAK,MAAM;gBACT,KAAK,CAAC,IAAI,CAAC,WAAW,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,CAAC,EAAE,CAAC,CAAC;gBAC5E,MAAM;YAER,KAAK,WAAW;gBACd,IAAI,OAAO,EAAE,CAAC;oBACZ,KAAK,CAAC,IAAI,CAAC,gBAAgB,OAAO,EAAE,CAAC,CAAC;gBACxC,CAAC;gBACD,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;oBACnB,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;wBAChC,KAAK,CAAC,IAAI,CACR,0BAA0B,EAAE,CAAC,QAAQ,CAAC,IAAI,eAAe,EAAE,CAAC,QAAQ,CAAC,SAAS,GAAG,CAClF,CAAC;oBACJ,CAAC;gBACH,CAAC;gBACD,MAAM;YAER,KAAK,MAAM;gBACT,KAAK,CAAC,IAAI,CAAC,oBAAoB,GAAG,CAAC,YAAY,IAAI,SAAS,MAAM,OAAO,EAAE,CAAC,CAAC;gBAC7E,MAAM;YAER,KAAK,SAAS;gBACZ,MAAM;YAER;gBACE,MAAM,GAAG,CAAC,IAAoB,CAAC;QACnC,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const openaiProvider: {
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,25 @@
1
+ import { createModelsHandler } from "./models.js";
2
+ import { createCompletionsHandler } from "./handler.js";
3
+ import { ConversationManager } from "../../conversation-manager.js";
4
+ export const openaiProvider = {
5
+ name: "OpenAI",
6
+ routes: ["GET /v1/models", "POST /v1/chat/completions"],
7
+ register(app, ctx) {
8
+ app.addHook("onRequest", (request, reply, done) => {
9
+ const ua = request.headers["user-agent"] ?? "";
10
+ if (!ua.startsWith("Xcode/")) {
11
+ ctx.logger.warn(`Rejected request from unexpected user-agent: ${ua}`);
12
+ void reply
13
+ .code(403)
14
+ .type("application/json")
15
+ .send('{"error":"Forbidden"}\n');
16
+ return;
17
+ }
18
+ done();
19
+ });
20
+ const manager = new ConversationManager(ctx.logger);
21
+ app.get("/v1/models", createModelsHandler(ctx));
22
+ app.post("/v1/chat/completions", createCompletionsHandler(ctx, manager));
23
+ },
24
+ };
25
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/providers/openai/provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEpE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,CAAC,gBAAgB,EAAE,2BAA2B,CAAC;IAEvD,QAAQ,CAAC,GAAG,EAAE,GAAG;QACf,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAChD,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;YAC/C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC7B,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,gDAAgD,EAAE,EAAE,CACrD,CAAC;gBACF,KAAK,KAAK;qBACP,IAAI,CAAC,GAAG,CAAC;qBACT,IAAI,CAAC,kBAAkB,CAAC;qBACxB,IAAI,CAAC,yBAAyB,CAAC,CAAC;gBACnC,OAAO;YACT,CAAC;YAED,IAAI,EAAE,CAAC;QACT,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,IAAI,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpD,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC;QAChD,GAAG,CAAC,IAAI,CAAC,sBAAsB,EAAE,wBAAwB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3E,CAAC;CACiB,CAAC"}
@@ -0,0 +1,98 @@
1
+ import { z } from "zod";
2
+ declare const MessageSchema: z.ZodObject<{
3
+ role: z.ZodOptional<z.ZodEnum<{
4
+ system: "system";
5
+ developer: "developer";
6
+ user: "user";
7
+ assistant: "assistant";
8
+ tool: "tool";
9
+ }>>;
10
+ content: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodObject<{
11
+ type: z.ZodString;
12
+ text: z.ZodOptional<z.ZodString>;
13
+ }, z.core.$loose>>, z.ZodNull]>>;
14
+ name: z.ZodOptional<z.ZodString>;
15
+ tool_calls: z.ZodOptional<z.ZodArray<z.ZodObject<{
16
+ index: z.ZodOptional<z.ZodNumber>;
17
+ id: z.ZodOptional<z.ZodString>;
18
+ type: z.ZodOptional<z.ZodString>;
19
+ function: z.ZodObject<{
20
+ name: z.ZodString;
21
+ arguments: z.ZodString;
22
+ }, z.core.$strip>;
23
+ }, z.core.$strip>>>;
24
+ tool_call_id: z.ZodOptional<z.ZodString>;
25
+ }, z.core.$strip>;
26
+ export type ChatCompletionMessage = z.infer<typeof MessageSchema>;
27
+ export declare const ChatCompletionRequestSchema: z.ZodObject<{
28
+ model: z.ZodString;
29
+ messages: z.ZodArray<z.ZodObject<{
30
+ role: z.ZodOptional<z.ZodEnum<{
31
+ system: "system";
32
+ developer: "developer";
33
+ user: "user";
34
+ assistant: "assistant";
35
+ tool: "tool";
36
+ }>>;
37
+ content: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodObject<{
38
+ type: z.ZodString;
39
+ text: z.ZodOptional<z.ZodString>;
40
+ }, z.core.$loose>>, z.ZodNull]>>;
41
+ name: z.ZodOptional<z.ZodString>;
42
+ tool_calls: z.ZodOptional<z.ZodArray<z.ZodObject<{
43
+ index: z.ZodOptional<z.ZodNumber>;
44
+ id: z.ZodOptional<z.ZodString>;
45
+ type: z.ZodOptional<z.ZodString>;
46
+ function: z.ZodObject<{
47
+ name: z.ZodString;
48
+ arguments: z.ZodString;
49
+ }, z.core.$strip>;
50
+ }, z.core.$strip>>>;
51
+ tool_call_id: z.ZodOptional<z.ZodString>;
52
+ }, z.core.$strip>>;
53
+ temperature: z.ZodOptional<z.ZodNumber>;
54
+ top_p: z.ZodOptional<z.ZodNumber>;
55
+ n: z.ZodOptional<z.ZodNumber>;
56
+ stop: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
57
+ max_tokens: z.ZodOptional<z.ZodNumber>;
58
+ presence_penalty: z.ZodOptional<z.ZodNumber>;
59
+ frequency_penalty: z.ZodOptional<z.ZodNumber>;
60
+ tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
61
+ type: z.ZodString;
62
+ function: z.ZodObject<{
63
+ name: z.ZodString;
64
+ description: z.ZodOptional<z.ZodString>;
65
+ parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
66
+ }, z.core.$strip>;
67
+ }, z.core.$strip>>>;
68
+ tool_choice: z.ZodOptional<z.ZodUnknown>;
69
+ user: z.ZodOptional<z.ZodString>;
70
+ }, z.core.$strip>;
71
+ export type ChatCompletionRequest = z.infer<typeof ChatCompletionRequestSchema>;
72
+ export interface Choice {
73
+ index: number;
74
+ message?: ChatCompletionMessage | undefined;
75
+ delta?: Partial<ChatCompletionMessage> | undefined;
76
+ finish_reason: string | null;
77
+ }
78
+ export interface ChatCompletionChunk {
79
+ id: string;
80
+ object: "chat.completion.chunk";
81
+ created: number;
82
+ model: string;
83
+ choices: Choice[];
84
+ system_fingerprint?: string | undefined;
85
+ }
86
+ export interface Model {
87
+ id: string;
88
+ object: "model";
89
+ created: number;
90
+ owned_by: string;
91
+ }
92
+ export interface ModelsResponse {
93
+ object: "list";
94
+ data: Model[];
95
+ }
96
+ export declare function currentTimestamp(): number;
97
+ export declare function extractContentText(content: ChatCompletionMessage["content"]): string;
98
+ export {};
@@ -0,0 +1,76 @@
1
+ import { z } from "zod";
2
+ const ContentPartSchema = z.looseObject({
3
+ type: z.string(),
4
+ text: z.string().optional(),
5
+ });
6
+ const VALID_ROLES = ["system", "developer", "user", "assistant", "tool"];
7
+ const MessageSchema = z.object({
8
+ role: z.enum(VALID_ROLES).optional(),
9
+ content: z
10
+ .union([z.string(), z.array(ContentPartSchema), z.null()])
11
+ .optional(),
12
+ name: z.string().optional(),
13
+ tool_calls: z
14
+ .array(z.object({
15
+ index: z.number().optional(),
16
+ id: z.string().optional(),
17
+ type: z.string().optional(),
18
+ function: z.object({
19
+ name: z.string(),
20
+ arguments: z.string(),
21
+ }),
22
+ }))
23
+ .optional(),
24
+ tool_call_id: z.string().optional(),
25
+ });
26
+ export const ChatCompletionRequestSchema = z.object({
27
+ model: z.string().min(1, "Model is required"),
28
+ messages: z.array(MessageSchema).min(1, "Messages are required"),
29
+ temperature: z.number().optional(),
30
+ top_p: z.number().optional(),
31
+ n: z.number().optional(),
32
+ stop: z.union([z.string(), z.array(z.string())]).optional(),
33
+ max_tokens: z.number().optional(),
34
+ presence_penalty: z.number().optional(),
35
+ frequency_penalty: z.number().optional(),
36
+ tools: z
37
+ .array(z.object({
38
+ type: z.string(),
39
+ function: z.object({
40
+ name: z.string(),
41
+ description: z.string().optional(),
42
+ parameters: z.record(z.string(), z.unknown()).optional(),
43
+ }),
44
+ }))
45
+ .optional(),
46
+ tool_choice: z.unknown().optional(),
47
+ user: z.string().optional(),
48
+ });
49
+ export function currentTimestamp() {
50
+ return Math.floor(Date.now() / 1000);
51
+ }
52
+ // We only support text content, so this rejects anything else early
53
+ // and lets the caller surface a 400.
54
+ export function extractContentText(content) {
55
+ if (content == null) {
56
+ return "";
57
+ }
58
+ if (typeof content === "string") {
59
+ return content;
60
+ }
61
+ if (!Array.isArray(content)) {
62
+ throw new Error(`invalid content type: expected string or array, got ${typeof content}`);
63
+ }
64
+ let text = "";
65
+ for (const part of content) {
66
+ if (part.type !== "text") {
67
+ throw new Error(`unsupported content type: ${part.type}`);
68
+ }
69
+ if (typeof part.text !== "string") {
70
+ throw new Error("text content part missing required 'text' field");
71
+ }
72
+ text += part.text;
73
+ }
74
+ return text;
75
+ }
76
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../../src/providers/openai/schemas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { FastifyReply } from "fastify";
2
+ import type { CopilotSession } from "@github/copilot-sdk";
3
+ import type { Logger } from "../../logger.js";
4
+ export declare function handleStreaming(reply: FastifyReply, session: CopilotSession, prompt: string, model: string, logger: Logger): Promise<boolean>;
@@ -0,0 +1,121 @@
1
+ import { formatCompaction, SSE_HEADERS } from "../shared/streaming-utils.js";
2
+ import { currentTimestamp } from "./schemas.js";
3
+ const REQUEST_TIMEOUT_MS = 5 * 60 * 1000;
4
+ export async function handleStreaming(reply, session, prompt, model, logger) {
5
+ reply.raw.writeHead(200, SSE_HEADERS);
6
+ const completionId = `chatcmpl-${String(Date.now())}`;
7
+ function sendChunk(delta, finishReason) {
8
+ const chunk = {
9
+ id: completionId,
10
+ object: "chat.completion.chunk",
11
+ created: currentTimestamp(),
12
+ model,
13
+ choices: [
14
+ {
15
+ index: 0,
16
+ delta,
17
+ finish_reason: finishReason,
18
+ },
19
+ ],
20
+ };
21
+ reply.raw.write(`data: ${JSON.stringify(chunk)}\n\n`);
22
+ }
23
+ sendChunk({ role: "assistant" }, null);
24
+ const { promise, resolve } = Promise.withResolvers();
25
+ let done = false;
26
+ function cleanup() {
27
+ done = true;
28
+ clearTimeout(timeout);
29
+ unsubscribe();
30
+ }
31
+ reply.raw.on("close", () => {
32
+ if (!done) {
33
+ logger.info("Client disconnected, aborting session");
34
+ cleanup();
35
+ session.abort().catch((err) => {
36
+ logger.error("Failed to abort session:", err);
37
+ });
38
+ resolve(false);
39
+ }
40
+ });
41
+ const timeout = setTimeout(() => {
42
+ logger.warn("Stream timed out after 5 minutes");
43
+ cleanup();
44
+ reply.raw.end();
45
+ resolve(false);
46
+ }, REQUEST_TIMEOUT_MS);
47
+ // Buffer deltas so we can drop intermediate narration before tool calls
48
+ let pendingDeltas = [];
49
+ const toolNames = new Map();
50
+ function flushPending() {
51
+ for (const text of pendingDeltas) {
52
+ sendChunk({ content: text }, null);
53
+ }
54
+ pendingDeltas = [];
55
+ }
56
+ const unsubscribe = session.on((event) => {
57
+ if (event.type === "tool.execution_start") {
58
+ const d = event.data;
59
+ toolNames.set(d.toolCallId, d.toolName);
60
+ logger.debug(`Running ${d.toolName} (${JSON.stringify(d.arguments)})`);
61
+ return;
62
+ }
63
+ if (event.type === "tool.execution_complete") {
64
+ const d = event.data;
65
+ const name = toolNames.get(d.toolCallId) ?? d.toolCallId;
66
+ toolNames.delete(d.toolCallId);
67
+ const detail = d.success
68
+ ? JSON.stringify(d.result?.content)
69
+ : d.error?.message ?? "failed";
70
+ logger.debug(`${name} done (${detail})`);
71
+ return;
72
+ }
73
+ switch (event.type) {
74
+ case "assistant.message_delta":
75
+ if (event.data.deltaContent) {
76
+ pendingDeltas.push(event.data.deltaContent);
77
+ }
78
+ break;
79
+ case "assistant.message":
80
+ if (event.data.toolRequests && event.data.toolRequests.length > 0) {
81
+ logger.debug(`Calling tools (dropping buffered text): ${event.data.toolRequests.map((tr) => tr.name).join(", ")}`);
82
+ pendingDeltas = [];
83
+ }
84
+ else {
85
+ flushPending();
86
+ }
87
+ break;
88
+ case "session.idle":
89
+ logger.info("Done, wrapping up stream");
90
+ flushPending();
91
+ cleanup();
92
+ sendChunk({}, "stop");
93
+ reply.raw.write("data: [DONE]\n\n");
94
+ reply.raw.end();
95
+ resolve(true);
96
+ break;
97
+ case "session.compaction_start":
98
+ logger.info("Compacting context...");
99
+ break;
100
+ case "session.compaction_complete":
101
+ logger.info(`Context compacted: ${formatCompaction(event.data)}`);
102
+ break;
103
+ case "session.error":
104
+ logger.error(`Session error: ${event.data.message}`);
105
+ cleanup();
106
+ reply.raw.end();
107
+ resolve(false);
108
+ break;
109
+ }
110
+ });
111
+ session.send({ prompt }).catch((err) => {
112
+ logger.error("Failed to send prompt:", err);
113
+ if (!done) {
114
+ cleanup();
115
+ reply.raw.end();
116
+ }
117
+ resolve(false);
118
+ });
119
+ return promise;
120
+ }
121
+ //# sourceMappingURL=streaming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming.js","sourceRoot":"","sources":["../../../src/providers/openai/streaming.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { FastifyReply } from "fastify";
2
+ type ErrorType = "invalid_request_error" | "api_error";
3
+ export declare function sendOpenAIError(reply: FastifyReply, status: number, type: ErrorType, message: string): void;
4
+ export declare function sendAnthropicError(reply: FastifyReply, status: number, type: ErrorType, message: string): void;
5
+ export {};
@@ -0,0 +1,10 @@
1
+ export function sendOpenAIError(reply, status, type, message) {
2
+ reply.status(status).send({ error: { message, type } });
3
+ }
4
+ export function sendAnthropicError(reply, status, type, message) {
5
+ reply.status(status).send({
6
+ type: "error",
7
+ error: { type, message },
8
+ });
9
+ }
10
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/providers/shared/errors.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,eAAe,CAC7B,KAAmB,EACnB,MAAc,EACd,IAAe,EACf,OAAe;IAEf,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,KAAmB,EACnB,MAAc,EACd,IAAe,EACf,OAAe;IAEf,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;QACxB,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;KACzB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ModelInfo } from "@github/copilot-sdk";
2
+ import type { Logger } from "../../logger.js";
3
+ export declare function resolveModel(requestedModel: string, availableModels: ModelInfo[], logger?: Logger): string | undefined;
@@ -0,0 +1,45 @@
1
+ function normalize(id) {
2
+ return id.replace(/-\d{8}$/, "").replace(/\./g, "-");
3
+ }
4
+ // We need to group models by family for fallback matching, so we grab the
5
+ // prefix before the first digit (e.g. "claude-sonnet-4-5" becomes "claude-sonnet-").
6
+ // This works for Claude naming but would lump all GPT models into "gpt-"
7
+ // so it'll need reworking once we support non-Claude model families here
8
+ // e.g. if we add Codex support.
9
+ function extractFamily(id) {
10
+ const match = id.match(/^(.*?-)\d/);
11
+ return match?.[1] ?? id;
12
+ }
13
+ export function resolveModel(requestedModel, availableModels, logger) {
14
+ if (availableModels.some((m) => m.id === requestedModel)) {
15
+ return requestedModel;
16
+ }
17
+ const normalizedRequest = normalize(requestedModel);
18
+ const normalizedMatch = availableModels.find((m) => normalize(m.id) === normalizedRequest);
19
+ if (normalizedMatch) {
20
+ logger?.debug(`Model "${requestedModel}" resolved to "${normalizedMatch.id}" (normalized match)`);
21
+ return normalizedMatch.id;
22
+ }
23
+ // Requested version may not exist in Copilot yet (e.g. opus 4.6 falls back to opus 4.5),
24
+ // so fall back to the closest model in the same family.
25
+ const requestFamily = extractFamily(normalizedRequest);
26
+ const familyMatches = availableModels.filter((m) => extractFamily(normalize(m.id)) === requestFamily);
27
+ let best;
28
+ let bestLen = 0;
29
+ for (const m of familyMatches) {
30
+ const norm = normalize(m.id);
31
+ let len = 0;
32
+ const minLen = Math.min(normalizedRequest.length, norm.length);
33
+ while (len < minLen && normalizedRequest[len] === norm[len])
34
+ len++;
35
+ if (len > bestLen) {
36
+ bestLen = len;
37
+ best = m;
38
+ }
39
+ }
40
+ if (!best)
41
+ return undefined;
42
+ logger?.warn(`Model "${requestedModel}" not available, falling back to "${best.id}" (closest in family)`);
43
+ return best.id;
44
+ }
45
+ //# sourceMappingURL=model-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-resolver.js","sourceRoot":"","sources":["../../../src/providers/shared/model-resolver.ts"],"names":[],"mappings":"AAGA,SAAS,SAAS,CAAC,EAAU;IAC3B,OAAO,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACvD,CAAC;AAED,0EAA0E;AAC1E,qFAAqF;AACrF,yEAAyE;AACzE,yEAAyE;AACzE,gCAAgC;AAChC,SAAS,aAAa,CAAC,EAAU;IAC/B,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACpC,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,cAAsB,EACtB,eAA4B,EAC5B,MAAe;IAEf,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,cAAc,CAAC,EAAE,CAAC;QACzD,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,MAAM,iBAAiB,GAAG,SAAS,CAAC,cAAc,CAAC,CAAC;IACpD,MAAM,eAAe,GAAG,eAAe,CAAC,IAAI,CAC1C,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,iBAAiB,CAC7C,CAAC;IACF,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,EAAE,KAAK,CACX,UAAU,cAAc,kBAAkB,eAAe,CAAC,EAAE,sBAAsB,CACnF,CAAC;QACF,OAAO,eAAe,CAAC,EAAE,CAAC;IAC5B,CAAC;IAED,yFAAyF;IACzF,wDAAwD;IACxD,MAAM,aAAa,GAAG,aAAa,CAAC,iBAAiB,CAAC,CAAC;IACvD,MAAM,aAAa,GAAG,eAAe,CAAC,MAAM,CAC1C,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,aAAa,CACxD,CAAC;IAEF,IAAI,IAA2B,CAAC;IAChC,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7B,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/D,OAAO,GAAG,GAAG,MAAM,IAAI,iBAAiB,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC;YAAE,GAAG,EAAE,CAAC;QACnE,IAAI,GAAG,GAAG,OAAO,EAAE,CAAC;YAClB,OAAO,GAAG,GAAG,CAAC;YACd,IAAI,GAAG,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IAED,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IAE5B,MAAM,EAAE,IAAI,CACV,UAAU,cAAc,qCAAqC,IAAI,CAAC,EAAE,uBAAuB,CAC5F,CAAC;IACF,OAAO,IAAI,CAAC,EAAE,CAAC;AACjB,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function filterExcludedFiles(s: string, patterns: string[]): string;
@@ -0,0 +1,15 @@
1
+ function escapeRegex(s) {
2
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3
+ }
4
+ // Xcode's search results can include full file contents for every match, so
5
+ // some files end up being thousands of lines and add nothing useful. We strip
6
+ // fenced code blocks whose header matches the excluded patterns (Xcode formats
7
+ // them as ```swift:/path/to/File.swift).
8
+ export function filterExcludedFiles(s, patterns) {
9
+ if (patterns.length === 0)
10
+ return s;
11
+ const joined = patterns.map(escapeRegex).join("|");
12
+ const re = new RegExp("```\\w*:[^\\n]*(?:" + joined + ")[^\\n]*\\n.*?\\n```\\n?", "gis");
13
+ return s.replace(re, "");
14
+ }
15
+ //# sourceMappingURL=prompt-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-utils.js","sourceRoot":"","sources":["../../../src/providers/shared/prompt-utils.ts"],"names":[],"mappings":"AAAA,SAAS,WAAW,CAAC,CAAS;IAC5B,OAAO,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC;AAED,4EAA4E;AAC5E,8EAA8E;AAC9E,+EAA+E;AAC/E,yCAAyC;AACzC,MAAM,UAAU,mBAAmB,CAAC,CAAS,EAAE,QAAkB;IAC/D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAEpC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnD,MAAM,EAAE,GAAG,IAAI,MAAM,CACnB,oBAAoB,GAAG,MAAM,GAAG,0BAA0B,EAC1D,KAAK,CACN,CAAC;IACF,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { SessionConfig } from "@github/copilot-sdk";
2
+ import type { ServerConfig } from "../../config.js";
3
+ import type { Logger } from "../../logger.js";
4
+ export interface SessionConfigOptions {
5
+ model: string;
6
+ systemMessage?: string | undefined;
7
+ logger: Logger;
8
+ config: ServerConfig;
9
+ supportsReasoningEffort: boolean;
10
+ cwd?: string | undefined;
11
+ hasToolBridge?: boolean;
12
+ port?: number | undefined;
13
+ conversationId?: string | undefined;
14
+ }
15
+ export declare function createSessionConfig({ model, systemMessage, logger, config, supportsReasoningEffort, cwd, hasToolBridge, port, conversationId, }: SessionConfigOptions): SessionConfig;