@zeroxyz/cli 1.0.0 → 1.2.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/dist/index.js +495 -86
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -76582,7 +76582,7 @@ init_esm_shims();
|
|
|
76582
76582
|
|
|
76583
76583
|
// package.json
|
|
76584
76584
|
var package_default = {
|
|
76585
|
-
version: "1.
|
|
76585
|
+
version: "1.2.0"};
|
|
76586
76586
|
|
|
76587
76587
|
// src/app.ts
|
|
76588
76588
|
init_esm_shims();
|
|
@@ -77578,7 +77578,7 @@ init_esm_shims();
|
|
|
77578
77578
|
// ../sdk/dist/index.js
|
|
77579
77579
|
init_esm_shims();
|
|
77580
77580
|
|
|
77581
|
-
// ../sdk/dist/chunk-
|
|
77581
|
+
// ../sdk/dist/chunk-SLXRHGE4.js
|
|
77582
77582
|
init_esm_shims();
|
|
77583
77583
|
|
|
77584
77584
|
// ../../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
|
|
@@ -144034,7 +144034,7 @@ var Payments = class {
|
|
|
144034
144034
|
};
|
|
144035
144035
|
};
|
|
144036
144036
|
var package_default2 = {
|
|
144037
|
-
version: "0.
|
|
144037
|
+
version: "0.2.0"
|
|
144038
144038
|
};
|
|
144039
144039
|
var SDK_VERSION2 = package_default2.version;
|
|
144040
144040
|
var userWalletDtoSchema = external_exports3.object({
|
|
@@ -144999,7 +144999,7 @@ var Wallet = class {
|
|
|
144999
144999
|
};
|
|
145000
145000
|
};
|
|
145001
145001
|
var DEFAULT_BASE_URL = "https://api.zero.xyz";
|
|
145002
|
-
var DEFAULT_TIMEOUT_MS =
|
|
145002
|
+
var DEFAULT_TIMEOUT_MS = 18e4;
|
|
145003
145003
|
var DEFAULT_MAX_RETRIES = 2;
|
|
145004
145004
|
var noopRefresh = async () => {
|
|
145005
145005
|
};
|
|
@@ -145283,11 +145283,44 @@ var recordErrorFetchRun = async (client, opts, result) => {
|
|
|
145283
145283
|
} catch {
|
|
145284
145284
|
}
|
|
145285
145285
|
};
|
|
145286
|
+
var recordTimeoutRun = async (client, opts, err, startedAt, capabilityIdRequested) => {
|
|
145287
|
+
const result = errorFetchResult(
|
|
145288
|
+
startedAt,
|
|
145289
|
+
err.message,
|
|
145290
|
+
"timeout",
|
|
145291
|
+
capabilityIdRequested,
|
|
145292
|
+
"network_error"
|
|
145293
|
+
);
|
|
145294
|
+
await recordErrorFetchRun(client, opts, result);
|
|
145295
|
+
};
|
|
145296
|
+
var sniffJsonShapeBytes = (buf) => {
|
|
145297
|
+
let i = 0;
|
|
145298
|
+
if (buf.length >= 3 && buf[0] === 239 && buf[1] === 187 && buf[2] === 191) {
|
|
145299
|
+
i = 3;
|
|
145300
|
+
}
|
|
145301
|
+
while (i < buf.length && (buf[i] === 32 || buf[i] === 9 || buf[i] === 10 || buf[i] === 13)) {
|
|
145302
|
+
i++;
|
|
145303
|
+
}
|
|
145304
|
+
if (i >= buf.length) return false;
|
|
145305
|
+
return buf[i] === 123 || buf[i] === 91;
|
|
145306
|
+
};
|
|
145307
|
+
var withDefaultContentType = (headers, body) => {
|
|
145308
|
+
if (!headers && body === void 0) return void 0;
|
|
145309
|
+
const next = headers ? { ...headers } : {};
|
|
145310
|
+
if (body === void 0) return next;
|
|
145311
|
+
const hasContentType = Object.keys(next).some(
|
|
145312
|
+
(k3) => k3.toLowerCase() === "content-type"
|
|
145313
|
+
);
|
|
145314
|
+
if (!hasContentType) {
|
|
145315
|
+
next["content-type"] = typeof body === "string" || sniffJsonShapeBytes(body) ? "application/json" : "application/octet-stream";
|
|
145316
|
+
}
|
|
145317
|
+
return next;
|
|
145318
|
+
};
|
|
145286
145319
|
var clientFetch = async (client, url4, opts = {}) => {
|
|
145287
145320
|
const startedAt = Date.now();
|
|
145288
145321
|
const capabilityIdRequested = opts.capabilityId !== void 0;
|
|
145289
145322
|
const method = opts.method ?? (opts.body !== void 0 ? "POST" : "GET");
|
|
145290
|
-
const probeHeaders = opts.headers
|
|
145323
|
+
const probeHeaders = withDefaultContentType(opts.headers, opts.body);
|
|
145291
145324
|
const requestInit = {
|
|
145292
145325
|
method,
|
|
145293
145326
|
headers: probeHeaders,
|
|
@@ -145304,6 +145337,16 @@ var clientFetch = async (client, url4, opts = {}) => {
|
|
|
145304
145337
|
try {
|
|
145305
145338
|
response = await configuredFetch(url4, requestInit);
|
|
145306
145339
|
} catch (err) {
|
|
145340
|
+
if (err instanceof ZeroTimeoutError) {
|
|
145341
|
+
await recordTimeoutRun(
|
|
145342
|
+
client,
|
|
145343
|
+
opts,
|
|
145344
|
+
err,
|
|
145345
|
+
startedAt,
|
|
145346
|
+
capabilityIdRequested
|
|
145347
|
+
);
|
|
145348
|
+
throw err;
|
|
145349
|
+
}
|
|
145307
145350
|
if (err instanceof ZeroError) throw err;
|
|
145308
145351
|
const errMessage = err instanceof Error ? err.message : String(err);
|
|
145309
145352
|
const result2 = errorFetchResult(
|
|
@@ -145325,8 +145368,9 @@ var clientFetch = async (client, url4, opts = {}) => {
|
|
|
145325
145368
|
url: url4,
|
|
145326
145369
|
method,
|
|
145327
145370
|
// Fresh clone for the paid retry — same rationale as
|
|
145328
|
-
// the probe-side clone above.
|
|
145329
|
-
|
|
145371
|
+
// the probe-side clone above. Re-derives the default
|
|
145372
|
+
// Content-Type so the paid leg matches the probe.
|
|
145373
|
+
headers: withDefaultContentType(opts.headers, opts.body),
|
|
145330
145374
|
body: opts.body,
|
|
145331
145375
|
maxPay: opts.maxPay,
|
|
145332
145376
|
account: opts.account,
|
|
@@ -145362,6 +145406,15 @@ var clientFetch = async (client, url4, opts = {}) => {
|
|
|
145362
145406
|
);
|
|
145363
145407
|
await recordErrorFetchRun(client, opts, result2);
|
|
145364
145408
|
return result2;
|
|
145409
|
+
} else if (err instanceof ZeroTimeoutError) {
|
|
145410
|
+
await recordTimeoutRun(
|
|
145411
|
+
client,
|
|
145412
|
+
opts,
|
|
145413
|
+
err,
|
|
145414
|
+
startedAt,
|
|
145415
|
+
capabilityIdRequested
|
|
145416
|
+
);
|
|
145417
|
+
throw err;
|
|
145365
145418
|
} else {
|
|
145366
145419
|
throw err;
|
|
145367
145420
|
}
|
|
@@ -146367,7 +146420,7 @@ var fetchCommand = (appContext) => new Command("fetch").description(
|
|
|
146367
146420
|
"Read the request body from stdin (equivalent to `-d @-`)."
|
|
146368
146421
|
).option("-H, --header <header...>", "Headers in Key:Value format").option("--max-pay <amount>", "Maximum per-call spend limit (USDC)").option(
|
|
146369
146422
|
"--timeout <seconds>",
|
|
146370
|
-
"Per-request timeout in seconds, overriding the default (
|
|
146423
|
+
"Per-request timeout in seconds, overriding the default (180). Applies to each HTTP leg of the call (probe and paid retry), not as a wall-clock deadline."
|
|
146371
146424
|
).option(
|
|
146372
146425
|
"--capability <id>",
|
|
146373
146426
|
"Bind this fetch to a capability (uid or slug) so a reviewable run is recorded even without a prior `zero search`"
|
|
@@ -146858,29 +146911,140 @@ var formatRating = (rating) => {
|
|
|
146858
146911
|
return `${successPct} success, ${reviews} reviews`;
|
|
146859
146912
|
};
|
|
146860
146913
|
var asNode = (v) => v && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
146861
|
-
var
|
|
146914
|
+
var schemaType = (node) => {
|
|
146915
|
+
const t = node?.type;
|
|
146916
|
+
if (typeof t === "string") return t;
|
|
146917
|
+
if (Array.isArray(t)) {
|
|
146918
|
+
const first = t.find((x2) => typeof x2 === "string" && x2 !== "null");
|
|
146919
|
+
return typeof first === "string" ? first : void 0;
|
|
146920
|
+
}
|
|
146921
|
+
return void 0;
|
|
146922
|
+
};
|
|
146923
|
+
var coerceToType = (value, type2) => {
|
|
146924
|
+
if (typeof value !== "string") return value;
|
|
146925
|
+
if (type2 === "number" || type2 === "integer") {
|
|
146926
|
+
const n = Number(value);
|
|
146927
|
+
return value.trim() !== "" && Number.isFinite(n) ? n : value;
|
|
146928
|
+
}
|
|
146929
|
+
if (type2 === "boolean") {
|
|
146930
|
+
if (value === "true") return true;
|
|
146931
|
+
if (value === "false") return false;
|
|
146932
|
+
}
|
|
146933
|
+
return value;
|
|
146934
|
+
};
|
|
146935
|
+
var sampleValueFor = (fieldName, propSchema) => {
|
|
146862
146936
|
const node = asNode(propSchema);
|
|
146937
|
+
const type2 = schemaType(node);
|
|
146863
146938
|
const example = node?.example ?? node?.default;
|
|
146864
|
-
if (
|
|
146865
|
-
|
|
146866
|
-
|
|
146939
|
+
if (example !== void 0 && example !== null) {
|
|
146940
|
+
return coerceToType(example, type2);
|
|
146941
|
+
}
|
|
146942
|
+
switch (type2) {
|
|
146943
|
+
case "number":
|
|
146944
|
+
case "integer":
|
|
146945
|
+
return 0;
|
|
146946
|
+
case "boolean":
|
|
146947
|
+
return false;
|
|
146948
|
+
case "array":
|
|
146949
|
+
return [];
|
|
146950
|
+
case "object":
|
|
146951
|
+
return {};
|
|
146952
|
+
default:
|
|
146953
|
+
return `<${fieldName.toUpperCase()}>`;
|
|
146867
146954
|
}
|
|
146868
|
-
return `<${fieldName.toUpperCase()}>`;
|
|
146869
146955
|
};
|
|
146956
|
+
var placeholderFor = (fieldName, propSchema) => String(sampleValueFor(fieldName, propSchema));
|
|
146870
146957
|
var extractInputEnvelope = (bodySchema, method) => {
|
|
146871
|
-
|
|
146872
|
-
|
|
146958
|
+
const root = asNode(bodySchema);
|
|
146959
|
+
if (!root) return {};
|
|
146960
|
+
const props = asNode(root.properties);
|
|
146873
146961
|
if (!props) return {};
|
|
146874
146962
|
const inputProps = asNode(asNode(props.input)?.properties);
|
|
146875
146963
|
if (inputProps) {
|
|
146876
146964
|
return {
|
|
146877
|
-
queryParams: asNode(
|
|
146878
|
-
body: asNode(
|
|
146965
|
+
queryParams: asNode(inputProps.queryParams) ?? void 0,
|
|
146966
|
+
body: asNode(inputProps.body) ?? void 0
|
|
146879
146967
|
};
|
|
146880
146968
|
}
|
|
146881
146969
|
const upperMethod = method.toUpperCase();
|
|
146882
146970
|
const isGetLike = upperMethod === "GET" || upperMethod === "DELETE";
|
|
146883
|
-
return isGetLike ? { queryParams:
|
|
146971
|
+
return isGetLike ? { queryParams: root } : { body: root };
|
|
146972
|
+
};
|
|
146973
|
+
var schemaTypeLabel = (node) => {
|
|
146974
|
+
const t = node.type;
|
|
146975
|
+
if (typeof t === "string") return t;
|
|
146976
|
+
if (Array.isArray(t)) {
|
|
146977
|
+
const parts = t.filter((x2) => typeof x2 === "string");
|
|
146978
|
+
return parts.length > 0 ? parts.join(" | ") : "any";
|
|
146979
|
+
}
|
|
146980
|
+
return "any";
|
|
146981
|
+
};
|
|
146982
|
+
var constraintHint = (node) => {
|
|
146983
|
+
const num2 = (k3) => typeof node[k3] === "number" ? node[k3] : void 0;
|
|
146984
|
+
const min = num2("minimum");
|
|
146985
|
+
const max = num2("maximum");
|
|
146986
|
+
if (min !== void 0 && max !== void 0) return `range: ${min}..${max}`;
|
|
146987
|
+
if (min !== void 0) return `min: ${min}`;
|
|
146988
|
+
if (max !== void 0) return `max: ${max}`;
|
|
146989
|
+
const minLen = num2("minLength");
|
|
146990
|
+
const maxLen = num2("maxLength");
|
|
146991
|
+
if (minLen !== void 0 && maxLen !== void 0)
|
|
146992
|
+
return `length: ${minLen}..${maxLen}`;
|
|
146993
|
+
if (maxLen !== void 0) return `maxLength: ${maxLen}`;
|
|
146994
|
+
if (minLen !== void 0) return `minLength: ${minLen}`;
|
|
146995
|
+
return null;
|
|
146996
|
+
};
|
|
146997
|
+
var renderParam = (name, propSchema, required3) => {
|
|
146998
|
+
const node = asNode(propSchema) ?? {};
|
|
146999
|
+
const attrs = [schemaTypeLabel(node)];
|
|
147000
|
+
if (required3) attrs.push("required");
|
|
147001
|
+
if (node.default !== void 0)
|
|
147002
|
+
attrs.push(`default: ${JSON.stringify(node.default)}`);
|
|
147003
|
+
if (Array.isArray(node.enum))
|
|
147004
|
+
attrs.push(`one of: ${node.enum.map((v) => String(v)).join(" | ")}`);
|
|
147005
|
+
const hint = constraintHint(node);
|
|
147006
|
+
if (hint) attrs.push(hint);
|
|
147007
|
+
const lines = [` ${name} (${attrs.join(", ")})`];
|
|
147008
|
+
const desc = typeof node.description === "string" ? node.description.trim() : "";
|
|
147009
|
+
if (desc) lines.push(` ${desc}`);
|
|
147010
|
+
return lines;
|
|
147011
|
+
};
|
|
147012
|
+
var renderProps = (node) => {
|
|
147013
|
+
const props = node ? asNode(node.properties) : null;
|
|
147014
|
+
if (!props) return [];
|
|
147015
|
+
const entries = Object.entries(props);
|
|
147016
|
+
if (entries.length === 0) return [];
|
|
147017
|
+
const requiredSet = new Set(
|
|
147018
|
+
Array.isArray(node?.required) ? node.required.filter((x2) => typeof x2 === "string") : []
|
|
147019
|
+
);
|
|
147020
|
+
return entries.flatMap(
|
|
147021
|
+
([name, schema]) => renderParam(name, schema, requiredSet.has(name))
|
|
147022
|
+
);
|
|
147023
|
+
};
|
|
147024
|
+
var buildSchemaSection = (capability) => {
|
|
147025
|
+
const { queryParams, body } = extractInputEnvelope(
|
|
147026
|
+
capability.bodySchema,
|
|
147027
|
+
capability.method
|
|
147028
|
+
);
|
|
147029
|
+
return [...renderProps(queryParams), ...renderProps(body)];
|
|
147030
|
+
};
|
|
147031
|
+
var buildResponseSection = (capability) => {
|
|
147032
|
+
const rs = asNode(capability.responseSchema);
|
|
147033
|
+
if (!rs) return [];
|
|
147034
|
+
if (rs.example !== void 0) {
|
|
147035
|
+
const example = JSON.stringify(rs.example);
|
|
147036
|
+
const truncated = example.length > 300 ? `${example.slice(0, 300)}\u2026` : example;
|
|
147037
|
+
return [" Returns (example):", ` ${truncated}`];
|
|
147038
|
+
}
|
|
147039
|
+
const props = asNode(rs.properties);
|
|
147040
|
+
if (props) {
|
|
147041
|
+
const fields = Object.entries(props).map(
|
|
147042
|
+
([k3, v]) => `${k3}: ${schemaTypeLabel(asNode(v) ?? {})}`
|
|
147043
|
+
);
|
|
147044
|
+
if (fields.length > 0)
|
|
147045
|
+
return [" Returns:", ` { ${fields.join(", ")} }`];
|
|
147046
|
+
}
|
|
147047
|
+
return [];
|
|
146884
147048
|
};
|
|
146885
147049
|
var buildTryItExample = (capability) => {
|
|
146886
147050
|
const method = capability.method.toUpperCase();
|
|
@@ -146894,7 +147058,8 @@ var buildTryItExample = (capability) => {
|
|
|
146894
147058
|
([k3, v]) => `-H "${k3}: ${v}" # [caller-provided]`
|
|
146895
147059
|
);
|
|
146896
147060
|
if (method === "GET" || queryParams && !body) {
|
|
146897
|
-
const
|
|
147061
|
+
const qpProps = queryParams ? asNode(queryParams.properties) : null;
|
|
147062
|
+
const qs = qpProps ? Object.entries(qpProps).map(
|
|
146898
147063
|
([k3, schema]) => `${encodeURIComponent(k3)}=${encodeURIComponent(placeholderFor(k3, schema))}`
|
|
146899
147064
|
).join("&") : "";
|
|
146900
147065
|
const url4 = qs ? `${capability.url}?${qs}` : capability.url;
|
|
@@ -146908,15 +147073,16 @@ var buildTryItExample = (capability) => {
|
|
|
146908
147073
|
}
|
|
146909
147074
|
if (!queryParams && method === "GET") {
|
|
146910
147075
|
lines.push(
|
|
146911
|
-
" # bodySchema did not expose queryParams \u2014 call the URL as-is
|
|
147076
|
+
" # bodySchema did not expose queryParams \u2014 call the URL as-is."
|
|
146912
147077
|
);
|
|
146913
147078
|
}
|
|
146914
147079
|
return lines;
|
|
146915
147080
|
}
|
|
146916
|
-
const
|
|
146917
|
-
|
|
147081
|
+
const bodyProps = body ? asNode(body.properties) : null;
|
|
147082
|
+
const samplePayload = bodyProps ? Object.fromEntries(
|
|
147083
|
+
Object.entries(bodyProps).map(([k3, schema]) => [
|
|
146918
147084
|
k3,
|
|
146919
|
-
|
|
147085
|
+
sampleValueFor(k3, schema)
|
|
146920
147086
|
])
|
|
146921
147087
|
) : null;
|
|
146922
147088
|
const bodyJson = samplePayload ? JSON.stringify(samplePayload) : "<BODY_JSON>";
|
|
@@ -146924,9 +147090,9 @@ var buildTryItExample = (capability) => {
|
|
|
146924
147090
|
if (method !== "POST") lines.push(` -X ${method} \\`);
|
|
146925
147091
|
for (const h2 of headerFlags) lines.push(` ${h2} \\`);
|
|
146926
147092
|
lines.push(` -d '${bodyJson}'`);
|
|
146927
|
-
if (!
|
|
147093
|
+
if (!bodyProps) {
|
|
146928
147094
|
lines.push(
|
|
146929
|
-
" # bodySchema did not expose input.body \u2014 replace <BODY_JSON> with the
|
|
147095
|
+
" # bodySchema did not expose input.body \u2014 replace <BODY_JSON> with the documented request shape."
|
|
146930
147096
|
);
|
|
146931
147097
|
}
|
|
146932
147098
|
return lines;
|
|
@@ -146948,6 +147114,12 @@ var formatCapability = (capability) => {
|
|
|
146948
147114
|
lines.push(` ${promptLine}`);
|
|
146949
147115
|
}
|
|
146950
147116
|
}
|
|
147117
|
+
const schemaLines = buildSchemaSection(capability);
|
|
147118
|
+
if (schemaLines.length > 0) {
|
|
147119
|
+
lines.push("", "Parameters:");
|
|
147120
|
+
lines.push(...schemaLines);
|
|
147121
|
+
}
|
|
147122
|
+
lines.push(...buildResponseSection(capability));
|
|
146951
147123
|
lines.push(...buildTryItExample(capability));
|
|
146952
147124
|
return lines.join("\n");
|
|
146953
147125
|
};
|
|
@@ -147020,9 +147192,293 @@ var getCommand = (appContext) => new Command("get").description(
|
|
|
147020
147192
|
|
|
147021
147193
|
// src/commands/init-command.ts
|
|
147022
147194
|
init_esm_shims();
|
|
147023
|
-
|
|
147024
|
-
|
|
147025
|
-
|
|
147195
|
+
|
|
147196
|
+
// src/util/install-banner.ts
|
|
147197
|
+
init_esm_shims();
|
|
147198
|
+
var colorsEnabled = () => {
|
|
147199
|
+
if (process.env.NO_COLOR) return false;
|
|
147200
|
+
if (process.env.FORCE_COLOR) return true;
|
|
147201
|
+
return Boolean(process.stdout.isTTY);
|
|
147202
|
+
};
|
|
147203
|
+
var wrap5 = (code, text) => colorsEnabled() ? `\x1B[${code}m${text}\x1B[0m` : text;
|
|
147204
|
+
var color = {
|
|
147205
|
+
bold: (s) => wrap5("1", s),
|
|
147206
|
+
dim: (s) => wrap5("2", s),
|
|
147207
|
+
cyan: (s) => wrap5("36", s),
|
|
147208
|
+
magenta: (s) => wrap5("35", s),
|
|
147209
|
+
green: (s) => wrap5("32", s),
|
|
147210
|
+
yellow: (s) => wrap5("33", s),
|
|
147211
|
+
red: (s) => wrap5("31", s),
|
|
147212
|
+
gray: (s) => wrap5("90", s),
|
|
147213
|
+
boldCyan: (s) => wrap5("1;36", s),
|
|
147214
|
+
boldMagenta: (s) => wrap5("1;35", s),
|
|
147215
|
+
boldGreen: (s) => wrap5("1;32", s),
|
|
147216
|
+
boldRed: (s) => wrap5("1;31", s)
|
|
147217
|
+
};
|
|
147218
|
+
var supportsUnicode = () => {
|
|
147219
|
+
if (process.platform !== "win32") return true;
|
|
147220
|
+
return Boolean(
|
|
147221
|
+
process.env.WT_SESSION || process.env.TERM_PROGRAM === "vscode"
|
|
147222
|
+
);
|
|
147223
|
+
};
|
|
147224
|
+
var SYMBOLS = supportsUnicode() ? { check: "\u2713", arrow: "\u203A", warn: "!" } : { check: "OK", arrow: ">", warn: "!" };
|
|
147225
|
+
var stepSuccess = (label, detail) => {
|
|
147226
|
+
const line = detail ? ` ${color.boldGreen(SYMBOLS.check)} ${label} ${color.dim(detail)}` : ` ${color.boldGreen(SYMBOLS.check)} ${label}`;
|
|
147227
|
+
console.log(line);
|
|
147228
|
+
};
|
|
147229
|
+
var stepWarn = (label, detail) => {
|
|
147230
|
+
const line = detail ? ` ${color.yellow(SYMBOLS.warn)} ${label} ${color.dim(detail)}` : ` ${color.yellow(SYMBOLS.warn)} ${label}`;
|
|
147231
|
+
console.log(line);
|
|
147232
|
+
};
|
|
147233
|
+
var stepSkip = (label, detail) => {
|
|
147234
|
+
const line = detail ? ` ${color.gray(SYMBOLS.arrow)} ${color.dim(`${label} ${detail}`)}` : ` ${color.gray(SYMBOLS.arrow)} ${color.dim(label)}`;
|
|
147235
|
+
console.log(line);
|
|
147236
|
+
};
|
|
147237
|
+
var stepInfo = (message2) => {
|
|
147238
|
+
console.log(` ${color.gray("\xB7")} ${color.dim(message2)}`);
|
|
147239
|
+
};
|
|
147240
|
+
var sectionDivider = () => {
|
|
147241
|
+
console.log("");
|
|
147242
|
+
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"));
|
|
147243
|
+
console.log("");
|
|
147244
|
+
};
|
|
147245
|
+
|
|
147246
|
+
// src/commands/init-command.ts
|
|
147247
|
+
var SKILL_DIRS = [".claude/skills", ".agents/skills"];
|
|
147248
|
+
var ZERO_SANDBOX_DOMAIN = "*.zero.xyz";
|
|
147249
|
+
var PLUGIN_HOOKS_ROOT = "${CLAUDE_PLUGIN_ROOT}/hooks";
|
|
147250
|
+
var SCRIPT_NAME_PATTERN = /\$\{CLAUDE_PLUGIN_ROOT\}\/hooks\/([a-z0-9][a-z0-9-]*\.sh)/;
|
|
147251
|
+
var fetchText = async (url4) => {
|
|
147252
|
+
const res = await fetch(url4);
|
|
147253
|
+
if (!res.ok) {
|
|
147254
|
+
throw new Error(`GET ${url4} failed with ${res.status}`);
|
|
147255
|
+
}
|
|
147256
|
+
return await res.text();
|
|
147257
|
+
};
|
|
147258
|
+
var entryScriptNames = (entry) => {
|
|
147259
|
+
const names = [];
|
|
147260
|
+
for (const hook of entry.hooks ?? []) {
|
|
147261
|
+
if (typeof hook.command !== "string") continue;
|
|
147262
|
+
const match = hook.command.match(SCRIPT_NAME_PATTERN);
|
|
147263
|
+
if (match?.[1]) names.push(match[1]);
|
|
147264
|
+
}
|
|
147265
|
+
return names;
|
|
147266
|
+
};
|
|
147267
|
+
var expandHome = (path3, home) => {
|
|
147268
|
+
if (path3 === "~") return home;
|
|
147269
|
+
if (path3.startsWith("~/")) return join(home, path3.slice(2));
|
|
147270
|
+
return path3;
|
|
147271
|
+
};
|
|
147272
|
+
var installSkill = (skillsDirs, skillMd, verbose) => {
|
|
147273
|
+
const installed = [];
|
|
147274
|
+
for (const dir of skillsDirs) {
|
|
147275
|
+
const dest = join(dir, "zero");
|
|
147276
|
+
try {
|
|
147277
|
+
mkdirSync(dest, { recursive: true });
|
|
147278
|
+
writeFileSync(join(dest, "SKILL.md"), skillMd);
|
|
147279
|
+
installed.push(join(dest, "SKILL.md"));
|
|
147280
|
+
if (verbose) stepInfo(`wrote ${join(dest, "SKILL.md")}`);
|
|
147281
|
+
} catch (err) {
|
|
147282
|
+
stepWarn(
|
|
147283
|
+
`Could not write the skill under ${dir}`,
|
|
147284
|
+
err instanceof Error ? err.message : String(err)
|
|
147285
|
+
);
|
|
147286
|
+
}
|
|
147287
|
+
}
|
|
147288
|
+
return installed;
|
|
147289
|
+
};
|
|
147290
|
+
var installHookScripts = async (home, hooksJson, webBase, verbose) => {
|
|
147291
|
+
const names = /* @__PURE__ */ new Set();
|
|
147292
|
+
for (const entries of Object.values(hooksJson.hooks)) {
|
|
147293
|
+
for (const entry of entries ?? []) {
|
|
147294
|
+
for (const name of entryScriptNames(entry)) names.add(name);
|
|
147295
|
+
}
|
|
147296
|
+
}
|
|
147297
|
+
if (names.size === 0) {
|
|
147298
|
+
throw new Error("hooks.json declared no recognizable hook scripts");
|
|
147299
|
+
}
|
|
147300
|
+
const hooksDir = join(home, ".zero", "hooks");
|
|
147301
|
+
mkdirSync(hooksDir, { recursive: true });
|
|
147302
|
+
return await Promise.all(
|
|
147303
|
+
[...names].map(async (name) => {
|
|
147304
|
+
const body = await fetchText(`${webBase}/hooks/${name}`);
|
|
147305
|
+
const dest = join(hooksDir, name);
|
|
147306
|
+
writeFileSync(dest, body);
|
|
147307
|
+
chmodSync(dest, 493);
|
|
147308
|
+
if (verbose) stepInfo(`wrote ${dest}`);
|
|
147309
|
+
return name;
|
|
147310
|
+
})
|
|
147311
|
+
);
|
|
147312
|
+
};
|
|
147313
|
+
var registerHooksInClaudeSettings = (home, hooksJson, verbose) => {
|
|
147314
|
+
const hooksDir = join(home, ".zero", "hooks");
|
|
147315
|
+
const settingsPath = join(home, ".claude", "settings.json");
|
|
147316
|
+
let settings = {};
|
|
147317
|
+
if (existsSync(settingsPath)) {
|
|
147318
|
+
try {
|
|
147319
|
+
settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
147320
|
+
} catch {
|
|
147321
|
+
stepWarn(
|
|
147322
|
+
"Hooks not registered",
|
|
147323
|
+
`${settingsPath} is not valid JSON \u2014 fix it and re-run \`zero init\``
|
|
147324
|
+
);
|
|
147325
|
+
return false;
|
|
147326
|
+
}
|
|
147327
|
+
}
|
|
147328
|
+
if (!settings.hooks || typeof settings.hooks !== "object") {
|
|
147329
|
+
settings.hooks = {};
|
|
147330
|
+
}
|
|
147331
|
+
const hooks = settings.hooks;
|
|
147332
|
+
for (const [event, entries] of Object.entries(hooksJson.hooks)) {
|
|
147333
|
+
for (const entry of entries ?? []) {
|
|
147334
|
+
const scripts = entryScriptNames(entry);
|
|
147335
|
+
if (scripts.length === 0) {
|
|
147336
|
+
if (verbose) {
|
|
147337
|
+
stepInfo(`${event}: entry has no plugin hook script \u2014 skipped`);
|
|
147338
|
+
}
|
|
147339
|
+
continue;
|
|
147340
|
+
}
|
|
147341
|
+
const rewritten = {
|
|
147342
|
+
...entry,
|
|
147343
|
+
hooks: (entry.hooks ?? []).map((hook) => ({
|
|
147344
|
+
...hook,
|
|
147345
|
+
command: typeof hook.command === "string" ? hook.command.replaceAll(PLUGIN_HOOKS_ROOT, hooksDir) : hook.command
|
|
147346
|
+
}))
|
|
147347
|
+
};
|
|
147348
|
+
if (!Array.isArray(hooks[event])) hooks[event] = [];
|
|
147349
|
+
const list2 = hooks[event];
|
|
147350
|
+
const existingIdx = list2.findIndex((existing) => {
|
|
147351
|
+
const existingHooks = existing?.hooks;
|
|
147352
|
+
if (!Array.isArray(existingHooks)) return false;
|
|
147353
|
+
return existingHooks.some(
|
|
147354
|
+
(h2) => typeof h2.command === "string" && scripts.some((s) => h2.command.includes(s))
|
|
147355
|
+
);
|
|
147356
|
+
});
|
|
147357
|
+
if (existingIdx >= 0) {
|
|
147358
|
+
list2[existingIdx] = rewritten;
|
|
147359
|
+
if (verbose) stepInfo(`${event}: ${scripts.join(", ")} entry replaced`);
|
|
147360
|
+
} else {
|
|
147361
|
+
list2.push(rewritten);
|
|
147362
|
+
if (verbose) stepInfo(`${event}: ${scripts.join(", ")} entry appended`);
|
|
147363
|
+
}
|
|
147364
|
+
}
|
|
147365
|
+
}
|
|
147366
|
+
if (!settings.sandbox || typeof settings.sandbox !== "object") {
|
|
147367
|
+
settings.sandbox = {};
|
|
147368
|
+
}
|
|
147369
|
+
const sandbox = settings.sandbox;
|
|
147370
|
+
if (!sandbox.network || typeof sandbox.network !== "object") {
|
|
147371
|
+
sandbox.network = {};
|
|
147372
|
+
}
|
|
147373
|
+
const network = sandbox.network;
|
|
147374
|
+
if (!Array.isArray(network.allowedDomains)) {
|
|
147375
|
+
network.allowedDomains = [];
|
|
147376
|
+
}
|
|
147377
|
+
const allowedDomains = network.allowedDomains;
|
|
147378
|
+
if (!allowedDomains.includes(ZERO_SANDBOX_DOMAIN)) {
|
|
147379
|
+
allowedDomains.push(ZERO_SANDBOX_DOMAIN);
|
|
147380
|
+
if (verbose) {
|
|
147381
|
+
stepInfo(`sandbox.network.allowedDomains += ${ZERO_SANDBOX_DOMAIN}`);
|
|
147382
|
+
}
|
|
147383
|
+
}
|
|
147384
|
+
mkdirSync(join(home, ".claude"), { recursive: true });
|
|
147385
|
+
writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}
|
|
147386
|
+
`);
|
|
147387
|
+
return true;
|
|
147388
|
+
};
|
|
147389
|
+
var runInit = async (appContext, options = {}) => {
|
|
147390
|
+
const verbose = options.verbose ?? false;
|
|
147391
|
+
appContext.services.analyticsService.capture("init_started", {});
|
|
147392
|
+
let currentStep = "fetch";
|
|
147393
|
+
try {
|
|
147394
|
+
console.log("");
|
|
147395
|
+
console.log(` ${color.boldCyan("Installing Zero")}`);
|
|
147396
|
+
console.log("");
|
|
147397
|
+
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"));
|
|
147398
|
+
console.log("");
|
|
147399
|
+
const home = homedir();
|
|
147400
|
+
const webBase = appContext.env.ZERO_WEB_URL;
|
|
147401
|
+
const [skillMd, hooksJsonRaw] = await Promise.all([
|
|
147402
|
+
fetchText(`${webBase}/SKILL.md`),
|
|
147403
|
+
fetchText(`${webBase}/hooks.json`)
|
|
147404
|
+
]);
|
|
147405
|
+
let hooksJson;
|
|
147406
|
+
try {
|
|
147407
|
+
hooksJson = JSON.parse(hooksJsonRaw);
|
|
147408
|
+
} catch {
|
|
147409
|
+
throw new Error(`${webBase}/hooks.json is not valid JSON`);
|
|
147410
|
+
}
|
|
147411
|
+
if (!hooksJson?.hooks || typeof hooksJson.hooks !== "object") {
|
|
147412
|
+
throw new Error(`${webBase}/hooks.json has no "hooks" object`);
|
|
147413
|
+
}
|
|
147414
|
+
if (verbose) {
|
|
147415
|
+
stepInfo(`fetched ${webBase}/SKILL.md and ${webBase}/hooks.json`);
|
|
147416
|
+
}
|
|
147417
|
+
currentStep = "skill";
|
|
147418
|
+
const skillsDirs = [
|
|
147419
|
+
.../* @__PURE__ */ new Set([
|
|
147420
|
+
...SKILL_DIRS.map((dir) => join(home, dir)),
|
|
147421
|
+
...(options.skillsDir ?? []).map((dir) => expandHome(dir, home))
|
|
147422
|
+
])
|
|
147423
|
+
];
|
|
147424
|
+
const skillsInstalled = installSkill(skillsDirs, skillMd, verbose);
|
|
147425
|
+
if (skillsInstalled.length === 0) {
|
|
147426
|
+
throw new Error("could not write the Zero skill to any skills directory");
|
|
147427
|
+
}
|
|
147428
|
+
stepSuccess("Skill installed", `${skillsInstalled.length} locations`);
|
|
147429
|
+
currentStep = "hooks";
|
|
147430
|
+
const hookScriptsInstalled = await installHookScripts(
|
|
147431
|
+
home,
|
|
147432
|
+
hooksJson,
|
|
147433
|
+
webBase,
|
|
147434
|
+
verbose
|
|
147435
|
+
);
|
|
147436
|
+
stepSuccess("Hook scripts installed", "~/.zero/hooks");
|
|
147437
|
+
currentStep = "settings";
|
|
147438
|
+
const settingsRegistered = registerHooksInClaudeSettings(
|
|
147439
|
+
home,
|
|
147440
|
+
hooksJson,
|
|
147441
|
+
verbose
|
|
147442
|
+
);
|
|
147443
|
+
if (settingsRegistered) {
|
|
147444
|
+
stepSuccess("Hooks registered", "~/.claude/settings.json");
|
|
147445
|
+
}
|
|
147446
|
+
currentStep = "complete";
|
|
147447
|
+
appContext.services.analyticsService.capture("init_completed", {
|
|
147448
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
147449
|
+
skills_installed: skillsInstalled,
|
|
147450
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
147451
|
+
skills_installed_count: skillsInstalled.length,
|
|
147452
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
147453
|
+
hook_scripts_installed: hookScriptsInstalled,
|
|
147454
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
147455
|
+
settings_registered: settingsRegistered
|
|
147456
|
+
});
|
|
147457
|
+
sectionDivider();
|
|
147458
|
+
console.log(` ${color.boldGreen("Zero is set up.")}`);
|
|
147459
|
+
console.log(
|
|
147460
|
+
` ${color.dim("Next: sign in with `zero auth login` \u2014 it prints a URL to approve in your browser.")}`
|
|
147461
|
+
);
|
|
147462
|
+
console.log("");
|
|
147463
|
+
return { skillsInstalled, hookScriptsInstalled, settingsRegistered };
|
|
147464
|
+
} catch (err) {
|
|
147465
|
+
appContext.services.analyticsService.capture("init_failed", {
|
|
147466
|
+
step: currentStep,
|
|
147467
|
+
error: truncateError(err instanceof Error ? err.message : String(err))
|
|
147468
|
+
});
|
|
147469
|
+
throw err;
|
|
147470
|
+
}
|
|
147471
|
+
};
|
|
147472
|
+
var initCommand = (appContext) => new Command("init").description(
|
|
147473
|
+
"Install the Zero skill and hooks for the agent harnesses on this machine"
|
|
147474
|
+
).option(
|
|
147475
|
+
"-v, --verbose",
|
|
147476
|
+
"Explain why each install step was taken or skipped"
|
|
147477
|
+
).option(
|
|
147478
|
+
"--skills-dir <dir...>",
|
|
147479
|
+
"Additional skills directories to install the skill into, for harnesses with bespoke locations (e.g. ~/.kiro/skills). ~/.claude/skills and ~/.agents/skills are always written. Note: `zero uninstall` only cleans the default locations."
|
|
147480
|
+
).action(async (options) => {
|
|
147481
|
+
await runInit(appContext, options);
|
|
147026
147482
|
});
|
|
147027
147483
|
|
|
147028
147484
|
// src/commands/review-command.ts
|
|
@@ -147288,58 +147744,6 @@ Examples:
|
|
|
147288
147744
|
|
|
147289
147745
|
// src/commands/search-command.ts
|
|
147290
147746
|
init_esm_shims();
|
|
147291
|
-
|
|
147292
|
-
// src/util/install-banner.ts
|
|
147293
|
-
init_esm_shims();
|
|
147294
|
-
var colorsEnabled = () => {
|
|
147295
|
-
if (process.env.NO_COLOR) return false;
|
|
147296
|
-
if (process.env.FORCE_COLOR) return true;
|
|
147297
|
-
return Boolean(process.stdout.isTTY);
|
|
147298
|
-
};
|
|
147299
|
-
var wrap5 = (code, text) => colorsEnabled() ? `\x1B[${code}m${text}\x1B[0m` : text;
|
|
147300
|
-
var color = {
|
|
147301
|
-
bold: (s) => wrap5("1", s),
|
|
147302
|
-
dim: (s) => wrap5("2", s),
|
|
147303
|
-
cyan: (s) => wrap5("36", s),
|
|
147304
|
-
magenta: (s) => wrap5("35", s),
|
|
147305
|
-
green: (s) => wrap5("32", s),
|
|
147306
|
-
yellow: (s) => wrap5("33", s),
|
|
147307
|
-
red: (s) => wrap5("31", s),
|
|
147308
|
-
gray: (s) => wrap5("90", s),
|
|
147309
|
-
boldCyan: (s) => wrap5("1;36", s),
|
|
147310
|
-
boldMagenta: (s) => wrap5("1;35", s),
|
|
147311
|
-
boldGreen: (s) => wrap5("1;32", s),
|
|
147312
|
-
boldRed: (s) => wrap5("1;31", s)
|
|
147313
|
-
};
|
|
147314
|
-
var supportsUnicode = () => {
|
|
147315
|
-
if (process.platform !== "win32") return true;
|
|
147316
|
-
return Boolean(
|
|
147317
|
-
process.env.WT_SESSION || process.env.TERM_PROGRAM === "vscode"
|
|
147318
|
-
);
|
|
147319
|
-
};
|
|
147320
|
-
var SYMBOLS = supportsUnicode() ? { check: "\u2713", arrow: "\u203A", warn: "!" } : { check: "OK", arrow: ">", warn: "!" };
|
|
147321
|
-
var stepSuccess = (label, detail) => {
|
|
147322
|
-
const line = detail ? ` ${color.boldGreen(SYMBOLS.check)} ${label} ${color.dim(detail)}` : ` ${color.boldGreen(SYMBOLS.check)} ${label}`;
|
|
147323
|
-
console.log(line);
|
|
147324
|
-
};
|
|
147325
|
-
var stepWarn = (label, detail) => {
|
|
147326
|
-
const line = ` ${color.yellow(SYMBOLS.warn)} ${label} ${color.dim(detail)}` ;
|
|
147327
|
-
console.log(line);
|
|
147328
|
-
};
|
|
147329
|
-
var stepSkip = (label, detail) => {
|
|
147330
|
-
const line = detail ? ` ${color.gray(SYMBOLS.arrow)} ${color.dim(`${label} ${detail}`)}` : ` ${color.gray(SYMBOLS.arrow)} ${color.dim(label)}`;
|
|
147331
|
-
console.log(line);
|
|
147332
|
-
};
|
|
147333
|
-
var stepInfo = (message2) => {
|
|
147334
|
-
console.log(` ${color.gray("\xB7")} ${color.dim(message2)}`);
|
|
147335
|
-
};
|
|
147336
|
-
var sectionDivider = () => {
|
|
147337
|
-
console.log("");
|
|
147338
|
-
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"));
|
|
147339
|
-
console.log("");
|
|
147340
|
-
};
|
|
147341
|
-
|
|
147342
|
-
// src/commands/search-command.ts
|
|
147343
147747
|
var DEFAULT_MAX_COST_USD = "30";
|
|
147344
147748
|
var formatReviewCount2 = (count) => {
|
|
147345
147749
|
if (count >= 1e3) return `${(count / 1e3).toFixed(1)}k`;
|
|
@@ -147528,8 +147932,12 @@ var AGENT_TOOLS = [
|
|
|
147528
147932
|
},
|
|
147529
147933
|
{ name: "Cursor", detectDir: ".cursor", skillsDir: ".cursor/skills" }
|
|
147530
147934
|
];
|
|
147531
|
-
var HOOK_FILES = [
|
|
147532
|
-
|
|
147935
|
+
var HOOK_FILES = [
|
|
147936
|
+
"auto-approve-zero.sh",
|
|
147937
|
+
"zero-context.sh",
|
|
147938
|
+
"ensure-runner.sh"
|
|
147939
|
+
];
|
|
147940
|
+
var ZERO_SANDBOX_DOMAIN2 = "*.zero.xyz";
|
|
147533
147941
|
var LEGACY_SKILL_NAMES = ["zero"];
|
|
147534
147942
|
var removeSkills = (home, verbose = false) => {
|
|
147535
147943
|
const skillNames = LEGACY_SKILL_NAMES;
|
|
@@ -147604,7 +148012,8 @@ var stripZeroFromSettings = (settings, verbose) => {
|
|
|
147604
148012
|
if (hooks) {
|
|
147605
148013
|
changed = removeHookEntries(hooks, "PreToolUse", "auto-approve-zero", verbose) || changed;
|
|
147606
148014
|
changed = removeHookEntries(hooks, "UserPromptSubmit", "zero-context", verbose) || changed;
|
|
147607
|
-
|
|
148015
|
+
changed = removeHookEntries(hooks, "SessionStart", "ensure-runner", verbose) || changed;
|
|
148016
|
+
for (const key of ["PreToolUse", "UserPromptSubmit", "SessionStart"]) {
|
|
147608
148017
|
const arr = hooks[key];
|
|
147609
148018
|
if (Array.isArray(arr) && arr.length === 0) delete hooks[key];
|
|
147610
148019
|
}
|
|
@@ -147614,11 +148023,11 @@ var stripZeroFromSettings = (settings, verbose) => {
|
|
|
147614
148023
|
const network = sandbox?.network && typeof sandbox.network === "object" ? sandbox.network : null;
|
|
147615
148024
|
if (network && Array.isArray(network.allowedDomains)) {
|
|
147616
148025
|
const domains = network.allowedDomains;
|
|
147617
|
-
const next = domains.filter((d3) => d3 !==
|
|
148026
|
+
const next = domains.filter((d3) => d3 !== ZERO_SANDBOX_DOMAIN2);
|
|
147618
148027
|
if (next.length !== domains.length) {
|
|
147619
148028
|
changed = true;
|
|
147620
148029
|
if (verbose) {
|
|
147621
|
-
stepInfo(`sandbox.network.allowedDomains -= ${
|
|
148030
|
+
stepInfo(`sandbox.network.allowedDomains -= ${ZERO_SANDBOX_DOMAIN2}`);
|
|
147622
148031
|
}
|
|
147623
148032
|
if (next.length === 0) {
|
|
147624
148033
|
delete network.allowedDomains;
|
|
@@ -148648,7 +149057,7 @@ var createApp = (appContext) => {
|
|
|
148648
149057
|
command: actionCommand.name()
|
|
148649
149058
|
});
|
|
148650
149059
|
});
|
|
148651
|
-
program2.addCommand(initCommand());
|
|
149060
|
+
program2.addCommand(initCommand(appContext));
|
|
148652
149061
|
program2.addCommand(uninstallCommand(appContext));
|
|
148653
149062
|
program2.addCommand(searchCommand(appContext));
|
|
148654
149063
|
program2.addCommand(getCommand(appContext));
|