@agentgrant.cash/cli 1.4.7 → 1.5.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.
@@ -72,6 +72,55 @@ export function registerAgent(program) {
72
72
  });
73
73
  emit(ctx, { result: data }, () => ui.green("✓ Done."));
74
74
  });
75
+ program
76
+ .command("do-task <query>")
77
+ .description("Run any pay-per-use task from a plain-language request (the backend picks + pays the vendor)")
78
+ .option("-i, --input <json>", "structured input for the task, as JSON")
79
+ .option("--confirm", "confirm a spend the backend flagged as needing approval")
80
+ .action(async (query, opts, cmd) => {
81
+ const ctx = buildContext(cmd);
82
+ if (!ctx.agent.connected)
83
+ throw new NotConnectedError("agent");
84
+ let input;
85
+ if (opts.input) {
86
+ try {
87
+ input = JSON.parse(String(opts.input));
88
+ }
89
+ catch {
90
+ throw new Error("--input must be valid JSON.");
91
+ }
92
+ }
93
+ const data = await ctx.agent.doTask({
94
+ query,
95
+ ...(input !== undefined ? { input } : {}),
96
+ ...(opts.confirm ? { confirm: true } : {}),
97
+ });
98
+ emit(ctx, { result: data }, () => `${ui.title("Task")} ${ui.dim("(use --json for the full result)")}`);
99
+ });
100
+ program
101
+ .command("best-vendor <capability>")
102
+ .description("See the ranked vendors for a capability, top pick first (no charge)")
103
+ .option("--include-untested", "also surface unverified vendors, flagged untested")
104
+ .action(async (capability, opts, cmd) => {
105
+ const ctx = buildContext(cmd);
106
+ if (!ctx.agent.connected)
107
+ throw new NotConnectedError("agent");
108
+ const data = await ctx.agent.bestVendor({
109
+ capability,
110
+ ...(opts.includeUntested ? { includeUntested: true } : {}),
111
+ });
112
+ emit(ctx, { result: data }, () => `${ui.title("Vendors")} ${ui.dim("(use --json for the ranking)")}`);
113
+ });
114
+ program
115
+ .command("find-capability <query>")
116
+ .description("Match a plain-language request to the capabilities the agent can run (no charge)")
117
+ .action(async (query, _opts, cmd) => {
118
+ const ctx = buildContext(cmd);
119
+ if (!ctx.agent.connected)
120
+ throw new NotConnectedError("agent");
121
+ const data = await ctx.agent.findCapability(query);
122
+ emit(ctx, { result: data }, () => `${ui.title("Capabilities")} ${ui.dim("(use --json for the matches)")}`);
123
+ });
75
124
  program
76
125
  .command("discover <origin>")
77
126
  .alias("add")
@@ -5,6 +5,35 @@ export interface AgentClientOpts {
5
5
  auth?: TokenHolder;
6
6
  fetchImpl?: typeof fetch;
7
7
  }
