@zeroxyz/cli 1.7.0 → 1.9.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 +24 -2
- package/dist/index.js +1854 -1549
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -52631,12 +52631,12 @@ var require_array = __commonJS({
|
|
|
52631
52631
|
if (Array.isArray(values)) {
|
|
52632
52632
|
arrayValues = values;
|
|
52633
52633
|
} else if (values && typeof values === "object") {
|
|
52634
|
-
let
|
|
52634
|
+
let unique2 = {};
|
|
52635
52635
|
arrayValues = coders.map((coder) => {
|
|
52636
52636
|
const name = coder.localName;
|
|
52637
52637
|
(0, index_js_1.assert)(name, "cannot encode object for signature with missing names", "INVALID_ARGUMENT", { argument: "values", info: { coder }, value: values });
|
|
52638
|
-
(0, index_js_1.assert)(!
|
|
52639
|
-
|
|
52638
|
+
(0, index_js_1.assert)(!unique2[name], "cannot encode object for signature with duplicate names", "INVALID_ARGUMENT", { argument: "values", info: { coder }, value: values });
|
|
52639
|
+
unique2[name] = true;
|
|
52640
52640
|
return values[name];
|
|
52641
52641
|
});
|
|
52642
52642
|
} else {
|
|
@@ -55096,10 +55096,10 @@ var require_dist = __commonJS({
|
|
|
55096
55096
|
}
|
|
55097
55097
|
}
|
|
55098
55098
|
check_fenced(norm);
|
|
55099
|
-
let
|
|
55100
|
-
let [g2] = determine_group(
|
|
55099
|
+
let unique2 = Array_from(new Set(chars));
|
|
55100
|
+
let [g2] = determine_group(unique2);
|
|
55101
55101
|
check_group(g2, chars);
|
|
55102
|
-
check_whole(g2,
|
|
55102
|
+
check_whole(g2, unique2);
|
|
55103
55103
|
type2 = g2.N;
|
|
55104
55104
|
}
|
|
55105
55105
|
}
|
|
@@ -55110,10 +55110,10 @@ var require_dist = __commonJS({
|
|
|
55110
55110
|
return info;
|
|
55111
55111
|
});
|
|
55112
55112
|
}
|
|
55113
|
-
function check_whole(group,
|
|
55113
|
+
function check_whole(group, unique2) {
|
|
55114
55114
|
let maker;
|
|
55115
55115
|
let shared = [];
|
|
55116
|
-
for (let cp of
|
|
55116
|
+
for (let cp of unique2) {
|
|
55117
55117
|
let whole = WHOLE_MAP.get(cp);
|
|
55118
55118
|
if (whole === UNIQUE_PH) return;
|
|
55119
55119
|
if (whole) {
|
|
@@ -55132,9 +55132,9 @@ var require_dist = __commonJS({
|
|
|
55132
55132
|
}
|
|
55133
55133
|
}
|
|
55134
55134
|
}
|
|
55135
|
-
function determine_group(
|
|
55135
|
+
function determine_group(unique2) {
|
|
55136
55136
|
let groups = GROUPS;
|
|
55137
|
-
for (let cp of
|
|
55137
|
+
for (let cp of unique2) {
|
|
55138
55138
|
let gs = groups.filter((g2) => group_has_cp(g2, cp));
|
|
55139
55139
|
if (!gs.length) {
|
|
55140
55140
|
if (!GROUPS.some((g2) => group_has_cp(g2, cp))) {
|
|
@@ -76582,7 +76582,7 @@ init_esm_shims();
|
|
|
76582
76582
|
|
|
76583
76583
|
// package.json
|
|
76584
76584
|
var package_default = {
|
|
76585
|
-
version: "1.
|
|
76585
|
+
version: "1.9.0"};
|
|
76586
76586
|
|
|
76587
76587
|
// src/app.ts
|
|
76588
76588
|
init_esm_shims();
|
|
@@ -77590,7 +77590,7 @@ init_esm_shims();
|
|
|
77590
77590
|
// ../sdk/dist/index.js
|
|
77591
77591
|
init_esm_shims();
|
|
77592
77592
|
|
|
77593
|
-
// ../sdk/dist/chunk-
|
|
77593
|
+
// ../sdk/dist/chunk-26IHUYNK.js
|
|
77594
77594
|
init_esm_shims();
|
|
77595
77595
|
|
|
77596
77596
|
// ../../node_modules/.pnpm/viem@2.52.2_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@6.0.6_zod@4.3.6/node_modules/viem/_esm/index.js
|
|
@@ -142971,6 +142971,8 @@ config(en_default2());
|
|
|
142971
142971
|
|
|
142972
142972
|
// ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/index.js
|
|
142973
142973
|
var zod_default = external_exports3;
|
|
142974
|
+
|
|
142975
|
+
// ../sdk/dist/chunk-26IHUYNK.js
|
|
142974
142976
|
var createManagedAccount = (client, address2) => toAccount({
|
|
142975
142977
|
address: address2,
|
|
142976
142978
|
async signMessage({ message: message2 }) {
|
|
@@ -144161,368 +144163,988 @@ var Payments = class {
|
|
|
144161
144163
|
};
|
|
144162
144164
|
};
|
|
144163
144165
|
};
|
|
144164
|
-
var
|
|
144165
|
-
|
|
144166
|
-
|
|
144167
|
-
var
|
|
144168
|
-
|
|
144169
|
-
|
|
144170
|
-
|
|
144171
|
-
|
|
144172
|
-
|
|
144173
|
-
|
|
144174
|
-
|
|
144175
|
-
|
|
144176
|
-
|
|
144177
|
-
|
|
144178
|
-
var
|
|
144179
|
-
|
|
144180
|
-
|
|
144181
|
-
|
|
144182
|
-
|
|
144183
|
-
|
|
144184
|
-
|
|
144185
|
-
|
|
144186
|
-
|
|
144187
|
-
|
|
144188
|
-
|
|
144189
|
-
|
|
144190
|
-
|
|
144191
|
-
|
|
144192
|
-
|
|
144193
|
-
|
|
144194
|
-
|
|
144195
|
-
|
|
144196
|
-
|
|
144197
|
-
|
|
144198
|
-
|
|
144199
|
-
|
|
144200
|
-
|
|
144201
|
-
|
|
144202
|
-
|
|
144203
|
-
|
|
144204
|
-
|
|
144205
|
-
});
|
|
144206
|
-
var deviceStartResponseSchema = external_exports3.object({
|
|
144207
|
-
deviceCode: external_exports3.string(),
|
|
144208
|
-
userCode: external_exports3.string(),
|
|
144209
|
-
verificationUri: external_exports3.string(),
|
|
144210
|
-
pollInterval: external_exports3.number(),
|
|
144211
|
-
expiresAt: external_exports3.number()
|
|
144212
|
-
});
|
|
144213
|
-
var devicePollResponseSchema = external_exports3.union([
|
|
144214
|
-
// userCode + verificationUri are optional: older API deployments don't
|
|
144215
|
-
// echo them on pending.
|
|
144216
|
-
external_exports3.object({
|
|
144217
|
-
error: external_exports3.literal("authorization_pending"),
|
|
144218
|
-
userCode: external_exports3.string().optional(),
|
|
144219
|
-
verificationUri: external_exports3.string().optional()
|
|
144220
|
-
}),
|
|
144221
|
-
external_exports3.object({ error: external_exports3.literal("expired_token") }),
|
|
144222
|
-
external_exports3.object({
|
|
144223
|
-
accessToken: external_exports3.string(),
|
|
144224
|
-
refreshToken: external_exports3.string(),
|
|
144225
|
-
expiresIn: external_exports3.number(),
|
|
144226
|
-
user: internalUserDtoSchema
|
|
144227
|
-
})
|
|
144228
|
-
]);
|
|
144229
|
-
var sessionExchangeResponseSchema = external_exports3.object({
|
|
144230
|
-
token: external_exports3.string(),
|
|
144231
|
-
expiresAt: external_exports3.number()
|
|
144232
|
-
});
|
|
144233
|
-
var refreshResponseSchema = external_exports3.object({
|
|
144234
|
-
accessToken: external_exports3.string(),
|
|
144235
|
-
refreshToken: external_exports3.string()
|
|
144236
|
-
});
|
|
144237
|
-
var tryRefreshSession = async (client, callerSignal) => {
|
|
144238
|
-
const credentials = client.getCredentials();
|
|
144239
|
-
if (credentials.kind !== "session") return false;
|
|
144240
|
-
if (!credentials.refreshToken) return false;
|
|
144241
|
-
const url4 = `${client.baseUrl.replace(/\/$/, "")}/v1/auth/refresh`;
|
|
144242
|
-
const timeoutSignal = AbortSignal.timeout(client.timeout);
|
|
144243
|
-
const signal = callerSignal ? AbortSignal.any([callerSignal, timeoutSignal]) : timeoutSignal;
|
|
144244
|
-
let response;
|
|
144245
|
-
try {
|
|
144246
|
-
response = await client.fetchImpl(url4, {
|
|
144247
|
-
method: "POST",
|
|
144248
|
-
headers: { "content-type": "application/json" },
|
|
144249
|
-
body: JSON.stringify({ refreshToken: credentials.refreshToken }),
|
|
144250
|
-
signal
|
|
144251
|
-
});
|
|
144252
|
-
} catch {
|
|
144253
|
-
return false;
|
|
144166
|
+
var isShortToken = (id) => id.startsWith("z_") && id.indexOf(".", 2) !== -1;
|
|
144167
|
+
var MAX_402_PROBE_BYTES = 1024 * 1024;
|
|
144168
|
+
var MAX_RESPONSE_BYTES = 10 * 1024 * 1024;
|
|
144169
|
+
var TEXT_CONTENT_TYPES = [
|
|
144170
|
+
"application/json",
|
|
144171
|
+
"application/xml",
|
|
144172
|
+
"application/javascript",
|
|
144173
|
+
"application/ecmascript",
|
|
144174
|
+
"application/x-www-form-urlencoded",
|
|
144175
|
+
"text/",
|
|
144176
|
+
"+json",
|
|
144177
|
+
"+xml"
|
|
144178
|
+
];
|
|
144179
|
+
var MPP_SCHEME_TOKENS = /* @__PURE__ */ new Set(["payment", "mpp"]);
|
|
144180
|
+
var splitWwwAuthenticateChallenges = (header) => {
|
|
144181
|
+
const chunks = [];
|
|
144182
|
+
let buf = "";
|
|
144183
|
+
let inQuotes = false;
|
|
144184
|
+
for (let i = 0; i < header.length; i++) {
|
|
144185
|
+
const ch = header[i];
|
|
144186
|
+
if (inQuotes) {
|
|
144187
|
+
if (ch === "\\" && i + 1 < header.length) {
|
|
144188
|
+
buf += ch + header[i + 1];
|
|
144189
|
+
i++;
|
|
144190
|
+
continue;
|
|
144191
|
+
}
|
|
144192
|
+
if (ch === '"') inQuotes = false;
|
|
144193
|
+
buf += ch;
|
|
144194
|
+
continue;
|
|
144195
|
+
}
|
|
144196
|
+
if (ch === '"') {
|
|
144197
|
+
inQuotes = true;
|
|
144198
|
+
buf += ch;
|
|
144199
|
+
continue;
|
|
144200
|
+
}
|
|
144201
|
+
if (ch === ",") {
|
|
144202
|
+
chunks.push(buf);
|
|
144203
|
+
buf = "";
|
|
144204
|
+
continue;
|
|
144205
|
+
}
|
|
144206
|
+
buf += ch;
|
|
144254
144207
|
}
|
|
144255
|
-
if (
|
|
144256
|
-
|
|
144208
|
+
if (buf.length > 0) chunks.push(buf);
|
|
144209
|
+
return chunks;
|
|
144210
|
+
};
|
|
144211
|
+
var isTextContentType = (contentType) => {
|
|
144212
|
+
if (!contentType) return true;
|
|
144213
|
+
const lower = contentType.toLowerCase();
|
|
144214
|
+
return TEXT_CONTENT_TYPES.some((marker) => lower.includes(marker));
|
|
144215
|
+
};
|
|
144216
|
+
var redactUrl2 = (url4) => {
|
|
144257
144217
|
try {
|
|
144258
|
-
|
|
144218
|
+
const u2 = new URL(url4);
|
|
144219
|
+
return `${u2.origin}${u2.pathname}`;
|
|
144259
144220
|
} catch {
|
|
144260
|
-
return
|
|
144221
|
+
return "<invalid url>";
|
|
144261
144222
|
}
|
|
144262
|
-
const parsed = refreshResponseSchema.safeParse(body);
|
|
144263
|
-
if (!parsed.success) return false;
|
|
144264
|
-
await client.applyRefreshedTokens({
|
|
144265
|
-
accessToken: parsed.data.accessToken,
|
|
144266
|
-
refreshToken: parsed.data.refreshToken
|
|
144267
|
-
});
|
|
144268
|
-
return true;
|
|
144269
|
-
};
|
|
144270
|
-
var buildSessionAuthHeaders = (accessToken) => ({
|
|
144271
|
-
authorization: `Bearer ${accessToken}`
|
|
144272
|
-
});
|
|
144273
|
-
var buildCanonicalMessage = (method, pathWithQuery, body, timestamp, nonce2) => {
|
|
144274
|
-
const bodyHash = createHash("sha256").update(body ?? "").digest("hex");
|
|
144275
|
-
return `${method}:${pathWithQuery}:${bodyHash}:${timestamp}:${nonce2}`;
|
|
144276
144223
|
};
|
|
144277
|
-
var
|
|
144278
|
-
|
|
144279
|
-
|
|
144280
|
-
|
|
144281
|
-
|
|
144282
|
-
|
|
144283
|
-
body,
|
|
144284
|
-
timestamp,
|
|
144285
|
-
nonce2
|
|
144224
|
+
var ECHO_DETECT_MIN_LEN = 16;
|
|
144225
|
+
var ECHO_DETECT_MAX_SCAN = 64 * 1024;
|
|
144226
|
+
var requestBodyEchoed = (candidate, requestBody) => {
|
|
144227
|
+
if (requestBody === void 0) return false;
|
|
144228
|
+
const asString = typeof requestBody === "string" ? requestBody : new TextDecoder("utf-8", { fatal: false }).decode(
|
|
144229
|
+
requestBody.byteLength > ECHO_DETECT_MAX_SCAN ? requestBody.subarray(0, ECHO_DETECT_MAX_SCAN) : requestBody
|
|
144286
144230
|
);
|
|
144287
|
-
|
|
144288
|
-
|
|
144289
|
-
|
|
144290
|
-
|
|
144291
|
-
|
|
144292
|
-
|
|
144293
|
-
};
|
|
144294
|
-
};
|
|
144295
|
-
var RETRYABLE_STATUS = /* @__PURE__ */ new Set([408, 502, 503, 504]);
|
|
144296
|
-
var sleep2 = (ms, signal) => new Promise((resolve6, reject) => {
|
|
144297
|
-
if (signal?.aborted) {
|
|
144298
|
-
reject(new DOMException("Aborted", "AbortError"));
|
|
144299
|
-
return;
|
|
144300
|
-
}
|
|
144301
|
-
const timer = setTimeout(() => {
|
|
144302
|
-
signal?.removeEventListener("abort", onAbort);
|
|
144303
|
-
resolve6();
|
|
144304
|
-
}, ms);
|
|
144305
|
-
const onAbort = () => {
|
|
144306
|
-
clearTimeout(timer);
|
|
144307
|
-
reject(new DOMException("Aborted", "AbortError"));
|
|
144308
|
-
};
|
|
144309
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
144310
|
-
});
|
|
144311
|
-
var buildPathWithQuery = (path3, query) => {
|
|
144312
|
-
const normalizedPath = path3.startsWith("/") ? path3 : `/${path3}`;
|
|
144313
|
-
if (!query) return normalizedPath;
|
|
144314
|
-
const params = new URLSearchParams();
|
|
144315
|
-
for (const [key, value] of Object.entries(query)) {
|
|
144316
|
-
if (value !== void 0) params.set(key, String(value));
|
|
144317
|
-
}
|
|
144318
|
-
const qs = params.toString();
|
|
144319
|
-
return qs ? `${normalizedPath}?${qs}` : normalizedPath;
|
|
144320
|
-
};
|
|
144321
|
-
var joinUrl = (baseUrl, pathWithQuery) => {
|
|
144322
|
-
const base3 = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
|
144323
|
-
return `${base3}${pathWithQuery}`;
|
|
144324
|
-
};
|
|
144325
|
-
var buildHeaders = async (client, method, pathWithQuery, hasBody, bodyStr) => {
|
|
144326
|
-
const headers = { ...client.defaultHeaders };
|
|
144327
|
-
if (hasBody) headers["content-type"] = "application/json";
|
|
144328
|
-
headers["x-zero-sdk-version"] = SDK_VERSION2;
|
|
144329
|
-
if (client.apiVersion) headers["x-zero-api-version"] = client.apiVersion;
|
|
144330
|
-
const credentials = client.getCredentials();
|
|
144331
|
-
if (credentials.kind === "session") {
|
|
144332
|
-
Object.assign(headers, buildSessionAuthHeaders(credentials.accessToken));
|
|
144333
|
-
} else if (credentials.kind === "account") {
|
|
144334
|
-
const signed = await buildAccountAuthHeaders(
|
|
144335
|
-
credentials.account,
|
|
144336
|
-
method,
|
|
144337
|
-
pathWithQuery,
|
|
144338
|
-
bodyStr
|
|
144339
|
-
);
|
|
144340
|
-
Object.assign(headers, signed);
|
|
144231
|
+
if (asString.length < ECHO_DETECT_MIN_LEN) return false;
|
|
144232
|
+
const scanLen = Math.min(asString.length, ECHO_DETECT_MAX_SCAN);
|
|
144233
|
+
for (let i = 0; i + ECHO_DETECT_MIN_LEN <= scanLen; i++) {
|
|
144234
|
+
if (candidate.includes(asString.slice(i, i + ECHO_DETECT_MIN_LEN))) {
|
|
144235
|
+
return true;
|
|
144236
|
+
}
|
|
144341
144237
|
}
|
|
144342
|
-
return
|
|
144238
|
+
return false;
|
|
144343
144239
|
};
|
|
144344
|
-
var
|
|
144240
|
+
var cancelBody2 = (response) => {
|
|
144345
144241
|
try {
|
|
144346
|
-
|
|
144242
|
+
response.body?.cancel().catch(() => {
|
|
144243
|
+
});
|
|
144347
144244
|
} catch {
|
|
144245
|
+
}
|
|
144246
|
+
};
|
|
144247
|
+
var detectPaymentRequirement = async (response) => {
|
|
144248
|
+
if (response.status !== 402) return null;
|
|
144249
|
+
const x402Header = response.headers.get("payment-required") ?? response.headers.get("x-payment-required");
|
|
144250
|
+
if (x402Header) {
|
|
144251
|
+
cancelBody2(response);
|
|
144348
144252
|
try {
|
|
144349
|
-
|
|
144253
|
+
const decoded = JSON.parse(
|
|
144254
|
+
Buffer.from(x402Header, "base64").toString("utf8")
|
|
144255
|
+
);
|
|
144256
|
+
return { protocol: "x402", raw: decoded };
|
|
144350
144257
|
} catch {
|
|
144351
|
-
return
|
|
144258
|
+
return { protocol: "x402", raw: { encoded: x402Header } };
|
|
144352
144259
|
}
|
|
144353
144260
|
}
|
|
144354
|
-
|
|
144355
|
-
|
|
144356
|
-
|
|
144357
|
-
|
|
144358
|
-
|
|
144359
|
-
|
|
144360
|
-
};
|
|
144361
|
-
var request2 = async (client, opts, schema) => {
|
|
144362
|
-
const pathWithQuery = buildPathWithQuery(opts.path, opts.query);
|
|
144363
|
-
const url4 = joinUrl(client.baseUrl, pathWithQuery);
|
|
144364
|
-
const hasBody = opts.body !== void 0;
|
|
144365
|
-
const bodyStr = hasBody ? JSON.stringify(
|
|
144366
|
-
opts.body,
|
|
144367
|
-
(_k, v) => typeof v === "bigint" ? v.toString() : v
|
|
144368
|
-
) : void 0;
|
|
144369
|
-
const configuredFetch = buildConfiguredFetch(client);
|
|
144370
|
-
const performOnce = async () => configuredFetch(url4, {
|
|
144371
|
-
method: opts.method,
|
|
144372
|
-
headers: await buildHeaders(
|
|
144373
|
-
client,
|
|
144374
|
-
opts.method,
|
|
144375
|
-
pathWithQuery,
|
|
144376
|
-
hasBody,
|
|
144377
|
-
bodyStr
|
|
144378
|
-
),
|
|
144379
|
-
body: bodyStr,
|
|
144380
|
-
signal: opts.signal
|
|
144381
|
-
});
|
|
144382
|
-
let refreshAttempted = false;
|
|
144383
|
-
const executeWithRefresh = async () => {
|
|
144384
|
-
const response = await performOnce();
|
|
144385
|
-
if (response.status !== 401 || refreshAttempted) return response;
|
|
144386
|
-
const credentials = client.getCredentials();
|
|
144387
|
-
if (credentials.kind !== "session") return response;
|
|
144388
|
-
refreshAttempted = true;
|
|
144389
|
-
const refreshed = await client.refreshSessionOnce(opts.signal);
|
|
144390
|
-
if (!refreshed) return response;
|
|
144391
|
-
return await performOnce();
|
|
144392
|
-
};
|
|
144393
|
-
let lastNetworkError;
|
|
144394
|
-
for (let attempt = 0; attempt <= client.maxRetries; attempt++) {
|
|
144395
|
-
let response;
|
|
144261
|
+
const declaredLen = Number.parseInt(
|
|
144262
|
+
response.headers.get("content-length") ?? "",
|
|
144263
|
+
10
|
|
144264
|
+
);
|
|
144265
|
+
const bodyFits = !Number.isFinite(declaredLen) || declaredLen <= MAX_402_PROBE_BYTES;
|
|
144266
|
+
if (bodyFits) {
|
|
144396
144267
|
try {
|
|
144397
|
-
|
|
144398
|
-
|
|
144399
|
-
|
|
144400
|
-
|
|
144401
|
-
|
|
144402
|
-
try {
|
|
144403
|
-
await sleep2(2 ** attempt * 200, opts.signal);
|
|
144404
|
-
} catch (sleepErr) {
|
|
144405
|
-
throw new ZeroApiError("Request aborted by caller", {
|
|
144406
|
-
status: 0,
|
|
144407
|
-
cause: sleepErr
|
|
144408
|
-
});
|
|
144268
|
+
const text = await readClippedText(response, MAX_402_PROBE_BYTES);
|
|
144269
|
+
if (text) {
|
|
144270
|
+
const parsed = JSON.parse(text);
|
|
144271
|
+
if (looksLikeX402Body(parsed)) {
|
|
144272
|
+
return { protocol: "x402", raw: parsed };
|
|
144409
144273
|
}
|
|
144410
|
-
continue;
|
|
144411
|
-
}
|
|
144412
|
-
throw new ZeroApiError("Network request failed", {
|
|
144413
|
-
status: 0,
|
|
144414
|
-
cause: e2
|
|
144415
|
-
});
|
|
144416
|
-
}
|
|
144417
|
-
if (response.ok) {
|
|
144418
|
-
let text;
|
|
144419
|
-
try {
|
|
144420
|
-
text = await response.text();
|
|
144421
|
-
} catch (e2) {
|
|
144422
|
-
throw new ZeroApiError("Response body read failed", {
|
|
144423
|
-
status: response.status,
|
|
144424
|
-
cause: e2
|
|
144425
|
-
});
|
|
144426
|
-
}
|
|
144427
|
-
let json3;
|
|
144428
|
-
try {
|
|
144429
|
-
json3 = JSON.parse(text);
|
|
144430
|
-
} catch {
|
|
144431
|
-
}
|
|
144432
|
-
const parsed = schema.safeParse(json3);
|
|
144433
|
-
if (!parsed.success) {
|
|
144434
|
-
throw new ZeroValidationError(
|
|
144435
|
-
`Response did not match expected schema for ${opts.method} ${opts.path}`,
|
|
144436
|
-
{ cause: parsed.error, body: text }
|
|
144437
|
-
);
|
|
144438
144274
|
}
|
|
144439
|
-
|
|
144275
|
+
} catch {
|
|
144440
144276
|
}
|
|
144441
|
-
|
|
144442
|
-
|
|
144443
|
-
|
|
144444
|
-
|
|
144445
|
-
|
|
144446
|
-
|
|
144447
|
-
|
|
144448
|
-
|
|
144449
|
-
}
|
|
144450
|
-
continue;
|
|
144277
|
+
}
|
|
144278
|
+
const wwwAuth = response.headers.get("www-authenticate");
|
|
144279
|
+
if (wwwAuth) {
|
|
144280
|
+
const schemes = splitWwwAuthenticateChallenges(wwwAuth).map(
|
|
144281
|
+
(challenge2) => challenge2.trim().split(/\s+/)[0]?.toLowerCase() ?? ""
|
|
144282
|
+
);
|
|
144283
|
+
if (schemes.some((scheme) => MPP_SCHEME_TOKENS.has(scheme))) {
|
|
144284
|
+
cancelBody2(response);
|
|
144285
|
+
return { protocol: "mpp", raw: { "www-authenticate": wwwAuth } };
|
|
144451
144286
|
}
|
|
144452
|
-
const errorBody = await parseErrorBody(response);
|
|
144453
|
-
const requestId = response.headers.get("x-request-id") ?? void 0;
|
|
144454
|
-
throw new ZeroApiError(errorMessageFromBody(errorBody, response.status), {
|
|
144455
|
-
status: response.status,
|
|
144456
|
-
requestId,
|
|
144457
|
-
body: errorBody
|
|
144458
|
-
});
|
|
144459
144287
|
}
|
|
144460
|
-
|
|
144461
|
-
|
|
144462
|
-
cause: lastNetworkError
|
|
144463
|
-
});
|
|
144288
|
+
cancelBody2(response);
|
|
144289
|
+
return { protocol: "unknown", raw: {} };
|
|
144464
144290
|
};
|
|
144465
|
-
var
|
|
144466
|
-
|
|
144467
|
-
|
|
144468
|
-
|
|
144469
|
-
|
|
144470
|
-
|
|
144471
|
-
{
|
|
144472
|
-
|
|
144473
|
-
|
|
144474
|
-
|
|
144475
|
-
|
|
144476
|
-
|
|
144477
|
-
|
|
144478
|
-
|
|
144479
|
-
|
|
144480
|
-
|
|
144481
|
-
|
|
144482
|
-
method: "POST",
|
|
144483
|
-
path: "/v1/auth/device/poll",
|
|
144484
|
-
body: { deviceCode },
|
|
144485
|
-
signal: opts.signal
|
|
144486
|
-
},
|
|
144487
|
-
devicePollResponseSchema
|
|
144488
|
-
);
|
|
144489
|
-
if ("error" in parsed) {
|
|
144490
|
-
return parsed.error === "authorization_pending" ? {
|
|
144491
|
-
status: "pending",
|
|
144492
|
-
userCode: parsed.userCode,
|
|
144493
|
-
verificationUri: parsed.verificationUri
|
|
144494
|
-
} : { status: "expired" };
|
|
144291
|
+
var readClippedBytes = async (response, max) => {
|
|
144292
|
+
if (response.body === null) return new Uint8Array(0);
|
|
144293
|
+
const reader = response.body.getReader();
|
|
144294
|
+
const chunks = [];
|
|
144295
|
+
let total = 0;
|
|
144296
|
+
try {
|
|
144297
|
+
while (total < max) {
|
|
144298
|
+
const { done, value } = await reader.read();
|
|
144299
|
+
if (done) break;
|
|
144300
|
+
if (!value) continue;
|
|
144301
|
+
chunks.push(value);
|
|
144302
|
+
total += value.byteLength;
|
|
144303
|
+
}
|
|
144304
|
+
} finally {
|
|
144305
|
+
try {
|
|
144306
|
+
await reader.cancel();
|
|
144307
|
+
} catch {
|
|
144495
144308
|
}
|
|
144309
|
+
}
|
|
144310
|
+
const merged = new Uint8Array(Math.min(total, max));
|
|
144311
|
+
let offset = 0;
|
|
144312
|
+
for (const c of chunks) {
|
|
144313
|
+
const take = Math.min(c.byteLength, max - offset);
|
|
144314
|
+
merged.set(c.subarray(0, take), offset);
|
|
144315
|
+
offset += take;
|
|
144316
|
+
if (offset >= max) break;
|
|
144317
|
+
}
|
|
144318
|
+
return merged;
|
|
144319
|
+
};
|
|
144320
|
+
var readClippedText = async (response, max) => {
|
|
144321
|
+
const bytes = await readClippedBytes(response, max);
|
|
144322
|
+
return new TextDecoder().decode(bytes);
|
|
144323
|
+
};
|
|
144324
|
+
var parseResponseBody = async (response, max) => {
|
|
144325
|
+
const contentType = response.headers.get("content-type");
|
|
144326
|
+
const bytes = await readClippedBytes(response, max + 1);
|
|
144327
|
+
const truncated = bytes.byteLength > max;
|
|
144328
|
+
const view = truncated ? bytes.subarray(0, max) : bytes;
|
|
144329
|
+
const buf = Buffer.from(view.buffer, view.byteOffset, view.byteLength);
|
|
144330
|
+
if (!isTextContentType(contentType)) {
|
|
144331
|
+
const base644 = buf.toString("base64");
|
|
144496
144332
|
return {
|
|
144497
|
-
|
|
144498
|
-
|
|
144499
|
-
|
|
144500
|
-
|
|
144501
|
-
user: parsed.user
|
|
144333
|
+
body: base644,
|
|
144334
|
+
bodyRaw: base644,
|
|
144335
|
+
bodyEncoding: "base64",
|
|
144336
|
+
truncated
|
|
144502
144337
|
};
|
|
144503
|
-
}
|
|
144338
|
+
}
|
|
144339
|
+
const text = buf.toString("utf8");
|
|
144340
|
+
if (contentType?.toLowerCase().includes("json")) {
|
|
144341
|
+
try {
|
|
144342
|
+
return { body: JSON.parse(text), bodyRaw: text, truncated };
|
|
144343
|
+
} catch {
|
|
144344
|
+
}
|
|
144345
|
+
}
|
|
144346
|
+
return { body: text, bodyRaw: text, truncated };
|
|
144504
144347
|
};
|
|
144505
|
-
var
|
|
144506
|
-
|
|
144507
|
-
|
|
144508
|
-
|
|
144509
|
-
|
|
144348
|
+
var UPSTREAM_ERROR_FIELDS = [
|
|
144349
|
+
"error",
|
|
144350
|
+
"message",
|
|
144351
|
+
"detail",
|
|
144352
|
+
"reason",
|
|
144353
|
+
"error_description"
|
|
144354
|
+
];
|
|
144355
|
+
var UPSTREAM_ERROR_MAX_LEN = 200;
|
|
144356
|
+
var ERROR_SNIPPET_BYTES = 500;
|
|
144357
|
+
var clampUpstreamMessage = (value) => {
|
|
144358
|
+
const trimmed = value.trim();
|
|
144359
|
+
if (!trimmed) return void 0;
|
|
144360
|
+
return trimmed.length > UPSTREAM_ERROR_MAX_LEN ? `${trimmed.slice(0, UPSTREAM_ERROR_MAX_LEN)}\u2026` : trimmed;
|
|
144510
144361
|
};
|
|
144511
|
-
var
|
|
144512
|
-
|
|
144513
|
-
|
|
144514
|
-
|
|
144515
|
-
|
|
144516
|
-
`Sign endpoint refused ${op} (HTTP 402)${detail}`,
|
|
144517
|
-
{ cause: err }
|
|
144518
|
-
);
|
|
144362
|
+
var tryParseJson = (text) => {
|
|
144363
|
+
try {
|
|
144364
|
+
return JSON.parse(text);
|
|
144365
|
+
} catch {
|
|
144366
|
+
return null;
|
|
144519
144367
|
}
|
|
144520
|
-
throw err;
|
|
144521
144368
|
};
|
|
144522
|
-
var
|
|
144523
|
-
|
|
144524
|
-
|
|
144525
|
-
|
|
144369
|
+
var extractUpstreamErrorMessage = (body) => {
|
|
144370
|
+
const parsed = tryParseJson(body);
|
|
144371
|
+
if (parsed === null || typeof parsed !== "object") {
|
|
144372
|
+
return clampUpstreamMessage(body);
|
|
144373
|
+
}
|
|
144374
|
+
const record3 = parsed;
|
|
144375
|
+
for (const field of UPSTREAM_ERROR_FIELDS) {
|
|
144376
|
+
const value = record3[field];
|
|
144377
|
+
if (typeof value === "string" && value.length > 0) {
|
|
144378
|
+
return clampUpstreamMessage(value);
|
|
144379
|
+
}
|
|
144380
|
+
if (value && typeof value === "object") {
|
|
144381
|
+
const nested = value.message;
|
|
144382
|
+
if (typeof nested === "string" && nested.length > 0) {
|
|
144383
|
+
return clampUpstreamMessage(nested);
|
|
144384
|
+
}
|
|
144385
|
+
}
|
|
144386
|
+
}
|
|
144387
|
+
return void 0;
|
|
144388
|
+
};
|
|
144389
|
+
var buildUpstreamError = (status, bodyRaw, bodyEncoding) => {
|
|
144390
|
+
if (status >= 200 && status < 300) return void 0;
|
|
144391
|
+
if (bodyRaw === null || bodyRaw.length === 0) return void 0;
|
|
144392
|
+
if (bodyEncoding === "base64") return void 0;
|
|
144393
|
+
const snippet = bodyRaw.slice(0, ERROR_SNIPPET_BYTES);
|
|
144394
|
+
return {
|
|
144395
|
+
status,
|
|
144396
|
+
message: extractUpstreamErrorMessage(bodyRaw),
|
|
144397
|
+
snippetHash: createHash("sha256").update(snippet).digest("hex"),
|
|
144398
|
+
snippetLength: snippet.length
|
|
144399
|
+
};
|
|
144400
|
+
};
|
|
144401
|
+
var computeOutcome = (status, payment, warnings) => {
|
|
144402
|
+
if (warnings.includes(FETCH_WARNINGS.mppSessionCloseFailed))
|
|
144403
|
+
return "payment_close_failed";
|
|
144404
|
+
if (status === 402 && payment !== null) return "payment_rejected";
|
|
144405
|
+
if (status === 402) return "payment_failed";
|
|
144406
|
+
if (status >= 400) return "server_error";
|
|
144407
|
+
return "success";
|
|
144408
|
+
};
|
|
144409
|
+
var errorFetchResult = (startedAt, error48, skipReason, capabilityIdRequested, outcome, status = null) => {
|
|
144410
|
+
const result = {
|
|
144411
|
+
runId: null,
|
|
144412
|
+
ok: false,
|
|
144413
|
+
status,
|
|
144414
|
+
latencyMs: Date.now() - startedAt,
|
|
144415
|
+
payment: null,
|
|
144416
|
+
outcome,
|
|
144417
|
+
body: null,
|
|
144418
|
+
bodyRaw: null,
|
|
144419
|
+
error: error48
|
|
144420
|
+
};
|
|
144421
|
+
if (capabilityIdRequested) result.runTrackingSkipped = [skipReason];
|
|
144422
|
+
return result;
|
|
144423
|
+
};
|
|
144424
|
+
var resolveRecordingClient = (client, opts) => {
|
|
144425
|
+
const credentials = client.getCredentials();
|
|
144426
|
+
const recordingClient = opts.account ? client.withAccount(opts.account) : client;
|
|
144427
|
+
const canRecord = opts.account !== void 0 || credentials.kind === "account" || credentials.kind === "session";
|
|
144428
|
+
return { recordingClient, canRecord };
|
|
144429
|
+
};
|
|
144430
|
+
var recordErrorFetchRun = async (client, opts, result, capabilityIdOverride) => {
|
|
144431
|
+
const effectiveCapId = opts.capabilityId;
|
|
144432
|
+
if (effectiveCapId === void 0) return;
|
|
144433
|
+
const { recordingClient, canRecord } = resolveRecordingClient(client, opts);
|
|
144434
|
+
if (!canRecord) return;
|
|
144435
|
+
const fetchOriginForRecord = opts.capabilityId === void 0 ? "direct_url" : isShortToken(effectiveCapId) ? "from_search" : opts.fetchOrigin;
|
|
144436
|
+
try {
|
|
144437
|
+
const created = await recordingClient.runs.create({
|
|
144438
|
+
capabilityId: effectiveCapId,
|
|
144439
|
+
...opts.searchId && { searchId: opts.searchId },
|
|
144440
|
+
...fetchOriginForRecord && { fetchOrigin: fetchOriginForRecord },
|
|
144441
|
+
...result.status !== null && { status: result.status },
|
|
144442
|
+
latencyMs: result.latencyMs,
|
|
144443
|
+
...opts.requestSchema && { requestSchema: opts.requestSchema }
|
|
144444
|
+
});
|
|
144445
|
+
result.runId = created.runId;
|
|
144446
|
+
delete result.runTrackingSkipped;
|
|
144447
|
+
} catch {
|
|
144448
|
+
}
|
|
144449
|
+
};
|
|
144450
|
+
var recordTimeoutRun = async (client, opts, err, startedAt, capabilityIdRequested, capabilityIdOverride) => {
|
|
144451
|
+
const result = errorFetchResult(
|
|
144452
|
+
startedAt,
|
|
144453
|
+
err.message,
|
|
144454
|
+
"timeout",
|
|
144455
|
+
capabilityIdRequested,
|
|
144456
|
+
"network_error"
|
|
144457
|
+
);
|
|
144458
|
+
await recordErrorFetchRun(client, opts, result);
|
|
144459
|
+
};
|
|
144460
|
+
var sniffJsonShapeBytes = (buf) => {
|
|
144461
|
+
let i = 0;
|
|
144462
|
+
if (buf.length >= 3 && buf[0] === 239 && buf[1] === 187 && buf[2] === 191) {
|
|
144463
|
+
i = 3;
|
|
144464
|
+
}
|
|
144465
|
+
while (i < buf.length && (buf[i] === 32 || buf[i] === 9 || buf[i] === 10 || buf[i] === 13)) {
|
|
144466
|
+
i++;
|
|
144467
|
+
}
|
|
144468
|
+
if (i >= buf.length) return false;
|
|
144469
|
+
return buf[i] === 123 || buf[i] === 91;
|
|
144470
|
+
};
|
|
144471
|
+
var withDefaultContentType = (headers, body) => {
|
|
144472
|
+
if (!headers && body === void 0) return void 0;
|
|
144473
|
+
const next = headers ? { ...headers } : {};
|
|
144474
|
+
if (body === void 0) return next;
|
|
144475
|
+
const hasContentType = Object.keys(next).some(
|
|
144476
|
+
(k3) => k3.toLowerCase() === "content-type"
|
|
144477
|
+
);
|
|
144478
|
+
if (!hasContentType) {
|
|
144479
|
+
next["content-type"] = typeof body === "string" || sniffJsonShapeBytes(body) ? "application/json" : "application/octet-stream";
|
|
144480
|
+
}
|
|
144481
|
+
return next;
|
|
144482
|
+
};
|
|
144483
|
+
var clientFetch = async (client, url4, opts = {}) => {
|
|
144484
|
+
const startedAt = Date.now();
|
|
144485
|
+
const capabilityIdRequested = opts.capabilityId !== void 0;
|
|
144486
|
+
const normalized = normalizeTransportEnvelopeRequest(url4, {
|
|
144487
|
+
method: opts.method,
|
|
144488
|
+
body: opts.body
|
|
144489
|
+
});
|
|
144490
|
+
const requestUrl = normalized.url;
|
|
144491
|
+
const requestBody = normalized.body;
|
|
144492
|
+
const method = normalized.method ?? (requestBody !== void 0 ? "POST" : "GET");
|
|
144493
|
+
const { canRecord: canRecordForResolve } = resolveRecordingClient(
|
|
144494
|
+
client,
|
|
144495
|
+
opts
|
|
144496
|
+
);
|
|
144497
|
+
const resolvePromise = !capabilityIdRequested && canRecordForResolve ? client.capabilities.resolveByUrl(redactUrl2(requestUrl), method).catch(() => null) : Promise.resolve(null);
|
|
144498
|
+
const probeHeaders = withDefaultContentType(opts.headers, requestBody);
|
|
144499
|
+
const requestInit = {
|
|
144500
|
+
method,
|
|
144501
|
+
headers: probeHeaders,
|
|
144502
|
+
body: requestBody,
|
|
144503
|
+
signal: opts.signal
|
|
144504
|
+
};
|
|
144505
|
+
const configuredFetch = buildConfiguredFetch(client, {
|
|
144506
|
+
timeoutMs: opts.timeoutMs
|
|
144507
|
+
});
|
|
144508
|
+
let response;
|
|
144509
|
+
let payment = null;
|
|
144510
|
+
const skipReasons = [];
|
|
144511
|
+
const warnings = [];
|
|
144512
|
+
try {
|
|
144513
|
+
response = await configuredFetch(requestUrl, requestInit);
|
|
144514
|
+
} catch (err) {
|
|
144515
|
+
if (err instanceof ZeroTimeoutError) {
|
|
144516
|
+
await recordTimeoutRun(
|
|
144517
|
+
client,
|
|
144518
|
+
opts,
|
|
144519
|
+
err,
|
|
144520
|
+
startedAt,
|
|
144521
|
+
capabilityIdRequested
|
|
144522
|
+
);
|
|
144523
|
+
throw err;
|
|
144524
|
+
}
|
|
144525
|
+
if (err instanceof ZeroError) throw err;
|
|
144526
|
+
const errMessage = err instanceof Error ? err.message : String(err);
|
|
144527
|
+
const result2 = errorFetchResult(
|
|
144528
|
+
startedAt,
|
|
144529
|
+
errMessage,
|
|
144530
|
+
"fetch_failed_before_response",
|
|
144531
|
+
capabilityIdRequested,
|
|
144532
|
+
"network_error"
|
|
144533
|
+
);
|
|
144534
|
+
await recordErrorFetchRun(client, opts, result2);
|
|
144535
|
+
return result2;
|
|
144536
|
+
}
|
|
144537
|
+
if (response.status === 402) {
|
|
144538
|
+
const requirement = await detectPaymentRequirement(response);
|
|
144539
|
+
if (requirement?.protocol === "x402" || requirement?.protocol === "mpp") {
|
|
144540
|
+
const payCall = requirement.protocol === "x402" ? client.payments.pay : client.payments.payMpp;
|
|
144541
|
+
try {
|
|
144542
|
+
const paid = await payCall({
|
|
144543
|
+
url: requestUrl,
|
|
144544
|
+
method,
|
|
144545
|
+
// Fresh clone for the paid retry — same rationale as
|
|
144546
|
+
// the probe-side clone above. Re-derives the default
|
|
144547
|
+
// Content-Type so the paid leg matches the probe.
|
|
144548
|
+
headers: withDefaultContentType(opts.headers, requestBody),
|
|
144549
|
+
body: requestBody,
|
|
144550
|
+
maxPay: opts.maxPay,
|
|
144551
|
+
account: opts.account,
|
|
144552
|
+
signal: opts.signal,
|
|
144553
|
+
timeoutMs: opts.timeoutMs,
|
|
144554
|
+
...opts.displayCostAmount && {
|
|
144555
|
+
displayCostAmount: opts.displayCostAmount
|
|
144556
|
+
}
|
|
144557
|
+
});
|
|
144558
|
+
response = paid.response;
|
|
144559
|
+
payment = paid.payment;
|
|
144560
|
+
if (paid.warnings) warnings.push(...paid.warnings);
|
|
144561
|
+
} catch (err) {
|
|
144562
|
+
if (err instanceof ZeroSessionCloseFailedError) {
|
|
144563
|
+
response = err.response;
|
|
144564
|
+
payment = {
|
|
144565
|
+
protocol: "mpp",
|
|
144566
|
+
chain: tempoChainLabelFromId(err.session.chainId),
|
|
144567
|
+
txHash: null,
|
|
144568
|
+
amount: err.capturedAmount,
|
|
144569
|
+
asset: "USDC",
|
|
144570
|
+
session: err.session
|
|
144571
|
+
};
|
|
144572
|
+
warnings.push(FETCH_WARNINGS.mppSessionCloseFailed);
|
|
144573
|
+
} else if (err instanceof ZeroInsufficientFundsError) {
|
|
144574
|
+
return errorFetchResult(
|
|
144575
|
+
startedAt,
|
|
144576
|
+
err.message,
|
|
144577
|
+
FETCH_SKIP_REASONS.insufficientFunds,
|
|
144578
|
+
capabilityIdRequested,
|
|
144579
|
+
"insufficient_funds",
|
|
144580
|
+
null
|
|
144581
|
+
);
|
|
144582
|
+
} else if (err instanceof ZeroPaymentError || err instanceof ZeroAuthError) {
|
|
144583
|
+
const result2 = errorFetchResult(
|
|
144584
|
+
startedAt,
|
|
144585
|
+
err.message,
|
|
144586
|
+
"payment_failed",
|
|
144587
|
+
capabilityIdRequested,
|
|
144588
|
+
"payment_failed",
|
|
144589
|
+
402
|
|
144590
|
+
);
|
|
144591
|
+
await recordErrorFetchRun(client, opts, result2);
|
|
144592
|
+
return result2;
|
|
144593
|
+
} else if (err instanceof ZeroTimeoutError) {
|
|
144594
|
+
await recordTimeoutRun(
|
|
144595
|
+
client,
|
|
144596
|
+
opts,
|
|
144597
|
+
err,
|
|
144598
|
+
startedAt,
|
|
144599
|
+
capabilityIdRequested
|
|
144600
|
+
);
|
|
144601
|
+
throw err;
|
|
144602
|
+
} else {
|
|
144603
|
+
throw err;
|
|
144604
|
+
}
|
|
144605
|
+
}
|
|
144606
|
+
} else if (requirement?.protocol === "unknown") {
|
|
144607
|
+
const result2 = errorFetchResult(
|
|
144608
|
+
startedAt,
|
|
144609
|
+
"Capability returned 402 with an unrecognized payment protocol. Neither x402 nor MPP markers were detected in the response headers or body.",
|
|
144610
|
+
"unrecognized_402_protocol",
|
|
144611
|
+
capabilityIdRequested,
|
|
144612
|
+
"payment_failed",
|
|
144613
|
+
402
|
|
144614
|
+
);
|
|
144615
|
+
await recordErrorFetchRun(client, opts, result2);
|
|
144616
|
+
return result2;
|
|
144617
|
+
}
|
|
144618
|
+
}
|
|
144619
|
+
const latencyMs = Date.now() - startedAt;
|
|
144620
|
+
const maxResponseBytes = opts.maxResponseBytes ?? MAX_RESPONSE_BYTES;
|
|
144621
|
+
let body;
|
|
144622
|
+
let bodyRaw;
|
|
144623
|
+
let bodyEncoding;
|
|
144624
|
+
try {
|
|
144625
|
+
const parsed = await parseResponseBody(response, maxResponseBytes);
|
|
144626
|
+
body = parsed.body;
|
|
144627
|
+
bodyRaw = parsed.bodyRaw;
|
|
144628
|
+
bodyEncoding = parsed.bodyEncoding;
|
|
144629
|
+
if (parsed.truncated) warnings.push(FETCH_WARNINGS.bodyTruncated);
|
|
144630
|
+
} catch (err) {
|
|
144631
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
144632
|
+
throw new ZeroApiError("Request aborted by caller", {
|
|
144633
|
+
status: 0,
|
|
144634
|
+
cause: err
|
|
144635
|
+
});
|
|
144636
|
+
}
|
|
144637
|
+
const message2 = err instanceof Error ? err.message : String(err);
|
|
144638
|
+
const skips = [];
|
|
144639
|
+
const settledLocally = paymentHasAnchor(payment);
|
|
144640
|
+
if (settledLocally && response.status === 402) {
|
|
144641
|
+
warnings.push(FETCH_WARNINGS.paidButStill402NotRecorded);
|
|
144642
|
+
skips.push(FETCH_WARNINGS.paidButStill402NotRecorded);
|
|
144643
|
+
}
|
|
144644
|
+
if (payment !== null && !settledLocally) {
|
|
144645
|
+
warnings.push(FETCH_WARNINGS.paymentSettlementUnconfirmed);
|
|
144646
|
+
skips.push(FETCH_WARNINGS.paymentSettlementUnconfirmed);
|
|
144647
|
+
}
|
|
144648
|
+
if (payment !== null && payment.amount === "unknown") {
|
|
144649
|
+
warnings.push(FETCH_WARNINGS.paymentAmountUnknown);
|
|
144650
|
+
}
|
|
144651
|
+
skips.push(FETCH_SKIP_REASONS.bodyReadFailed);
|
|
144652
|
+
const result2 = {
|
|
144653
|
+
runId: null,
|
|
144654
|
+
ok: false,
|
|
144655
|
+
status: response.status,
|
|
144656
|
+
latencyMs: Date.now() - startedAt,
|
|
144657
|
+
payment,
|
|
144658
|
+
outcome: computeOutcome(response.status, payment, warnings),
|
|
144659
|
+
body: null,
|
|
144660
|
+
bodyRaw: null,
|
|
144661
|
+
error: message2
|
|
144662
|
+
};
|
|
144663
|
+
if (capabilityIdRequested) result2.runTrackingSkipped = skips;
|
|
144664
|
+
if (warnings.length > 0) result2.warnings = warnings;
|
|
144665
|
+
return result2;
|
|
144666
|
+
}
|
|
144667
|
+
const settled = paymentHasAnchor(payment);
|
|
144668
|
+
const paidButStill402 = settled && response.status === 402;
|
|
144669
|
+
const settlementUnconfirmed = payment !== null && !settled;
|
|
144670
|
+
if (paidButStill402) warnings.push(FETCH_WARNINGS.paidButStill402NotRecorded);
|
|
144671
|
+
if (settlementUnconfirmed)
|
|
144672
|
+
warnings.push(FETCH_WARNINGS.paymentSettlementUnconfirmed);
|
|
144673
|
+
if (payment !== null && payment.amount === "unknown") {
|
|
144674
|
+
warnings.push(FETCH_WARNINGS.paymentAmountUnknown);
|
|
144675
|
+
}
|
|
144676
|
+
let runId = null;
|
|
144677
|
+
const closeFailed = warnings.includes(FETCH_WARNINGS.mppSessionCloseFailed);
|
|
144678
|
+
const upstreamErrorForRecord = buildUpstreamError(
|
|
144679
|
+
response.status,
|
|
144680
|
+
bodyRaw,
|
|
144681
|
+
bodyEncoding
|
|
144682
|
+
);
|
|
144683
|
+
if (capabilityIdRequested) {
|
|
144684
|
+
if (paidButStill402)
|
|
144685
|
+
skipReasons.push(FETCH_WARNINGS.paidButStill402NotRecorded);
|
|
144686
|
+
else if (closeFailed)
|
|
144687
|
+
skipReasons.push(FETCH_SKIP_REASONS.mppSessionCloseFailedNotRecorded);
|
|
144688
|
+
}
|
|
144689
|
+
const resolvedCap = await resolvePromise;
|
|
144690
|
+
const effectiveCapabilityId = opts.capabilityId ?? resolvedCap?.capabilityId;
|
|
144691
|
+
const capabilityResolution = !capabilityIdRequested && canRecordForResolve ? resolvedCap !== null ? {
|
|
144692
|
+
resolved: true,
|
|
144693
|
+
capabilityId: resolvedCap.capabilityId,
|
|
144694
|
+
capabilitySlug: resolvedCap.capabilitySlug,
|
|
144695
|
+
matchedVia: resolvedCap.matchedVia
|
|
144696
|
+
} : { resolved: false } : void 0;
|
|
144697
|
+
if (effectiveCapabilityId !== void 0 && !paidButStill402 && !closeFailed) {
|
|
144698
|
+
const { recordingClient, canRecord } = resolveRecordingClient(client, opts);
|
|
144699
|
+
if (!canRecord) {
|
|
144700
|
+
skipReasons.push("no_credentials");
|
|
144701
|
+
} else {
|
|
144702
|
+
const knownAmount = payment !== null && payment.amount !== "unknown";
|
|
144703
|
+
try {
|
|
144704
|
+
let derived;
|
|
144705
|
+
if (opts.deriveRunMetadata) {
|
|
144706
|
+
try {
|
|
144707
|
+
derived = opts.deriveRunMetadata({
|
|
144708
|
+
status: response.status,
|
|
144709
|
+
ok: response.ok,
|
|
144710
|
+
bodyRaw,
|
|
144711
|
+
...bodyEncoding && { bodyEncoding }
|
|
144712
|
+
});
|
|
144713
|
+
} catch {
|
|
144714
|
+
}
|
|
144715
|
+
}
|
|
144716
|
+
const result2 = await recordingClient.runs.create({
|
|
144717
|
+
capabilityId: effectiveCapabilityId,
|
|
144718
|
+
searchId: opts.searchId,
|
|
144719
|
+
// Auto-resolved runs are always direct_url — they only fire when
|
|
144720
|
+
// no capabilityId was supplied (the direct_url path by definition).
|
|
144721
|
+
...opts.capabilityId === void 0 ? { fetchOrigin: "direct_url" } : opts.fetchOrigin && { fetchOrigin: opts.fetchOrigin },
|
|
144722
|
+
status: response.status,
|
|
144723
|
+
latencyMs,
|
|
144724
|
+
...opts.requestSchema && { requestSchema: opts.requestSchema },
|
|
144725
|
+
...derived?.responseSchema && {
|
|
144726
|
+
responseSchema: derived.responseSchema
|
|
144727
|
+
},
|
|
144728
|
+
...upstreamErrorForRecord && {
|
|
144729
|
+
errorSnippetHash: upstreamErrorForRecord.snippetHash,
|
|
144730
|
+
errorSnippetLength: upstreamErrorForRecord.snippetLength
|
|
144731
|
+
},
|
|
144732
|
+
...payment && {
|
|
144733
|
+
...knownAmount && {
|
|
144734
|
+
costAmount: payment.amount,
|
|
144735
|
+
costAsset: payment.asset
|
|
144736
|
+
},
|
|
144737
|
+
paymentProtocol: payment.protocol,
|
|
144738
|
+
paymentChain: payment.chain,
|
|
144739
|
+
paymentTxHash: payment.txHash ?? void 0,
|
|
144740
|
+
paymentMode: payment.session ? "session" : "charge"
|
|
144741
|
+
}
|
|
144742
|
+
});
|
|
144743
|
+
runId = result2.runId;
|
|
144744
|
+
} catch (err) {
|
|
144745
|
+
const errorMessage22 = err instanceof Error ? err.message : String(err);
|
|
144746
|
+
const code = err instanceof ZeroError ? err.code : void 0;
|
|
144747
|
+
const skipMsg = code ? `run_create_failed:${code}: ${errorMessage22}` : `run_create_failed: ${errorMessage22}`;
|
|
144748
|
+
skipReasons.push(skipMsg);
|
|
144749
|
+
client.logger?.({
|
|
144750
|
+
level: "warn",
|
|
144751
|
+
message: "Failed to record run for fetch",
|
|
144752
|
+
meta: {
|
|
144753
|
+
url: redactUrl2(url4),
|
|
144754
|
+
capabilityId: effectiveCapabilityId,
|
|
144755
|
+
error: errorMessage22,
|
|
144756
|
+
errorCode: code
|
|
144757
|
+
}
|
|
144758
|
+
});
|
|
144759
|
+
}
|
|
144760
|
+
}
|
|
144761
|
+
}
|
|
144762
|
+
const result = {
|
|
144763
|
+
runId,
|
|
144764
|
+
ok: response.ok,
|
|
144765
|
+
status: response.status,
|
|
144766
|
+
latencyMs,
|
|
144767
|
+
payment,
|
|
144768
|
+
outcome: computeOutcome(response.status, payment, warnings),
|
|
144769
|
+
body,
|
|
144770
|
+
bodyRaw
|
|
144771
|
+
};
|
|
144772
|
+
if (bodyEncoding) result.bodyEncoding = bodyEncoding;
|
|
144773
|
+
if (!response.ok) {
|
|
144774
|
+
const candidate = bodyRaw !== null && bodyRaw.length > 0 && bodyEncoding !== "base64" ? bodyRaw.slice(0, 240) : null;
|
|
144775
|
+
result.error = candidate !== null && !requestBodyEchoed(candidate, opts.body) ? candidate : `HTTP ${response.status}`;
|
|
144776
|
+
if (upstreamErrorForRecord) result.upstreamError = upstreamErrorForRecord;
|
|
144777
|
+
}
|
|
144778
|
+
if (capabilityIdRequested && skipReasons.length > 0) {
|
|
144779
|
+
result.runTrackingSkipped = skipReasons;
|
|
144780
|
+
}
|
|
144781
|
+
if (warnings.length > 0) result.warnings = warnings;
|
|
144782
|
+
if (capabilityResolution !== void 0)
|
|
144783
|
+
result.capabilityResolution = capabilityResolution;
|
|
144784
|
+
return result;
|
|
144785
|
+
};
|
|
144786
|
+
var package_default2 = {
|
|
144787
|
+
version: "0.7.0"
|
|
144788
|
+
};
|
|
144789
|
+
var SDK_VERSION2 = package_default2.version;
|
|
144790
|
+
var userWalletDtoSchema = external_exports3.object({
|
|
144791
|
+
walletAddress: external_exports3.string(),
|
|
144792
|
+
source: external_exports3.enum(["self_custody", "privy_embedded"]),
|
|
144793
|
+
isPrimary: external_exports3.boolean(),
|
|
144794
|
+
linkedAt: external_exports3.union([external_exports3.string(), external_exports3.date()]).nullable().optional(),
|
|
144795
|
+
delegationGranted: external_exports3.boolean(),
|
|
144796
|
+
signerQuorumId: external_exports3.string().nullable(),
|
|
144797
|
+
// Per-transaction USDC cap in base units (6 dp). null = unlimited, 0 = free-only.
|
|
144798
|
+
maxTransactionUsdcBaseUnits: external_exports3.number().int().nullable()
|
|
144799
|
+
});
|
|
144800
|
+
var welcomeBonusSummarySchema = external_exports3.object({
|
|
144801
|
+
status: external_exports3.string(),
|
|
144802
|
+
amountUsd: external_exports3.number()
|
|
144803
|
+
});
|
|
144804
|
+
var internalUserDtoSchema = external_exports3.object({
|
|
144805
|
+
id: external_exports3.string(),
|
|
144806
|
+
email: external_exports3.string().nullable(),
|
|
144807
|
+
createdAt: external_exports3.union([external_exports3.string(), external_exports3.date()]).optional(),
|
|
144808
|
+
lastLoginAt: external_exports3.union([external_exports3.string(), external_exports3.date()]).nullable().optional(),
|
|
144809
|
+
onboardingCompleted: external_exports3.boolean().optional(),
|
|
144810
|
+
delegationGranted: external_exports3.boolean().optional(),
|
|
144811
|
+
wallets: external_exports3.array(userWalletDtoSchema).optional(),
|
|
144812
|
+
balance: external_exports3.object({ amount: external_exports3.string(), asset: external_exports3.string() }).nullable().optional(),
|
|
144813
|
+
welcomeBonus: welcomeBonusSummarySchema.nullable().optional()
|
|
144814
|
+
});
|
|
144815
|
+
var publicUserDtoSchema = external_exports3.object({
|
|
144816
|
+
user: external_exports3.object({
|
|
144817
|
+
id: external_exports3.string(),
|
|
144818
|
+
email: external_exports3.string().nullable()
|
|
144819
|
+
}),
|
|
144820
|
+
walletAddress: external_exports3.string().nullable(),
|
|
144821
|
+
balance: external_exports3.object({ amount: external_exports3.string(), asset: external_exports3.string() }).nullable(),
|
|
144822
|
+
welcomeBonus: welcomeBonusSummarySchema.nullable()
|
|
144823
|
+
});
|
|
144824
|
+
var signResponseSchema = external_exports3.object({
|
|
144825
|
+
signature: external_exports3.string().regex(/^0x[0-9a-fA-F]+$/, "must be 0x-prefixed hex"),
|
|
144826
|
+
walletAddress: external_exports3.string().regex(/^0x[0-9a-fA-F]{40}$/, "must be 0x-prefixed 40-char hex address")
|
|
144827
|
+
});
|
|
144828
|
+
var deviceStartResponseSchema = external_exports3.object({
|
|
144829
|
+
deviceCode: external_exports3.string(),
|
|
144830
|
+
userCode: external_exports3.string(),
|
|
144831
|
+
verificationUri: external_exports3.string(),
|
|
144832
|
+
pollInterval: external_exports3.number(),
|
|
144833
|
+
expiresAt: external_exports3.number()
|
|
144834
|
+
});
|
|
144835
|
+
var devicePollResponseSchema = external_exports3.union([
|
|
144836
|
+
// userCode + verificationUri are optional: older API deployments don't
|
|
144837
|
+
// echo them on pending.
|
|
144838
|
+
external_exports3.object({
|
|
144839
|
+
error: external_exports3.literal("authorization_pending"),
|
|
144840
|
+
userCode: external_exports3.string().optional(),
|
|
144841
|
+
verificationUri: external_exports3.string().optional()
|
|
144842
|
+
}),
|
|
144843
|
+
external_exports3.object({ error: external_exports3.literal("expired_token") }),
|
|
144844
|
+
external_exports3.object({
|
|
144845
|
+
accessToken: external_exports3.string(),
|
|
144846
|
+
refreshToken: external_exports3.string(),
|
|
144847
|
+
expiresIn: external_exports3.number(),
|
|
144848
|
+
user: internalUserDtoSchema
|
|
144849
|
+
})
|
|
144850
|
+
]);
|
|
144851
|
+
var sessionExchangeResponseSchema = external_exports3.object({
|
|
144852
|
+
token: external_exports3.string(),
|
|
144853
|
+
expiresAt: external_exports3.number()
|
|
144854
|
+
});
|
|
144855
|
+
var refreshResponseSchema = external_exports3.object({
|
|
144856
|
+
accessToken: external_exports3.string(),
|
|
144857
|
+
refreshToken: external_exports3.string()
|
|
144858
|
+
});
|
|
144859
|
+
var tryRefreshSession = async (client, callerSignal) => {
|
|
144860
|
+
const credentials = client.getCredentials();
|
|
144861
|
+
if (credentials.kind !== "session") return false;
|
|
144862
|
+
if (!credentials.refreshToken) return false;
|
|
144863
|
+
const url4 = `${client.baseUrl.replace(/\/$/, "")}/v1/auth/refresh`;
|
|
144864
|
+
const timeoutSignal = AbortSignal.timeout(client.timeout);
|
|
144865
|
+
const signal = callerSignal ? AbortSignal.any([callerSignal, timeoutSignal]) : timeoutSignal;
|
|
144866
|
+
let response;
|
|
144867
|
+
try {
|
|
144868
|
+
response = await client.fetchImpl(url4, {
|
|
144869
|
+
method: "POST",
|
|
144870
|
+
headers: { "content-type": "application/json" },
|
|
144871
|
+
body: JSON.stringify({ refreshToken: credentials.refreshToken }),
|
|
144872
|
+
signal
|
|
144873
|
+
});
|
|
144874
|
+
} catch {
|
|
144875
|
+
return false;
|
|
144876
|
+
}
|
|
144877
|
+
if (!response.ok) return false;
|
|
144878
|
+
let body;
|
|
144879
|
+
try {
|
|
144880
|
+
body = await response.json();
|
|
144881
|
+
} catch {
|
|
144882
|
+
return false;
|
|
144883
|
+
}
|
|
144884
|
+
const parsed = refreshResponseSchema.safeParse(body);
|
|
144885
|
+
if (!parsed.success) return false;
|
|
144886
|
+
await client.applyRefreshedTokens({
|
|
144887
|
+
accessToken: parsed.data.accessToken,
|
|
144888
|
+
refreshToken: parsed.data.refreshToken
|
|
144889
|
+
});
|
|
144890
|
+
return true;
|
|
144891
|
+
};
|
|
144892
|
+
var buildSessionAuthHeaders = (accessToken) => ({
|
|
144893
|
+
authorization: `Bearer ${accessToken}`
|
|
144894
|
+
});
|
|
144895
|
+
var buildCanonicalMessage = (method, pathWithQuery, body, timestamp, nonce2) => {
|
|
144896
|
+
const bodyHash = createHash("sha256").update(body ?? "").digest("hex");
|
|
144897
|
+
return `${method}:${pathWithQuery}:${bodyHash}:${timestamp}:${nonce2}`;
|
|
144898
|
+
};
|
|
144899
|
+
var buildAccountAuthHeaders = async (account, method, pathWithQuery, body) => {
|
|
144900
|
+
const timestamp = Math.floor(Date.now() / 1e3).toString();
|
|
144901
|
+
const nonce2 = crypto.randomUUID();
|
|
144902
|
+
const message2 = buildCanonicalMessage(
|
|
144903
|
+
method,
|
|
144904
|
+
pathWithQuery,
|
|
144905
|
+
body,
|
|
144906
|
+
timestamp,
|
|
144907
|
+
nonce2
|
|
144908
|
+
);
|
|
144909
|
+
const signature2 = await account.signMessage({ message: message2 });
|
|
144910
|
+
return {
|
|
144911
|
+
"x-zero-address": account.address,
|
|
144912
|
+
"x-zero-timestamp": timestamp,
|
|
144913
|
+
"x-zero-nonce": nonce2,
|
|
144914
|
+
"x-zero-signature": signature2
|
|
144915
|
+
};
|
|
144916
|
+
};
|
|
144917
|
+
var RETRYABLE_STATUS = /* @__PURE__ */ new Set([408, 502, 503, 504]);
|
|
144918
|
+
var sleep2 = (ms, signal) => new Promise((resolve6, reject) => {
|
|
144919
|
+
if (signal?.aborted) {
|
|
144920
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
144921
|
+
return;
|
|
144922
|
+
}
|
|
144923
|
+
const timer = setTimeout(() => {
|
|
144924
|
+
signal?.removeEventListener("abort", onAbort);
|
|
144925
|
+
resolve6();
|
|
144926
|
+
}, ms);
|
|
144927
|
+
const onAbort = () => {
|
|
144928
|
+
clearTimeout(timer);
|
|
144929
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
144930
|
+
};
|
|
144931
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
144932
|
+
});
|
|
144933
|
+
var buildPathWithQuery = (path3, query) => {
|
|
144934
|
+
const normalizedPath = path3.startsWith("/") ? path3 : `/${path3}`;
|
|
144935
|
+
if (!query) return normalizedPath;
|
|
144936
|
+
const params = new URLSearchParams();
|
|
144937
|
+
for (const [key, value] of Object.entries(query)) {
|
|
144938
|
+
if (value !== void 0) params.set(key, String(value));
|
|
144939
|
+
}
|
|
144940
|
+
const qs = params.toString();
|
|
144941
|
+
return qs ? `${normalizedPath}?${qs}` : normalizedPath;
|
|
144942
|
+
};
|
|
144943
|
+
var joinUrl = (baseUrl, pathWithQuery) => {
|
|
144944
|
+
const base3 = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
|
144945
|
+
return `${base3}${pathWithQuery}`;
|
|
144946
|
+
};
|
|
144947
|
+
var buildHeaders = async (client, method, pathWithQuery, hasBody, bodyStr) => {
|
|
144948
|
+
const headers = { ...client.defaultHeaders };
|
|
144949
|
+
if (hasBody) headers["content-type"] = "application/json";
|
|
144950
|
+
headers["x-zero-sdk-version"] = SDK_VERSION2;
|
|
144951
|
+
if (client.apiVersion) headers["x-zero-api-version"] = client.apiVersion;
|
|
144952
|
+
const credentials = client.getCredentials();
|
|
144953
|
+
if (credentials.kind === "session") {
|
|
144954
|
+
Object.assign(headers, buildSessionAuthHeaders(credentials.accessToken));
|
|
144955
|
+
} else if (credentials.kind === "account") {
|
|
144956
|
+
const signed = await buildAccountAuthHeaders(
|
|
144957
|
+
credentials.account,
|
|
144958
|
+
method,
|
|
144959
|
+
pathWithQuery,
|
|
144960
|
+
bodyStr
|
|
144961
|
+
);
|
|
144962
|
+
Object.assign(headers, signed);
|
|
144963
|
+
}
|
|
144964
|
+
return headers;
|
|
144965
|
+
};
|
|
144966
|
+
var parseErrorBody = async (response) => {
|
|
144967
|
+
try {
|
|
144968
|
+
return await response.clone().json();
|
|
144969
|
+
} catch {
|
|
144970
|
+
try {
|
|
144971
|
+
return await response.text();
|
|
144972
|
+
} catch {
|
|
144973
|
+
return void 0;
|
|
144974
|
+
}
|
|
144975
|
+
}
|
|
144976
|
+
};
|
|
144977
|
+
var errorMessageFromBody = (body, status) => {
|
|
144978
|
+
if (body !== null && typeof body === "object" && "error" in body && typeof body.error === "string") {
|
|
144979
|
+
return body.error;
|
|
144980
|
+
}
|
|
144981
|
+
return `HTTP ${status}`;
|
|
144982
|
+
};
|
|
144983
|
+
var request2 = async (client, opts, schema) => {
|
|
144984
|
+
const pathWithQuery = buildPathWithQuery(opts.path, opts.query);
|
|
144985
|
+
const url4 = joinUrl(client.baseUrl, pathWithQuery);
|
|
144986
|
+
const hasBody = opts.body !== void 0;
|
|
144987
|
+
const bodyStr = hasBody ? JSON.stringify(
|
|
144988
|
+
opts.body,
|
|
144989
|
+
(_k, v) => typeof v === "bigint" ? v.toString() : v
|
|
144990
|
+
) : void 0;
|
|
144991
|
+
const configuredFetch = buildConfiguredFetch(client);
|
|
144992
|
+
const performOnce = async () => configuredFetch(url4, {
|
|
144993
|
+
method: opts.method,
|
|
144994
|
+
headers: await buildHeaders(
|
|
144995
|
+
client,
|
|
144996
|
+
opts.method,
|
|
144997
|
+
pathWithQuery,
|
|
144998
|
+
hasBody,
|
|
144999
|
+
bodyStr
|
|
145000
|
+
),
|
|
145001
|
+
body: bodyStr,
|
|
145002
|
+
signal: opts.signal
|
|
145003
|
+
});
|
|
145004
|
+
let refreshAttempted = false;
|
|
145005
|
+
const executeWithRefresh = async () => {
|
|
145006
|
+
const response = await performOnce();
|
|
145007
|
+
if (response.status !== 401 || refreshAttempted) return response;
|
|
145008
|
+
const credentials = client.getCredentials();
|
|
145009
|
+
if (credentials.kind !== "session") return response;
|
|
145010
|
+
refreshAttempted = true;
|
|
145011
|
+
const refreshed = await client.refreshSessionOnce(opts.signal);
|
|
145012
|
+
if (!refreshed) return response;
|
|
145013
|
+
return await performOnce();
|
|
145014
|
+
};
|
|
145015
|
+
let lastNetworkError;
|
|
145016
|
+
for (let attempt = 0; attempt <= client.maxRetries; attempt++) {
|
|
145017
|
+
let response;
|
|
145018
|
+
try {
|
|
145019
|
+
response = await executeWithRefresh();
|
|
145020
|
+
} catch (e2) {
|
|
145021
|
+
if (e2 instanceof ZeroError) throw e2;
|
|
145022
|
+
lastNetworkError = e2;
|
|
145023
|
+
if (attempt < client.maxRetries) {
|
|
145024
|
+
try {
|
|
145025
|
+
await sleep2(2 ** attempt * 200, opts.signal);
|
|
145026
|
+
} catch (sleepErr) {
|
|
145027
|
+
throw new ZeroApiError("Request aborted by caller", {
|
|
145028
|
+
status: 0,
|
|
145029
|
+
cause: sleepErr
|
|
145030
|
+
});
|
|
145031
|
+
}
|
|
145032
|
+
continue;
|
|
145033
|
+
}
|
|
145034
|
+
throw new ZeroApiError("Network request failed", {
|
|
145035
|
+
status: 0,
|
|
145036
|
+
cause: e2
|
|
145037
|
+
});
|
|
145038
|
+
}
|
|
145039
|
+
if (response.ok) {
|
|
145040
|
+
let text;
|
|
145041
|
+
try {
|
|
145042
|
+
text = await response.text();
|
|
145043
|
+
} catch (e2) {
|
|
145044
|
+
throw new ZeroApiError("Response body read failed", {
|
|
145045
|
+
status: response.status,
|
|
145046
|
+
cause: e2
|
|
145047
|
+
});
|
|
145048
|
+
}
|
|
145049
|
+
let json3;
|
|
145050
|
+
try {
|
|
145051
|
+
json3 = JSON.parse(text);
|
|
145052
|
+
} catch {
|
|
145053
|
+
}
|
|
145054
|
+
const parsed = schema.safeParse(json3);
|
|
145055
|
+
if (!parsed.success) {
|
|
145056
|
+
throw new ZeroValidationError(
|
|
145057
|
+
`Response did not match expected schema for ${opts.method} ${opts.path}`,
|
|
145058
|
+
{ cause: parsed.error, body: text }
|
|
145059
|
+
);
|
|
145060
|
+
}
|
|
145061
|
+
return parsed.data;
|
|
145062
|
+
}
|
|
145063
|
+
if (RETRYABLE_STATUS.has(response.status) && attempt < client.maxRetries) {
|
|
145064
|
+
try {
|
|
145065
|
+
await sleep2(2 ** attempt * 200, opts.signal);
|
|
145066
|
+
} catch (sleepErr) {
|
|
145067
|
+
throw new ZeroApiError("Request aborted by caller", {
|
|
145068
|
+
status: 0,
|
|
145069
|
+
cause: sleepErr
|
|
145070
|
+
});
|
|
145071
|
+
}
|
|
145072
|
+
continue;
|
|
145073
|
+
}
|
|
145074
|
+
const errorBody = await parseErrorBody(response);
|
|
145075
|
+
const requestId = response.headers.get("x-request-id") ?? void 0;
|
|
145076
|
+
throw new ZeroApiError(errorMessageFromBody(errorBody, response.status), {
|
|
145077
|
+
status: response.status,
|
|
145078
|
+
requestId,
|
|
145079
|
+
body: errorBody
|
|
145080
|
+
});
|
|
145081
|
+
}
|
|
145082
|
+
throw new ZeroApiError("Exhausted retries", {
|
|
145083
|
+
status: 0,
|
|
145084
|
+
cause: lastNetworkError
|
|
145085
|
+
});
|
|
145086
|
+
};
|
|
145087
|
+
var AuthDevice = class {
|
|
145088
|
+
constructor(client) {
|
|
145089
|
+
this.client = client;
|
|
145090
|
+
}
|
|
145091
|
+
start = (opts = {}) => request2(
|
|
145092
|
+
this.client,
|
|
145093
|
+
{
|
|
145094
|
+
method: "POST",
|
|
145095
|
+
path: "/v1/auth/device/start",
|
|
145096
|
+
signal: opts.signal
|
|
145097
|
+
},
|
|
145098
|
+
deviceStartResponseSchema
|
|
145099
|
+
);
|
|
145100
|
+
poll = async (deviceCode, opts = {}) => {
|
|
145101
|
+
const parsed = await request2(
|
|
145102
|
+
this.client,
|
|
145103
|
+
{
|
|
145104
|
+
method: "POST",
|
|
145105
|
+
path: "/v1/auth/device/poll",
|
|
145106
|
+
body: { deviceCode },
|
|
145107
|
+
signal: opts.signal
|
|
145108
|
+
},
|
|
145109
|
+
devicePollResponseSchema
|
|
145110
|
+
);
|
|
145111
|
+
if ("error" in parsed) {
|
|
145112
|
+
return parsed.error === "authorization_pending" ? {
|
|
145113
|
+
status: "pending",
|
|
145114
|
+
userCode: parsed.userCode,
|
|
145115
|
+
verificationUri: parsed.verificationUri
|
|
145116
|
+
} : { status: "expired" };
|
|
145117
|
+
}
|
|
145118
|
+
return {
|
|
145119
|
+
status: "ok",
|
|
145120
|
+
accessToken: parsed.accessToken,
|
|
145121
|
+
refreshToken: parsed.refreshToken,
|
|
145122
|
+
expiresIn: parsed.expiresIn,
|
|
145123
|
+
user: parsed.user
|
|
145124
|
+
};
|
|
145125
|
+
};
|
|
145126
|
+
};
|
|
145127
|
+
var userWalletsSchema = external_exports3.array(userWalletDtoSchema);
|
|
145128
|
+
var normalizeMessage = (message2) => {
|
|
145129
|
+
if (typeof message2 === "string") return message2;
|
|
145130
|
+
if (typeof message2.raw === "string") return message2.raw;
|
|
145131
|
+
return bytesToHex(message2.raw);
|
|
145132
|
+
};
|
|
145133
|
+
var repackageSignFailure = (err, op) => {
|
|
145134
|
+
if (err instanceof ZeroApiError && err.status === 402) {
|
|
145135
|
+
const body = err.body;
|
|
145136
|
+
const detail = body && typeof body.error === "string" ? `: ${body.error}` : "";
|
|
145137
|
+
throw new ZeroPaymentError(
|
|
145138
|
+
`Sign endpoint refused ${op} (HTTP 402)${detail}`,
|
|
145139
|
+
{ cause: err }
|
|
145140
|
+
);
|
|
145141
|
+
}
|
|
145142
|
+
throw err;
|
|
145143
|
+
};
|
|
145144
|
+
var Auth = class {
|
|
145145
|
+
constructor(client) {
|
|
145146
|
+
this.client = client;
|
|
145147
|
+
this.device = new AuthDevice(client);
|
|
144526
145148
|
}
|
|
144527
145149
|
device;
|
|
144528
145150
|
// The internal (web-app facing) user profile. Richer than profile(): full
|
|
@@ -145005,816 +145627,201 @@ var Runs = class {
|
|
|
145005
145627
|
this.client,
|
|
145006
145628
|
{
|
|
145007
145629
|
method: "POST",
|
|
145008
|
-
path: "/v1/reviews/batch",
|
|
145009
|
-
body: { reviews },
|
|
145010
|
-
signal: opts.signal
|
|
145011
|
-
},
|
|
145012
|
-
batchReviewResponseSchema
|
|
145013
|
-
);
|
|
145014
|
-
};
|
|
145015
|
-
var USDC_BASE2 = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
|
|
145016
|
-
var USDC_TEMPO2 = "0x20c000000000000000000000b9537d11c60e8b50";
|
|
145017
|
-
var TEMPO_CHAIN_ID2 = 4217;
|
|
145018
|
-
var baseChain = base;
|
|
145019
|
-
var tempoChain2 = {
|
|
145020
|
-
id: TEMPO_CHAIN_ID2,
|
|
145021
|
-
name: "Tempo",
|
|
145022
|
-
nativeCurrency: { name: "USD", symbol: "USD", decimals: 18 },
|
|
145023
|
-
rpcUrls: {
|
|
145024
|
-
default: { http: ["https://rpc.tempo.xyz"] }
|
|
145025
|
-
}
|
|
145026
|
-
};
|
|
145027
|
-
var ERC20_BALANCE_ABI2 = [
|
|
145028
|
-
{
|
|
145029
|
-
inputs: [{ name: "account", type: "address" }],
|
|
145030
|
-
name: "balanceOf",
|
|
145031
|
-
outputs: [{ name: "", type: "uint256" }],
|
|
145032
|
-
stateMutability: "view",
|
|
145033
|
-
type: "function"
|
|
145034
|
-
}
|
|
145035
|
-
];
|
|
145036
|
-
var USDC_DECIMALS = 6;
|
|
145037
|
-
var fundingUrlResponseSchema = external_exports3.object({ url: external_exports3.string() });
|
|
145038
|
-
var userWalletListSchema = external_exports3.array(userWalletDtoSchema);
|
|
145039
|
-
var migrateAuthorizationResponseSchema = external_exports3.object({
|
|
145040
|
-
transactionHash: external_exports3.string()
|
|
145041
|
-
});
|
|
145042
|
-
var errorMessage = (reason) => reason instanceof Error ? reason.message : String(reason);
|
|
145043
|
-
var Wallet = class {
|
|
145044
|
-
constructor(client) {
|
|
145045
|
-
this.client = client;
|
|
145046
|
-
}
|
|
145047
|
-
clients = {};
|
|
145048
|
-
// The configured wallet address, or null if the client wasn't constructed
|
|
145049
|
-
// with an account. Stable read — does not hit the network.
|
|
145050
|
-
get address() {
|
|
145051
|
-
const credentials = this.client.getCredentials();
|
|
145052
|
-
if (credentials.kind !== "account") return null;
|
|
145053
|
-
return credentials.account.address;
|
|
145054
|
-
}
|
|
145055
|
-
balance = async (opts = {}) => {
|
|
145056
|
-
const target = opts.address ?? this.address;
|
|
145057
|
-
if (!target) {
|
|
145058
|
-
throw new ZeroWalletError(
|
|
145059
|
-
"balance() requires either an `address` option or a client constructed with an account"
|
|
145060
|
-
);
|
|
145061
|
-
}
|
|
145062
|
-
const chain2 = opts.chain ?? "total";
|
|
145063
|
-
if (chain2 !== "total") {
|
|
145064
|
-
const raw = await this.readChainBalance(chain2, target);
|
|
145065
|
-
return { amount: formatUnits(raw, USDC_DECIMALS), asset: "USDC" };
|
|
145066
|
-
}
|
|
145067
|
-
const chains = ["base", "tempo"];
|
|
145068
|
-
const settled = await Promise.allSettled(
|
|
145069
|
-
chains.map((c) => this.readChainBalance(c, target))
|
|
145070
|
-
);
|
|
145071
|
-
let sum = 0n;
|
|
145072
|
-
const errors = [];
|
|
145073
|
-
for (let i = 0; i < settled.length; i++) {
|
|
145074
|
-
const result = settled[i];
|
|
145075
|
-
const chainName = chains[i];
|
|
145076
|
-
if (!result || !chainName) continue;
|
|
145077
|
-
if (result.status === "fulfilled") {
|
|
145078
|
-
sum += result.value;
|
|
145079
|
-
} else {
|
|
145080
|
-
errors.push({ chain: chainName, message: errorMessage(result.reason) });
|
|
145081
|
-
}
|
|
145082
|
-
}
|
|
145083
|
-
if (errors.length === settled.length) {
|
|
145084
|
-
throw new ZeroWalletError(
|
|
145085
|
-
`balance() failed for every chain: ${errors.map((e2) => `${e2.chain} (${e2.message})`).join(", ")}`
|
|
145086
|
-
);
|
|
145087
|
-
}
|
|
145088
|
-
const balance = {
|
|
145089
|
-
amount: formatUnits(sum, USDC_DECIMALS),
|
|
145090
|
-
asset: "USDC"
|
|
145091
|
-
};
|
|
145092
|
-
if (errors.length > 0) balance.errors = errors;
|
|
145093
|
-
return balance;
|
|
145094
|
-
};
|
|
145095
|
-
// All wallets linked to the authenticated session user. Session-only.
|
|
145096
|
-
list = (opts = {}) => request2(
|
|
145097
|
-
this.client,
|
|
145098
|
-
{
|
|
145099
|
-
method: "GET",
|
|
145100
|
-
path: "/v1/users/me/wallets",
|
|
145101
|
-
signal: opts.signal
|
|
145102
|
-
},
|
|
145103
|
-
userWalletListSchema
|
|
145104
|
-
);
|
|
145105
|
-
// Provision a managed (Privy-embedded) wallet for the session user.
|
|
145106
|
-
// Idempotent server-side — repeat calls return the existing wallet.
|
|
145107
|
-
provision = (opts = {}) => request2(
|
|
145108
|
-
this.client,
|
|
145109
|
-
{
|
|
145110
|
-
method: "POST",
|
|
145111
|
-
path: "/v1/users/me/wallets/provision",
|
|
145112
|
-
signal: opts.signal
|
|
145113
|
-
},
|
|
145114
|
-
userWalletDtoSchema
|
|
145115
|
-
);
|
|
145116
|
-
// Relays a BYO-wallet-signed EIP-3009 ReceiveWithAuthorization, sweeping
|
|
145117
|
-
// USDC from the BYO wallet to the user's Zero wallet on Base via the
|
|
145118
|
-
// gas-paying relayer. The SDK does not author the authorization (chain
|
|
145119
|
-
// nonce + EIP-712 domain coupling stays caller-side); it only forwards
|
|
145120
|
-
// the signed payload. Session-only.
|
|
145121
|
-
migrateAuthorization = (authorization, opts = {}) => request2(
|
|
145122
|
-
this.client,
|
|
145123
|
-
{
|
|
145124
|
-
method: "POST",
|
|
145125
|
-
path: "/v1/users/me/wallets/migrate",
|
|
145126
|
-
body: { authorization },
|
|
145127
|
-
signal: opts.signal
|
|
145128
|
-
},
|
|
145129
|
-
migrateAuthorizationResponseSchema
|
|
145130
|
-
);
|
|
145131
|
-
// Routes by identity: account mode signs EIP-191 against /v1/wallet/fund-url,
|
|
145132
|
-
// session mode hits /v1/users/me/fund-url (Bearer-authed, wallet resolved
|
|
145133
|
-
// server-side). Both honor `provider` (coinbase | stripe).
|
|
145134
|
-
fundingUrl = async (opts = {}) => {
|
|
145135
|
-
const credentials = this.client.getCredentials();
|
|
145136
|
-
const path3 = credentials.kind === "account" ? "/v1/wallet/fund-url" : credentials.kind === "session" ? "/v1/users/me/fund-url" : null;
|
|
145137
|
-
if (!path3) {
|
|
145138
|
-
throw new ZeroWalletError(
|
|
145139
|
-
"fundingUrl() requires a client constructed with an account or session credentials"
|
|
145140
|
-
);
|
|
145141
|
-
}
|
|
145142
|
-
const query = {
|
|
145143
|
-
provider: opts.provider ?? "coinbase"
|
|
145144
|
-
};
|
|
145145
|
-
if (opts.amount) query.amount = opts.amount;
|
|
145146
|
-
const { url: url4 } = await request2(
|
|
145147
|
-
this.client,
|
|
145148
|
-
{ method: "GET", path: path3, query, signal: opts.signal },
|
|
145149
|
-
fundingUrlResponseSchema
|
|
145150
|
-
);
|
|
145151
|
-
return url4;
|
|
145152
|
-
};
|
|
145153
|
-
getPublicClient = (chain2) => {
|
|
145154
|
-
if (chain2 === "base") {
|
|
145155
|
-
if (!this.clients.base) {
|
|
145156
|
-
this.clients.base = createPublicClient({
|
|
145157
|
-
chain: baseChain,
|
|
145158
|
-
transport: http()
|
|
145159
|
-
});
|
|
145160
|
-
}
|
|
145161
|
-
return this.clients.base;
|
|
145162
|
-
}
|
|
145163
|
-
if (!this.clients.tempo) {
|
|
145164
|
-
this.clients.tempo = createPublicClient({
|
|
145165
|
-
// biome-ignore lint/suspicious/noExplicitAny: tempo is a custom chain object that viem's stricter Chain type rejects shape-wise but accepts at runtime
|
|
145166
|
-
chain: tempoChain2,
|
|
145167
|
-
transport: http()
|
|
145168
|
-
});
|
|
145169
|
-
}
|
|
145170
|
-
return this.clients.tempo;
|
|
145171
|
-
};
|
|
145172
|
-
/**
|
|
145173
|
-
* @internal
|
|
145174
|
-
*
|
|
145175
|
-
* Per-chain USDC balance read. Exposed (rather than private) so unit
|
|
145176
|
-
* tests can stub it without standing up a real viem public client —
|
|
145177
|
-
* viem's `http()` transport doesn't go through `client.fetchImpl`, so
|
|
145178
|
-
* the standard mock-fetch trick doesn't cover this path.
|
|
145179
|
-
*/
|
|
145180
|
-
readChainBalance = async (chain2, address2) => {
|
|
145181
|
-
const publicClient = this.getPublicClient(chain2);
|
|
145182
|
-
const tokenAddress = chain2 === "base" ? USDC_BASE2 : USDC_TEMPO2;
|
|
145183
|
-
const balance = await publicClient.readContract({
|
|
145184
|
-
address: tokenAddress,
|
|
145185
|
-
abi: ERC20_BALANCE_ABI2,
|
|
145186
|
-
functionName: "balanceOf",
|
|
145187
|
-
args: [address2]
|
|
145188
|
-
});
|
|
145189
|
-
return balance;
|
|
145190
|
-
};
|
|
145191
|
-
};
|
|
145192
|
-
var DEFAULT_BASE_URL = "https://api.zero.xyz";
|
|
145193
|
-
var DEFAULT_TIMEOUT_MS = 18e4;
|
|
145194
|
-
var DEFAULT_MAX_RETRIES = 2;
|
|
145195
|
-
var noopRefresh = async () => {
|
|
145196
|
-
};
|
|
145197
|
-
var MAX_402_PROBE_BYTES = 1024 * 1024;
|
|
145198
|
-
var MAX_RESPONSE_BYTES = 10 * 1024 * 1024;
|
|
145199
|
-
var TEXT_CONTENT_TYPES = [
|
|
145200
|
-
"application/json",
|
|
145201
|
-
"application/xml",
|
|
145202
|
-
"application/javascript",
|
|
145203
|
-
"application/ecmascript",
|
|
145204
|
-
"application/x-www-form-urlencoded",
|
|
145205
|
-
"text/",
|
|
145206
|
-
"+json",
|
|
145207
|
-
"+xml"
|
|
145208
|
-
];
|
|
145209
|
-
var MPP_SCHEME_TOKENS = /* @__PURE__ */ new Set(["payment", "mpp"]);
|
|
145210
|
-
var splitWwwAuthenticateChallenges = (header) => {
|
|
145211
|
-
const chunks = [];
|
|
145212
|
-
let buf = "";
|
|
145213
|
-
let inQuotes = false;
|
|
145214
|
-
for (let i = 0; i < header.length; i++) {
|
|
145215
|
-
const ch = header[i];
|
|
145216
|
-
if (inQuotes) {
|
|
145217
|
-
if (ch === "\\" && i + 1 < header.length) {
|
|
145218
|
-
buf += ch + header[i + 1];
|
|
145219
|
-
i++;
|
|
145220
|
-
continue;
|
|
145221
|
-
}
|
|
145222
|
-
if (ch === '"') inQuotes = false;
|
|
145223
|
-
buf += ch;
|
|
145224
|
-
continue;
|
|
145225
|
-
}
|
|
145226
|
-
if (ch === '"') {
|
|
145227
|
-
inQuotes = true;
|
|
145228
|
-
buf += ch;
|
|
145229
|
-
continue;
|
|
145230
|
-
}
|
|
145231
|
-
if (ch === ",") {
|
|
145232
|
-
chunks.push(buf);
|
|
145233
|
-
buf = "";
|
|
145234
|
-
continue;
|
|
145235
|
-
}
|
|
145236
|
-
buf += ch;
|
|
145237
|
-
}
|
|
145238
|
-
if (buf.length > 0) chunks.push(buf);
|
|
145239
|
-
return chunks;
|
|
145240
|
-
};
|
|
145241
|
-
var isTextContentType = (contentType) => {
|
|
145242
|
-
if (!contentType) return true;
|
|
145243
|
-
const lower = contentType.toLowerCase();
|
|
145244
|
-
return TEXT_CONTENT_TYPES.some((marker) => lower.includes(marker));
|
|
145245
|
-
};
|
|
145246
|
-
var redactUrl2 = (url4) => {
|
|
145247
|
-
try {
|
|
145248
|
-
const u2 = new URL(url4);
|
|
145249
|
-
return `${u2.origin}${u2.pathname}`;
|
|
145250
|
-
} catch {
|
|
145251
|
-
return "<invalid url>";
|
|
145252
|
-
}
|
|
145253
|
-
};
|
|
145254
|
-
var ECHO_DETECT_MIN_LEN = 16;
|
|
145255
|
-
var ECHO_DETECT_MAX_SCAN = 64 * 1024;
|
|
145256
|
-
var requestBodyEchoed = (candidate, requestBody) => {
|
|
145257
|
-
if (requestBody === void 0) return false;
|
|
145258
|
-
const asString = typeof requestBody === "string" ? requestBody : new TextDecoder("utf-8", { fatal: false }).decode(
|
|
145259
|
-
requestBody.byteLength > ECHO_DETECT_MAX_SCAN ? requestBody.subarray(0, ECHO_DETECT_MAX_SCAN) : requestBody
|
|
145260
|
-
);
|
|
145261
|
-
if (asString.length < ECHO_DETECT_MIN_LEN) return false;
|
|
145262
|
-
const scanLen = Math.min(asString.length, ECHO_DETECT_MAX_SCAN);
|
|
145263
|
-
for (let i = 0; i + ECHO_DETECT_MIN_LEN <= scanLen; i++) {
|
|
145264
|
-
if (candidate.includes(asString.slice(i, i + ECHO_DETECT_MIN_LEN))) {
|
|
145265
|
-
return true;
|
|
145266
|
-
}
|
|
145267
|
-
}
|
|
145268
|
-
return false;
|
|
145269
|
-
};
|
|
145270
|
-
var cancelBody2 = (response) => {
|
|
145271
|
-
try {
|
|
145272
|
-
response.body?.cancel().catch(() => {
|
|
145273
|
-
});
|
|
145274
|
-
} catch {
|
|
145275
|
-
}
|
|
145276
|
-
};
|
|
145277
|
-
var detectPaymentRequirement = async (response) => {
|
|
145278
|
-
if (response.status !== 402) return null;
|
|
145279
|
-
const x402Header = response.headers.get("payment-required") ?? response.headers.get("x-payment-required");
|
|
145280
|
-
if (x402Header) {
|
|
145281
|
-
cancelBody2(response);
|
|
145282
|
-
try {
|
|
145283
|
-
const decoded = JSON.parse(
|
|
145284
|
-
Buffer.from(x402Header, "base64").toString("utf8")
|
|
145285
|
-
);
|
|
145286
|
-
return { protocol: "x402", raw: decoded };
|
|
145287
|
-
} catch {
|
|
145288
|
-
return { protocol: "x402", raw: { encoded: x402Header } };
|
|
145289
|
-
}
|
|
145290
|
-
}
|
|
145291
|
-
const declaredLen = Number.parseInt(
|
|
145292
|
-
response.headers.get("content-length") ?? "",
|
|
145293
|
-
10
|
|
145294
|
-
);
|
|
145295
|
-
const bodyFits = !Number.isFinite(declaredLen) || declaredLen <= MAX_402_PROBE_BYTES;
|
|
145296
|
-
if (bodyFits) {
|
|
145297
|
-
try {
|
|
145298
|
-
const text = await readClippedText(response, MAX_402_PROBE_BYTES);
|
|
145299
|
-
if (text) {
|
|
145300
|
-
const parsed = JSON.parse(text);
|
|
145301
|
-
if (looksLikeX402Body(parsed)) {
|
|
145302
|
-
return { protocol: "x402", raw: parsed };
|
|
145303
|
-
}
|
|
145304
|
-
}
|
|
145305
|
-
} catch {
|
|
145306
|
-
}
|
|
145307
|
-
}
|
|
145308
|
-
const wwwAuth = response.headers.get("www-authenticate");
|
|
145309
|
-
if (wwwAuth) {
|
|
145310
|
-
const schemes = splitWwwAuthenticateChallenges(wwwAuth).map(
|
|
145311
|
-
(challenge2) => challenge2.trim().split(/\s+/)[0]?.toLowerCase() ?? ""
|
|
145312
|
-
);
|
|
145313
|
-
if (schemes.some((scheme) => MPP_SCHEME_TOKENS.has(scheme))) {
|
|
145314
|
-
cancelBody2(response);
|
|
145315
|
-
return { protocol: "mpp", raw: { "www-authenticate": wwwAuth } };
|
|
145316
|
-
}
|
|
145317
|
-
}
|
|
145318
|
-
cancelBody2(response);
|
|
145319
|
-
return { protocol: "unknown", raw: {} };
|
|
145320
|
-
};
|
|
145321
|
-
var readClippedBytes = async (response, max) => {
|
|
145322
|
-
if (response.body === null) return new Uint8Array(0);
|
|
145323
|
-
const reader = response.body.getReader();
|
|
145324
|
-
const chunks = [];
|
|
145325
|
-
let total = 0;
|
|
145326
|
-
try {
|
|
145327
|
-
while (total < max) {
|
|
145328
|
-
const { done, value } = await reader.read();
|
|
145329
|
-
if (done) break;
|
|
145330
|
-
if (!value) continue;
|
|
145331
|
-
chunks.push(value);
|
|
145332
|
-
total += value.byteLength;
|
|
145333
|
-
}
|
|
145334
|
-
} finally {
|
|
145335
|
-
try {
|
|
145336
|
-
await reader.cancel();
|
|
145337
|
-
} catch {
|
|
145338
|
-
}
|
|
145339
|
-
}
|
|
145340
|
-
const merged = new Uint8Array(Math.min(total, max));
|
|
145341
|
-
let offset = 0;
|
|
145342
|
-
for (const c of chunks) {
|
|
145343
|
-
const take = Math.min(c.byteLength, max - offset);
|
|
145344
|
-
merged.set(c.subarray(0, take), offset);
|
|
145345
|
-
offset += take;
|
|
145346
|
-
if (offset >= max) break;
|
|
145347
|
-
}
|
|
145348
|
-
return merged;
|
|
145349
|
-
};
|
|
145350
|
-
var readClippedText = async (response, max) => {
|
|
145351
|
-
const bytes = await readClippedBytes(response, max);
|
|
145352
|
-
return new TextDecoder().decode(bytes);
|
|
145353
|
-
};
|
|
145354
|
-
var parseResponseBody = async (response, max) => {
|
|
145355
|
-
const contentType = response.headers.get("content-type");
|
|
145356
|
-
const bytes = await readClippedBytes(response, max + 1);
|
|
145357
|
-
const truncated = bytes.byteLength > max;
|
|
145358
|
-
const view = truncated ? bytes.subarray(0, max) : bytes;
|
|
145359
|
-
const buf = Buffer.from(view.buffer, view.byteOffset, view.byteLength);
|
|
145360
|
-
if (!isTextContentType(contentType)) {
|
|
145361
|
-
const base644 = buf.toString("base64");
|
|
145362
|
-
return {
|
|
145363
|
-
body: base644,
|
|
145364
|
-
bodyRaw: base644,
|
|
145365
|
-
bodyEncoding: "base64",
|
|
145366
|
-
truncated
|
|
145367
|
-
};
|
|
145368
|
-
}
|
|
145369
|
-
const text = buf.toString("utf8");
|
|
145370
|
-
if (contentType?.toLowerCase().includes("json")) {
|
|
145371
|
-
try {
|
|
145372
|
-
return { body: JSON.parse(text), bodyRaw: text, truncated };
|
|
145373
|
-
} catch {
|
|
145374
|
-
}
|
|
145375
|
-
}
|
|
145376
|
-
return { body: text, bodyRaw: text, truncated };
|
|
145377
|
-
};
|
|
145378
|
-
var UPSTREAM_ERROR_FIELDS = [
|
|
145379
|
-
"error",
|
|
145380
|
-
"message",
|
|
145381
|
-
"detail",
|
|
145382
|
-
"reason",
|
|
145383
|
-
"error_description"
|
|
145384
|
-
];
|
|
145385
|
-
var UPSTREAM_ERROR_MAX_LEN = 200;
|
|
145386
|
-
var ERROR_SNIPPET_BYTES = 500;
|
|
145387
|
-
var clampUpstreamMessage = (value) => {
|
|
145388
|
-
const trimmed = value.trim();
|
|
145389
|
-
if (!trimmed) return void 0;
|
|
145390
|
-
return trimmed.length > UPSTREAM_ERROR_MAX_LEN ? `${trimmed.slice(0, UPSTREAM_ERROR_MAX_LEN)}\u2026` : trimmed;
|
|
145391
|
-
};
|
|
145392
|
-
var tryParseJson = (text) => {
|
|
145393
|
-
try {
|
|
145394
|
-
return JSON.parse(text);
|
|
145395
|
-
} catch {
|
|
145396
|
-
return null;
|
|
145397
|
-
}
|
|
145398
|
-
};
|
|
145399
|
-
var extractUpstreamErrorMessage = (body) => {
|
|
145400
|
-
const parsed = tryParseJson(body);
|
|
145401
|
-
if (parsed === null || typeof parsed !== "object") {
|
|
145402
|
-
return clampUpstreamMessage(body);
|
|
145403
|
-
}
|
|
145404
|
-
const record3 = parsed;
|
|
145405
|
-
for (const field of UPSTREAM_ERROR_FIELDS) {
|
|
145406
|
-
const value = record3[field];
|
|
145407
|
-
if (typeof value === "string" && value.length > 0) {
|
|
145408
|
-
return clampUpstreamMessage(value);
|
|
145409
|
-
}
|
|
145410
|
-
if (value && typeof value === "object") {
|
|
145411
|
-
const nested = value.message;
|
|
145412
|
-
if (typeof nested === "string" && nested.length > 0) {
|
|
145413
|
-
return clampUpstreamMessage(nested);
|
|
145414
|
-
}
|
|
145415
|
-
}
|
|
145416
|
-
}
|
|
145417
|
-
return void 0;
|
|
145418
|
-
};
|
|
145419
|
-
var buildUpstreamError = (status, bodyRaw, bodyEncoding) => {
|
|
145420
|
-
if (status >= 200 && status < 300) return void 0;
|
|
145421
|
-
if (bodyRaw === null || bodyRaw.length === 0) return void 0;
|
|
145422
|
-
if (bodyEncoding === "base64") return void 0;
|
|
145423
|
-
const snippet = bodyRaw.slice(0, ERROR_SNIPPET_BYTES);
|
|
145424
|
-
return {
|
|
145425
|
-
status,
|
|
145426
|
-
message: extractUpstreamErrorMessage(bodyRaw),
|
|
145427
|
-
snippetHash: createHash("sha256").update(snippet).digest("hex"),
|
|
145428
|
-
snippetLength: snippet.length
|
|
145429
|
-
};
|
|
145430
|
-
};
|
|
145431
|
-
var computeOutcome = (status, payment, warnings) => {
|
|
145432
|
-
if (warnings.includes(FETCH_WARNINGS.mppSessionCloseFailed))
|
|
145433
|
-
return "payment_close_failed";
|
|
145434
|
-
if (status === 402 && payment !== null) return "payment_rejected";
|
|
145435
|
-
if (status === 402) return "payment_failed";
|
|
145436
|
-
if (status >= 400) return "server_error";
|
|
145437
|
-
return "success";
|
|
145438
|
-
};
|
|
145439
|
-
var errorFetchResult = (startedAt, error48, skipReason, capabilityIdRequested, outcome, status = null) => {
|
|
145440
|
-
const result = {
|
|
145441
|
-
runId: null,
|
|
145442
|
-
ok: false,
|
|
145443
|
-
status,
|
|
145444
|
-
latencyMs: Date.now() - startedAt,
|
|
145445
|
-
payment: null,
|
|
145446
|
-
outcome,
|
|
145447
|
-
body: null,
|
|
145448
|
-
bodyRaw: null,
|
|
145449
|
-
error: error48
|
|
145450
|
-
};
|
|
145451
|
-
if (capabilityIdRequested) result.runTrackingSkipped = [skipReason];
|
|
145452
|
-
return result;
|
|
145453
|
-
};
|
|
145454
|
-
var resolveRecordingClient = (client, opts) => {
|
|
145455
|
-
const credentials = client.getCredentials();
|
|
145456
|
-
const recordingClient = opts.account ? client.withAccount(opts.account) : client;
|
|
145457
|
-
const canRecord = opts.account !== void 0 || credentials.kind === "account" || credentials.kind === "session";
|
|
145458
|
-
return { recordingClient, canRecord };
|
|
145459
|
-
};
|
|
145460
|
-
var recordErrorFetchRun = async (client, opts, result, capabilityIdOverride) => {
|
|
145461
|
-
const effectiveCapId = opts.capabilityId;
|
|
145462
|
-
if (effectiveCapId === void 0) return;
|
|
145463
|
-
const { recordingClient, canRecord } = resolveRecordingClient(client, opts);
|
|
145464
|
-
if (!canRecord) return;
|
|
145465
|
-
const fetchOriginForRecord = opts.capabilityId === void 0 ? "direct_url" : opts.fetchOrigin;
|
|
145466
|
-
try {
|
|
145467
|
-
const created = await recordingClient.runs.create({
|
|
145468
|
-
capabilityId: effectiveCapId,
|
|
145469
|
-
...opts.searchId && { searchId: opts.searchId },
|
|
145470
|
-
...fetchOriginForRecord && { fetchOrigin: fetchOriginForRecord },
|
|
145471
|
-
...result.status !== null && { status: result.status },
|
|
145472
|
-
latencyMs: result.latencyMs,
|
|
145473
|
-
...opts.requestSchema && { requestSchema: opts.requestSchema }
|
|
145474
|
-
});
|
|
145475
|
-
result.runId = created.runId;
|
|
145476
|
-
delete result.runTrackingSkipped;
|
|
145477
|
-
} catch {
|
|
145478
|
-
}
|
|
145479
|
-
};
|
|
145480
|
-
var recordTimeoutRun = async (client, opts, err, startedAt, capabilityIdRequested, capabilityIdOverride) => {
|
|
145481
|
-
const result = errorFetchResult(
|
|
145482
|
-
startedAt,
|
|
145483
|
-
err.message,
|
|
145484
|
-
"timeout",
|
|
145485
|
-
capabilityIdRequested,
|
|
145486
|
-
"network_error"
|
|
145630
|
+
path: "/v1/reviews/batch",
|
|
145631
|
+
body: { reviews },
|
|
145632
|
+
signal: opts.signal
|
|
145633
|
+
},
|
|
145634
|
+
batchReviewResponseSchema
|
|
145487
145635
|
);
|
|
145488
|
-
await recordErrorFetchRun(client, opts, result);
|
|
145489
145636
|
};
|
|
145490
|
-
var
|
|
145491
|
-
|
|
145492
|
-
|
|
145493
|
-
|
|
145494
|
-
|
|
145495
|
-
|
|
145496
|
-
|
|
145637
|
+
var USDC_BASE2 = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
|
|
145638
|
+
var USDC_TEMPO2 = "0x20c000000000000000000000b9537d11c60e8b50";
|
|
145639
|
+
var TEMPO_CHAIN_ID2 = 4217;
|
|
145640
|
+
var baseChain = base;
|
|
145641
|
+
var tempoChain2 = {
|
|
145642
|
+
id: TEMPO_CHAIN_ID2,
|
|
145643
|
+
name: "Tempo",
|
|
145644
|
+
nativeCurrency: { name: "USD", symbol: "USD", decimals: 18 },
|
|
145645
|
+
rpcUrls: {
|
|
145646
|
+
default: { http: ["https://rpc.tempo.xyz"] }
|
|
145497
145647
|
}
|
|
145498
|
-
if (i >= buf.length) return false;
|
|
145499
|
-
return buf[i] === 123 || buf[i] === 91;
|
|
145500
145648
|
};
|
|
145501
|
-
var
|
|
145502
|
-
|
|
145503
|
-
|
|
145504
|
-
|
|
145505
|
-
|
|
145506
|
-
|
|
145507
|
-
|
|
145508
|
-
if (!hasContentType) {
|
|
145509
|
-
next["content-type"] = typeof body === "string" || sniffJsonShapeBytes(body) ? "application/json" : "application/octet-stream";
|
|
145649
|
+
var ERC20_BALANCE_ABI2 = [
|
|
145650
|
+
{
|
|
145651
|
+
inputs: [{ name: "account", type: "address" }],
|
|
145652
|
+
name: "balanceOf",
|
|
145653
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
145654
|
+
stateMutability: "view",
|
|
145655
|
+
type: "function"
|
|
145510
145656
|
}
|
|
145511
|
-
|
|
145512
|
-
|
|
145513
|
-
var
|
|
145514
|
-
|
|
145515
|
-
|
|
145516
|
-
|
|
145517
|
-
|
|
145518
|
-
|
|
145519
|
-
|
|
145520
|
-
|
|
145521
|
-
|
|
145522
|
-
const method = normalized.method ?? (requestBody !== void 0 ? "POST" : "GET");
|
|
145523
|
-
const { canRecord: canRecordForResolve } = resolveRecordingClient(
|
|
145524
|
-
client,
|
|
145525
|
-
opts
|
|
145526
|
-
);
|
|
145527
|
-
const resolvePromise = !capabilityIdRequested && canRecordForResolve ? client.capabilities.resolveByUrl(redactUrl2(requestUrl), method).catch(() => null) : Promise.resolve(null);
|
|
145528
|
-
const probeHeaders = withDefaultContentType(opts.headers, requestBody);
|
|
145529
|
-
const requestInit = {
|
|
145530
|
-
method,
|
|
145531
|
-
headers: probeHeaders,
|
|
145532
|
-
body: requestBody,
|
|
145533
|
-
signal: opts.signal
|
|
145534
|
-
};
|
|
145535
|
-
const configuredFetch = buildConfiguredFetch(client, {
|
|
145536
|
-
timeoutMs: opts.timeoutMs
|
|
145537
|
-
});
|
|
145538
|
-
let response;
|
|
145539
|
-
let payment = null;
|
|
145540
|
-
const skipReasons = [];
|
|
145541
|
-
const warnings = [];
|
|
145542
|
-
try {
|
|
145543
|
-
response = await configuredFetch(requestUrl, requestInit);
|
|
145544
|
-
} catch (err) {
|
|
145545
|
-
if (err instanceof ZeroTimeoutError) {
|
|
145546
|
-
await recordTimeoutRun(
|
|
145547
|
-
client,
|
|
145548
|
-
opts,
|
|
145549
|
-
err,
|
|
145550
|
-
startedAt,
|
|
145551
|
-
capabilityIdRequested
|
|
145552
|
-
);
|
|
145553
|
-
throw err;
|
|
145554
|
-
}
|
|
145555
|
-
if (err instanceof ZeroError) throw err;
|
|
145556
|
-
const errMessage = err instanceof Error ? err.message : String(err);
|
|
145557
|
-
const result2 = errorFetchResult(
|
|
145558
|
-
startedAt,
|
|
145559
|
-
errMessage,
|
|
145560
|
-
"fetch_failed_before_response",
|
|
145561
|
-
capabilityIdRequested,
|
|
145562
|
-
"network_error"
|
|
145563
|
-
);
|
|
145564
|
-
await recordErrorFetchRun(client, opts, result2);
|
|
145565
|
-
return result2;
|
|
145657
|
+
];
|
|
145658
|
+
var USDC_DECIMALS = 6;
|
|
145659
|
+
var fundingUrlResponseSchema = external_exports3.object({ url: external_exports3.string() });
|
|
145660
|
+
var userWalletListSchema = external_exports3.array(userWalletDtoSchema);
|
|
145661
|
+
var migrateAuthorizationResponseSchema = external_exports3.object({
|
|
145662
|
+
transactionHash: external_exports3.string()
|
|
145663
|
+
});
|
|
145664
|
+
var errorMessage = (reason) => reason instanceof Error ? reason.message : String(reason);
|
|
145665
|
+
var Wallet = class {
|
|
145666
|
+
constructor(client) {
|
|
145667
|
+
this.client = client;
|
|
145566
145668
|
}
|
|
145567
|
-
|
|
145568
|
-
|
|
145569
|
-
|
|
145570
|
-
|
|
145571
|
-
|
|
145572
|
-
|
|
145573
|
-
|
|
145574
|
-
method,
|
|
145575
|
-
// Fresh clone for the paid retry — same rationale as
|
|
145576
|
-
// the probe-side clone above. Re-derives the default
|
|
145577
|
-
// Content-Type so the paid leg matches the probe.
|
|
145578
|
-
headers: withDefaultContentType(opts.headers, requestBody),
|
|
145579
|
-
body: requestBody,
|
|
145580
|
-
maxPay: opts.maxPay,
|
|
145581
|
-
account: opts.account,
|
|
145582
|
-
signal: opts.signal,
|
|
145583
|
-
timeoutMs: opts.timeoutMs,
|
|
145584
|
-
...opts.displayCostAmount && {
|
|
145585
|
-
displayCostAmount: opts.displayCostAmount
|
|
145586
|
-
}
|
|
145587
|
-
});
|
|
145588
|
-
response = paid.response;
|
|
145589
|
-
payment = paid.payment;
|
|
145590
|
-
if (paid.warnings) warnings.push(...paid.warnings);
|
|
145591
|
-
} catch (err) {
|
|
145592
|
-
if (err instanceof ZeroSessionCloseFailedError) {
|
|
145593
|
-
response = err.response;
|
|
145594
|
-
payment = {
|
|
145595
|
-
protocol: "mpp",
|
|
145596
|
-
chain: tempoChainLabelFromId(err.session.chainId),
|
|
145597
|
-
txHash: null,
|
|
145598
|
-
amount: err.capturedAmount,
|
|
145599
|
-
asset: "USDC",
|
|
145600
|
-
session: err.session
|
|
145601
|
-
};
|
|
145602
|
-
warnings.push(FETCH_WARNINGS.mppSessionCloseFailed);
|
|
145603
|
-
} else if (err instanceof ZeroInsufficientFundsError) {
|
|
145604
|
-
return errorFetchResult(
|
|
145605
|
-
startedAt,
|
|
145606
|
-
err.message,
|
|
145607
|
-
FETCH_SKIP_REASONS.insufficientFunds,
|
|
145608
|
-
capabilityIdRequested,
|
|
145609
|
-
"insufficient_funds",
|
|
145610
|
-
null
|
|
145611
|
-
);
|
|
145612
|
-
} else if (err instanceof ZeroPaymentError || err instanceof ZeroAuthError) {
|
|
145613
|
-
const result2 = errorFetchResult(
|
|
145614
|
-
startedAt,
|
|
145615
|
-
err.message,
|
|
145616
|
-
"payment_failed",
|
|
145617
|
-
capabilityIdRequested,
|
|
145618
|
-
"payment_failed",
|
|
145619
|
-
402
|
|
145620
|
-
);
|
|
145621
|
-
await recordErrorFetchRun(client, opts, result2);
|
|
145622
|
-
return result2;
|
|
145623
|
-
} else if (err instanceof ZeroTimeoutError) {
|
|
145624
|
-
await recordTimeoutRun(
|
|
145625
|
-
client,
|
|
145626
|
-
opts,
|
|
145627
|
-
err,
|
|
145628
|
-
startedAt,
|
|
145629
|
-
capabilityIdRequested
|
|
145630
|
-
);
|
|
145631
|
-
throw err;
|
|
145632
|
-
} else {
|
|
145633
|
-
throw err;
|
|
145634
|
-
}
|
|
145635
|
-
}
|
|
145636
|
-
} else if (requirement?.protocol === "unknown") {
|
|
145637
|
-
const result2 = errorFetchResult(
|
|
145638
|
-
startedAt,
|
|
145639
|
-
"Capability returned 402 with an unrecognized payment protocol. Neither x402 nor MPP markers were detected in the response headers or body.",
|
|
145640
|
-
"unrecognized_402_protocol",
|
|
145641
|
-
capabilityIdRequested,
|
|
145642
|
-
"payment_failed",
|
|
145643
|
-
402
|
|
145644
|
-
);
|
|
145645
|
-
await recordErrorFetchRun(client, opts, result2);
|
|
145646
|
-
return result2;
|
|
145647
|
-
}
|
|
145669
|
+
clients = {};
|
|
145670
|
+
// The configured wallet address, or null if the client wasn't constructed
|
|
145671
|
+
// with an account. Stable read — does not hit the network.
|
|
145672
|
+
get address() {
|
|
145673
|
+
const credentials = this.client.getCredentials();
|
|
145674
|
+
if (credentials.kind !== "account") return null;
|
|
145675
|
+
return credentials.account.address;
|
|
145648
145676
|
}
|
|
145649
|
-
|
|
145650
|
-
|
|
145651
|
-
|
|
145652
|
-
|
|
145653
|
-
|
|
145654
|
-
|
|
145655
|
-
const parsed = await parseResponseBody(response, maxResponseBytes);
|
|
145656
|
-
body = parsed.body;
|
|
145657
|
-
bodyRaw = parsed.bodyRaw;
|
|
145658
|
-
bodyEncoding = parsed.bodyEncoding;
|
|
145659
|
-
if (parsed.truncated) warnings.push(FETCH_WARNINGS.bodyTruncated);
|
|
145660
|
-
} catch (err) {
|
|
145661
|
-
if (err instanceof Error && err.name === "AbortError") {
|
|
145662
|
-
throw new ZeroApiError("Request aborted by caller", {
|
|
145663
|
-
status: 0,
|
|
145664
|
-
cause: err
|
|
145665
|
-
});
|
|
145677
|
+
balance = async (opts = {}) => {
|
|
145678
|
+
const target = opts.address ?? this.address;
|
|
145679
|
+
if (!target) {
|
|
145680
|
+
throw new ZeroWalletError(
|
|
145681
|
+
"balance() requires either an `address` option or a client constructed with an account"
|
|
145682
|
+
);
|
|
145666
145683
|
}
|
|
145667
|
-
const
|
|
145668
|
-
|
|
145669
|
-
|
|
145670
|
-
|
|
145671
|
-
warnings.push(FETCH_WARNINGS.paidButStill402NotRecorded);
|
|
145672
|
-
skips.push(FETCH_WARNINGS.paidButStill402NotRecorded);
|
|
145684
|
+
const chain2 = opts.chain ?? "total";
|
|
145685
|
+
if (chain2 !== "total") {
|
|
145686
|
+
const raw = await this.readChainBalance(chain2, target);
|
|
145687
|
+
return { amount: formatUnits(raw, USDC_DECIMALS), asset: "USDC" };
|
|
145673
145688
|
}
|
|
145674
|
-
|
|
145675
|
-
|
|
145676
|
-
|
|
145689
|
+
const chains = ["base", "tempo"];
|
|
145690
|
+
const settled = await Promise.allSettled(
|
|
145691
|
+
chains.map((c) => this.readChainBalance(c, target))
|
|
145692
|
+
);
|
|
145693
|
+
let sum = 0n;
|
|
145694
|
+
const errors = [];
|
|
145695
|
+
for (let i = 0; i < settled.length; i++) {
|
|
145696
|
+
const result = settled[i];
|
|
145697
|
+
const chainName = chains[i];
|
|
145698
|
+
if (!result || !chainName) continue;
|
|
145699
|
+
if (result.status === "fulfilled") {
|
|
145700
|
+
sum += result.value;
|
|
145701
|
+
} else {
|
|
145702
|
+
errors.push({ chain: chainName, message: errorMessage(result.reason) });
|
|
145703
|
+
}
|
|
145677
145704
|
}
|
|
145678
|
-
if (
|
|
145679
|
-
|
|
145705
|
+
if (errors.length === settled.length) {
|
|
145706
|
+
throw new ZeroWalletError(
|
|
145707
|
+
`balance() failed for every chain: ${errors.map((e2) => `${e2.chain} (${e2.message})`).join(", ")}`
|
|
145708
|
+
);
|
|
145680
145709
|
}
|
|
145681
|
-
|
|
145682
|
-
|
|
145683
|
-
|
|
145684
|
-
ok: false,
|
|
145685
|
-
status: response.status,
|
|
145686
|
-
latencyMs: Date.now() - startedAt,
|
|
145687
|
-
payment,
|
|
145688
|
-
outcome: computeOutcome(response.status, payment, warnings),
|
|
145689
|
-
body: null,
|
|
145690
|
-
bodyRaw: null,
|
|
145691
|
-
error: message2
|
|
145710
|
+
const balance = {
|
|
145711
|
+
amount: formatUnits(sum, USDC_DECIMALS),
|
|
145712
|
+
asset: "USDC"
|
|
145692
145713
|
};
|
|
145693
|
-
if (
|
|
145694
|
-
|
|
145695
|
-
|
|
145696
|
-
|
|
145697
|
-
|
|
145698
|
-
|
|
145699
|
-
|
|
145700
|
-
|
|
145701
|
-
|
|
145702
|
-
|
|
145703
|
-
|
|
145704
|
-
|
|
145705
|
-
}
|
|
145706
|
-
let runId = null;
|
|
145707
|
-
const closeFailed = warnings.includes(FETCH_WARNINGS.mppSessionCloseFailed);
|
|
145708
|
-
const upstreamErrorForRecord = buildUpstreamError(
|
|
145709
|
-
response.status,
|
|
145710
|
-
bodyRaw,
|
|
145711
|
-
bodyEncoding
|
|
145714
|
+
if (errors.length > 0) balance.errors = errors;
|
|
145715
|
+
return balance;
|
|
145716
|
+
};
|
|
145717
|
+
// All wallets linked to the authenticated session user. Session-only.
|
|
145718
|
+
list = (opts = {}) => request2(
|
|
145719
|
+
this.client,
|
|
145720
|
+
{
|
|
145721
|
+
method: "GET",
|
|
145722
|
+
path: "/v1/users/me/wallets",
|
|
145723
|
+
signal: opts.signal
|
|
145724
|
+
},
|
|
145725
|
+
userWalletListSchema
|
|
145712
145726
|
);
|
|
145713
|
-
|
|
145714
|
-
|
|
145715
|
-
|
|
145716
|
-
|
|
145717
|
-
|
|
145718
|
-
|
|
145719
|
-
|
|
145720
|
-
|
|
145721
|
-
|
|
145722
|
-
|
|
145723
|
-
|
|
145724
|
-
|
|
145725
|
-
|
|
145726
|
-
|
|
145727
|
-
|
|
145728
|
-
|
|
145729
|
-
|
|
145730
|
-
|
|
145731
|
-
|
|
145732
|
-
|
|
145733
|
-
|
|
145734
|
-
|
|
145735
|
-
|
|
145736
|
-
|
|
145737
|
-
|
|
145738
|
-
|
|
145739
|
-
|
|
145740
|
-
|
|
145741
|
-
|
|
145742
|
-
|
|
145743
|
-
|
|
145744
|
-
|
|
145745
|
-
|
|
145746
|
-
|
|
145747
|
-
|
|
145748
|
-
|
|
145749
|
-
|
|
145750
|
-
|
|
145751
|
-
|
|
145752
|
-
|
|
145753
|
-
|
|
145754
|
-
|
|
145755
|
-
|
|
145756
|
-
|
|
145757
|
-
|
|
145758
|
-
|
|
145759
|
-
|
|
145760
|
-
|
|
145761
|
-
|
|
145762
|
-
|
|
145763
|
-
|
|
145764
|
-
|
|
145765
|
-
|
|
145766
|
-
|
|
145767
|
-
paymentProtocol: payment.protocol,
|
|
145768
|
-
paymentChain: payment.chain,
|
|
145769
|
-
paymentTxHash: payment.txHash ?? void 0,
|
|
145770
|
-
paymentMode: payment.session ? "session" : "charge"
|
|
145771
|
-
}
|
|
145772
|
-
});
|
|
145773
|
-
runId = result2.runId;
|
|
145774
|
-
} catch (err) {
|
|
145775
|
-
const errorMessage22 = err instanceof Error ? err.message : String(err);
|
|
145776
|
-
const code = err instanceof ZeroError ? err.code : void 0;
|
|
145777
|
-
const skipMsg = code ? `run_create_failed:${code}: ${errorMessage22}` : `run_create_failed: ${errorMessage22}`;
|
|
145778
|
-
skipReasons.push(skipMsg);
|
|
145779
|
-
client.logger?.({
|
|
145780
|
-
level: "warn",
|
|
145781
|
-
message: "Failed to record run for fetch",
|
|
145782
|
-
meta: {
|
|
145783
|
-
url: redactUrl2(url4),
|
|
145784
|
-
capabilityId: effectiveCapabilityId,
|
|
145785
|
-
error: errorMessage22,
|
|
145786
|
-
errorCode: code
|
|
145787
|
-
}
|
|
145727
|
+
// Provision a managed (Privy-embedded) wallet for the session user.
|
|
145728
|
+
// Idempotent server-side — repeat calls return the existing wallet.
|
|
145729
|
+
provision = (opts = {}) => request2(
|
|
145730
|
+
this.client,
|
|
145731
|
+
{
|
|
145732
|
+
method: "POST",
|
|
145733
|
+
path: "/v1/users/me/wallets/provision",
|
|
145734
|
+
signal: opts.signal
|
|
145735
|
+
},
|
|
145736
|
+
userWalletDtoSchema
|
|
145737
|
+
);
|
|
145738
|
+
// Relays a BYO-wallet-signed EIP-3009 ReceiveWithAuthorization, sweeping
|
|
145739
|
+
// USDC from the BYO wallet to the user's Zero wallet on Base via the
|
|
145740
|
+
// gas-paying relayer. The SDK does not author the authorization (chain
|
|
145741
|
+
// nonce + EIP-712 domain coupling stays caller-side); it only forwards
|
|
145742
|
+
// the signed payload. Session-only.
|
|
145743
|
+
migrateAuthorization = (authorization, opts = {}) => request2(
|
|
145744
|
+
this.client,
|
|
145745
|
+
{
|
|
145746
|
+
method: "POST",
|
|
145747
|
+
path: "/v1/users/me/wallets/migrate",
|
|
145748
|
+
body: { authorization },
|
|
145749
|
+
signal: opts.signal
|
|
145750
|
+
},
|
|
145751
|
+
migrateAuthorizationResponseSchema
|
|
145752
|
+
);
|
|
145753
|
+
// Routes by identity: account mode signs EIP-191 against /v1/wallet/fund-url,
|
|
145754
|
+
// session mode hits /v1/users/me/fund-url (Bearer-authed, wallet resolved
|
|
145755
|
+
// server-side). Both honor `provider` (coinbase | stripe).
|
|
145756
|
+
fundingUrl = async (opts = {}) => {
|
|
145757
|
+
const credentials = this.client.getCredentials();
|
|
145758
|
+
const path3 = credentials.kind === "account" ? "/v1/wallet/fund-url" : credentials.kind === "session" ? "/v1/users/me/fund-url" : null;
|
|
145759
|
+
if (!path3) {
|
|
145760
|
+
throw new ZeroWalletError(
|
|
145761
|
+
"fundingUrl() requires a client constructed with an account or session credentials"
|
|
145762
|
+
);
|
|
145763
|
+
}
|
|
145764
|
+
const query = {
|
|
145765
|
+
provider: opts.provider ?? "coinbase"
|
|
145766
|
+
};
|
|
145767
|
+
if (opts.amount) query.amount = opts.amount;
|
|
145768
|
+
const { url: url4 } = await request2(
|
|
145769
|
+
this.client,
|
|
145770
|
+
{ method: "GET", path: path3, query, signal: opts.signal },
|
|
145771
|
+
fundingUrlResponseSchema
|
|
145772
|
+
);
|
|
145773
|
+
return url4;
|
|
145774
|
+
};
|
|
145775
|
+
getPublicClient = (chain2) => {
|
|
145776
|
+
if (chain2 === "base") {
|
|
145777
|
+
if (!this.clients.base) {
|
|
145778
|
+
this.clients.base = createPublicClient({
|
|
145779
|
+
chain: baseChain,
|
|
145780
|
+
transport: http()
|
|
145788
145781
|
});
|
|
145789
145782
|
}
|
|
145783
|
+
return this.clients.base;
|
|
145790
145784
|
}
|
|
145791
|
-
|
|
145792
|
-
|
|
145793
|
-
|
|
145794
|
-
|
|
145795
|
-
|
|
145796
|
-
|
|
145797
|
-
|
|
145798
|
-
|
|
145799
|
-
body,
|
|
145800
|
-
bodyRaw
|
|
145785
|
+
if (!this.clients.tempo) {
|
|
145786
|
+
this.clients.tempo = createPublicClient({
|
|
145787
|
+
// biome-ignore lint/suspicious/noExplicitAny: tempo is a custom chain object that viem's stricter Chain type rejects shape-wise but accepts at runtime
|
|
145788
|
+
chain: tempoChain2,
|
|
145789
|
+
transport: http()
|
|
145790
|
+
});
|
|
145791
|
+
}
|
|
145792
|
+
return this.clients.tempo;
|
|
145801
145793
|
};
|
|
145802
|
-
|
|
145803
|
-
|
|
145804
|
-
|
|
145805
|
-
|
|
145806
|
-
|
|
145807
|
-
|
|
145808
|
-
|
|
145809
|
-
|
|
145810
|
-
|
|
145811
|
-
|
|
145812
|
-
|
|
145813
|
-
|
|
145814
|
-
|
|
145794
|
+
/**
|
|
145795
|
+
* @internal
|
|
145796
|
+
*
|
|
145797
|
+
* Per-chain USDC balance read. Exposed (rather than private) so unit
|
|
145798
|
+
* tests can stub it without standing up a real viem public client —
|
|
145799
|
+
* viem's `http()` transport doesn't go through `client.fetchImpl`, so
|
|
145800
|
+
* the standard mock-fetch trick doesn't cover this path.
|
|
145801
|
+
*/
|
|
145802
|
+
readChainBalance = async (chain2, address2) => {
|
|
145803
|
+
const publicClient = this.getPublicClient(chain2);
|
|
145804
|
+
const tokenAddress = chain2 === "base" ? USDC_BASE2 : USDC_TEMPO2;
|
|
145805
|
+
const balance = await publicClient.readContract({
|
|
145806
|
+
address: tokenAddress,
|
|
145807
|
+
abi: ERC20_BALANCE_ABI2,
|
|
145808
|
+
functionName: "balanceOf",
|
|
145809
|
+
args: [address2]
|
|
145810
|
+
});
|
|
145811
|
+
return balance;
|
|
145812
|
+
};
|
|
145813
|
+
};
|
|
145814
|
+
var DEFAULT_BASE_URL = "https://api.zero.xyz";
|
|
145815
|
+
var DEFAULT_TIMEOUT_MS = 18e4;
|
|
145816
|
+
var DEFAULT_MAX_RETRIES = 2;
|
|
145817
|
+
var noopRefresh = async () => {
|
|
145815
145818
|
};
|
|
145816
145819
|
var searchResultSchema = external_exports3.object({
|
|
145817
145820
|
id: external_exports3.string(),
|
|
145821
|
+
// Opaque attribution token (format: `z_{shortId}.{position}`). Optional
|
|
145822
|
+
// so old API deploys that don't emit it still parse cleanly. Pass as
|
|
145823
|
+
// capabilityId to client.fetch() for exact search attribution.
|
|
145824
|
+
token: external_exports3.string().nullable().optional(),
|
|
145818
145825
|
position: external_exports3.number(),
|
|
145819
145826
|
slug: external_exports3.string(),
|
|
145820
145827
|
name: external_exports3.string(),
|
|
@@ -145833,6 +145840,9 @@ var searchResultSchema = external_exports3.object({
|
|
|
145833
145840
|
cost: external_exports3.object({ amount: external_exports3.string(), asset: external_exports3.string() }),
|
|
145834
145841
|
reviewCount: external_exports3.number().optional(),
|
|
145835
145842
|
rating: ratingSchema,
|
|
145843
|
+
// All-time activation count (non-deleted runs), mirroring capabilities.ts.
|
|
145844
|
+
// Optional so a response from an older API deploy still parses (ZERO-385).
|
|
145845
|
+
activationCount: external_exports3.number().optional(),
|
|
145836
145846
|
availabilityStatus: external_exports3.enum(["healthy", "unknown", "down"]).nullable().optional(),
|
|
145837
145847
|
/**
|
|
145838
145848
|
* @deprecated The API no longer emits `displayStatus`; it has been replaced
|
|
@@ -146313,7 +146323,7 @@ Categories the classifier picks from:
|
|
|
146313
146323
|
).action(
|
|
146314
146324
|
async (description, options) => {
|
|
146315
146325
|
try {
|
|
146316
|
-
const { analyticsService, client,
|
|
146326
|
+
const { analyticsService, client, walletAddress } = appContext.services;
|
|
146317
146327
|
if (!walletAddress) {
|
|
146318
146328
|
console.error(
|
|
146319
146329
|
"Wallet auth required \u2014 run `zero auth login`, or `zero wallet set <key>` / set ZERO_PRIVATE_KEY."
|
|
@@ -146394,12 +146404,6 @@ Bulk bug-report complete: ${ok} ok, ${failed} failed`
|
|
|
146394
146404
|
let { capability, run, search } = options;
|
|
146395
146405
|
const useAutoContext = options.context !== false;
|
|
146396
146406
|
if (useAutoContext) {
|
|
146397
|
-
const lastSearch = stateService.loadLastSearch();
|
|
146398
|
-
if (lastSearch) {
|
|
146399
|
-
search = search ?? lastSearch.searchId;
|
|
146400
|
-
const recent = lastSearch.capabilities[0];
|
|
146401
|
-
capability = capability ?? recent?.id;
|
|
146402
|
-
}
|
|
146403
146407
|
if (!run) {
|
|
146404
146408
|
try {
|
|
146405
146409
|
const list2 = await client.runs.list({ limit: 1 });
|
|
@@ -146607,11 +146611,6 @@ var sniffJsonShape = (buf) => {
|
|
|
146607
146611
|
if (i >= buf.length) return false;
|
|
146608
146612
|
return buf[i] === 123 || buf[i] === 91;
|
|
146609
146613
|
};
|
|
146610
|
-
var urlMatchesTemplate = (url4, template) => {
|
|
146611
|
-
const escaped = template.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
146612
|
-
const withCaptures = escaped.replace(/\\\{[^/\\}]+\\\}/g, "[^/]+");
|
|
146613
|
-
return new RegExp(`^${withCaptures}$`).test(url4);
|
|
146614
|
-
};
|
|
146615
146614
|
var resolveRequestBody = (rawData, readStdin2) => {
|
|
146616
146615
|
const fromFile = (spec) => {
|
|
146617
146616
|
if (spec === "@-") return readFileSync(0);
|
|
@@ -146678,27 +146677,25 @@ var fetchCommand = (appContext) => new Command("fetch").description(
|
|
|
146678
146677
|
).action(
|
|
146679
146678
|
async (url4, options) => {
|
|
146680
146679
|
try {
|
|
146681
|
-
const {
|
|
146682
|
-
|
|
146683
|
-
|
|
146684
|
-
stateService,
|
|
146685
|
-
walletAddress,
|
|
146686
|
-
lowBalanceWarning
|
|
146687
|
-
} = appContext.services;
|
|
146680
|
+
const { analyticsService, client, walletAddress, lowBalanceWarning } = appContext.services;
|
|
146681
|
+
const fromToken = options.capability ? isShortToken(options.capability) : false;
|
|
146682
|
+
const effectiveCapRef = options.capability;
|
|
146688
146683
|
let resolvedUrl;
|
|
146689
146684
|
let resolvedMethodFromCapability;
|
|
146685
|
+
let capFromNoUrl;
|
|
146690
146686
|
if (!url4) {
|
|
146691
146687
|
if (!options.capability) {
|
|
146692
146688
|
console.error(
|
|
146693
|
-
"Missing URL. Pass a URL argument or --capability <uid|slug> so the URL can be resolved from the capability."
|
|
146689
|
+
"Missing URL. Pass a URL argument or --capability <uid|slug|token> so the URL can be resolved from the capability."
|
|
146694
146690
|
);
|
|
146695
146691
|
process.exitCode = 1;
|
|
146696
146692
|
return;
|
|
146697
146693
|
}
|
|
146698
146694
|
try {
|
|
146699
|
-
const cap = await client.capabilities.get(
|
|
146695
|
+
const cap = await client.capabilities.get(effectiveCapRef ?? "");
|
|
146700
146696
|
resolvedUrl = cap.url;
|
|
146701
146697
|
resolvedMethodFromCapability = cap.method;
|
|
146698
|
+
capFromNoUrl = cap;
|
|
146702
146699
|
} catch (err) {
|
|
146703
146700
|
console.error(
|
|
146704
146701
|
`Failed to resolve --capability ${options.capability}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -146755,24 +146752,31 @@ var fetchCommand = (appContext) => new Command("fetch").description(
|
|
|
146755
146752
|
}
|
|
146756
146753
|
const log2 = (msg) => console.error(` ${msg}`);
|
|
146757
146754
|
const method = options.method ? options.method.toUpperCase() : resolvedMethodFromCapability ? resolvedMethodFromCapability.toUpperCase() : resolvedBody ? "POST" : "GET";
|
|
146758
|
-
|
|
146759
|
-
|
|
146760
|
-
|
|
146761
|
-
|
|
146762
|
-
|
|
146763
|
-
|
|
146764
|
-
|
|
146765
|
-
|
|
146766
|
-
|
|
146767
|
-
|
|
146768
|
-
|
|
146769
|
-
|
|
146770
|
-
|
|
146771
|
-
|
|
146772
|
-
|
|
146773
|
-
|
|
146774
|
-
|
|
146775
|
-
|
|
146755
|
+
let capabilityId = null;
|
|
146756
|
+
let capabilityUid = null;
|
|
146757
|
+
let capabilitySlug = null;
|
|
146758
|
+
let searchId;
|
|
146759
|
+
let displayCostAmount;
|
|
146760
|
+
let fetchOrigin;
|
|
146761
|
+
if (fromToken) {
|
|
146762
|
+
capabilityUid = capFromNoUrl?.uid ?? null;
|
|
146763
|
+
capabilityId = options.capability ?? "";
|
|
146764
|
+
capabilitySlug = capFromNoUrl?.slug ?? null;
|
|
146765
|
+
displayCostAmount = capFromNoUrl?.displayCostAmount;
|
|
146766
|
+
fetchOrigin = "from_search";
|
|
146767
|
+
} else if (options.capability) {
|
|
146768
|
+
capabilityUid = capFromNoUrl?.uid ?? null;
|
|
146769
|
+
capabilitySlug = capFromNoUrl?.slug ?? null;
|
|
146770
|
+
capabilityId = options.capability;
|
|
146771
|
+
displayCostAmount = capFromNoUrl?.displayCostAmount;
|
|
146772
|
+
fetchOrigin = "direct_slug";
|
|
146773
|
+
} else {
|
|
146774
|
+
const resolved = await client.capabilities.resolveByUrl(resolvedUrl, options.method ?? "GET").catch(() => null);
|
|
146775
|
+
capabilityUid = resolved?.capabilityId ?? null;
|
|
146776
|
+
capabilityId = capabilityUid;
|
|
146777
|
+
fetchOrigin = "direct_url";
|
|
146778
|
+
}
|
|
146779
|
+
const resultRank = void 0;
|
|
146776
146780
|
const cliSkipReasons = [];
|
|
146777
146781
|
if (!walletAddress) {
|
|
146778
146782
|
cliSkipReasons.push(
|
|
@@ -146808,16 +146812,17 @@ var fetchCommand = (appContext) => new Command("fetch").description(
|
|
|
146808
146812
|
// Adaptive MPP channel prefund: when the seller sends no
|
|
146809
146813
|
// suggestedDeposit and the caller didn't pass --max-pay,
|
|
146810
146814
|
// the SDK scales the channel to 10× displayCostAmount so
|
|
146811
|
-
// an expensive single call doesn't under-fund.
|
|
146812
|
-
//
|
|
146813
|
-
|
|
146814
|
-
|
|
146815
|
-
},
|
|
146815
|
+
// an expensive single call doesn't under-fund. Derived from
|
|
146816
|
+
// the capability details when available (token or direct-slug
|
|
146817
|
+
// paths that triggered a capabilities.get).
|
|
146818
|
+
...displayCostAmount && { displayCostAmount },
|
|
146816
146819
|
// Only attach the capability when wallet auth is available;
|
|
146817
146820
|
// recording without a wallet would skip server-side anyway,
|
|
146818
146821
|
// and omitting here keeps result.runTrackingSkipped clean.
|
|
146819
146822
|
...capabilityId && walletAddress && { capabilityId },
|
|
146820
|
-
|
|
146823
|
+
// searchId intentionally omitted: server derives attribution
|
|
146824
|
+
// via SearchAttributor (wallet + capId + 30-min window) so
|
|
146825
|
+
// parallel fetches are race-free without shared client state.
|
|
146821
146826
|
// Stamp how the agent arrived (from_search | direct_slug |
|
|
146822
146827
|
// direct_url) onto the run's metadata so direct execution is
|
|
146823
146828
|
// distinguishable from search-driven runs server-side. Only
|
|
@@ -146944,19 +146949,12 @@ var fetchCommand = (appContext) => new Command("fetch").description(
|
|
|
146944
146949
|
} else {
|
|
146945
146950
|
if (walletAddress && !runId) {
|
|
146946
146951
|
cliSkipReasons.push(
|
|
146947
|
-
"no capability resolved \u2014 pass --capability <uid|slug> or run `zero search` first so the URL can be matched"
|
|
146952
|
+
"no capability resolved \u2014 pass --capability <uid|slug|token> or run `zero search` first so the URL can be matched"
|
|
146948
146953
|
);
|
|
146949
146954
|
}
|
|
146950
|
-
const lastSearch = stateService.loadLastSearch();
|
|
146951
|
-
const cached2 = lastSearch?.capabilities ?? [];
|
|
146952
146955
|
analyticsService.capture("capability_resolution_missed", {
|
|
146953
146956
|
url: redactUrl(resolvedUrl),
|
|
146954
|
-
method
|
|
146955
|
-
hasLastSearch: lastSearch !== null,
|
|
146956
|
-
lastSearchSize: cached2.length,
|
|
146957
|
-
lastSearchHasTemplates: cached2.some(
|
|
146958
|
-
(c) => Boolean(c.urlTemplate)
|
|
146959
|
-
)
|
|
146957
|
+
method
|
|
146960
146958
|
});
|
|
146961
146959
|
}
|
|
146962
146960
|
}
|
|
@@ -147471,66 +147469,26 @@ var formatCapability = (capability) => {
|
|
|
147471
147469
|
lines.push(...buildTryItExample(capability));
|
|
147472
147470
|
return lines.join("\n");
|
|
147473
147471
|
};
|
|
147474
|
-
var getCommand = (appContext) => new Command("get").description(
|
|
147475
|
-
"Get details for a capability by position from last search, or by slug"
|
|
147476
|
-
).argument(
|
|
147472
|
+
var getCommand = (appContext) => new Command("get").description("Get details for a capability by token, slug, or uid").argument(
|
|
147477
147473
|
"<identifier>",
|
|
147478
|
-
"
|
|
147474
|
+
"Attribution token (z_xxx.N from search results), capability slug, or uid"
|
|
147479
147475
|
).option("--formatted", "Output formatted capability details").option("--json", "Output raw JSON to stdout (default)").option(
|
|
147480
147476
|
"--agent <name>",
|
|
147481
147477
|
"Identify your agent host for this invocation. Overrides auto-detect for this call only."
|
|
147482
147478
|
).action(async (identifier, options) => {
|
|
147483
147479
|
try {
|
|
147484
|
-
const { analyticsService, client
|
|
147485
|
-
const
|
|
147486
|
-
const isPosition = !Number.isNaN(position) && position >= 1;
|
|
147487
|
-
let capabilityId;
|
|
147488
|
-
let searchId;
|
|
147489
|
-
if (isPosition) {
|
|
147490
|
-
const lastSearch = stateService.loadLastSearch();
|
|
147491
|
-
if (!lastSearch) {
|
|
147492
|
-
console.error("No recent search found. Run `zero search` first.");
|
|
147493
|
-
process.exitCode = 1;
|
|
147494
|
-
return;
|
|
147495
|
-
}
|
|
147496
|
-
const entry = lastSearch.capabilities.find(
|
|
147497
|
-
(c) => c.position === position
|
|
147498
|
-
);
|
|
147499
|
-
if (!entry) {
|
|
147500
|
-
console.error(
|
|
147501
|
-
`No capability at position ${position}. Positions: ${lastSearch.capabilities.map((c) => c.position).join(", ")}`
|
|
147502
|
-
);
|
|
147503
|
-
process.exitCode = 1;
|
|
147504
|
-
return;
|
|
147505
|
-
}
|
|
147506
|
-
capabilityId = entry.id;
|
|
147507
|
-
searchId = lastSearch.searchId;
|
|
147508
|
-
} else {
|
|
147509
|
-
capabilityId = identifier;
|
|
147510
|
-
const ctx = stateService.findSearchContextByCapability(identifier);
|
|
147511
|
-
if (ctx) searchId = ctx.searchId;
|
|
147512
|
-
}
|
|
147513
|
-
const capability = await client.capabilities.get(capabilityId, {
|
|
147514
|
-
searchId
|
|
147515
|
-
});
|
|
147480
|
+
const { analyticsService, client } = appContext.services;
|
|
147481
|
+
const capability = await client.capabilities.get(identifier);
|
|
147516
147482
|
if (options.formatted && !options.json) {
|
|
147517
147483
|
console.log(formatCapability(capability));
|
|
147518
147484
|
} else {
|
|
147519
147485
|
console.log(JSON.stringify(capability, null, 2));
|
|
147520
147486
|
}
|
|
147521
147487
|
analyticsService.capture("capability_viewed", {
|
|
147522
|
-
|
|
147523
|
-
// resolved to uid via the last-search cache). Preserved
|
|
147524
|
-
// for back-compat with existing dashboards.
|
|
147525
|
-
capabilityId,
|
|
147526
|
-
// New canonical identifier fields read off the API response,
|
|
147527
|
-
// so they are always populated regardless of how the user
|
|
147528
|
-
// referenced the capability.
|
|
147488
|
+
capabilityRef: identifier,
|
|
147529
147489
|
capabilityUid: capability.uid,
|
|
147530
147490
|
capabilitySlug: capability.slug,
|
|
147531
|
-
|
|
147532
|
-
...isPosition ? { position } : {},
|
|
147533
|
-
...searchId ? { searchId } : {}
|
|
147491
|
+
fromToken: isShortToken(identifier)
|
|
147534
147492
|
});
|
|
147535
147493
|
} catch (err) {
|
|
147536
147494
|
console.error(err instanceof Error ? err.message : "Get failed");
|
|
@@ -147591,9 +147549,251 @@ var sectionDivider = () => {
|
|
|
147591
147549
|
console.log("");
|
|
147592
147550
|
};
|
|
147593
147551
|
|
|
147552
|
+
// src/util/json-config-file.ts
|
|
147553
|
+
init_esm_shims();
|
|
147554
|
+
var updateJsonConfigFile = (path3, update2, options = {}) => {
|
|
147555
|
+
let config2 = {};
|
|
147556
|
+
if (existsSync(path3)) {
|
|
147557
|
+
try {
|
|
147558
|
+
config2 = JSON.parse(readFileSync(path3, "utf-8"));
|
|
147559
|
+
} catch {
|
|
147560
|
+
return { status: "unparseable", path: path3 };
|
|
147561
|
+
}
|
|
147562
|
+
} else if (!options.createIfMissing) {
|
|
147563
|
+
return { status: "missing", path: path3 };
|
|
147564
|
+
}
|
|
147565
|
+
const changed = update2(config2);
|
|
147566
|
+
if (!changed) return { status: "unchanged", path: path3 };
|
|
147567
|
+
mkdirSync(dirname(path3), { recursive: true });
|
|
147568
|
+
writeFileSync(path3, `${JSON.stringify(config2, null, 2)}
|
|
147569
|
+
`);
|
|
147570
|
+
return { status: "updated", path: path3 };
|
|
147571
|
+
};
|
|
147572
|
+
|
|
147594
147573
|
// src/commands/init-command.ts
|
|
147595
147574
|
var SKILL_DIRS = [".claude/skills", ".agents/skills"];
|
|
147596
147575
|
var ZERO_SANDBOX_DOMAIN = "*.zero.xyz";
|
|
147576
|
+
var CLAUDE_SETTINGS_PATH = ".claude/settings.json";
|
|
147577
|
+
var CODEX_HOOKS_PATH = ".codex/hooks.json";
|
|
147578
|
+
var PLUGIN_AGENTS = ["codex", "claude", "gemini", "openclaw"];
|
|
147579
|
+
var INIT_AGENTS = [...PLUGIN_AGENTS, "standalone"];
|
|
147580
|
+
var initAgentSchema = zod_default.enum(INIT_AGENTS);
|
|
147581
|
+
var HARNESS_SPECS = {
|
|
147582
|
+
claude: {
|
|
147583
|
+
agent: "claude",
|
|
147584
|
+
displayName: "Claude Code",
|
|
147585
|
+
executable: "claude",
|
|
147586
|
+
installCommands: [
|
|
147587
|
+
{
|
|
147588
|
+
label: "add marketplace",
|
|
147589
|
+
command: "claude",
|
|
147590
|
+
args: ["plugin", "marketplace", "add", "officialzeroxyz/zero-plugins"],
|
|
147591
|
+
required: false
|
|
147592
|
+
},
|
|
147593
|
+
{
|
|
147594
|
+
label: "install plugin",
|
|
147595
|
+
command: "claude",
|
|
147596
|
+
args: ["plugin", "install", "zero@zero-plugins"]
|
|
147597
|
+
}
|
|
147598
|
+
],
|
|
147599
|
+
manualInstructions: [
|
|
147600
|
+
"Claude Code Desktop: open the Code tab, choose Customize, then add a Personal plugin marketplace from officialzeroxyz/zero-plugins.",
|
|
147601
|
+
"After it syncs, click the + icon on the Zero plugin, then start a new session and ask Claude to help set up and test Zero."
|
|
147602
|
+
]
|
|
147603
|
+
},
|
|
147604
|
+
codex: {
|
|
147605
|
+
agent: "codex",
|
|
147606
|
+
displayName: "Codex",
|
|
147607
|
+
executable: "codex",
|
|
147608
|
+
installCommands: [
|
|
147609
|
+
{
|
|
147610
|
+
label: "add marketplace",
|
|
147611
|
+
command: "codex",
|
|
147612
|
+
args: ["plugin", "marketplace", "add", "officialzeroxyz/zero-plugins"],
|
|
147613
|
+
required: false
|
|
147614
|
+
},
|
|
147615
|
+
{
|
|
147616
|
+
label: "install plugin",
|
|
147617
|
+
command: "codex",
|
|
147618
|
+
args: ["plugin", "add", "zero@zero-plugins"]
|
|
147619
|
+
}
|
|
147620
|
+
],
|
|
147621
|
+
manualInstructions: [
|
|
147622
|
+
"Codex app: open Plugins in the sidebar, click +, then add marketplace officialzeroxyz/zero-plugins.",
|
|
147623
|
+
"Select the Zero filter, click Add plugin on Zero, then start a new chat and ask Codex to help set up and test Zero."
|
|
147624
|
+
]
|
|
147625
|
+
},
|
|
147626
|
+
gemini: {
|
|
147627
|
+
agent: "gemini",
|
|
147628
|
+
displayName: "Gemini CLI",
|
|
147629
|
+
executable: "gemini",
|
|
147630
|
+
installCommands: [
|
|
147631
|
+
{
|
|
147632
|
+
label: "install extension",
|
|
147633
|
+
command: "gemini",
|
|
147634
|
+
args: [
|
|
147635
|
+
"extensions",
|
|
147636
|
+
"install",
|
|
147637
|
+
"https://github.com/officialzeroxyz/zero-plugins",
|
|
147638
|
+
"--auto-update"
|
|
147639
|
+
]
|
|
147640
|
+
}
|
|
147641
|
+
],
|
|
147642
|
+
manualInstructions: [
|
|
147643
|
+
"Gemini CLI: run this from a shell where `gemini` is on PATH: gemini extensions install https://github.com/officialzeroxyz/zero-plugins --auto-update"
|
|
147644
|
+
]
|
|
147645
|
+
},
|
|
147646
|
+
openclaw: {
|
|
147647
|
+
agent: "openclaw",
|
|
147648
|
+
displayName: "OpenClaw",
|
|
147649
|
+
executable: "openclaw",
|
|
147650
|
+
installCommands: [
|
|
147651
|
+
{
|
|
147652
|
+
label: "install plugin",
|
|
147653
|
+
command: "openclaw",
|
|
147654
|
+
args: [
|
|
147655
|
+
"plugins",
|
|
147656
|
+
"install",
|
|
147657
|
+
"zero",
|
|
147658
|
+
"--marketplace",
|
|
147659
|
+
"officialzeroxyz/zero-plugins"
|
|
147660
|
+
]
|
|
147661
|
+
}
|
|
147662
|
+
],
|
|
147663
|
+
manualInstructions: [
|
|
147664
|
+
"OpenClaw: run this from a shell where `openclaw` is on PATH: openclaw plugins install zero --marketplace officialzeroxyz/zero-plugins"
|
|
147665
|
+
]
|
|
147666
|
+
}
|
|
147667
|
+
};
|
|
147668
|
+
var unique = (items) => [...new Set(items)];
|
|
147669
|
+
var parseAgentValues = (values) => {
|
|
147670
|
+
if (!values || values.length === 0) {
|
|
147671
|
+
return {
|
|
147672
|
+
kind: "default",
|
|
147673
|
+
requestedAgents: [...PLUGIN_AGENTS],
|
|
147674
|
+
pluginAgents: [...PLUGIN_AGENTS]
|
|
147675
|
+
};
|
|
147676
|
+
}
|
|
147677
|
+
const parsed = unique(
|
|
147678
|
+
values.flatMap(
|
|
147679
|
+
(value) => value.split(",").map((part) => part.trim().toLowerCase()).filter(Boolean)
|
|
147680
|
+
)
|
|
147681
|
+
);
|
|
147682
|
+
if (parsed.length === 0) {
|
|
147683
|
+
throw new Error("Pass at least one agent name to --agent");
|
|
147684
|
+
}
|
|
147685
|
+
const agents = parsed.map((value) => {
|
|
147686
|
+
const result = initAgentSchema.safeParse(value);
|
|
147687
|
+
if (!result.success) {
|
|
147688
|
+
throw new Error(
|
|
147689
|
+
`Unknown agent "${value}". Expected one of: ${INIT_AGENTS.join(", ")}`
|
|
147690
|
+
);
|
|
147691
|
+
}
|
|
147692
|
+
return result.data;
|
|
147693
|
+
});
|
|
147694
|
+
if (agents.includes("standalone") && agents.length > 1) {
|
|
147695
|
+
throw new Error(
|
|
147696
|
+
"`standalone` cannot be combined with other --agent values; run it separately."
|
|
147697
|
+
);
|
|
147698
|
+
}
|
|
147699
|
+
if (agents[0] === "standalone") {
|
|
147700
|
+
return { kind: "standalone", requestedAgents: agents, pluginAgents: [] };
|
|
147701
|
+
}
|
|
147702
|
+
return {
|
|
147703
|
+
kind: "specific",
|
|
147704
|
+
requestedAgents: agents,
|
|
147705
|
+
pluginAgents: agents
|
|
147706
|
+
};
|
|
147707
|
+
};
|
|
147708
|
+
var collectAgentOption = (value, previous = []) => [
|
|
147709
|
+
...previous,
|
|
147710
|
+
value
|
|
147711
|
+
];
|
|
147712
|
+
var commandSummary = (command, args) => [command, ...args].join(" ");
|
|
147713
|
+
var commandOutput = (result) => {
|
|
147714
|
+
const chunks = [result.stderr, result.stdout].map((chunk) => typeof chunk === "string" ? chunk.trim() : "").filter(Boolean);
|
|
147715
|
+
return chunks.join("\n").trim();
|
|
147716
|
+
};
|
|
147717
|
+
var commandErrorDetail = (result, fallback2) => {
|
|
147718
|
+
if (result.error) return result.error.message;
|
|
147719
|
+
const output = commandOutput(result);
|
|
147720
|
+
if (output.length > 0) return truncateError(output);
|
|
147721
|
+
if (result.signal) return `${fallback2} exited via signal ${result.signal}`;
|
|
147722
|
+
return `${fallback2} exited with status ${result.status ?? "unknown"}`;
|
|
147723
|
+
};
|
|
147724
|
+
var isCommandCallable = (command) => {
|
|
147725
|
+
if (process.platform === "win32") {
|
|
147726
|
+
const result2 = spawnSync("where.exe", [command], {
|
|
147727
|
+
encoding: "utf8",
|
|
147728
|
+
stdio: "ignore"
|
|
147729
|
+
});
|
|
147730
|
+
return result2.status === 0;
|
|
147731
|
+
}
|
|
147732
|
+
const result = spawnSync("/bin/sh", ["-c", `command -v ${command}`], {
|
|
147733
|
+
encoding: "utf8",
|
|
147734
|
+
stdio: "ignore"
|
|
147735
|
+
});
|
|
147736
|
+
return result.status === 0;
|
|
147737
|
+
};
|
|
147738
|
+
var installHarnessPlugin = (spec, options) => {
|
|
147739
|
+
if (options.dryRun) {
|
|
147740
|
+
for (const step of spec.installCommands) {
|
|
147741
|
+
stepInfo(`would run: ${commandSummary(step.command, step.args)}`);
|
|
147742
|
+
}
|
|
147743
|
+
return {
|
|
147744
|
+
agent: spec.agent,
|
|
147745
|
+
displayName: spec.displayName,
|
|
147746
|
+
status: "would_install",
|
|
147747
|
+
detail: "dry run"
|
|
147748
|
+
};
|
|
147749
|
+
}
|
|
147750
|
+
let optionalFailure;
|
|
147751
|
+
for (const step of spec.installCommands) {
|
|
147752
|
+
if (options.verbose) {
|
|
147753
|
+
stepInfo(`running: ${commandSummary(step.command, step.args)}`);
|
|
147754
|
+
}
|
|
147755
|
+
const result = spawnSync(step.command, step.args, {
|
|
147756
|
+
encoding: "utf8",
|
|
147757
|
+
stdio: "pipe",
|
|
147758
|
+
env: process.env
|
|
147759
|
+
});
|
|
147760
|
+
if (result.status === 0) continue;
|
|
147761
|
+
const detail = commandErrorDetail(result, step.label);
|
|
147762
|
+
if (step.required === false) {
|
|
147763
|
+
optionalFailure = `${step.label}: ${detail}`;
|
|
147764
|
+
if (options.verbose) stepInfo(`${optionalFailure}; continuing`);
|
|
147765
|
+
continue;
|
|
147766
|
+
}
|
|
147767
|
+
return {
|
|
147768
|
+
agent: spec.agent,
|
|
147769
|
+
displayName: spec.displayName,
|
|
147770
|
+
status: "failed",
|
|
147771
|
+
detail
|
|
147772
|
+
};
|
|
147773
|
+
}
|
|
147774
|
+
return {
|
|
147775
|
+
agent: spec.agent,
|
|
147776
|
+
displayName: spec.displayName,
|
|
147777
|
+
status: "installed",
|
|
147778
|
+
detail: optionalFailure ? `installed; ignored ${optionalFailure}` : void 0
|
|
147779
|
+
};
|
|
147780
|
+
};
|
|
147781
|
+
var printManualInstructions = (spec) => {
|
|
147782
|
+
for (const line of spec.manualInstructions) {
|
|
147783
|
+
console.log(` ${color.gray("\xB7")} ${color.dim(line)}`);
|
|
147784
|
+
}
|
|
147785
|
+
};
|
|
147786
|
+
var fallbackReason = (selection, detectedAgents, results) => {
|
|
147787
|
+
if (selection.kind === "standalone")
|
|
147788
|
+
return "--agent standalone was requested";
|
|
147789
|
+
if (selection.kind === "default" && detectedAgents.length === 0) {
|
|
147790
|
+
return "no supported harness CLIs were callable in this shell";
|
|
147791
|
+
}
|
|
147792
|
+
if (results.every((result) => result.status === "skipped_unavailable")) {
|
|
147793
|
+
return "no requested harness CLIs were callable in this shell";
|
|
147794
|
+
}
|
|
147795
|
+
return "no plugin install succeeded";
|
|
147796
|
+
};
|
|
147597
147797
|
var PLUGIN_HOOKS_ROOT = "${CLAUDE_PLUGIN_ROOT}/hooks";
|
|
147598
147798
|
var SCRIPT_NAME_PATTERN = /\$\{CLAUDE_PLUGIN_ROOT\}\/hooks\/([a-z0-9][a-z0-9-]*\.sh)/;
|
|
147599
147799
|
var fetchText = async (url4) => {
|
|
@@ -147658,59 +147858,7 @@ var installHookScripts = async (home, hooksJson, webBase, verbose) => {
|
|
|
147658
147858
|
})
|
|
147659
147859
|
);
|
|
147660
147860
|
};
|
|
147661
|
-
var
|
|
147662
|
-
const hooksDir = join(home, ".zero", "hooks");
|
|
147663
|
-
const settingsPath = join(home, ".claude", "settings.json");
|
|
147664
|
-
let settings = {};
|
|
147665
|
-
if (existsSync(settingsPath)) {
|
|
147666
|
-
try {
|
|
147667
|
-
settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
147668
|
-
} catch {
|
|
147669
|
-
stepWarn(
|
|
147670
|
-
"Hooks not registered",
|
|
147671
|
-
`${settingsPath} is not valid JSON \u2014 fix it and re-run \`zero init\``
|
|
147672
|
-
);
|
|
147673
|
-
return false;
|
|
147674
|
-
}
|
|
147675
|
-
}
|
|
147676
|
-
if (!settings.hooks || typeof settings.hooks !== "object") {
|
|
147677
|
-
settings.hooks = {};
|
|
147678
|
-
}
|
|
147679
|
-
const hooks = settings.hooks;
|
|
147680
|
-
for (const [event, entries] of Object.entries(hooksJson.hooks)) {
|
|
147681
|
-
for (const entry of entries ?? []) {
|
|
147682
|
-
const scripts = entryScriptNames(entry);
|
|
147683
|
-
if (scripts.length === 0) {
|
|
147684
|
-
if (verbose) {
|
|
147685
|
-
stepInfo(`${event}: entry has no plugin hook script \u2014 skipped`);
|
|
147686
|
-
}
|
|
147687
|
-
continue;
|
|
147688
|
-
}
|
|
147689
|
-
const rewritten = {
|
|
147690
|
-
...entry,
|
|
147691
|
-
hooks: (entry.hooks ?? []).map((hook) => ({
|
|
147692
|
-
...hook,
|
|
147693
|
-
command: typeof hook.command === "string" ? hook.command.replaceAll(PLUGIN_HOOKS_ROOT, hooksDir) : hook.command
|
|
147694
|
-
}))
|
|
147695
|
-
};
|
|
147696
|
-
if (!Array.isArray(hooks[event])) hooks[event] = [];
|
|
147697
|
-
const list2 = hooks[event];
|
|
147698
|
-
const existingIdx = list2.findIndex((existing) => {
|
|
147699
|
-
const existingHooks = existing?.hooks;
|
|
147700
|
-
if (!Array.isArray(existingHooks)) return false;
|
|
147701
|
-
return existingHooks.some(
|
|
147702
|
-
(h2) => typeof h2.command === "string" && scripts.some((s) => h2.command.includes(s))
|
|
147703
|
-
);
|
|
147704
|
-
});
|
|
147705
|
-
if (existingIdx >= 0) {
|
|
147706
|
-
list2[existingIdx] = rewritten;
|
|
147707
|
-
if (verbose) stepInfo(`${event}: ${scripts.join(", ")} entry replaced`);
|
|
147708
|
-
} else {
|
|
147709
|
-
list2.push(rewritten);
|
|
147710
|
-
if (verbose) stepInfo(`${event}: ${scripts.join(", ")} entry appended`);
|
|
147711
|
-
}
|
|
147712
|
-
}
|
|
147713
|
-
}
|
|
147861
|
+
var ensureZeroSandboxAllowlist = (settings, verbose) => {
|
|
147714
147862
|
if (!settings.sandbox || typeof settings.sandbox !== "object") {
|
|
147715
147863
|
settings.sandbox = {};
|
|
147716
147864
|
}
|
|
@@ -147729,86 +147877,326 @@ var registerHooksInClaudeSettings = (home, hooksJson, verbose) => {
|
|
|
147729
147877
|
stepInfo(`sandbox.network.allowedDomains += ${ZERO_SANDBOX_DOMAIN}`);
|
|
147730
147878
|
}
|
|
147731
147879
|
}
|
|
147732
|
-
|
|
147733
|
-
|
|
147734
|
-
|
|
147880
|
+
};
|
|
147881
|
+
var registerHooksInJsonFile = (home, hooksJson, target, verbose) => {
|
|
147882
|
+
const hooksDir = join(home, ".zero", "hooks");
|
|
147883
|
+
const configPath = join(home, target.relativePath);
|
|
147884
|
+
const result = updateJsonConfigFile(
|
|
147885
|
+
configPath,
|
|
147886
|
+
(config2) => {
|
|
147887
|
+
if (!config2.hooks || typeof config2.hooks !== "object") {
|
|
147888
|
+
config2.hooks = {};
|
|
147889
|
+
}
|
|
147890
|
+
const hooks = config2.hooks;
|
|
147891
|
+
for (const [event, entries] of Object.entries(hooksJson.hooks)) {
|
|
147892
|
+
for (const entry of entries ?? []) {
|
|
147893
|
+
const scripts = entryScriptNames(entry);
|
|
147894
|
+
if (scripts.length === 0) {
|
|
147895
|
+
if (verbose) {
|
|
147896
|
+
stepInfo(`${event}: entry has no plugin hook script \u2014 skipped`);
|
|
147897
|
+
}
|
|
147898
|
+
continue;
|
|
147899
|
+
}
|
|
147900
|
+
const rewritten = {
|
|
147901
|
+
...entry,
|
|
147902
|
+
hooks: (entry.hooks ?? []).map((hook) => ({
|
|
147903
|
+
...hook,
|
|
147904
|
+
command: typeof hook.command === "string" ? hook.command.replaceAll(PLUGIN_HOOKS_ROOT, hooksDir) : hook.command
|
|
147905
|
+
}))
|
|
147906
|
+
};
|
|
147907
|
+
if (!Array.isArray(hooks[event])) hooks[event] = [];
|
|
147908
|
+
const list2 = hooks[event];
|
|
147909
|
+
const existingIdx = list2.findIndex((existing) => {
|
|
147910
|
+
const existingHooks = existing?.hooks;
|
|
147911
|
+
if (!Array.isArray(existingHooks)) return false;
|
|
147912
|
+
return existingHooks.some(
|
|
147913
|
+
(h2) => typeof h2.command === "string" && scripts.some((s) => h2.command.includes(s))
|
|
147914
|
+
);
|
|
147915
|
+
});
|
|
147916
|
+
if (existingIdx >= 0) {
|
|
147917
|
+
list2[existingIdx] = rewritten;
|
|
147918
|
+
if (verbose) {
|
|
147919
|
+
stepInfo(`${event}: ${scripts.join(", ")} entry replaced`);
|
|
147920
|
+
}
|
|
147921
|
+
} else {
|
|
147922
|
+
list2.push(rewritten);
|
|
147923
|
+
if (verbose) {
|
|
147924
|
+
stepInfo(`${event}: ${scripts.join(", ")} entry appended`);
|
|
147925
|
+
}
|
|
147926
|
+
}
|
|
147927
|
+
}
|
|
147928
|
+
}
|
|
147929
|
+
if (target.includeSandboxAllowlist) {
|
|
147930
|
+
ensureZeroSandboxAllowlist(config2, verbose);
|
|
147931
|
+
}
|
|
147932
|
+
return true;
|
|
147933
|
+
},
|
|
147934
|
+
{ createIfMissing: true }
|
|
147935
|
+
);
|
|
147936
|
+
if (result.status === "unparseable") {
|
|
147937
|
+
stepWarn(
|
|
147938
|
+
"Hooks not registered",
|
|
147939
|
+
`${configPath} is not valid JSON \u2014 fix it and re-run \`zero init\``
|
|
147940
|
+
);
|
|
147941
|
+
return false;
|
|
147942
|
+
}
|
|
147735
147943
|
return true;
|
|
147736
147944
|
};
|
|
147945
|
+
var runStandaloneInit = async (appContext, options = {}) => {
|
|
147946
|
+
const verbose = options.verbose ?? false;
|
|
147947
|
+
options.onStep?.("fetch");
|
|
147948
|
+
console.log("");
|
|
147949
|
+
console.log(` ${color.boldCyan("Installing standalone Zero fallback")}`);
|
|
147950
|
+
console.log("");
|
|
147951
|
+
console.log(color.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
147952
|
+
console.log("");
|
|
147953
|
+
const home = homedir();
|
|
147954
|
+
const webBase = appContext.env.ZERO_WEB_URL;
|
|
147955
|
+
const [skillMd, hooksJsonRaw] = await Promise.all([
|
|
147956
|
+
fetchText(`${webBase}/SKILL.md`),
|
|
147957
|
+
fetchText(`${webBase}/hooks.json`)
|
|
147958
|
+
]);
|
|
147959
|
+
let hooksJson;
|
|
147960
|
+
try {
|
|
147961
|
+
hooksJson = JSON.parse(hooksJsonRaw);
|
|
147962
|
+
} catch {
|
|
147963
|
+
throw new Error(`${webBase}/hooks.json is not valid JSON`);
|
|
147964
|
+
}
|
|
147965
|
+
if (!hooksJson?.hooks || typeof hooksJson.hooks !== "object") {
|
|
147966
|
+
throw new Error(`${webBase}/hooks.json has no "hooks" object`);
|
|
147967
|
+
}
|
|
147968
|
+
if (verbose) {
|
|
147969
|
+
stepInfo(`fetched ${webBase}/SKILL.md and ${webBase}/hooks.json`);
|
|
147970
|
+
}
|
|
147971
|
+
options.onStep?.("skill");
|
|
147972
|
+
const skillsDirs = unique([
|
|
147973
|
+
...SKILL_DIRS.map((dir) => join(home, dir)),
|
|
147974
|
+
...(options.skillsDir ?? []).map((dir) => expandHome(dir, home))
|
|
147975
|
+
]);
|
|
147976
|
+
const skillsInstalled = installSkill(skillsDirs, skillMd, verbose);
|
|
147977
|
+
if (skillsInstalled.length === 0) {
|
|
147978
|
+
throw new Error("could not write the Zero skill to any skills directory");
|
|
147979
|
+
}
|
|
147980
|
+
stepSuccess("Skill installed", `${skillsInstalled.length} locations`);
|
|
147981
|
+
options.onStep?.("hooks");
|
|
147982
|
+
const hookScriptsInstalled = await installHookScripts(
|
|
147983
|
+
home,
|
|
147984
|
+
hooksJson,
|
|
147985
|
+
webBase,
|
|
147986
|
+
verbose
|
|
147987
|
+
);
|
|
147988
|
+
stepSuccess("Hook scripts installed", "~/.zero/hooks");
|
|
147989
|
+
options.onStep?.("settings");
|
|
147990
|
+
const settingsRegistered = registerHooksInJsonFile(
|
|
147991
|
+
home,
|
|
147992
|
+
hooksJson,
|
|
147993
|
+
{
|
|
147994
|
+
relativePath: CLAUDE_SETTINGS_PATH,
|
|
147995
|
+
includeSandboxAllowlist: true
|
|
147996
|
+
},
|
|
147997
|
+
verbose
|
|
147998
|
+
);
|
|
147999
|
+
if (settingsRegistered) {
|
|
148000
|
+
stepSuccess("Hooks registered", "~/.claude/settings.json");
|
|
148001
|
+
}
|
|
148002
|
+
const codexHooksRegistered = registerHooksInJsonFile(
|
|
148003
|
+
home,
|
|
148004
|
+
hooksJson,
|
|
148005
|
+
{
|
|
148006
|
+
relativePath: CODEX_HOOKS_PATH,
|
|
148007
|
+
includeSandboxAllowlist: false
|
|
148008
|
+
},
|
|
148009
|
+
verbose
|
|
148010
|
+
);
|
|
148011
|
+
if (codexHooksRegistered) {
|
|
148012
|
+
stepSuccess("Codex hooks registered", "~/.codex/hooks.json");
|
|
148013
|
+
}
|
|
148014
|
+
return {
|
|
148015
|
+
skillsInstalled,
|
|
148016
|
+
hookScriptsInstalled,
|
|
148017
|
+
settingsRegistered,
|
|
148018
|
+
codexHooksRegistered
|
|
148019
|
+
};
|
|
148020
|
+
};
|
|
148021
|
+
var statusLabel = (result) => {
|
|
148022
|
+
switch (result.status) {
|
|
148023
|
+
case "installed":
|
|
148024
|
+
return "plugin installed";
|
|
148025
|
+
case "skipped_unavailable":
|
|
148026
|
+
return "skipped unavailable";
|
|
148027
|
+
case "failed":
|
|
148028
|
+
return "failed";
|
|
148029
|
+
case "would_install":
|
|
148030
|
+
return "would install";
|
|
148031
|
+
}
|
|
148032
|
+
};
|
|
148033
|
+
var printRunnerModelNote = () => {
|
|
148034
|
+
console.log(
|
|
148035
|
+
` ${color.dim("Agent sessions use the auto-updated managed runner at ~/.zero/runtime/bin/zero.")}`
|
|
148036
|
+
);
|
|
148037
|
+
console.log(
|
|
148038
|
+
` ${color.dim("The global npm `zero` is the bootstrap and manual CLI; it does not replace the managed runner.")}`
|
|
148039
|
+
);
|
|
148040
|
+
};
|
|
147737
148041
|
var runInit = async (appContext, options = {}) => {
|
|
147738
148042
|
const verbose = options.verbose ?? false;
|
|
148043
|
+
const dryRun = options.dryRun ?? false;
|
|
148044
|
+
const fallbackAllowed = options.fallback ?? true;
|
|
148045
|
+
const selection = parseAgentValues(options.agent);
|
|
148046
|
+
const requestedAgents = selection.requestedAgents;
|
|
148047
|
+
let currentStep = "plugins";
|
|
147739
148048
|
appContext.services.analyticsService.capture("init_started", {});
|
|
147740
|
-
let currentStep = "fetch";
|
|
147741
148049
|
try {
|
|
147742
148050
|
console.log("");
|
|
147743
|
-
console.log(` ${color.boldCyan("
|
|
148051
|
+
console.log(` ${color.boldCyan("Initializing Zero")}`);
|
|
147744
148052
|
console.log("");
|
|
147745
148053
|
console.log(color.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
147746
148054
|
console.log("");
|
|
147747
|
-
|
|
147748
|
-
|
|
147749
|
-
const [
|
|
147750
|
-
|
|
147751
|
-
|
|
147752
|
-
|
|
147753
|
-
|
|
147754
|
-
|
|
147755
|
-
|
|
147756
|
-
} catch {
|
|
147757
|
-
throw new Error(`${webBase}/hooks.json is not valid JSON`);
|
|
147758
|
-
}
|
|
147759
|
-
if (!hooksJson?.hooks || typeof hooksJson.hooks !== "object") {
|
|
147760
|
-
throw new Error(`${webBase}/hooks.json has no "hooks" object`);
|
|
147761
|
-
}
|
|
147762
|
-
if (verbose) {
|
|
147763
|
-
stepInfo(`fetched ${webBase}/SKILL.md and ${webBase}/hooks.json`);
|
|
148055
|
+
console.log(` Requested agents: ${requestedAgents.join(", ")}`);
|
|
148056
|
+
if (dryRun) stepInfo("dry run: no plugin commands or file writes will run");
|
|
148057
|
+
const detectedAgents = selection.kind === "standalone" ? [] : selection.pluginAgents.filter(
|
|
148058
|
+
(agent) => isCommandCallable(HARNESS_SPECS[agent].executable)
|
|
148059
|
+
);
|
|
148060
|
+
if (selection.kind === "default") {
|
|
148061
|
+
console.log(
|
|
148062
|
+
` Detected callable harnesses: ${detectedAgents.length > 0 ? detectedAgents.join(", ") : "none"}`
|
|
148063
|
+
);
|
|
147764
148064
|
}
|
|
147765
|
-
|
|
147766
|
-
const
|
|
147767
|
-
|
|
147768
|
-
|
|
147769
|
-
|
|
147770
|
-
|
|
147771
|
-
|
|
147772
|
-
|
|
147773
|
-
|
|
147774
|
-
|
|
148065
|
+
console.log("");
|
|
148066
|
+
const pluginResults = [];
|
|
148067
|
+
if (selection.kind !== "standalone") {
|
|
148068
|
+
for (const agent of selection.pluginAgents) {
|
|
148069
|
+
const spec = HARNESS_SPECS[agent];
|
|
148070
|
+
if (!detectedAgents.includes(agent)) {
|
|
148071
|
+
const result2 = {
|
|
148072
|
+
agent,
|
|
148073
|
+
displayName: spec.displayName,
|
|
148074
|
+
status: "skipped_unavailable",
|
|
148075
|
+
detail: `\`${spec.executable}\` is not callable in this shell`
|
|
148076
|
+
};
|
|
148077
|
+
pluginResults.push(result2);
|
|
148078
|
+
stepSkip(
|
|
148079
|
+
`${spec.displayName}: ${statusLabel(result2)}`,
|
|
148080
|
+
result2.detail
|
|
148081
|
+
);
|
|
148082
|
+
if (selection.kind === "specific") {
|
|
148083
|
+
printManualInstructions(spec);
|
|
148084
|
+
}
|
|
148085
|
+
continue;
|
|
148086
|
+
}
|
|
148087
|
+
const result = installHarnessPlugin(spec, { dryRun, verbose });
|
|
148088
|
+
pluginResults.push(result);
|
|
148089
|
+
if (result.status === "installed") {
|
|
148090
|
+
stepSuccess(
|
|
148091
|
+
`${spec.displayName}: ${statusLabel(result)}`,
|
|
148092
|
+
result.detail
|
|
148093
|
+
);
|
|
148094
|
+
} else if (result.status === "would_install") {
|
|
148095
|
+
stepSkip(
|
|
148096
|
+
`${spec.displayName}: ${statusLabel(result)}`,
|
|
148097
|
+
result.detail
|
|
148098
|
+
);
|
|
148099
|
+
} else {
|
|
148100
|
+
stepWarn(
|
|
148101
|
+
`${spec.displayName}: ${statusLabel(result)}`,
|
|
148102
|
+
result.detail
|
|
148103
|
+
);
|
|
148104
|
+
}
|
|
148105
|
+
}
|
|
147775
148106
|
}
|
|
147776
|
-
|
|
147777
|
-
|
|
147778
|
-
const hookScriptsInstalled = await installHookScripts(
|
|
147779
|
-
home,
|
|
147780
|
-
hooksJson,
|
|
147781
|
-
webBase,
|
|
147782
|
-
verbose
|
|
147783
|
-
);
|
|
147784
|
-
stepSuccess("Hook scripts installed", "~/.zero/hooks");
|
|
147785
|
-
currentStep = "settings";
|
|
147786
|
-
const settingsRegistered = registerHooksInClaudeSettings(
|
|
147787
|
-
home,
|
|
147788
|
-
hooksJson,
|
|
147789
|
-
verbose
|
|
148107
|
+
const pluginSucceeded = pluginResults.some(
|
|
148108
|
+
(result) => result.status === "installed" || result.status === "would_install"
|
|
147790
148109
|
);
|
|
147791
|
-
|
|
147792
|
-
|
|
148110
|
+
let standaloneFallbackReason;
|
|
148111
|
+
let standaloneFallbackUsed = false;
|
|
148112
|
+
let standaloneResult = {
|
|
148113
|
+
skillsInstalled: [],
|
|
148114
|
+
hookScriptsInstalled: [],
|
|
148115
|
+
settingsRegistered: false,
|
|
148116
|
+
codexHooksRegistered: false
|
|
148117
|
+
};
|
|
148118
|
+
if (selection.kind === "standalone" || !pluginSucceeded) {
|
|
148119
|
+
standaloneFallbackReason = fallbackReason(
|
|
148120
|
+
selection,
|
|
148121
|
+
detectedAgents,
|
|
148122
|
+
pluginResults
|
|
148123
|
+
);
|
|
148124
|
+
if (!fallbackAllowed && selection.kind !== "standalone") {
|
|
148125
|
+
throw new Error(
|
|
148126
|
+
`No Zero plugin install succeeded and --no-fallback was set (${standaloneFallbackReason}).`
|
|
148127
|
+
);
|
|
148128
|
+
}
|
|
148129
|
+
standaloneFallbackUsed = !dryRun;
|
|
148130
|
+
sectionDivider();
|
|
148131
|
+
const fallbackVerb = dryRun ? "would be used" : "used";
|
|
148132
|
+
console.log(
|
|
148133
|
+
` Standalone fallback ${fallbackVerb}: ${standaloneFallbackReason}.`
|
|
148134
|
+
);
|
|
148135
|
+
if (dryRun) {
|
|
148136
|
+
stepInfo("would install/update ~/.claude/skills/zero");
|
|
148137
|
+
stepInfo("would install/update ~/.agents/skills/zero");
|
|
148138
|
+
stepInfo(
|
|
148139
|
+
"would register current standalone hooks in ~/.claude/settings.json and ~/.codex/hooks.json"
|
|
148140
|
+
);
|
|
148141
|
+
} else {
|
|
148142
|
+
standaloneResult = await runStandaloneInit(appContext, {
|
|
148143
|
+
verbose,
|
|
148144
|
+
skillsDir: options.skillsDir,
|
|
148145
|
+
onStep: (step) => {
|
|
148146
|
+
currentStep = step;
|
|
148147
|
+
}
|
|
148148
|
+
});
|
|
148149
|
+
}
|
|
148150
|
+
} else {
|
|
148151
|
+
sectionDivider();
|
|
148152
|
+
console.log(
|
|
148153
|
+
" Standalone fallback not used: at least one harness plugin install succeeded."
|
|
148154
|
+
);
|
|
147793
148155
|
}
|
|
147794
148156
|
currentStep = "complete";
|
|
147795
148157
|
appContext.services.analyticsService.capture("init_completed", {
|
|
147796
148158
|
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
147797
|
-
|
|
148159
|
+
requested_agents: requestedAgents,
|
|
148160
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
148161
|
+
detected_harnesses: detectedAgents,
|
|
148162
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
148163
|
+
plugin_installs: pluginResults.map((result) => ({
|
|
148164
|
+
agent: result.agent,
|
|
148165
|
+
status: result.status
|
|
148166
|
+
})),
|
|
148167
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
148168
|
+
standalone_fallback_used: standaloneFallbackUsed,
|
|
148169
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
148170
|
+
standalone_fallback_reason: standaloneFallbackReason,
|
|
148171
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
148172
|
+
dry_run: dryRun,
|
|
148173
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
148174
|
+
skills_installed: standaloneResult.skillsInstalled,
|
|
148175
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
148176
|
+
skills_installed_count: standaloneResult.skillsInstalled.length,
|
|
147798
148177
|
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
147799
|
-
|
|
148178
|
+
hook_scripts_installed: standaloneResult.hookScriptsInstalled,
|
|
147800
148179
|
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
147801
|
-
|
|
148180
|
+
settings_registered: standaloneResult.settingsRegistered,
|
|
147802
148181
|
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
147803
|
-
|
|
148182
|
+
codex_hooks_registered: standaloneResult.codexHooksRegistered
|
|
147804
148183
|
});
|
|
147805
148184
|
sectionDivider();
|
|
147806
|
-
console.log(` ${color.boldGreen("Zero
|
|
148185
|
+
console.log(` ${color.boldGreen("Zero init complete.")}`);
|
|
147807
148186
|
console.log(
|
|
147808
148187
|
` ${color.dim("Next: sign in with `zero auth login` \u2014 it prints a URL to approve in your browser.")}`
|
|
147809
148188
|
);
|
|
148189
|
+
printRunnerModelNote();
|
|
147810
148190
|
console.log("");
|
|
147811
|
-
return {
|
|
148191
|
+
return {
|
|
148192
|
+
...standaloneResult,
|
|
148193
|
+
requestedAgents,
|
|
148194
|
+
detectedAgents,
|
|
148195
|
+
pluginResults,
|
|
148196
|
+
standaloneFallbackUsed,
|
|
148197
|
+
standaloneFallbackReason,
|
|
148198
|
+
dryRun
|
|
148199
|
+
};
|
|
147812
148200
|
} catch (err) {
|
|
147813
148201
|
appContext.services.analyticsService.capture("init_failed", {
|
|
147814
148202
|
step: currentStep,
|
|
@@ -147818,7 +148206,18 @@ var runInit = async (appContext, options = {}) => {
|
|
|
147818
148206
|
}
|
|
147819
148207
|
};
|
|
147820
148208
|
var initCommand = (appContext) => new Command("init").description(
|
|
147821
|
-
"Install the Zero
|
|
148209
|
+
"Install the Zero plugin for supported agents, with a standalone skill/hook fallback"
|
|
148210
|
+
).option(
|
|
148211
|
+
"--agent <agent>",
|
|
148212
|
+
"Agent target: codex, claude, gemini, openclaw, or standalone. Repeat or comma-separate values. Omit to target every supported agent.",
|
|
148213
|
+
collectAgentOption,
|
|
148214
|
+
[]
|
|
148215
|
+
).option(
|
|
148216
|
+
"--no-fallback",
|
|
148217
|
+
"Do not install standalone skills/hooks if plugin install does not succeed"
|
|
148218
|
+
).option(
|
|
148219
|
+
"--dry-run",
|
|
148220
|
+
"Show what would be installed without running commands or writing files"
|
|
147822
148221
|
).option(
|
|
147823
148222
|
"-v, --verbose",
|
|
147824
148223
|
"Explain why each install step was taken or skipped"
|
|
@@ -148166,11 +148565,12 @@ var formatDetail = (r2) => {
|
|
|
148166
148565
|
}
|
|
148167
148566
|
return lines.join("\n");
|
|
148168
148567
|
};
|
|
148169
|
-
var runsDetailCommand = (appContext) => new Command("detail").description("Show full metadata for a single run").argument("<runId>", "Run ID (run_\u2026)").option("--json", "Output raw JSON to stdout").action(async (runId,
|
|
148568
|
+
var runsDetailCommand = (appContext) => new Command("detail").description("Show full metadata for a single run (from server)").argument("<runId>", "Run ID (run_\u2026)").option("--json", "Output raw JSON to stdout").action(async (runId, _opts, cmd) => {
|
|
148569
|
+
const { json: json3 } = cmd.opts();
|
|
148170
148570
|
try {
|
|
148171
148571
|
const { client } = appContext.services;
|
|
148172
148572
|
const run = await client.runs.get(runId);
|
|
148173
|
-
if (
|
|
148573
|
+
if (json3) {
|
|
148174
148574
|
console.log(JSON.stringify(run, null, 2));
|
|
148175
148575
|
return;
|
|
148176
148576
|
}
|
|
@@ -148180,9 +148580,10 @@ var runsDetailCommand = (appContext) => new Command("detail").description("Show
|
|
|
148180
148580
|
process.exitCode = 1;
|
|
148181
148581
|
}
|
|
148182
148582
|
});
|
|
148183
|
-
var runsCommand = (appContext) =>
|
|
148184
|
-
"
|
|
148185
|
-
|
|
148583
|
+
var runsCommand = (appContext) => {
|
|
148584
|
+
const cmd = new Command("runs").description("List your recent capability runs").addHelpText(
|
|
148585
|
+
"after",
|
|
148586
|
+
`
|
|
148186
148587
|
View your recent capability runs \u2014 status, latency, cost, and payment info.
|
|
148187
148588
|
A leading [\u2713] means the run already has a review; [ ] means it does not.
|
|
148188
148589
|
|
|
@@ -148191,52 +148592,55 @@ Examples:
|
|
|
148191
148592
|
zero runs --unreviewed # filter to runs without a review
|
|
148192
148593
|
zero runs --capability translate-en # filter to one capability (uid or slug)
|
|
148193
148594
|
zero runs --json # full structured output for scripts
|
|
148194
|
-
zero runs detail <runId> # full metadata for a
|
|
148195
|
-
).
|
|
148196
|
-
|
|
148197
|
-
|
|
148198
|
-
|
|
148199
|
-
).option("--json", "Output raw JSON to stdout").option(
|
|
148200
|
-
|
|
148201
|
-
|
|
148202
|
-
).action(
|
|
148203
|
-
|
|
148204
|
-
|
|
148205
|
-
|
|
148206
|
-
|
|
148207
|
-
|
|
148208
|
-
|
|
148209
|
-
|
|
148210
|
-
|
|
148211
|
-
|
|
148212
|
-
|
|
148213
|
-
|
|
148214
|
-
|
|
148215
|
-
|
|
148216
|
-
|
|
148217
|
-
|
|
148218
|
-
|
|
148219
|
-
|
|
148220
|
-
|
|
148221
|
-
|
|
148222
|
-
|
|
148223
|
-
|
|
148224
|
-
|
|
148225
|
-
|
|
148226
|
-
|
|
148227
|
-
|
|
148228
|
-
|
|
148229
|
-
|
|
148230
|
-
|
|
148231
|
-
|
|
148595
|
+
zero runs detail <runId> # full server-side metadata for a run`
|
|
148596
|
+
).option("--capability <id>", "Filter by capability uid or slug").option("--unreviewed", "Only show runs without a review").option(
|
|
148597
|
+
"--limit <n>",
|
|
148598
|
+
"Max rows (1-100, default 25)",
|
|
148599
|
+
(v) => Number.parseInt(v, 10)
|
|
148600
|
+
).option("--json", "Output raw JSON to stdout").option(
|
|
148601
|
+
"--agent <name>",
|
|
148602
|
+
"Identify your agent host for this invocation. Overrides auto-detect for this call only."
|
|
148603
|
+
).action(
|
|
148604
|
+
async (options) => {
|
|
148605
|
+
try {
|
|
148606
|
+
const { client } = appContext.services;
|
|
148607
|
+
const result = await client.runs.list({
|
|
148608
|
+
capabilityId: options.capability,
|
|
148609
|
+
unreviewed: options.unreviewed,
|
|
148610
|
+
limit: options.limit
|
|
148611
|
+
});
|
|
148612
|
+
if (options.json) {
|
|
148613
|
+
console.log(JSON.stringify(result, null, 2));
|
|
148614
|
+
return;
|
|
148615
|
+
}
|
|
148616
|
+
if (result.runs.length === 0) {
|
|
148617
|
+
console.log("No runs found.");
|
|
148618
|
+
return;
|
|
148619
|
+
}
|
|
148620
|
+
for (const r2 of result.runs) {
|
|
148621
|
+
const when = r2.createdAt.toISOString().replace("T", " ").slice(0, 19);
|
|
148622
|
+
const mark = r2.reviewed ? "\u2713" : " ";
|
|
148623
|
+
const status = r2.status ?? "\u2014";
|
|
148624
|
+
const latency = r2.latencyMs != null ? `${r2.latencyMs}ms` : "\u2014";
|
|
148625
|
+
const cost = formatCost2(r2.cost);
|
|
148626
|
+
const payment = formatPayment(r2.payment);
|
|
148627
|
+
console.log(
|
|
148628
|
+
`[${mark}] ${r2.uid} ${r2.capabilitySlug} status=${status} ${latency} ${cost} ${payment} ${when}`
|
|
148629
|
+
);
|
|
148630
|
+
}
|
|
148631
|
+
if (result.nextCursor) {
|
|
148632
|
+
console.log(`
|
|
148232
148633
|
(more available \u2014 use --limit to see more)`);
|
|
148634
|
+
}
|
|
148635
|
+
} catch (err) {
|
|
148636
|
+
console.error(err instanceof Error ? err.message : "Failed");
|
|
148637
|
+
process.exitCode = 1;
|
|
148233
148638
|
}
|
|
148234
|
-
} catch (err) {
|
|
148235
|
-
console.error(err instanceof Error ? err.message : "Failed");
|
|
148236
|
-
process.exitCode = 1;
|
|
148237
148639
|
}
|
|
148238
|
-
|
|
148239
|
-
);
|
|
148640
|
+
);
|
|
148641
|
+
cmd.addCommand(runsDetailCommand(appContext));
|
|
148642
|
+
return cmd;
|
|
148643
|
+
};
|
|
148240
148644
|
|
|
148241
148645
|
// src/commands/search-command.ts
|
|
148242
148646
|
init_esm_shims();
|
|
@@ -148297,7 +148701,7 @@ var searchCommand = (appContext) => new Command("search").description("Search fo
|
|
|
148297
148701
|
).action(
|
|
148298
148702
|
async (query, options) => {
|
|
148299
148703
|
try {
|
|
148300
|
-
const { analyticsService, client
|
|
148704
|
+
const { analyticsService, client } = appContext.services;
|
|
148301
148705
|
if (options.protocol && !["x402", "mpp"].includes(options.protocol)) {
|
|
148302
148706
|
console.error(
|
|
148303
148707
|
`Invalid protocol "${options.protocol}". Must be x402 or mpp.`
|
|
@@ -148366,17 +148770,6 @@ var searchCommand = (appContext) => new Command("search").description("Search fo
|
|
|
148366
148770
|
);
|
|
148367
148771
|
return;
|
|
148368
148772
|
}
|
|
148369
|
-
stateService.saveLastSearch({
|
|
148370
|
-
searchId: result.searchId,
|
|
148371
|
-
capabilities: result.capabilities.map((c) => ({
|
|
148372
|
-
position: c.position,
|
|
148373
|
-
id: c.id,
|
|
148374
|
-
slug: c.slug,
|
|
148375
|
-
url: c.url,
|
|
148376
|
-
urlTemplate: c.urlTemplate ?? null,
|
|
148377
|
-
displayCostAmount: c.cost.amount
|
|
148378
|
-
}))
|
|
148379
|
-
});
|
|
148380
148773
|
console.log(formatSearchResults(result.capabilities));
|
|
148381
148774
|
if (result.hasMore) {
|
|
148382
148775
|
console.error(
|
|
@@ -148386,7 +148779,7 @@ var searchCommand = (appContext) => new Command("search").description("Search fo
|
|
|
148386
148779
|
}
|
|
148387
148780
|
if (result.capabilities.length > 0) {
|
|
148388
148781
|
console.error(
|
|
148389
|
-
"\n Run `zero get
|
|
148782
|
+
"\n Run `zero get <token>` (or `zero get <slug>`) to view a capability.\n"
|
|
148390
148783
|
);
|
|
148391
148784
|
}
|
|
148392
148785
|
} catch (err) {
|
|
@@ -148434,6 +148827,8 @@ var HOOK_FILES = [
|
|
|
148434
148827
|
"ensure-runner.sh"
|
|
148435
148828
|
];
|
|
148436
148829
|
var ZERO_SANDBOX_DOMAIN2 = "*.zero.xyz";
|
|
148830
|
+
var CLAUDE_SETTINGS_PATH2 = ".claude/settings.json";
|
|
148831
|
+
var CODEX_HOOKS_PATH2 = ".codex/hooks.json";
|
|
148437
148832
|
var LEGACY_SKILL_NAMES = ["zero"];
|
|
148438
148833
|
var removeSkills = (home, verbose = false) => {
|
|
148439
148834
|
const skillNames = LEGACY_SKILL_NAMES;
|
|
@@ -148459,30 +148854,17 @@ var removeSkills = (home, verbose = false) => {
|
|
|
148459
148854
|
return removed;
|
|
148460
148855
|
};
|
|
148461
148856
|
var removeHooks = (home, verbose = false) => {
|
|
148462
|
-
|
|
148463
|
-
|
|
148464
|
-
|
|
148465
|
-
|
|
148466
|
-
|
|
148467
|
-
|
|
148468
|
-
|
|
148469
|
-
|
|
148470
|
-
|
|
148471
|
-
|
|
148472
|
-
|
|
148473
|
-
}
|
|
148474
|
-
}
|
|
148475
|
-
if (settings) {
|
|
148476
|
-
settingsChanged = stripZeroFromSettings(settings, verbose);
|
|
148477
|
-
if (settingsChanged) {
|
|
148478
|
-
writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}
|
|
148479
|
-
`);
|
|
148480
|
-
if (verbose) stepInfo(`rewrote ${settingsPath} without Zero entries`);
|
|
148481
|
-
} else if (verbose) {
|
|
148482
|
-
stepInfo(`no Zero entries found in ${settingsPath}`);
|
|
148483
|
-
}
|
|
148484
|
-
}
|
|
148485
|
-
}
|
|
148857
|
+
const claudeSettingsChanged = stripZeroFromJsonFile(
|
|
148858
|
+
join(home, CLAUDE_SETTINGS_PATH2),
|
|
148859
|
+
verbose,
|
|
148860
|
+
true
|
|
148861
|
+
);
|
|
148862
|
+
const codexHooksChanged = stripZeroFromJsonFile(
|
|
148863
|
+
join(home, CODEX_HOOKS_PATH2),
|
|
148864
|
+
verbose,
|
|
148865
|
+
false
|
|
148866
|
+
);
|
|
148867
|
+
const settingsChanged = claudeSettingsChanged || codexHooksChanged;
|
|
148486
148868
|
let scriptsRemoved = 0;
|
|
148487
148869
|
const zeroHooksDir = join(home, ".zero", "hooks");
|
|
148488
148870
|
if (existsSync(zeroHooksDir)) {
|
|
@@ -148502,7 +148884,29 @@ var removeHooks = (home, verbose = false) => {
|
|
|
148502
148884
|
}
|
|
148503
148885
|
return { settingsChanged, scriptsRemoved };
|
|
148504
148886
|
};
|
|
148505
|
-
var
|
|
148887
|
+
var stripZeroFromJsonFile = (settingsPath, verbose, removeSandboxAllowlist) => {
|
|
148888
|
+
const result = updateJsonConfigFile(
|
|
148889
|
+
settingsPath,
|
|
148890
|
+
(settings) => stripZeroFromSettings(settings, verbose, removeSandboxAllowlist)
|
|
148891
|
+
);
|
|
148892
|
+
if (result.status === "missing") {
|
|
148893
|
+
if (verbose) stepInfo(`${settingsPath} not found \u2014 no settings to clean`);
|
|
148894
|
+
return false;
|
|
148895
|
+
}
|
|
148896
|
+
if (result.status === "unparseable") {
|
|
148897
|
+
if (verbose) {
|
|
148898
|
+
stepInfo(`${settingsPath} was unparseable JSON \u2014 leaving it untouched`);
|
|
148899
|
+
}
|
|
148900
|
+
return false;
|
|
148901
|
+
}
|
|
148902
|
+
if (result.status === "updated") {
|
|
148903
|
+
if (verbose) stepInfo(`rewrote ${settingsPath} without Zero entries`);
|
|
148904
|
+
return true;
|
|
148905
|
+
}
|
|
148906
|
+
if (verbose) stepInfo(`no Zero entries found in ${settingsPath}`);
|
|
148907
|
+
return false;
|
|
148908
|
+
};
|
|
148909
|
+
var stripZeroFromSettings = (settings, verbose, removeSandboxAllowlist) => {
|
|
148506
148910
|
let changed = false;
|
|
148507
148911
|
const hooks = settings.hooks && typeof settings.hooks === "object" ? settings.hooks : null;
|
|
148508
148912
|
if (hooks) {
|
|
@@ -148515,24 +148919,26 @@ var stripZeroFromSettings = (settings, verbose) => {
|
|
|
148515
148919
|
}
|
|
148516
148920
|
if (Object.keys(hooks).length === 0) delete settings.hooks;
|
|
148517
148921
|
}
|
|
148518
|
-
|
|
148519
|
-
|
|
148520
|
-
|
|
148521
|
-
|
|
148522
|
-
|
|
148523
|
-
|
|
148524
|
-
|
|
148525
|
-
|
|
148526
|
-
|
|
148527
|
-
|
|
148528
|
-
|
|
148529
|
-
|
|
148530
|
-
|
|
148531
|
-
|
|
148532
|
-
|
|
148533
|
-
|
|
148534
|
-
|
|
148535
|
-
|
|
148922
|
+
if (removeSandboxAllowlist) {
|
|
148923
|
+
const sandbox = settings.sandbox && typeof settings.sandbox === "object" ? settings.sandbox : null;
|
|
148924
|
+
const network = sandbox?.network && typeof sandbox.network === "object" ? sandbox.network : null;
|
|
148925
|
+
if (network && Array.isArray(network.allowedDomains)) {
|
|
148926
|
+
const domains = network.allowedDomains;
|
|
148927
|
+
const next = domains.filter((d3) => d3 !== ZERO_SANDBOX_DOMAIN2);
|
|
148928
|
+
if (next.length !== domains.length) {
|
|
148929
|
+
changed = true;
|
|
148930
|
+
if (verbose) {
|
|
148931
|
+
stepInfo(`sandbox.network.allowedDomains -= ${ZERO_SANDBOX_DOMAIN2}`);
|
|
148932
|
+
}
|
|
148933
|
+
if (next.length === 0) {
|
|
148934
|
+
delete network.allowedDomains;
|
|
148935
|
+
if (sandbox && Object.keys(network).length === 0)
|
|
148936
|
+
delete sandbox.network;
|
|
148937
|
+
if (sandbox && Object.keys(sandbox).length === 0)
|
|
148938
|
+
delete settings.sandbox;
|
|
148939
|
+
} else {
|
|
148940
|
+
network.allowedDomains = next;
|
|
148941
|
+
}
|
|
148536
148942
|
}
|
|
148537
148943
|
}
|
|
148538
148944
|
}
|
|
@@ -153656,105 +154062,6 @@ var AnalyticsService = class {
|
|
|
153656
154062
|
}
|
|
153657
154063
|
};
|
|
153658
154064
|
|
|
153659
|
-
// src/services/state-service.ts
|
|
153660
|
-
init_esm_shims();
|
|
153661
|
-
var RECENT_SEARCH_LIMIT = 10;
|
|
153662
|
-
var StateService = class {
|
|
153663
|
-
constructor(zeroDir) {
|
|
153664
|
-
this.zeroDir = zeroDir;
|
|
153665
|
-
this.lastSearchPath = join(zeroDir, "last_search.json");
|
|
153666
|
-
this.recentSearchesPath = join(zeroDir, "recent_searches.json");
|
|
153667
|
-
}
|
|
153668
|
-
lastSearchPath;
|
|
153669
|
-
recentSearchesPath;
|
|
153670
|
-
saveLastSearch = (data) => {
|
|
153671
|
-
mkdirSync(this.zeroDir, { recursive: true });
|
|
153672
|
-
writeFileSync(this.lastSearchPath, JSON.stringify(data, null, 2));
|
|
153673
|
-
const recent = this.loadRecentSearches();
|
|
153674
|
-
const filtered = recent.searches.filter(
|
|
153675
|
-
(s) => s.searchId !== data.searchId
|
|
153676
|
-
);
|
|
153677
|
-
const next = [data, ...filtered].slice(0, RECENT_SEARCH_LIMIT);
|
|
153678
|
-
writeFileSync(
|
|
153679
|
-
this.recentSearchesPath,
|
|
153680
|
-
JSON.stringify({ searches: next }, null, 2)
|
|
153681
|
-
);
|
|
153682
|
-
};
|
|
153683
|
-
loadLastSearch = () => {
|
|
153684
|
-
try {
|
|
153685
|
-
if (!existsSync(this.lastSearchPath)) return null;
|
|
153686
|
-
const raw = readFileSync(this.lastSearchPath, "utf8");
|
|
153687
|
-
return JSON.parse(raw);
|
|
153688
|
-
} catch {
|
|
153689
|
-
return null;
|
|
153690
|
-
}
|
|
153691
|
-
};
|
|
153692
|
-
loadRecentSearches = () => {
|
|
153693
|
-
try {
|
|
153694
|
-
if (!existsSync(this.recentSearchesPath)) {
|
|
153695
|
-
const last = this.loadLastSearch();
|
|
153696
|
-
return { searches: last ? [last] : [] };
|
|
153697
|
-
}
|
|
153698
|
-
const raw = readFileSync(this.recentSearchesPath, "utf8");
|
|
153699
|
-
const parsed = JSON.parse(raw);
|
|
153700
|
-
return { searches: parsed.searches ?? [] };
|
|
153701
|
-
} catch {
|
|
153702
|
-
return { searches: [] };
|
|
153703
|
-
}
|
|
153704
|
-
};
|
|
153705
|
-
// Walk recent searches newest-first, returning the first one whose
|
|
153706
|
-
// results contain `capabilityRef` (matches against uid OR slug).
|
|
153707
|
-
// Preferred over "loadLastSearch" for attributing rank — handles the
|
|
153708
|
-
// parallel-search case where the most recent search isn't the one being
|
|
153709
|
-
// fetched.
|
|
153710
|
-
findSearchContextByCapability = (capabilityRef) => {
|
|
153711
|
-
const recent = this.loadRecentSearches();
|
|
153712
|
-
for (const search of recent.searches) {
|
|
153713
|
-
const entry = search.capabilities.find(
|
|
153714
|
-
(c) => c.id === capabilityRef || c.slug === capabilityRef
|
|
153715
|
-
);
|
|
153716
|
-
if (entry) {
|
|
153717
|
-
return {
|
|
153718
|
-
searchId: search.searchId,
|
|
153719
|
-
resultRank: entry.position,
|
|
153720
|
-
capabilityId: entry.id,
|
|
153721
|
-
capabilityUid: entry.id,
|
|
153722
|
-
capabilitySlug: entry.slug ?? null,
|
|
153723
|
-
url: entry.url,
|
|
153724
|
-
displayCostAmount: entry.displayCostAmount
|
|
153725
|
-
};
|
|
153726
|
-
}
|
|
153727
|
-
}
|
|
153728
|
-
return null;
|
|
153729
|
-
};
|
|
153730
|
-
// URL-based attribution for `zero fetch <url>`. Matches by URL prefix
|
|
153731
|
-
// (some capabilities accept query params or path tails the agent appends)
|
|
153732
|
-
// across the recent ring, newest match wins. Falls back to a caller-
|
|
153733
|
-
// supplied urlTemplate matcher (ADS-509 path-parameterized URLs).
|
|
153734
|
-
findSearchContextByUrl = (url4, options) => {
|
|
153735
|
-
const recent = this.loadRecentSearches();
|
|
153736
|
-
for (const search of recent.searches) {
|
|
153737
|
-
const prefixHit = search.capabilities.find((c) => url4.startsWith(c.url));
|
|
153738
|
-
const templateHit = prefixHit ?? search.capabilities.find(
|
|
153739
|
-
(c) => c.urlTemplate && options?.matchTemplate ? options.matchTemplate(c.urlTemplate) : false
|
|
153740
|
-
);
|
|
153741
|
-
const entry = templateHit;
|
|
153742
|
-
if (entry) {
|
|
153743
|
-
return {
|
|
153744
|
-
searchId: search.searchId,
|
|
153745
|
-
resultRank: entry.position,
|
|
153746
|
-
capabilityId: entry.id,
|
|
153747
|
-
capabilityUid: entry.id,
|
|
153748
|
-
capabilitySlug: entry.slug ?? null,
|
|
153749
|
-
url: entry.url,
|
|
153750
|
-
displayCostAmount: entry.displayCostAmount
|
|
153751
|
-
};
|
|
153752
|
-
}
|
|
153753
|
-
}
|
|
153754
|
-
return null;
|
|
153755
|
-
};
|
|
153756
|
-
};
|
|
153757
|
-
|
|
153758
154065
|
// src/services/wallet-migration-service.ts
|
|
153759
154066
|
init_esm_shims();
|
|
153760
154067
|
var USDC_BASE3 = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
|
|
@@ -154038,7 +154345,6 @@ var getServices = async (env) => {
|
|
|
154038
154345
|
const walletMigrationService = new WalletMigrationService(
|
|
154039
154346
|
byoAccount ?? legacyAccount
|
|
154040
154347
|
);
|
|
154041
|
-
const stateService = new StateService(zeroDir);
|
|
154042
154348
|
const analyticsService = new AnalyticsService({
|
|
154043
154349
|
walletAddress: account?.address ?? null,
|
|
154044
154350
|
configPath,
|
|
@@ -154051,7 +154357,6 @@ var getServices = async (env) => {
|
|
|
154051
154357
|
analyticsService,
|
|
154052
154358
|
client,
|
|
154053
154359
|
walletMigrationService,
|
|
154054
|
-
stateService,
|
|
154055
154360
|
lowBalanceWarning,
|
|
154056
154361
|
// Canonical resolved wallet address across the CLI — covers BYO,
|
|
154057
154362
|
// managed (Privy embedded) and legacy paths via the precedence above.
|