@fluxa-pay/planner 0.1.0 → 0.1.1
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/planner.mjs +39 -6
package/package.json
CHANGED
package/planner.mjs
CHANGED
|
@@ -301,6 +301,36 @@ async function rawCall(url, method, data, extraHeaders = {}, auth = false) {
|
|
|
301
301
|
return { status: res.status, text };
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
+
// The proxy's API/MCP lanes bill the caller identified by the X-Agent-ID header
|
|
305
|
+
// and reject every non-discovery request without it. Default to the agent_id
|
|
306
|
+
// (UUID) from `fluxa-wallet status`; configs with require_agent_auth need a JWT
|
|
307
|
+
// instead, so agentCall() retries with a freshly minted wallet JWT on the
|
|
308
|
+
// "valid JWT" 401. Both values are cached for the process.
|
|
309
|
+
let _agentId = null;
|
|
310
|
+
async function agentId() {
|
|
311
|
+
if (_agentId) return _agentId;
|
|
312
|
+
const s = unwrap(await walletJson(["status"]).catch(() => ({})));
|
|
313
|
+
const id = s.agent_id || s.agentId || s.id;
|
|
314
|
+
if (!id) die("could not read agent_id from `fluxa-wallet status` — register once with `fluxa-wallet init`.");
|
|
315
|
+
return (_agentId = id);
|
|
316
|
+
}
|
|
317
|
+
let _walletJwt = null;
|
|
318
|
+
async function walletJwt() {
|
|
319
|
+
if (_walletJwt) return _walletJwt;
|
|
320
|
+
const j = unwrap(await walletJson(["refreshJWT"]).catch(() => ({})));
|
|
321
|
+
const jwt = j.jwt || j.token;
|
|
322
|
+
if (!jwt) die("could not mint a wallet JWT (`fluxa-wallet refreshJWT`).");
|
|
323
|
+
return (_walletJwt = jwt);
|
|
324
|
+
}
|
|
325
|
+
// rawCall + X-Agent-ID, with the UUID→JWT fallback for require_agent_auth configs.
|
|
326
|
+
async function agentCall(url, method, data, extra = {}) {
|
|
327
|
+
const r = await rawCall(url, method, data, { ...extra, "X-Agent-ID": await agentId() });
|
|
328
|
+
if (r.status === 401 && /valid JWT/i.test(r.text)) {
|
|
329
|
+
return rawCall(url, method, data, { ...extra, "X-Agent-ID": await walletJwt() });
|
|
330
|
+
}
|
|
331
|
+
return r;
|
|
332
|
+
}
|
|
333
|
+
|
|
304
334
|
async function ensureMandate(currency, budget, seconds, url) {
|
|
305
335
|
const cfg = loadConfig();
|
|
306
336
|
// only reuse a signed mandate of the SAME currency with budget left
|
|
@@ -339,9 +369,12 @@ function descriptorEndpoints(text) {
|
|
|
339
369
|
}
|
|
340
370
|
|
|
341
371
|
async function cmdCall(url, opts = {}) {
|
|
342
|
-
if (!url
|
|
343
|
-
return die("usage: planner call <url> [--endpoint <path>] [--data '<json>'] [--pay credits|usdc] [--method GET|POST] [--budget <units>] [--raw]");
|
|
372
|
+
if (!url) {
|
|
373
|
+
return die("usage: planner call <url|slug> [--endpoint <path>] [--data '<json>'] [--pay credits|usdc] [--method GET|POST] [--budget <units>] [--raw]");
|
|
344
374
|
}
|
|
375
|
+
// accept a bare AgentMarket slug (e.g. `web-search-api`) → the proxy API base.
|
|
376
|
+
// full http(s) URLs are used as-is.
|
|
377
|
+
if (!/^https?:\/\//.test(url)) url = `${PROXY}/api/${encodeURIComponent(url)}`;
|
|
345
378
|
const pay = (opts.pay || loadConfig().pay || "credits").toLowerCase();
|
|
346
379
|
const currency = pay === "usdc" ? "USDC" : "FLUXA_MONETIZE_CREDITS";
|
|
347
380
|
const budget = opts.budget ? Number(opts.budget) : (pay === "usdc" ? 5000000 : 500); // ~$5 default
|
|
@@ -357,7 +390,7 @@ async function cmdCall(url, opts = {}) {
|
|
|
357
390
|
// real paid sub-endpoints. Resolve it (unless --raw) so the agent doesn't have
|
|
358
391
|
// to read the catalog itself. We never spend without a supplied body.
|
|
359
392
|
if (!opts.raw) {
|
|
360
|
-
const probe = await
|
|
393
|
+
const probe = await agentCall(url, "GET");
|
|
361
394
|
const desc = probe.status === 200 ? descriptorEndpoints(probe.text) : null;
|
|
362
395
|
if (desc) {
|
|
363
396
|
const eps = desc.endpoints.filter((e) => e.enabled !== false);
|
|
@@ -388,7 +421,7 @@ async function cmdCall(url, opts = {}) {
|
|
|
388
421
|
}
|
|
389
422
|
|
|
390
423
|
// call the resolved endpoint — pay if it answers 402
|
|
391
|
-
let r = await
|
|
424
|
+
let r = await agentCall(targetUrl, method, data);
|
|
392
425
|
if (r.status !== 402) {
|
|
393
426
|
if (r.status >= 400) die(`${r.status} — ${r.text.slice(0, 300)}`);
|
|
394
427
|
return console.log(r.text); // raw body, no post-processing
|
|
@@ -402,8 +435,8 @@ async function cmdCall(url, opts = {}) {
|
|
|
402
435
|
const xPayment = paid.xPaymentB64 || paid.xPayment;
|
|
403
436
|
if (!xPayment) die("x402-v3 did not return a payment token (xPaymentB64).");
|
|
404
437
|
|
|
405
|
-
// 3. retry with the payment token
|
|
406
|
-
r = await
|
|
438
|
+
// 3. retry with the payment token (against the resolved endpoint, with X-Agent-ID)
|
|
439
|
+
r = await agentCall(targetUrl, method, opts.data, { "X-Payment": xPayment });
|
|
407
440
|
if (r.status >= 400) die(`paid retry failed: ${r.status} — ${r.text.slice(0, 300)}`);
|
|
408
441
|
console.log(r.text); // raw body, no post-processing
|
|
409
442
|
}
|