@nomomon/ai-sdk-provider-github-copilot 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +123 -0
- package/dist/index.cjs +613 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +143 -0
- package/dist/index.d.ts +143 -0
- package/dist/index.js +604 -0
- package/dist/index.js.map +1 -0
- package/package.json +72 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
import { LoadAPIKeyError, APICallError, NoSuchModelError } from '@ai-sdk/provider';
|
|
2
|
+
import { generateId } from '@ai-sdk/provider-utils';
|
|
3
|
+
import { CopilotClient } from '@github/copilot-sdk';
|
|
4
|
+
|
|
5
|
+
// src/errors.ts
|
|
6
|
+
var AUTH_ERROR_PATTERNS = [
|
|
7
|
+
"not authenticated",
|
|
8
|
+
"authentication",
|
|
9
|
+
"unauthorized",
|
|
10
|
+
"auth failed",
|
|
11
|
+
"please login",
|
|
12
|
+
"login required",
|
|
13
|
+
"invalid token",
|
|
14
|
+
"token expired"
|
|
15
|
+
];
|
|
16
|
+
function createAuthenticationError(options) {
|
|
17
|
+
return new LoadAPIKeyError({
|
|
18
|
+
message: options.message ?? "Authentication failed. Please ensure Copilot CLI is properly authenticated."
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
function createAPICallError(options) {
|
|
22
|
+
return new APICallError({
|
|
23
|
+
message: options.message,
|
|
24
|
+
url: "copilot://session",
|
|
25
|
+
requestBodyValues: {},
|
|
26
|
+
statusCode: options.statusCode,
|
|
27
|
+
cause: options.cause,
|
|
28
|
+
isRetryable: options.isRetryable ?? false
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function isAuthenticationError(error) {
|
|
32
|
+
const message = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
|
|
33
|
+
return AUTH_ERROR_PATTERNS.some((pattern) => message.includes(pattern));
|
|
34
|
+
}
|
|
35
|
+
function isAbortError(error) {
|
|
36
|
+
if (error && typeof error === "object") {
|
|
37
|
+
const e = error;
|
|
38
|
+
if (typeof e.name === "string" && e.name === "AbortError") return true;
|
|
39
|
+
if (typeof e.code === "string" && e.code.toUpperCase() === "ABORT_ERR") return true;
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
function handleCopilotError(error, _context) {
|
|
44
|
+
if (isAbortError(error)) {
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
48
|
+
if (isAuthenticationError(error)) {
|
|
49
|
+
throw createAuthenticationError({ message });
|
|
50
|
+
}
|
|
51
|
+
throw createAPICallError({
|
|
52
|
+
message: message || "GitHub Copilot SDK error",
|
|
53
|
+
cause: error,
|
|
54
|
+
isRetryable: false
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/convert-to-copilot-messages.ts
|
|
59
|
+
var IMAGE_URL_WARNING = "Image URLs are not supported by this provider; supply file paths as attachments.";
|
|
60
|
+
var IMAGE_BASE64_WARNING = "Base64/image data URLs require file paths. Write to temp file and pass path, or use attachments with path.";
|
|
61
|
+
function convertToCopilotMessages(prompt) {
|
|
62
|
+
const messages = [];
|
|
63
|
+
const warnings = [];
|
|
64
|
+
let systemMessage;
|
|
65
|
+
const attachments = [];
|
|
66
|
+
for (const message of prompt) {
|
|
67
|
+
switch (message.role) {
|
|
68
|
+
case "system": {
|
|
69
|
+
const content = message.content;
|
|
70
|
+
systemMessage = typeof content === "string" ? content : extractTextFromParts(content);
|
|
71
|
+
if (systemMessage?.trim()) {
|
|
72
|
+
messages.push(`System: ${systemMessage}`);
|
|
73
|
+
}
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
case "user": {
|
|
77
|
+
const content = message.content;
|
|
78
|
+
if (typeof content === "string") {
|
|
79
|
+
messages.push(`User: ${content}`);
|
|
80
|
+
} else {
|
|
81
|
+
const textParts = [];
|
|
82
|
+
for (const part of content) {
|
|
83
|
+
if (part.type === "text") {
|
|
84
|
+
textParts.push(part.text);
|
|
85
|
+
} else if (part.type === "file") {
|
|
86
|
+
const fileInfo = extractFileAttachment(part);
|
|
87
|
+
if (fileInfo.path) {
|
|
88
|
+
attachments.push({
|
|
89
|
+
type: "file",
|
|
90
|
+
path: fileInfo.path,
|
|
91
|
+
displayName: fileInfo.displayName
|
|
92
|
+
});
|
|
93
|
+
} else if (fileInfo.warning) {
|
|
94
|
+
warnings.push(fileInfo.warning);
|
|
95
|
+
}
|
|
96
|
+
} else if (part.type === "image") {
|
|
97
|
+
warnings.push(IMAGE_BASE64_WARNING);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (textParts.length > 0) {
|
|
101
|
+
messages.push(`User: ${textParts.join("\n")}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
case "assistant": {
|
|
107
|
+
const content = message.content;
|
|
108
|
+
if (typeof content === "string") {
|
|
109
|
+
messages.push(`Assistant: ${content}`);
|
|
110
|
+
} else {
|
|
111
|
+
const textParts = [];
|
|
112
|
+
for (const part of content) {
|
|
113
|
+
if (part.type === "text") {
|
|
114
|
+
textParts.push(part.text);
|
|
115
|
+
} else if (part.type === "tool-call") {
|
|
116
|
+
textParts.push(`[Tool call: ${part.toolName}]`);
|
|
117
|
+
} else if (part.type === "reasoning") {
|
|
118
|
+
textParts.push(`[Reasoning: ${part.text}]`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (textParts.length > 0) {
|
|
122
|
+
messages.push(`Assistant: ${textParts.join("\n")}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
case "tool": {
|
|
128
|
+
for (const part of message.content) {
|
|
129
|
+
if (part.type === "tool-result") {
|
|
130
|
+
const output = part.output;
|
|
131
|
+
let resultStr;
|
|
132
|
+
if (output.type === "text" || output.type === "error-text") {
|
|
133
|
+
resultStr = output.value;
|
|
134
|
+
} else if (output.type === "json" || output.type === "error-json") {
|
|
135
|
+
resultStr = JSON.stringify(output.value);
|
|
136
|
+
} else if (output.type === "execution-denied") {
|
|
137
|
+
resultStr = `[Execution denied${output.reason ? `: ${output.reason}` : ""}]`;
|
|
138
|
+
} else if (output.type === "content") {
|
|
139
|
+
resultStr = output.value.filter((p) => p.type === "text").map((p) => p.text).join("\n");
|
|
140
|
+
} else {
|
|
141
|
+
resultStr = "[Unknown output type]";
|
|
142
|
+
}
|
|
143
|
+
const isError = output.type === "error-text" || output.type === "error-json";
|
|
144
|
+
messages.push(
|
|
145
|
+
`Tool result (${part.toolName}): ${isError ? "Error: " : ""}${resultStr}`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const promptText = messages.join("\n\n");
|
|
154
|
+
return {
|
|
155
|
+
prompt: promptText,
|
|
156
|
+
systemMessage: systemMessage?.trim() || void 0,
|
|
157
|
+
attachments: attachments.length > 0 ? attachments : void 0,
|
|
158
|
+
warnings: warnings.length > 0 ? warnings : void 0
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function extractTextFromParts(content) {
|
|
162
|
+
return content.filter((p) => p.type === "text").map((p) => p.text).join("\n");
|
|
163
|
+
}
|
|
164
|
+
function extractFileAttachment(part) {
|
|
165
|
+
if (part.type !== "file") return {};
|
|
166
|
+
const data = part.data;
|
|
167
|
+
if (typeof data === "string") {
|
|
168
|
+
if (data.startsWith("http://") || data.startsWith("https://")) {
|
|
169
|
+
return { warning: IMAGE_URL_WARNING };
|
|
170
|
+
}
|
|
171
|
+
if (data.startsWith("file://")) {
|
|
172
|
+
return { path: data.slice(7), displayName: part.filename };
|
|
173
|
+
}
|
|
174
|
+
if (data.startsWith("/") || /^[A-Za-z]:[\\/]/.test(data)) {
|
|
175
|
+
return { path: data, displayName: part.filename };
|
|
176
|
+
}
|
|
177
|
+
return { warning: IMAGE_BASE64_WARNING };
|
|
178
|
+
}
|
|
179
|
+
return {};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// src/map-copilot-finish-reason.ts
|
|
183
|
+
function mapCopilotFinishReason() {
|
|
184
|
+
return {
|
|
185
|
+
unified: "stop",
|
|
186
|
+
raw: void 0
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// src/github-copilot-language-model.ts
|
|
191
|
+
function createEmptyUsage() {
|
|
192
|
+
return {
|
|
193
|
+
inputTokens: { total: 0, noCache: 0, cacheRead: 0, cacheWrite: 0 },
|
|
194
|
+
outputTokens: { total: 0, text: void 0, reasoning: void 0 },
|
|
195
|
+
raw: void 0
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function convertCopilotUsage(event) {
|
|
199
|
+
const inputTokens = event.inputTokens ?? 0;
|
|
200
|
+
const outputTokens = event.outputTokens ?? 0;
|
|
201
|
+
const cacheRead = event.cacheReadTokens ?? 0;
|
|
202
|
+
const cacheWrite = 0;
|
|
203
|
+
return {
|
|
204
|
+
inputTokens: {
|
|
205
|
+
total: inputTokens + cacheRead + cacheWrite,
|
|
206
|
+
noCache: inputTokens,
|
|
207
|
+
cacheRead,
|
|
208
|
+
cacheWrite
|
|
209
|
+
},
|
|
210
|
+
outputTokens: {
|
|
211
|
+
total: outputTokens,
|
|
212
|
+
text: outputTokens,
|
|
213
|
+
reasoning: void 0
|
|
214
|
+
},
|
|
215
|
+
raw: event
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
var GitHubCopilotLanguageModel = class {
|
|
219
|
+
specificationVersion = "v3";
|
|
220
|
+
defaultObjectGenerationMode = "json";
|
|
221
|
+
supportsImageUrls = false;
|
|
222
|
+
supportedUrls = {};
|
|
223
|
+
supportsStructuredOutputs = false;
|
|
224
|
+
modelId;
|
|
225
|
+
settings;
|
|
226
|
+
getClient;
|
|
227
|
+
constructor(options) {
|
|
228
|
+
this.modelId = options.modelId;
|
|
229
|
+
this.settings = options.settings;
|
|
230
|
+
this.getClient = options.getClient;
|
|
231
|
+
}
|
|
232
|
+
get provider() {
|
|
233
|
+
return "github-copilot";
|
|
234
|
+
}
|
|
235
|
+
getEffectiveModel() {
|
|
236
|
+
return this.settings.model ?? this.modelId;
|
|
237
|
+
}
|
|
238
|
+
buildSessionConfig(streaming) {
|
|
239
|
+
return {
|
|
240
|
+
model: this.getEffectiveModel(),
|
|
241
|
+
sessionId: this.settings.sessionId,
|
|
242
|
+
streaming,
|
|
243
|
+
systemMessage: this.settings.systemMessage,
|
|
244
|
+
tools: this.settings.tools,
|
|
245
|
+
provider: this.settings.provider,
|
|
246
|
+
workingDirectory: this.settings.workingDirectory
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
generateWarnings(options) {
|
|
250
|
+
const warnings = [];
|
|
251
|
+
const unsupported = [];
|
|
252
|
+
if (options.temperature !== void 0) unsupported.push("temperature");
|
|
253
|
+
if (options.topP !== void 0) unsupported.push("topP");
|
|
254
|
+
if (options.topK !== void 0) unsupported.push("topK");
|
|
255
|
+
if (options.presencePenalty !== void 0) unsupported.push("presencePenalty");
|
|
256
|
+
if (options.frequencyPenalty !== void 0) unsupported.push("frequencyPenalty");
|
|
257
|
+
if (options.stopSequences?.length) unsupported.push("stopSequences");
|
|
258
|
+
if (options.seed !== void 0) unsupported.push("seed");
|
|
259
|
+
for (const param of unsupported) {
|
|
260
|
+
warnings.push({
|
|
261
|
+
type: "unsupported",
|
|
262
|
+
feature: param,
|
|
263
|
+
details: `GitHub Copilot SDK does not support the ${param} parameter. It will be ignored.`
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
return warnings;
|
|
267
|
+
}
|
|
268
|
+
async doGenerate(options) {
|
|
269
|
+
const {
|
|
270
|
+
prompt,
|
|
271
|
+
systemMessage,
|
|
272
|
+
attachments,
|
|
273
|
+
warnings: msgWarnings
|
|
274
|
+
} = convertToCopilotMessages(options.prompt);
|
|
275
|
+
const warnings = [
|
|
276
|
+
...this.generateWarnings(options),
|
|
277
|
+
...msgWarnings?.map((m) => ({ type: "other", message: m })) ?? []
|
|
278
|
+
];
|
|
279
|
+
const client = this.getClient();
|
|
280
|
+
if (client.getState() !== "connected") {
|
|
281
|
+
await client.start();
|
|
282
|
+
}
|
|
283
|
+
const session = await client.createSession({
|
|
284
|
+
...this.buildSessionConfig(false),
|
|
285
|
+
systemMessage: systemMessage ? { mode: "append", content: systemMessage } : this.settings.systemMessage
|
|
286
|
+
});
|
|
287
|
+
let abortListener;
|
|
288
|
+
if (options.abortSignal) {
|
|
289
|
+
abortListener = () => session.abort();
|
|
290
|
+
options.abortSignal.addEventListener("abort", abortListener, { once: true });
|
|
291
|
+
}
|
|
292
|
+
try {
|
|
293
|
+
const result = await session.sendAndWait(
|
|
294
|
+
{ prompt, attachments },
|
|
295
|
+
options.abortSignal?.aborted ? 0 : 6e4
|
|
296
|
+
);
|
|
297
|
+
const content = [];
|
|
298
|
+
const text = result?.data?.content ?? "";
|
|
299
|
+
if (text) {
|
|
300
|
+
content.push({ type: "text", text });
|
|
301
|
+
}
|
|
302
|
+
let usage = createEmptyUsage();
|
|
303
|
+
const usageEvent = result?.data?.usage;
|
|
304
|
+
if (usageEvent && typeof usageEvent === "object") {
|
|
305
|
+
usage = convertCopilotUsage(usageEvent);
|
|
306
|
+
}
|
|
307
|
+
const finishReason = mapCopilotFinishReason();
|
|
308
|
+
return {
|
|
309
|
+
content,
|
|
310
|
+
finishReason,
|
|
311
|
+
usage,
|
|
312
|
+
warnings,
|
|
313
|
+
request: { body: { prompt, attachments } },
|
|
314
|
+
response: {
|
|
315
|
+
id: generateId(),
|
|
316
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
317
|
+
modelId: this.modelId
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
} catch (error) {
|
|
321
|
+
if (isAbortError(error)) {
|
|
322
|
+
throw options.abortSignal?.aborted ? options.abortSignal.reason : error;
|
|
323
|
+
}
|
|
324
|
+
handleCopilotError(error, { promptExcerpt: prompt.substring(0, 200) });
|
|
325
|
+
return void 0;
|
|
326
|
+
} finally {
|
|
327
|
+
if (options.abortSignal && abortListener) {
|
|
328
|
+
options.abortSignal.removeEventListener("abort", abortListener);
|
|
329
|
+
}
|
|
330
|
+
try {
|
|
331
|
+
await session.destroy();
|
|
332
|
+
} catch {
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
async doStream(options) {
|
|
337
|
+
const {
|
|
338
|
+
prompt,
|
|
339
|
+
systemMessage,
|
|
340
|
+
attachments,
|
|
341
|
+
warnings: msgWarnings
|
|
342
|
+
} = convertToCopilotMessages(options.prompt);
|
|
343
|
+
const warnings = [
|
|
344
|
+
...this.generateWarnings(options),
|
|
345
|
+
...msgWarnings?.map((m) => ({ type: "other", message: m })) ?? []
|
|
346
|
+
];
|
|
347
|
+
const client = this.getClient();
|
|
348
|
+
if (client.getState() !== "connected") {
|
|
349
|
+
await client.start();
|
|
350
|
+
}
|
|
351
|
+
const session = await client.createSession({
|
|
352
|
+
...this.buildSessionConfig(true),
|
|
353
|
+
systemMessage: systemMessage ? { mode: "append", content: systemMessage } : this.settings.systemMessage
|
|
354
|
+
});
|
|
355
|
+
const abortController = new AbortController();
|
|
356
|
+
let abortListener;
|
|
357
|
+
if (options.abortSignal?.aborted) {
|
|
358
|
+
abortController.abort(options.abortSignal.reason);
|
|
359
|
+
} else if (options.abortSignal) {
|
|
360
|
+
abortListener = () => {
|
|
361
|
+
session.abort();
|
|
362
|
+
abortController.abort(options.abortSignal?.reason);
|
|
363
|
+
};
|
|
364
|
+
options.abortSignal.addEventListener("abort", abortListener, { once: true });
|
|
365
|
+
}
|
|
366
|
+
const stream = new ReadableStream({
|
|
367
|
+
start: async (controller) => {
|
|
368
|
+
let textPartId;
|
|
369
|
+
let usage = createEmptyUsage();
|
|
370
|
+
const toolStates = /* @__PURE__ */ new Map();
|
|
371
|
+
try {
|
|
372
|
+
controller.enqueue({ type: "stream-start", warnings });
|
|
373
|
+
session.on((event) => {
|
|
374
|
+
if (event.type === "assistant.message_delta") {
|
|
375
|
+
const delta = event.data?.deltaContent;
|
|
376
|
+
if (delta) {
|
|
377
|
+
if (!textPartId) {
|
|
378
|
+
textPartId = generateId();
|
|
379
|
+
controller.enqueue({ type: "text-start", id: textPartId });
|
|
380
|
+
}
|
|
381
|
+
controller.enqueue({
|
|
382
|
+
type: "text-delta",
|
|
383
|
+
id: textPartId,
|
|
384
|
+
delta
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
} else if (event.type === "assistant.reasoning_delta") {
|
|
388
|
+
const delta = event.data?.deltaContent;
|
|
389
|
+
if (delta) {
|
|
390
|
+
const reasoningId = generateId();
|
|
391
|
+
controller.enqueue({ type: "reasoning-start", id: reasoningId });
|
|
392
|
+
controller.enqueue({
|
|
393
|
+
type: "reasoning-delta",
|
|
394
|
+
id: reasoningId,
|
|
395
|
+
delta
|
|
396
|
+
});
|
|
397
|
+
controller.enqueue({ type: "reasoning-end", id: reasoningId });
|
|
398
|
+
}
|
|
399
|
+
} else if (event.type === "assistant.message") {
|
|
400
|
+
const data = event.data;
|
|
401
|
+
if (data?.content && !textPartId) {
|
|
402
|
+
textPartId = generateId();
|
|
403
|
+
controller.enqueue({ type: "text-start", id: textPartId });
|
|
404
|
+
controller.enqueue({
|
|
405
|
+
type: "text-delta",
|
|
406
|
+
id: textPartId,
|
|
407
|
+
delta: data.content
|
|
408
|
+
});
|
|
409
|
+
controller.enqueue({ type: "text-end", id: textPartId });
|
|
410
|
+
}
|
|
411
|
+
if (data?.toolRequests?.length) {
|
|
412
|
+
for (const tr of data.toolRequests) {
|
|
413
|
+
const toolId = tr.toolCallId;
|
|
414
|
+
let state = toolStates.get(toolId);
|
|
415
|
+
if (!state) {
|
|
416
|
+
state = {
|
|
417
|
+
name: tr.name,
|
|
418
|
+
inputStarted: false,
|
|
419
|
+
callEmitted: false
|
|
420
|
+
};
|
|
421
|
+
toolStates.set(toolId, state);
|
|
422
|
+
}
|
|
423
|
+
if (!state.inputStarted) {
|
|
424
|
+
controller.enqueue({
|
|
425
|
+
type: "tool-input-start",
|
|
426
|
+
id: toolId,
|
|
427
|
+
toolName: tr.name,
|
|
428
|
+
providerExecuted: true,
|
|
429
|
+
dynamic: true
|
|
430
|
+
});
|
|
431
|
+
state.inputStarted = true;
|
|
432
|
+
}
|
|
433
|
+
const args = tr.arguments ?? {};
|
|
434
|
+
controller.enqueue({
|
|
435
|
+
type: "tool-input-delta",
|
|
436
|
+
id: toolId,
|
|
437
|
+
delta: JSON.stringify(args)
|
|
438
|
+
});
|
|
439
|
+
controller.enqueue({ type: "tool-input-end", id: toolId });
|
|
440
|
+
if (!state.callEmitted) {
|
|
441
|
+
controller.enqueue({
|
|
442
|
+
type: "tool-call",
|
|
443
|
+
toolCallId: toolId,
|
|
444
|
+
toolName: tr.name,
|
|
445
|
+
input: typeof args === "string" ? args : JSON.stringify(args),
|
|
446
|
+
providerExecuted: true,
|
|
447
|
+
dynamic: true
|
|
448
|
+
});
|
|
449
|
+
state.callEmitted = true;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
} else if (event.type === "tool.execution_start") {
|
|
454
|
+
const data = event.data;
|
|
455
|
+
if (data) {
|
|
456
|
+
const toolId = data.toolCallId;
|
|
457
|
+
let state = toolStates.get(toolId);
|
|
458
|
+
if (!state) {
|
|
459
|
+
state = {
|
|
460
|
+
name: data.toolName,
|
|
461
|
+
inputStarted: true,
|
|
462
|
+
callEmitted: false
|
|
463
|
+
};
|
|
464
|
+
toolStates.set(toolId, state);
|
|
465
|
+
}
|
|
466
|
+
if (!state.callEmitted) {
|
|
467
|
+
controller.enqueue({
|
|
468
|
+
type: "tool-input-start",
|
|
469
|
+
id: toolId,
|
|
470
|
+
toolName: data.toolName,
|
|
471
|
+
providerExecuted: true,
|
|
472
|
+
dynamic: true
|
|
473
|
+
});
|
|
474
|
+
controller.enqueue({ type: "tool-input-end", id: toolId });
|
|
475
|
+
controller.enqueue({
|
|
476
|
+
type: "tool-call",
|
|
477
|
+
toolCallId: toolId,
|
|
478
|
+
toolName: data.toolName,
|
|
479
|
+
input: "{}",
|
|
480
|
+
providerExecuted: true,
|
|
481
|
+
dynamic: true
|
|
482
|
+
});
|
|
483
|
+
state.callEmitted = true;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
} else if (event.type === "tool.execution_complete") {
|
|
487
|
+
const evt = event;
|
|
488
|
+
const data = evt.data;
|
|
489
|
+
if (data) {
|
|
490
|
+
const toolName = data.toolName ?? "unknown";
|
|
491
|
+
const result = data.success && data.result?.content ? data.result.content : data.error?.message ?? "Tool execution failed";
|
|
492
|
+
controller.enqueue({
|
|
493
|
+
type: "tool-result",
|
|
494
|
+
toolCallId: data.toolCallId,
|
|
495
|
+
toolName,
|
|
496
|
+
result,
|
|
497
|
+
isError: !data.success,
|
|
498
|
+
dynamic: true
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
} else if (event.type === "assistant.usage") {
|
|
502
|
+
const data = event.data;
|
|
503
|
+
if (data) {
|
|
504
|
+
usage = convertCopilotUsage(data);
|
|
505
|
+
}
|
|
506
|
+
} else if (event.type === "session.idle") {
|
|
507
|
+
if (textPartId) {
|
|
508
|
+
controller.enqueue({ type: "text-end", id: textPartId });
|
|
509
|
+
}
|
|
510
|
+
controller.enqueue({
|
|
511
|
+
type: "finish",
|
|
512
|
+
finishReason: mapCopilotFinishReason(),
|
|
513
|
+
usage
|
|
514
|
+
});
|
|
515
|
+
controller.close();
|
|
516
|
+
void session.destroy();
|
|
517
|
+
} else if (event.type === "session.error") {
|
|
518
|
+
const data = event.data;
|
|
519
|
+
controller.enqueue({
|
|
520
|
+
type: "error",
|
|
521
|
+
error: new Error(data?.message ?? "Session error")
|
|
522
|
+
});
|
|
523
|
+
controller.close();
|
|
524
|
+
void session.destroy();
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
await session.send({ prompt, attachments });
|
|
528
|
+
} catch (error) {
|
|
529
|
+
if (isAbortError(error)) {
|
|
530
|
+
controller.enqueue({
|
|
531
|
+
type: "error",
|
|
532
|
+
error: options.abortSignal?.aborted ? options.abortSignal.reason : error
|
|
533
|
+
});
|
|
534
|
+
} else {
|
|
535
|
+
handleCopilotError(error, { promptExcerpt: prompt.substring(0, 200) });
|
|
536
|
+
}
|
|
537
|
+
controller.close();
|
|
538
|
+
await session.destroy();
|
|
539
|
+
} finally {
|
|
540
|
+
if (options.abortSignal && abortListener) {
|
|
541
|
+
options.abortSignal.removeEventListener("abort", abortListener);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
},
|
|
545
|
+
cancel: () => {
|
|
546
|
+
if (options.abortSignal && abortListener) {
|
|
547
|
+
options.abortSignal.removeEventListener("abort", abortListener);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
return {
|
|
552
|
+
stream,
|
|
553
|
+
request: { body: { prompt, attachments } }
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
function createGitHubCopilot(options = {}) {
|
|
558
|
+
let clientInstance = null;
|
|
559
|
+
const getOrCreateClient = () => {
|
|
560
|
+
if (!clientInstance) {
|
|
561
|
+
clientInstance = new CopilotClient(options.clientOptions ?? {});
|
|
562
|
+
}
|
|
563
|
+
return clientInstance;
|
|
564
|
+
};
|
|
565
|
+
const createModel = (modelId, settings = {}) => {
|
|
566
|
+
const mergedSettings = {
|
|
567
|
+
...options.defaultSettings,
|
|
568
|
+
...settings
|
|
569
|
+
};
|
|
570
|
+
return new GitHubCopilotLanguageModel({
|
|
571
|
+
modelId,
|
|
572
|
+
settings: mergedSettings,
|
|
573
|
+
getClient: getOrCreateClient
|
|
574
|
+
});
|
|
575
|
+
};
|
|
576
|
+
const provider = function(modelId, settings) {
|
|
577
|
+
if (new.target) {
|
|
578
|
+
throw new Error("The GitHub Copilot model function cannot be called with the new keyword.");
|
|
579
|
+
}
|
|
580
|
+
return createModel(modelId, settings);
|
|
581
|
+
};
|
|
582
|
+
provider.languageModel = createModel;
|
|
583
|
+
provider.chat = createModel;
|
|
584
|
+
provider.specificationVersion = "v3";
|
|
585
|
+
provider.embeddingModel = (modelId) => {
|
|
586
|
+
throw new NoSuchModelError({
|
|
587
|
+
modelId,
|
|
588
|
+
modelType: "embeddingModel"
|
|
589
|
+
});
|
|
590
|
+
};
|
|
591
|
+
provider.imageModel = (modelId) => {
|
|
592
|
+
throw new NoSuchModelError({
|
|
593
|
+
modelId,
|
|
594
|
+
modelType: "imageModel"
|
|
595
|
+
});
|
|
596
|
+
};
|
|
597
|
+
provider.getClient = getOrCreateClient;
|
|
598
|
+
return provider;
|
|
599
|
+
}
|
|
600
|
+
var githubCopilot = createGitHubCopilot();
|
|
601
|
+
|
|
602
|
+
export { GitHubCopilotLanguageModel, createAPICallError, createAuthenticationError, createGitHubCopilot, githubCopilot, handleCopilotError, isAbortError, isAuthenticationError };
|
|
603
|
+
//# sourceMappingURL=index.js.map
|
|
604
|
+
//# sourceMappingURL=index.js.map
|