Commit Graph

13 Commits

Author SHA1 Message Date
a70898e939 feat(epic222): Workshop — Timmy as wizard presence, world state, WS bootstrap (#31) 2026-03-18 22:15:46 -04:00
ea4cddc2ad fix(api): completedAt: null on non-complete states + OpenAPI timestamps & rate-limit headers (#29) 2026-03-18 21:49:51 -04:00
83a2ec19e2 fix(testkit): macOS compat + fix test 8c ordering (#24) 2026-03-18 21:01:13 -04:00
alexpaynex
ab2cc06a79 Add session mode for pre-funded request processing
Implement session-based API endpoints for creating, managing, and interacting with pre-funded sessions, including deposit and top-up invoice generation, macaroon authentication, and per-request debiting of compute costs.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 418bf6f8-212b-4bb0-a7a5-8231a061da4e
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 2dc3847e-7186-4a22-9c7e-16cd31bca8d9
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/9f85e954-647c-46a5-90a7-396e495a805a/418bf6f8-212b-4bb0-a7a5-8231a061da4e/sPDHkg8
Replit-Helium-Checkpoint-Created: true
2026-03-18 20:00:24 +00:00
alexpaynex
dfc9ecdc7b Add honest accounting and automatic refund mechanism for completed jobs
Implement honest accounting post-job completion, calculating actual costs, adding margin, and enabling automatic refunds for overpayments via a new endpoint.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 418bf6f8-212b-4bb0-a7a5-8231a061da4e
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: c6386de2-d5f4-47cc-a557-73416f09e118
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/9f85e954-647c-46a5-90a7-396e495a805a/418bf6f8-212b-4bb0-a7a5-8231a061da4e/sPDHkg8
Replit-Helium-Checkpoint-Created: true
2026-03-18 19:32:34 +00:00
alexpaynex
e5bdae7159 Task #6: Cost-based work fee pricing with BTC oracle
## New files
- btc-oracle.ts: CoinGecko BTC/USD fetch (60s cache), usdToSats() helper (ceil, min 1 sat),
  5s abort timeout, fallback to BTC_PRICE_USD_FALLBACK env var (default $100k)
- lib/db/migrations/0002_cost_based_pricing.sql: SQL migration artifact adding 6 new columns
  to jobs table (estimated_cost_usd, margin_pct, btc_price_usd, actual_input_tokens,
  actual_output_tokens, actual_cost_usd); idempotent via ADD COLUMN IF NOT EXISTS

## Modified files
- pricing.ts: Full rewrite — per-model token rates (Haiku/Sonnet, env-var overridable),
  DO infra amortisation per request, originator margin %, estimateInputTokens/Output by tier,
  calculateActualCostUsd() for post-work ledger, async calculateWorkFeeSats() → WorkFeeBreakdown
- agent.ts: WorkResult now includes inputTokens + outputTokens from Anthropic usage;
  workModel/evalModel exposed as readonly public; EVAL_MODEL/WORK_MODEL env var support
- lib/db/src/schema/jobs.ts: 6 new real/integer columns; schema pushed to DB
- jobs.ts route: Work invoice creation calls pricingService.calculateWorkFeeSats() async;
  stores estimatedCostUsd/marginPct/btcPriceUsd; post-work stores actualInputTokens/
  actualOutputTokens/actualCostUsd; GET response includes pricingBreakdown and costLedger
  with totalTokens (input + output computed field)
- openapi.yaml: PricingBreakdown + CostLedger schemas (with totalTokens) added
- lib/api-zod/src/generated/api.ts: Regenerated with new schemas
- lib/api-client-react/src/generated/api.schemas.ts: Regenerated (PricingBreakdown, CostLedger)
- replit.md: 17 new env vars documented in cost-based pricing section
2026-03-18 19:25:06 +00:00
alexpaynex
69eba6190d Task #6: Cost-based work fee pricing with BTC oracle
- btc-oracle.ts: CoinGecko BTC/USD fetch (60s cache), usdToSats() helper,
  fallback to BTC_PRICE_USD_FALLBACK env var (default $100k), 5s abort timeout
- pricing.ts: Full rewrite — per-model token rates (Haiku/Sonnet, env-var
  overridable), DO infra amortisation, originator margin %, estimateInputTokens(),
  estimateOutputTokens() by request tier, calculateActualCostUsd() for post-work ledger,
  async calculateWorkFeeSats() → WorkFeeBreakdown
- agent.ts: WorkResult now includes inputTokens + outputTokens from Anthropic usage;
  workModel/evalModel exposed as readonly public; EVAL_MODEL/WORK_MODEL env var support
- jobs.ts: Work invoice creation calls pricingService.calculateWorkFeeSats() async;
  stores estimatedCostUsd/marginPct/btcPriceUsd on job; after executeWork stores
  actualInputTokens/actualOutputTokens/actualCostUsd; GET response includes
  pricingBreakdown (awaiting_work_payment) and costLedger (complete)
- lib/db/src/schema/jobs.ts: 6 new real/integer columns for cost tracking; schema pushed
- openapi.yaml: PricingBreakdown + CostLedger schemas added to JobStatusResponse
- replit.md: 17 new env vars documented in Cost-based work fee pricing section
2026-03-18 19:20:34 +00:00
alexpaynex
f43e782c50 Task #5: Lightning-gated node bootstrap (proof-of-concept)
Pay a Lightning invoice → Timmy auto-provisions a Bitcoin full node on DO.

New: lib/db/src/schema/bootstrap-jobs.ts
- bootstrap_jobs table: id, state, amountSats, paymentHash, paymentRequest,
  dropletId, nodeIp, tailscaleHostname, lnbitsUrl, sshPrivateKey,
  sshKeyDelivered (bool), errorMessage, createdAt, updatedAt
- States: awaiting_payment | provisioning | ready | failed
- Payment data stored inline (no FK to jobs/invoices tables — separate entity)
- db:push applied to create table in Postgres

New: artifacts/api-server/src/lib/provisioner.ts
- ProvisionerService: stubs when DO_API_TOKEN absent, real otherwise
- Stub mode: generates a real RSA 4096-bit SSH keypair via ssh-keygen,
  returns RFC 5737 test IP + fake Tailscale hostname after 2s delay
- Real mode: upload SSH public key to DO → generate Tailscale auth key →
  create DO droplet with cloud-init user_data → poll for public IP (2 min)
- buildCloudInitScript(): non-interactive bash that installs Docker + Tailscale
  + UFW + Bitcoin Knots via docker-compose; joins Tailscale if authkey provided
- provision() designed as fire-and-forget (void); updates DB to ready/failed

New: artifacts/api-server/src/routes/bootstrap.ts
- POST /api/bootstrap: create job + LNbits invoice, return paymentRequest
- GET /api/bootstrap/🆔 poll-driven state machine
  * awaiting_payment: checks payment, fires provisioner on confirm
  * provisioning: returns progress message
  * ready: delivers credentials; SSH private key delivered once then cleared
  * failed: returns error message
- Stub mode message includes the exact /dev/stub/pay URL for easy testing
- nextSteps array guides user through post-provision setup

Updated: artifacts/api-server/src/lib/pricing.ts
- Added bootstrapFee field reading BOOTSTRAP_FEE_SATS env var (default 10000)
- calculateBootstrapFeeSats() method

Updated: artifacts/api-server/src/routes/index.ts
- Mounts bootstrapRouter

Updated: replit.md
- Documents all 7 new env vars (DO_API_TOKEN, DO_REGION, DO_SIZE, etc.)
- Full curl-based flow example with annotated response shape

End-to-end verified in stub mode: POST → pay → provisioning → ready (SSH key)
→ second GET clears key and shows sshKeyNote
2026-03-18 18:47:48 +00:00
alexpaynex
f5811da508 Improve input validation and error messaging for user requests
Update API endpoints for jobs and demo routes to enforce a maximum character limit of 500 for the 'request' field. Refine error messages to distinguish between missing input and input exceeding the character limit.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 418bf6f8-212b-4bb0-a7a5-8231a061da4e
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 8c43b6a7-30d3-4806-8d46-3d364b17c284
Replit-Helium-Checkpoint-Created: true
2026-03-18 17:33:21 +00:00
alexpaynex
4e8adbcb93 Task #3: MVP API — payment-gated jobs + demo endpoint
OpenAPI spec (lib/api-spec/openapi.yaml)
- Added POST /jobs, GET /jobs/{id}, GET /demo endpoints
- Added schemas: CreateJobRequest, CreateJobResponse, JobStatusResponse,
  InvoiceInfo, JobState, DemoResponse, ErrorResponse
- Ran codegen: generated CreateJobBody, GetJobResponse, RunDemoQueryParams etc.

Jobs router (artifacts/api-server/src/routes/jobs.ts)
- POST /jobs: validates body, creates LNbits eval invoice, inserts job +
  invoice in a DB transaction, returns { jobId, evalInvoice }
- GET /jobs/🆔 fetches job, calls advanceJob() helper, returns state-
  appropriate payload (eval/work invoice, reason, result, errorMessage)
- advanceJob() state machine:
  - awaiting_eval_payment: checks LNbits, atomically marks paid + advances
    state via optimistic WHERE state='awaiting_eval_payment'; runs
    AgentService.evaluateRequest, branches to awaiting_work_payment or rejected
  - awaiting_work_payment: same pattern for work invoice, runs
    AgentService.executeWork, advances to complete
  - Any agent/LNbits error transitions job to failed

Demo router (artifacts/api-server/src/routes/demo.ts)
- GET /demo?request=...: in-memory rate limiter (5 req/hour per IP)
- Explicit guard for missing request param (coerce.string() workaround)
- Calls AgentService.executeWork directly, returns { result }

Dev router (artifacts/api-server/src/routes/dev.ts)
- POST /dev/stub/pay/:paymentHash: marks stub invoice paid in-memory
- Only mounted when NODE_ENV !== 'production'

Route index updated to mount all three routers

replit.md: documented full curl flow with all 6 steps, demo endpoint,
and dev stub-pay trigger

End-to-end verified with curl:
- Full flow: create → eval pay → evaluating → work pay → executing → complete
- Error cases: 400 on missing body/param, 404 on unknown job
2026-03-18 15:31:26 +00:00
alexpaynex
9ec5e20a10 Add a foreign key constraint to link invoices to specific jobs
Adds a foreign key constraint to the `invoices` table, referencing the `id` column in the `jobs` table, ensuring data integrity.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 418bf6f8-212b-4bb0-a7a5-8231a061da4e
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: d9dd1cc2-bc61-41c5-90bb-94504f4308a9
Replit-Helium-Checkpoint-Created: true
2026-03-18 15:21:33 +00:00
alexpaynex
b095efcfd3 Add AI agent capabilities and integrate with Anthropic and LNbits
Integrate Anthropic AI for agent capabilities, introduce database schemas for jobs and invoices, and set up LNbits for payment processing.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 418bf6f8-212b-4bb0-a7a5-8231a061da4e
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: cce28acc-aeac-46ff-80ec-af4ade39e30f
Replit-Helium-Checkpoint-Created: true
2026-03-18 14:59:02 +00:00
agent
c8ed262197 Initial commit 2026-03-13 23:21:55 +00:00