@aexhq/sdk 0.40.10 → 0.40.11
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/dist/_contracts/http.d.ts +11 -0
- package/dist/_contracts/http.js +119 -39
- package/dist/cli.mjs +116 -36
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -18,6 +18,17 @@ export interface HttpClientOptions {
|
|
|
18
18
|
readonly fetch?: FetchLike;
|
|
19
19
|
/** When set, every request emits a redacted one-line trace here. */
|
|
20
20
|
readonly debug?: DebugSink;
|
|
21
|
+
/**
|
|
22
|
+
* Retry transient transport failures for idempotent GET/HEAD requests.
|
|
23
|
+
* Disabled by default; host CLIs enable this so a single dropped API
|
|
24
|
+
* connection does not fail read-only commands.
|
|
25
|
+
*/
|
|
26
|
+
readonly retryTransientGets?: boolean | TransientGetRetryOptions;
|
|
27
|
+
}
|
|
28
|
+
export interface TransientGetRetryOptions {
|
|
29
|
+
readonly maxAttempts?: number;
|
|
30
|
+
readonly baseDelayMs?: number;
|
|
31
|
+
readonly sleep?: (ms: number) => Promise<void>;
|
|
21
32
|
}
|
|
22
33
|
/**
|
|
23
34
|
* Thin transport used by every BFF-bound operation. The SDK class and
|
package/dist/_contracts/http.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AexError, AexNetworkError, redactUrl } from "./sdk-errors.js";
|
|
1
|
+
import { AexError, AexNetworkError, extractErrorCode, redactUrl } from "./sdk-errors.js";
|
|
2
2
|
import { apiErrorFromResponse } from "./error-factory.js";
|
|
3
3
|
import { AEX_DEFAULT_BASE_URL } from "./stable.js";
|
|
4
4
|
/**
|
|
@@ -12,6 +12,7 @@ export class HttpClient {
|
|
|
12
12
|
#apiKey;
|
|
13
13
|
#fetch;
|
|
14
14
|
#debug;
|
|
15
|
+
#retryTransientGets;
|
|
15
16
|
constructor(options) {
|
|
16
17
|
if (!options.apiKey) {
|
|
17
18
|
throw new Error("HttpClient: apiKey is required");
|
|
@@ -28,6 +29,7 @@ export class HttpClient {
|
|
|
28
29
|
this.#apiKey = options.apiKey;
|
|
29
30
|
this.#fetch = options.fetch ?? fetch;
|
|
30
31
|
this.#debug = options.debug;
|
|
32
|
+
this.#retryTransientGets = resolveTransientGetRetry(options.retryTransientGets);
|
|
31
33
|
}
|
|
32
34
|
/** Emit a redacted round-trip trace (no auth header, body, or query). */
|
|
33
35
|
#trace(method, url, status, startedMs) {
|
|
@@ -52,25 +54,34 @@ export class HttpClient {
|
|
|
52
54
|
headers["content-type"] = "application/json";
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
57
|
+
const method = methodOf(init.method);
|
|
58
|
+
const retry = retryForMethod(method, this.#retryTransientGets);
|
|
59
|
+
const requestStartedMs = Date.now();
|
|
60
|
+
for (let attempt = 1; attempt <= retry.maxAttempts; attempt += 1) {
|
|
61
|
+
const startedMs = Date.now();
|
|
62
|
+
try {
|
|
63
|
+
const response = await this.#fetch(url, { ...init, headers });
|
|
64
|
+
this.#trace(method, url, response.status, startedMs);
|
|
65
|
+
const body = await readJson(response);
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
const errorBody = withResponseRequestId(body, response.headers);
|
|
68
|
+
throw apiErrorFromResponse({
|
|
69
|
+
status: response.status,
|
|
70
|
+
body: errorBody,
|
|
71
|
+
message: extractErrorMessage(errorBody)
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return body;
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
if (shouldRetryTransientRead(err, retry, attempt)) {
|
|
78
|
+
await sleepBeforeRetry(this.#debug, method, url, err, retry, attempt);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
throw toNetworkError(method, url, err, retry.maxAttempts > 1 ? attempt : undefined, Date.now() - requestStartedMs);
|
|
82
|
+
}
|
|
72
83
|
}
|
|
73
|
-
|
|
84
|
+
throw new Error("HttpClient.request retry loop exhausted");
|
|
74
85
|
}
|
|
75
86
|
async download(path, init = {}, query = {}) {
|
|
76
87
|
const url = new URL(path.replace(/^\//, ""), this.#baseUrl);
|
|
@@ -81,26 +92,93 @@ export class HttpClient {
|
|
|
81
92
|
authorization: `Bearer ${this.#apiKey}`,
|
|
82
93
|
...normalizeHeaders(init.headers)
|
|
83
94
|
};
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
95
|
+
const method = methodOf(init.method);
|
|
96
|
+
const retry = retryForMethod(method, this.#retryTransientGets);
|
|
97
|
+
const requestStartedMs = Date.now();
|
|
98
|
+
for (let attempt = 1; attempt <= retry.maxAttempts; attempt += 1) {
|
|
99
|
+
const startedMs = Date.now();
|
|
100
|
+
try {
|
|
101
|
+
const response = await this.#fetch(url, { ...init, headers });
|
|
102
|
+
this.#trace(method, url, response.status, startedMs);
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
const body = await readJson(response);
|
|
105
|
+
const errorBody = withResponseRequestId(body, response.headers);
|
|
106
|
+
throw apiErrorFromResponse({
|
|
107
|
+
status: response.status,
|
|
108
|
+
body: errorBody,
|
|
109
|
+
message: extractErrorMessage(errorBody)
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return { response };
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
if (shouldRetryTransientRead(err, retry, attempt)) {
|
|
116
|
+
await sleepBeforeRetry(this.#debug, method, url, err, retry, attempt);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
throw toNetworkError(method, url, err, retry.maxAttempts > 1 ? attempt : undefined, Date.now() - requestStartedMs);
|
|
120
|
+
}
|
|
101
121
|
}
|
|
102
|
-
|
|
122
|
+
throw new Error("HttpClient.download retry loop exhausted");
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const DEFAULT_TRANSIENT_GET_RETRY = {
|
|
126
|
+
maxAttempts: 3,
|
|
127
|
+
baseDelayMs: 250,
|
|
128
|
+
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms))
|
|
129
|
+
};
|
|
130
|
+
const TRANSIENT_READ_CODES = new Set([
|
|
131
|
+
"ConnectionRefused",
|
|
132
|
+
"ECONNRESET",
|
|
133
|
+
"ECONNREFUSED",
|
|
134
|
+
"ETIMEDOUT",
|
|
135
|
+
"EAI_AGAIN",
|
|
136
|
+
"UND_ERR_CONNECT_TIMEOUT",
|
|
137
|
+
"UND_ERR_HEADERS_TIMEOUT",
|
|
138
|
+
"UND_ERR_SOCKET",
|
|
139
|
+
"UND_ERR_BODY_TIMEOUT"
|
|
140
|
+
]);
|
|
141
|
+
function resolveTransientGetRetry(retry) {
|
|
142
|
+
if (!retry)
|
|
143
|
+
return null;
|
|
144
|
+
if (retry === true)
|
|
145
|
+
return DEFAULT_TRANSIENT_GET_RETRY;
|
|
146
|
+
return {
|
|
147
|
+
maxAttempts: Math.max(1, retry.maxAttempts ?? DEFAULT_TRANSIENT_GET_RETRY.maxAttempts),
|
|
148
|
+
baseDelayMs: Math.max(0, retry.baseDelayMs ?? DEFAULT_TRANSIENT_GET_RETRY.baseDelayMs),
|
|
149
|
+
sleep: retry.sleep ?? DEFAULT_TRANSIENT_GET_RETRY.sleep
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function methodOf(method) {
|
|
153
|
+
return (method ?? "GET").toUpperCase();
|
|
154
|
+
}
|
|
155
|
+
function retryForMethod(method, retry) {
|
|
156
|
+
if (!retry || (method !== "GET" && method !== "HEAD")) {
|
|
157
|
+
return { ...DEFAULT_TRANSIENT_GET_RETRY, maxAttempts: 1 };
|
|
103
158
|
}
|
|
159
|
+
return retry;
|
|
160
|
+
}
|
|
161
|
+
function shouldRetryTransientRead(err, retry, attempt) {
|
|
162
|
+
return attempt < retry.maxAttempts && transientReadErrorCode(err) !== undefined;
|
|
163
|
+
}
|
|
164
|
+
async function sleepBeforeRetry(debug, method, url, err, retry, attempt) {
|
|
165
|
+
const delayMs = retry.baseDelayMs * attempt;
|
|
166
|
+
debug?.(`[aex] ${method} ${url.pathname} transient ${transientReadErrorCode(err) ?? "network"} ` +
|
|
167
|
+
`attempt ${attempt}/${retry.maxAttempts}; retrying in ${delayMs}ms`);
|
|
168
|
+
await retry.sleep(delayMs);
|
|
169
|
+
}
|
|
170
|
+
function transientReadErrorCode(err) {
|
|
171
|
+
if (err instanceof AexError)
|
|
172
|
+
return undefined;
|
|
173
|
+
if (err?.name === "AbortError")
|
|
174
|
+
return undefined;
|
|
175
|
+
const code = extractErrorCode(err);
|
|
176
|
+
if (code && TRANSIENT_READ_CODES.has(code))
|
|
177
|
+
return code;
|
|
178
|
+
const text = err instanceof Error ? `${err.name}: ${err.message}` : String(err);
|
|
179
|
+
if (/fetch failed|socket hang up|other side closed|terminated|network.*reset/i.test(text))
|
|
180
|
+
return "fetch";
|
|
181
|
+
return undefined;
|
|
104
182
|
}
|
|
105
183
|
/**
|
|
106
184
|
* Wrap a fetch rejection into an {@link AexNetworkError} carrying the
|
|
@@ -108,7 +186,7 @@ export class HttpClient {
|
|
|
108
186
|
* already-structured aex errors (e.g. a retry layer's AexRateLimitError or
|
|
109
187
|
* AexNetworkError) pass through untouched.
|
|
110
188
|
*/
|
|
111
|
-
function toNetworkError(method, url, err) {
|
|
189
|
+
function toNetworkError(method, url, err, attempts, elapsedMs) {
|
|
112
190
|
if (err instanceof AexError)
|
|
113
191
|
return err;
|
|
114
192
|
// `DOMException` is not an `Error` subclass on every runtime, so match aborts by name.
|
|
@@ -118,7 +196,9 @@ function toNetworkError(method, url, err) {
|
|
|
118
196
|
method: (method ?? "GET").toUpperCase(),
|
|
119
197
|
host: url.host,
|
|
120
198
|
path: url.pathname,
|
|
121
|
-
cause: err
|
|
199
|
+
cause: err,
|
|
200
|
+
...(attempts !== undefined ? { attempts } : {}),
|
|
201
|
+
...(elapsedMs !== undefined ? { elapsedMs } : {})
|
|
122
202
|
});
|
|
123
203
|
}
|
|
124
204
|
function normalizeHeaders(headers) {
|
package/dist/cli.mjs
CHANGED
|
@@ -2104,6 +2104,7 @@ var HttpClient = class {
|
|
|
2104
2104
|
#apiKey;
|
|
2105
2105
|
#fetch;
|
|
2106
2106
|
#debug;
|
|
2107
|
+
#retryTransientGets;
|
|
2107
2108
|
constructor(options) {
|
|
2108
2109
|
if (!options.apiKey) {
|
|
2109
2110
|
throw new Error("HttpClient: apiKey is required");
|
|
@@ -2118,6 +2119,7 @@ var HttpClient = class {
|
|
|
2118
2119
|
this.#apiKey = options.apiKey;
|
|
2119
2120
|
this.#fetch = options.fetch ?? fetch;
|
|
2120
2121
|
this.#debug = options.debug;
|
|
2122
|
+
this.#retryTransientGets = resolveTransientGetRetry(options.retryTransientGets);
|
|
2121
2123
|
}
|
|
2122
2124
|
/** Emit a redacted round-trip trace (no auth header, body, or query). */
|
|
2123
2125
|
#trace(method, url, status, startedMs) {
|
|
@@ -2138,24 +2140,33 @@ var HttpClient = class {
|
|
|
2138
2140
|
headers["content-type"] = "application/json";
|
|
2139
2141
|
}
|
|
2140
2142
|
}
|
|
2141
|
-
const
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2143
|
+
const method = methodOf(init.method);
|
|
2144
|
+
const retry = retryForMethod(method, this.#retryTransientGets);
|
|
2145
|
+
const requestStartedMs = Date.now();
|
|
2146
|
+
for (let attempt = 1; attempt <= retry.maxAttempts; attempt += 1) {
|
|
2147
|
+
const startedMs = Date.now();
|
|
2148
|
+
try {
|
|
2149
|
+
const response = await this.#fetch(url, { ...init, headers });
|
|
2150
|
+
this.#trace(method, url, response.status, startedMs);
|
|
2151
|
+
const body = await readJson(response);
|
|
2152
|
+
if (!response.ok) {
|
|
2153
|
+
const errorBody = withResponseRequestId(body, response.headers);
|
|
2154
|
+
throw apiErrorFromResponse({
|
|
2155
|
+
status: response.status,
|
|
2156
|
+
body: errorBody,
|
|
2157
|
+
message: extractErrorMessage(errorBody)
|
|
2158
|
+
});
|
|
2159
|
+
}
|
|
2160
|
+
return body;
|
|
2161
|
+
} catch (err2) {
|
|
2162
|
+
if (shouldRetryTransientRead(err2, retry, attempt)) {
|
|
2163
|
+
await sleepBeforeRetry(this.#debug, method, url, err2, retry, attempt);
|
|
2164
|
+
continue;
|
|
2165
|
+
}
|
|
2166
|
+
throw toNetworkError(method, url, err2, retry.maxAttempts > 1 ? attempt : void 0, Date.now() - requestStartedMs);
|
|
2167
|
+
}
|
|
2157
2168
|
}
|
|
2158
|
-
|
|
2169
|
+
throw new Error("HttpClient.request retry loop exhausted");
|
|
2159
2170
|
}
|
|
2160
2171
|
async download(path, init = {}, query = {}) {
|
|
2161
2172
|
const url = new URL(path.replace(/^\//, ""), this.#baseUrl);
|
|
@@ -2166,27 +2177,93 @@ var HttpClient = class {
|
|
|
2166
2177
|
authorization: `Bearer ${this.#apiKey}`,
|
|
2167
2178
|
...normalizeHeaders(init.headers)
|
|
2168
2179
|
};
|
|
2169
|
-
const
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2180
|
+
const method = methodOf(init.method);
|
|
2181
|
+
const retry = retryForMethod(method, this.#retryTransientGets);
|
|
2182
|
+
const requestStartedMs = Date.now();
|
|
2183
|
+
for (let attempt = 1; attempt <= retry.maxAttempts; attempt += 1) {
|
|
2184
|
+
const startedMs = Date.now();
|
|
2185
|
+
try {
|
|
2186
|
+
const response = await this.#fetch(url, { ...init, headers });
|
|
2187
|
+
this.#trace(method, url, response.status, startedMs);
|
|
2188
|
+
if (!response.ok) {
|
|
2189
|
+
const body = await readJson(response);
|
|
2190
|
+
const errorBody = withResponseRequestId(body, response.headers);
|
|
2191
|
+
throw apiErrorFromResponse({
|
|
2192
|
+
status: response.status,
|
|
2193
|
+
body: errorBody,
|
|
2194
|
+
message: extractErrorMessage(errorBody)
|
|
2195
|
+
});
|
|
2196
|
+
}
|
|
2197
|
+
return { response };
|
|
2198
|
+
} catch (err2) {
|
|
2199
|
+
if (shouldRetryTransientRead(err2, retry, attempt)) {
|
|
2200
|
+
await sleepBeforeRetry(this.#debug, method, url, err2, retry, attempt);
|
|
2201
|
+
continue;
|
|
2202
|
+
}
|
|
2203
|
+
throw toNetworkError(method, url, err2, retry.maxAttempts > 1 ? attempt : void 0, Date.now() - requestStartedMs);
|
|
2204
|
+
}
|
|
2185
2205
|
}
|
|
2186
|
-
|
|
2206
|
+
throw new Error("HttpClient.download retry loop exhausted");
|
|
2187
2207
|
}
|
|
2188
2208
|
};
|
|
2189
|
-
|
|
2209
|
+
var DEFAULT_TRANSIENT_GET_RETRY = {
|
|
2210
|
+
maxAttempts: 3,
|
|
2211
|
+
baseDelayMs: 250,
|
|
2212
|
+
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms))
|
|
2213
|
+
};
|
|
2214
|
+
var TRANSIENT_READ_CODES = /* @__PURE__ */ new Set([
|
|
2215
|
+
"ConnectionRefused",
|
|
2216
|
+
"ECONNRESET",
|
|
2217
|
+
"ECONNREFUSED",
|
|
2218
|
+
"ETIMEDOUT",
|
|
2219
|
+
"EAI_AGAIN",
|
|
2220
|
+
"UND_ERR_CONNECT_TIMEOUT",
|
|
2221
|
+
"UND_ERR_HEADERS_TIMEOUT",
|
|
2222
|
+
"UND_ERR_SOCKET",
|
|
2223
|
+
"UND_ERR_BODY_TIMEOUT"
|
|
2224
|
+
]);
|
|
2225
|
+
function resolveTransientGetRetry(retry) {
|
|
2226
|
+
if (!retry)
|
|
2227
|
+
return null;
|
|
2228
|
+
if (retry === true)
|
|
2229
|
+
return DEFAULT_TRANSIENT_GET_RETRY;
|
|
2230
|
+
return {
|
|
2231
|
+
maxAttempts: Math.max(1, retry.maxAttempts ?? DEFAULT_TRANSIENT_GET_RETRY.maxAttempts),
|
|
2232
|
+
baseDelayMs: Math.max(0, retry.baseDelayMs ?? DEFAULT_TRANSIENT_GET_RETRY.baseDelayMs),
|
|
2233
|
+
sleep: retry.sleep ?? DEFAULT_TRANSIENT_GET_RETRY.sleep
|
|
2234
|
+
};
|
|
2235
|
+
}
|
|
2236
|
+
function methodOf(method) {
|
|
2237
|
+
return (method ?? "GET").toUpperCase();
|
|
2238
|
+
}
|
|
2239
|
+
function retryForMethod(method, retry) {
|
|
2240
|
+
if (!retry || method !== "GET" && method !== "HEAD") {
|
|
2241
|
+
return { ...DEFAULT_TRANSIENT_GET_RETRY, maxAttempts: 1 };
|
|
2242
|
+
}
|
|
2243
|
+
return retry;
|
|
2244
|
+
}
|
|
2245
|
+
function shouldRetryTransientRead(err2, retry, attempt) {
|
|
2246
|
+
return attempt < retry.maxAttempts && transientReadErrorCode(err2) !== void 0;
|
|
2247
|
+
}
|
|
2248
|
+
async function sleepBeforeRetry(debug2, method, url, err2, retry, attempt) {
|
|
2249
|
+
const delayMs = retry.baseDelayMs * attempt;
|
|
2250
|
+
debug2?.(`[aex] ${method} ${url.pathname} transient ${transientReadErrorCode(err2) ?? "network"} attempt ${attempt}/${retry.maxAttempts}; retrying in ${delayMs}ms`);
|
|
2251
|
+
await retry.sleep(delayMs);
|
|
2252
|
+
}
|
|
2253
|
+
function transientReadErrorCode(err2) {
|
|
2254
|
+
if (err2 instanceof AexError)
|
|
2255
|
+
return void 0;
|
|
2256
|
+
if (err2?.name === "AbortError")
|
|
2257
|
+
return void 0;
|
|
2258
|
+
const code = extractErrorCode(err2);
|
|
2259
|
+
if (code && TRANSIENT_READ_CODES.has(code))
|
|
2260
|
+
return code;
|
|
2261
|
+
const text = err2 instanceof Error ? `${err2.name}: ${err2.message}` : String(err2);
|
|
2262
|
+
if (/fetch failed|socket hang up|other side closed|terminated|network.*reset/i.test(text))
|
|
2263
|
+
return "fetch";
|
|
2264
|
+
return void 0;
|
|
2265
|
+
}
|
|
2266
|
+
function toNetworkError(method, url, err2, attempts, elapsedMs) {
|
|
2190
2267
|
if (err2 instanceof AexError)
|
|
2191
2268
|
return err2;
|
|
2192
2269
|
if (err2?.name === "AbortError")
|
|
@@ -2195,7 +2272,9 @@ function toNetworkError(method, url, err2) {
|
|
|
2195
2272
|
method: (method ?? "GET").toUpperCase(),
|
|
2196
2273
|
host: url.host,
|
|
2197
2274
|
path: url.pathname,
|
|
2198
|
-
cause: err2
|
|
2275
|
+
cause: err2,
|
|
2276
|
+
...attempts !== void 0 ? { attempts } : {},
|
|
2277
|
+
...elapsedMs !== void 0 ? { elapsedMs } : {}
|
|
2199
2278
|
});
|
|
2200
2279
|
}
|
|
2201
2280
|
function normalizeHeaders(headers) {
|
|
@@ -4202,6 +4281,7 @@ function makeHttpClient(io2, flags) {
|
|
|
4202
4281
|
return new HttpClient({
|
|
4203
4282
|
baseUrl: flags.aexUrl,
|
|
4204
4283
|
apiKey: flags.apiKey,
|
|
4284
|
+
retryTransientGets: true,
|
|
4205
4285
|
fetch: io2.fetchImpl,
|
|
4206
4286
|
// `--debug`: route the transport's redacted per-request traces to stderr.
|
|
4207
4287
|
...flags.debug ? { debug: (line) => io2.stderr(`${line}
|
package/dist/cli.mjs.sha256
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
383e87cd6909a7a5eb73b90a77c12b6adf78491678cdc14612d5cc878971458e cli.mjs
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aexhq/sdk",
|
|
3
|
-
"version": "0.40.
|
|
3
|
+
"version": "0.40.11",
|
|
4
4
|
"description": "TypeScript SDK for running autonomous agent sessions across providers (Anthropic, OpenAI, DeepSeek, Gemini, Mistral) behind one interface.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|