xcode-copilot-server 2.2.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 (150) hide show
  1. package/README.md +83 -26
  2. package/config.json5 +13 -8
  3. package/dist/cli-validators.js +2 -2
  4. package/dist/cli-validators.js.map +1 -1
  5. package/dist/config.d.ts +1 -1
  6. package/dist/config.js +1 -1
  7. package/dist/config.js.map +1 -1
  8. package/dist/conversation-manager.d.ts +2 -1
  9. package/dist/conversation-manager.js +20 -1
  10. package/dist/conversation-manager.js.map +1 -1
  11. package/dist/handlers/responses/streaming.d.ts +6 -0
  12. package/dist/handlers/responses/streaming.js +265 -0
  13. package/dist/handlers/responses/streaming.js.map +1 -0
  14. package/dist/handlers/responses/tool-result-handler.d.ts +4 -0
  15. package/dist/handlers/responses/tool-result-handler.js +9 -0
  16. package/dist/handlers/responses/tool-result-handler.js.map +1 -0
  17. package/dist/handlers/responses.d.ts +4 -0
  18. package/dist/handlers/responses.js +164 -0
  19. package/dist/handlers/responses.js.map +1 -0
  20. package/dist/handlers/streaming-utils.d.ts +1 -0
  21. package/dist/handlers/streaming-utils.js +3 -0
  22. package/dist/handlers/streaming-utils.js.map +1 -1
  23. package/dist/index.js +23 -108
  24. package/dist/index.js.map +1 -1
  25. package/dist/providers/claude/count-tokens.d.ts +3 -0
  26. package/dist/providers/claude/count-tokens.js +72 -0
  27. package/dist/providers/claude/count-tokens.js.map +1 -0
  28. package/dist/providers/claude/handler.d.ts +4 -0
  29. package/dist/providers/claude/handler.js +150 -0
  30. package/dist/providers/claude/handler.js.map +1 -0
  31. package/dist/providers/claude/prompt.d.ts +2 -0
  32. package/dist/providers/claude/prompt.js +52 -0
  33. package/dist/providers/claude/prompt.js.map +1 -0
  34. package/dist/providers/claude/provider.d.ts +5 -0
  35. package/dist/providers/claude/provider.js +28 -0
  36. package/dist/providers/claude/provider.js.map +1 -0
  37. package/dist/providers/claude/schemas.d.ts +140 -0
  38. package/dist/providers/claude/schemas.js +58 -0
  39. package/dist/providers/claude/schemas.js.map +1 -0
  40. package/dist/providers/claude/streaming.d.ts +6 -0
  41. package/dist/providers/claude/streaming.js +116 -0
  42. package/dist/providers/claude/streaming.js.map +1 -0
  43. package/dist/providers/claude/tool-results.d.ts +4 -0
  44. package/dist/providers/claude/tool-results.js +19 -0
  45. package/dist/providers/claude/tool-results.js.map +1 -0
  46. package/dist/providers/codex/handler.d.ts +4 -0
  47. package/dist/providers/codex/handler.js +164 -0
  48. package/dist/providers/codex/handler.js.map +1 -0
  49. package/dist/providers/codex/prompt.d.ts +4 -0
  50. package/dist/providers/codex/prompt.js +58 -0
  51. package/dist/providers/codex/prompt.js.map +1 -0
  52. package/dist/providers/codex/provider.d.ts +5 -0
  53. package/dist/providers/codex/provider.js +24 -0
  54. package/dist/providers/codex/provider.js.map +1 -0
  55. package/dist/providers/codex/schemas.d.ts +122 -0
  56. package/dist/providers/codex/schemas.js +55 -0
  57. package/dist/providers/codex/schemas.js.map +1 -0
  58. package/dist/providers/codex/streaming.d.ts +9 -0
  59. package/dist/providers/codex/streaming.js +172 -0
  60. package/dist/providers/codex/streaming.js.map +1 -0
  61. package/dist/providers/codex/tool-results.d.ts +4 -0
  62. package/dist/providers/codex/tool-results.js +9 -0
  63. package/dist/providers/codex/tool-results.js.map +1 -0
  64. package/dist/providers/codex.d.ts +5 -0
  65. package/dist/providers/codex.js +24 -0
  66. package/dist/providers/codex.js.map +1 -0
  67. package/dist/providers/index.d.ts +6 -1
  68. package/dist/providers/index.js +5 -3
  69. package/dist/providers/index.js.map +1 -1
  70. package/dist/providers/openai/handler.d.ts +4 -0
  71. package/dist/providers/openai/handler.js +120 -0
  72. package/dist/providers/openai/handler.js.map +1 -0
  73. package/dist/providers/openai/models.d.ts +3 -0
  74. package/dist/providers/openai/models.js +28 -0
  75. package/dist/providers/openai/models.js.map +1 -0
  76. package/dist/providers/openai/prompt.d.ts +3 -0
  77. package/dist/providers/openai/prompt.js +38 -0
  78. package/dist/providers/openai/prompt.js.map +1 -0
  79. package/dist/providers/openai/provider.d.ts +5 -0
  80. package/dist/providers/openai/provider.js +25 -0
  81. package/dist/providers/openai/provider.js.map +1 -0
  82. package/dist/providers/openai/schemas.d.ts +98 -0
  83. package/dist/providers/openai/schemas.js +76 -0
  84. package/dist/providers/openai/schemas.js.map +1 -0
  85. package/dist/providers/openai/streaming.d.ts +4 -0
  86. package/dist/providers/openai/streaming.js +121 -0
  87. package/dist/providers/openai/streaming.js.map +1 -0
  88. package/dist/providers/shared/errors.d.ts +5 -0
  89. package/dist/providers/shared/errors.js +10 -0
  90. package/dist/providers/shared/errors.js.map +1 -0
  91. package/dist/providers/shared/model-resolver.d.ts +3 -0
  92. package/dist/providers/shared/model-resolver.js +45 -0
  93. package/dist/providers/shared/model-resolver.js.map +1 -0
  94. package/dist/providers/shared/prompt-utils.d.ts +1 -0
  95. package/dist/providers/shared/prompt-utils.js +15 -0
  96. package/dist/providers/shared/prompt-utils.js.map +1 -0
  97. package/dist/providers/shared/session-config.d.ts +15 -0
  98. package/dist/providers/shared/session-config.js +98 -0
  99. package/dist/providers/shared/session-config.js.map +1 -0
  100. package/dist/providers/shared/streaming-core.d.ts +19 -0
  101. package/dist/providers/shared/streaming-core.js +176 -0
  102. package/dist/providers/shared/streaming-core.js.map +1 -0
  103. package/dist/providers/shared/streaming-utils.d.ts +10 -0
  104. package/dist/providers/shared/streaming-utils.js +28 -0
  105. package/dist/providers/shared/streaming-utils.js.map +1 -0
  106. package/dist/schemas/config.d.ts +19 -1
  107. package/dist/schemas/config.js +2 -1
  108. package/dist/schemas/config.js.map +1 -1
  109. package/dist/schemas/responses.d.ts +122 -0
  110. package/dist/schemas/responses.js +54 -0
  111. package/dist/schemas/responses.js.map +1 -0
  112. package/dist/server.js +1 -2
  113. package/dist/server.js.map +1 -1
  114. package/dist/settings-patcher/anthropic.d.ts +5 -0
  115. package/dist/{settings-patcher.js → settings-patcher/anthropic.js} +3 -7
  116. package/dist/settings-patcher/anthropic.js.map +1 -0
  117. package/dist/settings-patcher/claude.d.ts +5 -0
  118. package/dist/settings-patcher/claude.js +75 -0
  119. package/dist/settings-patcher/claude.js.map +1 -0
  120. package/dist/settings-patcher/codex.d.ts +23 -0
  121. package/dist/settings-patcher/codex.js +114 -0
  122. package/dist/settings-patcher/codex.js.map +1 -0
  123. package/dist/settings-patcher/index.d.ts +15 -0
  124. package/dist/settings-patcher/index.js +9 -0
  125. package/dist/settings-patcher/index.js.map +1 -0
  126. package/dist/{settings-patcher.d.ts → settings-patcher/types.d.ts} +1 -5
  127. package/dist/settings-patcher/types.js +2 -0
  128. package/dist/settings-patcher/types.js.map +1 -0
  129. package/dist/startup.d.ts +11 -0
  130. package/dist/startup.js +154 -0
  131. package/dist/startup.js.map +1 -0
  132. package/dist/tool-bridge/constants.d.ts +2 -0
  133. package/dist/tool-bridge/constants.js +3 -0
  134. package/dist/tool-bridge/constants.js.map +1 -0
  135. package/dist/tool-bridge/index.d.ts +1 -0
  136. package/dist/tool-bridge/index.js +1 -0
  137. package/dist/tool-bridge/index.js.map +1 -1
  138. package/dist/tool-bridge/routes.js +2 -1
  139. package/dist/tool-bridge/routes.js.map +1 -1
  140. package/dist/tool-bridge/session-lifecycle.js +1 -1
  141. package/dist/tool-bridge/state.d.ts +1 -1
  142. package/dist/tool-bridge/tool-cache.d.ts +1 -1
  143. package/dist/ui.d.ts +7 -0
  144. package/dist/ui.js +8 -0
  145. package/dist/ui.js.map +1 -1
  146. package/dist/utils/responses-prompt.d.ts +4 -0
  147. package/dist/utils/responses-prompt.js +58 -0
  148. package/dist/utils/responses-prompt.js.map +1 -0
  149. package/package.json +1 -1
  150. package/dist/settings-patcher.js.map +0 -1
