clawmoney 0.9.1 → 0.9.3

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.
@@ -16,6 +16,7 @@ interface CallOptions {
16
16
  skill: string;
17
17
  input?: string;
18
18
  timeout?: string;
19
+ pay?: boolean;
19
20
  }
20
21
  export declare function hubCallCommand(options: CallOptions): Promise<void>;
21
22
  interface RegisterOptions {
@@ -5,6 +5,7 @@ import chalk from "chalk";
5
5
  import ora from "ora";
6
6
  import { requireConfig } from "../utils/config.js";
7
7
  import { apiGet, apiPost } from "../utils/api.js";
8
+ import { awalExec } from "../utils/awal.js";
8
9
  import { readPid, isPidAlive, removePid } from "../hub/provider.js";
9
10
  const LOG_FILE = join(homedir(), ".clawmoney", "provider.log");
10
11
  // ── hub start ──
@@ -155,31 +156,86 @@ export async function hubCallCommand(options) {
155
156
  const timeout = options.timeout ? parseInt(options.timeout, 10) : 60;
156
157
  const spinner = ora(`Calling ${options.agent}/${options.skill}...`).start();
157
158
  try {
158
- // gateway/invoke takes agent_id, skill, timeout as query params; input_data as POST body
159
- const qs = new URLSearchParams({
160
- agent_id: options.agent,
161
- skill: options.skill,
162
- timeout: String(timeout),
163
- payment_method: "ledger",
164
- });
165
- const resp = await apiPost(`/api/v1/hub/gateway/invoke?${qs}`, inputData, config.api_key);
166
- if (!resp.ok) {
167
- const raw = resp.data && typeof resp.data === "object" && "detail" in resp.data
168
- ? resp.data.detail
169
- : resp.data;
170
- const detail = typeof raw === "string" ? raw : JSON.stringify(raw);
171
- spinner.fail(chalk.red(`Call failed (${resp.status}): ${detail}`));
172
- process.exit(1);
159
+ if (options.pay) {
160
+ // x402 payment flow via pay.clawmoney.ai Worker
161
+ // Step 1: Look up skill price
162
+ spinner.text = `Looking up price for ${options.agent}/${options.skill}...`;
163
+ const searchResp = await apiGet(`/api/v1/hub/skills/search?q=${encodeURIComponent(options.skill)}&agent_slug=${encodeURIComponent(options.agent)}&limit=1`);
164
+ const skills = searchResp.data?.data ?? [];
165
+ const skillPrice = skills[0]?.price ?? 0.01;
166
+ // Step 2: Pay via awal x402 → pay.clawmoney.ai Worker
167
+ spinner.text = `Paying $${skillPrice} USDC for ${options.agent}/${options.skill}...`;
168
+ const payUrl = `https://pay.clawmoney.ai/hub/${encodeURIComponent(options.agent)}/${encodeURIComponent(options.skill)}?price=${skillPrice}`;
169
+ let payResult;
170
+ try {
171
+ payResult = await awalExec(["x402", "pay", payUrl]);
172
+ }
173
+ catch (err) {
174
+ spinner.fail(chalk.red(`Payment failed: ${err.message}`));
175
+ process.exit(1);
176
+ }
177
+ // Extract payment_token from Worker response
178
+ const paymentToken = payResult.data?.payment_token;
179
+ if (!paymentToken) {
180
+ spinner.fail(chalk.red("Payment succeeded but no payment_token returned"));
181
+ console.error(chalk.dim(` Raw response: ${JSON.stringify(payResult.data).slice(0, 200)}`));
182
+ process.exit(1);
183
+ }
184
+ // Step 3: Invoke with payment_token
185
+ spinner.text = `Executing ${options.agent}/${options.skill}...`;
186
+ const qs = new URLSearchParams({
187
+ agent_id: options.agent,
188
+ skill: options.skill,
189
+ timeout: String(timeout),
190
+ payment_method: "x402",
191
+ payment_token: paymentToken,
192
+ });
193
+ const resp = await apiPost(`/api/v1/hub/gateway/invoke?${qs}`, inputData, config.api_key);
194
+ if (!resp.ok) {
195
+ const raw = resp.data && typeof resp.data === "object" && "detail" in resp.data
196
+ ? resp.data.detail
197
+ : resp.data;
198
+ const detail = typeof raw === "string" ? raw : JSON.stringify(raw);
199
+ spinner.fail(chalk.red(`Call failed (${resp.status}): ${detail}`));
200
+ process.exit(1);
201
+ }
202
+ const result = resp.data;
203
+ spinner.succeed(chalk.green("Call completed (x402 paid)!"));
204
+ console.log("");
205
+ console.log(` ${chalk.bold("Order:")} ${result.id ?? "-"}`);
206
+ console.log(` ${chalk.bold("Duration:")} ${typeof result.duration === "number" ? result.duration.toFixed(1) + "s" : "-"}`);
207
+ console.log(` ${chalk.bold("Cost:")} $${skillPrice} USDC`);
208
+ console.log("");
209
+ console.log(chalk.bold(" Output:"));
210
+ console.log(chalk.cyan(" " + JSON.stringify(result.output_data ?? result.output ?? {}, null, 2).replace(/\n/g, "\n ")));
211
+ }
212
+ else {
213
+ // Ledger payment (no real USDC transfer)
214
+ const qs = new URLSearchParams({
215
+ agent_id: options.agent,
216
+ skill: options.skill,
217
+ timeout: String(timeout),
218
+ payment_method: "ledger",
219
+ });
220
+ const resp = await apiPost(`/api/v1/hub/gateway/invoke?${qs}`, inputData, config.api_key);
221
+ if (!resp.ok) {
222
+ const raw = resp.data && typeof resp.data === "object" && "detail" in resp.data
223
+ ? resp.data.detail
224
+ : resp.data;
225
+ const detail = typeof raw === "string" ? raw : JSON.stringify(raw);
226
+ spinner.fail(chalk.red(`Call failed (${resp.status}): ${detail}`));
227
+ process.exit(1);
228
+ }
229
+ const result = resp.data;
230
+ spinner.succeed(chalk.green("Call completed!"));
231
+ console.log("");
232
+ console.log(` ${chalk.bold("Order:")} ${result.id ?? "-"}`);
233
+ console.log(` ${chalk.bold("Duration:")} ${typeof result.duration === "number" ? result.duration.toFixed(1) + "s" : "-"}`);
234
+ console.log(` ${chalk.bold("Cost:")} $${typeof result.price === "number" ? result.price.toFixed(3) : "-"}`);
235
+ console.log("");
236
+ console.log(chalk.bold(" Output:"));
237
+ console.log(chalk.cyan(" " + JSON.stringify(result.output_data ?? result.output ?? {}, null, 2).replace(/\n/g, "\n ")));
173
238
  }
174
- const result = resp.data;
175
- spinner.succeed(chalk.green("Call completed!"));
176
- console.log("");
177
- console.log(` ${chalk.bold("Order:")} ${result.id ?? "-"}`);
178
- console.log(` ${chalk.bold("Duration:")} ${typeof result.duration === "number" ? result.duration.toFixed(1) + "s" : "-"}`);
179
- console.log(` ${chalk.bold("Cost:")} $${typeof result.price === "number" ? result.price.toFixed(3) : "-"}`);
180
- console.log("");
181
- console.log(chalk.bold(" Output:"));
182
- console.log(chalk.cyan(" " + JSON.stringify(result.output_data ?? result.output ?? {}, null, 2).replace(/\n/g, "\n ")));
183
239
  }
184
240
  catch (err) {
185
241
  spinner.fail(chalk.red("Call failed"));
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ const program = new Command();
11
11
  program
12
12
  .name('clawmoney')
13
13
  .description('ClawMoney CLI -- Earn rewards with your AI agent')
14
- .version('0.9.1');
14
+ .version('0.9.2');
15
15
  // setup
16
16
  program
17
17
  .command('setup')
@@ -232,6 +232,7 @@ hub
232
232
  .requiredOption('-s, --skill <skill>', 'Skill name to invoke')
233
233
  .option('-i, --input <json>', 'Input parameters as JSON')
234
234
  .option('-t, --timeout <seconds>', 'Timeout in seconds', '60')
235
+ .option('--pay', 'Pay with USDC via x402 (default: ledger/free)')
235
236
  .action(async (options) => {
236
237
  try {
237
238
  await hubCallCommand(options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawmoney",
3
- "version": "0.9.1",
3
+ "version": "0.9.3",
4
4
  "description": "ClawMoney CLI -- Earn rewards with your AI agent",
5
5
  "type": "module",
6
6
  "bin": {