@zeroxyz/cli 0.0.26 → 0.0.27
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 +114 -37
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/app.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command12 } from "commander";
|
|
5
5
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@zeroxyz/cli",
|
|
9
|
-
version: "0.0.
|
|
9
|
+
version: "0.0.27",
|
|
10
10
|
type: "module",
|
|
11
11
|
bin: {
|
|
12
12
|
zero: "dist/index.js",
|
|
@@ -1167,9 +1167,14 @@ var isTextContentType = (contentType) => {
|
|
|
1167
1167
|
if (ct === "application/x-www-form-urlencoded") return true;
|
|
1168
1168
|
return false;
|
|
1169
1169
|
};
|
|
1170
|
-
var
|
|
1171
|
-
if (
|
|
1172
|
-
const
|
|
1170
|
+
var looksLikeX402V1Body = (body) => {
|
|
1171
|
+
if (!body || typeof body !== "object") return false;
|
|
1172
|
+
const b = body;
|
|
1173
|
+
return b.x402Version === 1 && Array.isArray(b.accepts) && b.accepts.length > 0;
|
|
1174
|
+
};
|
|
1175
|
+
var detectPaymentRequirement = async (response) => {
|
|
1176
|
+
if (response.status !== 402) return null;
|
|
1177
|
+
const x402Header = response.headers.get("payment-required") ?? response.headers.get("x-payment-required");
|
|
1173
1178
|
if (x402Header) {
|
|
1174
1179
|
try {
|
|
1175
1180
|
const decoded = JSON.parse(
|
|
@@ -1180,10 +1185,20 @@ var detectPaymentRequirement = (headers, status) => {
|
|
|
1180
1185
|
return { protocol: "x402", raw: { encoded: x402Header } };
|
|
1181
1186
|
}
|
|
1182
1187
|
}
|
|
1183
|
-
const wwwAuth = headers.get("www-authenticate");
|
|
1188
|
+
const wwwAuth = response.headers.get("www-authenticate");
|
|
1184
1189
|
if (wwwAuth?.toLowerCase().includes("payment")) {
|
|
1185
1190
|
return { protocol: "mpp", raw: { "www-authenticate": wwwAuth } };
|
|
1186
1191
|
}
|
|
1192
|
+
try {
|
|
1193
|
+
const text = await response.clone().text();
|
|
1194
|
+
if (text) {
|
|
1195
|
+
const parsed = JSON.parse(text);
|
|
1196
|
+
if (looksLikeX402V1Body(parsed)) {
|
|
1197
|
+
return { protocol: "x402", raw: parsed };
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
} catch {
|
|
1201
|
+
}
|
|
1187
1202
|
return { protocol: "unknown", raw: {} };
|
|
1188
1203
|
};
|
|
1189
1204
|
var fetchCommand = (appContext) => new Command3("fetch").description("Fetch a capability URL with automatic payment handling").argument("<url>", "URL to fetch").option(
|
|
@@ -1258,10 +1273,7 @@ var fetchCommand = (appContext) => new Command3("fetch").description("Fetch a ca
|
|
|
1258
1273
|
try {
|
|
1259
1274
|
log(`Calling ${url}...`);
|
|
1260
1275
|
const response = await fetch(url, requestInit);
|
|
1261
|
-
const paymentReq = detectPaymentRequirement(
|
|
1262
|
-
response.headers,
|
|
1263
|
-
response.status
|
|
1264
|
-
);
|
|
1276
|
+
const paymentReq = await detectPaymentRequirement(response);
|
|
1265
1277
|
if (paymentReq) {
|
|
1266
1278
|
log(
|
|
1267
1279
|
`Payment required (${paymentReq.protocol}) \u2014 preparing payment...`
|
|
@@ -1809,7 +1821,7 @@ var installSkills = (home) => {
|
|
|
1809
1821
|
}
|
|
1810
1822
|
return installed;
|
|
1811
1823
|
};
|
|
1812
|
-
var
|
|
1824
|
+
var runInit = async (appContext, options = {}) => {
|
|
1813
1825
|
appContext.services.analyticsService.capture("init_started", {
|
|
1814
1826
|
force: options.force ?? false
|
|
1815
1827
|
});
|
|
@@ -1920,16 +1932,18 @@ To remove them, run: zero init cleanup`
|
|
|
1920
1932
|
conflicting_skills_found: conflictingSkills.length,
|
|
1921
1933
|
force: options.force ?? false
|
|
1922
1934
|
});
|
|
1935
|
+
return { walletAddress, walletCreated };
|
|
1923
1936
|
} catch (err) {
|
|
1924
1937
|
appContext.services.analyticsService.capture("init_failed", {
|
|
1925
1938
|
step: currentStep,
|
|
1926
|
-
error: truncateError(
|
|
1927
|
-
err instanceof Error ? err.message : String(err)
|
|
1928
|
-
),
|
|
1939
|
+
error: truncateError(err instanceof Error ? err.message : String(err)),
|
|
1929
1940
|
force: options.force ?? false
|
|
1930
1941
|
});
|
|
1931
1942
|
throw err;
|
|
1932
1943
|
}
|
|
1944
|
+
};
|
|
1945
|
+
var initCommand = (appContext) => new Command5("init").description("Initialize Zero CLI for usage").option("--force", "Overwrite existing configuration").action(async (options) => {
|
|
1946
|
+
await runInit(appContext, options);
|
|
1933
1947
|
}).addCommand(
|
|
1934
1948
|
new Command5("cleanup").description(
|
|
1935
1949
|
"Remove deprecated skills (zam, tempo) that conflict with Zero"
|
|
@@ -2455,10 +2469,71 @@ var walletCommand = (appContext) => {
|
|
|
2455
2469
|
return cmd;
|
|
2456
2470
|
};
|
|
2457
2471
|
|
|
2472
|
+
// src/commands/welcome-command.ts
|
|
2473
|
+
import { existsSync as existsSync4, readFileSync as readFileSync6 } from "fs";
|
|
2474
|
+
import { homedir as homedir4 } from "os";
|
|
2475
|
+
import { join as join4 } from "path";
|
|
2476
|
+
import { Command as Command11 } from "commander";
|
|
2477
|
+
import open2 from "open";
|
|
2478
|
+
import { getAddress } from "viem";
|
|
2479
|
+
import { privateKeyToAccount as privateKeyToAccount3 } from "viem/accounts";
|
|
2480
|
+
var readPrivateKey = () => {
|
|
2481
|
+
const configPath = join4(homedir4(), ".zero", "config.json");
|
|
2482
|
+
if (!existsSync4(configPath)) return null;
|
|
2483
|
+
try {
|
|
2484
|
+
const config = JSON.parse(readFileSync6(configPath, "utf8"));
|
|
2485
|
+
if (typeof config.privateKey === "string") {
|
|
2486
|
+
return config.privateKey;
|
|
2487
|
+
}
|
|
2488
|
+
} catch {
|
|
2489
|
+
return null;
|
|
2490
|
+
}
|
|
2491
|
+
return null;
|
|
2492
|
+
};
|
|
2493
|
+
var welcomeCommand = (appContext) => new Command11("welcome").description("Claim your $5 welcome bonus.").action(async () => {
|
|
2494
|
+
const { analyticsService } = appContext.services;
|
|
2495
|
+
analyticsService.capture("welcome_started", {});
|
|
2496
|
+
try {
|
|
2497
|
+
let privateKey = readPrivateKey();
|
|
2498
|
+
if (!privateKey) {
|
|
2499
|
+
await runInit(appContext);
|
|
2500
|
+
privateKey = readPrivateKey();
|
|
2501
|
+
if (!privateKey) {
|
|
2502
|
+
throw new Error("Wallet initialization failed");
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
const account = privateKeyToAccount3(privateKey);
|
|
2506
|
+
const walletAddress = getAddress(account.address);
|
|
2507
|
+
const walletSignature = await account.signMessage({
|
|
2508
|
+
message: walletAddress
|
|
2509
|
+
});
|
|
2510
|
+
const url = new URL("/welcome", appContext.env.ZERO_WEB_URL);
|
|
2511
|
+
url.searchParams.set("wallet", walletAddress);
|
|
2512
|
+
url.searchParams.set("walletSignature", walletSignature);
|
|
2513
|
+
console.log(
|
|
2514
|
+
`Opening ${url.toString()}
|
|
2515
|
+
|
|
2516
|
+
If your browser didn't open, paste the URL above.`
|
|
2517
|
+
);
|
|
2518
|
+
await open2(url.toString());
|
|
2519
|
+
analyticsService.capture("welcome_link_opened", {
|
|
2520
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
2521
|
+
wallet_address: walletAddress
|
|
2522
|
+
});
|
|
2523
|
+
} catch (err) {
|
|
2524
|
+
analyticsService.capture("welcome_failed", {
|
|
2525
|
+
error: truncateError(
|
|
2526
|
+
err instanceof Error ? err.message : String(err)
|
|
2527
|
+
)
|
|
2528
|
+
});
|
|
2529
|
+
throw err;
|
|
2530
|
+
}
|
|
2531
|
+
});
|
|
2532
|
+
|
|
2458
2533
|
// src/app.ts
|
|
2459
2534
|
var createApp = (appContext) => {
|
|
2460
2535
|
const { analyticsService } = appContext.services;
|
|
2461
|
-
const program = new
|
|
2536
|
+
const program = new Command12().name("zero").description("Zero CLI \u2014 Search engine and payment platform for AI agents").version(package_default.version, "-v, --version").exitOverride().hook("preAction", async (_thisCommand, actionCommand) => {
|
|
2462
2537
|
const agentFlag = actionCommand.opts().agent;
|
|
2463
2538
|
if (typeof agentFlag === "string" && agentFlag.trim().length > 0) {
|
|
2464
2539
|
analyticsService.setAgentHost(agentFlag.trim());
|
|
@@ -2481,6 +2556,7 @@ var createApp = (appContext) => {
|
|
|
2481
2556
|
program.addCommand(walletCommand(appContext));
|
|
2482
2557
|
program.addCommand(configCommand(appContext));
|
|
2483
2558
|
program.addCommand(termsCommand(appContext));
|
|
2559
|
+
program.addCommand(welcomeCommand(appContext));
|
|
2484
2560
|
return program;
|
|
2485
2561
|
};
|
|
2486
2562
|
|
|
@@ -2488,6 +2564,7 @@ var createApp = (appContext) => {
|
|
|
2488
2564
|
import z4 from "zod";
|
|
2489
2565
|
var envSchema = z4.object({
|
|
2490
2566
|
ZERO_API_URL: z4.string().default("https://api.zero.xyz"),
|
|
2567
|
+
ZERO_WEB_URL: z4.string().default("https://zero.xyz"),
|
|
2491
2568
|
ZERO_PRIVATE_KEY: z4.string().optional(),
|
|
2492
2569
|
ZERO_ENV: z4.enum(["development", "production"]).default("production")
|
|
2493
2570
|
});
|
|
@@ -2503,14 +2580,14 @@ var getEnv = () => {
|
|
|
2503
2580
|
|
|
2504
2581
|
// src/app/app-services.ts
|
|
2505
2582
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2506
|
-
import { existsSync as
|
|
2507
|
-
import { homedir as
|
|
2508
|
-
import { join as
|
|
2509
|
-
import { privateKeyToAccount as
|
|
2583
|
+
import { existsSync as existsSync7, readFileSync as readFileSync9 } from "fs";
|
|
2584
|
+
import { homedir as homedir5 } from "os";
|
|
2585
|
+
import { join as join6 } from "path";
|
|
2586
|
+
import { privateKeyToAccount as privateKeyToAccount4 } from "viem/accounts";
|
|
2510
2587
|
|
|
2511
2588
|
// src/services/analytics-service.ts
|
|
2512
2589
|
import { randomUUID } from "crypto";
|
|
2513
|
-
import { existsSync as
|
|
2590
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
|
|
2514
2591
|
import { dirname as dirname2 } from "path";
|
|
2515
2592
|
import { PostHog } from "posthog-node";
|
|
2516
2593
|
var POSTHOG_API_KEY = "phc_B2vLyNxAf2mnqvdPQajf4d4b2iXc35dep2ZrvebMJLuX";
|
|
@@ -2532,8 +2609,8 @@ var AnalyticsService = class {
|
|
|
2532
2609
|
let telemetryEnabled = true;
|
|
2533
2610
|
let persistedAnonId;
|
|
2534
2611
|
try {
|
|
2535
|
-
if (
|
|
2536
|
-
const config = JSON.parse(
|
|
2612
|
+
if (existsSync5(opts.configPath)) {
|
|
2613
|
+
const config = JSON.parse(readFileSync7(opts.configPath, "utf8"));
|
|
2537
2614
|
if (config.telemetry === false) {
|
|
2538
2615
|
telemetryEnabled = false;
|
|
2539
2616
|
}
|
|
@@ -2558,7 +2635,7 @@ var AnalyticsService = class {
|
|
|
2558
2635
|
try {
|
|
2559
2636
|
const dir = dirname2(opts.configPath);
|
|
2560
2637
|
mkdirSync4(dir, { recursive: true });
|
|
2561
|
-
const existing =
|
|
2638
|
+
const existing = existsSync5(opts.configPath) ? JSON.parse(readFileSync7(opts.configPath, "utf8")) : {};
|
|
2562
2639
|
writeFileSync4(
|
|
2563
2640
|
opts.configPath,
|
|
2564
2641
|
JSON.stringify({ ...existing, anonId: newAnonId }, null, 2)
|
|
@@ -2594,7 +2671,7 @@ var AnalyticsService = class {
|
|
|
2594
2671
|
if (anonId === walletAddress) return;
|
|
2595
2672
|
let aliasedTo;
|
|
2596
2673
|
try {
|
|
2597
|
-
const config = JSON.parse(
|
|
2674
|
+
const config = JSON.parse(readFileSync7(configPath, "utf8"));
|
|
2598
2675
|
if (typeof config.aliasedTo === "string") {
|
|
2599
2676
|
aliasedTo = config.aliasedTo;
|
|
2600
2677
|
}
|
|
@@ -2603,7 +2680,7 @@ var AnalyticsService = class {
|
|
|
2603
2680
|
if (aliasedTo === walletAddress) return;
|
|
2604
2681
|
this.posthog.alias({ distinctId: walletAddress, alias: anonId });
|
|
2605
2682
|
try {
|
|
2606
|
-
const config =
|
|
2683
|
+
const config = existsSync5(configPath) ? JSON.parse(readFileSync7(configPath, "utf8")) : {};
|
|
2607
2684
|
writeFileSync4(
|
|
2608
2685
|
configPath,
|
|
2609
2686
|
JSON.stringify({ ...config, aliasedTo: walletAddress }, null, 2)
|
|
@@ -2646,12 +2723,12 @@ var AnalyticsService = class {
|
|
|
2646
2723
|
};
|
|
2647
2724
|
|
|
2648
2725
|
// src/services/state-service.ts
|
|
2649
|
-
import { existsSync as
|
|
2650
|
-
import { join as
|
|
2726
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
|
|
2727
|
+
import { join as join5 } from "path";
|
|
2651
2728
|
var StateService = class {
|
|
2652
2729
|
constructor(zeroDir) {
|
|
2653
2730
|
this.zeroDir = zeroDir;
|
|
2654
|
-
this.lastSearchPath =
|
|
2731
|
+
this.lastSearchPath = join5(zeroDir, "last_search.json");
|
|
2655
2732
|
}
|
|
2656
2733
|
lastSearchPath;
|
|
2657
2734
|
saveLastSearch = (data) => {
|
|
@@ -2660,8 +2737,8 @@ var StateService = class {
|
|
|
2660
2737
|
};
|
|
2661
2738
|
loadLastSearch = () => {
|
|
2662
2739
|
try {
|
|
2663
|
-
if (!
|
|
2664
|
-
const raw =
|
|
2740
|
+
if (!existsSync6(this.lastSearchPath)) return null;
|
|
2741
|
+
const raw = readFileSync8(this.lastSearchPath, "utf8");
|
|
2665
2742
|
return JSON.parse(raw);
|
|
2666
2743
|
} catch {
|
|
2667
2744
|
return null;
|
|
@@ -2709,12 +2786,12 @@ var detectAgentHost = (env = process.env) => {
|
|
|
2709
2786
|
var CLI_VERSION = package_default.version;
|
|
2710
2787
|
var getServices = (env) => {
|
|
2711
2788
|
let privateKey = env.ZERO_PRIVATE_KEY ? env.ZERO_PRIVATE_KEY : null;
|
|
2712
|
-
const zeroDir =
|
|
2713
|
-
const configPath =
|
|
2789
|
+
const zeroDir = join6(homedir5(), ".zero");
|
|
2790
|
+
const configPath = join6(zeroDir, "config.json");
|
|
2714
2791
|
if (!privateKey) {
|
|
2715
2792
|
try {
|
|
2716
|
-
if (
|
|
2717
|
-
const config = JSON.parse(
|
|
2793
|
+
if (existsSync7(configPath)) {
|
|
2794
|
+
const config = JSON.parse(readFileSync9(configPath, "utf8"));
|
|
2718
2795
|
if (typeof config.privateKey === "string") {
|
|
2719
2796
|
privateKey = config.privateKey;
|
|
2720
2797
|
}
|
|
@@ -2722,11 +2799,11 @@ var getServices = (env) => {
|
|
|
2722
2799
|
} catch {
|
|
2723
2800
|
}
|
|
2724
2801
|
}
|
|
2725
|
-
const account = privateKey ?
|
|
2802
|
+
const account = privateKey ? privateKeyToAccount4(privateKey) : null;
|
|
2726
2803
|
let lowBalanceWarning = 1;
|
|
2727
2804
|
try {
|
|
2728
|
-
if (
|
|
2729
|
-
const config = JSON.parse(
|
|
2805
|
+
if (existsSync7(configPath)) {
|
|
2806
|
+
const config = JSON.parse(readFileSync9(configPath, "utf8"));
|
|
2730
2807
|
if (typeof config.lowBalanceWarning === "number") {
|
|
2731
2808
|
lowBalanceWarning = config.lowBalanceWarning;
|
|
2732
2809
|
}
|