@fluxa-pay/planner 0.2.1 → 0.2.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.
- package/package.json +1 -1
- package/planner.mjs +26 -6
package/package.json
CHANGED
package/planner.mjs
CHANGED
|
@@ -47,6 +47,12 @@ const KIND = { model: c.cyan("model"), api: c.lime("api "), skill: c.green("ski
|
|
|
47
47
|
const pad = (s, n) => { s = String(s); return s.length > n ? s.slice(0, n - 1) + "…" : s.padEnd(n); };
|
|
48
48
|
const usd = (units) => { const v = (units || 0) * UNIT_USD; return v < 0.01 ? `$${v.toFixed(4)}` : `$${v.toFixed(2)}`; };
|
|
49
49
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
50
|
+
// The planner brain occasionally HTML-escapes angle brackets in free text
|
|
51
|
+
// (e.g. "<merchant>"); un-escape the common entities for terminal output.
|
|
52
|
+
// & is undone LAST so "&lt;" doesn't collapse into "<".
|
|
53
|
+
const unesc = (s) => typeof s === "string"
|
|
54
|
+
? s.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/?9;/g, "'").replace(/&/g, "&")
|
|
55
|
+
: s;
|
|
50
56
|
|
|
51
57
|
// --- config / auth ----------------------------------------------------------
|
|
52
58
|
function loadConfig() {
|
|
@@ -181,6 +187,18 @@ async function cmdModels(vendor) {
|
|
|
181
187
|
}
|
|
182
188
|
}
|
|
183
189
|
|
|
190
|
+
async function cmdVendors() {
|
|
191
|
+
const { data } = await http(`${PLATFORM}/api/llm/vendors`);
|
|
192
|
+
const vendors = data.vendors || [];
|
|
193
|
+
if (!vendors.length) return console.log(c.dim(" no vendors"));
|
|
194
|
+
console.log(" " + c.dim(pad("slug", 22) + pad("name", 22) + pad("models", 9) + pad("bundles", 9) + "price (Units/Mtok)"));
|
|
195
|
+
for (const v of vendors) {
|
|
196
|
+
const pr = v.priceRange;
|
|
197
|
+
const price = pr && Number.isFinite(pr.min) ? (pr.min === pr.max ? `${pr.min}` : `${pr.min}-${pr.max}`) : c.dim("—");
|
|
198
|
+
console.log(` ${c.bold(pad(v.slug, 22))}${c.gray(pad(v.name || "", 22))}${pad(String(v.modelCount ?? 0), 9)}${pad(String(v.bundleCount ?? 0), 9)}${price}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
184
202
|
async function cmdBalance(vendor) {
|
|
185
203
|
const url = vendor ? `${PROXY}/llm/wallet/balances/${vendor}` : `${PROXY}/llm/wallet/balances`;
|
|
186
204
|
const { data } = await http(url, { auth: true });
|
|
@@ -617,14 +635,14 @@ async function cmdPlan(task) {
|
|
|
617
635
|
}
|
|
618
636
|
|
|
619
637
|
function printAnswer(a) {
|
|
620
|
-
console.log("\n " + c.bold(a.answer));
|
|
638
|
+
console.log("\n " + c.bold(unesc(a.answer)));
|
|
621
639
|
if (a.command) {
|
|
622
640
|
console.log("\n " + c.dim("run:"));
|
|
623
|
-
console.log(" " + c.cyan(a.command));
|
|
641
|
+
console.log(" " + c.cyan(unesc(a.command)));
|
|
624
642
|
}
|
|
625
643
|
if (a.prompt) {
|
|
626
644
|
console.log("\n " + c.dim("copy this prompt for your agent:"));
|
|
627
|
-
for (const line of a.prompt.split("\n")) console.log(" " + line);
|
|
645
|
+
for (const line of unesc(a.prompt).split("\n")) console.log(" " + line);
|
|
628
646
|
}
|
|
629
647
|
console.log("");
|
|
630
648
|
}
|
|
@@ -632,17 +650,17 @@ function printAnswer(a) {
|
|
|
632
650
|
// Render a PlanOrAnswer plan: tools carry kind/slug/name/units/detail.
|
|
633
651
|
function printPlan(plan) {
|
|
634
652
|
const tools = plan.tools || [];
|
|
635
|
-
const heading = plan.reason || plan.task || "Recommended";
|
|
653
|
+
const heading = unesc(plan.reason || plan.task || "Recommended");
|
|
636
654
|
console.log("\n " + c.bold("Recommended") + " " + c.dim(heading));
|
|
637
655
|
let total = 0;
|
|
638
656
|
for (const t of tools) {
|
|
639
657
|
const k = KIND[t.kind] || pad(t.kind, 5);
|
|
640
658
|
total += t.units || 0;
|
|
641
|
-
console.log(` ${k} ${c.bold(pad(t.slug, 36))} ${c.dim(pad(t.detail || "", 30))} ${c.lime("~" + (t.units || 0).toLocaleString() + " Units")}`);
|
|
659
|
+
console.log(` ${k} ${c.bold(pad(t.slug, 36))} ${c.dim(pad(unesc(t.detail || ""), 30))} ${c.lime("~" + (t.units || 0).toLocaleString() + " Units")}`);
|
|
642
660
|
}
|
|
643
661
|
console.log(c.gray(" " + "─".repeat(78)));
|
|
644
662
|
console.log(` ${c.bold("est")} ${c.lime("~" + total.toLocaleString() + " Units")} ${c.dim("(~" + usd(total) + ")")}`);
|
|
645
|
-
if (plan.instructions) console.log("\n " + c.dim(plan.instructions));
|
|
663
|
+
if (plan.instructions) console.log("\n " + c.dim(unesc(plan.instructions)));
|
|
646
664
|
console.log(c.dim("\n → call these tools directly — FluxA settles each paid call from your wallet. No keys, no subs."));
|
|
647
665
|
return total;
|
|
648
666
|
}
|
|
@@ -770,6 +788,7 @@ ${c.bold("Headline")}
|
|
|
770
788
|
${c.bold("Primitives")} ${c.dim("(all live)")}
|
|
771
789
|
planner search "<q>" [--type api,skill,model] discover resources
|
|
772
790
|
planner models [--vendor <slug>] model catalog + Units rates
|
|
791
|
+
planner vendors list fundable merchants (slug, models, price)
|
|
773
792
|
planner balance [vendor] prepaid Units per merchant
|
|
774
793
|
planner topup <vendor> [--credits <N>|--bundle <slug>] prepay Units (x402, via wallet)
|
|
775
794
|
planner ledger <vendor> spend/topup history
|
|
@@ -838,6 +857,7 @@ async function main() {
|
|
|
838
857
|
});
|
|
839
858
|
case "search": return cmdSearch(arg, type);
|
|
840
859
|
case "models": return cmdModels(vendor);
|
|
860
|
+
case "vendors": return cmdVendors();
|
|
841
861
|
case "balance": case "bal": return cmdBalance(rest[0]);
|
|
842
862
|
case "topup":
|
|
843
863
|
return cmdTopup(rest[0], {
|