@witqq/agent-sdk 0.6.1 → 0.8.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/README.md +539 -6
- package/dist/{types-BvwNzZCj.d.cts → agent-CW9XbmG_.d.ts} +148 -95
- package/dist/{types-BvwNzZCj.d.ts → agent-DxY68NZL.d.cts} +148 -95
- package/dist/auth/index.cjs +260 -2
- package/dist/auth/index.cjs.map +1 -1
- package/dist/auth/index.d.cts +21 -138
- package/dist/auth/index.d.ts +21 -138
- package/dist/auth/index.js +260 -3
- package/dist/auth/index.js.map +1 -1
- package/dist/backends/claude.cjs +653 -140
- package/dist/backends/claude.cjs.map +1 -1
- package/dist/backends/claude.d.cts +4 -1
- package/dist/backends/claude.d.ts +4 -1
- package/dist/backends/claude.js +653 -140
- package/dist/backends/claude.js.map +1 -1
- package/dist/backends/copilot.cjs +428 -88
- package/dist/backends/copilot.cjs.map +1 -1
- package/dist/backends/copilot.d.cts +13 -4
- package/dist/backends/copilot.d.ts +13 -4
- package/dist/backends/copilot.js +428 -88
- package/dist/backends/copilot.js.map +1 -1
- package/dist/backends/vercel-ai.cjs +349 -77
- package/dist/backends/vercel-ai.cjs.map +1 -1
- package/dist/backends/vercel-ai.d.cts +3 -1
- package/dist/backends/vercel-ai.d.ts +3 -1
- package/dist/backends/vercel-ai.js +349 -77
- package/dist/backends/vercel-ai.js.map +1 -1
- package/dist/backends-BSrsBYFn.d.cts +39 -0
- package/dist/backends-BSrsBYFn.d.ts +39 -0
- package/dist/chat/accumulator.cjs +147 -0
- package/dist/chat/accumulator.cjs.map +1 -0
- package/dist/chat/accumulator.d.cts +64 -0
- package/dist/chat/accumulator.d.ts +64 -0
- package/dist/chat/accumulator.js +145 -0
- package/dist/chat/accumulator.js.map +1 -0
- package/dist/chat/backends.cjs +3524 -0
- package/dist/chat/backends.cjs.map +1 -0
- package/dist/chat/backends.d.cts +66 -0
- package/dist/chat/backends.d.ts +66 -0
- package/dist/chat/backends.js +3512 -0
- package/dist/chat/backends.js.map +1 -0
- package/dist/chat/context.cjs +280 -0
- package/dist/chat/context.cjs.map +1 -0
- package/dist/chat/context.d.cts +191 -0
- package/dist/chat/context.d.ts +191 -0
- package/dist/chat/context.js +277 -0
- package/dist/chat/context.js.map +1 -0
- package/dist/chat/core.cjs +305 -0
- package/dist/chat/core.cjs.map +1 -0
- package/dist/chat/core.d.cts +84 -0
- package/dist/chat/core.d.ts +84 -0
- package/dist/chat/core.js +282 -0
- package/dist/chat/core.js.map +1 -0
- package/dist/chat/errors.cjs +273 -0
- package/dist/chat/errors.cjs.map +1 -0
- package/dist/chat/errors.d.cts +97 -0
- package/dist/chat/errors.d.ts +97 -0
- package/dist/chat/errors.js +266 -0
- package/dist/chat/errors.js.map +1 -0
- package/dist/chat/events.cjs +203 -0
- package/dist/chat/events.cjs.map +1 -0
- package/dist/chat/events.d.cts +245 -0
- package/dist/chat/events.d.ts +245 -0
- package/dist/chat/events.js +196 -0
- package/dist/chat/events.js.map +1 -0
- package/dist/chat/index.cjs +5550 -0
- package/dist/chat/index.cjs.map +1 -0
- package/dist/chat/index.d.cts +77 -0
- package/dist/chat/index.d.ts +77 -0
- package/dist/chat/index.js +5505 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/chat/react/theme.css +2517 -0
- package/dist/chat/react.cjs +3589 -0
- package/dist/chat/react.cjs.map +1 -0
- package/dist/chat/react.d.cts +1088 -0
- package/dist/chat/react.d.ts +1088 -0
- package/dist/chat/react.js +3547 -0
- package/dist/chat/react.js.map +1 -0
- package/dist/chat/runtime.cjs +1245 -0
- package/dist/chat/runtime.cjs.map +1 -0
- package/dist/chat/runtime.d.cts +182 -0
- package/dist/chat/runtime.d.ts +182 -0
- package/dist/chat/runtime.js +1243 -0
- package/dist/chat/runtime.js.map +1 -0
- package/dist/chat/server.cjs +2668 -0
- package/dist/chat/server.cjs.map +1 -0
- package/dist/chat/server.d.cts +648 -0
- package/dist/chat/server.d.ts +648 -0
- package/dist/chat/server.js +2628 -0
- package/dist/chat/server.js.map +1 -0
- package/dist/chat/sessions.cjs +380 -0
- package/dist/chat/sessions.cjs.map +1 -0
- package/dist/chat/sessions.d.cts +158 -0
- package/dist/chat/sessions.d.ts +158 -0
- package/dist/chat/sessions.js +376 -0
- package/dist/chat/sessions.js.map +1 -0
- package/dist/chat/sqlite.cjs +441 -0
- package/dist/chat/sqlite.cjs.map +1 -0
- package/dist/chat/sqlite.d.cts +128 -0
- package/dist/chat/sqlite.d.ts +128 -0
- package/dist/chat/sqlite.js +435 -0
- package/dist/chat/sqlite.js.map +1 -0
- package/dist/chat/state.cjs +190 -0
- package/dist/chat/state.cjs.map +1 -0
- package/dist/chat/state.d.cts +95 -0
- package/dist/chat/state.d.ts +95 -0
- package/dist/chat/state.js +180 -0
- package/dist/chat/state.js.map +1 -0
- package/dist/chat/storage.cjs +249 -0
- package/dist/chat/storage.cjs.map +1 -0
- package/dist/chat/storage.d.cts +197 -0
- package/dist/chat/storage.d.ts +197 -0
- package/dist/chat/storage.js +245 -0
- package/dist/chat/storage.js.map +1 -0
- package/dist/errors-C-so0M4t.d.cts +33 -0
- package/dist/errors-C-so0M4t.d.ts +33 -0
- package/dist/errors-CmVvczxZ.d.cts +28 -0
- package/dist/errors-CmVvczxZ.d.ts +28 -0
- package/dist/in-process-transport-C1JnJGVR.d.ts +228 -0
- package/dist/in-process-transport-C7DSqPyX.d.cts +228 -0
- package/dist/index.cjs +365 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +322 -125
- package/dist/index.d.ts +322 -125
- package/dist/index.js +359 -60
- package/dist/index.js.map +1 -1
- package/dist/provider-types-PTSlRPNB.d.cts +39 -0
- package/dist/provider-types-PTSlRPNB.d.ts +39 -0
- package/dist/refresh-manager-B81PpYBr.d.cts +153 -0
- package/dist/refresh-manager-Dlv_iNZi.d.ts +153 -0
- package/dist/testing.cjs +383 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +132 -0
- package/dist/testing.d.ts +132 -0
- package/dist/testing.js +377 -0
- package/dist/testing.js.map +1 -0
- package/dist/token-store-CSUBgYwn.d.ts +48 -0
- package/dist/token-store-CuC4hB9Z.d.cts +48 -0
- package/dist/transport-Cdh3M0tS.d.cts +68 -0
- package/dist/transport-Ciap4PWK.d.ts +68 -0
- package/dist/types-4vbcmPTp.d.cts +143 -0
- package/dist/types-BxggH0Yh.d.ts +143 -0
- package/dist/types-DRgd_9R7.d.cts +363 -0
- package/dist/types-ajANVzf7.d.ts +363 -0
- package/package.json +178 -6
package/dist/backends/copilot.js
CHANGED
|
@@ -1,4 +1,42 @@
|
|
|
1
|
-
// src/types.ts
|
|
1
|
+
// src/types/errors.ts
|
|
2
|
+
var RECOVERABLE_CODES = /* @__PURE__ */ new Set([
|
|
3
|
+
"TIMEOUT" /* TIMEOUT */,
|
|
4
|
+
"RATE_LIMIT" /* RATE_LIMIT */,
|
|
5
|
+
"NETWORK" /* NETWORK */,
|
|
6
|
+
"TOOL_EXECUTION" /* TOOL_EXECUTION */,
|
|
7
|
+
"MODEL_OVERLOADED" /* MODEL_OVERLOADED */,
|
|
8
|
+
"PROVIDER_ERROR" /* PROVIDER_ERROR */
|
|
9
|
+
]);
|
|
10
|
+
function isRecoverableErrorCode(code) {
|
|
11
|
+
return RECOVERABLE_CODES.has(code);
|
|
12
|
+
}
|
|
13
|
+
function classifyAgentError(error) {
|
|
14
|
+
const msg = (error instanceof Error ? error.message : error).toLowerCase();
|
|
15
|
+
if (msg.includes("timeout") || msg.includes("timed out") || msg.includes("timedout") || msg.includes("etimedout")) {
|
|
16
|
+
return "TIMEOUT" /* TIMEOUT */;
|
|
17
|
+
}
|
|
18
|
+
if (msg.includes("rate limit") || msg.includes("rate_limit") || msg.includes("429") || msg.includes("too many requests")) {
|
|
19
|
+
return "RATE_LIMIT" /* RATE_LIMIT */;
|
|
20
|
+
}
|
|
21
|
+
if (msg.includes("unauthorized") || msg.includes("401") || msg.includes("auth") && (msg.includes("expired") || msg.includes("invalid") || msg.includes("denied") || msg.includes("failed"))) {
|
|
22
|
+
return "AUTH_EXPIRED" /* AUTH_EXPIRED */;
|
|
23
|
+
}
|
|
24
|
+
if (msg.includes("econnrefused") || msg.includes("econnreset") || msg.includes("enotfound") || msg.includes("network") || msg.includes("fetch failed") || msg.includes("socket hang up")) {
|
|
25
|
+
return "NETWORK" /* NETWORK */;
|
|
26
|
+
}
|
|
27
|
+
if (msg.includes("subprocess") || msg.includes("process exited") || msg.includes("spawn") || msg.includes("enoent") || msg.includes("killed")) {
|
|
28
|
+
return "DEPENDENCY_MISSING" /* DEPENDENCY_MISSING */;
|
|
29
|
+
}
|
|
30
|
+
if (msg.includes("abort") || msg.includes("cancel")) {
|
|
31
|
+
return "ABORTED" /* ABORTED */;
|
|
32
|
+
}
|
|
33
|
+
if (msg.includes("500") || msg.includes("502") || msg.includes("503") || msg.includes("internal server error") || msg.includes("service unavailable") || msg.includes("bad gateway") || msg.includes("overloaded")) {
|
|
34
|
+
return "PROVIDER_ERROR" /* PROVIDER_ERROR */;
|
|
35
|
+
}
|
|
36
|
+
return "PROVIDER_ERROR" /* PROVIDER_ERROR */;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/types/guards.ts
|
|
2
40
|
function getTextContent(content) {
|
|
3
41
|
if (typeof content === "string") return content;
|
|
4
42
|
return content.filter((p) => p.type === "text").map((p) => p.text).join("\n");
|
|
@@ -6,41 +44,71 @@ function getTextContent(content) {
|
|
|
6
44
|
|
|
7
45
|
// src/errors.ts
|
|
8
46
|
var AgentSDKError = class extends Error {
|
|
47
|
+
/** @internal Marker for cross-bundle identity checks */
|
|
48
|
+
_agentSDKError = true;
|
|
49
|
+
/** Machine-readable error code. Prefer values from the ErrorCode enum. */
|
|
50
|
+
code;
|
|
51
|
+
/** Whether this error is safe to retry */
|
|
52
|
+
retryable;
|
|
53
|
+
/** HTTP status code hint for error classification */
|
|
54
|
+
httpStatus;
|
|
9
55
|
constructor(message, options) {
|
|
10
56
|
super(message, options);
|
|
11
57
|
this.name = "AgentSDKError";
|
|
58
|
+
this.code = options?.code;
|
|
59
|
+
this.retryable = options?.retryable ?? false;
|
|
60
|
+
this.httpStatus = options?.httpStatus;
|
|
61
|
+
}
|
|
62
|
+
/** Check if an error is an AgentSDKError (works across bundled copies) */
|
|
63
|
+
static is(error) {
|
|
64
|
+
return error instanceof Error && "_agentSDKError" in error && error._agentSDKError === true;
|
|
12
65
|
}
|
|
13
66
|
};
|
|
14
67
|
var ReentrancyError = class extends AgentSDKError {
|
|
15
68
|
constructor() {
|
|
16
|
-
super("Agent is already running. Await the current run before starting another."
|
|
69
|
+
super("Agent is already running. Await the current run before starting another.", {
|
|
70
|
+
code: "REENTRANCY" /* REENTRANCY */
|
|
71
|
+
});
|
|
17
72
|
this.name = "ReentrancyError";
|
|
18
73
|
}
|
|
19
74
|
};
|
|
20
75
|
var DisposedError = class extends AgentSDKError {
|
|
21
76
|
constructor(entity) {
|
|
22
|
-
super(`${entity} has been disposed and cannot be used
|
|
77
|
+
super(`${entity} has been disposed and cannot be used.`, {
|
|
78
|
+
code: "DISPOSED" /* DISPOSED */
|
|
79
|
+
});
|
|
23
80
|
this.name = "DisposedError";
|
|
24
81
|
}
|
|
25
82
|
};
|
|
26
83
|
var SubprocessError = class extends AgentSDKError {
|
|
27
84
|
constructor(message, options) {
|
|
28
|
-
super(message, options);
|
|
85
|
+
super(message, { ...options, code: "DEPENDENCY_MISSING" /* DEPENDENCY_MISSING */ });
|
|
29
86
|
this.name = "SubprocessError";
|
|
30
87
|
}
|
|
31
88
|
};
|
|
32
89
|
var AbortError = class extends AgentSDKError {
|
|
33
90
|
constructor() {
|
|
34
|
-
super("Agent run was aborted.");
|
|
91
|
+
super("Agent run was aborted.", { code: "ABORTED" /* ABORTED */ });
|
|
35
92
|
this.name = "AbortError";
|
|
36
93
|
}
|
|
37
94
|
};
|
|
95
|
+
var ActivityTimeoutError = class extends AgentSDKError {
|
|
96
|
+
constructor(timeoutMs) {
|
|
97
|
+
super(`Stream activity timeout: no event received within ${timeoutMs}ms.`, {
|
|
98
|
+
code: "TIMEOUT" /* TIMEOUT */,
|
|
99
|
+
retryable: true
|
|
100
|
+
});
|
|
101
|
+
this.name = "ActivityTimeoutError";
|
|
102
|
+
}
|
|
103
|
+
};
|
|
38
104
|
|
|
39
105
|
// src/base-agent.ts
|
|
40
106
|
var BaseAgent = class {
|
|
41
107
|
state = "idle";
|
|
42
108
|
abortController = null;
|
|
43
109
|
config;
|
|
110
|
+
_cleanupExternalSignal = null;
|
|
111
|
+
_streamMiddleware = [];
|
|
44
112
|
/** CLI session ID for persistent mode. Override in backends that support it. */
|
|
45
113
|
get sessionId() {
|
|
46
114
|
return void 0;
|
|
@@ -56,12 +124,14 @@ var BaseAgent = class {
|
|
|
56
124
|
this.state = "running";
|
|
57
125
|
try {
|
|
58
126
|
const messages = [{ role: "user", content: prompt }];
|
|
59
|
-
const result = await this.
|
|
60
|
-
|
|
127
|
+
const result = await this.withRetry(
|
|
128
|
+
() => this.executeRun(messages, options, ac.signal),
|
|
129
|
+
options
|
|
130
|
+
);
|
|
131
|
+
this.enrichAndNotifyUsage(result, options);
|
|
61
132
|
return result;
|
|
62
133
|
} finally {
|
|
63
|
-
this.
|
|
64
|
-
this.abortController = null;
|
|
134
|
+
this.cleanupRun();
|
|
65
135
|
}
|
|
66
136
|
}
|
|
67
137
|
async runWithContext(messages, options) {
|
|
@@ -70,12 +140,14 @@ var BaseAgent = class {
|
|
|
70
140
|
const ac = this.createAbortController(options?.signal);
|
|
71
141
|
this.state = "running";
|
|
72
142
|
try {
|
|
73
|
-
const result = await this.
|
|
74
|
-
|
|
143
|
+
const result = await this.withRetry(
|
|
144
|
+
() => this.executeRun(messages, options, ac.signal),
|
|
145
|
+
options
|
|
146
|
+
);
|
|
147
|
+
this.enrichAndNotifyUsage(result, options);
|
|
75
148
|
return result;
|
|
76
149
|
} finally {
|
|
77
|
-
this.
|
|
78
|
-
this.abortController = null;
|
|
150
|
+
this.cleanupRun();
|
|
79
151
|
}
|
|
80
152
|
}
|
|
81
153
|
async runStructured(prompt, schema, options) {
|
|
@@ -85,17 +157,14 @@ var BaseAgent = class {
|
|
|
85
157
|
this.state = "running";
|
|
86
158
|
try {
|
|
87
159
|
const messages = [{ role: "user", content: prompt }];
|
|
88
|
-
const result = await this.
|
|
89
|
-
messages,
|
|
90
|
-
|
|
91
|
-
options,
|
|
92
|
-
ac.signal
|
|
160
|
+
const result = await this.withRetry(
|
|
161
|
+
() => this.executeRunStructured(messages, schema, options, ac.signal),
|
|
162
|
+
options
|
|
93
163
|
);
|
|
94
|
-
this.enrichAndNotifyUsage(result);
|
|
164
|
+
this.enrichAndNotifyUsage(result, options);
|
|
95
165
|
return result;
|
|
96
166
|
} finally {
|
|
97
|
-
this.
|
|
98
|
-
this.abortController = null;
|
|
167
|
+
this.cleanupRun();
|
|
99
168
|
}
|
|
100
169
|
}
|
|
101
170
|
async *stream(prompt, options) {
|
|
@@ -105,11 +174,12 @@ var BaseAgent = class {
|
|
|
105
174
|
this.state = "streaming";
|
|
106
175
|
try {
|
|
107
176
|
const messages = [{ role: "user", content: prompt }];
|
|
108
|
-
|
|
109
|
-
|
|
177
|
+
yield* this.streamWithRetry(
|
|
178
|
+
() => this.applyStreamPipeline(this.executeStream(messages, options, ac.signal), options, ac),
|
|
179
|
+
options
|
|
180
|
+
);
|
|
110
181
|
} finally {
|
|
111
|
-
this.
|
|
112
|
-
this.abortController = null;
|
|
182
|
+
this.cleanupRun();
|
|
113
183
|
}
|
|
114
184
|
}
|
|
115
185
|
async *streamWithContext(messages, options) {
|
|
@@ -118,13 +188,37 @@ var BaseAgent = class {
|
|
|
118
188
|
const ac = this.createAbortController(options?.signal);
|
|
119
189
|
this.state = "streaming";
|
|
120
190
|
try {
|
|
121
|
-
|
|
122
|
-
|
|
191
|
+
yield* this.streamWithRetry(
|
|
192
|
+
() => this.applyStreamPipeline(this.executeStream(messages, options, ac.signal), options, ac),
|
|
193
|
+
options
|
|
194
|
+
);
|
|
123
195
|
} finally {
|
|
124
|
-
this.
|
|
125
|
-
this.abortController = null;
|
|
196
|
+
this.cleanupRun();
|
|
126
197
|
}
|
|
127
198
|
}
|
|
199
|
+
/** Register a stream middleware. Applied in registration order after built-in transforms. */
|
|
200
|
+
addStreamMiddleware(middleware) {
|
|
201
|
+
this.guardDisposed();
|
|
202
|
+
this._streamMiddleware.push(middleware);
|
|
203
|
+
}
|
|
204
|
+
/** Apply built-in transforms (enrich→timeout→heartbeat) then custom middleware */
|
|
205
|
+
async *applyStreamPipeline(source, options, ac) {
|
|
206
|
+
let stream = this.enrichStream(source, options);
|
|
207
|
+
stream = this.activityTimeoutStream(stream, options?.activityTimeoutMs, ac);
|
|
208
|
+
stream = this.heartbeatStream(stream);
|
|
209
|
+
if (this._streamMiddleware.length > 0) {
|
|
210
|
+
const ctx = {
|
|
211
|
+
model: options.model,
|
|
212
|
+
backend: this.backendName,
|
|
213
|
+
abortController: ac,
|
|
214
|
+
config: Object.freeze({ ...this.config })
|
|
215
|
+
};
|
|
216
|
+
for (const mw of this._streamMiddleware) {
|
|
217
|
+
stream = mw(stream, ctx);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
yield* stream;
|
|
221
|
+
}
|
|
128
222
|
abort() {
|
|
129
223
|
if (this.abortController) {
|
|
130
224
|
this.abortController.abort();
|
|
@@ -142,29 +236,114 @@ var BaseAgent = class {
|
|
|
142
236
|
}
|
|
143
237
|
/** Mark agent as disposed. Override to add cleanup. */
|
|
144
238
|
dispose() {
|
|
239
|
+
this._cleanupExternalSignal?.();
|
|
240
|
+
this._cleanupExternalSignal = null;
|
|
145
241
|
this.abort();
|
|
146
242
|
this.state = "disposed";
|
|
147
243
|
}
|
|
244
|
+
// ─── Retry Logic ─────────────────────────────────────────────
|
|
245
|
+
/** Check if an error should be retried given the retry configuration. */
|
|
246
|
+
isRetryableError(error, retry) {
|
|
247
|
+
if (error instanceof AbortError || error instanceof ReentrancyError || error instanceof DisposedError) {
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
if (AgentSDKError.is(error)) {
|
|
251
|
+
if (retry.retryableErrors && retry.retryableErrors.length > 0 && error.code) {
|
|
252
|
+
return retry.retryableErrors.includes(error.code);
|
|
253
|
+
}
|
|
254
|
+
if (error.retryable) return true;
|
|
255
|
+
if (error.code) return isRecoverableErrorCode(error.code);
|
|
256
|
+
}
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
/** Execute a function with retry logic per RetryConfig. */
|
|
260
|
+
async withRetry(fn, options) {
|
|
261
|
+
const retry = options?.retry;
|
|
262
|
+
if (!retry || !retry.maxRetries || retry.maxRetries <= 0) {
|
|
263
|
+
return fn();
|
|
264
|
+
}
|
|
265
|
+
const maxRetries = retry.maxRetries;
|
|
266
|
+
const initialDelay = retry.initialDelayMs ?? 1e3;
|
|
267
|
+
const multiplier = retry.backoffMultiplier ?? 2;
|
|
268
|
+
let lastError;
|
|
269
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
270
|
+
try {
|
|
271
|
+
return await fn();
|
|
272
|
+
} catch (err) {
|
|
273
|
+
lastError = err;
|
|
274
|
+
if (attempt >= maxRetries || !this.isRetryableError(err, retry)) {
|
|
275
|
+
throw err;
|
|
276
|
+
}
|
|
277
|
+
const delay = initialDelay * Math.pow(multiplier, attempt);
|
|
278
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
279
|
+
if (options?.signal?.aborted || this.abortController?.signal.aborted) {
|
|
280
|
+
throw err;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
throw lastError;
|
|
285
|
+
}
|
|
286
|
+
/** Execute a stream factory with pre-stream retry: retries until first event, then committed. */
|
|
287
|
+
async *streamWithRetry(factory, options) {
|
|
288
|
+
const retry = options?.retry;
|
|
289
|
+
if (!retry || !retry.maxRetries || retry.maxRetries <= 0) {
|
|
290
|
+
yield* factory();
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
const maxRetries = retry.maxRetries;
|
|
294
|
+
const initialDelay = retry.initialDelayMs ?? 1e3;
|
|
295
|
+
const multiplier = retry.backoffMultiplier ?? 2;
|
|
296
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
297
|
+
try {
|
|
298
|
+
const stream = factory();
|
|
299
|
+
const iterator = stream[Symbol.asyncIterator]();
|
|
300
|
+
const first = await iterator.next();
|
|
301
|
+
if (first.done) return;
|
|
302
|
+
yield first.value;
|
|
303
|
+
while (true) {
|
|
304
|
+
const next = await iterator.next();
|
|
305
|
+
if (next.done) break;
|
|
306
|
+
yield next.value;
|
|
307
|
+
}
|
|
308
|
+
return;
|
|
309
|
+
} catch (err) {
|
|
310
|
+
if (attempt >= maxRetries || !this.isRetryableError(err, retry)) {
|
|
311
|
+
throw err;
|
|
312
|
+
}
|
|
313
|
+
const delay = initialDelay * Math.pow(multiplier, attempt);
|
|
314
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
315
|
+
if (options?.signal?.aborted || this.abortController?.signal.aborted) {
|
|
316
|
+
throw err;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
// ─── CallOptions Resolution ──────────────────────────────────
|
|
322
|
+
/** Resolve tools to use for this call (per-call override > config default) */
|
|
323
|
+
resolveTools(options) {
|
|
324
|
+
return options?.tools ?? this.config.tools ?? [];
|
|
325
|
+
}
|
|
148
326
|
// ─── Usage Enrichment ───────────────────────────────────────────
|
|
149
327
|
/** Enrich result usage with model/backend and fire onUsage callback */
|
|
150
|
-
enrichAndNotifyUsage(result) {
|
|
328
|
+
enrichAndNotifyUsage(result, options) {
|
|
151
329
|
if (result.usage) {
|
|
152
330
|
result.usage = {
|
|
153
331
|
...result.usage,
|
|
154
|
-
model:
|
|
332
|
+
model: options.model,
|
|
155
333
|
backend: this.backendName
|
|
156
334
|
};
|
|
157
335
|
this.callOnUsage(result.usage);
|
|
158
336
|
}
|
|
159
337
|
}
|
|
160
338
|
/** Wrap a stream to enrich usage_update events and fire onUsage callback */
|
|
161
|
-
async *enrichStream(source) {
|
|
339
|
+
async *enrichStream(source, options) {
|
|
340
|
+
const model = options.model;
|
|
162
341
|
for await (const event of source) {
|
|
163
342
|
if (event.type === "usage_update") {
|
|
164
343
|
const usage = {
|
|
165
344
|
promptTokens: event.promptTokens,
|
|
166
345
|
completionTokens: event.completionTokens,
|
|
167
|
-
model
|
|
346
|
+
model,
|
|
168
347
|
backend: this.backendName
|
|
169
348
|
};
|
|
170
349
|
this.callOnUsage(usage);
|
|
@@ -234,6 +413,35 @@ var BaseAgent = class {
|
|
|
234
413
|
heartbeatResolve = null;
|
|
235
414
|
}
|
|
236
415
|
}
|
|
416
|
+
// ─── Activity Timeout ────────────────────────────────────────
|
|
417
|
+
/** Wrap a stream to abort on inactivity. Resets timer on every event.
|
|
418
|
+
* When timeoutMs is not set, passes through directly. */
|
|
419
|
+
async *activityTimeoutStream(source, timeoutMs, ac) {
|
|
420
|
+
if (!timeoutMs || timeoutMs <= 0) {
|
|
421
|
+
yield* source;
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
425
|
+
let timerId;
|
|
426
|
+
try {
|
|
427
|
+
while (true) {
|
|
428
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
429
|
+
timerId = setTimeout(() => reject(new ActivityTimeoutError(timeoutMs)), timeoutMs);
|
|
430
|
+
});
|
|
431
|
+
const result = await Promise.race([iterator.next(), timeoutPromise]);
|
|
432
|
+
clearTimeout(timerId);
|
|
433
|
+
if (result.done) break;
|
|
434
|
+
yield result.value;
|
|
435
|
+
}
|
|
436
|
+
} catch (err) {
|
|
437
|
+
if (err instanceof ActivityTimeoutError) {
|
|
438
|
+
ac.abort(err);
|
|
439
|
+
}
|
|
440
|
+
throw err;
|
|
441
|
+
} finally {
|
|
442
|
+
clearTimeout(timerId);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
237
445
|
// ─── Guards ───────────────────────────────────────────────────
|
|
238
446
|
guardReentrancy() {
|
|
239
447
|
if (this.state === "running" || this.state === "streaming") {
|
|
@@ -252,16 +460,24 @@ var BaseAgent = class {
|
|
|
252
460
|
}
|
|
253
461
|
}
|
|
254
462
|
// ─── Internal Helpers ─────────────────────────────────────────
|
|
463
|
+
/** Clean up after a run completes (success, error, or abort). */
|
|
464
|
+
cleanupRun() {
|
|
465
|
+
this._cleanupExternalSignal?.();
|
|
466
|
+
this._cleanupExternalSignal = null;
|
|
467
|
+
this.state = "idle";
|
|
468
|
+
this.abortController = null;
|
|
469
|
+
}
|
|
255
470
|
createAbortController(externalSignal) {
|
|
256
471
|
const ac = new AbortController();
|
|
257
472
|
this.abortController = ac;
|
|
473
|
+
this._cleanupExternalSignal = null;
|
|
258
474
|
if (externalSignal) {
|
|
259
475
|
if (externalSignal.aborted) {
|
|
260
476
|
ac.abort();
|
|
261
477
|
} else {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
478
|
+
const listener = () => ac.abort();
|
|
479
|
+
externalSignal.addEventListener("abort", listener, { once: true });
|
|
480
|
+
this._cleanupExternalSignal = () => externalSignal.removeEventListener("abort", listener);
|
|
265
481
|
}
|
|
266
482
|
}
|
|
267
483
|
return ac;
|
|
@@ -324,13 +540,67 @@ function extractSchemaFromDef(schema) {
|
|
|
324
540
|
}
|
|
325
541
|
}
|
|
326
542
|
|
|
543
|
+
// src/backends/shared.ts
|
|
544
|
+
function extractLastUserPrompt(messages) {
|
|
545
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
546
|
+
const msg = messages[i];
|
|
547
|
+
if (msg.role === "user") {
|
|
548
|
+
return getTextContent(msg.content);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
return "";
|
|
552
|
+
}
|
|
553
|
+
function serializeToolCall(tc) {
|
|
554
|
+
const args = typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args);
|
|
555
|
+
return ` Tool call: ${tc.name}(${args})`;
|
|
556
|
+
}
|
|
557
|
+
function serializeToolResult(tr) {
|
|
558
|
+
const result = typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result);
|
|
559
|
+
const prefix = tr.isError ? "[ERROR] " : "";
|
|
560
|
+
return ` ${tr.name} \u2192 ${prefix}${result}`;
|
|
561
|
+
}
|
|
562
|
+
function buildContextualPrompt(messages) {
|
|
563
|
+
if (messages.length <= 1) {
|
|
564
|
+
return extractLastUserPrompt(messages);
|
|
565
|
+
}
|
|
566
|
+
const history = messages.slice(0, -1).map((msg) => {
|
|
567
|
+
if (msg.role === "user") {
|
|
568
|
+
return `User: ${msg.content ? getTextContent(msg.content) : ""}`;
|
|
569
|
+
}
|
|
570
|
+
if (msg.role === "tool" && msg.toolResults) {
|
|
571
|
+
const results = msg.toolResults.map(serializeToolResult).join("\n");
|
|
572
|
+
return `Tool results:
|
|
573
|
+
${results}`;
|
|
574
|
+
}
|
|
575
|
+
if (msg.role === "assistant") {
|
|
576
|
+
const parts = [];
|
|
577
|
+
const thinking = msg.thinking;
|
|
578
|
+
if (thinking) {
|
|
579
|
+
parts.push(`[reasoning: ${thinking}]`);
|
|
580
|
+
}
|
|
581
|
+
const text2 = msg.content ? getTextContent(msg.content) : "";
|
|
582
|
+
if (text2) parts.push(text2);
|
|
583
|
+
if (msg.toolCalls && msg.toolCalls.length > 0) {
|
|
584
|
+
parts.push(msg.toolCalls.map(serializeToolCall).join("\n"));
|
|
585
|
+
}
|
|
586
|
+
return `Assistant: ${parts.join("\n")}`;
|
|
587
|
+
}
|
|
588
|
+
const text = msg.content ? getTextContent(msg.content) : "";
|
|
589
|
+
return `${msg.role}: ${text}`;
|
|
590
|
+
}).join("\n");
|
|
591
|
+
const lastPrompt = extractLastUserPrompt(messages);
|
|
592
|
+
return `Conversation history:
|
|
593
|
+
${history}
|
|
594
|
+
|
|
595
|
+
User: ${lastPrompt}`;
|
|
596
|
+
}
|
|
597
|
+
|
|
327
598
|
// src/backends/copilot.ts
|
|
328
|
-
var
|
|
599
|
+
var _sdkMock = null;
|
|
329
600
|
async function loadSDK() {
|
|
330
|
-
if (
|
|
601
|
+
if (_sdkMock) return _sdkMock;
|
|
331
602
|
try {
|
|
332
|
-
|
|
333
|
-
return sdkModule;
|
|
603
|
+
return await import('@github/copilot-sdk');
|
|
334
604
|
} catch {
|
|
335
605
|
throw new SubprocessError(
|
|
336
606
|
"@github/copilot-sdk is not installed. Install it: npm install @github/copilot-sdk"
|
|
@@ -338,18 +608,34 @@ async function loadSDK() {
|
|
|
338
608
|
}
|
|
339
609
|
}
|
|
340
610
|
function _injectSDK(mock) {
|
|
341
|
-
|
|
611
|
+
_sdkMock = mock;
|
|
342
612
|
}
|
|
343
613
|
function _resetSDK() {
|
|
344
|
-
|
|
614
|
+
_sdkMock = null;
|
|
345
615
|
}
|
|
346
616
|
function mapToolsToSDK(tools) {
|
|
347
617
|
return tools.map((tool) => ({
|
|
348
618
|
name: tool.name,
|
|
349
619
|
description: tool.description,
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
620
|
+
parameters: convertParameters(tool.parameters),
|
|
621
|
+
handler: async (args) => {
|
|
622
|
+
const result = await tool.execute(args);
|
|
623
|
+
return typeof result === "string" ? result : JSON.stringify(result);
|
|
624
|
+
}
|
|
625
|
+
}));
|
|
626
|
+
}
|
|
627
|
+
function convertParameters(params) {
|
|
628
|
+
if (!params) return void 0;
|
|
629
|
+
if (params && typeof params === "object" && "_def" in params) {
|
|
630
|
+
return zodToJsonSchema(params);
|
|
631
|
+
}
|
|
632
|
+
return params;
|
|
633
|
+
}
|
|
634
|
+
async function mapToolsToSDKAsync(tools) {
|
|
635
|
+
return tools.map((tool) => ({
|
|
636
|
+
name: tool.name,
|
|
637
|
+
description: tool.description,
|
|
638
|
+
parameters: convertParameters(tool.parameters),
|
|
353
639
|
handler: async (args) => {
|
|
354
640
|
const result = await tool.execute(args);
|
|
355
641
|
return typeof result === "string" ? result : JSON.stringify(result);
|
|
@@ -370,6 +656,7 @@ function buildPermissionHandler(config) {
|
|
|
370
656
|
const unifiedRequest = {
|
|
371
657
|
toolName,
|
|
372
658
|
toolArgs: { ...request },
|
|
659
|
+
toolCallId: request.toolCallId,
|
|
373
660
|
rawSDKRequest: request
|
|
374
661
|
};
|
|
375
662
|
const ac = new AbortController();
|
|
@@ -512,15 +799,21 @@ function mapSessionEvent(event, tracker, thinkingTracker) {
|
|
|
512
799
|
};
|
|
513
800
|
case "session.error":
|
|
514
801
|
console.error("[copilot] mapSessionEvent error:", JSON.stringify(data));
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
802
|
+
{
|
|
803
|
+
const errorMsg = String(data.message ?? "Unknown error");
|
|
804
|
+
const code = classifyAgentError(errorMsg);
|
|
805
|
+
return {
|
|
806
|
+
type: "error",
|
|
807
|
+
error: errorMsg,
|
|
808
|
+
recoverable: isRecoverableErrorCode(code),
|
|
809
|
+
code
|
|
810
|
+
};
|
|
811
|
+
}
|
|
520
812
|
case "assistant.message": {
|
|
521
813
|
const doneEvent = {
|
|
522
814
|
type: "done",
|
|
523
|
-
finalOutput:
|
|
815
|
+
finalOutput: null,
|
|
816
|
+
streamed: true
|
|
524
817
|
};
|
|
525
818
|
if (thinkingTracker.endThinking()) {
|
|
526
819
|
return [{ type: "thinking_end" }, doneEvent];
|
|
@@ -540,13 +833,16 @@ var CopilotAgent = class extends BaseAgent {
|
|
|
540
833
|
isPersistent;
|
|
541
834
|
persistentSession = null;
|
|
542
835
|
_sessionId;
|
|
836
|
+
_persistentModel;
|
|
543
837
|
activeSession = null;
|
|
544
|
-
|
|
838
|
+
_resumeSessionId;
|
|
839
|
+
_toolsReady = null;
|
|
840
|
+
constructor(config, getClient, sendAndWaitTimeout, resumeSessionId) {
|
|
545
841
|
super(config);
|
|
546
842
|
this.getClient = getClient;
|
|
547
843
|
this.sendAndWaitTimeout = sendAndWaitTimeout;
|
|
548
844
|
this.isPersistent = config.sessionMode === "persistent";
|
|
549
|
-
this.sdkTools = mapToolsToSDK(config.tools);
|
|
845
|
+
this.sdkTools = mapToolsToSDK(config.tools ?? []);
|
|
550
846
|
this.sessionConfig = {
|
|
551
847
|
model: config.model,
|
|
552
848
|
tools: this.sdkTools,
|
|
@@ -556,8 +852,16 @@ var CopilotAgent = class extends BaseAgent {
|
|
|
556
852
|
},
|
|
557
853
|
onPermissionRequest: buildPermissionHandler(config),
|
|
558
854
|
onUserInputRequest: buildUserInputHandler(config),
|
|
559
|
-
...config.availableTools ? { availableTools: config.availableTools } : {}
|
|
855
|
+
...config.availableTools?.length ? { availableTools: config.availableTools } : {}
|
|
560
856
|
};
|
|
857
|
+
this._toolsReady = this._initToolsAsync(config);
|
|
858
|
+
this._resumeSessionId = resumeSessionId;
|
|
859
|
+
}
|
|
860
|
+
/** Pre-convert Zod schemas to JSON Schema asynchronously.
|
|
861
|
+
* Updates sdkTools and sessionConfig.tools before first session creation. */
|
|
862
|
+
async _initToolsAsync(config) {
|
|
863
|
+
this.sdkTools = await mapToolsToSDKAsync(config.tools ?? []);
|
|
864
|
+
this.sessionConfig.tools = this.sdkTools;
|
|
561
865
|
}
|
|
562
866
|
get sessionId() {
|
|
563
867
|
return this._sessionId;
|
|
@@ -580,27 +884,63 @@ var CopilotAgent = class extends BaseAgent {
|
|
|
580
884
|
});
|
|
581
885
|
this.persistentSession = null;
|
|
582
886
|
this._sessionId = void 0;
|
|
887
|
+
this._persistentModel = void 0;
|
|
583
888
|
}
|
|
584
889
|
}
|
|
585
|
-
async getOrCreateSession(streaming) {
|
|
890
|
+
async getOrCreateSession(streaming, options) {
|
|
586
891
|
if (this.isPersistent && this.persistentSession) {
|
|
587
|
-
|
|
892
|
+
if (options.model !== this._persistentModel) {
|
|
893
|
+
this.persistentSession.destroy().catch(() => {
|
|
894
|
+
});
|
|
895
|
+
this.persistentSession = null;
|
|
896
|
+
this._sessionId = void 0;
|
|
897
|
+
} else {
|
|
898
|
+
return { session: this.persistentSession, isNew: false };
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
if (this._toolsReady) {
|
|
902
|
+
await this._toolsReady;
|
|
903
|
+
this._toolsReady = null;
|
|
904
|
+
}
|
|
905
|
+
const sessionConfig = { ...this.sessionConfig };
|
|
906
|
+
sessionConfig.model = options.model;
|
|
907
|
+
const resolvedTools = this.resolveTools(options);
|
|
908
|
+
if (options?.tools) {
|
|
909
|
+
sessionConfig.tools = mapToolsToSDK(resolvedTools);
|
|
588
910
|
}
|
|
589
911
|
const client = await this.getClient();
|
|
912
|
+
if (this._resumeSessionId) {
|
|
913
|
+
const storedId = this._resumeSessionId;
|
|
914
|
+
this._resumeSessionId = void 0;
|
|
915
|
+
try {
|
|
916
|
+
const session2 = await client.resumeSession(storedId, {
|
|
917
|
+
...sessionConfig,
|
|
918
|
+
streaming: this.isPersistent ? true : streaming
|
|
919
|
+
});
|
|
920
|
+
if (this.isPersistent) {
|
|
921
|
+
this.persistentSession = session2;
|
|
922
|
+
this._sessionId = session2.sessionId;
|
|
923
|
+
this._persistentModel = options.model;
|
|
924
|
+
}
|
|
925
|
+
return { session: session2, isNew: false };
|
|
926
|
+
} catch {
|
|
927
|
+
}
|
|
928
|
+
}
|
|
590
929
|
const session = await client.createSession({
|
|
591
|
-
...
|
|
930
|
+
...sessionConfig,
|
|
592
931
|
streaming: this.isPersistent ? true : streaming
|
|
593
932
|
});
|
|
594
933
|
if (this.isPersistent) {
|
|
595
934
|
this.persistentSession = session;
|
|
596
935
|
this._sessionId = session.sessionId;
|
|
936
|
+
this._persistentModel = options.model;
|
|
597
937
|
}
|
|
598
938
|
return { session, isNew: true };
|
|
599
939
|
}
|
|
600
940
|
// ─── executeRun ─────────────────────────────────────────────────
|
|
601
|
-
async executeRun(messages,
|
|
941
|
+
async executeRun(messages, options, signal) {
|
|
602
942
|
this.checkAbort(signal);
|
|
603
|
-
const { session, isNew: isNewSession } = await this.getOrCreateSession(false);
|
|
943
|
+
const { session, isNew: isNewSession } = await this.getOrCreateSession(false, options);
|
|
604
944
|
this.activeSession = session;
|
|
605
945
|
const prompt = this.isPersistent && !isNewSession ? extractLastUserPrompt(messages) : buildContextualPrompt(messages);
|
|
606
946
|
const tracker = new ToolCallTracker();
|
|
@@ -697,9 +1037,9 @@ You MUST respond with ONLY valid JSON matching this schema:
|
|
|
697
1037
|
};
|
|
698
1038
|
}
|
|
699
1039
|
// ─── executeStream ──────────────────────────────────────────────
|
|
700
|
-
async *executeStream(messages,
|
|
1040
|
+
async *executeStream(messages, options, signal) {
|
|
701
1041
|
this.checkAbort(signal);
|
|
702
|
-
const { session, isNew: isNewSession } = await this.getOrCreateSession(true);
|
|
1042
|
+
const { session, isNew: isNewSession } = await this.getOrCreateSession(true, options);
|
|
703
1043
|
this.activeSession = session;
|
|
704
1044
|
if (isNewSession) {
|
|
705
1045
|
yield this.emitSessionInfo(session.sessionId);
|
|
@@ -785,28 +1125,20 @@ You MUST respond with ONLY valid JSON matching this schema:
|
|
|
785
1125
|
super.dispose();
|
|
786
1126
|
}
|
|
787
1127
|
};
|
|
788
|
-
function
|
|
789
|
-
|
|
790
|
-
const
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
const text = msg.content ? getTextContent(msg.content) : "";
|
|
803
|
-
return msg.role === "user" ? `User: ${text}` : `Assistant: ${text}`;
|
|
804
|
-
}).join("\n");
|
|
805
|
-
const lastPrompt = extractLastUserPrompt(messages);
|
|
806
|
-
return `Conversation history:
|
|
807
|
-
${history}
|
|
808
|
-
|
|
809
|
-
User: ${lastPrompt}`;
|
|
1128
|
+
function withTimeout(promise, ms, message) {
|
|
1129
|
+
return new Promise((resolve, reject) => {
|
|
1130
|
+
const timer = setTimeout(() => reject(new SubprocessError(message)), ms);
|
|
1131
|
+
promise.then(
|
|
1132
|
+
(val) => {
|
|
1133
|
+
clearTimeout(timer);
|
|
1134
|
+
resolve(val);
|
|
1135
|
+
},
|
|
1136
|
+
(err) => {
|
|
1137
|
+
clearTimeout(timer);
|
|
1138
|
+
reject(err);
|
|
1139
|
+
}
|
|
1140
|
+
);
|
|
1141
|
+
});
|
|
810
1142
|
}
|
|
811
1143
|
var CopilotAgentService = class {
|
|
812
1144
|
name = "copilot";
|
|
@@ -832,12 +1164,17 @@ var CopilotAgentService = class {
|
|
|
832
1164
|
autoRestart: true,
|
|
833
1165
|
logLevel: "error",
|
|
834
1166
|
githubToken: this.options.githubToken,
|
|
835
|
-
useLoggedInUser: this.options.useLoggedInUser ??
|
|
1167
|
+
useLoggedInUser: this.options.useLoggedInUser ?? !this.options.githubToken,
|
|
836
1168
|
...this.options.cliArgs ? { cliArgs: this.options.cliArgs } : {},
|
|
837
1169
|
...this.options.env ? { env: { ...process.env, ...this.options.env } } : {}
|
|
838
1170
|
});
|
|
839
|
-
|
|
840
|
-
|
|
1171
|
+
const startupTimeout = this.options.startupTimeoutMs ?? 3e4;
|
|
1172
|
+
await withTimeout(client.start(), startupTimeout, "CLI startup timed out");
|
|
1173
|
+
const auth = await withTimeout(
|
|
1174
|
+
client.getAuthStatus(),
|
|
1175
|
+
startupTimeout,
|
|
1176
|
+
"Auth status check timed out \u2014 token may be expired"
|
|
1177
|
+
);
|
|
841
1178
|
if (!auth.isAuthenticated) {
|
|
842
1179
|
await client.stop();
|
|
843
1180
|
throw new SubprocessError(
|
|
@@ -855,7 +1192,7 @@ var CopilotAgentService = class {
|
|
|
855
1192
|
}
|
|
856
1193
|
createAgent(config) {
|
|
857
1194
|
if (this.disposed) throw new DisposedError("CopilotAgentService");
|
|
858
|
-
return new CopilotAgent(config, () => this.ensureClient(), this.options.timeout);
|
|
1195
|
+
return new CopilotAgent(config, () => this.ensureClient(), this.options.timeout, this.options.resumeSessionId);
|
|
859
1196
|
}
|
|
860
1197
|
async listModels() {
|
|
861
1198
|
const client = await this.ensureClient();
|
|
@@ -863,7 +1200,10 @@ var CopilotAgentService = class {
|
|
|
863
1200
|
return models.map((m) => ({
|
|
864
1201
|
id: m.id,
|
|
865
1202
|
name: m.name,
|
|
866
|
-
provider: "copilot"
|
|
1203
|
+
provider: "copilot",
|
|
1204
|
+
...m.capabilities?.limits?.max_context_window_tokens != null && {
|
|
1205
|
+
contextWindow: m.capabilities.limits.max_context_window_tokens
|
|
1206
|
+
}
|
|
867
1207
|
}));
|
|
868
1208
|
}
|
|
869
1209
|
async validate() {
|