@agent-api/sdk 1.2.1 → 1.2.2
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/CHANGELOG.md +7 -0
- package/README.md +3 -2
- package/dist/internal/http.js +47 -5
- package/dist/types/common.d.ts +2 -0
- package/dist/version.d.ts +2 -2
- package/dist/version.js +1 -1
- package/dist-cjs/internal/http.js +47 -5
- package/dist-cjs/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog — @agent-api/sdk
|
|
2
2
|
|
|
3
|
+
## 1.2.2
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Added `RequestOptions.signal` so CLI, TUI, and desktop integrations can abort in-flight HTTP requests and response streams before a response ID is available.
|
|
8
|
+
- Documented and tested response cancellation behavior alongside the existing `responses.cancel(responseID)` backend cancellation API.
|
|
9
|
+
|
|
3
10
|
## 1.2.1
|
|
4
11
|
|
|
5
12
|
### Added
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Production JavaScript/TypeScript SDK for the Managed Agent API.
|
|
4
4
|
|
|
5
|
-
**Published on npm:** [`@agent-api/sdk`](https://www.npmjs.com/package/@agent-api/sdk) (v1.2.
|
|
5
|
+
**Published on npm:** [`@agent-api/sdk`](https://www.npmjs.com/package/@agent-api/sdk) (v1.2.2)
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -257,6 +257,7 @@ const context = await createLocalContextPackage(project, {
|
|
|
257
257
|
|
|
258
258
|
- **Retries:** automatic exponential backoff for network failures, 429, and 5xx (default 2 retries).
|
|
259
259
|
- **Timeouts:** 10 minute default for requests; 1 hour for streaming agent runs (configurable via `timeout` / `streamTimeout`).
|
|
260
|
+
- **Cancellation:** pass `signal` in request options to abort local HTTP waiting, and call `client.responses.cancel(responseID)` for backend best-effort cancellation after a response ID exists.
|
|
260
261
|
- **Typed errors:** `AuthenticationError`, `RateLimitError`, `NotFoundError`, `BadRequestError`, etc.
|
|
261
262
|
- **Pagination:** `listPage` returns a cursor page; `listIterator` auto-fetches all pages.
|
|
262
263
|
|
|
@@ -273,7 +274,7 @@ const stream = await client.responses.create({
|
|
|
273
274
|
preset: "fast-search",
|
|
274
275
|
input: "Summarize today's AI news.",
|
|
275
276
|
stream: true,
|
|
276
|
-
});
|
|
277
|
+
}, { signal: abortController.signal });
|
|
277
278
|
|
|
278
279
|
for await (const event of stream) {
|
|
279
280
|
if (event.type === "response.output_text.delta") {
|
package/dist/internal/http.js
CHANGED
|
@@ -33,6 +33,9 @@ export class HTTPClient {
|
|
|
33
33
|
return await this.fetchOnce(method, path, body, options, stream, rawBody);
|
|
34
34
|
}
|
|
35
35
|
catch (error) {
|
|
36
|
+
if (options.signal?.aborted) {
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
36
39
|
if (!(error instanceof APIError) || attempt >= maxRetries) {
|
|
37
40
|
throw error;
|
|
38
41
|
}
|
|
@@ -43,14 +46,29 @@ export class HTTPClient {
|
|
|
43
46
|
}
|
|
44
47
|
attempt += 1;
|
|
45
48
|
const delayMs = retryDelayMs(error, attempt);
|
|
46
|
-
await sleep(delayMs);
|
|
49
|
+
await sleep(delayMs, options.signal);
|
|
47
50
|
}
|
|
48
51
|
}
|
|
49
52
|
}
|
|
50
53
|
async fetchOnce(method, path, body, options, stream, rawBody) {
|
|
51
54
|
const controller = new AbortController();
|
|
52
55
|
const timeout = options.timeout ?? (stream ? this.options.streamTimeout : this.options.timeout);
|
|
53
|
-
|
|
56
|
+
let timedOut = false;
|
|
57
|
+
let callerAborted = options.signal?.aborted ?? false;
|
|
58
|
+
const timeoutID = setTimeout(() => {
|
|
59
|
+
timedOut = true;
|
|
60
|
+
controller.abort();
|
|
61
|
+
}, timeout);
|
|
62
|
+
const abortFromCaller = () => {
|
|
63
|
+
callerAborted = true;
|
|
64
|
+
controller.abort();
|
|
65
|
+
};
|
|
66
|
+
if (options.signal?.aborted) {
|
|
67
|
+
controller.abort();
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
options.signal?.addEventListener("abort", abortFromCaller, { once: true });
|
|
71
|
+
}
|
|
54
72
|
try {
|
|
55
73
|
const headers = {
|
|
56
74
|
Accept: stream ? "text/event-stream" : "application/json",
|
|
@@ -80,12 +98,19 @@ export class HTTPClient {
|
|
|
80
98
|
throw error;
|
|
81
99
|
}
|
|
82
100
|
if (error instanceof Error && error.name === "AbortError") {
|
|
83
|
-
|
|
101
|
+
if (callerAborted || options.signal?.aborted) {
|
|
102
|
+
throw new APIConnectionError("Request aborted", error);
|
|
103
|
+
}
|
|
104
|
+
if (timedOut) {
|
|
105
|
+
throw new APIConnectionError(`Request timed out after ${timeout}ms`, error);
|
|
106
|
+
}
|
|
107
|
+
throw new APIConnectionError("Request aborted", error);
|
|
84
108
|
}
|
|
85
109
|
throw new APIConnectionError("Request failed", error);
|
|
86
110
|
}
|
|
87
111
|
finally {
|
|
88
112
|
clearTimeout(timeoutID);
|
|
113
|
+
options.signal?.removeEventListener("abort", abortFromCaller);
|
|
89
114
|
}
|
|
90
115
|
}
|
|
91
116
|
}
|
|
@@ -99,6 +124,23 @@ function retryDelayMs(error, attempt) {
|
|
|
99
124
|
const jitter = Math.floor(Math.random() * 100);
|
|
100
125
|
return exponential + jitter;
|
|
101
126
|
}
|
|
102
|
-
function sleep(ms) {
|
|
103
|
-
|
|
127
|
+
function sleep(ms, signal) {
|
|
128
|
+
if (!signal) {
|
|
129
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
130
|
+
}
|
|
131
|
+
if (signal.aborted) {
|
|
132
|
+
return Promise.reject(new APIConnectionError("Request aborted"));
|
|
133
|
+
}
|
|
134
|
+
return new Promise((resolve, reject) => {
|
|
135
|
+
const timeout = setTimeout(() => {
|
|
136
|
+
signal.removeEventListener("abort", abort);
|
|
137
|
+
resolve();
|
|
138
|
+
}, ms);
|
|
139
|
+
const abort = () => {
|
|
140
|
+
clearTimeout(timeout);
|
|
141
|
+
signal.removeEventListener("abort", abort);
|
|
142
|
+
reject(new APIConnectionError("Request aborted"));
|
|
143
|
+
};
|
|
144
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
145
|
+
});
|
|
104
146
|
}
|
package/dist/types/common.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ export interface ClientOptions {
|
|
|
20
20
|
export interface RequestOptions {
|
|
21
21
|
headers?: Record<string, string>;
|
|
22
22
|
timeout?: number;
|
|
23
|
+
/** Abort the underlying HTTP request or stream from caller-controlled UI/runtime state. */
|
|
24
|
+
signal?: AbortSignal;
|
|
23
25
|
/** Override automatic retries for this request. */
|
|
24
26
|
maxRetries?: number;
|
|
25
27
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "1.2.
|
|
2
|
-
export declare const USER_AGENT = "@agent-api/sdk/1.2.
|
|
1
|
+
export declare const VERSION = "1.2.2";
|
|
2
|
+
export declare const USER_AGENT = "@agent-api/sdk/1.2.2";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = "1.2.
|
|
1
|
+
export const VERSION = "1.2.2";
|
|
2
2
|
export const USER_AGENT = `@agent-api/sdk/${VERSION}`;
|
|
@@ -36,6 +36,9 @@ class HTTPClient {
|
|
|
36
36
|
return await this.fetchOnce(method, path, body, options, stream, rawBody);
|
|
37
37
|
}
|
|
38
38
|
catch (error) {
|
|
39
|
+
if (options.signal?.aborted) {
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
39
42
|
if (!(error instanceof errors_js_1.APIError) || attempt >= maxRetries) {
|
|
40
43
|
throw error;
|
|
41
44
|
}
|
|
@@ -46,14 +49,29 @@ class HTTPClient {
|
|
|
46
49
|
}
|
|
47
50
|
attempt += 1;
|
|
48
51
|
const delayMs = retryDelayMs(error, attempt);
|
|
49
|
-
await sleep(delayMs);
|
|
52
|
+
await sleep(delayMs, options.signal);
|
|
50
53
|
}
|
|
51
54
|
}
|
|
52
55
|
}
|
|
53
56
|
async fetchOnce(method, path, body, options, stream, rawBody) {
|
|
54
57
|
const controller = new AbortController();
|
|
55
58
|
const timeout = options.timeout ?? (stream ? this.options.streamTimeout : this.options.timeout);
|
|
56
|
-
|
|
59
|
+
let timedOut = false;
|
|
60
|
+
let callerAborted = options.signal?.aborted ?? false;
|
|
61
|
+
const timeoutID = setTimeout(() => {
|
|
62
|
+
timedOut = true;
|
|
63
|
+
controller.abort();
|
|
64
|
+
}, timeout);
|
|
65
|
+
const abortFromCaller = () => {
|
|
66
|
+
callerAborted = true;
|
|
67
|
+
controller.abort();
|
|
68
|
+
};
|
|
69
|
+
if (options.signal?.aborted) {
|
|
70
|
+
controller.abort();
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
options.signal?.addEventListener("abort", abortFromCaller, { once: true });
|
|
74
|
+
}
|
|
57
75
|
try {
|
|
58
76
|
const headers = {
|
|
59
77
|
Accept: stream ? "text/event-stream" : "application/json",
|
|
@@ -83,12 +101,19 @@ class HTTPClient {
|
|
|
83
101
|
throw error;
|
|
84
102
|
}
|
|
85
103
|
if (error instanceof Error && error.name === "AbortError") {
|
|
86
|
-
|
|
104
|
+
if (callerAborted || options.signal?.aborted) {
|
|
105
|
+
throw new errors_js_1.APIConnectionError("Request aborted", error);
|
|
106
|
+
}
|
|
107
|
+
if (timedOut) {
|
|
108
|
+
throw new errors_js_1.APIConnectionError(`Request timed out after ${timeout}ms`, error);
|
|
109
|
+
}
|
|
110
|
+
throw new errors_js_1.APIConnectionError("Request aborted", error);
|
|
87
111
|
}
|
|
88
112
|
throw new errors_js_1.APIConnectionError("Request failed", error);
|
|
89
113
|
}
|
|
90
114
|
finally {
|
|
91
115
|
clearTimeout(timeoutID);
|
|
116
|
+
options.signal?.removeEventListener("abort", abortFromCaller);
|
|
92
117
|
}
|
|
93
118
|
}
|
|
94
119
|
}
|
|
@@ -103,6 +128,23 @@ function retryDelayMs(error, attempt) {
|
|
|
103
128
|
const jitter = Math.floor(Math.random() * 100);
|
|
104
129
|
return exponential + jitter;
|
|
105
130
|
}
|
|
106
|
-
function sleep(ms) {
|
|
107
|
-
|
|
131
|
+
function sleep(ms, signal) {
|
|
132
|
+
if (!signal) {
|
|
133
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
134
|
+
}
|
|
135
|
+
if (signal.aborted) {
|
|
136
|
+
return Promise.reject(new errors_js_1.APIConnectionError("Request aborted"));
|
|
137
|
+
}
|
|
138
|
+
return new Promise((resolve, reject) => {
|
|
139
|
+
const timeout = setTimeout(() => {
|
|
140
|
+
signal.removeEventListener("abort", abort);
|
|
141
|
+
resolve();
|
|
142
|
+
}, ms);
|
|
143
|
+
const abort = () => {
|
|
144
|
+
clearTimeout(timeout);
|
|
145
|
+
signal.removeEventListener("abort", abort);
|
|
146
|
+
reject(new errors_js_1.APIConnectionError("Request aborted"));
|
|
147
|
+
};
|
|
148
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
149
|
+
});
|
|
108
150
|
}
|
package/dist-cjs/version.js
CHANGED