@zeroxyz/cli 0.0.41 → 0.0.42
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 +371 -103
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { homedir as
|
|
5
|
-
import { join as
|
|
4
|
+
import { homedir as homedir9 } from "os";
|
|
5
|
+
import { join as join11 } from "path";
|
|
6
6
|
|
|
7
7
|
// package.json
|
|
8
8
|
var package_default = {
|
|
9
9
|
name: "@zeroxyz/cli",
|
|
10
|
-
version: "0.0.
|
|
10
|
+
version: "0.0.42",
|
|
11
11
|
type: "module",
|
|
12
12
|
bin: {
|
|
13
13
|
zero: "dist/index.js",
|
|
@@ -61,7 +61,7 @@ var package_default = {
|
|
|
61
61
|
};
|
|
62
62
|
|
|
63
63
|
// src/app.ts
|
|
64
|
-
import { Command as
|
|
64
|
+
import { Command as Command14 } from "commander";
|
|
65
65
|
|
|
66
66
|
// src/commands/auth-command.ts
|
|
67
67
|
import { homedir } from "os";
|
|
@@ -204,8 +204,7 @@ var searchResultSchema = z.object({
|
|
|
204
204
|
cost: z.object({ amount: z.string(), asset: z.string() }),
|
|
205
205
|
reviewCount: z.number().optional(),
|
|
206
206
|
rating: ratingSchema,
|
|
207
|
-
availabilityStatus: z.enum(["healthy", "
|
|
208
|
-
displayStatus: z.enum(["healthy", "stable", "degraded", "unhealthy", "unknown"]).optional(),
|
|
207
|
+
availabilityStatus: z.enum(["healthy", "unknown", "down"]).nullable().optional(),
|
|
209
208
|
// Pass-through: API stamps this on Zero-published / withzero.{ai,xyz}
|
|
210
209
|
// services so `zero search --json` consumers can render their own
|
|
211
210
|
// provenance UI. CLI doesn't render a badge today.
|
|
@@ -258,8 +257,7 @@ var capabilityResponseSchema = z.object({
|
|
|
258
257
|
priority: z.number()
|
|
259
258
|
})
|
|
260
259
|
).nullable(),
|
|
261
|
-
availabilityStatus: z.enum(["healthy", "
|
|
262
|
-
displayStatus: z.enum(["healthy", "stable", "degraded", "unhealthy", "unknown"]).optional(),
|
|
260
|
+
availabilityStatus: z.enum(["healthy", "unknown", "down"]).nullable().optional(),
|
|
263
261
|
activationCount: z.number().optional(),
|
|
264
262
|
lastUsedAt: z.string().nullable().optional(),
|
|
265
263
|
lastSuccessfullyRanAt: z.string().nullable().optional(),
|
|
@@ -586,16 +584,36 @@ var ApiService = class _ApiService {
|
|
|
586
584
|
});
|
|
587
585
|
return createBugReportResponseSchema.parse(json);
|
|
588
586
|
};
|
|
587
|
+
// Mints a one-time onramp URL for the caller's wallet. Two paths, picked by
|
|
588
|
+
// which identity is available:
|
|
589
|
+
// • BYO key present (this.account) → /v1/wallet/fund-url, proving ownership
|
|
590
|
+
// with an EIP-191 signature. Honors the `provider` choice.
|
|
591
|
+
// • No key but a session (managed/runner) → /v1/users/me/fund-url, which
|
|
592
|
+
// resolves the user's managed wallet server-side from the Bearer. Coinbase
|
|
593
|
+
// only (the managed onramp doesn't take a provider), so `provider` is
|
|
594
|
+
// ignored on this path.
|
|
595
|
+
// Returns null on any failure so callers can fall back to manual transfer.
|
|
589
596
|
getFundingUrl = async (amount, provider = "coinbase") => {
|
|
590
597
|
try {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
598
|
+
if (this.account) {
|
|
599
|
+
const params = new URLSearchParams({ provider });
|
|
600
|
+
if (amount) params.set("amount", amount);
|
|
601
|
+
const json = await this.request(
|
|
602
|
+
"GET",
|
|
603
|
+
`/v1/wallet/fund-url?${params.toString()}`,
|
|
604
|
+
void 0,
|
|
605
|
+
{ auth: "wallet-attributed" }
|
|
606
|
+
);
|
|
607
|
+
return z.object({ url: z.string() }).parse(json).url;
|
|
608
|
+
}
|
|
609
|
+
if (this.credentials.kind === "session") {
|
|
610
|
+
const params = new URLSearchParams();
|
|
611
|
+
if (amount) params.set("amount", amount);
|
|
612
|
+
const qs = params.toString() ? `?${params.toString()}` : "";
|
|
613
|
+
const json = await this.request("GET", `/v1/users/me/fund-url${qs}`);
|
|
614
|
+
return z.object({ url: z.string(), walletAddress: z.string() }).parse(json).url;
|
|
615
|
+
}
|
|
616
|
+
return null;
|
|
599
617
|
} catch {
|
|
600
618
|
return null;
|
|
601
619
|
}
|
|
@@ -2403,7 +2421,7 @@ var formatCapability = (capability) => {
|
|
|
2403
2421
|
const lines = [];
|
|
2404
2422
|
lines.push(capability.name);
|
|
2405
2423
|
lines.push(` Rating: ${formatRating(capability.rating)}`);
|
|
2406
|
-
lines.push(` Status: ${capability.
|
|
2424
|
+
lines.push(` Status: ${capability.availabilityStatus ?? "unknown"}`);
|
|
2407
2425
|
lines.push(...formatCost(capability));
|
|
2408
2426
|
lines.push(` URL: ${capability.url}`);
|
|
2409
2427
|
lines.push(` Method: ${capability.method}`);
|
|
@@ -2645,6 +2663,8 @@ var AGENT_TOOLS = [
|
|
|
2645
2663
|
},
|
|
2646
2664
|
{ name: "Cursor", detectDir: ".cursor", skillsDir: ".cursor/skills" }
|
|
2647
2665
|
];
|
|
2666
|
+
var HOOK_FILES = ["auto-approve-zero.sh", "zero-context.sh"];
|
|
2667
|
+
var ZERO_SANDBOX_DOMAIN = "*.zero.xyz";
|
|
2648
2668
|
var findResourceDir = (startDir, resourceName) => {
|
|
2649
2669
|
let current = startDir;
|
|
2650
2670
|
while (true) {
|
|
@@ -2714,10 +2734,9 @@ var installHook = (home, verbose = false) => {
|
|
|
2714
2734
|
const zeroHooksDir = join3(home, ".zero", "hooks");
|
|
2715
2735
|
mkdirSync3(zeroHooksDir, { recursive: true });
|
|
2716
2736
|
if (verbose) stepInfo(`staged hook dir at ${zeroHooksDir}`);
|
|
2717
|
-
const hookFiles = ["auto-approve-zero.sh", "zero-context.sh"];
|
|
2718
2737
|
const hookDests = {};
|
|
2719
2738
|
const hooksSourceDir = findResourceDir(getCliModuleDir(), "hooks");
|
|
2720
|
-
for (const hookFile of
|
|
2739
|
+
for (const hookFile of HOOK_FILES) {
|
|
2721
2740
|
const hookSource = join3(hooksSourceDir, hookFile);
|
|
2722
2741
|
const hookDest = join3(zeroHooksDir, hookFile);
|
|
2723
2742
|
copyFile(hookSource, hookDest);
|
|
@@ -2820,12 +2839,15 @@ var installHook = (home, verbose = false) => {
|
|
|
2820
2839
|
network.allowedDomains = [];
|
|
2821
2840
|
}
|
|
2822
2841
|
const allowedDomains = network.allowedDomains;
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2842
|
+
if (!allowedDomains.includes(ZERO_SANDBOX_DOMAIN)) {
|
|
2843
|
+
allowedDomains.push(ZERO_SANDBOX_DOMAIN);
|
|
2844
|
+
if (verbose) {
|
|
2845
|
+
stepInfo(`sandbox.network.allowedDomains += ${ZERO_SANDBOX_DOMAIN}`);
|
|
2846
|
+
}
|
|
2827
2847
|
} else if (verbose) {
|
|
2828
|
-
stepInfo(
|
|
2848
|
+
stepInfo(
|
|
2849
|
+
`${ZERO_SANDBOX_DOMAIN} already in sandbox allowlist \u2014 not modified`
|
|
2850
|
+
);
|
|
2829
2851
|
}
|
|
2830
2852
|
writeFileSync3(settingsPath, `${JSON.stringify(settings, null, 2)}
|
|
2831
2853
|
`);
|
|
@@ -2861,6 +2883,14 @@ var removeConflictingSkills = (home) => {
|
|
|
2861
2883
|
}
|
|
2862
2884
|
return removed;
|
|
2863
2885
|
};
|
|
2886
|
+
var getBundledSkillNames = () => {
|
|
2887
|
+
try {
|
|
2888
|
+
const skillsSourceDir = findResourceDir(getCliModuleDir(), "skills");
|
|
2889
|
+
return readdirSync(skillsSourceDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
2890
|
+
} catch {
|
|
2891
|
+
return ["zero"];
|
|
2892
|
+
}
|
|
2893
|
+
};
|
|
2864
2894
|
var installSkills = (home, verbose = false) => {
|
|
2865
2895
|
const skillsSourceDir = findResourceDir(getCliModuleDir(), "skills");
|
|
2866
2896
|
const skillDirs = readdirSync(skillsSourceDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
@@ -3404,8 +3434,16 @@ var formatRatingBadge = (rating) => {
|
|
|
3404
3434
|
return `${successPct} success \xB7 ${reviews} reviews`;
|
|
3405
3435
|
};
|
|
3406
3436
|
var formatStatusBadge = (status) => {
|
|
3407
|
-
|
|
3408
|
-
|
|
3437
|
+
switch (status) {
|
|
3438
|
+
case "healthy":
|
|
3439
|
+
return ` \u2014 ${color.green("\u2713 healthy")}`;
|
|
3440
|
+
case "down":
|
|
3441
|
+
return ` \u2014 ${color.red("\u2717 down")}`;
|
|
3442
|
+
case "unknown":
|
|
3443
|
+
return ` \u2014 ${color.yellow("? unknown")}`;
|
|
3444
|
+
default:
|
|
3445
|
+
return "";
|
|
3446
|
+
}
|
|
3409
3447
|
};
|
|
3410
3448
|
var formatSearchResults = (results) => {
|
|
3411
3449
|
if (results.length === 0) return "No capabilities found.";
|
|
@@ -3414,7 +3452,7 @@ var formatSearchResults = (results) => {
|
|
|
3414
3452
|
const displayName = r.brandName ? `${r.brandName} ${baseName}` : baseName;
|
|
3415
3453
|
const displayDescription = r.whatItDoes ?? r.description;
|
|
3416
3454
|
const ratingBadge = formatRatingBadge(r.rating);
|
|
3417
|
-
const statusBadge = formatStatusBadge(r.
|
|
3455
|
+
const statusBadge = formatStatusBadge(r.availabilityStatus);
|
|
3418
3456
|
const costLabel = r.cost.amount === "0" ? "Free" : r.cost.amount === "unknown" ? "variable pricing" : `$${r.cost.amount}/call`;
|
|
3419
3457
|
return ` ${r.position}. ${displayName} \u2014 ${costLabel} \u2014 ${ratingBadge}${statusBadge}
|
|
3420
3458
|
"${displayDescription}"`;
|
|
@@ -3425,7 +3463,7 @@ var searchCommand = (appContext) => new Command9("search").description("Search f
|
|
|
3425
3463
|
`Maximum cost per call in USD (default: ${DEFAULT_MAX_COST_USD})`
|
|
3426
3464
|
).option("--protocol <protocol>", "Payment protocol (x402 or mpp)").option(
|
|
3427
3465
|
"--status <status>",
|
|
3428
|
-
"Filter by availability (healthy, unknown, down).
|
|
3466
|
+
"Filter by availability (healthy, unknown, down). Default (unset) returns healthy + unknown with healthy first; pass 'healthy' for only-healthy, or --all to include everything."
|
|
3429
3467
|
).option("--all", "Disable default quality filtering").option(
|
|
3430
3468
|
"--source <source>",
|
|
3431
3469
|
"Only show results from this crawl source (e.g. mpp, bazaar)"
|
|
@@ -3460,12 +3498,8 @@ var searchCommand = (appContext) => new Command9("search").description("Search f
|
|
|
3460
3498
|
process.exitCode = 1;
|
|
3461
3499
|
return;
|
|
3462
3500
|
}
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
if (effectiveStatus === void 0 && !options.all) {
|
|
3466
|
-
effectiveStatus = "healthy";
|
|
3467
|
-
appliedDefaultStatus = true;
|
|
3468
|
-
}
|
|
3501
|
+
const effectiveStatus = options.status;
|
|
3502
|
+
const appliedDefaultStatus = effectiveStatus === void 0 && !options.all;
|
|
3469
3503
|
const result = await apiService.search({
|
|
3470
3504
|
query,
|
|
3471
3505
|
offset: options.offset,
|
|
@@ -3562,23 +3596,256 @@ Read the full terms at: ${TERMS_URL}
|
|
|
3562
3596
|
}
|
|
3563
3597
|
});
|
|
3564
3598
|
|
|
3565
|
-
// src/commands/
|
|
3566
|
-
import {
|
|
3599
|
+
// src/commands/uninstall-command.ts
|
|
3600
|
+
import {
|
|
3601
|
+
existsSync as existsSync3,
|
|
3602
|
+
readdirSync as readdirSync2,
|
|
3603
|
+
readFileSync as readFileSync7,
|
|
3604
|
+
rmSync as rmSync2,
|
|
3605
|
+
writeFileSync as writeFileSync4
|
|
3606
|
+
} from "fs";
|
|
3567
3607
|
import { homedir as homedir4 } from "os";
|
|
3568
|
-
import { join as
|
|
3569
|
-
import { confirm, isCancel } from "@clack/prompts";
|
|
3608
|
+
import { join as join4 } from "path";
|
|
3570
3609
|
import { Command as Command11 } from "commander";
|
|
3610
|
+
var removeSkills = (home, verbose = false) => {
|
|
3611
|
+
const skillNames = getBundledSkillNames();
|
|
3612
|
+
const removed = [];
|
|
3613
|
+
for (const tool of AGENT_TOOLS) {
|
|
3614
|
+
const toolSkillsPath = join4(home, tool.skillsDir);
|
|
3615
|
+
if (!existsSync3(toolSkillsPath)) {
|
|
3616
|
+
if (verbose) {
|
|
3617
|
+
stepInfo(
|
|
3618
|
+
`${tool.name}: ~/${tool.skillsDir} not found \u2014 nothing to remove`
|
|
3619
|
+
);
|
|
3620
|
+
}
|
|
3621
|
+
continue;
|
|
3622
|
+
}
|
|
3623
|
+
for (const skillName of skillNames) {
|
|
3624
|
+
const skillPath = join4(toolSkillsPath, skillName);
|
|
3625
|
+
if (!existsSync3(skillPath)) continue;
|
|
3626
|
+
rmSync2(skillPath, { recursive: true, force: true });
|
|
3627
|
+
removed.push(`${tool.name}: ${skillPath}`);
|
|
3628
|
+
if (verbose) stepInfo(`${tool.name}: removed skill '${skillName}'`);
|
|
3629
|
+
}
|
|
3630
|
+
}
|
|
3631
|
+
return removed;
|
|
3632
|
+
};
|
|
3633
|
+
var removeHooks = (home, verbose = false) => {
|
|
3634
|
+
let settingsChanged = false;
|
|
3635
|
+
const settingsPath = join4(home, ".claude", "settings.json");
|
|
3636
|
+
if (!existsSync3(settingsPath)) {
|
|
3637
|
+
if (verbose) stepInfo(`${settingsPath} not found \u2014 no settings to clean`);
|
|
3638
|
+
} else {
|
|
3639
|
+
let settings = null;
|
|
3640
|
+
try {
|
|
3641
|
+
settings = JSON.parse(readFileSync7(settingsPath, "utf-8"));
|
|
3642
|
+
} catch {
|
|
3643
|
+
if (verbose) {
|
|
3644
|
+
stepInfo(`${settingsPath} was unparseable JSON \u2014 leaving it untouched`);
|
|
3645
|
+
}
|
|
3646
|
+
}
|
|
3647
|
+
if (settings) {
|
|
3648
|
+
settingsChanged = stripZeroFromSettings(settings, verbose);
|
|
3649
|
+
if (settingsChanged) {
|
|
3650
|
+
writeFileSync4(settingsPath, `${JSON.stringify(settings, null, 2)}
|
|
3651
|
+
`);
|
|
3652
|
+
if (verbose) stepInfo(`rewrote ${settingsPath} without Zero entries`);
|
|
3653
|
+
} else if (verbose) {
|
|
3654
|
+
stepInfo(`no Zero entries found in ${settingsPath}`);
|
|
3655
|
+
}
|
|
3656
|
+
}
|
|
3657
|
+
}
|
|
3658
|
+
let scriptsRemoved = 0;
|
|
3659
|
+
const zeroHooksDir = join4(home, ".zero", "hooks");
|
|
3660
|
+
if (existsSync3(zeroHooksDir)) {
|
|
3661
|
+
for (const hookFile of HOOK_FILES) {
|
|
3662
|
+
const hookPath = join4(zeroHooksDir, hookFile);
|
|
3663
|
+
if (!existsSync3(hookPath)) continue;
|
|
3664
|
+
rmSync2(hookPath, { force: true });
|
|
3665
|
+
scriptsRemoved++;
|
|
3666
|
+
if (verbose) stepInfo(`removed ${hookPath}`);
|
|
3667
|
+
}
|
|
3668
|
+
if (readdirSync2(zeroHooksDir).length === 0) {
|
|
3669
|
+
rmSync2(zeroHooksDir, { recursive: true, force: true });
|
|
3670
|
+
if (verbose) stepInfo(`removed empty ${zeroHooksDir}`);
|
|
3671
|
+
}
|
|
3672
|
+
} else if (verbose) {
|
|
3673
|
+
stepInfo(`${zeroHooksDir} not found \u2014 no hook scripts to remove`);
|
|
3674
|
+
}
|
|
3675
|
+
return { settingsChanged, scriptsRemoved };
|
|
3676
|
+
};
|
|
3677
|
+
var stripZeroFromSettings = (settings, verbose) => {
|
|
3678
|
+
let changed = false;
|
|
3679
|
+
const hooks = settings.hooks && typeof settings.hooks === "object" ? settings.hooks : null;
|
|
3680
|
+
if (hooks) {
|
|
3681
|
+
changed = removeHookEntries(hooks, "PreToolUse", "auto-approve-zero", verbose) || changed;
|
|
3682
|
+
changed = removeHookEntries(hooks, "UserPromptSubmit", "zero-context", verbose) || changed;
|
|
3683
|
+
for (const key of ["PreToolUse", "UserPromptSubmit"]) {
|
|
3684
|
+
const arr = hooks[key];
|
|
3685
|
+
if (Array.isArray(arr) && arr.length === 0) delete hooks[key];
|
|
3686
|
+
}
|
|
3687
|
+
if (Object.keys(hooks).length === 0) delete settings.hooks;
|
|
3688
|
+
}
|
|
3689
|
+
const sandbox = settings.sandbox && typeof settings.sandbox === "object" ? settings.sandbox : null;
|
|
3690
|
+
const network = sandbox?.network && typeof sandbox.network === "object" ? sandbox.network : null;
|
|
3691
|
+
if (network && Array.isArray(network.allowedDomains)) {
|
|
3692
|
+
const domains = network.allowedDomains;
|
|
3693
|
+
const next = domains.filter((d) => d !== ZERO_SANDBOX_DOMAIN);
|
|
3694
|
+
if (next.length !== domains.length) {
|
|
3695
|
+
changed = true;
|
|
3696
|
+
if (verbose) {
|
|
3697
|
+
stepInfo(`sandbox.network.allowedDomains -= ${ZERO_SANDBOX_DOMAIN}`);
|
|
3698
|
+
}
|
|
3699
|
+
if (next.length === 0) {
|
|
3700
|
+
delete network.allowedDomains;
|
|
3701
|
+
if (sandbox && Object.keys(network).length === 0)
|
|
3702
|
+
delete sandbox.network;
|
|
3703
|
+
if (sandbox && Object.keys(sandbox).length === 0)
|
|
3704
|
+
delete settings.sandbox;
|
|
3705
|
+
} else {
|
|
3706
|
+
network.allowedDomains = next;
|
|
3707
|
+
}
|
|
3708
|
+
}
|
|
3709
|
+
}
|
|
3710
|
+
return changed;
|
|
3711
|
+
};
|
|
3712
|
+
var removeHookEntries = (hooks, hookType, commandSubstring, verbose) => {
|
|
3713
|
+
const entries = hooks[hookType];
|
|
3714
|
+
if (!Array.isArray(entries)) return false;
|
|
3715
|
+
const next = entries.filter((entry) => {
|
|
3716
|
+
const entryHooks = entry?.hooks;
|
|
3717
|
+
if (!Array.isArray(entryHooks)) return true;
|
|
3718
|
+
return !entryHooks.some(
|
|
3719
|
+
(h) => typeof h.command === "string" && h.command.includes(commandSubstring)
|
|
3720
|
+
);
|
|
3721
|
+
});
|
|
3722
|
+
if (next.length === entries.length) return false;
|
|
3723
|
+
hooks[hookType] = next;
|
|
3724
|
+
if (verbose) stepInfo(`removed ${hookType} entry (${commandSubstring})`);
|
|
3725
|
+
return true;
|
|
3726
|
+
};
|
|
3727
|
+
var removeWallet = (home, verbose = false) => {
|
|
3728
|
+
const zeroDir = join4(home, ".zero");
|
|
3729
|
+
const configPath = join4(zeroDir, "config.json");
|
|
3730
|
+
let removed = false;
|
|
3731
|
+
if (existsSync3(configPath)) {
|
|
3732
|
+
rmSync2(configPath, { force: true });
|
|
3733
|
+
removed = true;
|
|
3734
|
+
if (verbose) stepInfo(`removed ${configPath}`);
|
|
3735
|
+
}
|
|
3736
|
+
if (existsSync3(zeroDir) && readdirSync2(zeroDir).length === 0) {
|
|
3737
|
+
rmSync2(zeroDir, { recursive: true, force: true });
|
|
3738
|
+
if (verbose) stepInfo(`removed empty ${zeroDir}`);
|
|
3739
|
+
}
|
|
3740
|
+
return removed;
|
|
3741
|
+
};
|
|
3742
|
+
var runUninstall = async (appContext, options = {}) => {
|
|
3743
|
+
const verbose = options.verbose ?? false;
|
|
3744
|
+
const purge = options.purge ?? false;
|
|
3745
|
+
appContext.services.analyticsService.capture("uninstall_started", { purge });
|
|
3746
|
+
let currentStep = "skills";
|
|
3747
|
+
try {
|
|
3748
|
+
console.log("");
|
|
3749
|
+
console.log(` ${color.boldCyan("Uninstalling Zero")}`);
|
|
3750
|
+
console.log("");
|
|
3751
|
+
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"));
|
|
3752
|
+
console.log("");
|
|
3753
|
+
const home = homedir4();
|
|
3754
|
+
currentStep = "skills";
|
|
3755
|
+
const skillsRemoved = removeSkills(home, verbose);
|
|
3756
|
+
if (skillsRemoved.length > 0) {
|
|
3757
|
+
stepSuccess("Skills removed", `${skillsRemoved.length} removed`);
|
|
3758
|
+
} else {
|
|
3759
|
+
stepSkip("No Zero skills found");
|
|
3760
|
+
}
|
|
3761
|
+
currentStep = "hooks";
|
|
3762
|
+
const { settingsChanged, scriptsRemoved } = removeHooks(home, verbose);
|
|
3763
|
+
if (settingsChanged || scriptsRemoved > 0) {
|
|
3764
|
+
stepSuccess("Hooks removed");
|
|
3765
|
+
} else {
|
|
3766
|
+
stepSkip("No Zero hooks found");
|
|
3767
|
+
}
|
|
3768
|
+
currentStep = "wallet";
|
|
3769
|
+
let walletRemoved = false;
|
|
3770
|
+
if (purge) {
|
|
3771
|
+
walletRemoved = removeWallet(home, verbose);
|
|
3772
|
+
if (walletRemoved) {
|
|
3773
|
+
stepWarn("Wallet config deleted", "~/.zero/config.json");
|
|
3774
|
+
} else {
|
|
3775
|
+
stepSkip("No wallet config to delete");
|
|
3776
|
+
}
|
|
3777
|
+
} else {
|
|
3778
|
+
stepSkip(
|
|
3779
|
+
"Wallet preserved",
|
|
3780
|
+
"run `zero uninstall --purge` to also delete ~/.zero"
|
|
3781
|
+
);
|
|
3782
|
+
}
|
|
3783
|
+
currentStep = "complete";
|
|
3784
|
+
appContext.services.analyticsService.capture("uninstall_completed", {
|
|
3785
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
3786
|
+
skills_removed: skillsRemoved,
|
|
3787
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
3788
|
+
skills_removed_count: skillsRemoved.length,
|
|
3789
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
3790
|
+
hooks_removed: settingsChanged,
|
|
3791
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
3792
|
+
hook_scripts_removed: scriptsRemoved,
|
|
3793
|
+
// biome-ignore lint/style/useNamingConvention: snake_case for analytics
|
|
3794
|
+
wallet_removed: walletRemoved,
|
|
3795
|
+
purge
|
|
3796
|
+
});
|
|
3797
|
+
sectionDivider();
|
|
3798
|
+
console.log(` ${color.boldGreen("Zero uninstalled.")}`);
|
|
3799
|
+
if (!purge) {
|
|
3800
|
+
console.log(
|
|
3801
|
+
` ${color.dim("Your wallet is kept at ~/.zero \u2014 reinstall anytime with `zero init`.")}`
|
|
3802
|
+
);
|
|
3803
|
+
}
|
|
3804
|
+
console.log("");
|
|
3805
|
+
return {
|
|
3806
|
+
skillsRemoved,
|
|
3807
|
+
hooksRemoved: settingsChanged,
|
|
3808
|
+
hookScriptsRemoved: scriptsRemoved,
|
|
3809
|
+
walletRemoved
|
|
3810
|
+
};
|
|
3811
|
+
} catch (err) {
|
|
3812
|
+
appContext.services.analyticsService.capture("uninstall_failed", {
|
|
3813
|
+
step: currentStep,
|
|
3814
|
+
error: truncateError(err instanceof Error ? err.message : String(err)),
|
|
3815
|
+
purge
|
|
3816
|
+
});
|
|
3817
|
+
throw err;
|
|
3818
|
+
}
|
|
3819
|
+
};
|
|
3820
|
+
var uninstallCommand = (appContext) => new Command11("uninstall").description(
|
|
3821
|
+
"Remove Zero skills and hooks installed by `zero init` (keeps your wallet)"
|
|
3822
|
+
).option(
|
|
3823
|
+
"--purge",
|
|
3824
|
+
"Also delete the wallet config at ~/.zero (irreversible \u2014 destroys the private key)"
|
|
3825
|
+
).option(
|
|
3826
|
+
"-v, --verbose",
|
|
3827
|
+
"Explain why each removal step was taken or skipped"
|
|
3828
|
+
).action(async (options) => {
|
|
3829
|
+
await runUninstall(appContext, options);
|
|
3830
|
+
});
|
|
3831
|
+
|
|
3832
|
+
// src/commands/wallet-command.ts
|
|
3833
|
+
import { existsSync as existsSync4, readFileSync as readFileSync9 } from "fs";
|
|
3834
|
+
import { homedir as homedir5 } from "os";
|
|
3835
|
+
import { join as join6 } from "path";
|
|
3836
|
+
import { confirm, isCancel } from "@clack/prompts";
|
|
3837
|
+
import { Command as Command12 } from "commander";
|
|
3571
3838
|
import open2 from "open";
|
|
3572
3839
|
import { isAddress } from "viem";
|
|
3573
3840
|
import { generatePrivateKey as generatePrivateKey2, privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
3574
3841
|
|
|
3575
3842
|
// src/util/migrate-config.ts
|
|
3576
|
-
import { readFileSync as
|
|
3577
|
-
import { join as
|
|
3843
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
3844
|
+
import { join as join5 } from "path";
|
|
3578
3845
|
var backupAndStripPrivateKey = (zeroDir) => {
|
|
3579
|
-
const configPath =
|
|
3580
|
-
const backupPath =
|
|
3581
|
-
const raw =
|
|
3846
|
+
const configPath = join5(zeroDir, "config.json");
|
|
3847
|
+
const backupPath = join5(zeroDir, "config.backup.json");
|
|
3848
|
+
const raw = readFileSync8(configPath, "utf8");
|
|
3582
3849
|
ensureSecureDir(zeroDir);
|
|
3583
3850
|
writeSecureFile(backupPath, raw);
|
|
3584
3851
|
const parsed = JSON.parse(raw);
|
|
@@ -3599,7 +3866,7 @@ var readStdin = async () => {
|
|
|
3599
3866
|
// src/commands/wallet-command.ts
|
|
3600
3867
|
var PRIVATE_KEY_PATTERN = /^0x[0-9a-fA-F]{64}$/;
|
|
3601
3868
|
var parseProvider = (raw) => raw === "stripe" ? "stripe" : "coinbase";
|
|
3602
|
-
var walletBalanceCommand = (appContext) => new
|
|
3869
|
+
var walletBalanceCommand = (appContext) => new Command12("balance").description("Show wallet balance").option(
|
|
3603
3870
|
"--address <address>",
|
|
3604
3871
|
"Check balance for an arbitrary address (no key needed). Useful with `zero wallet generate` \u2014 verify funds arrived without setting the wallet as your default."
|
|
3605
3872
|
).action(async (options) => {
|
|
@@ -3648,7 +3915,7 @@ var readPrivateKeyFromStdin = async () => {
|
|
|
3648
3915
|
}
|
|
3649
3916
|
return raw;
|
|
3650
3917
|
};
|
|
3651
|
-
var walletFundCommand = (appContext) => new
|
|
3918
|
+
var walletFundCommand = (appContext) => new Command12("fund").description("Fund your wallet").argument("[amount]", "Amount to fund in USDC").option("--manual", "Show wallet address for manual transfer").option(
|
|
3652
3919
|
"--no-open",
|
|
3653
3920
|
"Print the funding URL instead of opening a browser (for agents \u2014 funding links are one-time use, hand the URL to the user)"
|
|
3654
3921
|
).option(
|
|
@@ -3745,7 +4012,7 @@ ${address}`);
|
|
|
3745
4012
|
}
|
|
3746
4013
|
}
|
|
3747
4014
|
);
|
|
3748
|
-
var walletAddressCommand = (appContext) => new
|
|
4015
|
+
var walletAddressCommand = (appContext) => new Command12("address").description("Show wallet address").action(() => {
|
|
3749
4016
|
const { walletService } = appContext.services;
|
|
3750
4017
|
const address = walletService.getAddress();
|
|
3751
4018
|
if (!address) {
|
|
@@ -3755,7 +4022,7 @@ var walletAddressCommand = (appContext) => new Command11("address").description(
|
|
|
3755
4022
|
}
|
|
3756
4023
|
console.log(address);
|
|
3757
4024
|
});
|
|
3758
|
-
var walletSetCommand = (appContext) => new
|
|
4025
|
+
var walletSetCommand = (appContext) => new Command12("set").description("Set wallet from an existing private key").argument("<privateKey>", "Hex-encoded private key (0x-prefixed)").option("--force", "Overwrite existing wallet without prompting").action(async (privateKey, options) => {
|
|
3759
4026
|
const { analyticsService } = appContext.services;
|
|
3760
4027
|
if (!privateKey.startsWith("0x")) {
|
|
3761
4028
|
console.error("Private key must be 0x-prefixed hex string.");
|
|
@@ -3770,11 +4037,11 @@ var walletSetCommand = (appContext) => new Command11("set").description("Set wal
|
|
|
3770
4037
|
process.exitCode = 1;
|
|
3771
4038
|
return;
|
|
3772
4039
|
}
|
|
3773
|
-
const zeroDir =
|
|
3774
|
-
const configPath =
|
|
3775
|
-
if (!options.force &&
|
|
4040
|
+
const zeroDir = join6(homedir5(), ".zero");
|
|
4041
|
+
const configPath = join6(zeroDir, "config.json");
|
|
4042
|
+
if (!options.force && existsSync4(configPath)) {
|
|
3776
4043
|
try {
|
|
3777
|
-
const existing2 = JSON.parse(
|
|
4044
|
+
const existing2 = JSON.parse(readFileSync9(configPath, "utf8"));
|
|
3778
4045
|
if (existing2.privateKey) {
|
|
3779
4046
|
console.error(
|
|
3780
4047
|
"Wallet already configured. Use --force to overwrite."
|
|
@@ -3786,7 +4053,7 @@ var walletSetCommand = (appContext) => new Command11("set").description("Set wal
|
|
|
3786
4053
|
}
|
|
3787
4054
|
}
|
|
3788
4055
|
ensureSecureDir(zeroDir);
|
|
3789
|
-
const existing =
|
|
4056
|
+
const existing = existsSync4(configPath) ? JSON.parse(readFileSync9(configPath, "utf8")) : {};
|
|
3790
4057
|
writeSecureFile(
|
|
3791
4058
|
configPath,
|
|
3792
4059
|
JSON.stringify(
|
|
@@ -3805,7 +4072,7 @@ var walletSetCommand = (appContext) => new Command11("set").description("Set wal
|
|
|
3805
4072
|
force: options.force ?? false
|
|
3806
4073
|
});
|
|
3807
4074
|
});
|
|
3808
|
-
var walletGenerateCommand = (appContext) => new
|
|
4075
|
+
var walletGenerateCommand = (appContext) => new Command12("generate").description(
|
|
3809
4076
|
"Generate a fresh wallet (address + private key) without touching your configured wallet"
|
|
3810
4077
|
).option("--json", "Emit { address, privateKey } as JSON").option(
|
|
3811
4078
|
"--fund",
|
|
@@ -3895,13 +4162,13 @@ var resolveZeroWalletAddress = async (apiService) => {
|
|
|
3895
4162
|
return null;
|
|
3896
4163
|
}
|
|
3897
4164
|
};
|
|
3898
|
-
var walletMigrateCommand = (appContext) => new
|
|
4165
|
+
var walletMigrateCommand = (appContext) => new Command12("migrate").description(
|
|
3899
4166
|
"Sweep all USDC from your private-key wallet into your Zero wallet"
|
|
3900
4167
|
).option("--json", "Emit the migration result as JSON").option("-y, --yes", "Skip the confirmation prompt").action(async (options) => {
|
|
3901
4168
|
const { apiService, paymentService } = appContext.services;
|
|
3902
|
-
const zeroDir =
|
|
3903
|
-
const configPath =
|
|
3904
|
-
const config =
|
|
4169
|
+
const zeroDir = join6(homedir5(), ".zero");
|
|
4170
|
+
const configPath = join6(zeroDir, "config.json");
|
|
4171
|
+
const config = existsSync4(configPath) ? readConfig(configPath) : {};
|
|
3905
4172
|
const privateKey = appContext.env.ZERO_PRIVATE_KEY ?? config.privateKey;
|
|
3906
4173
|
if (!privateKey) {
|
|
3907
4174
|
console.error(
|
|
@@ -4019,7 +4286,7 @@ var walletMigrateCommand = (appContext) => new Command11("migrate").description(
|
|
|
4019
4286
|
if (anyFailed) process.exitCode = 1;
|
|
4020
4287
|
});
|
|
4021
4288
|
var walletCommand = (appContext) => {
|
|
4022
|
-
const cmd = new
|
|
4289
|
+
const cmd = new Command12("wallet").description("Manage your wallet");
|
|
4023
4290
|
cmd.addCommand(walletBalanceCommand(appContext));
|
|
4024
4291
|
cmd.addCommand(walletFundCommand(appContext));
|
|
4025
4292
|
cmd.addCommand(walletAddressCommand(appContext));
|
|
@@ -4030,18 +4297,18 @@ var walletCommand = (appContext) => {
|
|
|
4030
4297
|
};
|
|
4031
4298
|
|
|
4032
4299
|
// src/commands/welcome-command.ts
|
|
4033
|
-
import { existsSync as
|
|
4034
|
-
import { homedir as
|
|
4035
|
-
import { join as
|
|
4036
|
-
import { Command as
|
|
4300
|
+
import { existsSync as existsSync5, readFileSync as readFileSync10 } from "fs";
|
|
4301
|
+
import { homedir as homedir6 } from "os";
|
|
4302
|
+
import { join as join7 } from "path";
|
|
4303
|
+
import { Command as Command13 } from "commander";
|
|
4037
4304
|
import open3 from "open";
|
|
4038
4305
|
import { getAddress } from "viem";
|
|
4039
4306
|
import { privateKeyToAccount as privateKeyToAccount3 } from "viem/accounts";
|
|
4040
4307
|
var readPrivateKey = () => {
|
|
4041
|
-
const configPath =
|
|
4042
|
-
if (!
|
|
4308
|
+
const configPath = join7(homedir6(), ".zero", "config.json");
|
|
4309
|
+
if (!existsSync5(configPath)) return null;
|
|
4043
4310
|
try {
|
|
4044
|
-
const config = JSON.parse(
|
|
4311
|
+
const config = JSON.parse(readFileSync10(configPath, "utf8"));
|
|
4045
4312
|
if (typeof config.privateKey === "string") {
|
|
4046
4313
|
return config.privateKey;
|
|
4047
4314
|
}
|
|
@@ -4076,7 +4343,7 @@ var printManualFallback = (url) => {
|
|
|
4076
4343
|
}
|
|
4077
4344
|
console.log(lines.join("\n"));
|
|
4078
4345
|
};
|
|
4079
|
-
var welcomeCommand = (appContext) => new
|
|
4346
|
+
var welcomeCommand = (appContext) => new Command13("welcome").description("Claim your $5 welcome bonus.").action(async () => {
|
|
4080
4347
|
const { analyticsService } = appContext.services;
|
|
4081
4348
|
analyticsService.capture("welcome_started", {});
|
|
4082
4349
|
let walletAddress;
|
|
@@ -4136,7 +4403,7 @@ If your browser didn't open, paste the URL above.`
|
|
|
4136
4403
|
// src/app.ts
|
|
4137
4404
|
var createApp = (appContext) => {
|
|
4138
4405
|
const { analyticsService } = appContext.services;
|
|
4139
|
-
const program = new
|
|
4406
|
+
const program = new Command14().name("zero").description("Zero CLI \u2014 Search engine for AI agents").version(package_default.version, "-v, --version").exitOverride().hook("preAction", async (_thisCommand, actionCommand) => {
|
|
4140
4407
|
const agentFlag = actionCommand.opts().agent;
|
|
4141
4408
|
if (typeof agentFlag === "string" && agentFlag.trim().length > 0) {
|
|
4142
4409
|
analyticsService.setAgentHost(agentFlag.trim());
|
|
@@ -4150,6 +4417,7 @@ var createApp = (appContext) => {
|
|
|
4150
4417
|
});
|
|
4151
4418
|
});
|
|
4152
4419
|
program.addCommand(initCommand(appContext));
|
|
4420
|
+
program.addCommand(uninstallCommand(appContext));
|
|
4153
4421
|
program.addCommand(searchCommand(appContext));
|
|
4154
4422
|
program.addCommand(getCommand(appContext));
|
|
4155
4423
|
program.addCommand(fetchCommand(appContext));
|
|
@@ -4185,14 +4453,14 @@ var getEnv = () => {
|
|
|
4185
4453
|
|
|
4186
4454
|
// src/app/app-services.ts
|
|
4187
4455
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
4188
|
-
import { existsSync as
|
|
4189
|
-
import { homedir as
|
|
4190
|
-
import { join as
|
|
4456
|
+
import { existsSync as existsSync8 } from "fs";
|
|
4457
|
+
import { homedir as homedir7 } from "os";
|
|
4458
|
+
import { join as join9 } from "path";
|
|
4191
4459
|
import { privateKeyToAccount as privateKeyToAccount4 } from "viem/accounts";
|
|
4192
4460
|
|
|
4193
4461
|
// src/services/analytics-service.ts
|
|
4194
4462
|
import { randomUUID } from "crypto";
|
|
4195
|
-
import { existsSync as
|
|
4463
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync11, writeFileSync as writeFileSync5 } from "fs";
|
|
4196
4464
|
import { dirname as dirname2 } from "path";
|
|
4197
4465
|
import { PostHog } from "posthog-node";
|
|
4198
4466
|
var POSTHOG_API_KEY = "phc_B2vLyNxAf2mnqvdPQajf4d4b2iXc35dep2ZrvebMJLuX";
|
|
@@ -4214,8 +4482,8 @@ var AnalyticsService = class {
|
|
|
4214
4482
|
let telemetryEnabled = true;
|
|
4215
4483
|
let persistedAnonId;
|
|
4216
4484
|
try {
|
|
4217
|
-
if (
|
|
4218
|
-
const config = JSON.parse(
|
|
4485
|
+
if (existsSync6(opts.configPath)) {
|
|
4486
|
+
const config = JSON.parse(readFileSync11(opts.configPath, "utf8"));
|
|
4219
4487
|
if (config.telemetry === false) {
|
|
4220
4488
|
telemetryEnabled = false;
|
|
4221
4489
|
}
|
|
@@ -4241,8 +4509,8 @@ var AnalyticsService = class {
|
|
|
4241
4509
|
try {
|
|
4242
4510
|
const dir = dirname2(opts.configPath);
|
|
4243
4511
|
mkdirSync4(dir, { recursive: true });
|
|
4244
|
-
const existing =
|
|
4245
|
-
|
|
4512
|
+
const existing = existsSync6(opts.configPath) ? JSON.parse(readFileSync11(opts.configPath, "utf8")) : {};
|
|
4513
|
+
writeFileSync5(
|
|
4246
4514
|
opts.configPath,
|
|
4247
4515
|
JSON.stringify({ ...existing, anonId: newAnonId }, null, 2)
|
|
4248
4516
|
);
|
|
@@ -4282,7 +4550,7 @@ var AnalyticsService = class {
|
|
|
4282
4550
|
if (anonId === walletAddress) return;
|
|
4283
4551
|
let aliasedTo;
|
|
4284
4552
|
try {
|
|
4285
|
-
const config = JSON.parse(
|
|
4553
|
+
const config = JSON.parse(readFileSync11(configPath, "utf8"));
|
|
4286
4554
|
if (typeof config.aliasedTo === "string") {
|
|
4287
4555
|
aliasedTo = config.aliasedTo;
|
|
4288
4556
|
}
|
|
@@ -4292,8 +4560,8 @@ var AnalyticsService = class {
|
|
|
4292
4560
|
this.posthog.alias({ distinctId: walletAddress, alias: anonId });
|
|
4293
4561
|
if (process.env.VITEST) return;
|
|
4294
4562
|
try {
|
|
4295
|
-
const config =
|
|
4296
|
-
|
|
4563
|
+
const config = existsSync6(configPath) ? JSON.parse(readFileSync11(configPath, "utf8")) : {};
|
|
4564
|
+
writeFileSync5(
|
|
4297
4565
|
configPath,
|
|
4298
4566
|
JSON.stringify({ ...config, aliasedTo: walletAddress }, null, 2)
|
|
4299
4567
|
);
|
|
@@ -4396,34 +4664,34 @@ var createApiAccount = (walletAddress, api) => toAccount({
|
|
|
4396
4664
|
});
|
|
4397
4665
|
|
|
4398
4666
|
// src/services/state-service.ts
|
|
4399
|
-
import { existsSync as
|
|
4400
|
-
import { join as
|
|
4667
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync12, writeFileSync as writeFileSync6 } from "fs";
|
|
4668
|
+
import { join as join8 } from "path";
|
|
4401
4669
|
var RECENT_SEARCH_LIMIT = 10;
|
|
4402
4670
|
var StateService = class {
|
|
4403
4671
|
constructor(zeroDir) {
|
|
4404
4672
|
this.zeroDir = zeroDir;
|
|
4405
|
-
this.lastSearchPath =
|
|
4406
|
-
this.recentSearchesPath =
|
|
4673
|
+
this.lastSearchPath = join8(zeroDir, "last_search.json");
|
|
4674
|
+
this.recentSearchesPath = join8(zeroDir, "recent_searches.json");
|
|
4407
4675
|
}
|
|
4408
4676
|
lastSearchPath;
|
|
4409
4677
|
recentSearchesPath;
|
|
4410
4678
|
saveLastSearch = (data) => {
|
|
4411
4679
|
mkdirSync5(this.zeroDir, { recursive: true });
|
|
4412
|
-
|
|
4680
|
+
writeFileSync6(this.lastSearchPath, JSON.stringify(data, null, 2));
|
|
4413
4681
|
const recent = this.loadRecentSearches();
|
|
4414
4682
|
const filtered = recent.searches.filter(
|
|
4415
4683
|
(s) => s.searchId !== data.searchId
|
|
4416
4684
|
);
|
|
4417
4685
|
const next = [data, ...filtered].slice(0, RECENT_SEARCH_LIMIT);
|
|
4418
|
-
|
|
4686
|
+
writeFileSync6(
|
|
4419
4687
|
this.recentSearchesPath,
|
|
4420
4688
|
JSON.stringify({ searches: next }, null, 2)
|
|
4421
4689
|
);
|
|
4422
4690
|
};
|
|
4423
4691
|
loadLastSearch = () => {
|
|
4424
4692
|
try {
|
|
4425
|
-
if (!
|
|
4426
|
-
const raw =
|
|
4693
|
+
if (!existsSync7(this.lastSearchPath)) return null;
|
|
4694
|
+
const raw = readFileSync12(this.lastSearchPath, "utf8");
|
|
4427
4695
|
return JSON.parse(raw);
|
|
4428
4696
|
} catch {
|
|
4429
4697
|
return null;
|
|
@@ -4431,11 +4699,11 @@ var StateService = class {
|
|
|
4431
4699
|
};
|
|
4432
4700
|
loadRecentSearches = () => {
|
|
4433
4701
|
try {
|
|
4434
|
-
if (!
|
|
4702
|
+
if (!existsSync7(this.recentSearchesPath)) {
|
|
4435
4703
|
const last = this.loadLastSearch();
|
|
4436
4704
|
return { searches: last ? [last] : [] };
|
|
4437
4705
|
}
|
|
4438
|
-
const raw =
|
|
4706
|
+
const raw = readFileSync12(this.recentSearchesPath, "utf8");
|
|
4439
4707
|
const parsed = JSON.parse(raw);
|
|
4440
4708
|
return { searches: parsed.searches ?? [] };
|
|
4441
4709
|
} catch {
|
|
@@ -4563,9 +4831,9 @@ var buildOnSessionRefreshed = (configPath) => async (tokens) => {
|
|
|
4563
4831
|
writeSecureFile(configPath, JSON.stringify(next, null, 2));
|
|
4564
4832
|
};
|
|
4565
4833
|
var getServices = async (env) => {
|
|
4566
|
-
const zeroDir =
|
|
4567
|
-
const configPath =
|
|
4568
|
-
const config =
|
|
4834
|
+
const zeroDir = join9(homedir7(), ".zero");
|
|
4835
|
+
const configPath = join9(zeroDir, "config.json");
|
|
4836
|
+
const config = existsSync8(configPath) ? readConfig(configPath) : {};
|
|
4569
4837
|
const { credentials, privateKey } = resolveCredentials(env, config);
|
|
4570
4838
|
const lowBalanceWarning = typeof config.lowBalanceWarning === "number" ? config.lowBalanceWarning : 1;
|
|
4571
4839
|
const apiService = new ApiService(
|
|
@@ -4638,15 +4906,15 @@ var createAppContext = async () => {
|
|
|
4638
4906
|
|
|
4639
4907
|
// src/util/update-check.ts
|
|
4640
4908
|
import {
|
|
4641
|
-
existsSync as
|
|
4909
|
+
existsSync as existsSync9,
|
|
4642
4910
|
lstatSync,
|
|
4643
4911
|
mkdirSync as mkdirSync6,
|
|
4644
|
-
readFileSync as
|
|
4912
|
+
readFileSync as readFileSync13,
|
|
4645
4913
|
readlinkSync,
|
|
4646
|
-
writeFileSync as
|
|
4914
|
+
writeFileSync as writeFileSync7
|
|
4647
4915
|
} from "fs";
|
|
4648
|
-
import { homedir as
|
|
4649
|
-
import { dirname as dirname3, join as
|
|
4916
|
+
import { homedir as homedir8 } from "os";
|
|
4917
|
+
import { dirname as dirname3, join as join10, resolve } from "path";
|
|
4650
4918
|
var CACHE_FILENAME = "update_check.json";
|
|
4651
4919
|
var NPM_REGISTRY_URL = "https://registry.npmjs.org/@zeroxyz/cli/latest";
|
|
4652
4920
|
var CHECK_INTERVAL_MS = 60 * 60 * 1e3;
|
|
@@ -4670,10 +4938,10 @@ var resolveExecPath = (execPath) => {
|
|
|
4670
4938
|
var detectInstallMethod = (opts = {}) => {
|
|
4671
4939
|
const execPath = opts.execPath ?? process.execPath;
|
|
4672
4940
|
const pkg = opts.pkg ?? process.pkg;
|
|
4673
|
-
const home = opts.home ??
|
|
4941
|
+
const home = opts.home ?? homedir8();
|
|
4674
4942
|
if (pkg) return "binary";
|
|
4675
4943
|
const resolved = resolveExecPath(execPath);
|
|
4676
|
-
const zeroBin =
|
|
4944
|
+
const zeroBin = join10(home, ".zero", "bin");
|
|
4677
4945
|
if (resolved.startsWith(zeroBin)) return "binary";
|
|
4678
4946
|
return "npm";
|
|
4679
4947
|
};
|
|
@@ -4698,12 +4966,12 @@ var compareVersions = (a, b) => {
|
|
|
4698
4966
|
if (pb.pre === null) return -1;
|
|
4699
4967
|
return pa.pre < pb.pre ? -1 : 1;
|
|
4700
4968
|
};
|
|
4701
|
-
var cachePath = (zeroDir) =>
|
|
4969
|
+
var cachePath = (zeroDir) => join10(zeroDir, CACHE_FILENAME);
|
|
4702
4970
|
var readCache = (zeroDir) => {
|
|
4703
4971
|
try {
|
|
4704
4972
|
const path = cachePath(zeroDir);
|
|
4705
|
-
if (!
|
|
4706
|
-
const raw =
|
|
4973
|
+
if (!existsSync9(path)) return emptyCache;
|
|
4974
|
+
const raw = readFileSync13(path, "utf8");
|
|
4707
4975
|
const parsed = JSON.parse(raw);
|
|
4708
4976
|
return {
|
|
4709
4977
|
lastCheckedMs: typeof parsed.lastCheckedMs === "number" ? parsed.lastCheckedMs : 0,
|
|
@@ -4717,7 +4985,7 @@ var readCache = (zeroDir) => {
|
|
|
4717
4985
|
var writeCache = (zeroDir, cache) => {
|
|
4718
4986
|
try {
|
|
4719
4987
|
mkdirSync6(zeroDir, { recursive: true });
|
|
4720
|
-
|
|
4988
|
+
writeFileSync7(cachePath(zeroDir), JSON.stringify(cache, null, 2));
|
|
4721
4989
|
} catch {
|
|
4722
4990
|
}
|
|
4723
4991
|
};
|
|
@@ -4792,7 +5060,7 @@ var main = async () => {
|
|
|
4792
5060
|
console.error("Failed to create app context");
|
|
4793
5061
|
process.exit(1);
|
|
4794
5062
|
}
|
|
4795
|
-
const zeroDir =
|
|
5063
|
+
const zeroDir = join11(homedir9(), ".zero");
|
|
4796
5064
|
maybePrintUpdateBanner(zeroDir, package_default.version);
|
|
4797
5065
|
const app = createApp(appContext);
|
|
4798
5066
|
let caughtError = null;
|