This repository has been archived on 2026-03-24 . You can view files and clone it. You cannot open issues or pull requests or push a commit.
3a617669f0147e49eeee341a30a06858539f3e17
1. Add `estimateRequestCost(request, model)` to PricingService in pricing.ts
- Unified method combining estimateInputTokens + estimateOutputTokens + calculateWorkFeeUsd
- Replaces duplicated token estimation logic at call sites in jobs.ts, sessions.ts, estimate.ts
2. Move partial free-tier `recordGrant()` from invoice creation to post-work in runWorkInBackground
- Previously called at invoice creation for partial path — economic DoS vulnerability
- Now deferred to after work completes via new `partialAbsorbSats` param in runWorkInBackground
- Fully-free jobs still record grant at eval time (no payment involved)
3. Sessions pre-gate: estimate → decide → execute → reconcile (with double-margin bug fix)
- Free-tier `decide()` now runs on ESTIMATED cost BEFORE `executeWork()` is called
- Fixed: estimateRequestCost already includes infra+margin via calculateWorkFeeUsd,
so convert estimatedCostUsd directly to sats — no second calculateActualChargeUsd call
- absorbedSats capped at actual cost post-execution (Math.min) to prevent over-absorption
4. Atomic pool deduction in recordGrant (free-tier.ts)
- Replaced non-atomic read-then-write pattern with SQL GREATEST expression inside transaction
- UPDATE timmyConfig SET value = GREATEST(value::int - absorbSats, 0)::text RETURNING value
- Audit log (freeTierGrants) receives actual post-deduct value from DB; no oversubscription
- Removed unused createHash import from free-tier.ts
Description
Timmy — Lightning-gated AI agent (TypeScript/Express)
Languages
TypeScript
68.2%
JavaScript
14.8%
Shell
12.4%
HTML
4.1%
CSS
0.4%