clawmoney 0.9.2 → 0.9.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.
@@ -4,7 +4,7 @@ import { homedir } from "node:os";
4
4
  import chalk from "chalk";
5
5
  import ora from "ora";
6
6
  import { requireConfig } from "../utils/config.js";
7
- import { apiGet, apiPost, getApiBase } from "../utils/api.js";
7
+ import { apiGet, apiPost } from "../utils/api.js";
8
8
  import { awalExec } from "../utils/awal.js";
9
9
  import { readPid, isPidAlive, removePid } from "../hub/provider.js";
10
10
  const LOG_FILE = join(homedir(), ".clawmoney", "provider.log");
@@ -157,10 +157,15 @@ export async function hubCallCommand(options) {
157
157
  const spinner = ora(`Calling ${options.agent}/${options.skill}...`).start();
158
158
  try {
159
159
  if (options.pay) {
160
- // x402 payment: two steps
161
- // Step 1: Pay via x402 to the payment endpoint (USDC → PaySplitter)
162
- spinner.text = `Paying for ${options.agent}/${options.skill} via x402...`;
163
- const payUrl = `${getApiBase()}/api/v1/hub/gateway/pay?agent_id=${encodeURIComponent(options.agent)}&skill=${encodeURIComponent(options.skill)}`;
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}`;
164
169
  let payResult;
165
170
  try {
166
171
  payResult = await awalExec(["x402", "pay", payUrl]);
@@ -169,13 +174,24 @@ export async function hubCallCommand(options) {
169
174
  spinner.fail(chalk.red(`Payment failed: ${err.message}`));
170
175
  process.exit(1);
171
176
  }
172
- // Step 2: Call invoke with ledger (payment already settled on-chain)
177
+ // Extract payment_token from Worker response
178
+ // awal returns {status, statusText, data: {payment_token, ...}, headers}
179
+ const payData = payResult.data;
180
+ const innerData = payData.data ?? payData;
181
+ const paymentToken = innerData.payment_token ?? payData.payment_token;
182
+ if (!paymentToken) {
183
+ spinner.fail(chalk.red("Payment succeeded but no payment_token returned"));
184
+ console.error(chalk.dim(` Raw response: ${JSON.stringify(payResult.data).slice(0, 200)}`));
185
+ process.exit(1);
186
+ }
187
+ // Step 3: Invoke with payment_token
173
188
  spinner.text = `Executing ${options.agent}/${options.skill}...`;
174
189
  const qs = new URLSearchParams({
175
190
  agent_id: options.agent,
176
191
  skill: options.skill,
177
192
  timeout: String(timeout),
178
- payment_method: "ledger",
193
+ payment_method: "x402",
194
+ payment_token: paymentToken,
179
195
  });
180
196
  const resp = await apiPost(`/api/v1/hub/gateway/invoke?${qs}`, inputData, config.api_key);
181
197
  if (!resp.ok) {
@@ -191,8 +207,7 @@ export async function hubCallCommand(options) {
191
207
  console.log("");
192
208
  console.log(` ${chalk.bold("Order:")} ${result.id ?? "-"}`);
193
209
  console.log(` ${chalk.bold("Duration:")} ${typeof result.duration === "number" ? result.duration.toFixed(1) + "s" : "-"}`);
194
- console.log(` ${chalk.bold("Cost:")} $${typeof result.price === "number" ? result.price.toFixed(3) : "-"} (USDC)`);
195
- console.log(` ${chalk.bold("Payment:")} ${JSON.stringify(payResult.data).slice(0, 100)}`);
210
+ console.log(` ${chalk.bold("Cost:")} $${skillPrice} USDC`);
196
211
  console.log("");
197
212
  console.log(chalk.bold(" Output:"));
198
213
  console.log(chalk.cyan(" " + JSON.stringify(result.output_data ?? result.output ?? {}, null, 2).replace(/\n/g, "\n ")));
@@ -192,6 +192,16 @@ export class Executor {
192
192
  // Parse OpenClaw's response format: { payloads, meta }
193
193
  const ocResult = parseOpenClawResponse(parsed);
194
194
  output = ocResult.result;
195
+ // Check if the agent explicitly reported failure
196
+ if (output.success === false && typeof output.error === "string") {
197
+ logger.error(`Agent reported failure for order=${call.order_id}: ${output.error}`);
198
+ this.send({
199
+ event: "deliver",
200
+ order_id: call.order_id,
201
+ error: output.error.slice(0, 2000),
202
+ });
203
+ return;
204
+ }
195
205
  // Upload local files to R2
196
206
  for (const filePath of ocResult.files) {
197
207
  const cdnUrl = await uploadFile(filePath, this.config);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawmoney",
3
- "version": "0.9.2",
3
+ "version": "0.9.4",
4
4
  "description": "ClawMoney CLI -- Earn rewards with your AI agent",
5
5
  "type": "module",
6
6
  "bin": {