@fluxa-pay/planner 0.2.4 → 0.2.5

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluxa-pay/planner",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "FluxA Planner CLI. Recommend the right models, APIs and skills for a task, and manage your oneshot APIs.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,7 +10,8 @@
10
10
  "node": ">=20"
11
11
  },
12
12
  "files": [
13
- "planner.mjs"
13
+ "planner.mjs",
14
+ "plan-format.mjs"
14
15
  ],
15
16
  "publishConfig": {
16
17
  "access": "public"
@@ -0,0 +1,49 @@
1
+ // Pure formatting of a `planner plan` result into terminal lines. No I/O and no
2
+ // color of its own — the caller passes a helpers bag (h) so planner.mjs injects
3
+ // ANSI while tests pass identity helpers and assert on plain text.
4
+ //
5
+ // When the plan carries capability `groups`, each capability prints its options
6
+ // (the recommended one first, tagged) so the agent sees the alternatives. Older
7
+ // / template plans without groups fall back to the flat `tools` list.
8
+ export function planLines(plan, h) {
9
+ const lines = [];
10
+ const heading = h.unesc(plan.reason || plan.task || "Recommended");
11
+ lines.push("");
12
+ lines.push(" " + h.bold("Recommended") + " " + h.dim(heading));
13
+
14
+ const groups = Array.isArray(plan.groups) ? plan.groups : null;
15
+ let total = 0;
16
+
17
+ if (groups && groups.length) {
18
+ for (const g of groups) {
19
+ lines.push(" " + h.dim(h.unesc(g.capability || "")));
20
+ const lead = g.options.find((o) => o.recommended) || g.options[0];
21
+ const ordered = lead ? [lead, ...g.options.filter((o) => o !== lead)] : g.options;
22
+ if (lead) total += lead.units || 0;
23
+ for (const o of ordered) {
24
+ const k = h.kind(o.kind);
25
+ const tag = o === lead ? " " + h.lime("recommended") : "";
26
+ lines.push(
27
+ ` ${k} ${h.bold(h.pad(o.slug, 34))} ${h.dim(h.pad(h.unesc(o.detail || ""), 24))} ${h.lime("~" + (o.units || 0).toLocaleString() + " Units")}${tag}`,
28
+ );
29
+ }
30
+ }
31
+ } else {
32
+ for (const t of plan.tools || []) {
33
+ total += t.units || 0;
34
+ const k = h.kind(t.kind);
35
+ lines.push(
36
+ ` ${k} ${h.bold(h.pad(t.slug, 36))} ${h.dim(h.pad(h.unesc(t.detail || ""), 30))} ${h.lime("~" + (t.units || 0).toLocaleString() + " Units")}`,
37
+ );
38
+ }
39
+ }
40
+
41
+ lines.push(h.gray(" " + "─".repeat(78)));
42
+ lines.push(` ${h.bold("est")} ${h.lime("~" + total.toLocaleString() + " Units")} ${h.dim("(~" + h.usd(total) + ")")}`);
43
+ if (plan.instructions) {
44
+ lines.push("");
45
+ lines.push(" " + h.dim(h.unesc(plan.instructions)));
46
+ }
47
+ lines.push(h.dim("\n → Run these yourself. Paid endpoints answer HTTP 402; settle with fluxa-wallet (planner info pay)."));
48
+ return { lines, total };
49
+ }
package/planner.mjs CHANGED
@@ -26,6 +26,7 @@ import { promisify } from "node:util";
26
26
  import { homedir } from "node:os";
27
27
  import { join } from "node:path";
28
28
  import { stdout, argv, env, exit } from "node:process";
29
+ import { planLines } from "./plan-format.mjs";
29
30
 
30
31
  const pexec = promisify(execFile);
31
32
 
@@ -519,19 +520,12 @@ function printAnswer(a) {
519
520
 
520
521
  // Render a PlanOrAnswer plan: tools carry kind/slug/name/units/detail.
521
522
  function printPlan(plan) {
522
- const tools = plan.tools || [];
523
- const heading = unesc(plan.reason || plan.task || "Recommended");
524
- console.log("\n " + c.bold("Recommended") + " " + c.dim(heading));
525
- let total = 0;
526
- for (const t of tools) {
527
- const k = KIND[t.kind] || pad(t.kind, 5);
528
- total += t.units || 0;
529
- console.log(` ${k} ${c.bold(pad(t.slug, 36))} ${c.dim(pad(unesc(t.detail || ""), 30))} ${c.lime("~" + (t.units || 0).toLocaleString() + " Units")}`);
530
- }
531
- console.log(c.gray(" " + "─".repeat(78)));
532
- console.log(` ${c.bold("est")} ${c.lime("~" + total.toLocaleString() + " Units")} ${c.dim("(~" + usd(total) + ")")}`);
533
- if (plan.instructions) console.log("\n " + c.dim(unesc(plan.instructions)));
534
- console.log(c.dim("\n → call these tools directly — FluxA settles each paid call from your wallet. No keys, no subs."));
523
+ const { lines, total } = planLines(plan, {
524
+ bold: c.bold, dim: c.dim, lime: c.lime, gray: c.gray,
525
+ kind: (k) => KIND[k] || pad(k, 5),
526
+ pad, usd, unesc,
527
+ });
528
+ for (const l of lines) console.log(l);
535
529
  return total;
536
530
  }
537
531