clawmoney 0.17.9 → 0.17.12

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.
@@ -1,4 +1,4 @@
1
- import { intro, outro, multiselect, text, confirm, spinner, isCancel, cancel, log, note, } from "@clack/prompts";
1
+ import { intro, outro, groupMultiselect, text, confirm, spinner, isCancel, cancel, log, note, } from "@clack/prompts";
2
2
  import chalk from "chalk";
3
3
  import { apiPost } from "../utils/api.js";
4
4
  import { loadConfig } from "../utils/config.js";
@@ -108,40 +108,35 @@ export async function marketSetupCommand(opts = {}) {
108
108
  intro(chalk.cyan(" ClawMoney Market Setup "));
109
109
  }
110
110
  log.message("Register one or more skills on the Market so other agents can call (and pay) you.");
111
- // ── Step 1: multiselect categories. Grouped visually: Instant first,
112
- // then Escrow, then Auto. clack's multiselect has no native separators,
113
- // so we fake them with disabled-looking header rows whose value is a
114
- // sentinel selecting one is a no-op (filtered out downstream). ──
115
- const INSTANT_HEADER = "__hdr_instant__";
116
- const ESCROW_HEADER = "__hdr_escrow__";
117
- const AUTO_HEADER = "__hdr_auto__";
118
- const HEADERS = new Set([INSTANT_HEADER, ESCROW_HEADER, AUTO_HEADER]);
111
+ // ── Step 1: groupMultiselect renders three native sections
112
+ // "Instant · poll for result", "Escrow · manual approve", "Auto · routed
113
+ // by price" with checkbox rows under each. Section titles are part of
114
+ // clack's group rendering, NOT selectable items, so the earlier confusion
115
+ // (title rows being accidentally tickable) is gone.
119
116
  const instantRows = CATEGORIES.filter((c) => c.routing === "instant");
120
117
  const escrowRows = CATEGORIES.filter((c) => c.routing === "escrow");
121
118
  const autoRows = CATEGORIES.filter((c) => c.routing === "auto");
122
- const groupedOptions = [
123
- { value: INSTANT_HEADER, label: chalk.dim("── Instant · poll for result ──"), hint: "" },
124
- ...instantRows.map((row) => ({ value: row.value, label: ` ${row.value}`, hint: formatHint(row) })),
125
- { value: ESCROW_HEADER, label: chalk.dim("── Escrow · manual approve ──"), hint: "" },
126
- ...escrowRows.map((row) => ({ value: row.value, label: ` ${row.value}`, hint: formatHint(row) })),
127
- { value: AUTO_HEADER, label: chalk.dim("── Auto · routed by price ──"), hint: "" },
128
- ...autoRows.map((row) => ({ value: row.value, label: ` ${row.value}`, hint: formatHint(row) })),
129
- ];
130
- const picked = await multiselect({
119
+ // Pad category names to the same width across all groups so the
120
+ // dim-colored timeout column lines up no matter which section it sits in.
121
+ const nameColumnWidth = Math.max(...CATEGORIES.map((c) => c.value.length)) + 2;
122
+ const renderRow = (row) => ({
123
+ value: row.value,
124
+ label: `${row.value.padEnd(nameColumnWidth, " ")}${chalk.dim(formatHint(row))}`,
125
+ });
126
+ const picked = await groupMultiselect({
131
127
  message: "Pick the skill categories to register (space to toggle, enter to confirm):",
132
- options: groupedOptions,
128
+ options: {
129
+ "Instant · poll for result": instantRows.map(renderRow),
130
+ "Escrow · manual approve": escrowRows.map(renderRow),
131
+ "Auto · routed by price": autoRows.map(renderRow),
132
+ },
133
133
  required: true,
134
134
  });
135
135
  if (isCancel(picked)) {
136
136
  cancel("Setup cancelled");
137
137
  process.exit(0);
138
138
  }
139
- // Strip header sentinels — they're visual-only group separators.
140
- const pickedCategories = picked.filter((v) => !HEADERS.has(v));
141
- if (pickedCategories.length === 0) {
142
- cancel("No categories selected");
143
- process.exit(0);
144
- }
139
+ const pickedCategories = picked;
145
140
  // Preserve the canonical CATEGORIES order rather than the click order —
146
141
  // makes the per-skill prompts and the review table read consistently.
147
142
  const orderedRows = CATEGORIES.filter((c) => pickedCategories.includes(c.value));
@@ -29,10 +29,13 @@ export async function providerSetupWizard() {
29
29
  console.log(chalk.red("\n No agent config found. Run `clawmoney setup` first to register.\n"));
30
30
  process.exit(1);
31
31
  }
32
- log.message(chalk.bold("Provider roles") +
33
- chalk.dim(" pick what you want to earn from. You can re-run this anytime."));
32
+ // Render the full role catalog as a note before the multiselect, so the
33
+ // user has a stable reference even after clack collapses the prompt to
34
+ // its selected-items summary. Without this, the user only sees what they
35
+ // ticked and can be left wondering "did I miss other roles?".
36
+ note(ROLES.map((r) => `${chalk.bold(r.label.padEnd(16, " "))}${chalk.dim(r.hint)}`).join("\n"), "Three provider roles — pick any combination");
34
37
  const picked = await multiselect({
35
- message: "Provider roles (space to toggle, enter to confirm):",
38
+ message: "Toggle roles with SPACE, confirm with ENTER (you can skip all to register no role):",
36
39
  options: ROLES.map((r) => ({
37
40
  value: r.value,
38
41
  label: r.label,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawmoney",
3
- "version": "0.17.9",
3
+ "version": "0.17.12",
4
4
  "description": "ClawMoney CLI -- Earn rewards with your AI agent",
5
5
  "type": "module",
6
6
  "bin": {