Skip to content

fix(inbox): keep the cap booking on a paid but unusable reply, and enforce the default cap at run time (#455) - #457

Closed
secret-mars wants to merge 1 commit into
aibtcdev:mainfrom
secret-mars:fix/auto-reply-paid-parse-and-cap
Closed

secret-mars wants to merge 1 commit into
aibtcdev:mainfrom
secret-mars:fix/auto-reply-paid-parse-and-cap

Conversation

@secret-mars

Copy link
Copy Markdown
Contributor

Fixes items 1 and 5 of #455. Items 2, 3, 4 and 6 are left for separate PRs, because each one changes ledger or dry-run behaviour and deserves its own review.

1. A paid inference with an unusable body is no longer refunded to the daily cap.
In marketplaceReplyGenerator, the three failures after payment (a non-JSON body, no choices[0].message.content, an empty reply after cleanReply) threw a plain Error. paymentWasSent() only recognises PaidRequestError, so runAutoReply called releaseDailySats for sats that had actually been spent. They now throw PaidRequestError when result.paid, and stay a plain Error on the unpaid path.

Scope note: this makes the cap count the spend. It does not stop the message from being retried and paid for again on the next run. That is item 3 of #455 (no per-message give-up state), and it is unchanged here.

5. The run-time cap no longer silently disappears when the config has no dailyCapSats.
readAppConfig is an unvalidated JSON cast, and the default was applied only in auto-reply-config. With the key missing, spent + sats > undefined is always false, so no cap applied. The new resolveDailyCapSats() keeps a stored non-negative safe integer (including 0) and otherwise falls back to DEFAULT_DAILY_CAP_SATS. runAutoReply applies it, so any caller is covered, and inbox.ts uses it for both the run and the printed dailyCapSats.

Tests (bun test src/lib/services/inbox-auto-reply.service.test.ts: 22 pass; tsc --noEmit clean):

  • marketplaceReplyGenerator against the existing sponsored-payment fixture serves a paid 200 with each of the three unusable bodies, and expects PaidRequestError each time. serveEndpoint gained an optional URL so it can serve INFERENCE_GATEWAY.
  • resolveDailyCapSats keeps 250 and 0, and falls back for undefined, null, "500", -1, 1.5 and NaN.
  • Red check: with the two source changes reverted, exactly these 2 tests fail (20 pass, 2 fail).

The same shape exists in the aibtc-mcp-server port: src/services/inbox-auto-reply.service.ts:293-297 throws a plain Error after a paid response. It is not changed here, since the ledgers are shared but the code is separate.

No upstream doc covers this; it is the repo's own spend logic. The checks use Number.isSafeInteger (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger).

🤖 Generated with Claude Code

…force the default cap at run time (aibtcdev#455)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@secret-mars

Copy link
Copy Markdown
Contributor Author

Closing as superseded by #459 (bf47c25, merged 2026-10-29T12:13Z). It closes #455 and includes both changes here: PaidInferenceError for paid but unusable replies, and the run-time daily-cap default. It also covers items 2, 3, 4 and 6. Nothing in this PR is left uncovered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant