@agent-store/cli 0.1.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/README.md +19 -0
- package/package.json +16 -0
- package/src/bin/agent-store.ts +7 -0
- package/src/commands/init.ts +51 -0
- package/src/index.ts +1 -0
- package/src/init/install-wallet.ts +173 -0
- package/src/init/ora-ui.ts +124 -0
- package/src/init/plain-ui.ts +113 -0
- package/src/init/state.ts +105 -0
- package/src/main.ts +29 -0
package/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Agent Store CLI
|
|
2
|
+
|
|
3
|
+
Agent Store is an online marketplace and resource-supply platform for large numbers of AI agents. Through this CLI, agents can discover products, place orders, make payments, and access the resources they need to operate autonomously.
|
|
4
|
+
|
|
5
|
+
Install globally:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @agent-store/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Current runtime requirements:
|
|
12
|
+
|
|
13
|
+
- `bun` must be installed because the published bin runs through Bun
|
|
14
|
+
- macOS, Linux, and WSL terminals are supported in v1
|
|
15
|
+
- `git` and `bash` must be available on `PATH`
|
|
16
|
+
|
|
17
|
+
Available commands:
|
|
18
|
+
|
|
19
|
+
- `agent-store init`, opens the wallet setup wizard.
|
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agent-store/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Agent Store CLI",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"agent-store": "./src/bin/agent-store.ts"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"README.md",
|
|
11
|
+
"src"
|
|
12
|
+
],
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"ora": "latest"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { checkPrerequisites, installWallet } from "../init/install-wallet.ts";
|
|
2
|
+
import { runOraInitUi } from "../init/ora-ui.ts";
|
|
3
|
+
import { runPlainInitUi } from "../init/plain-ui.ts";
|
|
4
|
+
|
|
5
|
+
const resolvePlatform = (): string =>
|
|
6
|
+
process.env.AGENT_STORE_CLI_FORCE_PLATFORM ?? process.platform;
|
|
7
|
+
|
|
8
|
+
const usePlainUi = (): boolean =>
|
|
9
|
+
process.env.AGENT_STORE_CLI_PLAIN === "1" ||
|
|
10
|
+
!process.stdin.isTTY ||
|
|
11
|
+
!process.stdout.isTTY;
|
|
12
|
+
|
|
13
|
+
export const runInitCommand = async (): Promise<number> => {
|
|
14
|
+
const install = async (
|
|
15
|
+
onStep: (step: string) => void,
|
|
16
|
+
): Promise<{ walletAddress: string }> => {
|
|
17
|
+
const prerequisites = checkPrerequisites({
|
|
18
|
+
platform: resolvePlatform(),
|
|
19
|
+
which: (command) => Bun.which(command) ?? null,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
if (!prerequisites.ok) {
|
|
23
|
+
const error = new Error(prerequisites.message) as Error & { step: string };
|
|
24
|
+
|
|
25
|
+
error.step = "Checking prerequisites";
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return installWallet({
|
|
30
|
+
onStep: (step) => {
|
|
31
|
+
if (step !== "Checking prerequisites") {
|
|
32
|
+
onStep(step);
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
if (usePlainUi()) {
|
|
39
|
+
const result = await runPlainInitUi({
|
|
40
|
+
installWallet: install,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return result.exitCode;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const result = await runOraInitUi({
|
|
47
|
+
installWallet: install,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return result.exitCode;
|
|
51
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { main } from "./main.ts";
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
5
|
+
|
|
6
|
+
import { INSTALL_STEPS } from "./state.ts";
|
|
7
|
+
|
|
8
|
+
const AWP_WALLET_REPOSITORY_URL = "https://github.com/awp-core/awp-wallet.git";
|
|
9
|
+
const WALLET_ADDRESS_COMMAND =
|
|
10
|
+
`bash -lc "TOKEN=\\$(awp-wallet unlock --duration 3600 | jq -r '.sessionToken'); ` +
|
|
11
|
+
`awp-wallet status --token \\$TOKEN | jq '.address'"`;
|
|
12
|
+
|
|
13
|
+
export class InstallWalletError extends Error {
|
|
14
|
+
step: string;
|
|
15
|
+
|
|
16
|
+
constructor(step: string, message: string) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.name = "InstallWalletError";
|
|
19
|
+
this.step = step;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const checkPrerequisites = (input: {
|
|
24
|
+
platform: string;
|
|
25
|
+
which: (command: string) => string | null;
|
|
26
|
+
}): { ok: true } | { ok: false; message: string } => {
|
|
27
|
+
if (input.platform !== "darwin" && input.platform !== "linux") {
|
|
28
|
+
return {
|
|
29
|
+
ok: false,
|
|
30
|
+
message:
|
|
31
|
+
"agent-store init currently supports macOS, Linux, and WSL terminals only.",
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
for (const command of ["bun", "git", "bash", "jq"] as const) {
|
|
36
|
+
if (!input.which(command)) {
|
|
37
|
+
return {
|
|
38
|
+
ok: false,
|
|
39
|
+
message: `Missing required command: ${command}`,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return { ok: true };
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const runSpawnedCommand = async (input: {
|
|
48
|
+
command: string;
|
|
49
|
+
cwd?: string;
|
|
50
|
+
}): Promise<string> => {
|
|
51
|
+
const child = spawn(input.command, {
|
|
52
|
+
cwd: input.cwd,
|
|
53
|
+
env: process.env,
|
|
54
|
+
shell: true,
|
|
55
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
let stderr = "";
|
|
59
|
+
let stdout = "";
|
|
60
|
+
|
|
61
|
+
child.stdout.on("data", (chunk: Buffer | string) => {
|
|
62
|
+
stdout += chunk.toString();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
child.stderr.on("data", (chunk: Buffer | string) => {
|
|
66
|
+
stderr += chunk.toString();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const exitCode = await new Promise<number | null>((resolveExit, reject) => {
|
|
70
|
+
child.on("error", reject);
|
|
71
|
+
child.on("close", resolveExit);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
if (exitCode !== 0) {
|
|
75
|
+
const detail = stderr.trim() || stdout.trim() || `${input.command} exited with code ${exitCode}`;
|
|
76
|
+
|
|
77
|
+
throw new Error(detail);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return stdout;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const parseWalletAddress = (output: string): string => {
|
|
84
|
+
const trimmed = output.trim();
|
|
85
|
+
|
|
86
|
+
if (!trimmed) {
|
|
87
|
+
throw new Error("awp-wallet status did not return an address.");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const parsed = JSON.parse(trimmed) as unknown;
|
|
92
|
+
|
|
93
|
+
if (typeof parsed === "string" && parsed.length > 0) {
|
|
94
|
+
return parsed;
|
|
95
|
+
}
|
|
96
|
+
} catch {
|
|
97
|
+
return trimmed;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return trimmed;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export const installWallet = async (input: {
|
|
104
|
+
mkdtemp?: (prefix: string) => Promise<string> | string;
|
|
105
|
+
onStep?: (step: string) => void;
|
|
106
|
+
rm?: (
|
|
107
|
+
path: string,
|
|
108
|
+
options: { force: boolean; recursive: boolean },
|
|
109
|
+
) => Promise<void> | void;
|
|
110
|
+
runCommand?: (input: {
|
|
111
|
+
command: string;
|
|
112
|
+
cwd?: string;
|
|
113
|
+
}) => Promise<string | void> | string | void;
|
|
114
|
+
tmpdir?: () => string;
|
|
115
|
+
} = {}): Promise<{
|
|
116
|
+
walletAddress: string;
|
|
117
|
+
}> => {
|
|
118
|
+
const makeTemporaryDirectory = input.mkdtemp ?? mkdtemp;
|
|
119
|
+
const removeDirectory = input.rm ?? rm;
|
|
120
|
+
const runCommand = input.runCommand ?? runSpawnedCommand;
|
|
121
|
+
const resolveTemporaryRoot = input.tmpdir ?? tmpdir;
|
|
122
|
+
let temporaryDirectory = "";
|
|
123
|
+
let currentStep: string = INSTALL_STEPS[0];
|
|
124
|
+
let walletAddress = "";
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
input.onStep?.(INSTALL_STEPS[0]);
|
|
128
|
+
temporaryDirectory = await makeTemporaryDirectory(
|
|
129
|
+
join(resolveTemporaryRoot(), "agent-store-cli-"),
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
const clonePath = join(temporaryDirectory, "awp-wallet");
|
|
133
|
+
|
|
134
|
+
currentStep = INSTALL_STEPS[1];
|
|
135
|
+
input.onStep?.(currentStep);
|
|
136
|
+
await runCommand({
|
|
137
|
+
command: `git clone ${AWP_WALLET_REPOSITORY_URL} ${clonePath}`,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
currentStep = INSTALL_STEPS[2];
|
|
141
|
+
input.onStep?.(currentStep);
|
|
142
|
+
await runCommand({
|
|
143
|
+
command: "bash install.sh",
|
|
144
|
+
cwd: clonePath,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const addressOutput = await runCommand({
|
|
148
|
+
command: WALLET_ADDRESS_COMMAND,
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
walletAddress = parseWalletAddress(addressOutput ?? "");
|
|
152
|
+
} catch (error) {
|
|
153
|
+
if (error instanceof InstallWalletError) {
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const message = error instanceof Error ? error.message : "Wallet installation failed.";
|
|
158
|
+
|
|
159
|
+
throw new InstallWalletError(currentStep, message);
|
|
160
|
+
} finally {
|
|
161
|
+
if (temporaryDirectory) {
|
|
162
|
+
input.onStep?.(INSTALL_STEPS[3]);
|
|
163
|
+
await removeDirectory(temporaryDirectory, {
|
|
164
|
+
force: true,
|
|
165
|
+
recursive: true,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
walletAddress,
|
|
172
|
+
};
|
|
173
|
+
};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { stdin as defaultStdin, stdout as defaultStdout } from "node:process";
|
|
2
|
+
|
|
3
|
+
import ora from "ora";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
INIT_BANNER,
|
|
7
|
+
INITIAL_INIT_STATE,
|
|
8
|
+
applyNumberedMenuChoice,
|
|
9
|
+
beginWalletInstall,
|
|
10
|
+
completeInit,
|
|
11
|
+
failInit,
|
|
12
|
+
formatWalletFundingMessage,
|
|
13
|
+
} from "./state.ts";
|
|
14
|
+
|
|
15
|
+
export const ORA_SPINNER_NAME = "sand";
|
|
16
|
+
|
|
17
|
+
type Reader = {
|
|
18
|
+
off: (event: "data", listener: (chunk: Buffer | string) => void) => void;
|
|
19
|
+
on: (event: "data", listener: (chunk: Buffer | string) => void) => void;
|
|
20
|
+
resume: () => void;
|
|
21
|
+
setEncoding: (encoding: BufferEncoding) => void;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
type Writer = typeof defaultStdout;
|
|
25
|
+
|
|
26
|
+
const readNumberedChoice = async (stdin: Reader): Promise<string> => {
|
|
27
|
+
stdin.setEncoding("utf8");
|
|
28
|
+
stdin.resume();
|
|
29
|
+
|
|
30
|
+
return new Promise<string>((resolve) => {
|
|
31
|
+
const onData = (chunk: Buffer | string) => {
|
|
32
|
+
const value = chunk.toString().trim();
|
|
33
|
+
|
|
34
|
+
if (!value) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
stdin.off("data", onData);
|
|
39
|
+
resolve(value[0] ?? value);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
stdin.on("data", onData);
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const runOraInitUi = async (input: {
|
|
47
|
+
installWallet: (
|
|
48
|
+
callback: (step: string) => void,
|
|
49
|
+
) => Promise<{ walletAddress: string }>;
|
|
50
|
+
stdin?: Reader;
|
|
51
|
+
stdout?: Writer;
|
|
52
|
+
}): Promise<{
|
|
53
|
+
exitCode: number;
|
|
54
|
+
selectedOption: "skip" | "wallet";
|
|
55
|
+
}> => {
|
|
56
|
+
const stdin = input.stdin ?? defaultStdin;
|
|
57
|
+
const stdout = input.stdout ?? defaultStdout;
|
|
58
|
+
|
|
59
|
+
stdout.write(`${INIT_BANNER}\n${INITIAL_INIT_STATE.prompt}\n`);
|
|
60
|
+
|
|
61
|
+
while (true) {
|
|
62
|
+
const answer = await readNumberedChoice(stdin);
|
|
63
|
+
const selectedState = applyNumberedMenuChoice(INITIAL_INIT_STATE, answer);
|
|
64
|
+
|
|
65
|
+
if (!selectedState) {
|
|
66
|
+
stdout.write("Enter 1 or 2.\n");
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (selectedState.selectedOption === "skip") {
|
|
71
|
+
const completed = completeInit(selectedState, "Skipped wallet setup.");
|
|
72
|
+
|
|
73
|
+
stdout.write(`${completed.currentStep}\n${completed.message}\n`);
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
exitCode: 0,
|
|
77
|
+
selectedOption: "skip",
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const runningState = beginWalletInstall(selectedState);
|
|
82
|
+
const spinner = ora({
|
|
83
|
+
spinner: ORA_SPINNER_NAME,
|
|
84
|
+
stream: stdout,
|
|
85
|
+
text: runningState.currentStep,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
spinner.start();
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const wallet = await input.installWallet((step) => {
|
|
92
|
+
spinner.text = step;
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const completed = completeInit(
|
|
96
|
+
runningState,
|
|
97
|
+
formatWalletFundingMessage(wallet.walletAddress),
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
spinner.succeed(completed.currentStep);
|
|
101
|
+
stdout.write(`${completed.message}\n`);
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
exitCode: 0,
|
|
105
|
+
selectedOption: "wallet",
|
|
106
|
+
};
|
|
107
|
+
} catch (error) {
|
|
108
|
+
const message = error instanceof Error ? error.message : "Wallet installation failed.";
|
|
109
|
+
const failed = failInit(runningState, message);
|
|
110
|
+
const step =
|
|
111
|
+
error instanceof Error && "step" in error && typeof error.step === "string"
|
|
112
|
+
? error.step
|
|
113
|
+
: runningState.currentStep;
|
|
114
|
+
|
|
115
|
+
spinner.fail(failed.currentStep);
|
|
116
|
+
stdout.write(`${step}\n${failed.message}\n`);
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
exitCode: 1,
|
|
120
|
+
selectedOption: "wallet",
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { stdin as defaultStdin, stdout as defaultStdout } from "node:process";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
INIT_BANNER,
|
|
5
|
+
INITIAL_INIT_STATE,
|
|
6
|
+
applyNumberedMenuChoice,
|
|
7
|
+
beginWalletInstall,
|
|
8
|
+
completeInit,
|
|
9
|
+
failInit,
|
|
10
|
+
formatWalletFundingMessage,
|
|
11
|
+
} from "./state.ts";
|
|
12
|
+
|
|
13
|
+
type Reader = {
|
|
14
|
+
on: (event: "data", listener: (chunk: Buffer | string) => void) => void;
|
|
15
|
+
off: (event: "data", listener: (chunk: Buffer | string) => void) => void;
|
|
16
|
+
resume: () => void;
|
|
17
|
+
setEncoding: (encoding: BufferEncoding) => void;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type Writer = {
|
|
21
|
+
write: (chunk: string) => void;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const readNumberedChoice = async (stdin: Reader): Promise<string> => {
|
|
25
|
+
stdin.setEncoding("utf8");
|
|
26
|
+
stdin.resume();
|
|
27
|
+
|
|
28
|
+
return new Promise<string>((resolve) => {
|
|
29
|
+
const onData = (chunk: Buffer | string) => {
|
|
30
|
+
const value = chunk.toString().trim();
|
|
31
|
+
|
|
32
|
+
if (!value) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
stdin.off("data", onData);
|
|
37
|
+
resolve(value[0] ?? value);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
stdin.on("data", onData);
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const runPlainInitUi = async (input: {
|
|
45
|
+
installWallet: (
|
|
46
|
+
callback: (step: string) => void,
|
|
47
|
+
) => Promise<{ walletAddress: string }>;
|
|
48
|
+
stdin?: Reader;
|
|
49
|
+
stdout?: Writer;
|
|
50
|
+
}): Promise<{
|
|
51
|
+
exitCode: number;
|
|
52
|
+
selectedOption: "skip" | "wallet";
|
|
53
|
+
}> => {
|
|
54
|
+
const stdin = input.stdin ?? defaultStdin;
|
|
55
|
+
const stdout = input.stdout ?? defaultStdout;
|
|
56
|
+
|
|
57
|
+
stdout.write(`${INIT_BANNER}\n${INITIAL_INIT_STATE.prompt}\n`);
|
|
58
|
+
|
|
59
|
+
while (true) {
|
|
60
|
+
const answer = await readNumberedChoice(stdin);
|
|
61
|
+
const selectedState = applyNumberedMenuChoice(INITIAL_INIT_STATE, answer);
|
|
62
|
+
|
|
63
|
+
if (!selectedState) {
|
|
64
|
+
stdout.write("Enter 1 or 2.\n");
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (selectedState.selectedOption === "skip") {
|
|
69
|
+
const completed = completeInit(selectedState, "Skipped wallet setup.");
|
|
70
|
+
|
|
71
|
+
stdout.write(`${completed.currentStep}\n${completed.message}\n`);
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
exitCode: 0,
|
|
75
|
+
selectedOption: "skip",
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const runningState = beginWalletInstall(selectedState);
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
const wallet = await input.installWallet((step) => {
|
|
83
|
+
stdout.write(`${step}\n`);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const completed = completeInit(
|
|
87
|
+
runningState,
|
|
88
|
+
formatWalletFundingMessage(wallet.walletAddress),
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
stdout.write(`${completed.currentStep}\n${completed.message}\n`);
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
exitCode: 0,
|
|
95
|
+
selectedOption: "wallet",
|
|
96
|
+
};
|
|
97
|
+
} catch (error) {
|
|
98
|
+
const message = error instanceof Error ? error.message : "Wallet installation failed.";
|
|
99
|
+
const failed = failInit(runningState, message);
|
|
100
|
+
const step =
|
|
101
|
+
error instanceof Error && "step" in error && typeof error.step === "string"
|
|
102
|
+
? error.step
|
|
103
|
+
: runningState.currentStep;
|
|
104
|
+
|
|
105
|
+
stdout.write(`${failed.currentStep}\n${step}\n${failed.message}\n`);
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
exitCode: 1,
|
|
109
|
+
selectedOption: "wallet",
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
export const INIT_BANNER = ` ___ __ _____ __
|
|
2
|
+
/ | ____ ____ ____ / /_ / ___// /_____ ________
|
|
3
|
+
/ /| |/ __ \`/ _ \\/ __ \\/ __/ \\__ \\/ __/ __ \\/ ___/ _ \\
|
|
4
|
+
/ ___ / /_/ / __/ / / / /_ ___/ / /_/ /_/ / / / __/
|
|
5
|
+
/_/ |_|\\__, /\\___/_/ /_/\\__/ /____/\\__/\\____/_/ \\___/
|
|
6
|
+
/____/ `;
|
|
7
|
+
export const INIT_PROMPT = "Setup Wallet:\n\n1. Agent Wallet\n2. Skip";
|
|
8
|
+
export const INSTALL_STEPS = [
|
|
9
|
+
"Checking prerequisites",
|
|
10
|
+
"Cloning awp-wallet",
|
|
11
|
+
"Running install.sh",
|
|
12
|
+
"Cleaning up",
|
|
13
|
+
] as const;
|
|
14
|
+
|
|
15
|
+
export type InitChoice = "wallet" | "skip";
|
|
16
|
+
export type InitPhase = "menu" | "installing" | "completed" | "failed";
|
|
17
|
+
export type InitStatus = "idle" | "selected" | "running" | "completed" | "failed";
|
|
18
|
+
|
|
19
|
+
export type InitState = {
|
|
20
|
+
phase: InitPhase;
|
|
21
|
+
prompt: string;
|
|
22
|
+
selectedOption: InitChoice | null;
|
|
23
|
+
status: InitStatus;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type RunningInitState = InitState & {
|
|
27
|
+
currentStep: (typeof INSTALL_STEPS)[number];
|
|
28
|
+
phase: "installing";
|
|
29
|
+
selectedOption: "wallet";
|
|
30
|
+
status: "running";
|
|
31
|
+
steps: readonly string[];
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type TerminalInitState = (RunningInitState | InitState) & {
|
|
35
|
+
currentStep: "Completed" | "Failed";
|
|
36
|
+
message: string;
|
|
37
|
+
phase: "completed" | "failed";
|
|
38
|
+
status: "completed" | "failed";
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const INITIAL_INIT_STATE: InitState = {
|
|
42
|
+
phase: "menu",
|
|
43
|
+
prompt: INIT_PROMPT,
|
|
44
|
+
selectedOption: null,
|
|
45
|
+
status: "idle",
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const formatWalletFundingMessage = (walletAddress: string): string =>
|
|
49
|
+
`Your wallet address is ${walletAddress}. Fund this address with some USDC so your agent can independently purchase the resources it needs.`;
|
|
50
|
+
|
|
51
|
+
export const applyNumberedMenuChoice = (
|
|
52
|
+
state: InitState,
|
|
53
|
+
input: string,
|
|
54
|
+
): InitState | null => {
|
|
55
|
+
const normalized = input.trim();
|
|
56
|
+
|
|
57
|
+
if (normalized === "1") {
|
|
58
|
+
return {
|
|
59
|
+
...state,
|
|
60
|
+
selectedOption: "wallet",
|
|
61
|
+
status: "selected",
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (normalized === "2") {
|
|
66
|
+
return {
|
|
67
|
+
...state,
|
|
68
|
+
selectedOption: "skip",
|
|
69
|
+
status: "selected",
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return null;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const beginWalletInstall = (state: InitState): RunningInitState => ({
|
|
77
|
+
...state,
|
|
78
|
+
currentStep: INSTALL_STEPS[0],
|
|
79
|
+
phase: "installing",
|
|
80
|
+
selectedOption: "wallet",
|
|
81
|
+
status: "running",
|
|
82
|
+
steps: INSTALL_STEPS,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
export const completeInit = (
|
|
86
|
+
state: InitState | RunningInitState,
|
|
87
|
+
message: string,
|
|
88
|
+
): TerminalInitState => ({
|
|
89
|
+
...state,
|
|
90
|
+
currentStep: "Completed",
|
|
91
|
+
message,
|
|
92
|
+
phase: "completed",
|
|
93
|
+
status: "completed",
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
export const failInit = (
|
|
97
|
+
state: InitState | RunningInitState,
|
|
98
|
+
message: string,
|
|
99
|
+
): TerminalInitState => ({
|
|
100
|
+
...state,
|
|
101
|
+
currentStep: "Failed",
|
|
102
|
+
message,
|
|
103
|
+
phase: "failed",
|
|
104
|
+
status: "failed",
|
|
105
|
+
});
|
package/src/main.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { runInitCommand } from "./commands/init.ts";
|
|
2
|
+
|
|
3
|
+
const HELP_TEXT = `agent-store
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
agent-store init
|
|
7
|
+
agent-store --help`;
|
|
8
|
+
|
|
9
|
+
export const main = async (argv: string[]): Promise<number> => {
|
|
10
|
+
const [command, ...rest] = argv;
|
|
11
|
+
|
|
12
|
+
if (!command || command === "--help" || command === "-h") {
|
|
13
|
+
process.stdout.write(`${HELP_TEXT}\n`);
|
|
14
|
+
return 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (command === "init") {
|
|
18
|
+
if (rest[0] === "--help" || rest[0] === "-h") {
|
|
19
|
+
process.stdout.write("Usage: agent-store init\n");
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return runInitCommand();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
process.stderr.write(`Unknown command: ${command}\n`);
|
|
27
|
+
process.stdout.write(`${HELP_TEXT}\n`);
|
|
28
|
+
return 1;
|
|
29
|
+
};
|