clawmoney 0.15.28 → 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 +34 -45
- 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 ──
|
|
@@ -201,10 +195,7 @@ export async function relaySetupCommand() {
|
|
|
201
195
|
log.warn(`${cli}: no recommended models found — skipping`);
|
|
202
196
|
continue;
|
|
203
197
|
}
|
|
204
|
-
log.step(`${chalk.bold(cli)}:
|
|
205
|
-
for (const m of recommended) {
|
|
206
|
-
log.message(chalk.dim(` · ${m}`));
|
|
207
|
-
}
|
|
198
|
+
log.step(`${chalk.bold(cli)}: ${recommended.length} models ${chalk.dim("— " + recommended.join(", "))}`);
|
|
208
199
|
for (const model of recommended) {
|
|
209
200
|
const p = API_PRICES[model];
|
|
210
201
|
registrations.push({
|
|
@@ -276,36 +267,30 @@ export async function relaySetupCommand() {
|
|
|
276
267
|
process.exit(0);
|
|
277
268
|
}
|
|
278
269
|
const dailyLimit = dailyLimitChoice;
|
|
279
|
-
// ── Step 5:
|
|
280
|
-
//
|
|
281
|
-
//
|
|
282
|
-
//
|
|
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.
|
|
283
284
|
const limitLabel = {
|
|
284
|
-
15: "~25%
|
|
285
|
-
30: "~50% (Balanced)",
|
|
286
|
-
45: "~75% (Heavy)",
|
|
287
|
-
60: "~100% (Full)",
|
|
285
|
+
15: "~25%", 30: "~50%", 45: "~75%", 60: "~100%",
|
|
288
286
|
};
|
|
289
|
-
|
|
290
|
-
for (const r of registrations) {
|
|
291
|
-
log.message(` ${chalk.cyan(r.cli + "/" + r.model).padEnd(50)} ${chalk.dim(formatBuyerPrice(r.input, r.output))}`);
|
|
292
|
-
}
|
|
293
|
-
log.message(chalk.dim(` ${registrations.length} provider(s) · ${limitLabel[dailyLimit] ?? `$${dailyLimit}/day cap`} per model`));
|
|
294
|
-
log.message(chalk.dim(` You earn ~${Math.round((1 - PLATFORM_FEE) * 100)}% of what buyers pay (after platform fee)`));
|
|
295
|
-
log.message(chalk.dim(` To customize: edit ~/.clawmoney/config.yaml after start`));
|
|
296
|
-
// ── Step 6: register each (idempotent — "already registered" counts as success) ──
|
|
297
|
-
//
|
|
298
|
-
// No "Register all N providers now?" confirm — the user already
|
|
299
|
-
// picked subscriptions + daily quota share. Seeing the summary and
|
|
300
|
-
// immediately going into registration is the expected flow. Ctrl-C
|
|
301
|
-
// still aborts, and registrations are idempotent so a mid-way abort
|
|
302
|
-
// is recoverable by re-running.
|
|
287
|
+
const earnPct = Math.round((1 - PLATFORM_FEE) * 100);
|
|
303
288
|
let succeeded = 0;
|
|
304
289
|
let failed = 0;
|
|
305
290
|
const failures = [];
|
|
291
|
+
const regSpin = spinner();
|
|
292
|
+
regSpin.start(`Registering ${registrations.length} providers...`);
|
|
306
293
|
for (const r of registrations) {
|
|
307
|
-
const regSpin = spinner();
|
|
308
|
-
regSpin.start(`Registering ${r.cli}/${r.model}...`);
|
|
309
294
|
try {
|
|
310
295
|
const body = {
|
|
311
296
|
cli_type: r.cli,
|
|
@@ -318,7 +303,6 @@ export async function relaySetupCommand() {
|
|
|
318
303
|
};
|
|
319
304
|
const resp = await apiPost("/api/v1/relay/providers", body, config.api_key);
|
|
320
305
|
if (resp.ok) {
|
|
321
|
-
regSpin.stop(`${chalk.green("✓")} ${r.cli}/${r.model}`);
|
|
322
306
|
succeeded++;
|
|
323
307
|
}
|
|
324
308
|
else {
|
|
@@ -328,11 +312,9 @@ export async function relaySetupCommand() {
|
|
|
328
312
|
const detail = typeof raw === "string" ? raw : JSON.stringify(raw);
|
|
329
313
|
// Already-registered is a soft success — idempotent re-run.
|
|
330
314
|
if (detail.includes("Already registered")) {
|
|
331
|
-
regSpin.stop(`${chalk.yellow("~")} ${r.cli}/${r.model} ${chalk.dim("(already registered, no change)")}`);
|
|
332
315
|
succeeded++;
|
|
333
316
|
}
|
|
334
317
|
else {
|
|
335
|
-
regSpin.stop(`${chalk.red("✗")} ${r.cli}/${r.model} ${chalk.dim("(" + detail.slice(0, 80) + ")")}`);
|
|
336
318
|
failed++;
|
|
337
319
|
failures.push({ cli: r.cli, model: r.model, error: detail });
|
|
338
320
|
}
|
|
@@ -340,21 +322,28 @@ export async function relaySetupCommand() {
|
|
|
340
322
|
}
|
|
341
323
|
catch (err) {
|
|
342
324
|
const msg = err.message;
|
|
343
|
-
regSpin.stop(`${chalk.red("✗")} ${r.cli}/${r.model} ${chalk.dim("(" + msg + ")")}`);
|
|
344
325
|
failed++;
|
|
345
326
|
failures.push({ cli: r.cli, model: r.model, error: msg });
|
|
346
327
|
}
|
|
347
328
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
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.
|
|
351
341
|
if (failed > 0) {
|
|
352
|
-
log.warn(`${failed} registrations failed`);
|
|
353
342
|
for (const f of failures) {
|
|
354
|
-
log.
|
|
343
|
+
log.warn(`${f.cli}/${f.model}: ${chalk.dim(f.error.slice(0, 120))}`);
|
|
355
344
|
}
|
|
356
345
|
}
|
|
357
|
-
// ── Step
|
|
346
|
+
// ── Step 7: auto-start the daemon ──
|
|
358
347
|
//
|
|
359
348
|
// The daemon now runs in multi-cli auto mode by default: it fetches
|
|
360
349
|
// every provider this agent has registered, preflights each distinct
|