@zeroxyz/cli 0.0.22 → 0.0.23
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 +83 -57
- package/package.json +1 -1
- package/skills/zero/SKILL.md +11 -3
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command as Command9 } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@zeroxyz/cli",
|
|
9
|
-
version: "0.0.
|
|
9
|
+
version: "0.0.23",
|
|
10
10
|
type: "module",
|
|
11
11
|
bin: {
|
|
12
12
|
zero: "dist/index.js",
|
|
@@ -168,7 +168,10 @@ var detectPaymentRequirement = (headers, status) => {
|
|
|
168
168
|
}
|
|
169
169
|
return { protocol: "unknown", raw: {} };
|
|
170
170
|
};
|
|
171
|
-
var fetchCommand = (appContext) => new Command2("fetch").description("Fetch a capability URL with automatic payment handling").argument("<url>", "URL to fetch").option(
|
|
171
|
+
var fetchCommand = (appContext) => new Command2("fetch").description("Fetch a capability URL with automatic payment handling").argument("<url>", "URL to fetch").option(
|
|
172
|
+
"-X, --method <method>",
|
|
173
|
+
"HTTP method (GET, POST, PUT, PATCH, DELETE). Defaults to POST when -d is set, otherwise GET"
|
|
174
|
+
).option("-d, --data <body>", "Request body (JSON string)").option("-H, --header <header...>", "Headers in Key:Value format").option("--max-pay <amount>", "Maximum amount willing to pay (USDC)").option(
|
|
172
175
|
"--capability <id>",
|
|
173
176
|
"Bind this fetch to a capability (uid or slug) so a reviewable run is recorded even without a prior `zero search`"
|
|
174
177
|
).option(
|
|
@@ -201,55 +204,80 @@ var fetchCommand = (appContext) => new Command2("fetch").description("Fetch a ca
|
|
|
201
204
|
headers["content-type"] = "application/json";
|
|
202
205
|
}
|
|
203
206
|
const log = (msg) => console.error(` ${msg}`);
|
|
207
|
+
const method = options.method ? options.method.toUpperCase() : options.data ? "POST" : "GET";
|
|
204
208
|
const requestInit = {
|
|
205
|
-
method
|
|
209
|
+
method,
|
|
206
210
|
headers,
|
|
207
211
|
body: options.data
|
|
208
212
|
};
|
|
209
|
-
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
response.headers,
|
|
213
|
-
response.status
|
|
213
|
+
const lastSearch = stateService.loadLastSearch();
|
|
214
|
+
const matchedCapability = lastSearch?.capabilities.find(
|
|
215
|
+
(c) => url.startsWith(c.url)
|
|
214
216
|
);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
const capabilityId = options.capability ?? matchedCapability?.id ?? null;
|
|
218
|
+
const searchId = matchedCapability ? lastSearch?.searchId : void 0;
|
|
219
|
+
const skipReasons = [];
|
|
220
|
+
if (!apiService.walletAddress) {
|
|
221
|
+
skipReasons.push(
|
|
222
|
+
"no wallet configured (run `zero wallet import` / set ZERO_PRIVATE_KEY)"
|
|
220
223
|
);
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
options.maxPay,
|
|
226
|
-
log
|
|
224
|
+
}
|
|
225
|
+
if (!capabilityId) {
|
|
226
|
+
skipReasons.push(
|
|
227
|
+
"no capability resolved \u2014 pass --capability <uid|slug> or run `zero search` first so the URL can be matched"
|
|
227
228
|
);
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
229
|
+
}
|
|
230
|
+
let finalResponse;
|
|
231
|
+
let body = "";
|
|
232
|
+
let paymentMeta;
|
|
233
|
+
let fetchError;
|
|
234
|
+
try {
|
|
235
|
+
log(`Calling ${url}...`);
|
|
236
|
+
const response = await fetch(url, requestInit);
|
|
237
|
+
const paymentReq = detectPaymentRequirement(
|
|
238
|
+
response.headers,
|
|
239
|
+
response.status
|
|
238
240
|
);
|
|
239
|
-
|
|
240
|
-
|
|
241
|
+
if (paymentReq) {
|
|
242
|
+
log(
|
|
243
|
+
`Payment required (${paymentReq.protocol}) \u2014 preparing payment...`
|
|
244
|
+
);
|
|
245
|
+
const result = await paymentService.handlePayment(
|
|
246
|
+
url,
|
|
247
|
+
requestInit,
|
|
248
|
+
paymentReq,
|
|
249
|
+
options.maxPay,
|
|
250
|
+
log
|
|
251
|
+
);
|
|
252
|
+
finalResponse = result.response;
|
|
253
|
+
paymentMeta = {
|
|
254
|
+
protocol: result.protocol,
|
|
255
|
+
chain: result.chain,
|
|
256
|
+
txHash: result.txHash,
|
|
257
|
+
amount: result.amount,
|
|
258
|
+
asset: result.asset
|
|
259
|
+
};
|
|
260
|
+
log(
|
|
261
|
+
`Paid ${result.amount} ${result.asset} via ${result.protocol} on ${result.chain}`
|
|
262
|
+
);
|
|
263
|
+
} else {
|
|
264
|
+
finalResponse = response;
|
|
265
|
+
}
|
|
266
|
+
body = await finalResponse.text();
|
|
267
|
+
} catch (err) {
|
|
268
|
+
fetchError = err instanceof Error ? err : new Error(String(err));
|
|
241
269
|
}
|
|
242
270
|
const latencyMs = Date.now() - startTime;
|
|
243
|
-
|
|
244
|
-
if (!options.json) {
|
|
271
|
+
if (finalResponse && !options.json) {
|
|
245
272
|
console.log(body);
|
|
246
273
|
}
|
|
247
274
|
analyticsService.capture("fetch_executed", {
|
|
248
275
|
url,
|
|
249
|
-
status: finalResponse
|
|
276
|
+
status: finalResponse?.status,
|
|
250
277
|
hasPayment: !!paymentMeta,
|
|
251
278
|
paymentProtocol: paymentMeta?.protocol,
|
|
252
|
-
paymentAmount: paymentMeta?.amount
|
|
279
|
+
paymentAmount: paymentMeta?.amount,
|
|
280
|
+
...fetchError && { error: fetchError.message }
|
|
253
281
|
});
|
|
254
282
|
if (paymentMeta) {
|
|
255
283
|
try {
|
|
@@ -268,24 +296,7 @@ var fetchCommand = (appContext) => new Command2("fetch").description("Fetch a ca
|
|
|
268
296
|
} catch {
|
|
269
297
|
}
|
|
270
298
|
}
|
|
271
|
-
const lastSearch = stateService.loadLastSearch();
|
|
272
|
-
const matchedCapability = lastSearch?.capabilities.find(
|
|
273
|
-
(c) => url.startsWith(c.url)
|
|
274
|
-
);
|
|
275
|
-
const capabilityId = options.capability ?? matchedCapability?.id ?? null;
|
|
276
|
-
const searchId = matchedCapability ? lastSearch?.searchId : void 0;
|
|
277
299
|
let runId = null;
|
|
278
|
-
const skipReasons = [];
|
|
279
|
-
if (!apiService.walletAddress) {
|
|
280
|
-
skipReasons.push(
|
|
281
|
-
"no wallet configured (run `zero wallet import` / set ZERO_PRIVATE_KEY)"
|
|
282
|
-
);
|
|
283
|
-
}
|
|
284
|
-
if (!capabilityId) {
|
|
285
|
-
skipReasons.push(
|
|
286
|
-
"no capability resolved \u2014 pass --capability <uid|slug> or run `zero search` first so the URL can be matched"
|
|
287
|
-
);
|
|
288
|
-
}
|
|
289
300
|
if (capabilityId && apiService.walletAddress) {
|
|
290
301
|
let requestSchema;
|
|
291
302
|
let responseSchema;
|
|
@@ -305,7 +316,7 @@ var fetchCommand = (appContext) => new Command2("fetch").description("Fetch a ca
|
|
|
305
316
|
const runResult = await apiService.createRun({
|
|
306
317
|
capabilityId,
|
|
307
318
|
searchId,
|
|
308
|
-
status: finalResponse
|
|
319
|
+
status: finalResponse?.status,
|
|
309
320
|
latencyMs,
|
|
310
321
|
requestSchema,
|
|
311
322
|
responseSchema,
|
|
@@ -325,14 +336,18 @@ var fetchCommand = (appContext) => new Command2("fetch").description("Fetch a ca
|
|
|
325
336
|
);
|
|
326
337
|
}
|
|
327
338
|
}
|
|
339
|
+
if (fetchError && !options.json) {
|
|
340
|
+
console.error(` Fetch failed: ${fetchError.message}`);
|
|
341
|
+
}
|
|
328
342
|
if (options.json) {
|
|
329
343
|
console.log(
|
|
330
344
|
JSON.stringify({
|
|
331
345
|
runId,
|
|
332
|
-
status: finalResponse
|
|
346
|
+
status: finalResponse?.status ?? null,
|
|
333
347
|
latencyMs,
|
|
334
348
|
payment: paymentMeta ?? null,
|
|
335
|
-
body,
|
|
349
|
+
body: finalResponse ? body : null,
|
|
350
|
+
...fetchError && { error: fetchError.message },
|
|
336
351
|
...skipReasons.length > 0 && {
|
|
337
352
|
runTrackingSkipped: skipReasons
|
|
338
353
|
}
|
|
@@ -365,6 +380,9 @@ var fetchCommand = (appContext) => new Command2("fetch").description("Fetch a ca
|
|
|
365
380
|
Note: this run was NOT recorded for review \u2014 ${skipReasons.join("; ")}.`
|
|
366
381
|
);
|
|
367
382
|
}
|
|
383
|
+
if (fetchError) {
|
|
384
|
+
process.exitCode = 1;
|
|
385
|
+
}
|
|
368
386
|
} catch (err) {
|
|
369
387
|
console.error(err instanceof Error ? err.message : "Fetch failed");
|
|
370
388
|
process.exitCode = 1;
|
|
@@ -994,7 +1012,13 @@ var formatSearchResults = (results) => {
|
|
|
994
1012
|
var searchCommand = (appContext) => new Command7("search").description("Search for capabilities").argument("<query>", "Search query").option("--json", "Output raw JSON to stdout").option("--offset <n>", "Pagination offset", Number).option("--limit <n>", "Results per page", Number).option("--free", "Only show free capabilities").option("--max-cost <amount>", "Maximum cost per call").option("--min-rating <stars>", "Minimum star rating (1-5)", Number).option("--protocol <protocol>", "Payment protocol (x402 or mpp)").option("--min-trust <n>", "Minimum trust score (0-100)", Number).option(
|
|
995
1013
|
"--status <status>",
|
|
996
1014
|
"Filter by availability (healthy, degraded, down)"
|
|
997
|
-
).option("--all", "Show all results (no trust or health filtering)").
|
|
1015
|
+
).option("--all", "Show all results (no trust or health filtering)").option(
|
|
1016
|
+
"--source <source>",
|
|
1017
|
+
"Only show results from this crawl source (e.g. mpp, bazaar)"
|
|
1018
|
+
).option(
|
|
1019
|
+
"--exclude-source <source>",
|
|
1020
|
+
"Exclude results from this crawl source"
|
|
1021
|
+
).action(
|
|
998
1022
|
async (query, options) => {
|
|
999
1023
|
try {
|
|
1000
1024
|
const { analyticsService, apiService, stateService } = appContext.services;
|
|
@@ -1023,7 +1047,9 @@ var searchCommand = (appContext) => new Command7("search").description("Search f
|
|
|
1023
1047
|
protocol: options.protocol,
|
|
1024
1048
|
minTrust: options.minTrust,
|
|
1025
1049
|
availabilityStatus: options.status,
|
|
1026
|
-
includeAll: options.all
|
|
1050
|
+
includeAll: options.all,
|
|
1051
|
+
source: options.source,
|
|
1052
|
+
excludeSource: options.excludeSource
|
|
1027
1053
|
});
|
|
1028
1054
|
analyticsService.capture("search_executed", {
|
|
1029
1055
|
query,
|
package/package.json
CHANGED
package/skills/zero/SKILL.md
CHANGED
|
@@ -33,7 +33,13 @@ Run these commands in order. Do not skip steps.
|
|
|
33
33
|
|
|
34
34
|
**Step 1 — Install:** `npm i -g @zeroxyz/cli`
|
|
35
35
|
|
|
36
|
-
**Step 2 —
|
|
36
|
+
**Step 2 — Provide a wallet.** Pick one path:
|
|
37
|
+
|
|
38
|
+
- **New wallet (persistent):** `zero init` — generates a wallet and writes it to `~/.zero/config.json`. Save the printed address.
|
|
39
|
+
- **Existing wallet (persistent):** `zero wallet set <privateKey>` — 0x-prefixed hex. Writes to `~/.zero/config.json`. Refuses to overwrite an existing wallet without `--force`.
|
|
40
|
+
- **Existing wallet (ephemeral, e.g. CI):** set `ZERO_PRIVATE_KEY=0x...` in the environment. The CLI reads it at runtime and writes nothing to disk.
|
|
41
|
+
|
|
42
|
+
**Prefer `zero init` or `zero wallet set` for local/interactive use** so the wallet persists across shells. Use `ZERO_PRIVATE_KEY` only when persisting to disk is undesirable — CI jobs, containers, one-off scripts, or secrets-manager-injected environments.
|
|
37
43
|
|
|
38
44
|
**Step 3 — Fund wallet:** `zero wallet fund` — opens browser to add USDC (Base). For manual transfer: `zero wallet fund --manual`.
|
|
39
45
|
|
|
@@ -41,7 +47,7 @@ Run these commands in order. Do not skip steps.
|
|
|
41
47
|
|
|
42
48
|
### Setup Rules
|
|
43
49
|
|
|
44
|
-
-
|
|
50
|
+
- Precedence: `ZERO_PRIVATE_KEY` (env) > `~/.zero/config.json`. If the env var is set, it wins even when a config file exists — useful for overriding on a single invocation (`ZERO_PRIVATE_KEY=0x... zero wallet balance`).
|
|
45
51
|
- Wallet must be funded with USDC on Base before calling paid capabilities.
|
|
46
52
|
|
|
47
53
|
## After Setup
|
|
@@ -105,7 +111,9 @@ zero fetch https://api.example.com/expensive --max-pay 0.50
|
|
|
105
111
|
|
|
106
112
|
### Rules
|
|
107
113
|
|
|
108
|
-
- Always
|
|
114
|
+
- **Always `zero search` fresh, every time.** Never reuse a capability URL, slug, schema, or price from an earlier turn, prior conversation, training data, or memory. Capabilities churn constantly — endpoints go offline, prices change, schemas evolve, and rankings shift as reviews accumulate. A capability that worked yesterday may be dead, repriced, or outranked today. Searching again costs nothing and is the only way to get current trust scores and availability.
|
|
115
|
+
- **Always `zero get` before `zero fetch`.** Even if you "know" the URL, re-fetch the full details to confirm the URL, method, required headers, body schema, and current price. Do not reconstruct a fetch call from memory.
|
|
116
|
+
- Never guess endpoint URLs or schemas.
|
|
109
117
|
- Use `--max-pay` before potentially expensive requests.
|
|
110
118
|
- Review capabilities after every paid call. The review signal feeds search ranking — skipping reviews means your next search is less informed.
|
|
111
119
|
- Before ending a multi-call task, run `zero runs --unreviewed` and review anything you missed.
|