clawmoney 0.15.29 → 0.15.30
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/dist/commands/relay-setup.js +33 -41
- package/package.json +1 -1
|
@@ -7,7 +7,7 @@ import chalk from "chalk";
|
|
|
7
7
|
import { apiPost } from "../utils/api.js";
|
|
8
8
|
import { loadConfig, requireConfig } from "../utils/config.js";
|
|
9
9
|
import { setupCommand } from "./setup.js";
|
|
10
|
-
import { API_PRICES,
|
|
10
|
+
import { API_PRICES, PLATFORM_FEE } from "../relay/pricing.js";
|
|
11
11
|
// ── Per-cli_type model catalogs ──
|
|
12
12
|
//
|
|
13
13
|
// `RECOMMENDED_MODELS` is what gets registered when the user picks "all
|
|
@@ -119,12 +119,6 @@ function detectInstalledClis() {
|
|
|
119
119
|
});
|
|
120
120
|
return results;
|
|
121
121
|
}
|
|
122
|
-
// ── Helpers ──
|
|
123
|
-
function formatBuyerPrice(input, output) {
|
|
124
|
-
const buyerInput = (input * RELAY_DISCOUNT).toFixed(3);
|
|
125
|
-
const buyerOutput = (output * RELAY_DISCOUNT).toFixed(3);
|
|
126
|
-
return `$${buyerInput}/$${buyerOutput} per 1M (after ${Math.round((1 - RELAY_DISCOUNT) * 100)}% relay discount)`;
|
|
127
|
-
}
|
|
128
122
|
// ── Main command ──
|
|
129
123
|
export async function relaySetupCommand() {
|
|
130
124
|
// ── Step 0: ensure the agent is logged in ──
|
|
@@ -273,36 +267,30 @@ export async function relaySetupCommand() {
|
|
|
273
267
|
process.exit(0);
|
|
274
268
|
}
|
|
275
269
|
const dailyLimit = dailyLimitChoice;
|
|
276
|
-
// ── Step 5:
|
|
277
|
-
//
|
|
278
|
-
//
|
|
279
|
-
//
|
|
270
|
+
// ── Step 5: register everything under one spinner ──
|
|
271
|
+
//
|
|
272
|
+
// We deliberately skip the old per-model Summary block: pricing is on
|
|
273
|
+
// the website, and Step 3 already listed which models were queued per
|
|
274
|
+
// subscription. The remaining signal (quota share + earn %) goes into
|
|
275
|
+
// the spinner's final message so users see it exactly once.
|
|
276
|
+
//
|
|
277
|
+
// Also: one spinner for the whole batch, not N. Sequential per-model
|
|
278
|
+
// spinners produced 7+ rows of clack vertical whitespace for what's
|
|
279
|
+
// really a single bulk action.
|
|
280
|
+
//
|
|
281
|
+
// No "Register all N providers now?" confirm either — the user picked
|
|
282
|
+
// subscriptions + quota share above; Ctrl-C still aborts, and the
|
|
283
|
+
// backend is idempotent so mid-way aborts are safe to re-run.
|
|
280
284
|
const limitLabel = {
|
|
281
|
-
15: "~25%
|
|
282
|
-
30: "~50% (Balanced)",
|
|
283
|
-
45: "~75% (Heavy)",
|
|
284
|
-
60: "~100% (Full)",
|
|
285
|
+
15: "~25%", 30: "~50%", 45: "~75%", 60: "~100%",
|
|
285
286
|
};
|
|
286
|
-
|
|
287
|
-
for (const r of registrations) {
|
|
288
|
-
log.message(` ${chalk.cyan(r.cli + "/" + r.model).padEnd(50)} ${chalk.dim(formatBuyerPrice(r.input, r.output))}`);
|
|
289
|
-
}
|
|
290
|
-
log.message(chalk.dim(` ${registrations.length} provider(s) · ${limitLabel[dailyLimit] ?? `$${dailyLimit}/day cap`} per model`));
|
|
291
|
-
log.message(chalk.dim(` You earn ~${Math.round((1 - PLATFORM_FEE) * 100)}% of what buyers pay (after platform fee)`));
|
|
292
|
-
log.message(chalk.dim(` To customize: edit ~/.clawmoney/config.yaml after start`));
|
|
293
|
-
// ── Step 6: register each (idempotent — "already registered" counts as success) ──
|
|
294
|
-
//
|
|
295
|
-
// No "Register all N providers now?" confirm — the user already
|
|
296
|
-
// picked subscriptions + daily quota share. Seeing the summary and
|
|
297
|
-
// immediately going into registration is the expected flow. Ctrl-C
|
|
298
|
-
// still aborts, and registrations are idempotent so a mid-way abort
|
|
299
|
-
// is recoverable by re-running.
|
|
287
|
+
const earnPct = Math.round((1 - PLATFORM_FEE) * 100);
|
|
300
288
|
let succeeded = 0;
|
|
301
289
|
let failed = 0;
|
|
302
290
|
const failures = [];
|
|
291
|
+
const regSpin = spinner();
|
|
292
|
+
regSpin.start(`Registering ${registrations.length} providers...`);
|
|
303
293
|
for (const r of registrations) {
|
|
304
|
-
const regSpin = spinner();
|
|
305
|
-
regSpin.start(`Registering ${r.cli}/${r.model}...`);
|
|
306
294
|
try {
|
|
307
295
|
const body = {
|
|
308
296
|
cli_type: r.cli,
|
|
@@ -315,7 +303,6 @@ export async function relaySetupCommand() {
|
|
|
315
303
|
};
|
|
316
304
|
const resp = await apiPost("/api/v1/relay/providers", body, config.api_key);
|
|
317
305
|
if (resp.ok) {
|
|
318
|
-
regSpin.stop(`${chalk.green("✓")} ${r.cli}/${r.model}`);
|
|
319
306
|
succeeded++;
|
|
320
307
|
}
|
|
321
308
|
else {
|
|
@@ -325,11 +312,9 @@ export async function relaySetupCommand() {
|
|
|
325
312
|
const detail = typeof raw === "string" ? raw : JSON.stringify(raw);
|
|
326
313
|
// Already-registered is a soft success — idempotent re-run.
|
|
327
314
|
if (detail.includes("Already registered")) {
|
|
328
|
-
regSpin.stop(`${chalk.yellow("~")} ${r.cli}/${r.model} ${chalk.dim("(already registered, no change)")}`);
|
|
329
315
|
succeeded++;
|
|
330
316
|
}
|
|
331
317
|
else {
|
|
332
|
-
regSpin.stop(`${chalk.red("✗")} ${r.cli}/${r.model} ${chalk.dim("(" + detail.slice(0, 80) + ")")}`);
|
|
333
318
|
failed++;
|
|
334
319
|
failures.push({ cli: r.cli, model: r.model, error: detail });
|
|
335
320
|
}
|
|
@@ -337,21 +322,28 @@ export async function relaySetupCommand() {
|
|
|
337
322
|
}
|
|
338
323
|
catch (err) {
|
|
339
324
|
const msg = err.message;
|
|
340
|
-
regSpin.stop(`${chalk.red("✗")} ${r.cli}/${r.model} ${chalk.dim("(" + msg + ")")}`);
|
|
341
325
|
failed++;
|
|
342
326
|
failures.push({ cli: r.cli, model: r.model, error: msg });
|
|
343
327
|
}
|
|
344
328
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
329
|
+
if (failed === 0) {
|
|
330
|
+
regSpin.stop(`${chalk.green(`✓ ${succeeded} providers registered`)} ` +
|
|
331
|
+
chalk.dim(`(${limitLabel[dailyLimit] ?? `$${dailyLimit}`} quota share · you earn ~${earnPct}%)`));
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
regSpin.stop(`${chalk.yellow(`${succeeded} registered, ${failed} failed`)}`);
|
|
335
|
+
}
|
|
336
|
+
// ── Step 6: on failure, list which ones broke ──
|
|
337
|
+
//
|
|
338
|
+
// On success we say nothing — the spinner's final message is already
|
|
339
|
+
// the "registered" summary. On failure we dump a per-row detail line
|
|
340
|
+
// so the user can tell what to fix.
|
|
348
341
|
if (failed > 0) {
|
|
349
|
-
log.warn(`${failed} registrations failed`);
|
|
350
342
|
for (const f of failures) {
|
|
351
|
-
log.
|
|
343
|
+
log.warn(`${f.cli}/${f.model}: ${chalk.dim(f.error.slice(0, 120))}`);
|
|
352
344
|
}
|
|
353
345
|
}
|
|
354
|
-
// ── Step
|
|
346
|
+
// ── Step 7: auto-start the daemon ──
|
|
355
347
|
//
|
|
356
348
|
// The daemon now runs in multi-cli auto mode by default: it fetches
|
|
357
349
|
// every provider this agent has registered, preflights each distinct
|