8
+ /**
9
+ * The backend's `NamedFunctionResult` (POST /do-task), returned VERBATIM. The
10
+ * client is a thin caller — it never re-implements selection/failover/refund;
11
+ * the money-safe engine owns those and encodes its outcome in `status`. A driving
12
+ * agent keys off `status` (`settlement_pending` = still confirming, don't re-run;
13
+ * `blocked` + `code` = terminal, stop). `data` shape varies by provider.
14
+ */
15
+ export interface NamedFunctionResult {
16
+ status: "ok" | "needs_input" | "no_vendor" | "all_failed" | "settlement_pending" | "unknown_function" | "blocked";
17
+ [k: string]: unknown;
18
+ }
19
+ /** One ranked vendor for a capability (GET /agent/best-vendor). */
20
+ export interface VendorPick {
21
+ slug: string;
22
+ name: string;
23
+ priceMinor: string;
24
+ url?: string;
25
+ method?: string;
26
+ asset?: string;
27
+ untested?: boolean;
28
+ [k: string]: unknown;
29
+ }
30
+ /** Ranked vendors + top pick for a capability (GET /agent/best-vendor). */
31
+ export interface VendorSelectionResult {
32
+ capability: string;
33
+ vendors: VendorPick[];
34
+ best: VendorPick | null;
35
+ message: string;
36
+ }
8
37
  export declare class AgentClient {
9
38
  private base;
10
39
  private auth?;
@@ -40,6 +69,19 @@ export declare class AgentClient {
40
69
  tx(id: string): Promise<Record<string, unknown>>;
41
70
  /** Exact POST /x402/pay contract for a catalog entry by slug (requestSchema + price). No spend. */
42
71
  schema(slug: string): Promise<Record<string, unknown>>;
72
+ /**
73
+ * Ranked vendors for a capability (`GET /agent/best-vendor`). Reads only — no
74
+ * spend. `includeUntested` opts in 'probed' vendors ranked below every verified
75
+ * one and flagged `untested`; omit it to route only execution-verified vendors.
76
+ */
77
+ bestVendor(b: {
78
+ capability: string;
79
+ includeUntested?: boolean;
80
+ }): Promise<VendorSelectionResult>;
81
+ /** Free-text capability match (`GET /agent/find-capability`). Reads only — no spend. */
82
+ findCapability(query: string): Promise<{
83
+ matches: unknown[];
84
+ }>;
43
85
  /** Ingest any x402 origin's endpoints into the catalog so they become searchable/payable. */
44
86
  discover(origin: string): Promise<Record<string, unknown>>;
45
87
  /** Claim an invite / bonus credit by code. Mints or tops up the session's spendable funds. */
@@ -50,6 +92,19 @@ export declare class AgentClient {
50
92
  code: string;
51
93
  expiresAt: number;
52
94
  }>;
95
+ /**
96
+ * One-shot natural-language task (`POST /do-task`): the backend resolves the
97
+ * query to the best vendor, validates input, pays under the session guardrails,
98
+ * and fails over — all server-side. Returns the `NamedFunctionResult` VERBATIM
99
+ * (including demote/refund/stop outcomes); the client never re-implements the
100
+ * engine. An `Idempotency-Key` guards the write path against a double-charge on
101
+ * retry; a transport error is tagged `recoverable` exactly like {@link fetchPay}.
102
+ */
103
+ doTask(b: {
104
+ query: string;
105
+ input?: Record<string, unknown>;
106
+ confirm?: boolean;
107
+ }): Promise<NamedFunctionResult>;
53
108
  /**
54
109
  * Pay + run an endpoint via the session. Body matches `POST /x402/pay`'s
55
110
  * schema: `method` is required (uppercased), `expectedPriceMinor` (the spend
@@ -142,6 +142,22 @@ export class AgentClient {
142
142
  schema(slug) {
143
143
  return this.request("GET", `/marketplace/x402/${encodeURIComponent(slug)}`, { auth: true });
144
144
  }
145
+ /**
146
+ * Ranked vendors for a capability (`GET /agent/best-vendor`). Reads only — no
147
+ * spend. `includeUntested` opts in 'probed' vendors ranked below every verified
148
+ * one and flagged `untested`; omit it to route only execution-verified vendors.
149
+ */
150
+ bestVendor(b) {
151
+ const p = new URLSearchParams({ capability: b.capability });
152
+ if (b.includeUntested)
153
+ p.set("includeUntested", "true");
154
+ return this.request("GET", `/agent/best-vendor?${p}`, { auth: true });
155
+ }
156
+ /** Free-text capability match (`GET /agent/find-capability`). Reads only — no spend. */
157
+ findCapability(query) {
158
+ const p = new URLSearchParams({ query });
159
+ return this.request("GET", `/agent/find-capability?${p}`, { auth: true });
160
+ }
145
161
  // ── catalog + account management ──
146
162
  /** Ingest any x402 origin's endpoints into the catalog so they become searchable/payable. */
147
163
  discover(origin) {
@@ -162,6 +178,25 @@ export class AgentClient {
162
178
  return this.request("POST", "/account/link-code", { body: {}, auth: true });
163
179
  }
164
180
  // ── spends (session-owned, guardrailed) ──
181
+ /**
182
+ * One-shot natural-language task (`POST /do-task`): the backend resolves the
183
+ * query to the best vendor, validates input, pays under the session guardrails,
184
+ * and fails over — all server-side. Returns the `NamedFunctionResult` VERBATIM
185
+ * (including demote/refund/stop outcomes); the client never re-implements the
186
+ * engine. An `Idempotency-Key` guards the write path against a double-charge on
187
+ * retry; a transport error is tagged `recoverable` exactly like {@link fetchPay}.
188
+ */
189
+ doTask(b) {
190
+ return this.request("POST", "/do-task", {
191
+ body: {
192
+ query: b.query,
193
+ ...(b.input !== undefined ? { input: b.input } : {}),
194
+ ...(b.confirm !== undefined ? { confirm: b.confirm } : {}),
195
+ },
196
+ auth: true,
197
+ idempotent: true,
198
+ });
199
+ }
165
200
  /**
166
201
  * Pay + run an endpoint via the session. Body matches `POST /x402/pay`'s
167
202
  * schema: `method` is required (uppercased), `expectedPriceMinor` (the spend
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentgrant.cash/cli",
3
- "version": "1.4.7",
3
+ "version": "1.5.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
  "main": "./dist/lib/index.js",