@clawcard/cli 1.1.1 → 1.1.4
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/package.json +1 -1
- package/src/commands/help.js +3 -0
- package/src/commands/keys.js +44 -10
- package/src/commands/signup.js +36 -16
- package/src/index.js +66 -22
package/package.json
CHANGED
package/src/commands/help.js
CHANGED
|
@@ -11,6 +11,9 @@ const COMMANDS = [
|
|
|
11
11
|
[" logout", "Clear session"],
|
|
12
12
|
[" whoami", "Show current account"],
|
|
13
13
|
["", ""],
|
|
14
|
+
[orange.bold("Agent"), ""],
|
|
15
|
+
[" agent", "Show your agent's identity"],
|
|
16
|
+
["", ""],
|
|
14
17
|
[orange.bold("Keys"), ""],
|
|
15
18
|
[" keys", "Interactive key management"],
|
|
16
19
|
[" keys create", "Create a new API key"],
|
package/src/commands/keys.js
CHANGED
|
@@ -102,16 +102,15 @@ export async function keysCreateCommand() {
|
|
|
102
102
|
p.log.success("Copied to clipboard");
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
105
|
+
// Show provisioned resources
|
|
106
|
+
const details = [
|
|
107
|
+
`Name: ${orange.bold(result.name || "unnamed")}`,
|
|
108
|
+
result.email && `Email: ${result.email}`,
|
|
109
|
+
result.phone && `Phone: ${result.phone}`,
|
|
110
|
+
`Limit: $${(result.spendLimitCents / 100).toFixed(2)}`,
|
|
111
|
+
].filter(Boolean).join("\n");
|
|
112
|
+
|
|
113
|
+
p.note(details, "Your Agent");
|
|
115
114
|
} catch (err) {
|
|
116
115
|
s.stop("Failed to create key");
|
|
117
116
|
p.log.error(err.message);
|
|
@@ -209,6 +208,41 @@ export async function keysInfoCommand(keyIdOrPrefix) {
|
|
|
209
208
|
}
|
|
210
209
|
}
|
|
211
210
|
|
|
211
|
+
export async function agentStatusCommand() {
|
|
212
|
+
requireAuth();
|
|
213
|
+
|
|
214
|
+
const s = p.spinner();
|
|
215
|
+
s.start("Fetching agent...");
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
const agents = await listAgents();
|
|
219
|
+
const active = agents.filter((a) => a.status === "active");
|
|
220
|
+
|
|
221
|
+
if (!active.length) {
|
|
222
|
+
s.stop("");
|
|
223
|
+
p.log.info("No active agent. Create one with: clawcard keys create");
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const agent = await getAgent(active[0].id);
|
|
228
|
+
s.stop("");
|
|
229
|
+
|
|
230
|
+
const info = [
|
|
231
|
+
`Name: ${orange.bold(agent.name || "unnamed")}`,
|
|
232
|
+
`Key: ${chalk.dim(agent.keyPrefix + "...")}`,
|
|
233
|
+
`Email: ${agent.email || "-"}`,
|
|
234
|
+
`Phone: ${agent.phone || "-"}`,
|
|
235
|
+
`Limit: $${(agent.spendLimitCents / 100).toFixed(2)}`,
|
|
236
|
+
`Status: ${chalk.green("active")}`,
|
|
237
|
+
].join("\n");
|
|
238
|
+
|
|
239
|
+
p.note(info, "Your Agent");
|
|
240
|
+
} catch (err) {
|
|
241
|
+
s.stop("Failed");
|
|
242
|
+
p.log.error(err.message);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
212
246
|
export async function keysRevokeCommand() {
|
|
213
247
|
requireAuth();
|
|
214
248
|
|
package/src/commands/signup.js
CHANGED
|
@@ -45,33 +45,53 @@ export async function signupCommand() {
|
|
|
45
45
|
|
|
46
46
|
p.note(
|
|
47
47
|
[
|
|
48
|
-
`${orange.bold("Step 1:")}
|
|
49
|
-
` ${chalk.dim("$
|
|
48
|
+
`${orange.bold("Step 1:")} Top up your balance`,
|
|
49
|
+
` ${chalk.dim("Minimum $5 to get started")}`,
|
|
50
50
|
"",
|
|
51
|
-
`${orange.bold("Step 2:")}
|
|
52
|
-
` ${chalk.dim("
|
|
51
|
+
`${orange.bold("Step 2:")} Create your agent key`,
|
|
52
|
+
` ${chalk.dim("Gets you an email, phone number, and virtual cards")}`,
|
|
53
53
|
"",
|
|
54
|
-
`${orange.bold("Step 3:")}
|
|
55
|
-
` ${chalk.dim("
|
|
54
|
+
`${orange.bold("Step 3:")} Set up your agent`,
|
|
55
|
+
` ${chalk.dim("Installs the ClawCard skill for your agent")}`,
|
|
56
56
|
].join("\n"),
|
|
57
57
|
"Getting Started"
|
|
58
58
|
);
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
// Step 1: Top up
|
|
61
|
+
const topup = await p.confirm({
|
|
62
|
+
message: "Top up your balance now? (required to create an agent)",
|
|
62
63
|
});
|
|
63
64
|
|
|
64
|
-
if (!p.isCancel(
|
|
65
|
-
const {
|
|
66
|
-
await
|
|
65
|
+
if (!p.isCancel(topup) && topup) {
|
|
66
|
+
const { billingTopupCommand } = await import("./billing.js");
|
|
67
|
+
await billingTopupCommand();
|
|
67
68
|
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
p.log.info(chalk.dim("Complete the payment in your browser, then come back here."));
|
|
70
|
+
|
|
71
|
+
const ready = await p.confirm({
|
|
72
|
+
message: "Payment complete?",
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
if (p.isCancel(ready) || !ready) return;
|
|
76
|
+
|
|
77
|
+
// Step 2: Create key
|
|
78
|
+
const createKey = await p.confirm({
|
|
79
|
+
message: "Create your agent key now?",
|
|
70
80
|
});
|
|
71
81
|
|
|
72
|
-
if (!p.isCancel(
|
|
73
|
-
const {
|
|
74
|
-
await
|
|
82
|
+
if (!p.isCancel(createKey) && createKey) {
|
|
83
|
+
const { keysCreateCommand } = await import("./keys.js");
|
|
84
|
+
await keysCreateCommand();
|
|
85
|
+
|
|
86
|
+
// Step 3: Setup
|
|
87
|
+
const runSetup = await p.confirm({
|
|
88
|
+
message: "Set up your agent now?",
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
if (!p.isCancel(runSetup) && runSetup) {
|
|
92
|
+
const { setupCommand } = await import("./setup.js");
|
|
93
|
+
await setupCommand();
|
|
94
|
+
}
|
|
75
95
|
}
|
|
76
96
|
}
|
|
77
97
|
} catch (err) {
|
package/src/index.js
CHANGED
|
@@ -88,6 +88,15 @@ keys
|
|
|
88
88
|
await keysRevokeCommand();
|
|
89
89
|
});
|
|
90
90
|
|
|
91
|
+
// Agent status
|
|
92
|
+
program
|
|
93
|
+
.command("agent")
|
|
94
|
+
.description("Show your agent's identity (email, phone, key)")
|
|
95
|
+
.action(async () => {
|
|
96
|
+
const { agentStatusCommand } = await import("./commands/keys.js");
|
|
97
|
+
await agentStatusCommand();
|
|
98
|
+
});
|
|
99
|
+
|
|
91
100
|
// Setup
|
|
92
101
|
program
|
|
93
102
|
.command("setup")
|
|
@@ -177,28 +186,61 @@ if (process.argv.length <= 2) {
|
|
|
177
186
|
);
|
|
178
187
|
}
|
|
179
188
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
189
|
+
let options;
|
|
190
|
+
|
|
191
|
+
if (!loggedIn) {
|
|
192
|
+
options = [
|
|
193
|
+
{ value: "login", label: "Log in", hint: "authenticate via browser" },
|
|
194
|
+
{
|
|
195
|
+
value: "signup",
|
|
196
|
+
label: "Sign up",
|
|
197
|
+
hint: "create account with invite code",
|
|
198
|
+
},
|
|
199
|
+
{ value: "help", label: "Help", hint: "show all commands" },
|
|
200
|
+
];
|
|
201
|
+
} else {
|
|
202
|
+
// Check user state to show contextual nudges
|
|
203
|
+
let hasBalance = true;
|
|
204
|
+
let hasAgent = true;
|
|
205
|
+
|
|
206
|
+
try {
|
|
207
|
+
const { getBalance, listAgents } = await import("./api.js");
|
|
208
|
+
const [balance, agents] = await Promise.all([
|
|
209
|
+
getBalance().catch(() => ({ amountCents: 0 })),
|
|
210
|
+
listAgents().catch(() => []),
|
|
211
|
+
]);
|
|
212
|
+
hasBalance = balance.amountCents >= 500;
|
|
213
|
+
hasAgent = agents.some((a) => a.status === "active");
|
|
214
|
+
} catch {
|
|
215
|
+
// couldn't check — show full menu
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (!hasBalance) {
|
|
219
|
+
p.log.warn(
|
|
220
|
+
`You need at least $5 balance to create an agent. Run ${orange("clawcard billing topup")} to get started.`
|
|
221
|
+
);
|
|
222
|
+
} else if (!hasAgent) {
|
|
223
|
+
p.log.warn(
|
|
224
|
+
`You have balance but no agent yet. Run ${orange("clawcard keys create")} to create one.`
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
options = [
|
|
229
|
+
...(!hasBalance
|
|
230
|
+
? [{ value: "billing", label: "Top up balance", hint: "required — minimum $5 to get started" }]
|
|
231
|
+
: !hasAgent
|
|
232
|
+
? [{ value: "keys-create", label: "Create agent", hint: "you have balance — create your agent now" }]
|
|
233
|
+
: [{ value: "agent", label: "My Agent", hint: "email, phone, key details" }]),
|
|
234
|
+
...(hasAgent
|
|
235
|
+
? [{ value: "setup", label: "Setup", hint: "set up your agent" }]
|
|
236
|
+
: []),
|
|
237
|
+
{ value: "billing", label: "Billing", hint: "check balance & top up" },
|
|
238
|
+
{ value: "referral", label: "Referral", hint: "share & earn $5" },
|
|
239
|
+
{ value: "whoami", label: "Who am I?", hint: "show current account" },
|
|
240
|
+
{ value: "logout", label: "Logout", hint: "clear session" },
|
|
241
|
+
{ value: "help", label: "Help", hint: "show all commands" },
|
|
242
|
+
];
|
|
243
|
+
}
|
|
202
244
|
|
|
203
245
|
const action = await p.select({
|
|
204
246
|
message: "What would you like to do?",
|
|
@@ -215,6 +257,8 @@ if (process.argv.length <= 2) {
|
|
|
215
257
|
signup: () => import("./commands/signup.js").then((m) => m.signupCommand()),
|
|
216
258
|
logout: () => import("./commands/logout.js").then((m) => m.logoutCommand()),
|
|
217
259
|
whoami: () => import("./commands/whoami.js").then((m) => m.whoamiCommand()),
|
|
260
|
+
agent: () => import("./commands/keys.js").then((m) => m.agentStatusCommand()),
|
|
261
|
+
"keys-create": () => import("./commands/keys.js").then((m) => m.keysCreateCommand()),
|
|
218
262
|
keys: () => import("./commands/keys.js").then((m) => m.keysCommand()),
|
|
219
263
|
setup: () => import("./commands/setup.js").then((m) => m.setupCommand()),
|
|
220
264
|
billing: () =>
|