clawmoney 0.15.59 → 0.15.60

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.
@@ -285,21 +285,31 @@ export async function relayStatusCommand() {
285
285
  const totalDailySpent = providers.reduce((s, p) => s + (p.daily_spent_usd ?? 0), 0);
286
286
  const totalDailyLimit = providers.reduce((s, p) => s + (p.daily_limit_usd ?? 0), 0);
287
287
  // Per-provider rows — compact table with status/cli/model/load.
288
- const header = ` ${"STATUS".padEnd(9)} ${"CLI".padEnd(12)} ${"MODEL".padEnd(30)} ${"LOAD".padEnd(8)} ${"EARNED".padEnd(10)}`;
288
+ // QUARANTINED rows get a follow-up indented line showing the
289
+ // expected/got mismatch reason so the operator knows exactly what
290
+ // to fix — the WS notice also logs this when it first happens,
291
+ // but `relay status` is the after-the-fact checkpoint.
292
+ const header = ` ${"STATUS".padEnd(12)} ${"CLI".padEnd(12)} ${"MODEL".padEnd(30)} ${"LOAD".padEnd(8)} ${"EARNED".padEnd(10)}`;
289
293
  console.log(chalk.bold(header));
290
- console.log(chalk.dim(" " + "─".repeat(75)));
294
+ console.log(chalk.dim(" " + "─".repeat(78)));
291
295
  for (const p of providers) {
292
- const statusRaw = (p.status ?? "-").padEnd(9);
296
+ const statusRaw = (p.status ?? "-").padEnd(12);
293
297
  const statusColored = p.status === "online"
294
298
  ? chalk.green(statusRaw)
295
- : p.status === "offline"
296
- ? chalk.dim(statusRaw)
297
- : chalk.yellow(statusRaw);
299
+ : p.status === "quarantined"
300
+ ? chalk.red(statusRaw)
301
+ : p.status === "offline"
302
+ ? chalk.dim(statusRaw)
303
+ : chalk.yellow(statusRaw);
298
304
  const cli = (p.cli_type ?? "-").padEnd(12);
299
305
  const model = (p.model ?? "-").padEnd(30);
300
306
  const load = `${p.current_load ?? 0}/${p.concurrency ?? "-"}`.padEnd(8);
301
307
  const earned = `$${(p.total_earned_usd ?? 0).toFixed(2)}`.padEnd(10);
302
308
  console.log(` ${statusColored} ${cli} ${model} ${load} ${earned}`);
309
+ if (p.status === "quarantined" && p.quarantine_reason) {
310
+ console.log(chalk.red(` ↳ ${p.quarantine_reason}`) +
311
+ chalk.dim(" (fix: restart daemon after correcting the subscription/registration)"));
312
+ }
303
313
  }
304
314
  console.log("");
305
315
  console.log(` ${chalk.bold("Daily quota:")} $${totalDailySpent.toFixed(2)} / $${totalDailyLimit.toFixed(2)}`);
@@ -285,13 +285,23 @@ async function executeRelayRequest(request, config, sendChunk) {
285
285
  status: snap.sessionWindow.status,
286
286
  };
287
287
  }
288
+ // CLAWMONEY_FAKE_MODEL_USED — test-only lever. When set, rewrite the
289
+ // reported `model_used` field to the env var's value before returning
290
+ // to the Hub. Used to manually exercise the Hub's model-mismatch guard
291
+ // + quarantine flow without having to juggle real subscription tiers
292
+ // or fake upstream accounts. DO NOT set this in production.
293
+ const fakeModelUsed = process.env.CLAWMONEY_FAKE_MODEL_USED;
294
+ const reportedModel = fakeModelUsed || parsed.model || model;
295
+ if (fakeModelUsed) {
296
+ logger.warn(` ! CLAWMONEY_FAKE_MODEL_USED=${fakeModelUsed} — reporting fake model to Hub (test mode)`);
297
+ }
288
298
  return {
289
299
  event: "relay_response",
290
300
  request_id,
291
301
  content: parsed.text,
292
302
  cli_session_id: parsed.sessionId || undefined,
293
303
  usage: parsed.usage,
294
- model_used: parsed.model || model,
304
+ model_used: reportedModel,
295
305
  cost_usd: parsed.costUsd || undefined,
296
306
  session_window: sessionWindowTelemetry,
297
307
  };
@@ -447,6 +457,18 @@ export function runRelayProvider(cliOverride) {
447
457
  case "error":
448
458
  logger.error(`Server error: ${event.message}`);
449
459
  break;
460
+ case "relay_notice":
461
+ // Loud WARN for the human operator. Quarantine notices are the
462
+ // most important kind — they mean buyers are going to stop
463
+ // seeing this provider until the daemon is restarted, so we
464
+ // don't want them buried in the log.
465
+ logger.warn(`[NOTICE ${event.notice_type}] ${event.message}`);
466
+ if (event.notice_type === "model_mismatch_quarantine" &&
467
+ event.expected_model &&
468
+ event.got_model) {
469
+ logger.warn(` expected=${event.expected_model} got=${event.got_model} cli=${event.cli_type ?? "?"}`);
470
+ }
471
+ break;
450
472
  default:
451
473
  logger.warn("Unknown event:", event);
452
474
  }
@@ -30,7 +30,15 @@ export interface RelayErrorEvent {
30
30
  event: "error";
31
31
  message: string;
32
32
  }
33
- export type RelayIncomingEvent = RelayRequest | RelayConnectedEvent | RelayErrorEvent;
33
+ export interface RelayNoticeEvent {
34
+ event: "relay_notice";
35
+ notice_type: string;
36
+ cli_type?: string;
37
+ expected_model?: string;
38
+ got_model?: string;
39
+ message: string;
40
+ }
41
+ export type RelayIncomingEvent = RelayRequest | RelayConnectedEvent | RelayErrorEvent | RelayNoticeEvent;
34
42
  export interface RelayResponseSessionWindow {
35
43
  reset_at_ms: number;
36
44
  utilization?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawmoney",
3
- "version": "0.15.59",
3
+ "version": "0.15.60",
4
4
  "description": "ClawMoney CLI -- Earn rewards with your AI agent",
5
5
  "type": "module",
6
6
  "bin": {