@witqq/agent-sdk 0.7.0 → 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 +140 -34
- package/dist/{types-CqvUAYxt.d.cts → agent-CW9XbmG_.d.ts} +137 -102
- package/dist/{types-CqvUAYxt.d.ts → agent-DxY68NZL.d.cts} +137 -102
- package/dist/auth/index.cjs +72 -1
- package/dist/auth/index.cjs.map +1 -1
- package/dist/auth/index.d.cts +21 -154
- package/dist/auth/index.d.ts +21 -154
- package/dist/auth/index.js +72 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/backends/claude.cjs +480 -261
- package/dist/backends/claude.cjs.map +1 -1
- package/dist/backends/claude.d.cts +3 -1
- package/dist/backends/claude.d.ts +3 -1
- package/dist/backends/claude.js +480 -261
- package/dist/backends/claude.js.map +1 -1
- package/dist/backends/copilot.cjs +329 -97
- package/dist/backends/copilot.cjs.map +1 -1
- package/dist/backends/copilot.d.cts +12 -4
- package/dist/backends/copilot.d.ts +12 -4
- package/dist/backends/copilot.js +329 -97
- package/dist/backends/copilot.js.map +1 -1
- package/dist/backends/vercel-ai.cjs +294 -61
- 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 +294 -61
- 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 +1 -1
- package/dist/chat/accumulator.cjs.map +1 -1
- package/dist/chat/accumulator.d.cts +5 -2
- package/dist/chat/accumulator.d.ts +5 -2
- package/dist/chat/accumulator.js +1 -1
- package/dist/chat/accumulator.js.map +1 -1
- package/dist/chat/backends.cjs +736 -746
- package/dist/chat/backends.cjs.map +1 -1
- package/dist/chat/backends.d.cts +10 -6
- package/dist/chat/backends.d.ts +10 -6
- package/dist/chat/backends.js +736 -725
- package/dist/chat/backends.js.map +1 -1
- package/dist/chat/context.cjs +50 -0
- package/dist/chat/context.cjs.map +1 -1
- package/dist/chat/context.d.cts +27 -3
- package/dist/chat/context.d.ts +27 -3
- package/dist/chat/context.js +50 -0
- package/dist/chat/context.js.map +1 -1
- package/dist/chat/core.cjs +25 -2
- package/dist/chat/core.cjs.map +1 -1
- package/dist/chat/core.d.cts +30 -381
- package/dist/chat/core.d.ts +30 -381
- package/dist/chat/core.js +24 -3
- package/dist/chat/core.js.map +1 -1
- package/dist/chat/errors.cjs +48 -26
- package/dist/chat/errors.cjs.map +1 -1
- package/dist/chat/errors.d.cts +6 -31
- package/dist/chat/errors.d.ts +6 -31
- package/dist/chat/errors.js +48 -25
- package/dist/chat/errors.js.map +1 -1
- package/dist/chat/events.cjs.map +1 -1
- package/dist/chat/events.d.cts +6 -2
- package/dist/chat/events.d.ts +6 -2
- package/dist/chat/events.js.map +1 -1
- package/dist/chat/index.cjs +1199 -1008
- package/dist/chat/index.cjs.map +1 -1
- package/dist/chat/index.d.cts +35 -10
- package/dist/chat/index.d.ts +35 -10
- package/dist/chat/index.js +1196 -987
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/react/theme.css +2517 -0
- package/dist/chat/react.cjs +2003 -1153
- package/dist/chat/react.cjs.map +1 -1
- package/dist/chat/react.d.cts +590 -121
- package/dist/chat/react.d.ts +590 -121
- package/dist/chat/react.js +1984 -1151
- package/dist/chat/react.js.map +1 -1
- package/dist/chat/runtime.cjs +401 -186
- package/dist/chat/runtime.cjs.map +1 -1
- package/dist/chat/runtime.d.cts +92 -28
- package/dist/chat/runtime.d.ts +92 -28
- package/dist/chat/runtime.js +401 -186
- package/dist/chat/runtime.js.map +1 -1
- package/dist/chat/server.cjs +2234 -209
- package/dist/chat/server.cjs.map +1 -1
- package/dist/chat/server.d.cts +451 -90
- package/dist/chat/server.d.ts +451 -90
- package/dist/chat/server.js +2221 -210
- package/dist/chat/server.js.map +1 -1
- package/dist/chat/sessions.cjs +25 -43
- package/dist/chat/sessions.cjs.map +1 -1
- package/dist/chat/sessions.d.cts +37 -118
- package/dist/chat/sessions.d.ts +37 -118
- package/dist/chat/sessions.js +25 -43
- package/dist/chat/sessions.js.map +1 -1
- 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 +14 -1
- package/dist/chat/state.cjs.map +1 -1
- package/dist/chat/state.d.cts +5 -2
- package/dist/chat/state.d.ts +5 -2
- package/dist/chat/state.js +14 -1
- package/dist/chat/state.js.map +1 -1
- package/dist/chat/storage.cjs +19 -10
- package/dist/chat/storage.cjs.map +1 -1
- package/dist/chat/storage.d.cts +11 -5
- package/dist/chat/storage.d.ts +11 -5
- package/dist/chat/storage.js +19 -10
- package/dist/chat/storage.js.map +1 -1
- 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-C2oPTYs6.d.ts → in-process-transport-C1JnJGVR.d.ts} +28 -23
- package/dist/{in-process-transport-DG-w5G6k.d.cts → in-process-transport-C7DSqPyX.d.cts} +28 -23
- package/dist/index.cjs +340 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +292 -123
- package/dist/index.d.ts +292 -123
- package/dist/index.js +334 -47
- 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-DX1Nhm4N.d.cts → transport-Cdh3M0tS.d.cts} +5 -4
- package/dist/{transport-D1OaUgRk.d.ts → transport-Ciap4PWK.d.ts} +5 -4
- package/dist/{types-CGF7AEX1.d.cts → types-4vbcmPTp.d.cts} +4 -2
- package/dist/{types-Bh5AhqD-.d.ts → types-BxggH0Yh.d.ts} +4 -2
- package/dist/types-DRgd_9R7.d.cts +363 -0
- package/dist/types-ajANVzf7.d.ts +363 -0
- package/package.json +31 -6
- package/dist/errors-BDLbNu9w.d.cts +0 -13
- package/dist/errors-BDLbNu9w.d.ts +0 -13
- package/dist/types-DLZzlJxt.d.ts +0 -39
- package/dist/types-tE0CXwBl.d.cts +0 -39
package/dist/chat/backends.cjs
CHANGED
|
@@ -1,31 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var fs = require('fs');
|
|
4
|
-
var path = require('path');
|
|
5
|
-
var os = require('os');
|
|
6
|
-
|
|
7
|
-
function _interopNamespace(e) {
|
|
8
|
-
if (e && e.__esModule) return e;
|
|
9
|
-
var n = Object.create(null);
|
|
10
|
-
if (e) {
|
|
11
|
-
Object.keys(e).forEach(function (k) {
|
|
12
|
-
if (k !== 'default') {
|
|
13
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
-
enumerable: true,
|
|
16
|
-
get: function () { return e[k]; }
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
n.default = e;
|
|
22
|
-
return Object.freeze(n);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
|
|
26
|
-
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
27
|
-
var os__namespace = /*#__PURE__*/_interopNamespace(os);
|
|
28
|
-
|
|
29
3
|
var __defProp = Object.defineProperty;
|
|
30
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
31
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -47,16 +21,69 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
47
21
|
};
|
|
48
22
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
49
23
|
|
|
50
|
-
// src/errors.ts
|
|
51
|
-
|
|
24
|
+
// src/types/errors.ts
|
|
25
|
+
function isRecoverableErrorCode(code) {
|
|
26
|
+
return RECOVERABLE_CODES.has(code);
|
|
27
|
+
}
|
|
28
|
+
function classifyAgentError(error) {
|
|
29
|
+
const msg = (error instanceof Error ? error.message : error).toLowerCase();
|
|
30
|
+
if (msg.includes("timeout") || msg.includes("timed out") || msg.includes("timedout") || msg.includes("etimedout")) {
|
|
31
|
+
return "TIMEOUT" /* TIMEOUT */;
|
|
32
|
+
}
|
|
33
|
+
if (msg.includes("rate limit") || msg.includes("rate_limit") || msg.includes("429") || msg.includes("too many requests")) {
|
|
34
|
+
return "RATE_LIMIT" /* RATE_LIMIT */;
|
|
35
|
+
}
|
|
36
|
+
if (msg.includes("unauthorized") || msg.includes("401") || msg.includes("auth") && (msg.includes("expired") || msg.includes("invalid") || msg.includes("denied") || msg.includes("failed"))) {
|
|
37
|
+
return "AUTH_EXPIRED" /* AUTH_EXPIRED */;
|
|
38
|
+
}
|
|
39
|
+
if (msg.includes("econnrefused") || msg.includes("econnreset") || msg.includes("enotfound") || msg.includes("network") || msg.includes("fetch failed") || msg.includes("socket hang up")) {
|
|
40
|
+
return "NETWORK" /* NETWORK */;
|
|
41
|
+
}
|
|
42
|
+
if (msg.includes("subprocess") || msg.includes("process exited") || msg.includes("spawn") || msg.includes("enoent") || msg.includes("killed")) {
|
|
43
|
+
return "DEPENDENCY_MISSING" /* DEPENDENCY_MISSING */;
|
|
44
|
+
}
|
|
45
|
+
if (msg.includes("abort") || msg.includes("cancel")) {
|
|
46
|
+
return "ABORTED" /* ABORTED */;
|
|
47
|
+
}
|
|
48
|
+
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")) {
|
|
49
|
+
return "PROVIDER_ERROR" /* PROVIDER_ERROR */;
|
|
50
|
+
}
|
|
51
|
+
return "PROVIDER_ERROR" /* PROVIDER_ERROR */;
|
|
52
|
+
}
|
|
53
|
+
var RECOVERABLE_CODES;
|
|
52
54
|
var init_errors = __esm({
|
|
55
|
+
"src/types/errors.ts"() {
|
|
56
|
+
RECOVERABLE_CODES = /* @__PURE__ */ new Set([
|
|
57
|
+
"TIMEOUT" /* TIMEOUT */,
|
|
58
|
+
"RATE_LIMIT" /* RATE_LIMIT */,
|
|
59
|
+
"NETWORK" /* NETWORK */,
|
|
60
|
+
"TOOL_EXECUTION" /* TOOL_EXECUTION */,
|
|
61
|
+
"MODEL_OVERLOADED" /* MODEL_OVERLOADED */,
|
|
62
|
+
"PROVIDER_ERROR" /* PROVIDER_ERROR */
|
|
63
|
+
]);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// src/errors.ts
|
|
68
|
+
var AgentSDKError, ReentrancyError, DisposedError, SubprocessError, DependencyError, AbortError, ToolExecutionError, ActivityTimeoutError;
|
|
69
|
+
var init_errors2 = __esm({
|
|
53
70
|
"src/errors.ts"() {
|
|
71
|
+
init_errors();
|
|
54
72
|
AgentSDKError = class extends Error {
|
|
55
73
|
/** @internal Marker for cross-bundle identity checks */
|
|
56
74
|
_agentSDKError = true;
|
|
75
|
+
/** Machine-readable error code. Prefer values from the ErrorCode enum. */
|
|
76
|
+
code;
|
|
77
|
+
/** Whether this error is safe to retry */
|
|
78
|
+
retryable;
|
|
79
|
+
/** HTTP status code hint for error classification */
|
|
80
|
+
httpStatus;
|
|
57
81
|
constructor(message, options) {
|
|
58
82
|
super(message, options);
|
|
59
83
|
this.name = "AgentSDKError";
|
|
84
|
+
this.code = options?.code;
|
|
85
|
+
this.retryable = options?.retryable ?? false;
|
|
86
|
+
this.httpStatus = options?.httpStatus;
|
|
60
87
|
}
|
|
61
88
|
/** Check if an error is an AgentSDKError (works across bundled copies) */
|
|
62
89
|
static is(error) {
|
|
@@ -65,83 +92,84 @@ var init_errors = __esm({
|
|
|
65
92
|
};
|
|
66
93
|
ReentrancyError = class extends AgentSDKError {
|
|
67
94
|
constructor() {
|
|
68
|
-
super("Agent is already running. Await the current run before starting another."
|
|
95
|
+
super("Agent is already running. Await the current run before starting another.", {
|
|
96
|
+
code: "REENTRANCY" /* REENTRANCY */
|
|
97
|
+
});
|
|
69
98
|
this.name = "ReentrancyError";
|
|
70
99
|
}
|
|
71
100
|
};
|
|
72
101
|
DisposedError = class extends AgentSDKError {
|
|
73
102
|
constructor(entity) {
|
|
74
|
-
super(`${entity} has been disposed and cannot be used
|
|
103
|
+
super(`${entity} has been disposed and cannot be used.`, {
|
|
104
|
+
code: "DISPOSED" /* DISPOSED */
|
|
105
|
+
});
|
|
75
106
|
this.name = "DisposedError";
|
|
76
107
|
}
|
|
77
108
|
};
|
|
78
|
-
BackendNotFoundError = class extends AgentSDKError {
|
|
79
|
-
constructor(backend) {
|
|
80
|
-
super(
|
|
81
|
-
`Unknown backend: "${backend}". Built-in: copilot, claude, vercel-ai. Custom: use registerBackend() first.`
|
|
82
|
-
);
|
|
83
|
-
this.name = "BackendNotFoundError";
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
BackendAlreadyRegisteredError = class extends AgentSDKError {
|
|
87
|
-
constructor(backend) {
|
|
88
|
-
super(`Backend "${backend}" is already registered. Use a different name or unregister first.`);
|
|
89
|
-
this.name = "BackendAlreadyRegisteredError";
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
109
|
SubprocessError = class extends AgentSDKError {
|
|
93
110
|
constructor(message, options) {
|
|
94
|
-
super(message, options);
|
|
111
|
+
super(message, { ...options, code: "DEPENDENCY_MISSING" /* DEPENDENCY_MISSING */ });
|
|
95
112
|
this.name = "SubprocessError";
|
|
96
113
|
}
|
|
97
114
|
};
|
|
98
115
|
DependencyError = class extends AgentSDKError {
|
|
99
116
|
packageName;
|
|
100
117
|
constructor(packageName) {
|
|
101
|
-
super(`${packageName} is not installed. Install it: npm install ${packageName}
|
|
118
|
+
super(`${packageName} is not installed. Install it: npm install ${packageName}`, {
|
|
119
|
+
code: "DEPENDENCY_MISSING" /* DEPENDENCY_MISSING */
|
|
120
|
+
});
|
|
102
121
|
this.name = "DependencyError";
|
|
103
122
|
this.packageName = packageName;
|
|
104
123
|
}
|
|
105
124
|
};
|
|
106
125
|
AbortError = class extends AgentSDKError {
|
|
107
126
|
constructor() {
|
|
108
|
-
super("Agent run was aborted.");
|
|
127
|
+
super("Agent run was aborted.", { code: "ABORTED" /* ABORTED */ });
|
|
109
128
|
this.name = "AbortError";
|
|
110
129
|
}
|
|
111
130
|
};
|
|
112
131
|
ToolExecutionError = class extends AgentSDKError {
|
|
113
132
|
toolName;
|
|
114
133
|
constructor(toolName, message, options) {
|
|
115
|
-
super(`Tool "${toolName}" failed: ${message}`, options);
|
|
134
|
+
super(`Tool "${toolName}" failed: ${message}`, { ...options, code: "TOOL_EXECUTION" /* TOOL_EXECUTION */ });
|
|
116
135
|
this.name = "ToolExecutionError";
|
|
117
136
|
this.toolName = toolName;
|
|
118
137
|
}
|
|
119
138
|
};
|
|
120
|
-
|
|
121
|
-
constructor(
|
|
122
|
-
super(`
|
|
123
|
-
|
|
139
|
+
ActivityTimeoutError = class extends AgentSDKError {
|
|
140
|
+
constructor(timeoutMs) {
|
|
141
|
+
super(`Stream activity timeout: no event received within ${timeoutMs}ms.`, {
|
|
142
|
+
code: "TIMEOUT" /* TIMEOUT */,
|
|
143
|
+
retryable: true
|
|
144
|
+
});
|
|
145
|
+
this.name = "ActivityTimeoutError";
|
|
124
146
|
}
|
|
125
147
|
};
|
|
126
148
|
}
|
|
127
149
|
});
|
|
128
150
|
|
|
129
|
-
// src/types.ts
|
|
130
|
-
function isToolDefinition(tool) {
|
|
131
|
-
return "execute" in tool && typeof tool.execute === "function";
|
|
132
|
-
}
|
|
133
|
-
function isTextContent(content) {
|
|
134
|
-
return typeof content === "string";
|
|
135
|
-
}
|
|
136
|
-
function isMultiPartContent(content) {
|
|
137
|
-
return Array.isArray(content);
|
|
138
|
-
}
|
|
151
|
+
// src/types/guards.ts
|
|
139
152
|
function getTextContent(content) {
|
|
140
153
|
if (typeof content === "string") return content;
|
|
141
154
|
return content.filter((p) => p.type === "text").map((p) => p.text).join("\n");
|
|
142
155
|
}
|
|
156
|
+
var init_guards = __esm({
|
|
157
|
+
"src/types/guards.ts"() {
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// src/types/index.ts
|
|
143
162
|
var init_types = __esm({
|
|
163
|
+
"src/types/index.ts"() {
|
|
164
|
+
init_errors();
|
|
165
|
+
init_guards();
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// src/types.ts
|
|
170
|
+
var init_types2 = __esm({
|
|
144
171
|
"src/types.ts"() {
|
|
172
|
+
init_types();
|
|
145
173
|
}
|
|
146
174
|
});
|
|
147
175
|
|
|
@@ -149,12 +177,15 @@ var init_types = __esm({
|
|
|
149
177
|
var BaseAgent;
|
|
150
178
|
var init_base_agent = __esm({
|
|
151
179
|
"src/base-agent.ts"() {
|
|
180
|
+
init_errors2();
|
|
181
|
+
init_errors2();
|
|
152
182
|
init_errors();
|
|
153
183
|
BaseAgent = class {
|
|
154
184
|
state = "idle";
|
|
155
185
|
abortController = null;
|
|
156
186
|
config;
|
|
157
187
|
_cleanupExternalSignal = null;
|
|
188
|
+
_streamMiddleware = [];
|
|
158
189
|
/** CLI session ID for persistent mode. Override in backends that support it. */
|
|
159
190
|
get sessionId() {
|
|
160
191
|
return void 0;
|
|
@@ -170,8 +201,11 @@ var init_base_agent = __esm({
|
|
|
170
201
|
this.state = "running";
|
|
171
202
|
try {
|
|
172
203
|
const messages = [{ role: "user", content: prompt }];
|
|
173
|
-
const result = await this.
|
|
174
|
-
|
|
204
|
+
const result = await this.withRetry(
|
|
205
|
+
() => this.executeRun(messages, options, ac.signal),
|
|
206
|
+
options
|
|
207
|
+
);
|
|
208
|
+
this.enrichAndNotifyUsage(result, options);
|
|
175
209
|
return result;
|
|
176
210
|
} finally {
|
|
177
211
|
this.cleanupRun();
|
|
@@ -183,8 +217,11 @@ var init_base_agent = __esm({
|
|
|
183
217
|
const ac = this.createAbortController(options?.signal);
|
|
184
218
|
this.state = "running";
|
|
185
219
|
try {
|
|
186
|
-
const result = await this.
|
|
187
|
-
|
|
220
|
+
const result = await this.withRetry(
|
|
221
|
+
() => this.executeRun(messages, options, ac.signal),
|
|
222
|
+
options
|
|
223
|
+
);
|
|
224
|
+
this.enrichAndNotifyUsage(result, options);
|
|
188
225
|
return result;
|
|
189
226
|
} finally {
|
|
190
227
|
this.cleanupRun();
|
|
@@ -197,13 +234,11 @@ var init_base_agent = __esm({
|
|
|
197
234
|
this.state = "running";
|
|
198
235
|
try {
|
|
199
236
|
const messages = [{ role: "user", content: prompt }];
|
|
200
|
-
const result = await this.
|
|
201
|
-
messages,
|
|
202
|
-
|
|
203
|
-
options,
|
|
204
|
-
ac.signal
|
|
237
|
+
const result = await this.withRetry(
|
|
238
|
+
() => this.executeRunStructured(messages, schema, options, ac.signal),
|
|
239
|
+
options
|
|
205
240
|
);
|
|
206
|
-
this.enrichAndNotifyUsage(result);
|
|
241
|
+
this.enrichAndNotifyUsage(result, options);
|
|
207
242
|
return result;
|
|
208
243
|
} finally {
|
|
209
244
|
this.cleanupRun();
|
|
@@ -216,8 +251,10 @@ var init_base_agent = __esm({
|
|
|
216
251
|
this.state = "streaming";
|
|
217
252
|
try {
|
|
218
253
|
const messages = [{ role: "user", content: prompt }];
|
|
219
|
-
|
|
220
|
-
|
|
254
|
+
yield* this.streamWithRetry(
|
|
255
|
+
() => this.applyStreamPipeline(this.executeStream(messages, options, ac.signal), options, ac),
|
|
256
|
+
options
|
|
257
|
+
);
|
|
221
258
|
} finally {
|
|
222
259
|
this.cleanupRun();
|
|
223
260
|
}
|
|
@@ -228,12 +265,37 @@ var init_base_agent = __esm({
|
|
|
228
265
|
const ac = this.createAbortController(options?.signal);
|
|
229
266
|
this.state = "streaming";
|
|
230
267
|
try {
|
|
231
|
-
|
|
232
|
-
|
|
268
|
+
yield* this.streamWithRetry(
|
|
269
|
+
() => this.applyStreamPipeline(this.executeStream(messages, options, ac.signal), options, ac),
|
|
270
|
+
options
|
|
271
|
+
);
|
|
233
272
|
} finally {
|
|
234
273
|
this.cleanupRun();
|
|
235
274
|
}
|
|
236
275
|
}
|
|
276
|
+
/** Register a stream middleware. Applied in registration order after built-in transforms. */
|
|
277
|
+
addStreamMiddleware(middleware) {
|
|
278
|
+
this.guardDisposed();
|
|
279
|
+
this._streamMiddleware.push(middleware);
|
|
280
|
+
}
|
|
281
|
+
/** Apply built-in transforms (enrich→timeout→heartbeat) then custom middleware */
|
|
282
|
+
async *applyStreamPipeline(source, options, ac) {
|
|
283
|
+
let stream = this.enrichStream(source, options);
|
|
284
|
+
stream = this.activityTimeoutStream(stream, options?.activityTimeoutMs, ac);
|
|
285
|
+
stream = this.heartbeatStream(stream);
|
|
286
|
+
if (this._streamMiddleware.length > 0) {
|
|
287
|
+
const ctx = {
|
|
288
|
+
model: options.model,
|
|
289
|
+
backend: this.backendName,
|
|
290
|
+
abortController: ac,
|
|
291
|
+
config: Object.freeze({ ...this.config })
|
|
292
|
+
};
|
|
293
|
+
for (const mw of this._streamMiddleware) {
|
|
294
|
+
stream = mw(stream, ctx);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
yield* stream;
|
|
298
|
+
}
|
|
237
299
|
abort() {
|
|
238
300
|
if (this.abortController) {
|
|
239
301
|
this.abortController.abort();
|
|
@@ -256,26 +318,109 @@ var init_base_agent = __esm({
|
|
|
256
318
|
this.abort();
|
|
257
319
|
this.state = "disposed";
|
|
258
320
|
}
|
|
321
|
+
// ─── Retry Logic ─────────────────────────────────────────────
|
|
322
|
+
/** Check if an error should be retried given the retry configuration. */
|
|
323
|
+
isRetryableError(error, retry) {
|
|
324
|
+
if (error instanceof AbortError || error instanceof ReentrancyError || error instanceof DisposedError) {
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
if (AgentSDKError.is(error)) {
|
|
328
|
+
if (retry.retryableErrors && retry.retryableErrors.length > 0 && error.code) {
|
|
329
|
+
return retry.retryableErrors.includes(error.code);
|
|
330
|
+
}
|
|
331
|
+
if (error.retryable) return true;
|
|
332
|
+
if (error.code) return isRecoverableErrorCode(error.code);
|
|
333
|
+
}
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
/** Execute a function with retry logic per RetryConfig. */
|
|
337
|
+
async withRetry(fn, options) {
|
|
338
|
+
const retry = options?.retry;
|
|
339
|
+
if (!retry || !retry.maxRetries || retry.maxRetries <= 0) {
|
|
340
|
+
return fn();
|
|
341
|
+
}
|
|
342
|
+
const maxRetries = retry.maxRetries;
|
|
343
|
+
const initialDelay = retry.initialDelayMs ?? 1e3;
|
|
344
|
+
const multiplier = retry.backoffMultiplier ?? 2;
|
|
345
|
+
let lastError;
|
|
346
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
347
|
+
try {
|
|
348
|
+
return await fn();
|
|
349
|
+
} catch (err) {
|
|
350
|
+
lastError = err;
|
|
351
|
+
if (attempt >= maxRetries || !this.isRetryableError(err, retry)) {
|
|
352
|
+
throw err;
|
|
353
|
+
}
|
|
354
|
+
const delay = initialDelay * Math.pow(multiplier, attempt);
|
|
355
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
356
|
+
if (options?.signal?.aborted || this.abortController?.signal.aborted) {
|
|
357
|
+
throw err;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
throw lastError;
|
|
362
|
+
}
|
|
363
|
+
/** Execute a stream factory with pre-stream retry: retries until first event, then committed. */
|
|
364
|
+
async *streamWithRetry(factory, options) {
|
|
365
|
+
const retry = options?.retry;
|
|
366
|
+
if (!retry || !retry.maxRetries || retry.maxRetries <= 0) {
|
|
367
|
+
yield* factory();
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const maxRetries = retry.maxRetries;
|
|
371
|
+
const initialDelay = retry.initialDelayMs ?? 1e3;
|
|
372
|
+
const multiplier = retry.backoffMultiplier ?? 2;
|
|
373
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
374
|
+
try {
|
|
375
|
+
const stream = factory();
|
|
376
|
+
const iterator = stream[Symbol.asyncIterator]();
|
|
377
|
+
const first = await iterator.next();
|
|
378
|
+
if (first.done) return;
|
|
379
|
+
yield first.value;
|
|
380
|
+
while (true) {
|
|
381
|
+
const next = await iterator.next();
|
|
382
|
+
if (next.done) break;
|
|
383
|
+
yield next.value;
|
|
384
|
+
}
|
|
385
|
+
return;
|
|
386
|
+
} catch (err) {
|
|
387
|
+
if (attempt >= maxRetries || !this.isRetryableError(err, retry)) {
|
|
388
|
+
throw err;
|
|
389
|
+
}
|
|
390
|
+
const delay = initialDelay * Math.pow(multiplier, attempt);
|
|
391
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
392
|
+
if (options?.signal?.aborted || this.abortController?.signal.aborted) {
|
|
393
|
+
throw err;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
// ─── CallOptions Resolution ──────────────────────────────────
|
|
399
|
+
/** Resolve tools to use for this call (per-call override > config default) */
|
|
400
|
+
resolveTools(options) {
|
|
401
|
+
return options?.tools ?? this.config.tools ?? [];
|
|
402
|
+
}
|
|
259
403
|
// ─── Usage Enrichment ───────────────────────────────────────────
|
|
260
404
|
/** Enrich result usage with model/backend and fire onUsage callback */
|
|
261
|
-
enrichAndNotifyUsage(result) {
|
|
405
|
+
enrichAndNotifyUsage(result, options) {
|
|
262
406
|
if (result.usage) {
|
|
263
407
|
result.usage = {
|
|
264
408
|
...result.usage,
|
|
265
|
-
model:
|
|
409
|
+
model: options.model,
|
|
266
410
|
backend: this.backendName
|
|
267
411
|
};
|
|
268
412
|
this.callOnUsage(result.usage);
|
|
269
413
|
}
|
|
270
414
|
}
|
|
271
415
|
/** Wrap a stream to enrich usage_update events and fire onUsage callback */
|
|
272
|
-
async *enrichStream(source) {
|
|
416
|
+
async *enrichStream(source, options) {
|
|
417
|
+
const model = options.model;
|
|
273
418
|
for await (const event of source) {
|
|
274
419
|
if (event.type === "usage_update") {
|
|
275
420
|
const usage = {
|
|
276
421
|
promptTokens: event.promptTokens,
|
|
277
422
|
completionTokens: event.completionTokens,
|
|
278
|
-
model
|
|
423
|
+
model,
|
|
279
424
|
backend: this.backendName
|
|
280
425
|
};
|
|
281
426
|
this.callOnUsage(usage);
|
|
@@ -311,9 +456,9 @@ var init_base_agent = __esm({
|
|
|
311
456
|
let heartbeatResolve = null;
|
|
312
457
|
const timer = setInterval(() => {
|
|
313
458
|
if (heartbeatResolve) {
|
|
314
|
-
const
|
|
459
|
+
const resolve = heartbeatResolve;
|
|
315
460
|
heartbeatResolve = null;
|
|
316
|
-
|
|
461
|
+
resolve();
|
|
317
462
|
}
|
|
318
463
|
}, interval);
|
|
319
464
|
try {
|
|
@@ -321,8 +466,8 @@ var init_base_agent = __esm({
|
|
|
321
466
|
if (!pendingEvent) {
|
|
322
467
|
pendingEvent = iterator.next();
|
|
323
468
|
}
|
|
324
|
-
const heartbeatPromise = new Promise((
|
|
325
|
-
heartbeatResolve =
|
|
469
|
+
const heartbeatPromise = new Promise((resolve) => {
|
|
470
|
+
heartbeatResolve = resolve;
|
|
326
471
|
});
|
|
327
472
|
const eventDone = pendingEvent.then(
|
|
328
473
|
(r) => ({ kind: "event", result: r })
|
|
@@ -345,6 +490,35 @@ var init_base_agent = __esm({
|
|
|
345
490
|
heartbeatResolve = null;
|
|
346
491
|
}
|
|
347
492
|
}
|
|
493
|
+
// ─── Activity Timeout ────────────────────────────────────────
|
|
494
|
+
/** Wrap a stream to abort on inactivity. Resets timer on every event.
|
|
495
|
+
* When timeoutMs is not set, passes through directly. */
|
|
496
|
+
async *activityTimeoutStream(source, timeoutMs, ac) {
|
|
497
|
+
if (!timeoutMs || timeoutMs <= 0) {
|
|
498
|
+
yield* source;
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
502
|
+
let timerId;
|
|
503
|
+
try {
|
|
504
|
+
while (true) {
|
|
505
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
506
|
+
timerId = setTimeout(() => reject(new ActivityTimeoutError(timeoutMs)), timeoutMs);
|
|
507
|
+
});
|
|
508
|
+
const result = await Promise.race([iterator.next(), timeoutPromise]);
|
|
509
|
+
clearTimeout(timerId);
|
|
510
|
+
if (result.done) break;
|
|
511
|
+
yield result.value;
|
|
512
|
+
}
|
|
513
|
+
} catch (err) {
|
|
514
|
+
if (err instanceof ActivityTimeoutError) {
|
|
515
|
+
ac.abort(err);
|
|
516
|
+
}
|
|
517
|
+
throw err;
|
|
518
|
+
} finally {
|
|
519
|
+
clearTimeout(timerId);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
348
522
|
// ─── Guards ───────────────────────────────────────────────────
|
|
349
523
|
guardReentrancy() {
|
|
350
524
|
if (this.state === "running" || this.state === "streaming") {
|
|
@@ -449,6 +623,66 @@ var init_schema = __esm({
|
|
|
449
623
|
}
|
|
450
624
|
});
|
|
451
625
|
|
|
626
|
+
// src/backends/shared.ts
|
|
627
|
+
function extractLastUserPrompt(messages) {
|
|
628
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
629
|
+
const msg = messages[i];
|
|
630
|
+
if (msg.role === "user") {
|
|
631
|
+
return getTextContent(msg.content);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
return "";
|
|
635
|
+
}
|
|
636
|
+
function serializeToolCall(tc) {
|
|
637
|
+
const args = typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args);
|
|
638
|
+
return ` Tool call: ${tc.name}(${args})`;
|
|
639
|
+
}
|
|
640
|
+
function serializeToolResult(tr) {
|
|
641
|
+
const result = typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result);
|
|
642
|
+
const prefix = tr.isError ? "[ERROR] " : "";
|
|
643
|
+
return ` ${tr.name} \u2192 ${prefix}${result}`;
|
|
644
|
+
}
|
|
645
|
+
function buildContextualPrompt(messages) {
|
|
646
|
+
if (messages.length <= 1) {
|
|
647
|
+
return extractLastUserPrompt(messages);
|
|
648
|
+
}
|
|
649
|
+
const history = messages.slice(0, -1).map((msg) => {
|
|
650
|
+
if (msg.role === "user") {
|
|
651
|
+
return `User: ${msg.content ? getTextContent(msg.content) : ""}`;
|
|
652
|
+
}
|
|
653
|
+
if (msg.role === "tool" && msg.toolResults) {
|
|
654
|
+
const results = msg.toolResults.map(serializeToolResult).join("\n");
|
|
655
|
+
return `Tool results:
|
|
656
|
+
${results}`;
|
|
657
|
+
}
|
|
658
|
+
if (msg.role === "assistant") {
|
|
659
|
+
const parts = [];
|
|
660
|
+
const thinking = msg.thinking;
|
|
661
|
+
if (thinking) {
|
|
662
|
+
parts.push(`[reasoning: ${thinking}]`);
|
|
663
|
+
}
|
|
664
|
+
const text2 = msg.content ? getTextContent(msg.content) : "";
|
|
665
|
+
if (text2) parts.push(text2);
|
|
666
|
+
if (msg.toolCalls && msg.toolCalls.length > 0) {
|
|
667
|
+
parts.push(msg.toolCalls.map(serializeToolCall).join("\n"));
|
|
668
|
+
}
|
|
669
|
+
return `Assistant: ${parts.join("\n")}`;
|
|
670
|
+
}
|
|
671
|
+
const text = msg.content ? getTextContent(msg.content) : "";
|
|
672
|
+
return `${msg.role}: ${text}`;
|
|
673
|
+
}).join("\n");
|
|
674
|
+
const lastPrompt = extractLastUserPrompt(messages);
|
|
675
|
+
return `Conversation history:
|
|
676
|
+
${history}
|
|
677
|
+
|
|
678
|
+
User: ${lastPrompt}`;
|
|
679
|
+
}
|
|
680
|
+
var init_shared = __esm({
|
|
681
|
+
"src/backends/shared.ts"() {
|
|
682
|
+
init_types2();
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
|
|
452
686
|
// src/backends/copilot.ts
|
|
453
687
|
var copilot_exports = {};
|
|
454
688
|
__export(copilot_exports, {
|
|
@@ -457,10 +691,9 @@ __export(copilot_exports, {
|
|
|
457
691
|
createCopilotService: () => createCopilotService
|
|
458
692
|
});
|
|
459
693
|
async function loadSDK() {
|
|
460
|
-
if (
|
|
694
|
+
if (_sdkMock) return _sdkMock;
|
|
461
695
|
try {
|
|
462
|
-
|
|
463
|
-
return sdkModule;
|
|
696
|
+
return await import('@github/copilot-sdk');
|
|
464
697
|
} catch {
|
|
465
698
|
throw new SubprocessError(
|
|
466
699
|
"@github/copilot-sdk is not installed. Install it: npm install @github/copilot-sdk"
|
|
@@ -468,10 +701,10 @@ async function loadSDK() {
|
|
|
468
701
|
}
|
|
469
702
|
}
|
|
470
703
|
function _injectSDK(mock) {
|
|
471
|
-
|
|
704
|
+
_sdkMock = mock;
|
|
472
705
|
}
|
|
473
706
|
function _resetSDK() {
|
|
474
|
-
|
|
707
|
+
_sdkMock = null;
|
|
475
708
|
}
|
|
476
709
|
function mapToolsToSDK(tools) {
|
|
477
710
|
return tools.map((tool) => ({
|
|
@@ -516,6 +749,7 @@ function buildPermissionHandler(config) {
|
|
|
516
749
|
const unifiedRequest = {
|
|
517
750
|
toolName,
|
|
518
751
|
toolArgs: { ...request },
|
|
752
|
+
toolCallId: request.toolCallId,
|
|
519
753
|
rawSDKRequest: request
|
|
520
754
|
};
|
|
521
755
|
const ac = new AbortController();
|
|
@@ -620,15 +854,21 @@ function mapSessionEvent(event, tracker, thinkingTracker) {
|
|
|
620
854
|
};
|
|
621
855
|
case "session.error":
|
|
622
856
|
console.error("[copilot] mapSessionEvent error:", JSON.stringify(data));
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
857
|
+
{
|
|
858
|
+
const errorMsg = String(data.message ?? "Unknown error");
|
|
859
|
+
const code = classifyAgentError(errorMsg);
|
|
860
|
+
return {
|
|
861
|
+
type: "error",
|
|
862
|
+
error: errorMsg,
|
|
863
|
+
recoverable: isRecoverableErrorCode(code),
|
|
864
|
+
code
|
|
865
|
+
};
|
|
866
|
+
}
|
|
628
867
|
case "assistant.message": {
|
|
629
868
|
const doneEvent = {
|
|
630
869
|
type: "done",
|
|
631
|
-
finalOutput:
|
|
870
|
+
finalOutput: null,
|
|
871
|
+
streamed: true
|
|
632
872
|
};
|
|
633
873
|
if (thinkingTracker.endThinking()) {
|
|
634
874
|
return [{ type: "thinking_end" }, doneEvent];
|
|
@@ -639,66 +879,13 @@ function mapSessionEvent(event, tracker, thinkingTracker) {
|
|
|
639
879
|
return null;
|
|
640
880
|
}
|
|
641
881
|
}
|
|
642
|
-
function extractLastUserPrompt(messages) {
|
|
643
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
644
|
-
const msg = messages[i];
|
|
645
|
-
if (msg.role === "user") {
|
|
646
|
-
return getTextContent(msg.content);
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
return "";
|
|
650
|
-
}
|
|
651
|
-
function serializeToolCall(tc) {
|
|
652
|
-
const args = typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args);
|
|
653
|
-
return ` Tool call: ${tc.name}(${args})`;
|
|
654
|
-
}
|
|
655
|
-
function serializeToolResult(tr) {
|
|
656
|
-
const result = typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result);
|
|
657
|
-
const prefix = tr.isError ? "[ERROR] " : "";
|
|
658
|
-
return ` ${tr.name} \u2192 ${prefix}${result}`;
|
|
659
|
-
}
|
|
660
|
-
function buildContextualPrompt(messages) {
|
|
661
|
-
if (messages.length <= 1) {
|
|
662
|
-
return extractLastUserPrompt(messages);
|
|
663
|
-
}
|
|
664
|
-
const history = messages.slice(0, -1).map((msg) => {
|
|
665
|
-
if (msg.role === "user") {
|
|
666
|
-
return `User: ${msg.content ? getTextContent(msg.content) : ""}`;
|
|
667
|
-
}
|
|
668
|
-
if (msg.role === "tool" && msg.toolResults) {
|
|
669
|
-
const results = msg.toolResults.map(serializeToolResult).join("\n");
|
|
670
|
-
return `Tool results:
|
|
671
|
-
${results}`;
|
|
672
|
-
}
|
|
673
|
-
if (msg.role === "assistant") {
|
|
674
|
-
const parts = [];
|
|
675
|
-
const thinking = msg.thinking;
|
|
676
|
-
if (thinking) {
|
|
677
|
-
parts.push(`[reasoning: ${thinking}]`);
|
|
678
|
-
}
|
|
679
|
-
const text2 = msg.content ? getTextContent(msg.content) : "";
|
|
680
|
-
if (text2) parts.push(text2);
|
|
681
|
-
if (msg.toolCalls && msg.toolCalls.length > 0) {
|
|
682
|
-
parts.push(msg.toolCalls.map(serializeToolCall).join("\n"));
|
|
683
|
-
}
|
|
684
|
-
return `Assistant: ${parts.join("\n")}`;
|
|
685
|
-
}
|
|
686
|
-
const text = msg.content ? getTextContent(msg.content) : "";
|
|
687
|
-
return `${msg.role}: ${text}`;
|
|
688
|
-
}).join("\n");
|
|
689
|
-
const lastPrompt = extractLastUserPrompt(messages);
|
|
690
|
-
return `Conversation history:
|
|
691
|
-
${history}
|
|
692
|
-
|
|
693
|
-
User: ${lastPrompt}`;
|
|
694
|
-
}
|
|
695
882
|
function withTimeout(promise, ms, message) {
|
|
696
|
-
return new Promise((
|
|
883
|
+
return new Promise((resolve, reject) => {
|
|
697
884
|
const timer = setTimeout(() => reject(new SubprocessError(message)), ms);
|
|
698
885
|
promise.then(
|
|
699
886
|
(val) => {
|
|
700
887
|
clearTimeout(timer);
|
|
701
|
-
|
|
888
|
+
resolve(val);
|
|
702
889
|
},
|
|
703
890
|
(err) => {
|
|
704
891
|
clearTimeout(timer);
|
|
@@ -710,14 +897,15 @@ function withTimeout(promise, ms, message) {
|
|
|
710
897
|
function createCopilotService(options) {
|
|
711
898
|
return new CopilotAgentService(options);
|
|
712
899
|
}
|
|
713
|
-
var
|
|
900
|
+
var _sdkMock, ToolCallTracker, ThinkingTracker, CopilotAgent, CopilotAgentService;
|
|
714
901
|
var init_copilot = __esm({
|
|
715
902
|
"src/backends/copilot.ts"() {
|
|
716
|
-
|
|
903
|
+
init_types2();
|
|
717
904
|
init_base_agent();
|
|
718
|
-
|
|
905
|
+
init_errors2();
|
|
719
906
|
init_schema();
|
|
720
|
-
|
|
907
|
+
init_shared();
|
|
908
|
+
_sdkMock = null;
|
|
721
909
|
ToolCallTracker = class {
|
|
722
910
|
map = /* @__PURE__ */ new Map();
|
|
723
911
|
trackStart(toolCallId, toolName, args) {
|
|
@@ -765,6 +953,7 @@ var init_copilot = __esm({
|
|
|
765
953
|
isPersistent;
|
|
766
954
|
persistentSession = null;
|
|
767
955
|
_sessionId;
|
|
956
|
+
_persistentModel;
|
|
768
957
|
activeSession = null;
|
|
769
958
|
_resumeSessionId;
|
|
770
959
|
_toolsReady = null;
|
|
@@ -815,47 +1004,63 @@ var init_copilot = __esm({
|
|
|
815
1004
|
});
|
|
816
1005
|
this.persistentSession = null;
|
|
817
1006
|
this._sessionId = void 0;
|
|
1007
|
+
this._persistentModel = void 0;
|
|
818
1008
|
}
|
|
819
1009
|
}
|
|
820
|
-
async getOrCreateSession(streaming) {
|
|
1010
|
+
async getOrCreateSession(streaming, options) {
|
|
821
1011
|
if (this.isPersistent && this.persistentSession) {
|
|
822
|
-
|
|
1012
|
+
if (options.model !== this._persistentModel) {
|
|
1013
|
+
this.persistentSession.destroy().catch(() => {
|
|
1014
|
+
});
|
|
1015
|
+
this.persistentSession = null;
|
|
1016
|
+
this._sessionId = void 0;
|
|
1017
|
+
} else {
|
|
1018
|
+
return { session: this.persistentSession, isNew: false };
|
|
1019
|
+
}
|
|
823
1020
|
}
|
|
824
1021
|
if (this._toolsReady) {
|
|
825
1022
|
await this._toolsReady;
|
|
826
1023
|
this._toolsReady = null;
|
|
827
1024
|
}
|
|
1025
|
+
const sessionConfig = { ...this.sessionConfig };
|
|
1026
|
+
sessionConfig.model = options.model;
|
|
1027
|
+
const resolvedTools = this.resolveTools(options);
|
|
1028
|
+
if (options?.tools) {
|
|
1029
|
+
sessionConfig.tools = mapToolsToSDK(resolvedTools);
|
|
1030
|
+
}
|
|
828
1031
|
const client = await this.getClient();
|
|
829
1032
|
if (this._resumeSessionId) {
|
|
830
1033
|
const storedId = this._resumeSessionId;
|
|
831
1034
|
this._resumeSessionId = void 0;
|
|
832
1035
|
try {
|
|
833
1036
|
const session2 = await client.resumeSession(storedId, {
|
|
834
|
-
...
|
|
1037
|
+
...sessionConfig,
|
|
835
1038
|
streaming: this.isPersistent ? true : streaming
|
|
836
1039
|
});
|
|
837
1040
|
if (this.isPersistent) {
|
|
838
1041
|
this.persistentSession = session2;
|
|
839
1042
|
this._sessionId = session2.sessionId;
|
|
1043
|
+
this._persistentModel = options.model;
|
|
840
1044
|
}
|
|
841
1045
|
return { session: session2, isNew: false };
|
|
842
1046
|
} catch {
|
|
843
1047
|
}
|
|
844
1048
|
}
|
|
845
1049
|
const session = await client.createSession({
|
|
846
|
-
...
|
|
1050
|
+
...sessionConfig,
|
|
847
1051
|
streaming: this.isPersistent ? true : streaming
|
|
848
1052
|
});
|
|
849
1053
|
if (this.isPersistent) {
|
|
850
1054
|
this.persistentSession = session;
|
|
851
1055
|
this._sessionId = session.sessionId;
|
|
1056
|
+
this._persistentModel = options.model;
|
|
852
1057
|
}
|
|
853
1058
|
return { session, isNew: true };
|
|
854
1059
|
}
|
|
855
1060
|
// ─── executeRun ─────────────────────────────────────────────────
|
|
856
|
-
async executeRun(messages,
|
|
1061
|
+
async executeRun(messages, options, signal) {
|
|
857
1062
|
this.checkAbort(signal);
|
|
858
|
-
const { session, isNew: isNewSession } = await this.getOrCreateSession(false);
|
|
1063
|
+
const { session, isNew: isNewSession } = await this.getOrCreateSession(false, options);
|
|
859
1064
|
this.activeSession = session;
|
|
860
1065
|
const prompt = this.isPersistent && !isNewSession ? extractLastUserPrompt(messages) : buildContextualPrompt(messages);
|
|
861
1066
|
const tracker = new ToolCallTracker();
|
|
@@ -952,9 +1157,9 @@ You MUST respond with ONLY valid JSON matching this schema:
|
|
|
952
1157
|
};
|
|
953
1158
|
}
|
|
954
1159
|
// ─── executeStream ──────────────────────────────────────────────
|
|
955
|
-
async *executeStream(messages,
|
|
1160
|
+
async *executeStream(messages, options, signal) {
|
|
956
1161
|
this.checkAbort(signal);
|
|
957
|
-
const { session, isNew: isNewSession } = await this.getOrCreateSession(true);
|
|
1162
|
+
const { session, isNew: isNewSession } = await this.getOrCreateSession(true, options);
|
|
958
1163
|
this.activeSession = session;
|
|
959
1164
|
if (isNewSession) {
|
|
960
1165
|
yield this.emitSessionInfo(session.sessionId);
|
|
@@ -971,8 +1176,8 @@ You MUST respond with ONLY valid JSON matching this schema:
|
|
|
971
1176
|
notify = null;
|
|
972
1177
|
}
|
|
973
1178
|
};
|
|
974
|
-
const waitForItem = () => new Promise((
|
|
975
|
-
notify =
|
|
1179
|
+
const waitForItem = () => new Promise((resolve) => {
|
|
1180
|
+
notify = resolve;
|
|
976
1181
|
});
|
|
977
1182
|
const unsubscribe = session.on((event) => {
|
|
978
1183
|
const mapped = mapSessionEvent(event, tracker, thinkingTracker);
|
|
@@ -1100,7 +1305,10 @@ You MUST respond with ONLY valid JSON matching this schema:
|
|
|
1100
1305
|
return models.map((m) => ({
|
|
1101
1306
|
id: m.id,
|
|
1102
1307
|
name: m.name,
|
|
1103
|
-
provider: "copilot"
|
|
1308
|
+
provider: "copilot",
|
|
1309
|
+
...m.capabilities?.limits?.max_context_window_tokens != null && {
|
|
1310
|
+
contextWindow: m.capabilities.limits.max_context_window_tokens
|
|
1311
|
+
}
|
|
1104
1312
|
}));
|
|
1105
1313
|
}
|
|
1106
1314
|
async validate() {
|
|
@@ -1153,10 +1361,9 @@ function stripMcpPrefix(name) {
|
|
|
1153
1361
|
return name.startsWith(MCP_TOOL_PREFIX) ? name.slice(MCP_TOOL_PREFIX.length) : name;
|
|
1154
1362
|
}
|
|
1155
1363
|
async function loadSDK2() {
|
|
1156
|
-
if (
|
|
1364
|
+
if (_sdkMock2) return _sdkMock2;
|
|
1157
1365
|
try {
|
|
1158
|
-
|
|
1159
|
-
return sdkModule2;
|
|
1366
|
+
return await import('@anthropic-ai/claude-agent-sdk');
|
|
1160
1367
|
} catch {
|
|
1161
1368
|
throw new SubprocessError(
|
|
1162
1369
|
"@anthropic-ai/claude-agent-sdk is not installed. Install it: npm install @anthropic-ai/claude-agent-sdk"
|
|
@@ -1164,13 +1371,32 @@ async function loadSDK2() {
|
|
|
1164
1371
|
}
|
|
1165
1372
|
}
|
|
1166
1373
|
function _injectSDK2(mock) {
|
|
1167
|
-
|
|
1374
|
+
_sdkMock2 = mock;
|
|
1168
1375
|
}
|
|
1169
1376
|
function _resetSDK2() {
|
|
1170
|
-
|
|
1377
|
+
_sdkMock2 = null;
|
|
1378
|
+
}
|
|
1379
|
+
function normalizeAskUserInput(args) {
|
|
1380
|
+
if (typeof args.question === "string") {
|
|
1381
|
+
return {
|
|
1382
|
+
question: args.question,
|
|
1383
|
+
choices: Array.isArray(args.choices) ? args.choices : void 0,
|
|
1384
|
+
allowFreeform: args.allowFreeform !== false
|
|
1385
|
+
};
|
|
1386
|
+
}
|
|
1387
|
+
const questions = args.questions;
|
|
1388
|
+
if (questions && questions.length > 0) {
|
|
1389
|
+
const first = questions[0];
|
|
1390
|
+
return {
|
|
1391
|
+
question: first.question,
|
|
1392
|
+
choices: first.options?.map((o) => o.label),
|
|
1393
|
+
allowFreeform: true
|
|
1394
|
+
};
|
|
1395
|
+
}
|
|
1396
|
+
return { question: JSON.stringify(args), allowFreeform: true };
|
|
1171
1397
|
}
|
|
1172
|
-
function buildMcpServer(sdk, tools, toolResultCapture) {
|
|
1173
|
-
if (tools.length === 0) return void 0;
|
|
1398
|
+
function buildMcpServer(sdk, tools, toolResultCapture, onAskUser) {
|
|
1399
|
+
if (tools.length === 0 && !onAskUser) return void 0;
|
|
1174
1400
|
const mcpTools = tools.map((tool) => {
|
|
1175
1401
|
const zodSchema = tool.parameters;
|
|
1176
1402
|
const inputSchema = zodSchema.shape ?? zodToJsonSchema(tool.parameters);
|
|
@@ -1194,6 +1420,39 @@ function buildMcpServer(sdk, tools, toolResultCapture) {
|
|
|
1194
1420
|
}
|
|
1195
1421
|
);
|
|
1196
1422
|
});
|
|
1423
|
+
if (onAskUser) {
|
|
1424
|
+
const askUserTool = sdk.tool(
|
|
1425
|
+
"ask_user",
|
|
1426
|
+
"Ask the user a question and wait for their response",
|
|
1427
|
+
{
|
|
1428
|
+
question: { type: "string", description: "The question to ask the user" },
|
|
1429
|
+
choices: {
|
|
1430
|
+
type: "array",
|
|
1431
|
+
items: { type: "string" },
|
|
1432
|
+
description: "Optional list of choices for multiple choice"
|
|
1433
|
+
},
|
|
1434
|
+
questions: {
|
|
1435
|
+
type: "array",
|
|
1436
|
+
items: {
|
|
1437
|
+
type: "object",
|
|
1438
|
+
properties: {
|
|
1439
|
+
question: { type: "string" },
|
|
1440
|
+
options: { type: "array", items: { type: "object", properties: { label: { type: "string" } } } }
|
|
1441
|
+
}
|
|
1442
|
+
},
|
|
1443
|
+
description: "Alternative nested question format"
|
|
1444
|
+
}
|
|
1445
|
+
},
|
|
1446
|
+
async (args) => {
|
|
1447
|
+
const normalized = normalizeAskUserInput(args);
|
|
1448
|
+
const response = await onAskUser(normalized, AbortSignal.timeout(3e5));
|
|
1449
|
+
return {
|
|
1450
|
+
content: [{ type: "text", text: response.answer }]
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
);
|
|
1454
|
+
mcpTools.push(askUserTool);
|
|
1455
|
+
}
|
|
1197
1456
|
return sdk.createSdkMcpServer({
|
|
1198
1457
|
name: MCP_SERVER_NAME,
|
|
1199
1458
|
version: "1.0.0",
|
|
@@ -1243,6 +1502,7 @@ function buildCanUseTool(config) {
|
|
|
1243
1502
|
const unifiedRequest = {
|
|
1244
1503
|
toolName,
|
|
1245
1504
|
toolArgs: input,
|
|
1505
|
+
toolCallId: options.toolUseID,
|
|
1246
1506
|
suggestedScope: extractSuggestedScope(options.suggestions),
|
|
1247
1507
|
rawSDKRequest: { toolName, input, ...options }
|
|
1248
1508
|
};
|
|
@@ -1295,6 +1555,7 @@ function mapSDKMessage(msg, thinkingBlockIndices, toolCallTracker) {
|
|
|
1295
1555
|
if (block.type === "tool_use") {
|
|
1296
1556
|
const toolCallId = String(block.id ?? "");
|
|
1297
1557
|
const toolName = stripMcpPrefix(block.name ?? "unknown");
|
|
1558
|
+
if (CLAUDE_INTERNAL_TOOL_NAMES.has(toolName)) continue;
|
|
1298
1559
|
if (toolCallTracker) {
|
|
1299
1560
|
toolCallTracker.trackStart(toolCallId, toolName);
|
|
1300
1561
|
}
|
|
@@ -1318,6 +1579,7 @@ function mapSDKMessage(msg, thinkingBlockIndices, toolCallTracker) {
|
|
|
1318
1579
|
case "tool_use_summary": {
|
|
1319
1580
|
const summary = msg.summary;
|
|
1320
1581
|
const toolName = stripMcpPrefix(msg.tool_name ?? "unknown");
|
|
1582
|
+
if (CLAUDE_INTERNAL_TOOL_NAMES.has(toolName)) return null;
|
|
1321
1583
|
const precedingIds = msg.preceding_tool_use_ids;
|
|
1322
1584
|
let toolCallId = "";
|
|
1323
1585
|
if (precedingIds && precedingIds.length > 0) {
|
|
@@ -1371,10 +1633,13 @@ function mapSDKMessage(msg, thinkingBlockIndices, toolCallTracker) {
|
|
|
1371
1633
|
}
|
|
1372
1634
|
if (msg.is_error) {
|
|
1373
1635
|
const r = msg;
|
|
1636
|
+
const errorMsg = r.errors?.join("; ") ?? "Unknown error";
|
|
1637
|
+
const code = classifyAgentError(errorMsg);
|
|
1374
1638
|
return {
|
|
1375
1639
|
type: "error",
|
|
1376
|
-
error:
|
|
1377
|
-
recoverable:
|
|
1640
|
+
error: errorMsg,
|
|
1641
|
+
recoverable: isRecoverableErrorCode(code),
|
|
1642
|
+
code
|
|
1378
1643
|
};
|
|
1379
1644
|
}
|
|
1380
1645
|
return null;
|
|
@@ -1383,72 +1648,21 @@ function mapSDKMessage(msg, thinkingBlockIndices, toolCallTracker) {
|
|
|
1383
1648
|
return null;
|
|
1384
1649
|
}
|
|
1385
1650
|
}
|
|
1386
|
-
function extractLastUserPrompt2(messages) {
|
|
1387
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1388
|
-
const msg = messages[i];
|
|
1389
|
-
if (msg.role === "user") {
|
|
1390
|
-
return getTextContent(msg.content);
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1393
|
-
return "";
|
|
1394
|
-
}
|
|
1395
|
-
function serializeToolCall2(tc) {
|
|
1396
|
-
const args = typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args);
|
|
1397
|
-
return ` Tool call: ${tc.name}(${args})`;
|
|
1398
|
-
}
|
|
1399
|
-
function serializeToolResult2(tr) {
|
|
1400
|
-
const result = typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result);
|
|
1401
|
-
const prefix = tr.isError ? "[ERROR] " : "";
|
|
1402
|
-
return ` ${tr.name} \u2192 ${prefix}${result}`;
|
|
1403
|
-
}
|
|
1404
|
-
function buildContextualPrompt2(messages) {
|
|
1405
|
-
if (messages.length <= 1) {
|
|
1406
|
-
return extractLastUserPrompt2(messages);
|
|
1407
|
-
}
|
|
1408
|
-
const history = messages.slice(0, -1).map((msg) => {
|
|
1409
|
-
if (msg.role === "user") {
|
|
1410
|
-
return `User: ${msg.content ? getTextContent(msg.content) : ""}`;
|
|
1411
|
-
}
|
|
1412
|
-
if (msg.role === "tool" && msg.toolResults) {
|
|
1413
|
-
const results = msg.toolResults.map(serializeToolResult2).join("\n");
|
|
1414
|
-
return `Tool results:
|
|
1415
|
-
${results}`;
|
|
1416
|
-
}
|
|
1417
|
-
if (msg.role === "assistant") {
|
|
1418
|
-
const parts = [];
|
|
1419
|
-
const thinking = msg.thinking;
|
|
1420
|
-
if (thinking) {
|
|
1421
|
-
parts.push(`[reasoning: ${thinking}]`);
|
|
1422
|
-
}
|
|
1423
|
-
const text2 = msg.content ? getTextContent(msg.content) : "";
|
|
1424
|
-
if (text2) parts.push(text2);
|
|
1425
|
-
if (msg.toolCalls && msg.toolCalls.length > 0) {
|
|
1426
|
-
parts.push(msg.toolCalls.map(serializeToolCall2).join("\n"));
|
|
1427
|
-
}
|
|
1428
|
-
return `Assistant: ${parts.join("\n")}`;
|
|
1429
|
-
}
|
|
1430
|
-
const text = msg.content ? getTextContent(msg.content) : "";
|
|
1431
|
-
return `${msg.role}: ${text}`;
|
|
1432
|
-
}).join("\n");
|
|
1433
|
-
const lastPrompt = extractLastUserPrompt2(messages);
|
|
1434
|
-
return `Conversation history:
|
|
1435
|
-
${history}
|
|
1436
|
-
|
|
1437
|
-
User: ${lastPrompt}`;
|
|
1438
|
-
}
|
|
1439
1651
|
function createClaudeService(options) {
|
|
1440
1652
|
return new ClaudeAgentService(options);
|
|
1441
1653
|
}
|
|
1442
|
-
var MCP_SERVER_NAME, MCP_TOOL_PREFIX,
|
|
1654
|
+
var MCP_SERVER_NAME, MCP_TOOL_PREFIX, CLAUDE_INTERNAL_TOOL_NAMES, _sdkMock2, ANTHROPIC_MODELS_URL, ANTHROPIC_API_VERSION, ANTHROPIC_OAUTH_BETA, ClaudeToolCallTracker, ClaudeAgent, ClaudeAgentService;
|
|
1443
1655
|
var init_claude = __esm({
|
|
1444
1656
|
"src/backends/claude.ts"() {
|
|
1445
|
-
|
|
1657
|
+
init_types2();
|
|
1446
1658
|
init_base_agent();
|
|
1447
|
-
|
|
1659
|
+
init_errors2();
|
|
1448
1660
|
init_schema();
|
|
1661
|
+
init_shared();
|
|
1449
1662
|
MCP_SERVER_NAME = "agent-sdk-tools";
|
|
1450
1663
|
MCP_TOOL_PREFIX = `mcp__${MCP_SERVER_NAME}__`;
|
|
1451
|
-
|
|
1664
|
+
CLAUDE_INTERNAL_TOOL_NAMES = /* @__PURE__ */ new Set(["AskUserQuestion"]);
|
|
1665
|
+
_sdkMock2 = null;
|
|
1452
1666
|
ANTHROPIC_MODELS_URL = "https://api.anthropic.com/v1/models";
|
|
1453
1667
|
ANTHROPIC_API_VERSION = "2023-06-01";
|
|
1454
1668
|
ANTHROPIC_OAUTH_BETA = "oauth-2025-04-20";
|
|
@@ -1493,11 +1707,6 @@ var init_claude = __esm({
|
|
|
1493
1707
|
if (options.resumeSessionId) {
|
|
1494
1708
|
this._sessionId = options.resumeSessionId;
|
|
1495
1709
|
}
|
|
1496
|
-
if (config.supervisor?.onAskUser) {
|
|
1497
|
-
console.warn(
|
|
1498
|
-
"[agent-sdk/claude] supervisor.onAskUser is not supported by the Claude CLI backend. User interaction requests from the model will not be forwarded."
|
|
1499
|
-
);
|
|
1500
|
-
}
|
|
1501
1710
|
}
|
|
1502
1711
|
get sessionId() {
|
|
1503
1712
|
return this._sessionId;
|
|
@@ -1521,12 +1730,12 @@ var init_claude = __esm({
|
|
|
1521
1730
|
const transcriptPath = home ? `${home}/.claude/projects/.session/sessions/${sessionId}/conversation.jsonl` : void 0;
|
|
1522
1731
|
return { type: "session_info", sessionId, transcriptPath, backend: "claude" };
|
|
1523
1732
|
}
|
|
1524
|
-
buildQueryOptions(signal) {
|
|
1733
|
+
buildQueryOptions(signal, options) {
|
|
1525
1734
|
const ac = new AbortController();
|
|
1526
1735
|
signal.addEventListener("abort", () => ac.abort(), { once: true });
|
|
1527
1736
|
const opts = {
|
|
1528
1737
|
abortController: ac,
|
|
1529
|
-
model:
|
|
1738
|
+
model: options.model,
|
|
1530
1739
|
maxTurns: this.options.maxTurns,
|
|
1531
1740
|
cwd: this.options.workingDirectory,
|
|
1532
1741
|
pathToClaudeCodeExecutable: this.options.cliPath,
|
|
@@ -1556,25 +1765,85 @@ var init_claude = __esm({
|
|
|
1556
1765
|
return opts;
|
|
1557
1766
|
}
|
|
1558
1767
|
async buildMcpConfig(opts, toolResultCapture) {
|
|
1559
|
-
|
|
1768
|
+
const onAskUser = this.config.supervisor?.onAskUser;
|
|
1769
|
+
if (this.tools.length === 0 && !onAskUser) return opts;
|
|
1560
1770
|
const sdk = await loadSDK2();
|
|
1561
|
-
const mcpServer = buildMcpServer(sdk, this.tools, toolResultCapture);
|
|
1771
|
+
const mcpServer = buildMcpServer(sdk, this.tools, toolResultCapture, onAskUser);
|
|
1562
1772
|
if (mcpServer) {
|
|
1563
1773
|
opts.mcpServers = {
|
|
1564
1774
|
[MCP_SERVER_NAME]: mcpServer
|
|
1565
1775
|
};
|
|
1566
1776
|
const mcpToolNames = this.tools.map((t) => mcpToolName(t.name));
|
|
1777
|
+
if (onAskUser) {
|
|
1778
|
+
mcpToolNames.push(mcpToolName("ask_user"));
|
|
1779
|
+
}
|
|
1567
1780
|
opts.allowedTools = [...opts.allowedTools ?? [], ...mcpToolNames];
|
|
1568
1781
|
}
|
|
1782
|
+
if (onAskUser) {
|
|
1783
|
+
opts.disallowedTools = [...opts.disallowedTools ?? [], "AskUserQuestion"];
|
|
1784
|
+
}
|
|
1569
1785
|
return opts;
|
|
1570
1786
|
}
|
|
1787
|
+
// ─── Retry Helpers (shared across executeRun/RunStructured/Stream) ──
|
|
1788
|
+
/** Setup a retry query: clear session, rebuild with full history */
|
|
1789
|
+
async prepareRetryQuery(sdk, messages, signal, options, toolResultCapture, modifyOpts) {
|
|
1790
|
+
this.clearPersistentSession();
|
|
1791
|
+
const retryPrompt = buildContextualPrompt(messages);
|
|
1792
|
+
let retryOpts = this.buildQueryOptions(signal, options);
|
|
1793
|
+
toolResultCapture.clear();
|
|
1794
|
+
retryOpts = await this.buildMcpConfig(retryOpts, toolResultCapture);
|
|
1795
|
+
modifyOpts?.(retryOpts);
|
|
1796
|
+
const retryQ = sdk.query({ prompt: retryPrompt, options: retryOpts });
|
|
1797
|
+
this.activeQuery = retryQ;
|
|
1798
|
+
return retryQ;
|
|
1799
|
+
}
|
|
1800
|
+
/** Extract tool_use blocks from an assistant SDK message into toolCalls array */
|
|
1801
|
+
collectToolCallsFromMessage(msg, toolCalls, toolResultCapture) {
|
|
1802
|
+
if (msg.type !== "assistant") return;
|
|
1803
|
+
const betaMessage = msg.message;
|
|
1804
|
+
if (!betaMessage?.content) return;
|
|
1805
|
+
for (const block of betaMessage.content) {
|
|
1806
|
+
if (block.type === "tool_use") {
|
|
1807
|
+
const toolName = stripMcpPrefix(block.name ?? "unknown");
|
|
1808
|
+
if (CLAUDE_INTERNAL_TOOL_NAMES.has(toolName)) continue;
|
|
1809
|
+
toolCalls.push({
|
|
1810
|
+
toolName,
|
|
1811
|
+
args: block.input ?? {},
|
|
1812
|
+
result: toolResultCapture.get(toolName) ?? null,
|
|
1813
|
+
approved: true
|
|
1814
|
+
});
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
/** Back-fill tool results from capture map on summary/result messages */
|
|
1819
|
+
backfillToolResults(msg, toolCalls, toolResultCapture) {
|
|
1820
|
+
if (msg.type !== "tool_use_summary" && msg.type !== "result") return;
|
|
1821
|
+
for (const tc of toolCalls) {
|
|
1822
|
+
if (tc.result === null) {
|
|
1823
|
+
const captured = toolResultCapture.get(tc.toolName);
|
|
1824
|
+
if (captured !== void 0) tc.result = captured;
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
/** Wrap retry inner loop with shared error handling */
|
|
1829
|
+
async withRetryErrorHandling(signal, fn) {
|
|
1830
|
+
try {
|
|
1831
|
+
return await fn();
|
|
1832
|
+
} catch (retryError) {
|
|
1833
|
+
if (this.isPersistent) this.clearPersistentSession();
|
|
1834
|
+
if (signal.aborted) throw new AbortError();
|
|
1835
|
+
throw retryError;
|
|
1836
|
+
} finally {
|
|
1837
|
+
this.activeQuery = null;
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1571
1840
|
// ─── executeRun ─────────────────────────────────────────────────
|
|
1572
|
-
async executeRun(messages,
|
|
1841
|
+
async executeRun(messages, options, signal) {
|
|
1573
1842
|
this.checkAbort(signal);
|
|
1574
1843
|
const sdk = await loadSDK2();
|
|
1575
1844
|
const isResuming = this.isPersistent && this._sessionId !== void 0;
|
|
1576
|
-
const prompt = isResuming ?
|
|
1577
|
-
let opts = this.buildQueryOptions(signal);
|
|
1845
|
+
const prompt = isResuming ? extractLastUserPrompt(messages) : buildContextualPrompt(messages);
|
|
1846
|
+
let opts = this.buildQueryOptions(signal, options);
|
|
1578
1847
|
const toolResultCapture = /* @__PURE__ */ new Map();
|
|
1579
1848
|
opts = await this.buildMcpConfig(opts, toolResultCapture);
|
|
1580
1849
|
const q = sdk.query({ prompt, options: opts });
|
|
@@ -1584,30 +1853,8 @@ var init_claude = __esm({
|
|
|
1584
1853
|
let usage;
|
|
1585
1854
|
try {
|
|
1586
1855
|
for await (const msg of q) {
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
if (betaMessage?.content) {
|
|
1590
|
-
for (const block of betaMessage.content) {
|
|
1591
|
-
if (block.type === "tool_use") {
|
|
1592
|
-
const toolName = stripMcpPrefix(block.name ?? "unknown");
|
|
1593
|
-
toolCalls.push({
|
|
1594
|
-
toolName,
|
|
1595
|
-
args: block.input ?? {},
|
|
1596
|
-
result: toolResultCapture.get(toolName) ?? null,
|
|
1597
|
-
approved: true
|
|
1598
|
-
});
|
|
1599
|
-
}
|
|
1600
|
-
}
|
|
1601
|
-
}
|
|
1602
|
-
}
|
|
1603
|
-
if (msg.type === "tool_use_summary" || msg.type === "result") {
|
|
1604
|
-
for (const tc of toolCalls) {
|
|
1605
|
-
if (tc.result === null) {
|
|
1606
|
-
const captured = toolResultCapture.get(tc.toolName);
|
|
1607
|
-
if (captured !== void 0) tc.result = captured;
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1610
|
-
}
|
|
1856
|
+
this.collectToolCallsFromMessage(msg, toolCalls, toolResultCapture);
|
|
1857
|
+
this.backfillToolResults(msg, toolCalls, toolResultCapture);
|
|
1611
1858
|
if (msg.type === "result") {
|
|
1612
1859
|
if (msg.subtype === "success") {
|
|
1613
1860
|
const r = msg;
|
|
@@ -1627,41 +1874,13 @@ var init_claude = __esm({
|
|
|
1627
1874
|
} catch (e) {
|
|
1628
1875
|
if (signal.aborted) throw new AbortError();
|
|
1629
1876
|
if (isResuming && this.isPersistent) {
|
|
1630
|
-
this.
|
|
1631
|
-
const retryPrompt = buildContextualPrompt2(messages);
|
|
1632
|
-
let retryOpts = this.buildQueryOptions(signal);
|
|
1633
|
-
toolResultCapture.clear();
|
|
1634
|
-
retryOpts = await this.buildMcpConfig(retryOpts, toolResultCapture);
|
|
1635
|
-
const retryQ = sdk.query({ prompt: retryPrompt, options: retryOpts });
|
|
1636
|
-
this.activeQuery = retryQ;
|
|
1877
|
+
const retryQ = await this.prepareRetryQuery(sdk, messages, signal, options, toolResultCapture);
|
|
1637
1878
|
toolCalls.length = 0;
|
|
1638
1879
|
output = null;
|
|
1639
|
-
|
|
1880
|
+
return this.withRetryErrorHandling(signal, async () => {
|
|
1640
1881
|
for await (const msg of retryQ) {
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
if (betaMessage?.content) {
|
|
1644
|
-
for (const block of betaMessage.content) {
|
|
1645
|
-
if (block.type === "tool_use") {
|
|
1646
|
-
const toolName = stripMcpPrefix(block.name ?? "unknown");
|
|
1647
|
-
toolCalls.push({
|
|
1648
|
-
toolName,
|
|
1649
|
-
args: block.input ?? {},
|
|
1650
|
-
result: toolResultCapture.get(toolName) ?? null,
|
|
1651
|
-
approved: true
|
|
1652
|
-
});
|
|
1653
|
-
}
|
|
1654
|
-
}
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1657
|
-
if (msg.type === "tool_use_summary" || msg.type === "result") {
|
|
1658
|
-
for (const tc of toolCalls) {
|
|
1659
|
-
if (tc.result === null) {
|
|
1660
|
-
const captured = toolResultCapture.get(tc.toolName);
|
|
1661
|
-
if (captured !== void 0) tc.result = captured;
|
|
1662
|
-
}
|
|
1663
|
-
}
|
|
1664
|
-
}
|
|
1882
|
+
this.collectToolCallsFromMessage(msg, toolCalls, toolResultCapture);
|
|
1883
|
+
this.backfillToolResults(msg, toolCalls, toolResultCapture);
|
|
1665
1884
|
if (msg.type === "result") {
|
|
1666
1885
|
if (msg.subtype === "success") {
|
|
1667
1886
|
const r = msg;
|
|
@@ -1678,23 +1897,17 @@ var init_claude = __esm({
|
|
|
1678
1897
|
}
|
|
1679
1898
|
}
|
|
1680
1899
|
}
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
messages: [
|
|
1693
|
-
...messages,
|
|
1694
|
-
...output !== null ? [{ role: "assistant", content: output }] : []
|
|
1695
|
-
],
|
|
1696
|
-
usage
|
|
1697
|
-
};
|
|
1900
|
+
return {
|
|
1901
|
+
output,
|
|
1902
|
+
structuredOutput: void 0,
|
|
1903
|
+
toolCalls,
|
|
1904
|
+
messages: [
|
|
1905
|
+
...messages,
|
|
1906
|
+
...output !== null ? [{ role: "assistant", content: output }] : []
|
|
1907
|
+
],
|
|
1908
|
+
usage
|
|
1909
|
+
};
|
|
1910
|
+
});
|
|
1698
1911
|
}
|
|
1699
1912
|
if (this.isPersistent) this.clearPersistentSession();
|
|
1700
1913
|
throw e;
|
|
@@ -1713,12 +1926,12 @@ var init_claude = __esm({
|
|
|
1713
1926
|
};
|
|
1714
1927
|
}
|
|
1715
1928
|
// ─── executeRunStructured ───────────────────────────────────────
|
|
1716
|
-
async executeRunStructured(messages, schema,
|
|
1929
|
+
async executeRunStructured(messages, schema, options, signal) {
|
|
1717
1930
|
this.checkAbort(signal);
|
|
1718
1931
|
const sdk = await loadSDK2();
|
|
1719
1932
|
const isResuming = this.isPersistent && this._sessionId !== void 0;
|
|
1720
|
-
const prompt = isResuming ?
|
|
1721
|
-
let opts = this.buildQueryOptions(signal);
|
|
1933
|
+
const prompt = isResuming ? extractLastUserPrompt(messages) : buildContextualPrompt(messages);
|
|
1934
|
+
let opts = this.buildQueryOptions(signal, options);
|
|
1722
1935
|
const toolResultCapture = /* @__PURE__ */ new Map();
|
|
1723
1936
|
opts = await this.buildMcpConfig(opts, toolResultCapture);
|
|
1724
1937
|
const jsonSchema = zodToJsonSchema(schema.schema);
|
|
@@ -1734,30 +1947,8 @@ var init_claude = __esm({
|
|
|
1734
1947
|
let usage;
|
|
1735
1948
|
try {
|
|
1736
1949
|
for await (const msg of q) {
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
if (betaMessage?.content) {
|
|
1740
|
-
for (const block of betaMessage.content) {
|
|
1741
|
-
if (block.type === "tool_use") {
|
|
1742
|
-
const toolName = stripMcpPrefix(block.name ?? "unknown");
|
|
1743
|
-
toolCalls.push({
|
|
1744
|
-
toolName,
|
|
1745
|
-
args: block.input ?? {},
|
|
1746
|
-
result: toolResultCapture.get(toolName) ?? null,
|
|
1747
|
-
approved: true
|
|
1748
|
-
});
|
|
1749
|
-
}
|
|
1750
|
-
}
|
|
1751
|
-
}
|
|
1752
|
-
}
|
|
1753
|
-
if (msg.type === "tool_use_summary" || msg.type === "result") {
|
|
1754
|
-
for (const tc of toolCalls) {
|
|
1755
|
-
if (tc.result === null) {
|
|
1756
|
-
const captured = toolResultCapture.get(tc.toolName);
|
|
1757
|
-
if (captured !== void 0) tc.result = captured;
|
|
1758
|
-
}
|
|
1759
|
-
}
|
|
1760
|
-
}
|
|
1950
|
+
this.collectToolCallsFromMessage(msg, toolCalls, toolResultCapture);
|
|
1951
|
+
this.backfillToolResults(msg, toolCalls, toolResultCapture);
|
|
1761
1952
|
if (msg.type === "result" && msg.subtype === "success") {
|
|
1762
1953
|
const r = msg;
|
|
1763
1954
|
output = r.result;
|
|
@@ -1792,46 +1983,23 @@ var init_claude = __esm({
|
|
|
1792
1983
|
} catch (e) {
|
|
1793
1984
|
if (signal.aborted) throw new AbortError();
|
|
1794
1985
|
if (isResuming && this.isPersistent) {
|
|
1795
|
-
this.
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
this.activeQuery = retryQ;
|
|
1986
|
+
const retryQ = await this.prepareRetryQuery(
|
|
1987
|
+
sdk,
|
|
1988
|
+
messages,
|
|
1989
|
+
signal,
|
|
1990
|
+
options,
|
|
1991
|
+
toolResultCapture,
|
|
1992
|
+
(opts2) => {
|
|
1993
|
+
opts2.outputFormat = { type: "json_schema", schema: jsonSchema };
|
|
1994
|
+
}
|
|
1995
|
+
);
|
|
1806
1996
|
toolCalls.length = 0;
|
|
1807
1997
|
output = null;
|
|
1808
1998
|
structuredOutput = void 0;
|
|
1809
|
-
|
|
1999
|
+
return this.withRetryErrorHandling(signal, async () => {
|
|
1810
2000
|
for await (const msg of retryQ) {
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
if (betaMessage?.content) {
|
|
1814
|
-
for (const block of betaMessage.content) {
|
|
1815
|
-
if (block.type === "tool_use") {
|
|
1816
|
-
const toolName = stripMcpPrefix(block.name ?? "unknown");
|
|
1817
|
-
toolCalls.push({
|
|
1818
|
-
toolName,
|
|
1819
|
-
args: block.input ?? {},
|
|
1820
|
-
result: toolResultCapture.get(toolName) ?? null,
|
|
1821
|
-
approved: true
|
|
1822
|
-
});
|
|
1823
|
-
}
|
|
1824
|
-
}
|
|
1825
|
-
}
|
|
1826
|
-
}
|
|
1827
|
-
if (msg.type === "tool_use_summary" || msg.type === "result") {
|
|
1828
|
-
for (const tc of toolCalls) {
|
|
1829
|
-
if (tc.result === null) {
|
|
1830
|
-
const captured = toolResultCapture.get(tc.toolName);
|
|
1831
|
-
if (captured !== void 0) tc.result = captured;
|
|
1832
|
-
}
|
|
1833
|
-
}
|
|
1834
|
-
}
|
|
2001
|
+
this.collectToolCallsFromMessage(msg, toolCalls, toolResultCapture);
|
|
2002
|
+
this.backfillToolResults(msg, toolCalls, toolResultCapture);
|
|
1835
2003
|
if (msg.type === "result" && msg.subtype === "success") {
|
|
1836
2004
|
const r = msg;
|
|
1837
2005
|
output = r.result;
|
|
@@ -1863,23 +2031,17 @@ var init_claude = __esm({
|
|
|
1863
2031
|
);
|
|
1864
2032
|
}
|
|
1865
2033
|
}
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
messages: [
|
|
1878
|
-
...messages,
|
|
1879
|
-
...output !== null ? [{ role: "assistant", content: output }] : []
|
|
1880
|
-
],
|
|
1881
|
-
usage
|
|
1882
|
-
};
|
|
2034
|
+
return {
|
|
2035
|
+
output,
|
|
2036
|
+
structuredOutput,
|
|
2037
|
+
toolCalls,
|
|
2038
|
+
messages: [
|
|
2039
|
+
...messages,
|
|
2040
|
+
...output !== null ? [{ role: "assistant", content: output }] : []
|
|
2041
|
+
],
|
|
2042
|
+
usage
|
|
2043
|
+
};
|
|
2044
|
+
});
|
|
1883
2045
|
}
|
|
1884
2046
|
if (this.isPersistent) this.clearPersistentSession();
|
|
1885
2047
|
throw e;
|
|
@@ -1898,12 +2060,12 @@ var init_claude = __esm({
|
|
|
1898
2060
|
};
|
|
1899
2061
|
}
|
|
1900
2062
|
// ─── executeStream ──────────────────────────────────────────────
|
|
1901
|
-
async *executeStream(messages,
|
|
2063
|
+
async *executeStream(messages, options, signal) {
|
|
1902
2064
|
this.checkAbort(signal);
|
|
1903
2065
|
const sdk = await loadSDK2();
|
|
1904
2066
|
const isResuming = this.isPersistent && this._sessionId !== void 0;
|
|
1905
|
-
const prompt = isResuming ?
|
|
1906
|
-
let opts = this.buildQueryOptions(signal);
|
|
2067
|
+
const prompt = isResuming ? extractLastUserPrompt(messages) : buildContextualPrompt(messages);
|
|
2068
|
+
let opts = this.buildQueryOptions(signal, options);
|
|
1907
2069
|
const toolResultCapture = /* @__PURE__ */ new Map();
|
|
1908
2070
|
opts = await this.buildMcpConfig(opts, toolResultCapture);
|
|
1909
2071
|
const q = sdk.query({ prompt, options: opts });
|
|
@@ -1911,6 +2073,7 @@ var init_claude = __esm({
|
|
|
1911
2073
|
const thinkingBlockIndices = /* @__PURE__ */ new Set();
|
|
1912
2074
|
const toolCallTracker = new ClaudeToolCallTracker();
|
|
1913
2075
|
const pendingStreamToolCalls = /* @__PURE__ */ new Map();
|
|
2076
|
+
let hasStreamedText = false;
|
|
1914
2077
|
try {
|
|
1915
2078
|
for await (const msg of q) {
|
|
1916
2079
|
if (signal.aborted) throw new AbortError();
|
|
@@ -1928,6 +2091,7 @@ var init_claude = __esm({
|
|
|
1928
2091
|
} else if (e.type === "tool_call_end") {
|
|
1929
2092
|
pendingStreamToolCalls.delete(e.toolCallId);
|
|
1930
2093
|
}
|
|
2094
|
+
if (e.type === "text_delta") hasStreamedText = true;
|
|
1931
2095
|
yield e;
|
|
1932
2096
|
}
|
|
1933
2097
|
}
|
|
@@ -1951,22 +2115,21 @@ var init_claude = __esm({
|
|
|
1951
2115
|
}
|
|
1952
2116
|
yield this.emitSessionInfo(r.session_id);
|
|
1953
2117
|
}
|
|
1954
|
-
yield {
|
|
2118
|
+
yield {
|
|
2119
|
+
type: "done",
|
|
2120
|
+
finalOutput: hasStreamedText ? null : r.result,
|
|
2121
|
+
...hasStreamedText ? { streamed: true } : {}
|
|
2122
|
+
};
|
|
1955
2123
|
}
|
|
1956
2124
|
}
|
|
1957
2125
|
} catch (e) {
|
|
1958
2126
|
if (signal.aborted) throw new AbortError();
|
|
1959
2127
|
if (isResuming && this.isPersistent) {
|
|
1960
|
-
this.
|
|
1961
|
-
const retryPrompt = buildContextualPrompt2(messages);
|
|
1962
|
-
let retryOpts = this.buildQueryOptions(signal);
|
|
1963
|
-
toolResultCapture.clear();
|
|
1964
|
-
retryOpts = await this.buildMcpConfig(retryOpts, toolResultCapture);
|
|
1965
|
-
const retryQ = sdk.query({ prompt: retryPrompt, options: retryOpts });
|
|
1966
|
-
this.activeQuery = retryQ;
|
|
2128
|
+
const retryQ = await this.prepareRetryQuery(sdk, messages, signal, options, toolResultCapture);
|
|
1967
2129
|
const retryThinkingBlockIndices = /* @__PURE__ */ new Set();
|
|
1968
2130
|
const retryToolCallTracker = new ClaudeToolCallTracker();
|
|
1969
2131
|
const retryPendingToolCalls = /* @__PURE__ */ new Map();
|
|
2132
|
+
let retryHasStreamedText = false;
|
|
1970
2133
|
try {
|
|
1971
2134
|
for await (const msg of retryQ) {
|
|
1972
2135
|
if (signal.aborted) throw new AbortError();
|
|
@@ -1984,6 +2147,7 @@ var init_claude = __esm({
|
|
|
1984
2147
|
} else if (ev.type === "tool_call_end") {
|
|
1985
2148
|
retryPendingToolCalls.delete(ev.toolCallId);
|
|
1986
2149
|
}
|
|
2150
|
+
if (ev.type === "text_delta") retryHasStreamedText = true;
|
|
1987
2151
|
yield ev;
|
|
1988
2152
|
}
|
|
1989
2153
|
}
|
|
@@ -2007,7 +2171,11 @@ var init_claude = __esm({
|
|
|
2007
2171
|
}
|
|
2008
2172
|
yield this.emitSessionInfo(r.session_id);
|
|
2009
2173
|
}
|
|
2010
|
-
yield {
|
|
2174
|
+
yield {
|
|
2175
|
+
type: "done",
|
|
2176
|
+
finalOutput: retryHasStreamedText ? null : r.result,
|
|
2177
|
+
...retryHasStreamedText ? { streamed: true } : {}
|
|
2178
|
+
};
|
|
2011
2179
|
}
|
|
2012
2180
|
}
|
|
2013
2181
|
} catch (retryError) {
|
|
@@ -2069,7 +2237,8 @@ var init_claude = __esm({
|
|
|
2069
2237
|
this.cachedModels = body.data.map((m) => ({
|
|
2070
2238
|
id: m.id,
|
|
2071
2239
|
name: m.display_name,
|
|
2072
|
-
provider: "claude"
|
|
2240
|
+
provider: "claude",
|
|
2241
|
+
...m.max_input_tokens != null && { contextWindow: m.max_input_tokens }
|
|
2073
2242
|
}));
|
|
2074
2243
|
return this.cachedModels;
|
|
2075
2244
|
}
|
|
@@ -2127,32 +2296,30 @@ __export(vercel_ai_exports, {
|
|
|
2127
2296
|
createVercelAIService: () => createVercelAIService
|
|
2128
2297
|
});
|
|
2129
2298
|
async function loadSDK3() {
|
|
2130
|
-
if (
|
|
2299
|
+
if (_sdkMock3) return _sdkMock3;
|
|
2131
2300
|
try {
|
|
2132
|
-
|
|
2133
|
-
return sdkModule3;
|
|
2301
|
+
return await import('ai');
|
|
2134
2302
|
} catch {
|
|
2135
2303
|
throw new DependencyError("ai");
|
|
2136
2304
|
}
|
|
2137
2305
|
}
|
|
2138
2306
|
async function loadCompat() {
|
|
2139
|
-
if (
|
|
2307
|
+
if (_compatMock) return _compatMock;
|
|
2140
2308
|
try {
|
|
2141
|
-
|
|
2142
|
-
return compatModule;
|
|
2309
|
+
return await import('@ai-sdk/openai-compatible');
|
|
2143
2310
|
} catch {
|
|
2144
2311
|
throw new DependencyError("@ai-sdk/openai-compatible");
|
|
2145
2312
|
}
|
|
2146
2313
|
}
|
|
2147
2314
|
function _injectSDK3(mock) {
|
|
2148
|
-
|
|
2315
|
+
_sdkMock3 = mock;
|
|
2149
2316
|
}
|
|
2150
2317
|
function _injectCompat(mock) {
|
|
2151
|
-
|
|
2318
|
+
_compatMock = mock;
|
|
2152
2319
|
}
|
|
2153
2320
|
function _resetSDK3() {
|
|
2154
|
-
|
|
2155
|
-
|
|
2321
|
+
_sdkMock3 = null;
|
|
2322
|
+
_compatMock = null;
|
|
2156
2323
|
}
|
|
2157
2324
|
function mapToolsToSDK2(sdk, tools, config, sessionApprovals, permissionStore, signal) {
|
|
2158
2325
|
const toolMap = {};
|
|
@@ -2195,13 +2362,14 @@ function mapToolsToSDK2(sdk, tools, config, sessionApprovals, permissionStore, s
|
|
|
2195
2362
|
return toolMap;
|
|
2196
2363
|
}
|
|
2197
2364
|
function wrapToolExecute(ourTool, supervisor, sessionApprovals, permissionStore, signal) {
|
|
2198
|
-
return async (args) => {
|
|
2365
|
+
return async (args, options) => {
|
|
2199
2366
|
if (ourTool.needsApproval && supervisor?.onPermission) {
|
|
2200
2367
|
const storeApproved = permissionStore && await permissionStore.isApproved(ourTool.name);
|
|
2201
2368
|
if (!storeApproved && !sessionApprovals.has(ourTool.name)) {
|
|
2202
2369
|
const request = {
|
|
2203
2370
|
toolName: ourTool.name,
|
|
2204
|
-
toolArgs: args ?? {}
|
|
2371
|
+
toolArgs: args ?? {},
|
|
2372
|
+
toolCallId: options?.toolCallId
|
|
2205
2373
|
};
|
|
2206
2374
|
const decision = await supervisor.onPermission(
|
|
2207
2375
|
request,
|
|
@@ -2308,7 +2476,8 @@ function mapStreamPart(part) {
|
|
|
2308
2476
|
return {
|
|
2309
2477
|
type: "error",
|
|
2310
2478
|
error: p.error instanceof Error ? p.error.message : String(p.error ?? "Tool execution failed"),
|
|
2311
|
-
recoverable: true
|
|
2479
|
+
recoverable: true,
|
|
2480
|
+
code: "TOOL_EXECUTION" /* TOOL_EXECUTION */
|
|
2312
2481
|
};
|
|
2313
2482
|
}
|
|
2314
2483
|
case "reasoning-start":
|
|
@@ -2329,10 +2498,13 @@ function mapStreamPart(part) {
|
|
|
2329
2498
|
}
|
|
2330
2499
|
case "error": {
|
|
2331
2500
|
const p = part;
|
|
2501
|
+
const errorMsg = p.error instanceof Error ? p.error.message : String(p.error ?? "Unknown error");
|
|
2502
|
+
const code = classifyAgentError(errorMsg);
|
|
2332
2503
|
return {
|
|
2333
2504
|
type: "error",
|
|
2334
|
-
error:
|
|
2335
|
-
recoverable:
|
|
2505
|
+
error: errorMsg,
|
|
2506
|
+
recoverable: isRecoverableErrorCode(code),
|
|
2507
|
+
code
|
|
2336
2508
|
};
|
|
2337
2509
|
}
|
|
2338
2510
|
default:
|
|
@@ -2342,15 +2514,15 @@ function mapStreamPart(part) {
|
|
|
2342
2514
|
function createVercelAIService(options) {
|
|
2343
2515
|
return new VercelAIAgentService(options);
|
|
2344
2516
|
}
|
|
2345
|
-
var
|
|
2517
|
+
var _sdkMock3, _compatMock, DEFAULT_BASE_URL, DEFAULT_PROVIDER, DEFAULT_MAX_TURNS, VercelAIAgent, VercelAIAgentService;
|
|
2346
2518
|
var init_vercel_ai = __esm({
|
|
2347
2519
|
"src/backends/vercel-ai.ts"() {
|
|
2348
|
-
|
|
2520
|
+
init_types2();
|
|
2349
2521
|
init_base_agent();
|
|
2350
|
-
|
|
2522
|
+
init_errors2();
|
|
2351
2523
|
init_schema();
|
|
2352
|
-
|
|
2353
|
-
|
|
2524
|
+
_sdkMock3 = null;
|
|
2525
|
+
_compatMock = null;
|
|
2354
2526
|
DEFAULT_BASE_URL = "https://openrouter.ai/api/v1";
|
|
2355
2527
|
DEFAULT_PROVIDER = "openrouter";
|
|
2356
2528
|
DEFAULT_MAX_TURNS = 10;
|
|
@@ -2363,28 +2535,33 @@ var init_vercel_ai = __esm({
|
|
|
2363
2535
|
super(config);
|
|
2364
2536
|
this.backendOptions = backendOptions;
|
|
2365
2537
|
}
|
|
2366
|
-
async getModel() {
|
|
2367
|
-
|
|
2538
|
+
async getModel(options) {
|
|
2539
|
+
const requestedModel = options.model;
|
|
2540
|
+
const defaultModel = this.config.model;
|
|
2541
|
+
if (requestedModel === defaultModel && this.model) return this.model;
|
|
2368
2542
|
const compat = await loadCompat();
|
|
2369
2543
|
const provider = compat.createOpenAICompatible({
|
|
2370
2544
|
name: this.backendOptions.provider ?? DEFAULT_PROVIDER,
|
|
2371
2545
|
baseURL: this.backendOptions.baseUrl ?? DEFAULT_BASE_URL,
|
|
2372
2546
|
apiKey: this.backendOptions.apiKey
|
|
2373
2547
|
});
|
|
2374
|
-
const
|
|
2375
|
-
|
|
2376
|
-
|
|
2548
|
+
const model = provider.chatModel(requestedModel);
|
|
2549
|
+
if (requestedModel === defaultModel) {
|
|
2550
|
+
this.model = model;
|
|
2551
|
+
}
|
|
2552
|
+
return model;
|
|
2377
2553
|
}
|
|
2378
|
-
async getSDKTools(signal) {
|
|
2554
|
+
async getSDKTools(signal, options) {
|
|
2379
2555
|
const sdk = await loadSDK3();
|
|
2380
|
-
|
|
2556
|
+
const tools = this.resolveTools(options);
|
|
2557
|
+
return mapToolsToSDK2(sdk, tools, this.config, this.sessionApprovals, this.config.permissionStore, signal);
|
|
2381
2558
|
}
|
|
2382
2559
|
// ─── executeRun ─────────────────────────────────────────────────
|
|
2383
|
-
async executeRun(messages,
|
|
2560
|
+
async executeRun(messages, options, signal) {
|
|
2384
2561
|
this.checkAbort(signal);
|
|
2385
2562
|
const sdk = await loadSDK3();
|
|
2386
|
-
const model = await this.getModel();
|
|
2387
|
-
const tools = await this.getSDKTools(signal);
|
|
2563
|
+
const model = await this.getModel(options);
|
|
2564
|
+
const tools = await this.getSDKTools(signal, options);
|
|
2388
2565
|
const maxTurns = this.config.maxTurns ?? DEFAULT_MAX_TURNS;
|
|
2389
2566
|
const sdkMessages = messagesToSDK(messages);
|
|
2390
2567
|
const hasTools = Object.keys(tools).length > 0;
|
|
@@ -2440,10 +2617,10 @@ var init_vercel_ai = __esm({
|
|
|
2440
2617
|
};
|
|
2441
2618
|
}
|
|
2442
2619
|
// ─── executeRunStructured ───────────────────────────────────────
|
|
2443
|
-
async executeRunStructured(messages, schema,
|
|
2620
|
+
async executeRunStructured(messages, schema, options, signal) {
|
|
2444
2621
|
this.checkAbort(signal);
|
|
2445
2622
|
const sdk = await loadSDK3();
|
|
2446
|
-
const model = await this.getModel();
|
|
2623
|
+
const model = await this.getModel(options);
|
|
2447
2624
|
const sdkMessages = messagesToSDK(messages);
|
|
2448
2625
|
const jsonSchema = zodToJsonSchema(schema.schema);
|
|
2449
2626
|
const result = await sdk.generateObject({
|
|
@@ -2485,11 +2662,11 @@ var init_vercel_ai = __esm({
|
|
|
2485
2662
|
};
|
|
2486
2663
|
}
|
|
2487
2664
|
// ─── executeStream ──────────────────────────────────────────────
|
|
2488
|
-
async *executeStream(messages,
|
|
2665
|
+
async *executeStream(messages, options, signal) {
|
|
2489
2666
|
this.checkAbort(signal);
|
|
2490
2667
|
const sdk = await loadSDK3();
|
|
2491
|
-
const model = await this.getModel();
|
|
2492
|
-
const tools = await this.getSDKTools(signal);
|
|
2668
|
+
const model = await this.getModel(options);
|
|
2669
|
+
const tools = await this.getSDKTools(signal, options);
|
|
2493
2670
|
const maxTurns = this.config.maxTurns ?? DEFAULT_MAX_TURNS;
|
|
2494
2671
|
const sdkMessages = messagesToSDK(messages);
|
|
2495
2672
|
const hasTools = Object.keys(tools).length > 0;
|
|
@@ -2535,9 +2712,11 @@ var init_vercel_ai = __esm({
|
|
|
2535
2712
|
promptTokens: Number(totalUsage?.inputTokens ?? 0),
|
|
2536
2713
|
completionTokens: Number(totalUsage?.outputTokens ?? 0)
|
|
2537
2714
|
};
|
|
2715
|
+
const hasStreamed = finalText.length > 0;
|
|
2538
2716
|
yield {
|
|
2539
2717
|
type: "done",
|
|
2540
|
-
finalOutput: finalText || null
|
|
2718
|
+
finalOutput: hasStreamed ? null : finalText || null,
|
|
2719
|
+
...hasStreamed ? { streamed: true } : {}
|
|
2541
2720
|
};
|
|
2542
2721
|
} catch (e) {
|
|
2543
2722
|
if (signal.aborted) throw new AbortError();
|
|
@@ -2566,16 +2745,33 @@ var init_vercel_ai = __esm({
|
|
|
2566
2745
|
const baseUrl = (this.options.baseUrl || "https://api.openai.com/v1").replace(/\/+$/, "");
|
|
2567
2746
|
try {
|
|
2568
2747
|
const res = await globalThis.fetch(`${baseUrl}/models`, {
|
|
2569
|
-
headers: {
|
|
2748
|
+
headers: {
|
|
2749
|
+
Authorization: `Bearer ${this.options.apiKey}`,
|
|
2750
|
+
// OpenRouter requires HTTP-Referer for API access
|
|
2751
|
+
"HTTP-Referer": "https://github.com/nicepkg/agent-sdk"
|
|
2752
|
+
}
|
|
2570
2753
|
});
|
|
2571
2754
|
if (!res.ok) {
|
|
2572
2755
|
return [];
|
|
2573
2756
|
}
|
|
2574
2757
|
const body = await res.json();
|
|
2575
|
-
if (
|
|
2576
|
-
return
|
|
2758
|
+
if (body.data && Array.isArray(body.data)) {
|
|
2759
|
+
return body.data.filter((m) => typeof m.id === "string").map((m) => ({
|
|
2760
|
+
id: m.id,
|
|
2761
|
+
...typeof m.name === "string" && { name: m.name },
|
|
2762
|
+
...typeof m.description === "string" && { description: m.description },
|
|
2763
|
+
...typeof m.context_length === "number" && { contextWindow: m.context_length }
|
|
2764
|
+
}));
|
|
2765
|
+
}
|
|
2766
|
+
if (Array.isArray(body)) {
|
|
2767
|
+
return body.filter((m) => typeof m.id === "string").map((m) => ({
|
|
2768
|
+
id: m.id,
|
|
2769
|
+
...typeof m.name === "string" && { name: m.name },
|
|
2770
|
+
...typeof m.description === "string" && { description: m.description },
|
|
2771
|
+
...typeof m.context_length === "number" && { contextWindow: m.context_length }
|
|
2772
|
+
}));
|
|
2577
2773
|
}
|
|
2578
|
-
return
|
|
2774
|
+
return [];
|
|
2579
2775
|
} catch {
|
|
2580
2776
|
return [];
|
|
2581
2777
|
}
|
|
@@ -2606,272 +2802,25 @@ var init_vercel_ai = __esm({
|
|
|
2606
2802
|
}
|
|
2607
2803
|
});
|
|
2608
2804
|
|
|
2609
|
-
// src/
|
|
2610
|
-
function
|
|
2611
|
-
|
|
2612
|
-
throw new BackendAlreadyRegisteredError(name);
|
|
2613
|
-
}
|
|
2614
|
-
registry.set(name, { factory, builtin: false });
|
|
2615
|
-
}
|
|
2616
|
-
function unregisterBackend(name) {
|
|
2617
|
-
return registry.delete(name);
|
|
2805
|
+
// src/chat/backends/types.ts
|
|
2806
|
+
function isResumableBackend(adapter) {
|
|
2807
|
+
return "canResume" in adapter && typeof adapter.canResume === "function";
|
|
2618
2808
|
}
|
|
2619
|
-
function hasBackend(name) {
|
|
2620
|
-
return registry.has(name) || isBuiltinName(name);
|
|
2621
|
-
}
|
|
2622
|
-
function listBackends() {
|
|
2623
|
-
const names = new Set(registry.keys());
|
|
2624
|
-
for (const builtin of BUILTIN_BACKENDS) {
|
|
2625
|
-
names.add(builtin);
|
|
2626
|
-
}
|
|
2627
|
-
return [...names];
|
|
2628
|
-
}
|
|
2629
|
-
function resetRegistry() {
|
|
2630
|
-
registry.clear();
|
|
2631
|
-
}
|
|
2632
|
-
function isBuiltinName(name) {
|
|
2633
|
-
return BUILTIN_BACKENDS.has(name);
|
|
2634
|
-
}
|
|
2635
|
-
async function loadBuiltinFactory(name) {
|
|
2636
|
-
switch (name) {
|
|
2637
|
-
case "copilot": {
|
|
2638
|
-
const mod = await Promise.resolve().then(() => (init_copilot(), copilot_exports));
|
|
2639
|
-
return (opts) => mod.createCopilotService(opts);
|
|
2640
|
-
}
|
|
2641
|
-
case "claude": {
|
|
2642
|
-
const mod = await Promise.resolve().then(() => (init_claude(), claude_exports));
|
|
2643
|
-
return (opts) => mod.createClaudeService(opts);
|
|
2644
|
-
}
|
|
2645
|
-
case "vercel-ai": {
|
|
2646
|
-
const mod = await Promise.resolve().then(() => (init_vercel_ai(), vercel_ai_exports));
|
|
2647
|
-
return (opts) => mod.createVercelAIService(opts);
|
|
2648
|
-
}
|
|
2649
|
-
}
|
|
2650
|
-
}
|
|
2651
|
-
async function createAgentService(name, options) {
|
|
2652
|
-
const entry = registry.get(name);
|
|
2653
|
-
if (entry) {
|
|
2654
|
-
return entry.factory(options);
|
|
2655
|
-
}
|
|
2656
|
-
if (isBuiltinName(name)) {
|
|
2657
|
-
const factory = await loadBuiltinFactory(name);
|
|
2658
|
-
registry.set(name, { factory, builtin: true });
|
|
2659
|
-
return factory(options);
|
|
2660
|
-
}
|
|
2661
|
-
throw new BackendNotFoundError(name);
|
|
2662
|
-
}
|
|
2663
|
-
var registry, BUILTIN_BACKENDS;
|
|
2664
|
-
var init_registry = __esm({
|
|
2665
|
-
"src/registry.ts"() {
|
|
2666
|
-
init_errors();
|
|
2667
|
-
registry = /* @__PURE__ */ new Map();
|
|
2668
|
-
BUILTIN_BACKENDS = /* @__PURE__ */ new Set([
|
|
2669
|
-
"copilot",
|
|
2670
|
-
"claude",
|
|
2671
|
-
"vercel-ai"
|
|
2672
|
-
]);
|
|
2673
|
-
}
|
|
2674
|
-
});
|
|
2675
|
-
|
|
2676
|
-
// src/utils/messages.ts
|
|
2677
|
-
function messagesToPrompt(messages) {
|
|
2678
|
-
return messages.map((msg) => {
|
|
2679
|
-
switch (msg.role) {
|
|
2680
|
-
case "user":
|
|
2681
|
-
return contentToText(msg.content);
|
|
2682
|
-
case "assistant":
|
|
2683
|
-
return contentToText(msg.content);
|
|
2684
|
-
case "system":
|
|
2685
|
-
return msg.content;
|
|
2686
|
-
case "tool":
|
|
2687
|
-
return msg.content ?? "";
|
|
2688
|
-
}
|
|
2689
|
-
}).filter(Boolean).join("\n\n");
|
|
2690
|
-
}
|
|
2691
|
-
function contentToText(content) {
|
|
2692
|
-
return getTextContent(content);
|
|
2693
|
-
}
|
|
2694
|
-
function buildSystemPrompt(base, schemaInstruction) {
|
|
2695
|
-
if (!schemaInstruction) return base;
|
|
2696
|
-
return `${base}
|
|
2697
2809
|
|
|
2698
|
-
|
|
2699
|
-
}
|
|
2700
|
-
var init_messages = __esm({
|
|
2701
|
-
"src/utils/messages.ts"() {
|
|
2702
|
-
init_types();
|
|
2703
|
-
}
|
|
2704
|
-
});
|
|
2705
|
-
function createDefaultPermissionStore(projectDir) {
|
|
2706
|
-
const sessionStore = new InMemoryPermissionStore();
|
|
2707
|
-
const projectPath = projectDir ? path__namespace.join(projectDir, ".agent-sdk", "permissions.json") : path__namespace.join(process.cwd(), ".agent-sdk", "permissions.json");
|
|
2708
|
-
const userPath = path__namespace.join(os__namespace.homedir(), ".agent-sdk", "permissions.json");
|
|
2709
|
-
const projectStore = new FilePermissionStore(projectPath);
|
|
2710
|
-
const userStore = new FilePermissionStore(userPath);
|
|
2711
|
-
return new CompositePermissionStore(sessionStore, projectStore, userStore);
|
|
2712
|
-
}
|
|
2713
|
-
var InMemoryPermissionStore, FilePermissionStore, CompositePermissionStore;
|
|
2714
|
-
var init_permission_store = __esm({
|
|
2715
|
-
"src/permission-store.ts"() {
|
|
2716
|
-
InMemoryPermissionStore = class {
|
|
2717
|
-
approvals = /* @__PURE__ */ new Map();
|
|
2718
|
-
async isApproved(toolName) {
|
|
2719
|
-
return this.approvals.has(toolName);
|
|
2720
|
-
}
|
|
2721
|
-
async approve(toolName, scope) {
|
|
2722
|
-
if (scope === "once") return;
|
|
2723
|
-
this.approvals.set(toolName, scope);
|
|
2724
|
-
}
|
|
2725
|
-
async revoke(toolName) {
|
|
2726
|
-
this.approvals.delete(toolName);
|
|
2727
|
-
}
|
|
2728
|
-
async clear() {
|
|
2729
|
-
this.approvals.clear();
|
|
2730
|
-
}
|
|
2731
|
-
async dispose() {
|
|
2732
|
-
this.approvals.clear();
|
|
2733
|
-
}
|
|
2734
|
-
};
|
|
2735
|
-
FilePermissionStore = class {
|
|
2736
|
-
filePath;
|
|
2737
|
-
constructor(filePath) {
|
|
2738
|
-
this.filePath = path__namespace.resolve(filePath);
|
|
2739
|
-
}
|
|
2740
|
-
async isApproved(toolName) {
|
|
2741
|
-
const data = this.readFile();
|
|
2742
|
-
return toolName in data.approvals;
|
|
2743
|
-
}
|
|
2744
|
-
async approve(toolName, scope) {
|
|
2745
|
-
if (scope === "once") return;
|
|
2746
|
-
const data = this.readFile();
|
|
2747
|
-
data.approvals[toolName] = { scope, timestamp: Date.now() };
|
|
2748
|
-
this.writeFileAtomic(data);
|
|
2749
|
-
}
|
|
2750
|
-
async revoke(toolName) {
|
|
2751
|
-
const data = this.readFile();
|
|
2752
|
-
delete data.approvals[toolName];
|
|
2753
|
-
this.writeFileAtomic(data);
|
|
2754
|
-
}
|
|
2755
|
-
async clear() {
|
|
2756
|
-
this.writeFileAtomic({ approvals: {} });
|
|
2757
|
-
}
|
|
2758
|
-
async dispose() {
|
|
2759
|
-
}
|
|
2760
|
-
readFile() {
|
|
2761
|
-
try {
|
|
2762
|
-
const raw = fs__namespace.readFileSync(this.filePath, "utf-8");
|
|
2763
|
-
const parsed = JSON.parse(raw);
|
|
2764
|
-
if (parsed && typeof parsed.approvals === "object") return parsed;
|
|
2765
|
-
} catch {
|
|
2766
|
-
}
|
|
2767
|
-
return { approvals: {} };
|
|
2768
|
-
}
|
|
2769
|
-
writeFileAtomic(data) {
|
|
2770
|
-
const dir = path__namespace.dirname(this.filePath);
|
|
2771
|
-
fs__namespace.mkdirSync(dir, { recursive: true });
|
|
2772
|
-
const tmpPath = this.filePath + `.tmp.${process.pid}.${Date.now()}`;
|
|
2773
|
-
fs__namespace.writeFileSync(tmpPath, JSON.stringify(data, null, 2), "utf-8");
|
|
2774
|
-
fs__namespace.renameSync(tmpPath, this.filePath);
|
|
2775
|
-
}
|
|
2776
|
-
};
|
|
2777
|
-
CompositePermissionStore = class {
|
|
2778
|
-
sessionStore;
|
|
2779
|
-
projectStore;
|
|
2780
|
-
userStore;
|
|
2781
|
-
constructor(sessionStore, projectStore, userStore) {
|
|
2782
|
-
this.sessionStore = sessionStore;
|
|
2783
|
-
this.projectStore = projectStore;
|
|
2784
|
-
this.userStore = userStore ?? projectStore;
|
|
2785
|
-
}
|
|
2786
|
-
async isApproved(toolName) {
|
|
2787
|
-
return await this.sessionStore.isApproved(toolName) || await this.projectStore.isApproved(toolName) || await this.userStore.isApproved(toolName);
|
|
2788
|
-
}
|
|
2789
|
-
async approve(toolName, scope) {
|
|
2790
|
-
if (scope === "once") return;
|
|
2791
|
-
if (scope === "session") {
|
|
2792
|
-
await this.sessionStore.approve(toolName, scope);
|
|
2793
|
-
} else if (scope === "project") {
|
|
2794
|
-
await this.projectStore.approve(toolName, scope);
|
|
2795
|
-
} else {
|
|
2796
|
-
await this.userStore.approve(toolName, scope);
|
|
2797
|
-
}
|
|
2798
|
-
}
|
|
2799
|
-
async revoke(toolName) {
|
|
2800
|
-
await this.sessionStore.revoke(toolName);
|
|
2801
|
-
await this.projectStore.revoke(toolName);
|
|
2802
|
-
await this.userStore.revoke(toolName);
|
|
2803
|
-
}
|
|
2804
|
-
async clear() {
|
|
2805
|
-
await this.sessionStore.clear();
|
|
2806
|
-
await this.projectStore.clear();
|
|
2807
|
-
await this.userStore.clear();
|
|
2808
|
-
}
|
|
2809
|
-
async dispose() {
|
|
2810
|
-
await this.sessionStore.dispose();
|
|
2811
|
-
await this.projectStore.dispose();
|
|
2812
|
-
if (this.userStore !== this.projectStore) {
|
|
2813
|
-
await this.userStore.dispose();
|
|
2814
|
-
}
|
|
2815
|
-
}
|
|
2816
|
-
};
|
|
2817
|
-
}
|
|
2818
|
-
});
|
|
2819
|
-
|
|
2820
|
-
// src/index.ts
|
|
2821
|
-
var src_exports = {};
|
|
2822
|
-
__export(src_exports, {
|
|
2823
|
-
AbortError: () => AbortError,
|
|
2824
|
-
AgentSDKError: () => AgentSDKError,
|
|
2825
|
-
BackendAlreadyRegisteredError: () => BackendAlreadyRegisteredError,
|
|
2826
|
-
BackendNotFoundError: () => BackendNotFoundError,
|
|
2827
|
-
BaseAgent: () => BaseAgent,
|
|
2828
|
-
CompositePermissionStore: () => CompositePermissionStore,
|
|
2829
|
-
DependencyError: () => DependencyError,
|
|
2830
|
-
DisposedError: () => DisposedError,
|
|
2831
|
-
FilePermissionStore: () => FilePermissionStore,
|
|
2832
|
-
InMemoryPermissionStore: () => InMemoryPermissionStore,
|
|
2833
|
-
ReentrancyError: () => ReentrancyError,
|
|
2834
|
-
StructuredOutputError: () => StructuredOutputError,
|
|
2835
|
-
SubprocessError: () => SubprocessError,
|
|
2836
|
-
ToolExecutionError: () => ToolExecutionError,
|
|
2837
|
-
buildSystemPrompt: () => buildSystemPrompt,
|
|
2838
|
-
contentToText: () => contentToText,
|
|
2839
|
-
createAgentService: () => createAgentService,
|
|
2840
|
-
createDefaultPermissionStore: () => createDefaultPermissionStore,
|
|
2841
|
-
getTextContent: () => getTextContent,
|
|
2842
|
-
hasBackend: () => hasBackend,
|
|
2843
|
-
isMultiPartContent: () => isMultiPartContent,
|
|
2844
|
-
isTextContent: () => isTextContent,
|
|
2845
|
-
isToolDefinition: () => isToolDefinition,
|
|
2846
|
-
listBackends: () => listBackends,
|
|
2847
|
-
messagesToPrompt: () => messagesToPrompt,
|
|
2848
|
-
registerBackend: () => registerBackend,
|
|
2849
|
-
resetRegistry: () => resetRegistry,
|
|
2850
|
-
unregisterBackend: () => unregisterBackend,
|
|
2851
|
-
zodToJsonSchema: () => zodToJsonSchema
|
|
2852
|
-
});
|
|
2853
|
-
var init_src = __esm({
|
|
2854
|
-
"src/index.ts"() {
|
|
2855
|
-
init_types();
|
|
2856
|
-
init_errors();
|
|
2857
|
-
init_registry();
|
|
2858
|
-
init_base_agent();
|
|
2859
|
-
init_schema();
|
|
2860
|
-
init_messages();
|
|
2861
|
-
init_permission_store();
|
|
2862
|
-
}
|
|
2863
|
-
});
|
|
2864
|
-
|
|
2865
|
-
// src/chat/core.ts
|
|
2810
|
+
// src/chat/types.ts
|
|
2866
2811
|
function createChatId() {
|
|
2867
2812
|
return crypto.randomUUID();
|
|
2868
2813
|
}
|
|
2814
|
+
|
|
2815
|
+
// src/chat/chat-utils.ts
|
|
2869
2816
|
function getMessageText(message) {
|
|
2870
2817
|
return message.parts.filter((p) => p.type === "text").map((p) => p.text).join("");
|
|
2871
2818
|
}
|
|
2872
2819
|
function getMessageToolCalls(message) {
|
|
2873
2820
|
return message.parts.filter((p) => p.type === "tool_call");
|
|
2874
2821
|
}
|
|
2822
|
+
|
|
2823
|
+
// src/chat/bridge.ts
|
|
2875
2824
|
function agentEventToChatEvent(event, messageId) {
|
|
2876
2825
|
switch (event.type) {
|
|
2877
2826
|
case "text_delta":
|
|
@@ -2924,6 +2873,7 @@ function agentEventToChatEvent(event, messageId) {
|
|
|
2924
2873
|
type: "error",
|
|
2925
2874
|
error: event.error,
|
|
2926
2875
|
recoverable: event.recoverable,
|
|
2876
|
+
code: event.code,
|
|
2927
2877
|
messageId
|
|
2928
2878
|
};
|
|
2929
2879
|
case "heartbeat":
|
|
@@ -2945,6 +2895,8 @@ async function* adaptAgentEvents(events, messageId) {
|
|
|
2945
2895
|
}
|
|
2946
2896
|
}
|
|
2947
2897
|
}
|
|
2898
|
+
|
|
2899
|
+
// src/chat/conversion.ts
|
|
2948
2900
|
function toAgentMessage(message) {
|
|
2949
2901
|
const textContent = getMessageText(message);
|
|
2950
2902
|
const toolCallParts = getMessageToolCalls(message);
|
|
@@ -2965,6 +2917,7 @@ function toAgentMessage(message) {
|
|
|
2965
2917
|
}
|
|
2966
2918
|
|
|
2967
2919
|
// src/chat/errors.ts
|
|
2920
|
+
init_errors2();
|
|
2968
2921
|
init_errors();
|
|
2969
2922
|
var ChatError = class extends AgentSDKError {
|
|
2970
2923
|
code;
|
|
@@ -2972,7 +2925,11 @@ var ChatError = class extends AgentSDKError {
|
|
|
2972
2925
|
retryAfter;
|
|
2973
2926
|
timestamp;
|
|
2974
2927
|
constructor(message, options) {
|
|
2975
|
-
super(message, {
|
|
2928
|
+
super(message, {
|
|
2929
|
+
cause: options.cause,
|
|
2930
|
+
code: options.code,
|
|
2931
|
+
retryable: options.retryable
|
|
2932
|
+
});
|
|
2976
2933
|
this.name = "ChatError";
|
|
2977
2934
|
this.code = options.code;
|
|
2978
2935
|
this.retryable = options.retryable ?? false;
|
|
@@ -2984,25 +2941,51 @@ var ChatError = class extends AgentSDKError {
|
|
|
2984
2941
|
// src/chat/backends/base.ts
|
|
2985
2942
|
var BaseBackendAdapter = class {
|
|
2986
2943
|
name;
|
|
2987
|
-
_agentService;
|
|
2988
|
-
|
|
2944
|
+
_agentService = null;
|
|
2945
|
+
_agentServiceFactory = null;
|
|
2989
2946
|
_disposed = false;
|
|
2990
2947
|
_agentConfig;
|
|
2991
2948
|
_ownsService;
|
|
2949
|
+
// Agent lifecycle: tracks current agent and the model it was created with.
|
|
2950
|
+
// For persistent sessions, reused across calls when model matches.
|
|
2951
|
+
// For non-persistent, recreated every call.
|
|
2952
|
+
_currentAgent = null;
|
|
2992
2953
|
constructor(name, options) {
|
|
2993
2954
|
this.name = name;
|
|
2994
2955
|
this._agentConfig = options.agentConfig;
|
|
2995
2956
|
if (options.agentService) {
|
|
2996
2957
|
this._agentService = options.agentService;
|
|
2997
2958
|
this._ownsService = false;
|
|
2959
|
+
} else if (options.agentServiceFactory) {
|
|
2960
|
+
this._agentServiceFactory = options.agentServiceFactory;
|
|
2961
|
+
this._ownsService = true;
|
|
2998
2962
|
} else {
|
|
2999
2963
|
this._agentService = this.createService();
|
|
3000
2964
|
this._ownsService = true;
|
|
3001
2965
|
}
|
|
3002
2966
|
}
|
|
3003
2967
|
get agentService() {
|
|
2968
|
+
if (!this._agentService) {
|
|
2969
|
+
if (this._agentServiceFactory) {
|
|
2970
|
+
this._agentService = this._agentServiceFactory();
|
|
2971
|
+
this._agentServiceFactory = null;
|
|
2972
|
+
} else {
|
|
2973
|
+
throw new ChatError("Agent service not available", {
|
|
2974
|
+
code: "BACKEND_NOT_INSTALLED" /* BACKEND_NOT_INSTALLED */
|
|
2975
|
+
});
|
|
2976
|
+
}
|
|
2977
|
+
}
|
|
3004
2978
|
return this._agentService;
|
|
3005
2979
|
}
|
|
2980
|
+
get currentModel() {
|
|
2981
|
+
return this._agentConfig.model;
|
|
2982
|
+
}
|
|
2983
|
+
/**
|
|
2984
|
+
* @deprecated No-op. Tools are passed per-call via SendMessageOptions.tools.
|
|
2985
|
+
* Kept for backward compatibility with code that calls setTools() directly.
|
|
2986
|
+
*/
|
|
2987
|
+
setTools() {
|
|
2988
|
+
}
|
|
3006
2989
|
async sendMessage(session, message, options) {
|
|
3007
2990
|
this.assertNotDisposed();
|
|
3008
2991
|
const events = this.streamMessage(session, message, options);
|
|
@@ -3040,9 +3023,13 @@ var BaseBackendAdapter = class {
|
|
|
3040
3023
|
*/
|
|
3041
3024
|
async *streamAgentEvents(agent, messages, options) {
|
|
3042
3025
|
const messageId = createChatId();
|
|
3026
|
+
const model = options?.model ?? this._agentConfig.model ?? "";
|
|
3043
3027
|
const agentEvents = agent.streamWithContext(messages, {
|
|
3028
|
+
model,
|
|
3044
3029
|
signal: options?.signal,
|
|
3045
|
-
context: options?.context
|
|
3030
|
+
context: options?.context,
|
|
3031
|
+
tools: options?.tools,
|
|
3032
|
+
...options?.systemPrompt ? { systemMessage: options.systemPrompt } : {}
|
|
3046
3033
|
});
|
|
3047
3034
|
yield { type: "message:start", messageId, role: "assistant" };
|
|
3048
3035
|
let text = "";
|
|
@@ -3068,31 +3055,45 @@ var BaseBackendAdapter = class {
|
|
|
3068
3055
|
}
|
|
3069
3056
|
async listModels() {
|
|
3070
3057
|
this.assertNotDisposed();
|
|
3071
|
-
return this.
|
|
3058
|
+
return this.agentService.listModels();
|
|
3072
3059
|
}
|
|
3073
3060
|
async validate() {
|
|
3074
3061
|
this.assertNotDisposed();
|
|
3075
|
-
return this.
|
|
3062
|
+
return this.agentService.validate();
|
|
3076
3063
|
}
|
|
3077
3064
|
async dispose() {
|
|
3078
3065
|
if (this._disposed) return;
|
|
3079
3066
|
this._disposed = true;
|
|
3080
|
-
this.
|
|
3081
|
-
|
|
3082
|
-
|
|
3067
|
+
if (this._currentAgent) {
|
|
3068
|
+
this._currentAgent.instance.dispose();
|
|
3069
|
+
this._currentAgent = null;
|
|
3070
|
+
}
|
|
3071
|
+
if (this._ownsService && this._agentService && typeof this._agentService.dispose === "function") {
|
|
3083
3072
|
await this._agentService.dispose();
|
|
3084
3073
|
}
|
|
3085
3074
|
}
|
|
3086
|
-
/** Get or create an agent
|
|
3075
|
+
/** Get or create an agent. Model is passed per-call via RunOptions.
|
|
3076
|
+
* Tools are passed per-call via SendMessageOptions — not baked into config.
|
|
3077
|
+
* For persistent sessions, reuses agent when model matches. */
|
|
3087
3078
|
getOrCreateAgent(options) {
|
|
3088
|
-
const
|
|
3089
|
-
if (this._agentConfig.sessionMode === "persistent" && this.
|
|
3090
|
-
|
|
3079
|
+
const model = options?.model ?? this._agentConfig.model;
|
|
3080
|
+
if (this._agentConfig.sessionMode === "persistent" && this._currentAgent) {
|
|
3081
|
+
if (this._currentAgent.model === model) {
|
|
3082
|
+
return this._currentAgent.instance;
|
|
3083
|
+
}
|
|
3084
|
+
this._currentAgent.instance.dispose();
|
|
3085
|
+
this._currentAgent = null;
|
|
3091
3086
|
}
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
this.
|
|
3087
|
+
if (this._currentAgent) {
|
|
3088
|
+
this._currentAgent.instance.dispose();
|
|
3089
|
+
this._currentAgent = null;
|
|
3095
3090
|
}
|
|
3091
|
+
const config = {
|
|
3092
|
+
...this._agentConfig,
|
|
3093
|
+
...model !== void 0 && { model }
|
|
3094
|
+
};
|
|
3095
|
+
const agent = this.agentService.createAgent(config);
|
|
3096
|
+
this._currentAgent = { instance: agent, model };
|
|
3096
3097
|
return agent;
|
|
3097
3098
|
}
|
|
3098
3099
|
assertNotDisposed() {
|
|
@@ -3117,8 +3118,8 @@ var CopilotChatAdapter = class extends BaseBackendAdapter {
|
|
|
3117
3118
|
this._copilotOptions = options.copilotOptions;
|
|
3118
3119
|
}
|
|
3119
3120
|
createService() {
|
|
3120
|
-
const {
|
|
3121
|
-
return
|
|
3121
|
+
const { createCopilotService: createCopilotService2 } = (init_copilot(), __toCommonJS(copilot_exports));
|
|
3122
|
+
return createCopilotService2(this._copilotOptions || {});
|
|
3122
3123
|
}
|
|
3123
3124
|
get backendSessionId() {
|
|
3124
3125
|
return this._backendSessionId;
|
|
@@ -3170,8 +3171,8 @@ var ClaudeChatAdapter = class extends BaseBackendAdapter {
|
|
|
3170
3171
|
this._claudeOptions = options.claudeOptions;
|
|
3171
3172
|
}
|
|
3172
3173
|
createService() {
|
|
3173
|
-
const {
|
|
3174
|
-
return
|
|
3174
|
+
const { createClaudeService: createClaudeService2 } = (init_claude(), __toCommonJS(claude_exports));
|
|
3175
|
+
return createClaudeService2(this._claudeOptions || {});
|
|
3175
3176
|
}
|
|
3176
3177
|
get backendSessionId() {
|
|
3177
3178
|
return this._backendSessionId;
|
|
@@ -3218,20 +3219,8 @@ var VercelAIChatAdapter = class extends BaseBackendAdapter {
|
|
|
3218
3219
|
this._vercelOptions = options.vercelOptions;
|
|
3219
3220
|
}
|
|
3220
3221
|
createService() {
|
|
3221
|
-
const {
|
|
3222
|
-
return
|
|
3223
|
-
}
|
|
3224
|
-
get backendSessionId() {
|
|
3225
|
-
return null;
|
|
3226
|
-
}
|
|
3227
|
-
canResume() {
|
|
3228
|
-
return false;
|
|
3229
|
-
}
|
|
3230
|
-
async *resume(_session, _backendSessionId, _options) {
|
|
3231
|
-
throw new ChatError(
|
|
3232
|
-
"Vercel AI adapter does not support session resume (stateless)",
|
|
3233
|
-
{ code: "PROVIDER_ERROR" /* PROVIDER_ERROR */ }
|
|
3234
|
-
);
|
|
3222
|
+
const { createVercelAIService: createVercelAIService2 } = (init_vercel_ai(), __toCommonJS(vercel_ai_exports));
|
|
3223
|
+
return createVercelAIService2(this._vercelOptions || {});
|
|
3235
3224
|
}
|
|
3236
3225
|
captureSessionId(_agent) {
|
|
3237
3226
|
}
|
|
@@ -3412,9 +3401,9 @@ var InProcessChatTransport = class {
|
|
|
3412
3401
|
send(event) {
|
|
3413
3402
|
if (!this._open) return;
|
|
3414
3403
|
if (this._resolve) {
|
|
3415
|
-
const
|
|
3404
|
+
const resolve = this._resolve;
|
|
3416
3405
|
this._resolve = null;
|
|
3417
|
-
|
|
3406
|
+
resolve({ value: event, done: false });
|
|
3418
3407
|
} else {
|
|
3419
3408
|
this._buffer.push(event);
|
|
3420
3409
|
}
|
|
@@ -3423,9 +3412,9 @@ var InProcessChatTransport = class {
|
|
|
3423
3412
|
if (!this._open) return;
|
|
3424
3413
|
this._open = false;
|
|
3425
3414
|
if (this._resolve) {
|
|
3426
|
-
const
|
|
3415
|
+
const resolve = this._resolve;
|
|
3427
3416
|
this._resolve = null;
|
|
3428
|
-
|
|
3417
|
+
resolve({ value: void 0, done: true });
|
|
3429
3418
|
}
|
|
3430
3419
|
}
|
|
3431
3420
|
error(err) {
|
|
@@ -3437,9 +3426,9 @@ var InProcessChatTransport = class {
|
|
|
3437
3426
|
recoverable: false
|
|
3438
3427
|
};
|
|
3439
3428
|
if (this._resolve) {
|
|
3440
|
-
const
|
|
3429
|
+
const resolve = this._resolve;
|
|
3441
3430
|
this._resolve = null;
|
|
3442
|
-
|
|
3431
|
+
resolve({ value: errorEvent, done: false });
|
|
3443
3432
|
} else {
|
|
3444
3433
|
this._error = err;
|
|
3445
3434
|
}
|
|
@@ -3464,8 +3453,8 @@ var InProcessChatTransport = class {
|
|
|
3464
3453
|
if (!this._open) {
|
|
3465
3454
|
return Promise.resolve({ value: void 0, done: true });
|
|
3466
3455
|
}
|
|
3467
|
-
return new Promise((
|
|
3468
|
-
this._resolve =
|
|
3456
|
+
return new Promise((resolve) => {
|
|
3457
|
+
this._resolve = resolve;
|
|
3469
3458
|
});
|
|
3470
3459
|
}
|
|
3471
3460
|
};
|
|
@@ -3528,6 +3517,7 @@ exports.SSEChatTransport = SSEChatTransport;
|
|
|
3528
3517
|
exports.VercelAIChatAdapter = VercelAIChatAdapter;
|
|
3529
3518
|
exports.WS_READY_STATE = WS_READY_STATE;
|
|
3530
3519
|
exports.WsChatTransport = WsChatTransport;
|
|
3520
|
+
exports.isResumableBackend = isResumableBackend;
|
|
3531
3521
|
exports.streamToTransport = streamToTransport;
|
|
3532
3522
|
exports.withInterceptors = withInterceptors;
|
|
3533
3523
|
//# sourceMappingURL=backends.cjs.map
|