@@ -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,2 @@
1
+ import type { AnthropicMessage } from "./schemas.js";
2
+ export declare function formatAnthropicPrompt(messages: AnthropicMessage[], excludedFilePatterns: string[]): string;
@@ -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/providers/claude/provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,CAAC,mBAAmB,EAAE,gCAAgC,CAAC;IAE/D,QAAQ,CAAC,GAAG,EAAE,GAAG;QACf,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAChD,mDAAmD;YACnD,wCAAwC;YACxC,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpC,IAAI,EAAE,CAAC;gBACP,OAAO;YACT,CAAC;YACD,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;YAC/C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;gBAClC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,gDAAgD,EAAE,EAAE,CAAC,CAAC;gBACtE,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;gBAC9E,OAAO;YACT,CAAC;YACD,IAAI,EAAE,CAAC;QACT,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QACpD,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,qBAAqB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;QAC9D,GAAG,CAAC,IAAI,CAAC,2BAA2B,EAAE,wBAAwB,CAAC,GAAG,CAAC,CAAC,CAAC;IACvE,CAAC;CACiB,CAAC"}
@@ -0,0 +1,140 @@
1
+ import { z } from "zod";
2
+ export interface TextBlock {
3
+ type: "text";
4
+ text: string;
5
+ }
6
+ export interface ToolUseBlock {
7
+ type: "tool_use";
8
+ id: string;
9
+ name: string;
10
+ input: Record<string, unknown>;
11
+ }
12
+ export interface ToolResultBlock {
13
+ type: "tool_result";
14
+ tool_use_id: string;
15
+ content?: string | TextBlock[] | undefined;
16
+ }
17
+ export type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock;
18
+ export interface AnthropicMessage {
19
+ role: "user" | "assistant";
20
+ content: string | ContentBlock[];
21
+ }
22
+ export interface AnthropicToolDefinition {
23
+ name: string;
24
+ description?: string | undefined;
25
+ input_schema: Record<string, unknown>;
26
+ }
27
+ export interface MessageStartEvent {
28
+ type: "message_start";
29
+ message: {
30
+ id: string;
31
+ type: "message";
32
+ role: "assistant";
33
+ content: [];
34
+ model: string;
35
+ stop_reason: null;
36
+ usage: {
37
+ input_tokens: number;
38
+ output_tokens: number;
39
+ };
40
+ };
41
+ }
42
+ export type TextContentBlock = {
43
+ type: "text";
44
+ text: "";
45
+ };
46
+ export type ToolUseContentBlock = {
47
+ type: "tool_use";
48
+ id: string;
49
+ name: string;
50
+ input: Record<string, unknown>;
51
+ };
52
+ export interface ContentBlockStartEvent {
53
+ type: "content_block_start";
54
+ index: number;
55
+ content_block: TextContentBlock | ToolUseContentBlock;
56
+ }
57
+ export type TextDelta = {
58
+ type: "text_delta";
59
+ text: string;
60
+ };
61
+ export type InputJsonDelta = {
62
+ type: "input_json_delta";
63
+ partial_json: string;
64
+ };
65
+ export interface ContentBlockDeltaEvent {
66
+ type: "content_block_delta";
67
+ index: number;
68
+ delta: TextDelta | InputJsonDelta;
69
+ }
70
+ export interface ContentBlockStopEvent {
71
+ type: "content_block_stop";
72
+ index: number;
73
+ }
74
+ export interface MessageDeltaEvent {
75
+ type: "message_delta";
76
+ delta: {
77
+ stop_reason: string;
78
+ stop_sequence: null;
79
+ };
80
+ usage: {
81
+ output_tokens: number;
82
+ };
83
+ }
84
+ export interface MessageStopEvent {
85
+ type: "message_stop";
86
+ }
87
+ export type AnthropicSSEEvent = MessageStartEvent | ContentBlockStartEvent | ContentBlockDeltaEvent | ContentBlockStopEvent | MessageDeltaEvent | MessageStopEvent;
88
+ export interface AnthropicErrorResponse {
89
+ type: "error";
90
+ error: {
91
+ type: "invalid_request_error" | "api_error";
92
+ message: string;
93
+ };
94
+ }
95
+ export interface CountTokensResponse {
96
+ input_tokens: number;
97
+ }
98
+ export declare const AnthropicMessagesRequestSchema: z.ZodObject<{
99
+ model: z.ZodString;
100
+ max_tokens: z.ZodNumber;
101
+ system: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodObject<{
102
+ type: z.ZodLiteral<"text">;
103
+ text: z.ZodString;
104
+ }, z.core.$strip>>]>>;
105
+ messages: z.ZodArray<z.ZodObject<{
106
+ role: z.ZodEnum<{
107
+ user: "user";
108
+ assistant: "assistant";
109
+ }>;
110
+ content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
111
+ type: z.ZodLiteral<"text">;
112
+ text: z.ZodString;
113
+ }, z.core.$strip>, z.ZodObject<{
114
+ type: z.ZodLiteral<"tool_use">;
115
+ id: z.ZodString;
116
+ name: z.ZodString;
117
+ input: z.ZodRecord<z.ZodString, z.ZodUnknown>;
118
+ }, z.core.$strip>, z.ZodObject<{
119
+ type: z.ZodLiteral<"tool_result">;
120
+ tool_use_id: z.ZodString;
121
+ content: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodObject<{
122
+ type: z.ZodLiteral<"text">;
123
+ text: z.ZodString;
124
+ }, z.core.$strip>>]>>;
125
+ }, z.core.$strip>], "type">>]>;
126
+ }, z.core.$strip>>;
127
+ tools: z.ZodOptional<z.ZodArray<z.ZodObject<{
128
+ name: z.ZodString;
129
+ description: z.ZodOptional<z.ZodString>;
130
+ input_schema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
131
+ }, z.core.$strip>>>;
132
+ stream: z.ZodOptional<z.ZodBoolean>;
133
+ temperature: z.ZodOptional<z.ZodNumber>;
134
+ top_p: z.ZodOptional<z.ZodNumber>;
135
+ top_k: z.ZodOptional<z.ZodNumber>;
136
+ stop_sequences: z.ZodOptional<z.ZodArray<z.ZodString>>;
137
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
138
+ }, z.core.$strip>;
139
+ export type AnthropicMessagesRequest = z.infer<typeof AnthropicMessagesRequestSchema>;
140
+ export declare function extractAnthropicSystem(system: string | TextBlock[] | undefined): string | undefined;
@@ -0,0 +1,58 @@
1
+ import { z } from "zod";
2
+ const TextBlockSchema = z.object({
3
+ type: z.literal("text"),
4
+ text: z.string(),
5
+ });
6
+ const ToolUseBlockSchema = z.object({
7
+ type: z.literal("tool_use"),
8
+ id: z.string(),
9
+ name: z.string(),
10
+ input: z.record(z.string(), z.unknown()),
11
+ });
12
+ const ToolResultContentSchema = z.union([
13
+ z.string(),
14
+ z.array(TextBlockSchema),
15
+ ]);
16
+ const ToolResultBlockSchema = z.object({
17
+ type: z.literal("tool_result"),
18
+ tool_use_id: z.string(),
19
+ content: ToolResultContentSchema.optional(),
20
+ });
21
+ const ContentBlockSchema = z.discriminatedUnion("type", [
22
+ TextBlockSchema,
23
+ ToolUseBlockSchema,
24
+ ToolResultBlockSchema,
25
+ ]);
26
+ const AnthropicMessageSchema = z.object({
27
+ role: z.enum(["user", "assistant"]),
28
+ content: z.union([z.string(), z.array(ContentBlockSchema)]),
29
+ });
30
+ const AnthropicToolDefinitionSchema = z.object({
31
+ name: z.string(),
32
+ description: z.string().optional(),
33
+ input_schema: z.record(z.string(), z.unknown()),
34
+ });
35
+ export const AnthropicMessagesRequestSchema = z.object({
36
+ model: z.string().min(1, "Model is required"),
37
+ max_tokens: z.number().int().positive("max_tokens must be positive"),
38
+ system: z.union([z.string(), z.array(TextBlockSchema)]).optional(),
39
+ messages: z.array(AnthropicMessageSchema).min(1, "Messages are required"),
40
+ tools: z.array(AnthropicToolDefinitionSchema).optional(),
41
+ stream: z.boolean().optional(),
42
+ temperature: z.number().optional(),
43
+ top_p: z.number().optional(),
44
+ top_k: z.number().optional(),
45
+ stop_sequences: z.array(z.string()).optional(),
46
+ metadata: z.record(z.string(), z.unknown()).optional(),
47
+ });
48
+ // The Anthropic API accepts system as a string or an array of text blocks,
49
+ // so we flatten it into a single string for the Copilot SDK.
50
+ export function extractAnthropicSystem(system) {
51
+ if (system == null)
52
+ return undefined;
53
+ if (typeof system === "string")
54
+ return system;
55
+ const text = system.map((b) => b.text).join("\n\n");
56
+ return text || undefined;
57
+ }
58
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../../src/providers/claude/schemas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { FastifyReply } from "fastify";
2
+ import type { CopilotSession } from "@github/copilot-sdk";
3
+ import type { Logger } from "../../logger.js";
4
+ import type { ToolBridgeState } from "../../tool-bridge/state.js";
5
+ export declare function startReply(reply: FastifyReply, model: string): void;
6
+ export declare function handleAnthropicStreaming(state: ToolBridgeState, session: CopilotSession, prompt: string, model: string, logger: Logger, hasBridge?: boolean): Promise<void>;
@@ -0,0 +1,116 @@
1
+ import { SSE_HEADERS, sendSSEEvent as sendEvent } from "../shared/streaming-utils.js";
2
+ import { runSessionStreaming } from "../shared/streaming-core.js";
3
+ export function startReply(reply, model) {
4
+ reply.raw.writeHead(200, SSE_HEADERS);
5
+ const messageStart = {
6
+ type: "message_start",
7
+ message: {
8
+ id: `msg_${String(Date.now())}`,
9
+ type: "message",
10
+ role: "assistant",
11
+ content: [],
12
+ model,
13
+ stop_reason: null,
14
+ usage: { input_tokens: 0, output_tokens: 0 },
15
+ },
16
+ };
17
+ sendEvent(reply, "message_start", messageStart);
18
+ }
19
+ function createAnthropicProtocol() {
20
+ let textBlockStarted = false;
21
+ function ensureTextBlock(r) {
22
+ if (!textBlockStarted) {
23
+ const blockStart = {
24
+ type: "content_block_start",
25
+ index: 0,
26
+ content_block: { type: "text", text: "" },
27
+ };
28
+ sendEvent(r, "content_block_start", blockStart);
29
+ textBlockStarted = true;
30
+ }
31
+ }
32
+ function sendBlockStop(r) {
33
+ sendEvent(r, "content_block_stop", {
34
+ type: "content_block_stop",
35
+ index: 0,
36
+ });
37
+ }
38
+ function sendEpilogue(r, stopReason) {
39
+ const messageDelta = {
40
+ type: "message_delta",
41
+ delta: { stop_reason: stopReason, stop_sequence: null },
42
+ usage: { output_tokens: 0 },
43
+ };
44
+ sendEvent(r, "message_delta", messageDelta);
45
+ sendEvent(r, "message_stop", { type: "message_stop" });
46
+ }
47
+ function emitToolUseBlocks(r, toolRequests) {
48
+ let startIndex;
49
+ if (textBlockStarted) {
50
+ sendBlockStop(r);
51
+ startIndex = 1;
52
+ }
53
+ else {
54
+ startIndex = 0;
55
+ }
56
+ let index = startIndex;
57
+ for (const tr of toolRequests) {
58
+ sendEvent(r, "content_block_start", {
59
+ type: "content_block_start",
60
+ index,
61
+ content_block: { type: "tool_use", id: tr.toolCallId, name: tr.name, input: {} },
62
+ });
63
+ const argsJson = tr.arguments != null ? JSON.stringify(tr.arguments) : "{}";
64
+ sendEvent(r, "content_block_delta", {
65
+ type: "content_block_delta",
66
+ index,
67
+ delta: { type: "input_json_delta", partial_json: argsJson },
68
+ });
69
+ sendEvent(r, "content_block_stop", {
70
+ type: "content_block_stop",
71
+ index,
72
+ });
73
+ index++;
74
+ }
75
+ }
76
+ return {
77
+ flushDeltas(r, deltas) {
78
+ ensureTextBlock(r);
79
+ for (const text of deltas) {
80
+ const delta = {
81
+ type: "content_block_delta",
82
+ index: 0,
83
+ delta: { type: "text_delta", text },
84
+ };
85
+ sendEvent(r, "content_block_delta", delta);
86
+ }
87
+ },
88
+ emitToolsAndFinish(r, tools) {
89
+ emitToolUseBlocks(r, tools);
90
+ sendEpilogue(r, "tool_use");
91
+ },
92
+ sendCompleted(r) {
93
+ ensureTextBlock(r);
94
+ sendBlockStop(r);
95
+ sendEpilogue(r, "end_turn");
96
+ },
97
+ sendFailed(r) {
98
+ if (textBlockStarted)
99
+ sendBlockStop(r);
100
+ sendEpilogue(r, "end_turn");
101
+ },
102
+ teardown() { },
103
+ reset() {
104
+ textBlockStarted = false;
105
+ },
106
+ };
107
+ }
108
+ export async function handleAnthropicStreaming(state, session, prompt, model, logger, hasBridge = false) {
109
+ const reply = state.currentReply;
110
+ if (!reply)
111
+ throw new Error("No reply set on bridge state");
112
+ startReply(reply, model);
113
+ const protocol = createAnthropicProtocol();
114
+ return runSessionStreaming(state, session, prompt, logger, hasBridge, protocol, reply);
115
+ }
116
+ //# sourceMappingURL=streaming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming.js","sourceRoot":"","sources":["../../../src/providers/claude/streaming.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { AnthropicMessage } from "./schemas.js";
2
+ import type { ToolBridgeState } from "../../tool-bridge/state.js";
3
+ import type { Logger } from "../../logger.js";
4
+ export declare function resolveToolResults(messages: AnthropicMessage[], state: ToolBridgeState, logger: Logger): void;
@@ -0,0 +1,19 @@
1
+ export function resolveToolResults(messages, state, logger) {
2
+ const lastMsg = messages[messages.length - 1];
3
+ if (!lastMsg || lastMsg.role !== "user" || typeof lastMsg.content === "string")
4
+ return;
5
+ for (const block of lastMsg.content) {
6
+ if (block.type === "tool_result") {
7
+ const resultText = typeof block.content === "string"
8
+ ? block.content
9
+ : Array.isArray(block.content)
10
+ ? block.content.map((b) => b.text).join("\n")
11
+ : "";
12
+ logger.debug(`Resolving tool result for ${block.tool_use_id}`);
13
+ if (!state.resolveToolCall(block.tool_use_id, resultText)) {
14
+ logger.warn(`No pending MCP request for tool_use_id ${block.tool_use_id}`);
15
+ }
16
+ }
17
+ }
18
+ }
19
+ //# sourceMappingURL=tool-results.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-results.js","sourceRoot":"","sources":["../../../src/providers/claude/tool-results.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,kBAAkB,CAChC,QAA4B,EAC5B,KAAsB,EACtB,MAAc;IAEd,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC9C,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ;QAAE,OAAO;IAEvF,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACjC,MAAM,UAAU,GAAG,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;gBAClD,CAAC,CAAC,KAAK,CAAC,OAAO;gBACf,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;oBAC5B,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;oBAC7C,CAAC,CAAC,EAAE,CAAC;YACT,MAAM,CAAC,KAAK,CAAC,6BAA6B,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;YAC/D,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,WAAW,EAAE,UAAU,CAAC,EAAE,CAAC;gBAC1D,MAAM,CAAC,IAAI,CAAC,0CAA0C,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;YAC7E,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -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 createResponsesHandler({ service, logger, config, port }: AppContext, manager: ConversationManager): (request: FastifyRequest, reply: FastifyReply) => Promise<void>;