@agentgrant.cash/cli 1.1.0 → 1.2.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.
|
@@ -141,7 +141,7 @@ async function gatherExtras(ctx) {
|
|
|
141
141
|
}
|
|
142
142
|
async function gather(cmd) {
|
|
143
143
|
const ctx = buildContext(cmd);
|
|
144
|
-
const [prefsR, moneyR, extrasR, agentR] = await Promise.allSettled([
|
|
144
|
+
const [prefsR, moneyR, extrasR, agentR, creditR] = await Promise.allSettled([
|
|
145
145
|
ctx.money.connected ? loadDisplayPrefs(ctx) : Promise.resolve(DEFAULT_PREFS),
|
|
146
146
|
ctx.money.connected
|
|
147
147
|
? ctx.money.getPortfolio("full")
|
|
@@ -150,6 +150,9 @@ async function gather(cmd) {
|
|
|
150
150
|
ctx.agent.connected
|
|
151
151
|
? ctx.agent.balance()
|
|
152
152
|
: Promise.resolve(null),
|
|
153
|
+
ctx.agent.connected
|
|
154
|
+
? ctx.agent.credit()
|
|
155
|
+
: Promise.resolve(null),
|
|
153
156
|
]);
|
|
154
157
|
return {
|
|
155
158
|
ctx,
|
|
@@ -159,6 +162,7 @@ async function gather(cmd) {
|
|
|
159
162
|
moneyFailed: moneyR.status === "rejected",
|
|
160
163
|
agent: agentR.status === "fulfilled" ? agentR.value : null,
|
|
161
164
|
agentFailed: agentR.status === "rejected",
|
|
165
|
+
credit: creditR.status === "fulfilled" ? creditR.value : null,
|
|
162
166
|
};
|
|
163
167
|
}
|
|
164
168
|
/** Indent every line of a block by two spaces. */
|
|
@@ -171,7 +175,7 @@ function indent(block) {
|
|
|
171
175
|
export function registerPortfolio(program) {
|
|
172
176
|
const run = async (cmd) => {
|
|
173
177
|
const g = await gather(cmd);
|
|
174
|
-
const { ctx, prefs, money, extras, moneyFailed, agent, agentFailed } = g;
|
|
178
|
+
const { ctx, prefs, money, extras, moneyFailed, agent, agentFailed, credit } = g;
|
|
175
179
|
emit(ctx, {
|
|
176
180
|
investments: money
|
|
177
181
|
? {
|
|
@@ -186,6 +190,8 @@ export function registerPortfolio(program) {
|
|
|
186
190
|
}
|
|
187
191
|
: null,
|
|
188
192
|
spending: agent,
|
|
193
|
+
// The free-credit / wallet split (parity with the app's Spending screen).
|
|
194
|
+
credit,
|
|
189
195
|
}, () => {
|
|
190
196
|
if (!ctx.money.connected && !ctx.agent.connected)
|
|
191
197
|
return "Not connected yet. Run `grant login`.";
|
|
@@ -208,7 +214,7 @@ export function registerPortfolio(program) {
|
|
|
208
214
|
lines.push(ui.dim(" Not connected."));
|
|
209
215
|
}
|
|
210
216
|
else if (agent) {
|
|
211
|
-
lines.push(formatAgentFunds(agent));
|
|
217
|
+
lines.push(formatAgentFunds(agent, credit));
|
|
212
218
|
}
|
|
213
219
|
else {
|
|
214
220
|
lines.push(ui.amber(` ${agentFailed ? "Temporarily unavailable." : "—"}`));
|
package/dist/lib/agent-client.js
CHANGED
|
@@ -74,6 +74,15 @@ export class AgentClient {
|
|
|
74
74
|
balance() {
|
|
75
75
|
return this.request("GET", "/balance", { auth: true });
|
|
76
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* The chain-agnostic spendable split — sign-up free credit + funds you added +
|
|
79
|
+
* total. Hits `GET /credit` (dual-auth, so the api-key works). This is the same
|
|
80
|
+
* figure the app shows on the Spending screen; `balance()` (/balance) carries
|
|
81
|
+
* the session status, so the portfolio uses both.
|
|
82
|
+
*/
|
|
83
|
+
credit() {
|
|
84
|
+
return this.request("GET", "/credit", { auth: true });
|
|
85
|
+
}
|
|
77
86
|
/**
|
|
78
87
|
* Find a payable endpoint in the curated catalog. Hits `GET /marketplace/x402`
|
|
79
88
|
* (the grouped, public catalog route) — NOT `/marketplace`, which does not
|
|
@@ -189,8 +189,15 @@ function usdcMinorPlain(minor) {
|
|
|
189
189
|
const n = Number(minor) / 1e6;
|
|
190
190
|
return `$${n.toFixed(n !== 0 && Math.abs(n) < 0.01 ? 4 : 2)}`;
|
|
191
191
|
}
|
|
192
|
-
/**
|
|
193
|
-
|
|
192
|
+
/**
|
|
193
|
+
* Render the agent (spending) funds block as indented lines (no section title).
|
|
194
|
+
*
|
|
195
|
+
* When the chain-agnostic `credit` read (GET /credit) is supplied, we render the
|
|
196
|
+
* full split — total spendable, the sign-up free credit, and (if the user has
|
|
197
|
+
* funded a wallet) the funds they added — for parity with the app. Without it we
|
|
198
|
+
* fall back to the `/balance` status shape (USDC/USDT or sign-up-credit total).
|
|
199
|
+
*/
|
|
200
|
+
export function formatAgentFunds(bal, credit) {
|
|
194
201
|
const status = bal.status;
|
|
195
202
|
if (status === "not_set_up" || status === "no_active_session") {
|
|
196
203
|
return [
|
|
@@ -203,10 +210,22 @@ export function formatAgentFunds(bal) {
|
|
|
203
210
|
}
|
|
204
211
|
if (status === "credit_exhausted") {
|
|
205
212
|
return [
|
|
206
|
-
` Sign-up credit used up — balance ${usdcMinorPlain(bal.totalMinor)}`,
|
|
213
|
+
` Sign-up credit used up — balance ${usdcMinorPlain(bal.totalMinor ?? credit?.totalMinor)}`,
|
|
207
214
|
" Add funds to keep spending (`grant fetch`/`grant transfer` need a balance).",
|
|
208
215
|
].join("\n");
|
|
209
216
|
}
|
|
217
|
+
// Prefer the chain-agnostic credit split (free credit + funds you added) when
|
|
218
|
+
// available — this is the same figure the app shows on the Spending screen.
|
|
219
|
+
if (credit && credit.totalMinor !== undefined) {
|
|
220
|
+
const lines = [` Spendable: ${usdcMinorPlain(credit.totalMinor)}`];
|
|
221
|
+
lines.push(` Free credit: ${usdcMinorPlain(credit.grantMinor)}`);
|
|
222
|
+
if (credit.walletMinor !== undefined) {
|
|
223
|
+
lines.push(` Your wallet: ${usdcMinorPlain(credit.walletMinor)}`);
|
|
224
|
+
}
|
|
225
|
+
if (bal.address)
|
|
226
|
+
lines.push(` Address: ${bal.address}`);
|
|
227
|
+
return lines.join("\n");
|
|
228
|
+
}
|
|
210
229
|
// active. A funded on-chain session carries live USDC/USDT; a grant-only user
|
|
211
230
|
// carries the chain-agnostic sign-up credit total in minor units.
|
|
212
231
|
if (bal.USDC !== undefined || bal.USDT !== undefined) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentgrant.cash/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Grant Cash — one CLI for your money (gold) and your agent (pay-per-use services). Routes to the Perfolio backend and the Agent-mode backend behind a single, plain-language surface.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -126,10 +126,18 @@ Every **cash** amount is in the user's display currency — a bare `50` means
|
|
|
126
126
|
- `grant schema <slug>` — the exact pay contract for a catalogued service (no charge).
|
|
127
127
|
- `grant fetch <url> [-m POST] [-b '<json>'] [--price <amount>] [--asset USDC|USDT]` (alias `pay`) — pay for and run a service.
|
|
128
128
|
- `grant transfer <recipient> <amount>` — send money to an address.
|
|
129
|
+
- `grant spending deposit --amount <cash>` (aliases `add`, `top-up`) — move cash from the Investments side into the Spending balance (the agent's pay-per-use money). Amount is in the user's currency — a bare `50` means ₹50 for an INR user, $50 for a USD user. Funds land a few minutes after submitting. There is no reverse: Spending is funded from cash, not the other way around.
|
|
129
130
|
- `grant redeem <code>` — claim an invite or bonus credit toward spending.
|
|
130
131
|
- `grant upgrade` — get a one-time link to secure a full account and add spending funds.
|
|
131
132
|
- `grant revoke` (alias `stop`) — stop all agent spending immediately.
|
|
132
133
|
|
|
134
|
+
**Keeping Spending funded (assistant guidance).** The Spending balance only goes down as the agent pays for services — top it up from the user's cash with `grant spending deposit`:
|
|
135
|
+
- **User asks explicitly** ("move ₹2,000 to spending", "top up my spending balance") → run `grant spending deposit --amount <cash>` directly. No need to ask again.
|
|
136
|
+
- **Running low** (a paid action is about to exceed — or only barely fits — the remaining Spending balance) → before paying, tell the user the balance is low and ask whether to transfer some cash over first. Don't transfer without a yes.
|
|
137
|
+
- **Empty / zero balance** (a `grant fetch`/pay fails for lack of funds, or `grant portfolio` shows Spending at 0) → tell the user their Spending account is empty and suggest moving some money in, **quoted in their local currency** — e.g. *"Your spending balance is empty — shall I move ₹2,000 (≈ $24) over from your cash?"* Then, on confirmation, run `grant spending deposit`.
|
|
138
|
+
|
|
139
|
+
Always state amounts in the user's display currency (never raw USD/USDT or chains), and only transfer proactively after the user agrees — an explicit request is the go-ahead; a low/empty balance is a prompt to ask.
|
|
140
|
+
|
|
133
141
|
### Transactions & self-orientation
|
|
134
142
|
- `grant tx status <txHash>` — check whether a transaction confirmed. `grant tx history [--limit <n>]` — recent transactions.
|
|
135
143
|
- `grant session status` / `grant session grant` — your agent-access (session) status and how to enable it.
|
|
@@ -164,6 +172,7 @@ grant polymarket bet 0x1234 --side yes --amount 25 # bet $25 on "yes"
|
|
|
164
172
|
grant search "web search" --limit 5 # find a live service (Spending)
|
|
165
173
|
grant check https://api.example.com/run # what it costs + needs, no charge
|
|
166
174
|
grant fetch https://api.example.com/run -b '{"q":"gold news today"}' # pay + run
|
|
175
|
+
grant spending deposit --amount 25 # move $25 of cash into Spending
|
|
167
176
|
grant activity --json # full combined history
|
|
168
177
|
grant revoke # stop all agent spending
|
|
169
178
|
```
|