@oxygen-agent/cli 1.142.4 → 1.152.15
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 +1 -1
- package/dist/http-client.js +44 -28
- package/dist/index.js +690 -16
- package/node_modules/@oxygen/shared/dist/index.d.ts +24 -0
- package/node_modules/@oxygen/shared/dist/index.js +49 -0
- package/node_modules/@oxygen/shared/dist/linkedin-sequences.d.ts +83 -0
- package/node_modules/@oxygen/shared/dist/linkedin-sequences.js +268 -0
- package/node_modules/@oxygen/shared/dist/telemetry.d.ts +4 -1
- package/node_modules/@oxygen/shared/dist/telemetry.js +17 -5
- package/node_modules/@oxygen/shared/dist/version.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/version.js +1 -1
- package/node_modules/@oxygen/shared/dist/workflow-trigger-metadata.d.ts +2 -0
- package/node_modules/@oxygen/shared/dist/workflow-trigger-metadata.js +14 -0
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/http-client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OXYGEN_VERSION, OxygenError } from "@oxygen/shared";
|
|
1
|
+
import { OXYGEN_VERSION, OxygenError, isVersionGreater } from "@oxygen/shared";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { defaultApiUrl, loadCredentials } from "./credentials.js";
|
|
4
4
|
import { resolveCliUpdateGuidance } from "./runtime.js";
|
|
@@ -24,6 +24,9 @@ path, options = {}) {
|
|
|
24
24
|
const headers = {
|
|
25
25
|
Accept: "application/json",
|
|
26
26
|
"X-Oxygen-Trace-Id": traceId,
|
|
27
|
+
// Advertise the CLI version so the server can enforce its minimum-CLI floor
|
|
28
|
+
// even against clients that predate the client-side envelope gate.
|
|
29
|
+
"X-Oxygen-Client-Version": OXYGEN_VERSION,
|
|
27
30
|
};
|
|
28
31
|
addVercelProtectionBypassHeader(apiUrl, headers);
|
|
29
32
|
if (credentials?.token) {
|
|
@@ -83,9 +86,10 @@ path, options = {}) {
|
|
|
83
86
|
if (!response.ok || !envelope.ok) {
|
|
84
87
|
const failure = envelope;
|
|
85
88
|
const responseTraceId = response.headers.get("x-oxygen-trace-id") ?? traceId;
|
|
89
|
+
const details = withRetryAfterDetails(failure.error.details, response);
|
|
86
90
|
throw new OxygenError(failure.error.code, failure.error.message, {
|
|
87
|
-
details: withTraceDetails(
|
|
88
|
-
exitCode:
|
|
91
|
+
details: withTraceDetails(details, responseTraceId, compatibility, apiUrl),
|
|
92
|
+
exitCode: 1,
|
|
89
93
|
});
|
|
90
94
|
}
|
|
91
95
|
return envelope.data;
|
|
@@ -197,6 +201,43 @@ function readEnvelopeCompatibility(envelope) {
|
|
|
197
201
|
}
|
|
198
202
|
return compatibility;
|
|
199
203
|
}
|
|
204
|
+
// Surface the server's 429 backoff as a first-class `retry_after_seconds` detail
|
|
205
|
+
// so loop-driving callers can wait the right amount of time instead of dead-
|
|
206
|
+
// reckoning. Prefers a value the API already put in details; otherwise derives
|
|
207
|
+
// it from the RFC 6585 Retry-After header (or reset_at). Non-429 responses and
|
|
208
|
+
// unparseable values pass through untouched.
|
|
209
|
+
function withRetryAfterDetails(details, response) {
|
|
210
|
+
if (response.status !== 429)
|
|
211
|
+
return details;
|
|
212
|
+
const record = details && typeof details === "object" && !Array.isArray(details)
|
|
213
|
+
? details
|
|
214
|
+
: null;
|
|
215
|
+
if (record && typeof record.retry_after_seconds === "number")
|
|
216
|
+
return details;
|
|
217
|
+
const retryAfterSeconds = retryAfterSecondsFromResponse(response, record);
|
|
218
|
+
if (retryAfterSeconds === null)
|
|
219
|
+
return details;
|
|
220
|
+
if (record)
|
|
221
|
+
return { ...record, retry_after_seconds: retryAfterSeconds };
|
|
222
|
+
if (details === undefined)
|
|
223
|
+
return { retry_after_seconds: retryAfterSeconds };
|
|
224
|
+
return { details, retry_after_seconds: retryAfterSeconds };
|
|
225
|
+
}
|
|
226
|
+
function retryAfterSecondsFromResponse(response, details) {
|
|
227
|
+
const header = response.headers.get("retry-after");
|
|
228
|
+
if (header) {
|
|
229
|
+
const seconds = Number(header);
|
|
230
|
+
if (Number.isFinite(seconds) && seconds >= 0)
|
|
231
|
+
return Math.ceil(seconds);
|
|
232
|
+
}
|
|
233
|
+
const resetAt = details?.reset_at;
|
|
234
|
+
if (typeof resetAt === "string") {
|
|
235
|
+
const resetMs = Date.parse(resetAt);
|
|
236
|
+
if (!Number.isNaN(resetMs))
|
|
237
|
+
return Math.max(0, Math.ceil((resetMs - Date.now()) / 1000));
|
|
238
|
+
}
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
200
241
|
function withTraceDetails(details, traceId, compatibility, apiUrl) {
|
|
201
242
|
const serverVersion = compatibility.version;
|
|
202
243
|
const fields = {
|
|
@@ -225,31 +266,6 @@ function withTraceDetails(details, traceId, compatibility, apiUrl) {
|
|
|
225
266
|
...fields,
|
|
226
267
|
};
|
|
227
268
|
}
|
|
228
|
-
function isVersionGreater(left, right) {
|
|
229
|
-
const leftParts = parseSemver(left);
|
|
230
|
-
const rightParts = parseSemver(right);
|
|
231
|
-
if (!leftParts || !rightParts)
|
|
232
|
-
return false;
|
|
233
|
-
for (let index = 0; index < leftParts.length; index += 1) {
|
|
234
|
-
const leftPart = leftParts[index] ?? 0;
|
|
235
|
-
const rightPart = rightParts[index] ?? 0;
|
|
236
|
-
if (leftPart > rightPart)
|
|
237
|
-
return true;
|
|
238
|
-
if (leftPart < rightPart)
|
|
239
|
-
return false;
|
|
240
|
-
}
|
|
241
|
-
return false;
|
|
242
|
-
}
|
|
243
|
-
function parseSemver(value) {
|
|
244
|
-
const match = /^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(value);
|
|
245
|
-
if (!match)
|
|
246
|
-
return null;
|
|
247
|
-
return [
|
|
248
|
-
Number(match[1]),
|
|
249
|
-
Number(match[2]),
|
|
250
|
-
Number(match[3]),
|
|
251
|
-
];
|
|
252
|
-
}
|
|
253
269
|
function addVercelProtectionBypassHeader(apiUrl, headers) {
|
|
254
270
|
const secret = process.env.VERCEL_AUTOMATION_BYPASS_SECRET?.trim();
|
|
255
271
|
if (!secret)
|