@alchemy/cli 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{auth-4HAUNG54.js → auth-BNT5Z5GZ.js} +2 -2
- package/dist/{chunk-A6L3WCJN.js → chunk-5IFXLC2S.js} +68 -8
- package/dist/{chunk-WWWVMK3J.js → chunk-RS3DSL3X.js} +1 -1
- package/dist/{chunk-I3X4G2UY.js → chunk-SYP6KKP6.js} +1 -1
- package/dist/index.js +50 -15
- package/dist/{interactive-F2AFLW7U.js → interactive-N33RCX33.js} +5 -2
- package/dist/{onboarding-RBJF5E7U.js → onboarding-S6HKWOEA.js} +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -82,7 +82,7 @@ Have your agent run `agent-prompt` as its first step to get a complete, machine-
|
|
|
82
82
|
alchemy --json --no-interactive agent-prompt
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
This returns a single JSON document with execution policy, preflight instructions, auth matrix, the full command tree with all arguments and options, error codes with recovery actions, and example invocations. No external docs required.
|
|
85
|
+
This returns a single JSON document with execution policy, runtime discovery instructions, preflight instructions, auth matrix, the full command tree with all arguments and options, error codes with recovery actions, and example invocations. No external docs required.
|
|
86
86
|
|
|
87
87
|
Agents can also call `alchemy --json --no-interactive update-check` to retrieve the current CLI version, latest known version, and install command for upgrades.
|
|
88
88
|
|
|
@@ -3,11 +3,11 @@ if(process.argv.includes("--no-color"))process.env.NO_COLOR="1";
|
|
|
3
3
|
import {
|
|
4
4
|
registerAuth,
|
|
5
5
|
selectAppAfterAuth
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-SYP6KKP6.js";
|
|
7
7
|
import "./chunk-HSKKIATB.js";
|
|
8
8
|
import "./chunk-HYCRHNPX.js";
|
|
9
9
|
import "./chunk-TOEVZMIP.js";
|
|
10
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-5IFXLC2S.js";
|
|
11
11
|
import "./chunk-7WD3YLRK.js";
|
|
12
12
|
import "./chunk-QEDAULQ2.js";
|
|
13
13
|
export {
|
|
@@ -46,6 +46,53 @@ function suspendStdinKeypressListeners() {
|
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
|
+
function resetStdinKeypressDecoder() {
|
|
50
|
+
const input = stdin;
|
|
51
|
+
for (const symbol of Object.getOwnPropertySymbols(input)) {
|
|
52
|
+
const name = String(symbol);
|
|
53
|
+
if (name === "Symbol(keypress-decoder)" || name === "Symbol(escape-decoder)") {
|
|
54
|
+
delete input[symbol];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function isReadlineKeypressDataListener(listener) {
|
|
59
|
+
return typeof listener === "function" && listener.name === "onData";
|
|
60
|
+
}
|
|
61
|
+
function prepareStdinKeypressEvents() {
|
|
62
|
+
const dataListeners = stdin.listeners("data");
|
|
63
|
+
const keypressListeners = stdin.listeners("keypress");
|
|
64
|
+
for (const listener of dataListeners) {
|
|
65
|
+
stdin.removeListener("data", listener);
|
|
66
|
+
}
|
|
67
|
+
for (const listener of keypressListeners) {
|
|
68
|
+
stdin.removeListener("keypress", listener);
|
|
69
|
+
}
|
|
70
|
+
resetStdinKeypressDecoder();
|
|
71
|
+
readline.emitKeypressEvents(stdin);
|
|
72
|
+
return () => {
|
|
73
|
+
for (const listener of stdin.listeners("data")) {
|
|
74
|
+
stdin.removeListener("data", listener);
|
|
75
|
+
}
|
|
76
|
+
resetStdinKeypressDecoder();
|
|
77
|
+
for (const listener of dataListeners) {
|
|
78
|
+
if (!isReadlineKeypressDataListener(listener)) {
|
|
79
|
+
stdin.on("data", listener);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
for (const listener of keypressListeners) {
|
|
83
|
+
stdin.on("keypress", listener);
|
|
84
|
+
}
|
|
85
|
+
if (keypressListeners.length > 0) {
|
|
86
|
+
readline.emitKeypressEvents(stdin);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function requestPromptInterrupt() {
|
|
91
|
+
const handled = process.emit("SIGINT", "SIGINT");
|
|
92
|
+
if (!handled) {
|
|
93
|
+
process.exit(130);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
49
96
|
async function runListPrompt(opts) {
|
|
50
97
|
if (!stdin.isTTY || !stdout.isTTY) {
|
|
51
98
|
if (opts.allowMultiple) {
|
|
@@ -54,8 +101,7 @@ async function runListPrompt(opts) {
|
|
|
54
101
|
const initial = opts.initialValue ?? opts.options.find((o) => !o.disabled)?.value ?? null;
|
|
55
102
|
return { value: initial, cancelled: false };
|
|
56
103
|
}
|
|
57
|
-
|
|
58
|
-
const restoreKeypressListeners = suspendStdinKeypressListeners();
|
|
104
|
+
const restoreKeypressEvents = prepareStdinKeypressEvents();
|
|
59
105
|
const previousRawMode = stdin.isRaw;
|
|
60
106
|
stdin.resume();
|
|
61
107
|
stdin.setRawMode(true);
|
|
@@ -131,7 +177,7 @@ async function runListPrompt(opts) {
|
|
|
131
177
|
if (renderedLines > 0) clearRenderedLines(renderedLines);
|
|
132
178
|
stdin.setRawMode(previousRawMode);
|
|
133
179
|
stdin.removeListener("keypress", onKeypress);
|
|
134
|
-
|
|
180
|
+
restoreKeypressEvents();
|
|
135
181
|
if (!previousRawMode) {
|
|
136
182
|
stdin.pause();
|
|
137
183
|
}
|
|
@@ -144,7 +190,13 @@ async function runListPrompt(opts) {
|
|
|
144
190
|
const onKeypress = (str, key) => {
|
|
145
191
|
const filtered = getFiltered();
|
|
146
192
|
const current = filtered[cursor];
|
|
147
|
-
if (key.
|
|
193
|
+
if (key.ctrl && key.name === "c") {
|
|
194
|
+
cleanup();
|
|
195
|
+
requestPromptInterrupt();
|
|
196
|
+
resolver({ value: null, cancelled: true });
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (key.name === "escape") {
|
|
148
200
|
cleanup();
|
|
149
201
|
resolver({ value: null, cancelled: true });
|
|
150
202
|
return;
|
|
@@ -222,8 +274,10 @@ async function promptText(opts) {
|
|
|
222
274
|
const previousRawMode = stdin.isRaw;
|
|
223
275
|
if (previousRawMode) stdin.setRawMode(false);
|
|
224
276
|
const ABORTED = /* @__PURE__ */ Symbol("aborted");
|
|
277
|
+
const INTERRUPTED = /* @__PURE__ */ Symbol("interrupted");
|
|
278
|
+
let removeAbortListener;
|
|
225
279
|
const value = await new Promise((resolve) => {
|
|
226
|
-
rl.on("SIGINT", () => resolve(
|
|
280
|
+
rl.on("SIGINT", () => resolve(INTERRUPTED));
|
|
227
281
|
rl.question(question, (answer) => resolve(answer));
|
|
228
282
|
if (opts.abortSignal) {
|
|
229
283
|
const onAbort = () => resolve(ABORTED);
|
|
@@ -231,18 +285,24 @@ async function promptText(opts) {
|
|
|
231
285
|
onAbort();
|
|
232
286
|
} else {
|
|
233
287
|
opts.abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
288
|
+
removeAbortListener = () => opts.abortSignal?.removeEventListener("abort", onAbort);
|
|
234
289
|
}
|
|
235
290
|
}
|
|
236
291
|
});
|
|
237
292
|
rl.close();
|
|
293
|
+
removeAbortListener?.();
|
|
238
294
|
restoreKeypressListeners();
|
|
239
|
-
if (previousRawMode)
|
|
295
|
+
if (previousRawMode) {
|
|
296
|
+
stdin.setRawMode(true);
|
|
297
|
+
} else {
|
|
298
|
+
stdin.pause();
|
|
299
|
+
}
|
|
240
300
|
if (opts.clearAfterSubmit || value === ABORTED) {
|
|
241
301
|
clearRenderedLines(2);
|
|
242
302
|
}
|
|
243
303
|
if (value === ABORTED) return "";
|
|
244
|
-
if (value ===
|
|
245
|
-
|
|
304
|
+
if (value === INTERRUPTED) {
|
|
305
|
+
requestPromptInterrupt();
|
|
246
306
|
return null;
|
|
247
307
|
}
|
|
248
308
|
if (!value.trim() && opts.defaultValue !== void 0) return opts.defaultValue;
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
if(process.argv.includes("--no-color"))process.env.NO_COLOR="1";
|
|
3
3
|
import {
|
|
4
4
|
registerAuth
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-SYP6KKP6.js";
|
|
6
6
|
import {
|
|
7
7
|
openBrowser
|
|
8
8
|
} from "./chunk-HSKKIATB.js";
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
getAvailableUpdate,
|
|
47
47
|
getUpdateStatus,
|
|
48
48
|
printUpdateNotice
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-RS3DSL3X.js";
|
|
50
50
|
import {
|
|
51
51
|
bold,
|
|
52
52
|
brand,
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
weiToEth,
|
|
71
71
|
withSpinner,
|
|
72
72
|
yellow
|
|
73
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-5IFXLC2S.js";
|
|
74
74
|
import {
|
|
75
75
|
KEY_MAP,
|
|
76
76
|
configDir,
|
|
@@ -283,7 +283,6 @@ function validateTxHash(hash) {
|
|
|
283
283
|
|
|
284
284
|
// src/commands/config.ts
|
|
285
285
|
var RESET_KEY_MAP = { ...KEY_MAP, app: "app" };
|
|
286
|
-
var APP_SEARCH_THRESHOLD = 15;
|
|
287
286
|
async function saveAppWithPrompt(app) {
|
|
288
287
|
const cfg = load();
|
|
289
288
|
const updated = {
|
|
@@ -331,17 +330,12 @@ async function selectOrCreateApp(admin) {
|
|
|
331
330
|
})),
|
|
332
331
|
{ label: "Create a new app", value: CREATE_NEW }
|
|
333
332
|
];
|
|
334
|
-
const selected =
|
|
333
|
+
const selected = await promptAutocomplete({
|
|
335
334
|
message: "Select default app",
|
|
336
335
|
placeholder: "Type app name or id",
|
|
337
336
|
options,
|
|
338
337
|
cancelMessage: "Cancelled app selection.",
|
|
339
338
|
commitLabel: null
|
|
340
|
-
}) : await promptSelect({
|
|
341
|
-
message: "Select default app",
|
|
342
|
-
options,
|
|
343
|
-
cancelMessage: "Cancelled app selection.",
|
|
344
|
-
commitLabel: null
|
|
345
339
|
});
|
|
346
340
|
if (selected === null) {
|
|
347
341
|
return;
|
|
@@ -1185,8 +1179,9 @@ function registerApps(program2) {
|
|
|
1185
1179
|
printJSON({ apps: result.apps.map(maskAppSecrets) });
|
|
1186
1180
|
return;
|
|
1187
1181
|
}
|
|
1188
|
-
const appId = await
|
|
1182
|
+
const appId = await promptAutocomplete({
|
|
1189
1183
|
message: "Select an app",
|
|
1184
|
+
placeholder: "Type to search by name or id",
|
|
1190
1185
|
options: result.apps.map((app) => ({
|
|
1191
1186
|
value: app.id,
|
|
1192
1187
|
label: app.name,
|
|
@@ -4694,12 +4689,39 @@ function buildAgentPrompt(program2) {
|
|
|
4694
4689
|
"Parse stdout as JSON on exit code 0",
|
|
4695
4690
|
"Parse stderr as JSON on nonzero exit code",
|
|
4696
4691
|
"Never run bare 'alchemy' without --json --no-interactive",
|
|
4692
|
+
"Before answering Alchemy CLI capability or usage questions, inspect the live command contract from agent-prompt and trust it over model memory",
|
|
4693
|
+
"For general capability and usage questions, prefer npx -y @alchemy/cli@latest --json --no-interactive agent-prompt so stale local installs or PATH shims do not hide new commands",
|
|
4694
|
+
"Use the user's installed alchemy binary only when executing commands against their local config or diagnosing their installed version",
|
|
4695
|
+
"If installed alchemy help contradicts latest npm help, compare alchemy --json --no-interactive version with npx -y @alchemy/cli@latest --json --no-interactive version and check command -v alchemy",
|
|
4697
4696
|
"Run alchemy --json --no-interactive update-check when you need to detect available CLI upgrades"
|
|
4698
4697
|
],
|
|
4699
4698
|
preflight: {
|
|
4700
4699
|
command: "alchemy --json --no-interactive config status",
|
|
4701
4700
|
description: "Check auth readiness before first command. If complete is false, follow nextCommands in the response to configure auth."
|
|
4702
4701
|
},
|
|
4702
|
+
runtimeDiscovery: {
|
|
4703
|
+
installed: {
|
|
4704
|
+
command: "alchemy --json --no-interactive agent-prompt",
|
|
4705
|
+
description: "Use for the user's currently installed CLI only when executing against local config or diagnosing local install behavior."
|
|
4706
|
+
},
|
|
4707
|
+
latest: {
|
|
4708
|
+
command: "npx -y @alchemy/cli@latest --json --no-interactive agent-prompt",
|
|
4709
|
+
description: "Default source of truth for general capability and usage questions; avoids stale local installs and PATH shims."
|
|
4710
|
+
},
|
|
4711
|
+
commandHelp: {
|
|
4712
|
+
commandTemplate: "npx -y @alchemy/cli@latest --no-interactive help <command...>",
|
|
4713
|
+
description: "Use for command-specific help from the latest published CLI when constructing an invocation."
|
|
4714
|
+
},
|
|
4715
|
+
versionCheck: {
|
|
4716
|
+
installedCommand: "alchemy --json --no-interactive version",
|
|
4717
|
+
latestCommand: "npx -y @alchemy/cli@latest --json --no-interactive version",
|
|
4718
|
+
description: "Compare when local help or agent-prompt output appears stale after an install or update."
|
|
4719
|
+
},
|
|
4720
|
+
pathCheck: {
|
|
4721
|
+
command: "command -v alchemy && alchemy version",
|
|
4722
|
+
description: "Use when installed CLI behavior contradicts the latest contract or an update appears not to take effect."
|
|
4723
|
+
}
|
|
4724
|
+
},
|
|
4703
4725
|
auth: [
|
|
4704
4726
|
{
|
|
4705
4727
|
method: "API key",
|
|
@@ -4809,6 +4831,19 @@ function formatAsSystemPrompt(payload) {
|
|
|
4809
4831
|
lines.push(` Command: ${payload.preflight.command}`);
|
|
4810
4832
|
lines.push(` ${payload.preflight.description}`);
|
|
4811
4833
|
lines.push("");
|
|
4834
|
+
lines.push("Runtime discovery:");
|
|
4835
|
+
lines.push(` Installed CLI: ${payload.runtimeDiscovery.installed.command}`);
|
|
4836
|
+
lines.push(` ${payload.runtimeDiscovery.installed.description}`);
|
|
4837
|
+
lines.push(` Latest npm CLI: ${payload.runtimeDiscovery.latest.command}`);
|
|
4838
|
+
lines.push(` ${payload.runtimeDiscovery.latest.description}`);
|
|
4839
|
+
lines.push(` Command help: ${payload.runtimeDiscovery.commandHelp.commandTemplate}`);
|
|
4840
|
+
lines.push(` ${payload.runtimeDiscovery.commandHelp.description}`);
|
|
4841
|
+
lines.push(` Installed version: ${payload.runtimeDiscovery.versionCheck.installedCommand}`);
|
|
4842
|
+
lines.push(` Latest npm version: ${payload.runtimeDiscovery.versionCheck.latestCommand}`);
|
|
4843
|
+
lines.push(` ${payload.runtimeDiscovery.versionCheck.description}`);
|
|
4844
|
+
lines.push(` Path check: ${payload.runtimeDiscovery.pathCheck.command}`);
|
|
4845
|
+
lines.push(` ${payload.runtimeDiscovery.pathCheck.description}`);
|
|
4846
|
+
lines.push("");
|
|
4812
4847
|
lines.push("Auth methods:");
|
|
4813
4848
|
for (const auth of payload.auth) {
|
|
4814
4849
|
lines.push(` ${auth.method}:`);
|
|
@@ -7953,7 +7988,7 @@ function resetUpdateNoticeState() {
|
|
|
7953
7988
|
}
|
|
7954
7989
|
program.name("alchemy").description(
|
|
7955
7990
|
"The Alchemy CLI lets you query blockchain data, call JSON-RPC methods, and manage your Alchemy configuration."
|
|
7956
|
-
).version("0.7.
|
|
7991
|
+
).version("0.7.1", "-v, --version", "display CLI version").option("--api-key <key>", "Alchemy API key (env: ALCHEMY_API_KEY)").option(
|
|
7957
7992
|
"-n, --network <network>",
|
|
7958
7993
|
"Target network (default: eth-mainnet) (env: ALCHEMY_NETWORK)"
|
|
7959
7994
|
).option("--x402", "Use x402 wallet-based gateway auth").option(
|
|
@@ -8144,7 +8179,7 @@ ${styledLine}`;
|
|
|
8144
8179
|
const authToken = resolveAuthToken2(cfg);
|
|
8145
8180
|
const hasApiKey = Boolean(cfg.api_key?.trim() || cfg.app?.apiKey);
|
|
8146
8181
|
if (authToken && !hasApiKey) {
|
|
8147
|
-
const { selectAppAfterAuth } = await import("./auth-
|
|
8182
|
+
const { selectAppAfterAuth } = await import("./auth-BNT5Z5GZ.js");
|
|
8148
8183
|
console.log("");
|
|
8149
8184
|
console.log(` No app selected. Please select an app to continue.`);
|
|
8150
8185
|
await selectAppAfterAuth(authToken);
|
|
@@ -8175,7 +8210,7 @@ ${styledLine}`;
|
|
|
8175
8210
|
if (isInteractiveAllowed(program)) {
|
|
8176
8211
|
let latestForInteractiveStartup = null;
|
|
8177
8212
|
if (shouldRunOnboarding(program, cfg)) {
|
|
8178
|
-
const { runOnboarding } = await import("./onboarding-
|
|
8213
|
+
const { runOnboarding } = await import("./onboarding-S6HKWOEA.js");
|
|
8179
8214
|
const latest = getAvailableUpdateOnce();
|
|
8180
8215
|
const completed = await runOnboarding(program, latest);
|
|
8181
8216
|
updateShownDuringInteractiveStartup = Boolean(latest);
|
|
@@ -8189,7 +8224,7 @@ ${styledLine}`;
|
|
|
8189
8224
|
latestForInteractiveStartup
|
|
8190
8225
|
);
|
|
8191
8226
|
}
|
|
8192
|
-
const { startREPL } = await import("./interactive-
|
|
8227
|
+
const { startREPL } = await import("./interactive-N33RCX33.js");
|
|
8193
8228
|
program.exitOverride();
|
|
8194
8229
|
program.configureOutput({
|
|
8195
8230
|
writeErr: () => {
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from "./chunk-TOEVZMIP.js";
|
|
10
10
|
import {
|
|
11
11
|
getUpdateNoticeLines
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-RS3DSL3X.js";
|
|
13
13
|
import {
|
|
14
14
|
bold,
|
|
15
15
|
brand,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
dim,
|
|
18
18
|
green,
|
|
19
19
|
setBrandedHelpSuppressed
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-5IFXLC2S.js";
|
|
21
21
|
import {
|
|
22
22
|
configDir,
|
|
23
23
|
load
|
|
@@ -436,6 +436,9 @@ async function startREPL(program, latestUpdate = null) {
|
|
|
436
436
|
};
|
|
437
437
|
return new Promise((resolve) => {
|
|
438
438
|
rl.on("line", (line) => void onLine(line));
|
|
439
|
+
rl.on("SIGINT", () => {
|
|
440
|
+
rl.close();
|
|
441
|
+
});
|
|
439
442
|
rl.on("close", () => {
|
|
440
443
|
if (Array.isArray(rlWithHistory.history)) {
|
|
441
444
|
saveReplHistory([...rlWithHistory.history].reverse());
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
if(process.argv.includes("--no-color"))process.env.NO_COLOR="1";
|
|
3
3
|
import {
|
|
4
4
|
getUpdateNoticeLines
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-RS3DSL3X.js";
|
|
6
6
|
import {
|
|
7
7
|
bold,
|
|
8
8
|
brand,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
dim,
|
|
11
11
|
green,
|
|
12
12
|
promptText
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-5IFXLC2S.js";
|
|
14
14
|
import {
|
|
15
15
|
load,
|
|
16
16
|
save
|
|
@@ -51,7 +51,7 @@ async function runOnboarding(_program, latestUpdate = null) {
|
|
|
51
51
|
auth_token_expires_at: result.expiresAt
|
|
52
52
|
});
|
|
53
53
|
console.log(` ${green("\u2713")} Logged in successfully`);
|
|
54
|
-
const { selectAppAfterAuth } = await import("./auth-
|
|
54
|
+
const { selectAppAfterAuth } = await import("./auth-BNT5Z5GZ.js");
|
|
55
55
|
await selectAppAfterAuth(result.token);
|
|
56
56
|
return true;
|
|
57
57
|
} catch (err) {
|