mcp-scraper 0.90.6 → 0.90.8

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.
Files changed (51) hide show
  1. package/CHANGELOG.md +49 -2
  2. package/README.md +2 -2
  3. package/dist/{analytics-repository-WNJESD4A.js → analytics-repository-IHOFBSUV.js} +1 -1
  4. package/dist/bin/api-server.js +1 -1
  5. package/dist/bin/mcp-scraper-cli.js +1 -1
  6. package/dist/bin/mcp-scraper-core.js +1 -1
  7. package/dist/bin/mcp-scraper-install.js +1 -1
  8. package/dist/bin/mcp-stdio-server.js +1 -1
  9. package/dist/bin/paa-harvest.js +1 -1
  10. package/dist/{chunk-MADTJXNI.js → chunk-2F35B4U5.js} +105 -105
  11. package/dist/{chunk-56UT5M5Y.js → chunk-2SP57VCG.js} +5 -5
  12. package/dist/{chunk-XARSC34L.js → chunk-53IEEOKA.js} +167 -167
  13. package/dist/chunk-6DTXIZY2.js +1 -0
  14. package/dist/{chunk-WDB5CTRY.js → chunk-6FMIMP5Z.js} +1 -1
  15. package/dist/chunk-7SHEBDEB.js +1 -0
  16. package/dist/{chunk-NWRRVZKW.js → chunk-DKXZIIA5.js} +1 -1
  17. package/dist/{chunk-XXK5PLRB.js → chunk-IK5BG7MO.js} +9 -8
  18. package/dist/{chunk-AQSMJCTF.js → chunk-J374DIKA.js} +1 -1
  19. package/dist/{chunk-AAJG5OHF.js → chunk-KZV2FLGG.js} +1 -1
  20. package/dist/{chunk-4OTWTGKC.js → chunk-LI7WHOII.js} +1 -1
  21. package/dist/{chunk-BVSK6YHX.js → chunk-LSFDB5XE.js} +1 -1
  22. package/dist/{chunk-5MMN27Q6.js → chunk-OIMPG6M6.js} +1 -1
  23. package/dist/{chunk-YDOBZMLS.js → chunk-OMYTA34L.js} +1 -1
  24. package/dist/chunk-ORB4RHCK.js +63 -0
  25. package/dist/chunk-OVTHAIDS.js +1 -0
  26. package/dist/{chunk-Q5SUDDSQ.js → chunk-QTDLZTQ7.js} +1 -1
  27. package/dist/chunk-RK2VCTZI.js +1 -0
  28. package/dist/{chunk-KKHTMYCD.js → chunk-WJ4XFLS4.js} +160 -115
  29. package/dist/{chunk-COIA4RW4.js → chunk-X7GZJU5P.js} +1 -1
  30. package/dist/{chunk-D6BTAT5Y.js → chunk-YGBTTW5D.js} +1 -1
  31. package/dist/{chunk-AQXYXVOP.js → chunk-ZMNUI5LB.js} +7 -7
  32. package/dist/db-B5XJTOGN.js +1 -0
  33. package/dist/{extract-bundle-CP6WBOJI.js → extract-bundle-II3RPATK.js} +10 -10
  34. package/dist/gmail-service-E5KORS6C.js +1 -0
  35. package/dist/index.cjs +17 -17
  36. package/dist/index.js +1 -1
  37. package/dist/{lead-list-enrichment-repository-AIMOP7YM.js → lead-list-enrichment-repository-AWZZMY2H.js} +1 -1
  38. package/dist/{location-data-repository-25D3GHXE.js → location-data-repository-6XAVI65Z.js} +1 -1
  39. package/dist/operation-metering-DB5F7SXN.js +1 -0
  40. package/dist/server-MI6XN25Z.js +4961 -0
  41. package/dist/{site-extract-repository-KG6FQU55.js → site-extract-repository-JHSVJJ62.js} +1 -1
  42. package/dist/stripe-event-worker-7KNF3VH5.js +1 -0
  43. package/dist/worker-3VTFFYHH.js +1 -0
  44. package/package.json +1 -1
  45. package/dist/chunk-NOUHD54C.js +0 -48
  46. package/dist/chunk-UM4WSLKQ.js +0 -1
  47. package/dist/db-XN7YPDGC.js +0 -1
  48. package/dist/gmail-service-5NH2GVQ5.js +0 -1
  49. package/dist/server-TQJ6Z3ZF.js +0 -4931
  50. package/dist/stripe-event-worker-ZNNQEVK4.js +0 -1
  51. package/dist/worker-4LFWAEX2.js +0 -1
@@ -1,4 +1,4 @@
1
- import{createClient as Be}from"@libsql/client/http";import{createHash as U,randomBytes as P,randomUUID as N,scryptSync as pe,timingSafeEqual as Ge}from"crypto";import{z as p}from"zod";var D="2026-06-26 21:58:03";var dt="Google returned a CAPTCHA. Run with --headless=false to re-warm the browser profile, then retry.",xe="This operation is temporarily unavailable. Please retry later.",Ie=["request_aborted","captcha_exhausted","captcha_or_blocked","location_mismatch","proxy_tunnel_failed","proxy_unavailable","harvest_timeout","mcp_request_timeout","mcp_http_error","extraction_failed","concurrency_limit_exceeded","unauthorized","forbidden","invalid_request","rate_limited","upstream_rate_limited","insufficient_balance","service_unavailable","response_lost","vendor_unavailable","page_not_found","page_forbidden","page_rate_limited","page_server_error","page_http_error","bot_check_unresolved","page_too_large","page_unreachable","browser_session_interrupted","site_export_not_found","site_export_format_unavailable","site_export_read_failed","site_export_image_not_found","image_url_invalid","image_url_not_https","image_host_unresolvable","image_host_blocked","image_redirect_invalid","image_source_unavailable","image_too_large","image_redirect_limit","image_base64_invalid","image_source_missing","image_source_ambiguous","image_source_type_invalid","image_artifact_not_found","image_page_too_large","page_image_not_found","page_image_candidates_unusable","image_format_unsupported","image_storage_unconfigured","featured_image_unhostable"],ye=["request_aborted","captcha","location_mismatch","connection","timeout","extraction","concurrency_limit","unauthorized","forbidden","invalid_request","rate_limit","billing","service_unavailable"];function w(e){return e?JSON.stringify(e):null}function se(e){if(e==null)return null;try{let t=typeof e=="string"?JSON.parse(e):e;if(!t||typeof t!="object"||Array.isArray(t))return null;let r=t;if(typeof r.error_code!="string"||!ie.has(r.error_code))return null;let n=Pe({errorCode:r.error_code,errorType:r.error_type,retryable:r.retryable,retryAfterSeconds:r.retry_after_seconds,chargeStatus:r.charge_status,details:r.details});if(typeof r.message=="string"){let i=ae(r.message).trim().slice(0,1e3);i&&!/https?:\/\//i.test(i)&&(n.message=i)}return n}catch{return null}}var ie=new Set(Ie),Ce=new Set(ye),Ue=new Set(["active","limit","operation","upgrade_url","topup_url","upgrade_command","slots_per_pack","pack_price_usd","balance_credits","required_credits","retry_guidance","http_status"]),De=12,ke=500;function W(e){return typeof e=="string"&&ie.has(e)?e:"service_unavailable"}function ve(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t={};for(let[r,n]of Object.entries(e)){if(Object.keys(t).length>=De)break;if(Ue.has(r))if(typeof n=="string"){if((r==="upgrade_url"||r==="topup_url")&&!Xe(n))continue;let i=ae(n).slice(0,ke);i&&(t[r]=i)}else(typeof n=="number"&&Number.isFinite(n)||typeof n=="boolean"||n===null)&&(t[r]=n)}return Object.keys(t).length>0?t:void 0}function Xe(e){if(e.startsWith("/")&&!e.startsWith("//"))return!0;try{let t=new URL(e);return t.protocol==="https:"&&(t.hostname==="mcpscraper.dev"||t.hostname.endsWith(".mcpscraper.dev"))}catch{return!1}}function Me(e){let t=W(e);switch(t){case"captcha_exhausted":case"captcha_or_blocked":return"captcha";case"proxy_tunnel_failed":case"proxy_unavailable":case"response_lost":return"connection";case"harvest_timeout":case"mcp_request_timeout":return"timeout";case"concurrency_limit_exceeded":return"concurrency_limit";case"rate_limited":case"upstream_rate_limited":return"rate_limit";case"extraction_failed":case"page_not_found":case"page_forbidden":case"page_rate_limited":case"page_server_error":case"page_http_error":case"bot_check_unresolved":case"page_too_large":case"page_unreachable":case"browser_session_interrupted":case"site_export_not_found":case"site_export_format_unavailable":case"site_export_read_failed":case"site_export_image_not_found":return"extraction";case"image_url_invalid":case"image_url_not_https":case"image_host_unresolvable":case"image_host_blocked":case"image_redirect_invalid":case"image_source_unavailable":case"image_too_large":case"image_redirect_limit":case"image_base64_invalid":case"image_source_missing":case"image_source_ambiguous":case"image_source_type_invalid":case"image_artifact_not_found":case"image_page_too_large":case"page_image_not_found":case"page_image_candidates_unusable":case"image_format_unsupported":case"image_storage_unconfigured":case"featured_image_unhostable":return"invalid_request";case"insufficient_balance":return"billing";case"vendor_unavailable":case"mcp_http_error":return"service_unavailable";default:return t}}function Fe(e){switch(W(e)){case"request_aborted":return"The request was cancelled before it completed.";case"captcha_exhausted":case"captcha_or_blocked":return"The target site returned a verification challenge. Heavy traffic can temporarily increase these challenges; retry in a few minutes.";case"location_mismatch":return"The target site returned results for a different location. Please retry.";case"proxy_tunnel_failed":case"proxy_unavailable":return"The web request could not establish a working connection. Please retry later.";case"harvest_timeout":return"The request timed out before it completed. Please retry with a smaller request.";case"mcp_request_timeout":return"The MCP caller stopped waiting before a final response arrived. Durable work may still be running; continue with the returned Task or job handle instead of restarting it.";case"concurrency_limit_exceeded":return"The service is available, but this account has reached its parallel-operation limit. Wait for an active operation to finish or add capacity.";case"unauthorized":return"Authentication is required to perform this operation.";case"forbidden":return"This account does not have permission to perform this operation.";case"invalid_request":return"The request is invalid. Check the supplied inputs and try again.";case"rate_limited":return"This account is sending requests too quickly. Wait briefly and retry.";case"upstream_rate_limited":return"The connected provider is temporarily rate-limiting requests. Wait briefly and retry.";case"mcp_http_error":return"The API returned an unexpected HTTP response.";case"insufficient_balance":return"This account does not have enough Credits for the operation.";case"extraction_failed":return"The target could not be extracted. Please retry later.";case"response_lost":return"The connection was lost before the response arrived. The operation may have already completed and been billed on our side \u2014 check credits_info before retrying blind.";case"vendor_unavailable":return"MCP Scraper's internal browser services require MCP Scraper team attention. Servers or IPs are down until this is fixed \u2014 this is not caused by your request. Please retry in a few minutes.";case"page_not_found":return"The page could not be found. It may have been moved or deleted.";case"page_forbidden":return"The site refused the request.";case"page_rate_limited":return"The site is rate-limiting requests right now. Retrying after a short wait usually works.";case"page_server_error":return"The page's own server returned an error. This is on the target site's side, not something a retry here can fix.";case"page_http_error":return"The page returned an unexpected HTTP response.";case"bot_check_unresolved":return"This site has automated-traffic protection (a bot/CAPTCHA check) that could not be resolved in time. Some sites are simply not extractable this way.";case"page_too_large":return"The page is larger than we can safely process.";case"page_unreachable":return"The page did not respond in time, or the connection could not be completed.";case"browser_session_interrupted":return"The browser session closed before extraction completed. MCP Scraper will retry once with a fresh session; retry the request if this persists.";case"site_export_not_found":return"The site export or requested page was not found, expired, or does not belong to this account.";case"site_export_format_unavailable":return"That representation was not retained for this export page. Read the export manifest and request one of the formats marked available.";case"site_export_read_failed":return"The stored site export could not be read or did not pass its integrity check.";case"site_export_image_not_found":return"The requested site-export image was not found, expired, or does not belong to this account.";case"image_url_invalid":return"The image source is not a valid URL. Use a stable public HTTPS URL or inline image bytes.";case"image_url_not_https":return"Commons image sources must use a public HTTPS URL or inline image bytes.";case"image_host_unresolvable":return"The image host could not be resolved. Use a different stable public URL or inline image bytes.";case"image_host_blocked":return"The image source resolves to a network address Commons cannot fetch safely.";case"image_redirect_invalid":return"The image source redirected to an invalid or unsafe destination.";case"image_source_unavailable":return"The image source could not be fetched. Host a different stable public URL or provide inline image bytes.";case"image_too_large":return"The image exceeds the Commons image size limit.";case"image_redirect_limit":return"The image source exceeded the Commons redirect limit.";case"image_base64_invalid":return"The supplied inline image bytes are invalid.";case"image_source_missing":return"Provide exactly one of a public image or webpage URL, inline image bytes, or an owner-scoped image artifact.";case"image_source_ambiguous":return"Provide only one image source: sourceUrl, imageBase64, or artifactId.";case"image_source_type_invalid":return"Use sourceType only with inline image bytes or an owner-scoped image artifact.";case"image_artifact_not_found":return"The image artifact was not found, expired, or does not belong to this account.";case"image_page_too_large":return"The webpage is too large for bounded Commons image discovery.";case"page_image_not_found":return"The webpage did not expose a usable featured or content image.";case"page_image_candidates_unusable":return"The webpage exposed image candidates, but none returned supported public image bytes.";case"image_format_unsupported":return"Commons accepts JPEG, PNG, GIF, or WebP image bytes.";case"image_storage_unconfigured":return"Commons image storage is temporarily unavailable.";case"featured_image_unhostable":return"The required featured image could not be hosted for Commons publication.";default:return xe}}function Pe(e){let t=W(e.errorCode),r=typeof e.retryAfterSeconds=="number"&&Number.isFinite(e.retryAfterSeconds)?Math.max(1,Math.min(86400,Math.trunc(e.retryAfterSeconds))):void 0,n=e.chargeStatus==="not_charged"||e.chargeStatus==="refund_pending"||e.chargeStatus==="refunded"||e.chargeStatus==="charged"?e.chargeStatus:void 0,i=typeof e.errorType=="string"&&Ce.has(e.errorType)?e.errorType:void 0,a=ve(e.details);return{error_code:t,error_type:i??Me(t),message:Fe(t),retryable:e.retryable===!0,...r?{retry_after_seconds:r}:{},...n?{charge_status:n}:{},...a?{details:a}:{}}}function ae(e){return e.replace((new RegExp("https?:\\/\\/[^\\s]*(?:\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061|on\u006b\u0065\u0072\u006e\u0065\u006c|\u006b\u0065\u0072\u006e\u0065\u006c\\.sh)[^\\s]*", "gi")),"the service").replace(/bright\s*data/gi,"the service").replace((new RegExp("\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061", "gi")),"the service").replace((new RegExp("\u006b\u0065\u0072\u006e\u0065\u006c\\.sh\\s+sessions?", "gi")),"sessions").replace((new RegExp("\u006b\u0065\u0072\u006e\u0065\u006c\\.sh\\s+session", "gi")),"this session").replace((new RegExp("\u006b\u0065\u0072\u006e\u0065\u006c\\.sh", "gi")),"the service").replace((new RegExp("\u006b\u0065\u0072\u006e\u0065\u006c\\s+sessions?", "gi")),"sessions").replace((new RegExp("\u006b\u0065\u0072\u006e\u0065\u006c\\s+session", "gi")),"this session").replace(/\b(?:sub|cus|sess|proxy)_[A-Za-z0-9_-]+\b/g,"[redacted]").replace((new RegExp("\\b(?:\u004b\u0045\u0052\u004e\u0045\u004c|\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041|\u0042\u0052\u0049\u0047\u0048\u0054_\u0044\u0041\u0054\u0041)_[A-Z0-9_]*API_KEY\\b", "g")),"BROWSER_SERVICE_API_KEY").replace((new RegExp("\\b\u006b\u0065\u0072\u006e\u0065\u006c\\b", "gi")),"the service").replace(/ +/g," ").trim()}var Q=class extends Error{constructor(r){super(`CAPTCHA detected. ${r}`);this.instructions=r}instructions;name="CaptchaError"},Z=class extends Error{constructor(r,n){super(r);this.cause=n}cause;name="ExtractionError"},ee=class extends Error{constructor(r){super(`Google Maps search did not reach a complete result state (${r})`);this.pageState=r}pageState;name="MapsSearchIncompletePageError"},te=class extends Error{name="RequestAbortedError";constructor(t="Request aborted before harvest completed"){super(t)}},re=class extends Error{name="PaaInteractionInterruptedError"},ne=class extends Error{name="LocationMismatchError";constructor(t="Google returned results for a different location than requested"){super(t)}};var f=["oauth_store_metadata","oauth_clients","oauth_client_redirect_uris","oauth_codes","oauth_code_exchanges","oauth_refresh_families","oauth_refresh_tokens","oauth_refresh_rotations","oauth_security_events","oauth_rate_limit_buckets"],h=["oauth_clients_inactivity_idx","oauth_clients_cleanup_idx","oauth_codes_expiry_idx","oauth_codes_client_idx","oauth_code_exchanges_replay_expiry_idx","oauth_refresh_families_lifecycle_idx","oauth_refresh_families_user_status_idx","oauth_refresh_families_client_idx","oauth_refresh_families_cleanup_idx","oauth_refresh_tokens_expiry_idx","oauth_refresh_rotations_replay_expiry_idx","oauth_security_events_retention_idx","oauth_rate_limit_buckets_expiry_idx"],oe={oauth_clients:"oauth_clients_legacy_raw",oauth_codes:"oauth_codes_legacy_raw",oauth_tokens:"oauth_tokens_legacy_raw"},L="strftime('%Y-%m-%dT%H:%M:%fZ','now')";async function x(e,t,r=!1){try{await e.execute(t)}catch(n){let i=n.code;if(!r||i!=="SQL_PARSE_ERROR")throw n}}var He=[`CREATE TABLE IF NOT EXISTS oauth_store_metadata (
1
+ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,randomBytes as q,randomUUID as N,scryptSync as Ne,timingSafeEqual as ze}from"crypto";import{z as p}from"zod";var k="2026-06-26 21:58:03";var Lt="Google returned a CAPTCHA. Run with --headless=false to re-warm the browser profile, then retry.",ve="This operation is temporarily unavailable. Please retry later.",ke=["request_aborted","captcha_exhausted","captcha_or_blocked","location_mismatch","proxy_tunnel_failed","proxy_unavailable","harvest_timeout","mcp_request_timeout","mcp_http_error","extraction_failed","concurrency_limit_exceeded","unauthorized","forbidden","invalid_request","rate_limited","upstream_rate_limited","insufficient_balance","service_unavailable","response_lost","vendor_unavailable","page_not_found","page_forbidden","page_rate_limited","page_server_error","page_http_error","bot_check_unresolved","page_too_large","page_unreachable","browser_session_interrupted","site_export_not_found","site_export_format_unavailable","site_export_read_failed","site_export_image_not_found","image_url_invalid","image_url_not_https","image_host_unresolvable","image_host_blocked","image_redirect_invalid","image_source_unavailable","image_too_large","image_redirect_limit","image_base64_invalid","image_source_missing","image_source_ambiguous","image_source_type_invalid","image_artifact_not_found","image_page_too_large","page_image_not_found","page_image_candidates_unusable","image_format_unsupported","image_storage_unconfigured","featured_image_unhostable"],Xe=["request_aborted","captcha","location_mismatch","connection","timeout","extraction","concurrency_limit","unauthorized","forbidden","invalid_request","rate_limit","billing","service_unavailable"];function O(e){return e?JSON.stringify(e):null}function ae(e){if(e==null)return null;try{let t=typeof e=="string"?JSON.parse(e):e;if(!t||typeof t!="object"||Array.isArray(t))return null;let r=t;if(typeof r.error_code!="string"||!oe.has(r.error_code))return null;let n=Ge({errorCode:r.error_code,errorType:r.error_type,retryable:r.retryable,retryAfterSeconds:r.retry_after_seconds,chargeStatus:r.charge_status,details:r.details});if(typeof r.message=="string"){let s=_e(r.message).trim().slice(0,1e3);s&&!/https?:\/\//i.test(s)&&(n.message=s)}return n}catch{return null}}var oe=new Set(ke),Me=new Set(Xe),Fe=new Set(["active","limit","operation","upgrade_url","topup_url","upgrade_command","slots_per_pack","pack_price_usd","balance_credits","required_credits","retry_guidance","http_status"]),Pe=12,He=500;function j(e){return typeof e=="string"&&oe.has(e)?e:"service_unavailable"}function qe(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t={};for(let[r,n]of Object.entries(e)){if(Object.keys(t).length>=Pe)break;if(Fe.has(r))if(typeof n=="string"){if((r==="upgrade_url"||r==="topup_url")&&!We(n))continue;let s=_e(n).slice(0,He);s&&(t[r]=s)}else(typeof n=="number"&&Number.isFinite(n)||typeof n=="boolean"||n===null)&&(t[r]=n)}return Object.keys(t).length>0?t:void 0}function We(e){if(e.startsWith("/")&&!e.startsWith("//"))return!0;try{let t=new URL(e);return t.protocol==="https:"&&(t.hostname==="mcpscraper.dev"||t.hostname.endsWith(".mcpscraper.dev"))}catch{return!1}}function je(e){let t=j(e);switch(t){case"captcha_exhausted":case"captcha_or_blocked":return"captcha";case"proxy_tunnel_failed":case"proxy_unavailable":case"response_lost":return"connection";case"harvest_timeout":case"mcp_request_timeout":return"timeout";case"concurrency_limit_exceeded":return"concurrency_limit";case"rate_limited":case"upstream_rate_limited":return"rate_limit";case"extraction_failed":case"page_not_found":case"page_forbidden":case"page_rate_limited":case"page_server_error":case"page_http_error":case"bot_check_unresolved":case"page_too_large":case"page_unreachable":case"browser_session_interrupted":case"site_export_not_found":case"site_export_format_unavailable":case"site_export_read_failed":case"site_export_image_not_found":return"extraction";case"image_url_invalid":case"image_url_not_https":case"image_host_unresolvable":case"image_host_blocked":case"image_redirect_invalid":case"image_source_unavailable":case"image_too_large":case"image_redirect_limit":case"image_base64_invalid":case"image_source_missing":case"image_source_ambiguous":case"image_source_type_invalid":case"image_artifact_not_found":case"image_page_too_large":case"page_image_not_found":case"page_image_candidates_unusable":case"image_format_unsupported":case"image_storage_unconfigured":case"featured_image_unhostable":return"invalid_request";case"insufficient_balance":return"billing";case"vendor_unavailable":case"mcp_http_error":return"service_unavailable";default:return t}}function Be(e){switch(j(e)){case"request_aborted":return"The request was cancelled before it completed.";case"captcha_exhausted":case"captcha_or_blocked":return"The target site returned a verification challenge. Heavy traffic can temporarily increase these challenges; retry in a few minutes.";case"location_mismatch":return"The target site returned results for a different location. Please retry.";case"proxy_tunnel_failed":case"proxy_unavailable":return"The web request could not establish a working connection. Please retry later.";case"harvest_timeout":return"The request timed out before it completed. Please retry with a smaller request.";case"mcp_request_timeout":return"The MCP caller stopped waiting before a final response arrived. Durable work may still be running; continue with the returned Task or job handle instead of restarting it.";case"concurrency_limit_exceeded":return"The service is available, but this account has reached its parallel-operation limit. Wait for an active operation to finish or add capacity.";case"unauthorized":return"Authentication is required to perform this operation.";case"forbidden":return"This account does not have permission to perform this operation.";case"invalid_request":return"The request is invalid. Check the supplied inputs and try again.";case"rate_limited":return"This account is sending requests too quickly. Wait briefly and retry.";case"upstream_rate_limited":return"The connected provider is temporarily rate-limiting requests. Wait briefly and retry.";case"mcp_http_error":return"The API returned an unexpected HTTP response.";case"insufficient_balance":return"This account does not have enough Credits for the operation.";case"extraction_failed":return"The target could not be extracted. Please retry later.";case"response_lost":return"The connection was lost before the response arrived. The operation may have already completed and been billed on our side \u2014 check credits_info before retrying blind.";case"vendor_unavailable":return"MCP Scraper's internal browser services require MCP Scraper team attention. Servers or IPs are down until this is fixed \u2014 this is not caused by your request. Please retry in a few minutes.";case"page_not_found":return"The page could not be found. It may have been moved or deleted.";case"page_forbidden":return"The site refused the request.";case"page_rate_limited":return"The site is rate-limiting requests right now. Retrying after a short wait usually works.";case"page_server_error":return"The page's own server returned an error. This is on the target site's side, not something a retry here can fix.";case"page_http_error":return"The page returned an unexpected HTTP response.";case"bot_check_unresolved":return"This site has automated-traffic protection (a bot/CAPTCHA check) that could not be resolved in time. Some sites are simply not extractable this way.";case"page_too_large":return"The page is larger than we can safely process.";case"page_unreachable":return"The page did not respond in time, or the connection could not be completed.";case"browser_session_interrupted":return"The browser session closed before extraction completed. MCP Scraper will retry once with a fresh session; retry the request if this persists.";case"site_export_not_found":return"The site export or requested page was not found, expired, or does not belong to this account.";case"site_export_format_unavailable":return"That representation was not retained for this export page. Read the export manifest and request one of the formats marked available.";case"site_export_read_failed":return"The stored site export could not be read or did not pass its integrity check.";case"site_export_image_not_found":return"The requested site-export image was not found, expired, or does not belong to this account.";case"image_url_invalid":return"The image source is not a valid URL. Use a stable public HTTPS URL or inline image bytes.";case"image_url_not_https":return"Commons image sources must use a public HTTPS URL or inline image bytes.";case"image_host_unresolvable":return"The image host could not be resolved. Use a different stable public URL or inline image bytes.";case"image_host_blocked":return"The image source resolves to a network address Commons cannot fetch safely.";case"image_redirect_invalid":return"The image source redirected to an invalid or unsafe destination.";case"image_source_unavailable":return"The image source could not be fetched. Host a different stable public URL or provide inline image bytes.";case"image_too_large":return"The image exceeds the Commons image size limit.";case"image_redirect_limit":return"The image source exceeded the Commons redirect limit.";case"image_base64_invalid":return"The supplied inline image bytes are invalid.";case"image_source_missing":return"Provide exactly one of a public image or webpage URL, inline image bytes, or an owner-scoped image artifact.";case"image_source_ambiguous":return"Provide only one image source: sourceUrl, imageBase64, or artifactId.";case"image_source_type_invalid":return"Use sourceType only with inline image bytes or an owner-scoped image artifact.";case"image_artifact_not_found":return"The image artifact was not found, expired, or does not belong to this account.";case"image_page_too_large":return"The webpage is too large for bounded Commons image discovery.";case"page_image_not_found":return"The webpage did not expose a usable featured or content image.";case"page_image_candidates_unusable":return"The webpage exposed image candidates, but none returned supported public image bytes.";case"image_format_unsupported":return"Commons accepts JPEG, PNG, GIF, or WebP image bytes.";case"image_storage_unconfigured":return"Commons image storage is temporarily unavailable.";case"featured_image_unhostable":return"The required featured image could not be hosted for Commons publication.";default:return ve}}function Ge(e){let t=j(e.errorCode),r=typeof e.retryAfterSeconds=="number"&&Number.isFinite(e.retryAfterSeconds)?Math.max(1,Math.min(86400,Math.trunc(e.retryAfterSeconds))):void 0,n=e.chargeStatus==="not_charged"||e.chargeStatus==="refund_pending"||e.chargeStatus==="refunded"||e.chargeStatus==="charged"?e.chargeStatus:void 0,s=typeof e.errorType=="string"&&Me.has(e.errorType)?e.errorType:void 0,a=qe(e.details);return{error_code:t,error_type:s??je(t),message:Be(t),retryable:e.retryable===!0,...r?{retry_after_seconds:r}:{},...n?{charge_status:n}:{},...a?{details:a}:{}}}function _e(e){return e.replace((new RegExp("https?:\\/\\/[^\\s]*(?:\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061|on\u006b\u0065\u0072\u006e\u0065\u006c|\u006b\u0065\u0072\u006e\u0065\u006c\\.sh)[^\\s]*", "gi")),"the service").replace(/bright\s*data/gi,"the service").replace((new RegExp("\u0062\u0072\u0069\u0067\u0068\u0074\u0064\u0061\u0074\u0061", "gi")),"the service").replace((new RegExp("\u006b\u0065\u0072\u006e\u0065\u006c\\.sh\\s+sessions?", "gi")),"sessions").replace((new RegExp("\u006b\u0065\u0072\u006e\u0065\u006c\\.sh\\s+session", "gi")),"this session").replace((new RegExp("\u006b\u0065\u0072\u006e\u0065\u006c\\.sh", "gi")),"the service").replace((new RegExp("\u006b\u0065\u0072\u006e\u0065\u006c\\s+sessions?", "gi")),"sessions").replace((new RegExp("\u006b\u0065\u0072\u006e\u0065\u006c\\s+session", "gi")),"this session").replace(/\b(?:sub|cus|sess|proxy)_[A-Za-z0-9_-]+\b/g,"[redacted]").replace((new RegExp("\\b(?:\u004b\u0045\u0052\u004e\u0045\u004c|\u0042\u0052\u0049\u0047\u0048\u0054\u0044\u0041\u0054\u0041|\u0042\u0052\u0049\u0047\u0048\u0054_\u0044\u0041\u0054\u0041)_[A-Z0-9_]*API_KEY\\b", "g")),"BROWSER_SERVICE_API_KEY").replace((new RegExp("\\b\u006b\u0065\u0072\u006e\u0065\u006c\\b", "gi")),"the service").replace(/ +/g," ").trim()}var ee=class extends Error{constructor(r){super(`CAPTCHA detected. ${r}`);this.instructions=r}instructions;name="CaptchaError"},te=class extends Error{constructor(r,n){super(r);this.cause=n}cause;name="ExtractionError"},re=class extends Error{constructor(r){super(`Google Maps search did not reach a complete result state (${r})`);this.pageState=r}pageState;name="MapsSearchIncompletePageError"},ne=class extends Error{name="RequestAbortedError";constructor(t="Request aborted before harvest completed"){super(t)}},se=class extends Error{name="PaaInteractionInterruptedError"},ie=class extends Error{name="LocationMismatchError";constructor(t="Google returned results for a different location than requested"){super(t)}};var I=["oauth_store_metadata","oauth_clients","oauth_client_redirect_uris","oauth_codes","oauth_code_exchanges","oauth_refresh_families","oauth_refresh_tokens","oauth_refresh_rotations","oauth_security_events","oauth_rate_limit_buckets"],x=["oauth_clients_inactivity_idx","oauth_clients_cleanup_idx","oauth_codes_expiry_idx","oauth_codes_client_idx","oauth_code_exchanges_replay_expiry_idx","oauth_refresh_families_lifecycle_idx","oauth_refresh_families_user_status_idx","oauth_refresh_families_client_idx","oauth_refresh_families_cleanup_idx","oauth_refresh_tokens_expiry_idx","oauth_refresh_rotations_replay_expiry_idx","oauth_security_events_retention_idx","oauth_rate_limit_buckets_expiry_idx"],ue={oauth_clients:"oauth_clients_legacy_raw",oauth_codes:"oauth_codes_legacy_raw",oauth_tokens:"oauth_tokens_legacy_raw"},L="strftime('%Y-%m-%dT%H:%M:%fZ','now')";async function y(e,t,r=!1){try{await e.execute(t)}catch(n){let s=n.code;if(!r||s!=="SQL_PARSE_ERROR")throw n}}var Ye=[`CREATE TABLE IF NOT EXISTS oauth_store_metadata (
2
2
  id INTEGER PRIMARY KEY CHECK (id = 1),
3
3
  store_id TEXT NOT NULL UNIQUE,
4
4
  schema_version INTEGER NOT NULL CHECK (schema_version > 0),
@@ -97,9 +97,9 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
97
97
  reason_code TEXT NOT NULL,
98
98
  occurred_at TEXT NOT NULL DEFAULT (${L}),
99
99
  retain_until TEXT NOT NULL
100
- ) STRICT`,"CREATE INDEX IF NOT EXISTS oauth_clients_inactivity_idx ON oauth_clients(status, last_used_at, client_id)","CREATE INDEX IF NOT EXISTS oauth_codes_expiry_idx ON oauth_codes(expires_at, code_digest)","CREATE INDEX IF NOT EXISTS oauth_code_exchanges_replay_expiry_idx ON oauth_code_exchanges(replay_expires_at, code_digest)","CREATE INDEX IF NOT EXISTS oauth_refresh_families_lifecycle_idx ON oauth_refresh_families(status, expires_at, family_id)","CREATE INDEX IF NOT EXISTS oauth_refresh_families_user_status_idx ON oauth_refresh_families(user_id, status)","CREATE INDEX IF NOT EXISTS oauth_refresh_tokens_expiry_idx ON oauth_refresh_tokens(expires_at, family_id, generation)","CREATE INDEX IF NOT EXISTS oauth_refresh_rotations_replay_expiry_idx ON oauth_refresh_rotations(replay_expires_at, family_id, predecessor_generation)","CREATE INDEX IF NOT EXISTS oauth_security_events_retention_idx ON oauth_security_events(retain_until, event_id)"],ue=["CREATE INDEX IF NOT EXISTS oauth_clients_cleanup_idx ON oauth_clients(COALESCE(last_used_at,created_at), client_id)","CREATE INDEX IF NOT EXISTS oauth_codes_client_idx ON oauth_codes(client_id, code_digest)","CREATE INDEX IF NOT EXISTS oauth_refresh_families_client_idx ON oauth_refresh_families(client_id, family_id)",`CREATE INDEX IF NOT EXISTS oauth_refresh_families_cleanup_idx
100
+ ) STRICT`,"CREATE INDEX IF NOT EXISTS oauth_clients_inactivity_idx ON oauth_clients(status, last_used_at, client_id)","CREATE INDEX IF NOT EXISTS oauth_codes_expiry_idx ON oauth_codes(expires_at, code_digest)","CREATE INDEX IF NOT EXISTS oauth_code_exchanges_replay_expiry_idx ON oauth_code_exchanges(replay_expires_at, code_digest)","CREATE INDEX IF NOT EXISTS oauth_refresh_families_lifecycle_idx ON oauth_refresh_families(status, expires_at, family_id)","CREATE INDEX IF NOT EXISTS oauth_refresh_families_user_status_idx ON oauth_refresh_families(user_id, status)","CREATE INDEX IF NOT EXISTS oauth_refresh_tokens_expiry_idx ON oauth_refresh_tokens(expires_at, family_id, generation)","CREATE INDEX IF NOT EXISTS oauth_refresh_rotations_replay_expiry_idx ON oauth_refresh_rotations(replay_expires_at, family_id, predecessor_generation)","CREATE INDEX IF NOT EXISTS oauth_security_events_retention_idx ON oauth_security_events(retain_until, event_id)"],ce=["CREATE INDEX IF NOT EXISTS oauth_clients_cleanup_idx ON oauth_clients(COALESCE(last_used_at,created_at), client_id)","CREATE INDEX IF NOT EXISTS oauth_codes_client_idx ON oauth_codes(client_id, code_digest)","CREATE INDEX IF NOT EXISTS oauth_refresh_families_client_idx ON oauth_refresh_families(client_id, family_id)",`CREATE INDEX IF NOT EXISTS oauth_refresh_families_cleanup_idx
101
101
  ON oauth_refresh_families(COALESCE(compromised_at,revoked_at,expires_at), family_id)
102
- WHERE status!='active'`],q=[`CREATE TABLE IF NOT EXISTS oauth_rate_limit_buckets (
102
+ WHERE status!='active'`],B=[`CREATE TABLE IF NOT EXISTS oauth_rate_limit_buckets (
103
103
  scope TEXT NOT NULL CHECK (length(scope) BETWEEN 1 AND 80),
104
104
  key_digest BLOB NOT NULL CHECK (typeof(key_digest) = 'blob' AND length(key_digest) = 32),
105
105
  window_start INTEGER NOT NULL CHECK (window_start >= 0),
@@ -109,7 +109,49 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
109
109
  updated_at TEXT NOT NULL DEFAULT (${L}),
110
110
  PRIMARY KEY (scope, key_digest, window_start, window_seconds)
111
111
  ) STRICT`,`CREATE INDEX IF NOT EXISTS oauth_rate_limit_buckets_expiry_idx
112
- ON oauth_rate_limit_buckets(expires_at, scope, key_digest, window_start, window_seconds)`],k=[...He,...ue,...q];async function We(e){if(await x(e,"PRAGMA foreign_keys = ON"),await x(e,"PRAGMA busy_timeout = 5000",!0),(await e.execute("SELECT name FROM pragma_table_info('oauth_codes')")).rows.some(u=>String(u.name)==="code"))throw new Error("Legacy raw OAuth tables require the explicit maintenance-mode coexistence migration");let n=(await e.execute("SELECT 1 present FROM sqlite_master WHERE type='table' AND name='oauth_store_metadata'")).rows.length>0?await e.execute("SELECT schema_version FROM oauth_store_metadata WHERE id=1"):void 0,i=n?.rows[0]?.schema_version==null?void 0:Number(n.rows[0].schema_version);if(i!==void 0&&(!Number.isSafeInteger(i)||i<1||i>3))throw new Error("OAuth store schema version cannot be migrated by this runtime");let a=i===void 0?k:i===1?[...ue,...q]:i===2?q:[];for(let u of a)await e.execute(u);if(i!==void 0&&i<3&&(await e.execute({sql:`UPDATE oauth_store_metadata SET schema_version=?,updated_at=${L} WHERE id=1 AND schema_version=?`,args:[3,i]})).rowsAffected!==1)throw new Error("OAuth store schema version changed during migration");await x(e,"PRAGMA optimize",!0)}async function _e(e){await x(e,"PRAGMA foreign_keys = ON"),await x(e,"PRAGMA busy_timeout = 5000",!0);let t=await e.execute("SELECT name FROM pragma_table_info('oauth_codes')");if(!t.rows.some(a=>String(a.name)==="code")){let a=t.rows.some(u=>String(u.name)==="code_digest");return await We(e),a?"current":"created"}if((await e.execute({sql:"SELECT name FROM sqlite_master WHERE type='table' AND name IN (?,?,?)",args:Object.values(oe)})).rows.length>0)throw new Error("Legacy OAuth archive names already exist; refusing ambiguous migration");let i=await e.transaction("write");try{for(let[a,u]of Object.entries(oe))(await i.execute({sql:"SELECT 1 present FROM sqlite_master WHERE type='table' AND name=?",args:[a]})).rows.length>0&&await i.execute({sql:`ALTER TABLE ${a} RENAME TO ${u}`,args:[]});for(let a of k)await i.execute({sql:a,args:[]});await i.commit()}finally{i.close()}return"archived_legacy"}var qe={oauth_store_metadata:["id","store_id","schema_version","authority_epoch","authority_state","updated_at"],oauth_clients:["client_id","client_name","client_type","token_endpoint_auth_method","status","created_at","last_used_at","expires_at"],oauth_client_redirect_uris:["client_id","redirect_uri","redirect_kind"],oauth_codes:["code_digest","lookup_key_id","client_id","redirect_uri","code_challenge","challenge_method","user_id","scope","resource","issued_at","expires_at"],oauth_code_exchanges:["code_digest","request_fingerprint","client_id","family_id","grant_scope","grant_resource","scope","resource","sealed_refresh","sealed_nonce","sealed_tag","replay_key_id","completed_at","replay_expires_at"],oauth_refresh_families:["family_id","user_id","client_id","issuer","scope","resource","status","current_generation","created_at","expires_at","revoked_at","compromised_at"],oauth_refresh_tokens:["family_id","generation","token_digest","lookup_key_id","token_prefix","predecessor_generation","issued_at","expires_at","used_at","revoked_at"],oauth_refresh_rotations:["family_id","predecessor_generation","request_fingerprint","successor_generation","sealed_successor","sealed_nonce","sealed_tag","replay_key_id","rotated_at","replay_expires_at"],oauth_security_events:["event_id","family_id","event_type","reason_code","occurred_at","retain_until"],oauth_rate_limit_buckets:["scope","key_digest","window_start","window_seconds","count","expires_at","updated_at"]},je={oauth_clients_inactivity_idx:["status","last_used_at","client_id"],oauth_clients_cleanup_idx:[null,"client_id"],oauth_codes_expiry_idx:["expires_at","code_digest"],oauth_codes_client_idx:["client_id","code_digest"],oauth_code_exchanges_replay_expiry_idx:["replay_expires_at","code_digest"],oauth_refresh_families_lifecycle_idx:["status","expires_at","family_id"],oauth_refresh_families_user_status_idx:["user_id","status"],oauth_refresh_families_client_idx:["client_id","family_id"],oauth_refresh_families_cleanup_idx:[null,"family_id"],oauth_refresh_tokens_expiry_idx:["expires_at","family_id","generation"],oauth_refresh_rotations_replay_expiry_idx:["replay_expires_at","family_id","predecessor_generation"],oauth_security_events_retention_idx:["retain_until","event_id"],oauth_rate_limit_buckets_expiry_idx:["expires_at","scope","key_digest","window_start","window_seconds"]};async function ce(e){let t=await e.execute({sql:`SELECT name FROM sqlite_master WHERE type = 'table' AND name IN (${f.map(()=>"?").join(",")})`,args:[...f]}),r=await e.execute({sql:`SELECT name FROM sqlite_master WHERE type = 'index' AND name IN (${h.map(()=>"?").join(",")})`,args:[...h]}),n=new Set(t.rows.map(o=>String(o.name))),i=new Set(r.rows.map(o=>String(o.name))),a=await e.execute("PRAGMA foreign_keys"),u=[],_=o=>o.replace(/\bIF\s+NOT\s+EXISTS\b/gi,"").replace(/\s+/g," ").trim().toLowerCase();for(let o of f){if(!n.has(o))continue;let d=(await e.execute(`PRAGMA table_info('${o}')`)).rows.map(g=>String(g.name));JSON.stringify(d)!==JSON.stringify(qe[o])&&u.push(`${o}:columns`);let E=await e.execute({sql:"SELECT sql FROM sqlite_master WHERE type='table' AND name=?",args:[o]}),l=String(E.rows[0]?.sql??""),m=k.find(g=>_(g).startsWith(`create table ${o} `));(!m||_(l)!==_(m))&&u.push(`${o}:definition`)}for(let o of h){if(!i.has(o))continue;let d=(await e.execute(`PRAGMA index_info('${o}')`)).rows.map(g=>g.name==null?null:String(g.name));JSON.stringify(d)!==JSON.stringify(je[o])&&u.push(`${o}:columns`);let E=await e.execute({sql:"SELECT sql FROM sqlite_master WHERE type='index' AND name=?",args:[o]}),l=String(E.rows[0]?.sql??""),m=k.find(g=>_(g).startsWith(`create index ${o} `));(!m||_(l)!==_(m))&&u.push(`${o}:definition`)}return{ok:f.every(o=>n.has(o))&&h.every(o=>i.has(o))&&Number(a.rows[0]?.foreign_keys??0)===1&&u.length===0,missingTables:f.filter(o=>!n.has(o)),missingIndexes:h.filter(o=>!i.has(o)),foreignKeysEnabled:Number(a.rows[0]?.foreign_keys??0)===1,problems:u}}var Ye=process.env.TURSO_DATABASE_URL??"file:./paa-api.db",Ke=process.env.TURSO_AUTH_TOKEN,X=null,y="2026-09-22.1",de="data-2026-07-28-site-extract-counters.1",le=["admin_credit_adjustment_events","admin_credit_adjustments","billing_authorizations","billing_credits","billing_debits","billing_debit_allocations","billing_events","browser_profile_labels","connected_account_billing","concurrency_locks","credit_lot_expirations","credit_lots","credit_lot_repairs","free_credit_refreshes","harvest_attempts","inbox_messages","jobs","kpo_jobs","kpo_phase_log","ledger","oauth_clients","oauth_codes","oauth_tokens","operation_attempts","operation_billing_links","operation_runs","page_snapshots","password_reset_tokens","rate_limits","request_events","provider_reconciliation_runs","provider_usage_receipts","scheduled_run_view_links","serp_identities","site_audit_jobs","site_audit_phase_log","site_extract_jobs","site_extract_pages","stripe_events","users","workflow_artifacts","workflow_runs","workflow_schedules","workflow_webhook_deliveries","workshop_registrations"],Ee=["admin_credit_adjustment_events_reference","admin_credit_adjustments_user_created","billing_authorizations_user_status","billing_credits_user_status","billing_debits_user_status","billing_events_authorization","billing_events_user_created_at","concurrency_locks_active_user","concurrency_locks_operation","concurrency_locks_user_status","credit_lots_user_active","credit_lot_repairs_user_applied","harvest_attempts_job_id","harvest_attempts_provider_lookup","harvest_attempts_user_created_at","inbox_messages_user_sent_at","jobs_created_at_status_user","jobs_status","jobs_user_created_at_status","jobs_user_id","kpo_jobs_status","kpo_jobs_user_id","kpo_phase_log_job_id","ledger_stripe_pi_unique","ledger_user_id","oauth_tokens_identity","operation_attempts_provider_status","operation_attempts_run_number","operation_billing_links_run","operation_runs_idempotency_scope","operation_runs_status_started","operation_runs_tool_started","operation_runs_user_started","page_snapshots_user_checked_at","prt_user_id","request_events_created_at","request_events_user_created_at","provider_reconciliation_runs_provider_started","provider_usage_receipts_attempt","provider_usage_receipts_pending","provider_usage_receipts_provider_source","scheduled_run_view_links_expiry","scheduled_run_view_links_owner_run","stripe_events_due","serp_identities_user_name","site_audit_jobs_status","site_audit_jobs_user_id","site_audit_phase_log_job_id","site_extract_jobs_status","site_extract_jobs_idempotency","site_extract_jobs_user_id","site_extract_pages_job_id","workflow_artifacts_run","workflow_runs_idempotency","workflow_runs_schedule","workflow_runs_user_created","workflow_schedules_due","workflow_schedules_user_status","workflow_webhook_deliveries_run","workshop_registrations_event_status"],Te=["credit_lots_bounds_insert","credit_lots_bounds_update","credit_lots_one_migration_insert","credit_lots_one_migration_update"],$e={credit_lots:["never_expires"],harvest_attempts:["debug_json","browser_provider","provider_session_id","provider_session_observed_at","provider_lookup_status","provider_status","provider_error_code","provider_error_message","provider_reason_source","provider_duration_ms","provider_bandwidth_bytes","provider_captcha","provider_checked_at","provider_detail_json","provider_disconnect_observed","provider_disconnect_message"],jobs:["public_error_json"],oauth_tokens:["replaced_by","rotated_at"],site_extract_jobs:["attempted_urls","successful_urls","failed_urls","idempotency_key","request_fingerprint","dispatch_attempts","next_dispatch_at","dispatch_error","settlement_attempts","next_settlement_at","settlement_error","public_error_json"],stripe_events:["attempt_count","claim_token","claimed_at","completed_at","event_type","last_error","last_error_code","next_attempt_at","received_at","status","stripe_created_at","updated_at"],users:["balance_mc","concurrency_stripe_sub_id","concurrency_pack_quantity","extra_concurrency_slots","key_active","memory_identity","memory_key","memory_plan","memory_provisioned","memory_subscription_id","password_hash","stripe_customer_id","subscription_concurrency","subscription_id","subscription_tier"],workshop_registrations:["field_notes_email_id","reminder_48h_email_id","reminder_24h_email_id","reminder_1h_email_id"],workflow_artifacts:["content"],workflow_runs:["step_index","step_log_json","step_state_json","total_steps","webhook_url"]};function v(e){return e.map(t=>`'${t.replaceAll("'","''")}'`).join(", ")}async function M(e){let t=[`(SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name IN (${v(le)})) = ${le.length}`,`(SELECT COUNT(*) FROM sqlite_master WHERE type = 'index' AND name IN (${v(Ee)})) = ${Ee.length}`,`(SELECT COUNT(*) FROM sqlite_master WHERE type = 'trigger' AND name IN (${v(Te)})) = ${Te.length}`,...Object.entries($e).map(([n,i])=>`(SELECT COUNT(*) FROM pragma_table_info('${n}') WHERE name IN (${v(i)})) = ${i.length}`)],r=await e.execute(`SELECT ${t.join(" AND ")} AS ready`);return Number(r.rows[0]?.ready??0)===1}async function bt(e=s()){let t=!1;try{t=(await e.execute({sql:"SELECT 1 AS applied FROM schema_migrations WHERE version = ? LIMIT 1",args:[y]})).rows.length===1}catch(n){let i=n instanceof Error?n.message.toLowerCase():String(n).toLowerCase();if(!i.includes("no such table")||!i.includes("schema_migrations"))throw n}let r=t?await M(e):!1;return{coreSchemaVersion:y,migrationApplied:t,schemaReady:r}}async function Je(e){await e.execute(`
112
+ ON oauth_rate_limit_buckets(expires_at, scope, key_digest, window_start, window_seconds)`],X=[...Ye,...ce,...B];async function Ke(e){if(await y(e,"PRAGMA foreign_keys = ON"),await y(e,"PRAGMA busy_timeout = 5000",!0),(await e.execute("SELECT name FROM pragma_table_info('oauth_codes')")).rows.some(_=>String(_.name)==="code"))throw new Error("Legacy raw OAuth tables require the explicit maintenance-mode coexistence migration");let n=(await e.execute("SELECT 1 present FROM sqlite_master WHERE type='table' AND name='oauth_store_metadata'")).rows.length>0?await e.execute("SELECT schema_version FROM oauth_store_metadata WHERE id=1"):void 0,s=n?.rows[0]?.schema_version==null?void 0:Number(n.rows[0].schema_version);if(s!==void 0&&(!Number.isSafeInteger(s)||s<1||s>3))throw new Error("OAuth store schema version cannot be migrated by this runtime");let a=s===void 0?X:s===1?[...ce,...B]:s===2?B:[];for(let _ of a)await e.execute(_);if(s!==void 0&&s<3&&(await e.execute({sql:`UPDATE oauth_store_metadata SET schema_version=?,updated_at=${L} WHERE id=1 AND schema_version=?`,args:[3,s]})).rowsAffected!==1)throw new Error("OAuth store schema version changed during migration");await y(e,"PRAGMA optimize",!0)}async function de(e){await y(e,"PRAGMA foreign_keys = ON"),await y(e,"PRAGMA busy_timeout = 5000",!0);let t=await e.execute("SELECT name FROM pragma_table_info('oauth_codes')");if(!t.rows.some(a=>String(a.name)==="code")){let a=t.rows.some(_=>String(_.name)==="code_digest");return await Ke(e),a?"current":"created"}if((await e.execute({sql:"SELECT name FROM sqlite_master WHERE type='table' AND name IN (?,?,?)",args:Object.values(ue)})).rows.length>0)throw new Error("Legacy OAuth archive names already exist; refusing ambiguous migration");let s=await e.transaction("write");try{for(let[a,_]of Object.entries(ue))(await s.execute({sql:"SELECT 1 present FROM sqlite_master WHERE type='table' AND name=?",args:[a]})).rows.length>0&&await s.execute({sql:`ALTER TABLE ${a} RENAME TO ${_}`,args:[]});for(let a of X)await s.execute({sql:a,args:[]});await s.commit()}finally{s.close()}return"archived_legacy"}var $e={oauth_store_metadata:["id","store_id","schema_version","authority_epoch","authority_state","updated_at"],oauth_clients:["client_id","client_name","client_type","token_endpoint_auth_method","status","created_at","last_used_at","expires_at"],oauth_client_redirect_uris:["client_id","redirect_uri","redirect_kind"],oauth_codes:["code_digest","lookup_key_id","client_id","redirect_uri","code_challenge","challenge_method","user_id","scope","resource","issued_at","expires_at"],oauth_code_exchanges:["code_digest","request_fingerprint","client_id","family_id","grant_scope","grant_resource","scope","resource","sealed_refresh","sealed_nonce","sealed_tag","replay_key_id","completed_at","replay_expires_at"],oauth_refresh_families:["family_id","user_id","client_id","issuer","scope","resource","status","current_generation","created_at","expires_at","revoked_at","compromised_at"],oauth_refresh_tokens:["family_id","generation","token_digest","lookup_key_id","token_prefix","predecessor_generation","issued_at","expires_at","used_at","revoked_at"],oauth_refresh_rotations:["family_id","predecessor_generation","request_fingerprint","successor_generation","sealed_successor","sealed_nonce","sealed_tag","replay_key_id","rotated_at","replay_expires_at"],oauth_security_events:["event_id","family_id","event_type","reason_code","occurred_at","retain_until"],oauth_rate_limit_buckets:["scope","key_digest","window_start","window_seconds","count","expires_at","updated_at"]},Je={oauth_clients_inactivity_idx:["status","last_used_at","client_id"],oauth_clients_cleanup_idx:[null,"client_id"],oauth_codes_expiry_idx:["expires_at","code_digest"],oauth_codes_client_idx:["client_id","code_digest"],oauth_code_exchanges_replay_expiry_idx:["replay_expires_at","code_digest"],oauth_refresh_families_lifecycle_idx:["status","expires_at","family_id"],oauth_refresh_families_user_status_idx:["user_id","status"],oauth_refresh_families_client_idx:["client_id","family_id"],oauth_refresh_families_cleanup_idx:[null,"family_id"],oauth_refresh_tokens_expiry_idx:["expires_at","family_id","generation"],oauth_refresh_rotations_replay_expiry_idx:["replay_expires_at","family_id","predecessor_generation"],oauth_security_events_retention_idx:["retain_until","event_id"],oauth_rate_limit_buckets_expiry_idx:["expires_at","scope","key_digest","window_start","window_seconds"]};async function le(e){let t=await e.execute({sql:`SELECT name FROM sqlite_master WHERE type = 'table' AND name IN (${I.map(()=>"?").join(",")})`,args:[...I]}),r=await e.execute({sql:`SELECT name FROM sqlite_master WHERE type = 'index' AND name IN (${x.map(()=>"?").join(",")})`,args:[...x]}),n=new Set(t.rows.map(o=>String(o.name))),s=new Set(r.rows.map(o=>String(o.name))),a=await e.execute("PRAGMA foreign_keys"),_=[],u=o=>o.replace(/\bIF\s+NOT\s+EXISTS\b/gi,"").replace(/\s+/g," ").trim().toLowerCase();for(let o of I){if(!n.has(o))continue;let d=(await e.execute(`PRAGMA table_info('${o}')`)).rows.map(g=>String(g.name));JSON.stringify(d)!==JSON.stringify($e[o])&&_.push(`${o}:columns`);let E=await e.execute({sql:"SELECT sql FROM sqlite_master WHERE type='table' AND name=?",args:[o]}),l=String(E.rows[0]?.sql??""),m=X.find(g=>u(g).startsWith(`create table ${o} `));(!m||u(l)!==u(m))&&_.push(`${o}:definition`)}for(let o of x){if(!s.has(o))continue;let d=(await e.execute(`PRAGMA index_info('${o}')`)).rows.map(g=>g.name==null?null:String(g.name));JSON.stringify(d)!==JSON.stringify(Je[o])&&_.push(`${o}:columns`);let E=await e.execute({sql:"SELECT sql FROM sqlite_master WHERE type='index' AND name=?",args:[o]}),l=String(E.rows[0]?.sql??""),m=X.find(g=>u(g).startsWith(`create index ${o} `));(!m||u(l)!==u(m))&&_.push(`${o}:definition`)}return{ok:I.every(o=>n.has(o))&&x.every(o=>s.has(o))&&Number(a.rows[0]?.foreign_keys??0)===1&&_.length===0,missingTables:I.filter(o=>!n.has(o)),missingIndexes:x.filter(o=>!s.has(o)),foreignKeysEnabled:Number(a.rows[0]?.foreign_keys??0)===1,problems:_}}var Qe=process.env.TURSO_DATABASE_URL??"file:./paa-api.db",Ze=process.env.TURSO_AUTH_TOKEN,F=null,U="2026-09-23.2",Ee="data-2026-07-28-site-extract-counters.1",Te=["admin_credit_adjustment_events","admin_credit_adjustments","billing_authorizations","billing_credits","billing_debits","billing_debit_allocations","billing_events","browser_profile_labels","connected_account_billing","concurrency_locks","credit_lot_expirations","credit_lots","credit_lot_repairs","free_credit_refreshes","harvest_attempts","inbox_messages","jobs","kpo_jobs","kpo_phase_log","ledger","oauth_clients","oauth_codes","oauth_tokens","operation_attempts","operation_billing_links","operation_coverage_defects","operation_runs","page_snapshots","password_reset_tokens","rate_limits","request_events","provider_reconciliation_runs","provider_account_windows","provider_usage_receipts","scheduled_run_view_links","serp_identities","site_audit_jobs","site_audit_phase_log","site_extract_jobs","site_extract_pages","stripe_events","users","workflow_artifacts","workflow_runs","workflow_schedules","workflow_webhook_deliveries","workshop_registrations"],pe=["admin_credit_adjustment_events_reference","admin_credit_adjustments_user_created","billing_authorizations_user_status","billing_credits_user_status","billing_debits_user_status","billing_events_authorization","billing_events_user_created_at","concurrency_locks_active_user","concurrency_locks_operation","concurrency_locks_user_status","credit_lots_user_active","credit_lot_repairs_user_applied","harvest_attempts_job_id","harvest_attempts_provider_lookup","harvest_attempts_user_created_at","inbox_messages_user_sent_at","jobs_created_at_status_user","jobs_status","jobs_user_created_at_status","jobs_user_id","kpo_jobs_status","kpo_jobs_user_id","kpo_phase_log_job_id","ledger_stripe_pi_unique","ledger_user_id","oauth_tokens_identity","operation_attempts_provider_status","operation_attempts_run_number","operation_billing_links_run","operation_coverage_defects_created","operation_runs_idempotency_scope","operation_runs_status_started","operation_runs_tool_started","operation_runs_user_started","page_snapshots_user_checked_at","prt_user_id","request_events_created_at","request_events_user_created_at","provider_reconciliation_runs_provider_started","provider_account_windows_lookup","provider_usage_receipts_attempt","provider_usage_receipts_pending","provider_usage_receipts_provider_source","scheduled_run_view_links_expiry","scheduled_run_view_links_owner_run","stripe_events_due","serp_identities_user_name","site_audit_jobs_status","site_audit_jobs_user_id","site_audit_phase_log_job_id","site_extract_jobs_status","site_extract_jobs_idempotency","site_extract_jobs_user_id","site_extract_pages_job_id","workflow_artifacts_run","workflow_runs_idempotency","workflow_runs_schedule","workflow_runs_user_created","workflow_schedules_due","workflow_schedules_user_status","workflow_webhook_deliveries_run","workshop_registrations_event_status"],me=["credit_lots_bounds_insert","credit_lots_bounds_update","credit_lots_one_migration_insert","credit_lots_one_migration_update"],et={credit_lots:["never_expires"],harvest_attempts:["debug_json","browser_provider","provider_session_id","provider_session_observed_at","provider_lookup_status","provider_status","provider_error_code","provider_error_message","provider_reason_source","provider_duration_ms","provider_bandwidth_bytes","provider_captcha","provider_checked_at","provider_detail_json","provider_disconnect_observed","provider_disconnect_message"],jobs:["public_error_json"],oauth_tokens:["replaced_by","rotated_at"],provider_usage_receipts:["provider_product","billing_tier","billable_event","measurement_source","rate_numerator","rate_denominator","rate_policy_version","rate_effective_at"],site_extract_jobs:["attempted_urls","successful_urls","failed_urls","idempotency_key","request_fingerprint","dispatch_attempts","next_dispatch_at","dispatch_error","settlement_attempts","next_settlement_at","settlement_error","public_error_json"],stripe_events:["attempt_count","claim_token","claimed_at","completed_at","event_type","last_error","last_error_code","next_attempt_at","received_at","status","stripe_created_at","updated_at"],users:["balance_mc","concurrency_stripe_sub_id","concurrency_pack_quantity","extra_concurrency_slots","key_active","memory_identity","memory_key","memory_plan","memory_provisioned","memory_subscription_id","password_hash","stripe_customer_id","subscription_concurrency","subscription_id","subscription_tier"],workshop_registrations:["field_notes_email_id","reminder_48h_email_id","reminder_24h_email_id","reminder_1h_email_id"],workflow_artifacts:["content"],workflow_runs:["step_index","step_log_json","step_state_json","total_steps","webhook_url"]},b="provider_usage_receipts",f="provider_usage_receipts_measured_v1",ge="cost_state IN ('pending', 'estimated', 'measured', 'actual', 'unavailable')";function Le(e=b){if(e!==b&&e!==f)throw new Error(`Unsupported provider receipt table name: ${e}`);return`
113
+ CREATE TABLE IF NOT EXISTS ${e} (
114
+ id TEXT PRIMARY KEY,
115
+ attempt_id TEXT NOT NULL REFERENCES operation_attempts(id) ON DELETE CASCADE,
116
+ provider TEXT NOT NULL,
117
+ account_scope_hash TEXT NOT NULL,
118
+ method TEXT NOT NULL,
119
+ provider_source_key TEXT,
120
+ provider_source_key_hash TEXT,
121
+ cost_state TEXT NOT NULL DEFAULT 'pending'
122
+ CHECK (cost_state IN ('pending', 'estimated', 'measured', 'actual', 'unavailable')),
123
+ provider_product TEXT,
124
+ billing_tier TEXT,
125
+ billable_event TEXT,
126
+ measurement_source TEXT,
127
+ rate_numerator INTEGER CHECK (rate_numerator IS NULL OR rate_numerator >= 0),
128
+ rate_denominator INTEGER CHECK (rate_denominator IS NULL OR rate_denominator > 0),
129
+ rate_policy_version TEXT,
130
+ rate_effective_at TEXT,
131
+ units REAL CHECK (units IS NULL OR units >= 0),
132
+ unit_type TEXT,
133
+ amount_usd_nanos INTEGER CHECK (amount_usd_nanos IS NULL OR amount_usd_nanos >= 0),
134
+ currency TEXT NOT NULL DEFAULT 'USD',
135
+ rate_source TEXT,
136
+ zero_cost_reason TEXT,
137
+ provider_status TEXT,
138
+ provider_duration_ms INTEGER CHECK (provider_duration_ms IS NULL OR provider_duration_ms >= 0),
139
+ provider_captcha INTEGER CHECK (provider_captcha IS NULL OR provider_captcha IN (0, 1)),
140
+ error_code TEXT,
141
+ error_message TEXT,
142
+ checked_at TEXT,
143
+ finalized_at TEXT,
144
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
145
+ updated_at TEXT NOT NULL DEFAULT (datetime('now')),
146
+ CHECK (provider_source_key IS NULL OR provider_source_key_hash IS NOT NULL),
147
+ CHECK (cost_state <> 'pending' OR (amount_usd_nanos IS NULL AND finalized_at IS NULL)),
148
+ CHECK (cost_state <> 'actual' OR (amount_usd_nanos IS NOT NULL AND finalized_at IS NOT NULL
149
+ AND (amount_usd_nanos > 0 OR zero_cost_reason IS NOT NULL))),
150
+ CHECK (cost_state NOT IN ('estimated', 'measured', 'unavailable') OR finalized_at IS NOT NULL),
151
+ CHECK (cost_state <> 'measured' OR (amount_usd_nanos IS NOT NULL
152
+ AND (amount_usd_nanos > 0 OR zero_cost_reason IS NOT NULL)))
153
+ )
154
+ `}async function be(e){let t=await e.execute({sql:"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?",args:[b]});return t.rows[0]?.sql==null?null:String(t.rows[0].sql)}function Se(e){return e==null||e.includes(ge)}async function tt(e){let t=await be(e);if(Se(t))return"not_needed";if((await e.execute({sql:"SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1",args:[f]})).rows.length>0)throw new Error(`Refusing provider receipt migration because ${f} already exists`);let s=(await e.execute(`PRAGMA table_info(${b})`)).rows.map(a=>String(a.name)).map(a=>`"${a.replaceAll('"','""')}"`).join(", ");if(!s)throw new Error("Provider receipt migration found no source columns");return await e.batch([Le(f),`INSERT INTO ${f} (${s}) SELECT ${s} FROM ${b}`,`DROP TABLE ${b}`,`ALTER TABLE ${f} RENAME TO ${b}`,"CREATE INDEX provider_usage_receipts_attempt ON provider_usage_receipts(attempt_id, created_at)","CREATE INDEX provider_usage_receipts_pending ON provider_usage_receipts(cost_state, checked_at, created_at) WHERE cost_state = 'pending'","CREATE UNIQUE INDEX provider_usage_receipts_provider_source ON provider_usage_receipts(provider, account_scope_hash, method, provider_source_key_hash) WHERE provider_source_key_hash IS NOT NULL"],"write"),"rebuilt"}function M(e){return e.map(t=>`'${t.replaceAll("'","''")}'`).join(", ")}async function P(e){let t=[`(SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name IN (${M(Te)})) = ${Te.length}`,`(SELECT COUNT(*) FROM sqlite_master WHERE type = 'index' AND name IN (${M(pe)})) = ${pe.length}`,`(SELECT COUNT(*) FROM sqlite_master WHERE type = 'trigger' AND name IN (${M(me)})) = ${me.length}`,...Object.entries(et).map(([n,s])=>`(SELECT COUNT(*) FROM pragma_table_info('${n}') WHERE name IN (${M(s)})) = ${s.length}`),`(SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name = '${b}' AND instr(sql, '${ge.replaceAll("'","''")}') > 0) = 1`],r=await e.execute(`SELECT ${t.join(" AND ")} AS ready`);return Number(r.rows[0]?.ready??0)===1}async function It(e=i()){let t=!1;try{t=(await e.execute({sql:"SELECT 1 AS applied FROM schema_migrations WHERE version = ? LIMIT 1",args:[U]})).rows.length===1}catch(n){let s=n instanceof Error?n.message.toLowerCase():String(n).toLowerCase();if(!s.includes("no such table")||!s.includes("schema_migrations"))throw n}let r=t?await P(e):!1;return{coreSchemaVersion:U,migrationApplied:t,schemaReady:r}}async function rt(e){await e.execute(`
113
155
  UPDATE site_extract_jobs SET
114
156
  attempted_urls = done_urls,
115
157
  successful_urls = (
@@ -146,12 +188,12 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
146
188
  AND attempted_urls = 0
147
189
  AND successful_urls = 0
148
190
  AND failed_urls = 0
149
- `)}async function j(e){(await e.execute({sql:"SELECT 1 AS applied FROM schema_migrations WHERE version = ? LIMIT 1",args:[de]})).rows.length>0||(await Je(e),await e.execute({sql:"INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",args:[de]}))}function s(){return X||(X=Be({url:Ye,authToken:Ke})),X}function St(e){X=e}async function Rt(e=s()){if(process.env.OAUTH_MAINTENANCE_MODE!=="true")throw new Error("Secured main OAuth schema migration requires OAUTH_MAINTENANCE_MODE=true");await _e(e)}async function At(e=s()){return ce(e)}async function wt(e={}){let t=s(),r;try{r=await t.execute({sql:"SELECT 1 AS applied FROM schema_migrations WHERE version = ? LIMIT 1",args:[y]})}catch(n){let i=n instanceof Error?n.message.toLowerCase():String(n).toLowerCase();if(!i.includes("no such table")||!i.includes("schema_migrations"))throw n;await t.execute(`
191
+ `)}async function G(e){(await e.execute({sql:"SELECT 1 AS applied FROM schema_migrations WHERE version = ? LIMIT 1",args:[Ee]})).rows.length>0||(await rt(e),await e.execute({sql:"INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",args:[Ee]}))}function i(){return F||(F=Ve({url:Qe,authToken:Ze})),F}function xt(e){F=e}async function yt(e=i()){if(process.env.OAUTH_MAINTENANCE_MODE!=="true")throw new Error("Secured main OAuth schema migration requires OAUTH_MAINTENANCE_MODE=true");await de(e)}async function Ct(e=i()){return le(e)}async function nt(e={}){let t=i(),r;try{r=await t.execute({sql:"SELECT 1 AS applied FROM schema_migrations WHERE version = ? LIMIT 1",args:[U]})}catch(s){let a=s instanceof Error?s.message.toLowerCase():String(s).toLowerCase();if(!a.includes("no such table")||!a.includes("schema_migrations"))throw s;await t.execute(`
150
192
  CREATE TABLE IF NOT EXISTS schema_migrations (
151
193
  version TEXT PRIMARY KEY,
152
194
  applied_at TEXT NOT NULL DEFAULT (datetime('now'))
153
195
  )
154
- `),r={rows:[]}}if(r.rows.length>0){if(!e.verifyCurrentSchema)return;if(await M(t)){e.runDataRepairs&&await j(t);return}}if(await M(t)){await j(t),await t.execute({sql:"INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",args:[y]});return}await t.execute(`
196
+ `),r={rows:[]}}if(r.rows.length>0){if(!e.verifyCurrentSchema)return;if(await P(t)){e.runDataRepairs&&await G(t);return}}let n=await be(t);if(!Se(n))throw new Error("Provider receipt schema requires the explicit operator migration: run npm run db:migrate before starting the new application release");if(await P(t)){await G(t),await t.execute({sql:"INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",args:[U]});return}await t.execute(`
155
197
  CREATE TABLE IF NOT EXISTS users (
156
198
  id INTEGER PRIMARY KEY AUTOINCREMENT,
157
199
  email TEXT UNIQUE NOT NULL,
@@ -218,7 +260,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
218
260
  completed_at TEXT,
219
261
  UNIQUE(job_id, attempt_number)
220
262
  )
221
- `),await t.execute("CREATE INDEX IF NOT EXISTS harvest_attempts_job_id ON harvest_attempts(job_id)"),await t.execute("CREATE INDEX IF NOT EXISTS harvest_attempts_user_created_at ON harvest_attempts(user_id, created_at DESC)");try{await t.execute("ALTER TABLE harvest_attempts ADD COLUMN debug_json TEXT")}catch{}for(let n of["browser_provider TEXT","provider_session_id TEXT","provider_session_observed_at TEXT","provider_lookup_status TEXT","provider_status TEXT","provider_error_code TEXT","provider_error_message TEXT","provider_reason_source TEXT","provider_duration_ms INTEGER","provider_bandwidth_bytes INTEGER","provider_captcha INTEGER","provider_checked_at TEXT","provider_detail_json TEXT","provider_disconnect_observed INTEGER","provider_disconnect_message TEXT"])try{await t.execute(`ALTER TABLE harvest_attempts ADD COLUMN ${n}`)}catch{}await t.execute("CREATE INDEX IF NOT EXISTS harvest_attempts_provider_lookup ON harvest_attempts(browser_provider, provider_lookup_status, provider_checked_at)");try{await t.execute("ALTER TABLE users ADD COLUMN password_hash TEXT")}catch{}try{await t.execute("ALTER TABLE users ADD COLUMN key_active INTEGER NOT NULL DEFAULT 1")}catch{}await t.execute(`
263
+ `),await t.execute("CREATE INDEX IF NOT EXISTS harvest_attempts_job_id ON harvest_attempts(job_id)"),await t.execute("CREATE INDEX IF NOT EXISTS harvest_attempts_user_created_at ON harvest_attempts(user_id, created_at DESC)");try{await t.execute("ALTER TABLE harvest_attempts ADD COLUMN debug_json TEXT")}catch{}for(let s of["browser_provider TEXT","provider_session_id TEXT","provider_session_observed_at TEXT","provider_lookup_status TEXT","provider_status TEXT","provider_error_code TEXT","provider_error_message TEXT","provider_reason_source TEXT","provider_duration_ms INTEGER","provider_bandwidth_bytes INTEGER","provider_captcha INTEGER","provider_checked_at TEXT","provider_detail_json TEXT","provider_disconnect_observed INTEGER","provider_disconnect_message TEXT"])try{await t.execute(`ALTER TABLE harvest_attempts ADD COLUMN ${s}`)}catch{}await t.execute("CREATE INDEX IF NOT EXISTS harvest_attempts_provider_lookup ON harvest_attempts(browser_provider, provider_lookup_status, provider_checked_at)");try{await t.execute("ALTER TABLE users ADD COLUMN password_hash TEXT")}catch{}try{await t.execute("ALTER TABLE users ADD COLUMN key_active INTEGER NOT NULL DEFAULT 1")}catch{}await t.execute(`
222
264
  CREATE TABLE IF NOT EXISTS kpo_jobs (
223
265
  id TEXT PRIMARY KEY,
224
266
  user_id INTEGER NOT NULL REFERENCES users(id),
@@ -496,39 +538,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
496
538
  CHECK ((status = 'running' AND ended_at IS NULL AND duration_ms IS NULL)
497
539
  OR (status <> 'running' AND ended_at IS NOT NULL AND duration_ms IS NOT NULL))
498
540
  )
499
- `),await t.execute("CREATE UNIQUE INDEX IF NOT EXISTS operation_attempts_run_number ON operation_attempts(run_id, attempt_number)"),await t.execute("CREATE INDEX IF NOT EXISTS operation_attempts_provider_status ON operation_attempts(provider, status, started_at)"),await t.execute(`
500
- CREATE TABLE IF NOT EXISTS provider_usage_receipts (
501
- id TEXT PRIMARY KEY,
502
- attempt_id TEXT NOT NULL REFERENCES operation_attempts(id) ON DELETE CASCADE,
503
- provider TEXT NOT NULL,
504
- account_scope_hash TEXT NOT NULL,
505
- method TEXT NOT NULL,
506
- provider_source_key TEXT,
507
- provider_source_key_hash TEXT,
508
- cost_state TEXT NOT NULL DEFAULT 'pending'
509
- CHECK (cost_state IN ('pending', 'estimated', 'actual', 'unavailable')),
510
- units REAL CHECK (units IS NULL OR units >= 0),
511
- unit_type TEXT,
512
- amount_usd_nanos INTEGER CHECK (amount_usd_nanos IS NULL OR amount_usd_nanos >= 0),
513
- currency TEXT NOT NULL DEFAULT 'USD',
514
- rate_source TEXT,
515
- zero_cost_reason TEXT,
516
- provider_status TEXT,
517
- provider_duration_ms INTEGER CHECK (provider_duration_ms IS NULL OR provider_duration_ms >= 0),
518
- provider_captcha INTEGER CHECK (provider_captcha IS NULL OR provider_captcha IN (0, 1)),
519
- error_code TEXT,
520
- error_message TEXT,
521
- checked_at TEXT,
522
- finalized_at TEXT,
523
- created_at TEXT NOT NULL DEFAULT (datetime('now')),
524
- updated_at TEXT NOT NULL DEFAULT (datetime('now')),
525
- CHECK (provider_source_key IS NULL OR provider_source_key_hash IS NOT NULL),
526
- CHECK (cost_state <> 'pending' OR (amount_usd_nanos IS NULL AND finalized_at IS NULL)),
527
- CHECK (cost_state <> 'actual' OR (amount_usd_nanos IS NOT NULL AND finalized_at IS NOT NULL
528
- AND (amount_usd_nanos > 0 OR zero_cost_reason IS NOT NULL))),
529
- CHECK (cost_state NOT IN ('estimated', 'unavailable') OR finalized_at IS NOT NULL)
530
- )
531
- `),await t.execute("CREATE INDEX IF NOT EXISTS provider_usage_receipts_attempt ON provider_usage_receipts(attempt_id, created_at)"),await t.execute("CREATE INDEX IF NOT EXISTS provider_usage_receipts_pending ON provider_usage_receipts(cost_state, checked_at, created_at) WHERE cost_state = 'pending'"),await t.execute("CREATE UNIQUE INDEX IF NOT EXISTS provider_usage_receipts_provider_source ON provider_usage_receipts(provider, account_scope_hash, method, provider_source_key_hash) WHERE provider_source_key_hash IS NOT NULL"),await t.execute(`
541
+ `),await t.execute("CREATE UNIQUE INDEX IF NOT EXISTS operation_attempts_run_number ON operation_attempts(run_id, attempt_number)"),await t.execute("CREATE INDEX IF NOT EXISTS operation_attempts_provider_status ON operation_attempts(provider, status, started_at)"),await t.execute(Le()),await t.execute("CREATE INDEX IF NOT EXISTS provider_usage_receipts_attempt ON provider_usage_receipts(attempt_id, created_at)"),await t.execute("CREATE INDEX IF NOT EXISTS provider_usage_receipts_pending ON provider_usage_receipts(cost_state, checked_at, created_at) WHERE cost_state = 'pending'"),await t.execute("CREATE UNIQUE INDEX IF NOT EXISTS provider_usage_receipts_provider_source ON provider_usage_receipts(provider, account_scope_hash, method, provider_source_key_hash) WHERE provider_source_key_hash IS NOT NULL"),await t.execute(`
532
542
  CREATE TABLE IF NOT EXISTS provider_reconciliation_runs (
533
543
  id TEXT PRIMARY KEY,
534
544
  provider TEXT NOT NULL,
@@ -545,6 +555,40 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
545
555
  CHECK ((status = 'running' AND completed_at IS NULL) OR (status <> 'running' AND completed_at IS NOT NULL))
546
556
  )
547
557
  `),await t.execute("CREATE INDEX IF NOT EXISTS provider_reconciliation_runs_provider_started ON provider_reconciliation_runs(provider, started_at DESC)"),await t.execute(`
558
+ CREATE TABLE IF NOT EXISTS provider_account_windows (
559
+ id TEXT PRIMARY KEY,
560
+ provider TEXT NOT NULL,
561
+ provider_product TEXT NOT NULL,
562
+ account_scope_hash TEXT NOT NULL,
563
+ window_start TEXT NOT NULL,
564
+ window_end TEXT NOT NULL,
565
+ source TEXT NOT NULL,
566
+ source_observed_at TEXT NOT NULL,
567
+ account_total_usd_nanos INTEGER NOT NULL CHECK (account_total_usd_nanos >= 0),
568
+ actual_usd_nanos INTEGER NOT NULL CHECK (actual_usd_nanos >= 0),
569
+ measured_usd_nanos INTEGER NOT NULL CHECK (measured_usd_nanos >= 0),
570
+ estimated_usd_nanos INTEGER NOT NULL CHECK (estimated_usd_nanos >= 0),
571
+ unattributed_usd_nanos INTEGER NOT NULL,
572
+ pending_count INTEGER NOT NULL CHECK (pending_count >= 0),
573
+ unavailable_count INTEGER NOT NULL CHECK (unavailable_count >= 0),
574
+ receipt_count INTEGER NOT NULL CHECK (receipt_count >= 0),
575
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
576
+ CHECK (window_start < window_end),
577
+ CHECK (account_total_usd_nanos = actual_usd_nanos + measured_usd_nanos + estimated_usd_nanos + unattributed_usd_nanos),
578
+ UNIQUE (provider, provider_product, account_scope_hash, window_start, window_end, source)
579
+ )
580
+ `),await t.execute("CREATE INDEX IF NOT EXISTS provider_account_windows_lookup ON provider_account_windows(provider, provider_product, window_start, window_end)"),await t.execute(`
581
+ CREATE TABLE IF NOT EXISTS operation_coverage_defects (
582
+ id TEXT PRIMARY KEY,
583
+ tool TEXT NOT NULL,
584
+ method TEXT NOT NULL,
585
+ phase TEXT NOT NULL,
586
+ error_code TEXT NOT NULL,
587
+ run_id TEXT,
588
+ attempt_id TEXT,
589
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
590
+ )
591
+ `),await t.execute("CREATE INDEX IF NOT EXISTS operation_coverage_defects_created ON operation_coverage_defects(created_at, tool, method)"),await t.execute(`
548
592
  CREATE TABLE IF NOT EXISTS operation_billing_links (
549
593
  run_id TEXT NOT NULL REFERENCES operation_runs(id) ON DELETE CASCADE,
550
594
  billing_table TEXT NOT NULL CHECK (billing_table IN ('billing_authorizations', 'billing_events', 'billing_debits', 'billing_credits', 'ledger')),
@@ -767,7 +811,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
767
811
  processed_at TEXT NOT NULL DEFAULT (datetime('now')),
768
812
  updated_at TEXT NOT NULL DEFAULT (datetime('now'))
769
813
  )
770
- `);for(let n of["status TEXT NOT NULL DEFAULT 'processed'","attempt_count INTEGER NOT NULL DEFAULT 1","claim_token TEXT","event_type TEXT","stripe_created_at INTEGER","received_at TEXT","claimed_at TEXT","next_attempt_at TEXT","completed_at TEXT","last_error TEXT","last_error_code TEXT","updated_at TEXT"])try{await t.execute(`ALTER TABLE stripe_events ADD COLUMN ${n}`)}catch{}await t.execute(`
814
+ `);for(let s of["status TEXT NOT NULL DEFAULT 'processed'","attempt_count INTEGER NOT NULL DEFAULT 1","claim_token TEXT","event_type TEXT","stripe_created_at INTEGER","received_at TEXT","claimed_at TEXT","next_attempt_at TEXT","completed_at TEXT","last_error TEXT","last_error_code TEXT","updated_at TEXT"])try{await t.execute(`ALTER TABLE stripe_events ADD COLUMN ${s}`)}catch{}await t.execute(`
771
815
  UPDATE stripe_events
772
816
  SET updated_at = COALESCE(updated_at, processed_at),
773
817
  received_at = COALESCE(received_at, processed_at, updated_at, datetime('now')),
@@ -817,7 +861,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
817
861
  revoked INTEGER NOT NULL DEFAULT 0,
818
862
  created_at TEXT NOT NULL DEFAULT (datetime('now'))
819
863
  )
820
- `),await t.execute("CREATE INDEX IF NOT EXISTS oauth_tokens_identity ON oauth_tokens(identity)");for(let n of["replaced_by TEXT","rotated_at TEXT"])try{await t.execute(`ALTER TABLE oauth_tokens ADD COLUMN ${n}`)}catch{}await t.execute(`
864
+ `),await t.execute("CREATE INDEX IF NOT EXISTS oauth_tokens_identity ON oauth_tokens(identity)");for(let s of["replaced_by TEXT","rotated_at TEXT"])try{await t.execute(`ALTER TABLE oauth_tokens ADD COLUMN ${s}`)}catch{}await t.execute(`
821
865
  CREATE TABLE IF NOT EXISTS page_snapshots (
822
866
  user_id INTEGER NOT NULL REFERENCES users(id),
823
867
  url TEXT NOT NULL,
@@ -861,7 +905,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
861
905
  updated_at TEXT NOT NULL DEFAULT (datetime('now')),
862
906
  UNIQUE(event_slug, email)
863
907
  )
864
- `);for(let n of["field_notes_email_id TEXT","reminder_48h_email_id TEXT","reminder_24h_email_id TEXT","reminder_1h_email_id TEXT"])try{await t.execute(`ALTER TABLE workshop_registrations ADD COLUMN ${n}`)}catch{}if(await t.execute(`
908
+ `);for(let s of["field_notes_email_id TEXT","reminder_48h_email_id TEXT","reminder_24h_email_id TEXT","reminder_1h_email_id TEXT"])try{await t.execute(`ALTER TABLE workshop_registrations ADD COLUMN ${s}`)}catch{}if(await t.execute(`
865
909
  CREATE INDEX IF NOT EXISTS workshop_registrations_event_status
866
910
  ON workshop_registrations(event_slug, status, registered_at)
867
911
  `),await t.execute(`
@@ -891,20 +935,20 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
891
935
  `),await t.execute(`
892
936
  CREATE UNIQUE INDEX IF NOT EXISTS serp_identities_user_name
893
937
  ON serp_identities(user_id, name)
894
- `),!await M(t))throw new Error("core schema migration finished without all required tables, indexes, and columns");await j(t),await t.execute({sql:"INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",args:[y]})}async function Ot(e,t,r){await s().execute({sql:"INSERT INTO oauth_clients (client_id, redirect_uris, name) VALUES (?, ?, ?)",args:[e,JSON.stringify(t),r]})}async function ft(e){let r=(await s().execute({sql:"SELECT * FROM oauth_clients WHERE client_id = ?",args:[e]})).rows[0];if(!r)return;let n=[];try{let i=JSON.parse(String(r.redirect_uris));Array.isArray(i)&&(n=i.filter(a=>typeof a=="string"))}catch{n=[]}return{client_id:String(r.client_id),redirect_uris:n,name:r.name!=null?String(r.name):null,created_at:String(r.created_at)}}async function ht(e){await s().execute({sql:"INSERT INTO oauth_codes (code, client_id, redirect_uri, code_challenge, identity, scope, resource, expires_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",args:[e.code,e.client_id,e.redirect_uri,e.code_challenge,e.identity,e.scope,e.resource,e.expires_at]})}async function xt(e){let t=s(),n=(await t.execute({sql:"SELECT * FROM oauth_codes WHERE code = ?",args:[e]})).rows[0];if(await t.execute({sql:"DELETE FROM oauth_codes WHERE code = ?",args:[e]}),!!n)return{code:String(n.code),client_id:String(n.client_id),redirect_uri:String(n.redirect_uri),code_challenge:String(n.code_challenge),identity:String(n.identity),scope:String(n.scope),resource:n.resource!=null?String(n.resource):null,expires_at:String(n.expires_at)}}async function ze(e){await s().execute({sql:"INSERT INTO oauth_tokens (refresh_token, client_id, identity, scope, resource, expires_at, revoked) VALUES (?, ?, ?, ?, ?, ?, 0)",args:[e.refresh_token,e.client_id,e.identity,e.scope,e.resource,e.expires_at]})}async function It(e){let r=(await s().execute({sql:"SELECT * FROM oauth_tokens WHERE refresh_token = ?",args:[e]})).rows[0];if(r)return{refresh_token:String(r.refresh_token),client_id:String(r.client_id),identity:String(r.identity),scope:String(r.scope),resource:r.resource!=null?String(r.resource):null,expires_at:String(r.expires_at),revoked:Number(r.revoked??0),replaced_by:r.replaced_by!=null?String(r.replaced_by):null,rotated_at:r.rotated_at!=null?String(r.rotated_at):null}}async function yt(e){await s().execute({sql:"UPDATE oauth_tokens SET revoked = 1 WHERE refresh_token = ?",args:[e]})}async function Ct(e,t){await ze(t),await s().execute({sql:"UPDATE oauth_tokens SET revoked = 1, replaced_by = ?, rotated_at = ? WHERE refresh_token = ?",args:[t.refresh_token,new Date().toISOString(),e]})}async function Ut(e,t,r){return(await s().execute({sql:`INSERT OR IGNORE INTO stripe_events
938
+ `),!await P(t))throw new Error("core schema migration finished without all required tables, indexes, and columns");await G(t),await t.execute({sql:"INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",args:[U]})}async function Ut(e={}){let t=await tt(i());return await nt(e),{providerUsageReceipts:t}}async function Dt(e,t,r){await i().execute({sql:"INSERT INTO oauth_clients (client_id, redirect_uris, name) VALUES (?, ?, ?)",args:[e,JSON.stringify(t),r]})}async function vt(e){let r=(await i().execute({sql:"SELECT * FROM oauth_clients WHERE client_id = ?",args:[e]})).rows[0];if(!r)return;let n=[];try{let s=JSON.parse(String(r.redirect_uris));Array.isArray(s)&&(n=s.filter(a=>typeof a=="string"))}catch{n=[]}return{client_id:String(r.client_id),redirect_uris:n,name:r.name!=null?String(r.name):null,created_at:String(r.created_at)}}async function kt(e){await i().execute({sql:"INSERT INTO oauth_codes (code, client_id, redirect_uri, code_challenge, identity, scope, resource, expires_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",args:[e.code,e.client_id,e.redirect_uri,e.code_challenge,e.identity,e.scope,e.resource,e.expires_at]})}async function Xt(e){let t=i(),n=(await t.execute({sql:"SELECT * FROM oauth_codes WHERE code = ?",args:[e]})).rows[0];if(await t.execute({sql:"DELETE FROM oauth_codes WHERE code = ?",args:[e]}),!!n)return{code:String(n.code),client_id:String(n.client_id),redirect_uri:String(n.redirect_uri),code_challenge:String(n.code_challenge),identity:String(n.identity),scope:String(n.scope),resource:n.resource!=null?String(n.resource):null,expires_at:String(n.expires_at)}}async function st(e){await i().execute({sql:"INSERT INTO oauth_tokens (refresh_token, client_id, identity, scope, resource, expires_at, revoked) VALUES (?, ?, ?, ?, ?, ?, 0)",args:[e.refresh_token,e.client_id,e.identity,e.scope,e.resource,e.expires_at]})}async function Mt(e){let r=(await i().execute({sql:"SELECT * FROM oauth_tokens WHERE refresh_token = ?",args:[e]})).rows[0];if(r)return{refresh_token:String(r.refresh_token),client_id:String(r.client_id),identity:String(r.identity),scope:String(r.scope),resource:r.resource!=null?String(r.resource):null,expires_at:String(r.expires_at),revoked:Number(r.revoked??0),replaced_by:r.replaced_by!=null?String(r.replaced_by):null,rotated_at:r.rotated_at!=null?String(r.rotated_at):null}}async function Ft(e){await i().execute({sql:"UPDATE oauth_tokens SET revoked = 1 WHERE refresh_token = ?",args:[e]})}async function Pt(e,t){await st(t),await i().execute({sql:"UPDATE oauth_tokens SET revoked = 1, replaced_by = ?, rotated_at = ? WHERE refresh_token = ?",args:[t.refresh_token,new Date().toISOString(),e]})}async function Ht(e,t,r){return(await i().execute({sql:`INSERT OR IGNORE INTO stripe_events
895
939
  (event_id, event_type, stripe_created_at, status, attempt_count, received_at, next_attempt_at, processed_at, updated_at)
896
- VALUES (?, ?, ?, 'pending', 0, datetime('now'), datetime('now'), datetime('now'), datetime('now'))`,args:[e,t,r]})).rowsAffected===1?"queued":"duplicate"}async function Dt(e=50,t=300){let r=Math.max(1,Math.min(500,Math.trunc(e))),n=await s().execute({sql:`SELECT event_id
940
+ VALUES (?, ?, ?, 'pending', 0, datetime('now'), datetime('now'), datetime('now'), datetime('now'))`,args:[e,t,r]})).rowsAffected===1?"queued":"duplicate"}async function qt(e=50,t=300){let r=Math.max(1,Math.min(500,Math.trunc(e))),n=await i().execute({sql:`SELECT event_id
897
941
  FROM stripe_events
898
942
  WHERE (status IN ('pending', 'retryable') AND COALESCE(next_attempt_at, received_at) <= datetime('now'))
899
943
  OR (status = 'processing' AND claimed_at <= datetime('now', '-' || ? || ' seconds'))
900
944
  ORDER BY COALESCE(next_attempt_at, received_at), received_at
901
- LIMIT ?`,args:[t,r]}),i=[];for(let a of n.rows){let u=String(a.event_id),_=N();if((await s().execute({sql:`UPDATE stripe_events
945
+ LIMIT ?`,args:[t,r]}),s=[];for(let a of n.rows){let _=String(a.event_id),u=N();if((await i().execute({sql:`UPDATE stripe_events
902
946
  SET status = 'processing', attempt_count = attempt_count + 1,
903
947
  claim_token = ?, claimed_at = datetime('now'), last_error = NULL,
904
948
  last_error_code = NULL, updated_at = datetime('now')
905
949
  WHERE event_id = ?
906
950
  AND ((status IN ('pending', 'retryable') AND COALESCE(next_attempt_at, received_at) <= datetime('now'))
907
- OR (status = 'processing' AND claimed_at <= datetime('now', '-' || ? || ' seconds')))`,args:[_,u,t]})).rowsAffected!==1)continue;let c=await s().execute({sql:"SELECT event_type, attempt_count FROM stripe_events WHERE event_id = ? LIMIT 1",args:[u]});i.push({eventId:u,eventType:c.rows[0]?.event_type!=null?String(c.rows[0].event_type):null,attemptCount:Number(c.rows[0]?.attempt_count??1),token:_})}return i}async function kt(e,t){return(await s().execute({sql:`UPDATE stripe_events
951
+ OR (status = 'processing' AND claimed_at <= datetime('now', '-' || ? || ' seconds')))`,args:[u,_,t]})).rowsAffected!==1)continue;let c=await i().execute({sql:"SELECT event_type, attempt_count FROM stripe_events WHERE event_id = ? LIMIT 1",args:[_]});s.push({eventId:_,eventType:c.rows[0]?.event_type!=null?String(c.rows[0].event_type):null,attemptCount:Number(c.rows[0]?.attempt_count??1),token:u})}return s}async function Wt(e,t){return(await i().execute({sql:`UPDATE stripe_events
908
952
  SET status = 'processed',
909
953
  claim_token = NULL,
910
954
  claimed_at = NULL,
@@ -913,7 +957,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
913
957
  last_error = NULL,
914
958
  processed_at = datetime('now'),
915
959
  updated_at = datetime('now')
916
- WHERE event_id = ? AND status = 'processing' AND claim_token = ?`,args:[e,t]})).rowsAffected===1}async function vt(e,t,r,n,i){return(await s().execute({sql:`UPDATE stripe_events
960
+ WHERE event_id = ? AND status = 'processing' AND claim_token = ?`,args:[e,t]})).rowsAffected===1}async function jt(e,t,r,n,s){return(await i().execute({sql:`UPDATE stripe_events
917
961
  SET status = 'retryable',
918
962
  claim_token = NULL,
919
963
  claimed_at = NULL,
@@ -921,10 +965,10 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
921
965
  last_error_code = ?,
922
966
  next_attempt_at = datetime('now', '+' || ? || ' seconds'),
923
967
  updated_at = datetime('now')
924
- WHERE event_id = ? AND status = 'processing' AND claim_token = ?`,args:[r.slice(0,500),n.slice(0,100),Math.max(0,Math.trunc(i)),e,t]})).rowsAffected===1}async function Xt(e,t,r,n){return(await s().execute({sql:`UPDATE stripe_events
968
+ WHERE event_id = ? AND status = 'processing' AND claim_token = ?`,args:[r.slice(0,500),n.slice(0,100),Math.max(0,Math.trunc(s)),e,t]})).rowsAffected===1}async function Bt(e,t,r,n){return(await i().execute({sql:`UPDATE stripe_events
925
969
  SET status = 'dead_letter', claim_token = NULL, claimed_at = NULL,
926
970
  last_error = ?, last_error_code = ?, next_attempt_at = NULL, updated_at = datetime('now')
927
- WHERE event_id = ? AND status = 'processing' AND claim_token = ?`,args:[r.slice(0,500),n.slice(0,100),e,t]})).rowsAffected===1}async function Mt(){let t=(await s().execute(`
971
+ WHERE event_id = ? AND status = 'processing' AND claim_token = ?`,args:[r.slice(0,500),n.slice(0,100),e,t]})).rowsAffected===1}async function Gt(){let t=(await i().execute(`
928
972
  SELECT
929
973
  SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) AS pending,
930
974
  SUM(CASE WHEN status = 'processing' THEN 1 ELSE 0 END) AS processing,
@@ -932,21 +976,21 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
932
976
  SUM(CASE WHEN status = 'dead_letter' THEN 1 ELSE 0 END) AS dead_letter,
933
977
  MIN(CASE WHEN status IN ('pending', 'retryable') THEN COALESCE(next_attempt_at, received_at) END) AS oldest_due_at
934
978
  FROM stripe_events
935
- `)).rows[0];return{pending:Number(t?.pending??0),processing:Number(t?.processing??0),retryable:Number(t?.retryable??0),dead_letter:Number(t?.dead_letter??0),oldest_due_at:t?.oldest_due_at!=null?String(t.oldest_due_at):null}}async function Ft(e){return(await s().execute({sql:"SELECT 1 FROM stripe_events WHERE event_id = ? AND status = 'processed' LIMIT 1",args:[e]})).rows.length>0}function me(){return"sk_"+P(24).toString("hex")}function Ne(e){let t=P(16).toString("hex"),r=pe(e,t,64);return`${t}:${r.toString("hex")}`}function Pt(e,t){let[r,n]=t.split(":"),i=Buffer.from(n,"hex"),a=pe(e,r,64);return Ge(i,a)}function b(e){return{id:Number(e.id),email:String(e.email),name:e.name!=null?String(e.name):null,api_key:String(e.api_key),key_active:Number(e.key_active??1),password_hash:e.password_hash!=null?String(e.password_hash):null,created_at:String(e.created_at),active:Number(e.active),stripe_customer_id:e.stripe_customer_id!=null?String(e.stripe_customer_id):null,balance_mc:Number(e.balance_mc??0),extra_concurrency_slots:Number(e.extra_concurrency_slots??0),concurrency_stripe_sub_id:e.concurrency_stripe_sub_id!=null?String(e.concurrency_stripe_sub_id):null,concurrency_pack_quantity:Number(e.concurrency_pack_quantity??0),subscription_concurrency:Number(e.subscription_concurrency??0),subscription_tier:e.subscription_tier!=null?String(e.subscription_tier):null,subscription_id:e.subscription_id!=null?String(e.subscription_id):null,memory_plan:e.memory_plan!=null?String(e.memory_plan):"free",memory_subscription_id:e.memory_subscription_id!=null?String(e.memory_subscription_id):null,memory_provisioned:Number(e.memory_provisioned??0)}}async function Ht(e){let t=await s().execute({sql:"SELECT * FROM users WHERE email = ? AND active = 1",args:[e]});return t.rows[0]?b(t.rows[0]):void 0}async function Wt(e){let t=await s().execute({sql:"SELECT * FROM users WHERE api_key = ? AND active = 1 AND key_active = 1",args:[e]});return t.rows[0]?b(t.rows[0]):void 0}async function qt(e){let t=await s().execute({sql:"SELECT * FROM users WHERE id = ? AND active = 1",args:[e]});return t.rows[0]?b(t.rows[0]):void 0}async function jt(e){let r=(await s().execute({sql:"SELECT memory_key, memory_identity FROM users WHERE id = ?",args:[e]})).rows[0];return{memory_key:r?.memory_key!=null?String(r.memory_key):null,memory_identity:r?.memory_identity!=null?String(r.memory_identity):null}}async function Bt(e,t,r){await s().execute({sql:"UPDATE users SET memory_key = ?, memory_identity = ? WHERE id = ?",args:[t,r,e]})}async function Gt(e,t){await s().execute({sql:"UPDATE users SET password_hash = ? WHERE id = ?",args:[Ne(t),e]})}async function Yt(e){let t=s(),[r,n,i,a,u]=await Promise.all([t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ?",args:[e]}),t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'done'",args:[e]}),t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'failed'",args:[e]}),t.execute({sql:"SELECT COALESCE(SUM(json_extract(result, '$.totalQuestions')), 0) as n FROM jobs WHERE user_id = ? AND status = 'done'",args:[e]}),t.execute({sql:"SELECT MAX(created_at) as t FROM jobs WHERE user_id = ?",args:[e]})]);return{total:Number(r.rows[0]?.n??0),done:Number(n.rows[0]?.n??0),failed:Number(i.rows[0]?.n??0),totalQuestions:Number(a.rows[0]?.n??0),lastUsed:u.rows[0]?.t!=null?String(u.rows[0].t):null}}async function Kt(e,t,r,n){let i=s(),a=me(),u=r??P(6).toString("hex"),_=Ne(u);return{id:(await i.execute({sql:"INSERT INTO users (email, name, api_key, password_hash, stripe_customer_id) VALUES (?, ?, ?, ?, ?)",args:[e,t??null,a,_,n??null]})).lastInsertRowid,email:e,name:t,api_key:a,password:u}}async function $t(e,t,r,n){let i=Math.floor(Date.now()/1e3),a=Math.floor(i/n)*n,u=U("sha256").update(t).digest("hex"),o=await s().execute({sql:`
979
+ `)).rows[0];return{pending:Number(t?.pending??0),processing:Number(t?.processing??0),retryable:Number(t?.retryable??0),dead_letter:Number(t?.dead_letter??0),oldest_due_at:t?.oldest_due_at!=null?String(t.oldest_due_at):null}}async function Yt(e){return(await i().execute({sql:"SELECT 1 FROM stripe_events WHERE event_id = ? AND status = 'processed' LIMIT 1",args:[e]})).rows.length>0}function Re(){return"sk_"+q(24).toString("hex")}function Ae(e){let t=q(16).toString("hex"),r=Ne(e,t,64);return`${t}:${r.toString("hex")}`}function Kt(e,t){let[r,n]=t.split(":"),s=Buffer.from(n,"hex"),a=Ne(e,r,64);return ze(s,a)}function S(e){return{id:Number(e.id),email:String(e.email),name:e.name!=null?String(e.name):null,api_key:String(e.api_key),key_active:Number(e.key_active??1),password_hash:e.password_hash!=null?String(e.password_hash):null,created_at:String(e.created_at),active:Number(e.active),stripe_customer_id:e.stripe_customer_id!=null?String(e.stripe_customer_id):null,balance_mc:Number(e.balance_mc??0),extra_concurrency_slots:Number(e.extra_concurrency_slots??0),concurrency_stripe_sub_id:e.concurrency_stripe_sub_id!=null?String(e.concurrency_stripe_sub_id):null,concurrency_pack_quantity:Number(e.concurrency_pack_quantity??0),subscription_concurrency:Number(e.subscription_concurrency??0),subscription_tier:e.subscription_tier!=null?String(e.subscription_tier):null,subscription_id:e.subscription_id!=null?String(e.subscription_id):null,memory_plan:e.memory_plan!=null?String(e.memory_plan):"free",memory_subscription_id:e.memory_subscription_id!=null?String(e.memory_subscription_id):null,memory_provisioned:Number(e.memory_provisioned??0)}}async function $t(e){let t=await i().execute({sql:"SELECT * FROM users WHERE email = ? AND active = 1",args:[e]});return t.rows[0]?S(t.rows[0]):void 0}async function Jt(e){let t=await i().execute({sql:"SELECT * FROM users WHERE api_key = ? AND active = 1 AND key_active = 1",args:[e]});return t.rows[0]?S(t.rows[0]):void 0}async function Vt(e){let t=await i().execute({sql:"SELECT * FROM users WHERE id = ? AND active = 1",args:[e]});return t.rows[0]?S(t.rows[0]):void 0}async function zt(e){let r=(await i().execute({sql:"SELECT memory_key, memory_identity FROM users WHERE id = ?",args:[e]})).rows[0];return{memory_key:r?.memory_key!=null?String(r.memory_key):null,memory_identity:r?.memory_identity!=null?String(r.memory_identity):null}}async function Qt(e,t,r){await i().execute({sql:"UPDATE users SET memory_key = ?, memory_identity = ? WHERE id = ?",args:[t,r,e]})}async function Zt(e,t){await i().execute({sql:"UPDATE users SET password_hash = ? WHERE id = ?",args:[Ae(t),e]})}async function er(e){let t=i(),[r,n,s,a,_]=await Promise.all([t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ?",args:[e]}),t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'done'",args:[e]}),t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'failed'",args:[e]}),t.execute({sql:"SELECT COALESCE(SUM(json_extract(result, '$.totalQuestions')), 0) as n FROM jobs WHERE user_id = ? AND status = 'done'",args:[e]}),t.execute({sql:"SELECT MAX(created_at) as t FROM jobs WHERE user_id = ?",args:[e]})]);return{total:Number(r.rows[0]?.n??0),done:Number(n.rows[0]?.n??0),failed:Number(s.rows[0]?.n??0),totalQuestions:Number(a.rows[0]?.n??0),lastUsed:_.rows[0]?.t!=null?String(_.rows[0].t):null}}async function tr(e,t,r,n){let s=i(),a=Re(),_=r??q(6).toString("hex"),u=Ae(_);return{id:(await s.execute({sql:"INSERT INTO users (email, name, api_key, password_hash, stripe_customer_id) VALUES (?, ?, ?, ?, ?)",args:[e,t??null,a,u,n??null]})).lastInsertRowid,email:e,name:t,api_key:a,password:_}}async function rr(e,t,r,n){let s=Math.floor(Date.now()/1e3),a=Math.floor(s/n)*n,_=v("sha256").update(t).digest("hex"),o=await i().execute({sql:`
936
980
  INSERT INTO rate_limits (scope, key_hash, window_start, count)
937
981
  VALUES (?, ?, ?, 1)
938
982
  ON CONFLICT(scope, key_hash, window_start)
939
983
  DO UPDATE SET count = count + 1, updated_at = datetime('now')
940
984
  RETURNING count
941
- `,args:[e,u,a]}),c=Number(o.rows[0]?.count);if(!Number.isSafeInteger(c)||c<1)throw new Error("Rate-limit bucket mutation did not return a valid count");return{allowed:c<=r,count:c,remaining:Math.max(0,r-c),resetSeconds:Math.max(1,a+n-i)}}async function Jt(e){let t=P(32).toString("hex"),r=U("sha256").update(t).digest("hex"),n=new Date(Date.now()+3600*1e3).toISOString();return await s().execute({sql:"INSERT INTO password_reset_tokens (token, user_id, expires_at) VALUES (?, ?, ?)",args:[r,e,n]}),t}async function zt(e){let t=s(),r=U("sha256").update(e).digest("hex"),i=(await t.execute({sql:"SELECT user_id, expires_at, used FROM password_reset_tokens WHERE token = ?",args:[r]})).rows[0];return!i||Number(i.used)||new Date(String(i.expires_at))<new Date?null:(await t.execute({sql:"UPDATE password_reset_tokens SET used = 1 WHERE token = ?",args:[r]}),Number(i.user_id))}async function Vt(e){let t=me();return await s().execute({sql:"UPDATE users SET api_key = ?, key_active = 1 WHERE id = ?",args:[t,e]}),t}async function Qt(e){await s().execute({sql:"UPDATE users SET key_active = 0 WHERE id = ?",args:[e]})}async function Zt(){return(await s().execute("SELECT id, email, name, created_at, active FROM users ORDER BY created_at DESC")).rows.map(t=>b({...t,api_key:"",key_active:1}))}async function er(e){await s().execute({sql:"UPDATE users SET active = 0 WHERE id = ?",args:[e]})}function S(e){return{id:String(e.id),user_id:Number(e.user_id),status:String(e.status),query:String(e.query),options:String(e.options),callback_url:e.callback_url!=null?String(e.callback_url):null,result:e.result!=null?String(e.result):null,error:e.error!=null?String(e.error):null,public_error_json:e.public_error_json!=null?String(e.public_error_json):null,created_at:String(e.created_at),started_at:e.started_at!=null?String(e.started_at):null,completed_at:e.completed_at!=null?String(e.completed_at):null}}function I(e){return e==null?null:Number(e)===1}function F(e){if(e==null)return null;try{return JSON.parse(String(e))}catch{return null}}function ge(e){return{id:String(e.id),job_id:String(e.job_id),user_id:Number(e.user_id),attempt_number:Number(e.attempt_number),max_attempts:Number(e.max_attempts),query:String(e.query),location:e.location!=null?String(e.location):null,max_questions:Number(e.max_questions),status:String(e.status),outcome:e.outcome!=null?String(e.outcome):null,\u006b\u0065\u0072\u006e\u0065\u006c_session_id:e.\u006b\u0065\u0072\u006e\u0065\u006c_session_id!=null?String(e.\u006b\u0065\u0072\u006e\u0065\u006c_session_id):null,question_count:e.question_count!=null?Number(e.question_count):null,duration_ms:e.duration_ms!=null?Number(e.duration_ms):null,error:e.error!=null?String(e.error):null,will_retry:I(e.will_retry),\u006b\u0065\u0072\u006e\u0065\u006c_delete_started:Number(e.\u006b\u0065\u0072\u006e\u0065\u006c_delete_started??0)===1,\u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded:I(e.\u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded),\u006b\u0065\u0072\u006e\u0065\u006c_delete_error:e.\u006b\u0065\u0072\u006e\u0065\u006c_delete_error!=null?String(e.\u006b\u0065\u0072\u006e\u0065\u006c_delete_error):null,browser_close_succeeded:I(e.browser_close_succeeded),browser_close_error:e.browser_close_error!=null?String(e.browser_close_error):null,browser_provider:e.browser_provider!=null?String(e.browser_provider):null,provider_session_id:e.provider_session_id!=null?String(e.provider_session_id):null,provider_session_observed_at:e.provider_session_observed_at!=null?String(e.provider_session_observed_at):null,provider_lookup_status:e.provider_lookup_status!=null?String(e.provider_lookup_status):null,provider_status:e.provider_status!=null?String(e.provider_status):null,provider_error_code:e.provider_error_code!=null?String(e.provider_error_code):null,provider_error_message:e.provider_error_message!=null?String(e.provider_error_message):null,provider_reason_source:e.provider_reason_source!=null?String(e.provider_reason_source):null,provider_duration_ms:e.provider_duration_ms!=null?Number(e.provider_duration_ms):null,provider_bandwidth_bytes:e.provider_bandwidth_bytes!=null?Number(e.provider_bandwidth_bytes):null,provider_captcha:I(e.provider_captcha),provider_checked_at:e.provider_checked_at!=null?String(e.provider_checked_at):null,provider_detail:F(e.provider_detail_json),provider_disconnect_observed:I(e.provider_disconnect_observed),provider_disconnect_message:e.provider_disconnect_message!=null?String(e.provider_disconnect_message):null,debug:F(e.debug_json),created_at:String(e.created_at),completed_at:e.completed_at!=null?String(e.completed_at):null}}function O(e){let{public_error_json:t,...r}=e;return{...r,options:JSON.parse(e.options),result:e.result?JSON.parse(e.result):null,publicError:se(t)}}async function tr(e,t,r,n){let i=N();return await Ve(i,e,t,r,n),i}async function Ve(e,t,r,n,i){if(!/^[a-zA-Z0-9-]{1,100}$/.test(e))throw new Error("job id is invalid");await s().execute({sql:"INSERT INTO jobs (id, user_id, query, options, callback_url) VALUES (?, ?, ?, ?, ?)",args:[e,t,r,JSON.stringify(n),i??null]})}async function rr(e,t,r){let n=N();return await s().execute({sql:"INSERT INTO jobs (id, user_id, query, options, status, started_at) VALUES (?, ?, ?, ?, 'running', datetime('now'))",args:[n,e,t,JSON.stringify(r)]}),n}async function nr(e,t,r,n){let i=await s().execute({sql:`INSERT INTO jobs (id, user_id, query, options, status, started_at)
985
+ `,args:[e,_,a]}),c=Number(o.rows[0]?.count);if(!Number.isSafeInteger(c)||c<1)throw new Error("Rate-limit bucket mutation did not return a valid count");return{allowed:c<=r,count:c,remaining:Math.max(0,r-c),resetSeconds:Math.max(1,a+n-s)}}async function nr(e){let t=q(32).toString("hex"),r=v("sha256").update(t).digest("hex"),n=new Date(Date.now()+3600*1e3).toISOString();return await i().execute({sql:"INSERT INTO password_reset_tokens (token, user_id, expires_at) VALUES (?, ?, ?)",args:[r,e,n]}),t}async function sr(e){let t=i(),r=v("sha256").update(e).digest("hex"),s=(await t.execute({sql:"SELECT user_id, expires_at, used FROM password_reset_tokens WHERE token = ?",args:[r]})).rows[0];return!s||Number(s.used)||new Date(String(s.expires_at))<new Date?null:(await t.execute({sql:"UPDATE password_reset_tokens SET used = 1 WHERE token = ?",args:[r]}),Number(s.user_id))}async function ir(e){let t=Re();return await i().execute({sql:"UPDATE users SET api_key = ?, key_active = 1 WHERE id = ?",args:[t,e]}),t}async function ar(e){await i().execute({sql:"UPDATE users SET key_active = 0 WHERE id = ?",args:[e]})}async function or(){return(await i().execute("SELECT id, email, name, created_at, active FROM users ORDER BY created_at DESC")).rows.map(t=>S({...t,api_key:"",key_active:1}))}async function _r(e){await i().execute({sql:"UPDATE users SET active = 0 WHERE id = ?",args:[e]})}function R(e){return{id:String(e.id),user_id:Number(e.user_id),status:String(e.status),query:String(e.query),options:String(e.options),callback_url:e.callback_url!=null?String(e.callback_url):null,result:e.result!=null?String(e.result):null,error:e.error!=null?String(e.error):null,public_error_json:e.public_error_json!=null?String(e.public_error_json):null,created_at:String(e.created_at),started_at:e.started_at!=null?String(e.started_at):null,completed_at:e.completed_at!=null?String(e.completed_at):null}}function C(e){return e==null?null:Number(e)===1}function H(e){if(e==null)return null;try{return JSON.parse(String(e))}catch{return null}}function we(e){return{id:String(e.id),job_id:String(e.job_id),user_id:Number(e.user_id),attempt_number:Number(e.attempt_number),max_attempts:Number(e.max_attempts),query:String(e.query),location:e.location!=null?String(e.location):null,max_questions:Number(e.max_questions),status:String(e.status),outcome:e.outcome!=null?String(e.outcome):null,\u006b\u0065\u0072\u006e\u0065\u006c_session_id:e.\u006b\u0065\u0072\u006e\u0065\u006c_session_id!=null?String(e.\u006b\u0065\u0072\u006e\u0065\u006c_session_id):null,question_count:e.question_count!=null?Number(e.question_count):null,duration_ms:e.duration_ms!=null?Number(e.duration_ms):null,error:e.error!=null?String(e.error):null,will_retry:C(e.will_retry),\u006b\u0065\u0072\u006e\u0065\u006c_delete_started:Number(e.\u006b\u0065\u0072\u006e\u0065\u006c_delete_started??0)===1,\u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded:C(e.\u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded),\u006b\u0065\u0072\u006e\u0065\u006c_delete_error:e.\u006b\u0065\u0072\u006e\u0065\u006c_delete_error!=null?String(e.\u006b\u0065\u0072\u006e\u0065\u006c_delete_error):null,browser_close_succeeded:C(e.browser_close_succeeded),browser_close_error:e.browser_close_error!=null?String(e.browser_close_error):null,browser_provider:e.browser_provider!=null?String(e.browser_provider):null,provider_session_id:e.provider_session_id!=null?String(e.provider_session_id):null,provider_session_observed_at:e.provider_session_observed_at!=null?String(e.provider_session_observed_at):null,provider_lookup_status:e.provider_lookup_status!=null?String(e.provider_lookup_status):null,provider_status:e.provider_status!=null?String(e.provider_status):null,provider_error_code:e.provider_error_code!=null?String(e.provider_error_code):null,provider_error_message:e.provider_error_message!=null?String(e.provider_error_message):null,provider_reason_source:e.provider_reason_source!=null?String(e.provider_reason_source):null,provider_duration_ms:e.provider_duration_ms!=null?Number(e.provider_duration_ms):null,provider_bandwidth_bytes:e.provider_bandwidth_bytes!=null?Number(e.provider_bandwidth_bytes):null,provider_captcha:C(e.provider_captcha),provider_checked_at:e.provider_checked_at!=null?String(e.provider_checked_at):null,provider_detail:H(e.provider_detail_json),provider_disconnect_observed:C(e.provider_disconnect_observed),provider_disconnect_message:e.provider_disconnect_message!=null?String(e.provider_disconnect_message):null,debug:H(e.debug_json),created_at:String(e.created_at),completed_at:e.completed_at!=null?String(e.completed_at):null}}function h(e){let{public_error_json:t,...r}=e;return{...r,options:JSON.parse(e.options),result:e.result?JSON.parse(e.result):null,publicError:ae(t)}}async function ur(e,t,r,n){let s=N();return await it(s,e,t,r,n),s}async function it(e,t,r,n,s){if(!/^[a-zA-Z0-9-]{1,100}$/.test(e))throw new Error("job id is invalid");await i().execute({sql:"INSERT INTO jobs (id, user_id, query, options, callback_url) VALUES (?, ?, ?, ?, ?)",args:[e,t,r,JSON.stringify(n),s??null]})}async function cr(e,t,r){let n=N();return await i().execute({sql:"INSERT INTO jobs (id, user_id, query, options, status, started_at) VALUES (?, ?, ?, ?, 'running', datetime('now'))",args:[n,e,t,JSON.stringify(r)]}),n}async function dr(e,t,r,n){let s=await i().execute({sql:`INSERT INTO jobs (id, user_id, query, options, status, started_at)
942
986
  VALUES (?, ?, ?, ?, 'running', datetime('now'))
943
- ON CONFLICT(id) DO NOTHING`,args:[e,t,r,JSON.stringify(n)]}),a=await G(e,t);if(!a)throw new Error(`getOrCreateRunningJob: row missing immediately after insert/lookup for ${e}`);return{job:a,created:i.rowsAffected===1}}async function sr(e){await s().execute({sql:`
987
+ ON CONFLICT(id) DO NOTHING`,args:[e,t,r,JSON.stringify(n)]}),a=await K(e,t);if(!a)throw new Error(`getOrCreateRunningJob: row missing immediately after insert/lookup for ${e}`);return{job:a,created:s.rowsAffected===1}}async function lr(e){await i().execute({sql:`
944
988
  INSERT INTO harvest_attempts (
945
989
  id, job_id, user_id, attempt_number, max_attempts, query, location, max_questions, status, created_at
946
990
  )
947
991
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'running', ?)
948
992
  ON CONFLICT(job_id, attempt_number) DO NOTHING
949
- `,args:[N(),e.jobId,e.userId,e.attemptNumber,e.maxAttempts,e.query,e.location,e.maxQuestions,e.startedAt]})}async function ir(e){return(await s().execute({sql:`
993
+ `,args:[N(),e.jobId,e.userId,e.attemptNumber,e.maxAttempts,e.query,e.location,e.maxQuestions,e.startedAt]})}async function Er(e){return(await i().execute({sql:`
950
994
  UPDATE harvest_attempts SET
951
995
  browser_provider = ?,
952
996
  provider_session_id = ?,
@@ -956,7 +1000,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
956
1000
  ELSE 'pending'
957
1001
  END
958
1002
  WHERE job_id = ? AND attempt_number = ? AND status = 'running'
959
- `,args:[e.browserProvider,e.providerSessionId,e.observedAt,e.jobId,e.attemptNumber]})).rowsAffected===1}async function ar(e,t,r=new Date().toISOString()){return(await s().execute({sql:`
1003
+ `,args:[e.browserProvider,e.providerSessionId,e.observedAt,e.jobId,e.attemptNumber]})).rowsAffected===1}async function Tr(e,t,r=new Date().toISOString()){return(await i().execute({sql:`
960
1004
  UPDATE harvest_attempts SET
961
1005
  status = 'finished',
962
1006
  outcome = COALESCE(outcome, 'timeout'),
@@ -969,7 +1013,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
969
1013
  provider_reason_source = COALESCE(provider_reason_source, 'client_runtime'),
970
1014
  completed_at = COALESCE(completed_at, ?)
971
1015
  WHERE job_id = ? AND status = 'running'
972
- `,args:[r,t?1:0,r,e]})).rowsAffected}async function or(e){await s().execute({sql:`
1016
+ `,args:[r,t?1:0,r,e]})).rowsAffected}async function pr(e){await i().execute({sql:`
973
1017
  UPDATE harvest_attempts SET
974
1018
  status = 'finished',
975
1019
  outcome = ?,
@@ -1012,7 +1056,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1012
1056
  debug_json = ?,
1013
1057
  completed_at = ?
1014
1058
  WHERE job_id = ? AND attempt_number = ?
1015
- `,args:[e.outcome,e.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,e.questionCount,e.durationMs,e.error,e.willRetry?1:0,e.\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted?1:0,e.\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded==null?null:e.\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded?1:0,e.\u006b\u0065\u0072\u006e\u0065\u006cDeleteError,e.browserCloseSucceeded==null?null:e.browserCloseSucceeded?1:0,e.browserCloseError,e.browserProvider??null,e.providerSessionId??null,e.providerLookupStatus??null,e.providerStatus??null,e.providerErrorCode??null,e.providerErrorMessage??null,e.providerReasonSource??null,e.providerDurationMs??null,e.providerBandwidthBytes??null,e.providerCaptcha==null?null:e.providerCaptcha?1:0,e.providerCheckedAt??null,e.providerDetail==null?null:Le(e.providerDetail),e.providerDisconnectObserved==null?null:e.providerDisconnectObserved?1:0,e.providerDisconnectMessage??null,e.debug==null?null:JSON.stringify(e.debug),e.completedAt,e.jobId,e.attemptNumber]})}function Le(e,t=4096){let r=JSON.stringify(e);return r.length<=t?r:JSON.stringify({truncated:!0})}async function ur(e){return(await s().execute({sql:`
1059
+ `,args:[e.outcome,e.\u006b\u0065\u0072\u006e\u0065\u006cSessionId,e.questionCount,e.durationMs,e.error,e.willRetry?1:0,e.\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted?1:0,e.\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded==null?null:e.\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded?1:0,e.\u006b\u0065\u0072\u006e\u0065\u006cDeleteError,e.browserCloseSucceeded==null?null:e.browserCloseSucceeded?1:0,e.browserCloseError,e.browserProvider??null,e.providerSessionId??null,e.providerLookupStatus??null,e.providerStatus??null,e.providerErrorCode??null,e.providerErrorMessage??null,e.providerReasonSource??null,e.providerDurationMs??null,e.providerBandwidthBytes??null,e.providerCaptcha==null?null:e.providerCaptcha?1:0,e.providerCheckedAt??null,e.providerDetail==null?null:Oe(e.providerDetail),e.providerDisconnectObserved==null?null:e.providerDisconnectObserved?1:0,e.providerDisconnectMessage??null,e.debug==null?null:JSON.stringify(e.debug),e.completedAt,e.jobId,e.attemptNumber]})}function Oe(e,t=4096){let r=JSON.stringify(e);return r.length<=t?r:JSON.stringify({truncated:!0})}async function mr(e){return(await i().execute({sql:`
1016
1060
  UPDATE harvest_attempts SET
1017
1061
  provider_lookup_status = ?,
1018
1062
  provider_status = ?,
@@ -1030,24 +1074,24 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1030
1074
  AND browser_provider = '\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api'
1031
1075
  AND provider_session_id = ?
1032
1076
  AND COALESCE(provider_lookup_status, '') <> 'complete'
1033
- `,args:[e.lookupStatus,e.providerStatus??null,e.errorCode??null,e.errorMessage??null,e.reasonSource??null,e.durationMs??null,e.bandwidthBytes??null,e.captcha==null?null:e.captcha?1:0,e.checkedAt,e.detail==null?null:Le(e.detail),e.attemptId,e.jobId,e.userId,e.providerSessionId]})).rowsAffected===1}async function _r(e=25){let t=Math.max(1,Math.min(100,Math.trunc(e)));return(await s().execute({sql:`
1077
+ `,args:[e.lookupStatus,e.providerStatus??null,e.errorCode??null,e.errorMessage??null,e.reasonSource??null,e.durationMs??null,e.bandwidthBytes??null,e.captcha==null?null:e.captcha?1:0,e.checkedAt,e.detail==null?null:Oe(e.detail),e.attemptId,e.jobId,e.userId,e.providerSessionId]})).rowsAffected===1}async function Nr(e=25){let t=Math.max(1,Math.min(100,Math.trunc(e)));return(await i().execute({sql:`
1034
1078
  SELECT * FROM harvest_attempts
1035
1079
  WHERE browser_provider = '\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api'
1036
1080
  AND provider_session_id IS NOT NULL
1037
1081
  AND provider_lookup_status IN ('pending', 'temporary_error')
1038
1082
  ORDER BY COALESCE(provider_checked_at, created_at) ASC
1039
1083
  LIMIT ?
1040
- `,args:[t]})).rows.map(n=>ge(n))}async function cr(e,t){return(t==null?await s().execute({sql:"SELECT * FROM harvest_attempts WHERE job_id = ? ORDER BY attempt_number ASC",args:[e]}):await s().execute({sql:`
1084
+ `,args:[t]})).rows.map(n=>we(n))}async function gr(e,t){return(t==null?await i().execute({sql:"SELECT * FROM harvest_attempts WHERE job_id = ? ORDER BY attempt_number ASC",args:[e]}):await i().execute({sql:`
1041
1085
  SELECT ha.*
1042
1086
  FROM harvest_attempts ha
1043
1087
  INNER JOIN jobs j ON j.id = ha.job_id
1044
1088
  WHERE ha.job_id = ? AND j.user_id = ?
1045
1089
  ORDER BY ha.attempt_number ASC
1046
- `,args:[e,t]})).rows.map(n=>ge(n))}async function G(e,t){let r=s(),n=t?await r.execute({sql:"SELECT * FROM jobs WHERE id = ? AND user_id = ?",args:[e,t]}):await r.execute({sql:"SELECT * FROM jobs WHERE id = ?",args:[e]});return n.rows[0]?O(S(n.rows[0])):void 0}async function dr(e,t,r){await s().execute({sql:`UPDATE jobs
1090
+ `,args:[e,t]})).rows.map(n=>we(n))}async function K(e,t){let r=i(),n=t?await r.execute({sql:"SELECT * FROM jobs WHERE id = ? AND user_id = ?",args:[e,t]}):await r.execute({sql:"SELECT * FROM jobs WHERE id = ?",args:[e]});return n.rows[0]?h(R(n.rows[0])):void 0}async function Lr(e,t,r){await i().execute({sql:`UPDATE jobs
1047
1091
  SET status = 'running', started_at = COALESCE(started_at, datetime('now'))
1048
1092
  WHERE id = ? AND status = 'pending'
1049
1093
  AND json_extract(options, '$.executionOwner') = ?
1050
- AND json_extract(options, '$.jobKind') = ?`,args:[e,t,r]});let n=await G(e);if(!(!n||n.options.executionOwner!==t||n.options.jobKind!==r))return n}async function lr(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await s().execute({sql:`SELECT * FROM jobs
1094
+ AND json_extract(options, '$.jobKind') = ?`,args:[e,t,r]});let n=await K(e);if(!(!n||n.options.executionOwner!==t||n.options.jobKind!==r))return n}async function br(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await i().execute({sql:`SELECT * FROM jobs
1051
1095
  WHERE status = 'pending'
1052
1096
  AND json_extract(options, '$.executionOwner') = 'inngest'
1053
1097
  AND json_extract(options, '$.jobKind') = 'extract_url'
@@ -1055,14 +1099,14 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1055
1099
  AND created_at <= datetime('now', '-30 seconds')
1056
1100
  AND datetime(COALESCE(json_extract(options, '$.extractUrlLastDispatchAt'), '1970-01-01')) <= datetime('now', '-30 seconds')
1057
1101
  ORDER BY created_at
1058
- LIMIT ?`,args:[t]})).rows.map(n=>O(S(n)))}async function Er(e,t){return(await s().execute({sql:`UPDATE jobs
1102
+ LIMIT ?`,args:[t]})).rows.map(n=>h(R(n)))}async function Sr(e,t){return(await i().execute({sql:`UPDATE jobs
1059
1103
  SET options = json_set(options,
1060
1104
  '$.extractUrlDispatchAttempts', COALESCE(json_extract(options, '$.extractUrlDispatchAttempts'), 0) + 1,
1061
1105
  '$.extractUrlLastDispatchAt', ?,
1062
1106
  '$.extractUrlLastDispatchError', ?)
1063
1107
  WHERE id = ? AND status = 'pending'
1064
1108
  AND json_extract(options, '$.executionOwner') = 'inngest'
1065
- AND json_extract(options, '$.jobKind') = 'extract_url'`,args:[new Date().toISOString(),t??null,e]})).rowsAffected===1}async function Tr(e){return(await s().execute({sql:"SELECT * FROM jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50",args:[e]})).rows.map(r=>O(S(r)))}async function pr(e,t){let n=(await s().execute({sql:"SELECT content_hash, content, title, content_bytes, truncated, checked_at FROM page_snapshots WHERE user_id = ? AND url = ?",args:[e,t]})).rows[0];return n?{contentHash:String(n.content_hash),content:String(n.content),title:n.title==null?null:String(n.title),contentBytes:Number(n.content_bytes),truncated:Number(n.truncated)===1,checkedAt:String(n.checked_at)}:null}async function mr(e,t,r){await s().execute({sql:`
1109
+ AND json_extract(options, '$.jobKind') = 'extract_url'`,args:[new Date().toISOString(),t??null,e]})).rowsAffected===1}async function Rr(e){return(await i().execute({sql:"SELECT * FROM jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50",args:[e]})).rows.map(r=>h(R(r)))}async function Ar(e,t){let n=(await i().execute({sql:"SELECT content_hash, content, title, content_bytes, truncated, checked_at FROM page_snapshots WHERE user_id = ? AND url = ?",args:[e,t]})).rows[0];return n?{contentHash:String(n.content_hash),content:String(n.content),title:n.title==null?null:String(n.title),contentBytes:Number(n.content_bytes),truncated:Number(n.truncated)===1,checkedAt:String(n.checked_at)}:null}async function wr(e,t,r){await i().execute({sql:`
1066
1110
  INSERT INTO page_snapshots (user_id, url, content_hash, content, title, content_bytes, truncated, checked_at)
1067
1111
  VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'))
1068
1112
  ON CONFLICT(user_id, url) DO UPDATE SET
@@ -1072,56 +1116,56 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1072
1116
  content_bytes = excluded.content_bytes,
1073
1117
  truncated = excluded.truncated,
1074
1118
  checked_at = excluded.checked_at
1075
- `,args:[e,t,r.contentHash,r.content,r.title,r.contentBytes,r.truncated?1:0]})}var Qe=32*1024;function Ze(e){if(e==null)return null;let t=JSON.stringify(e),r=Buffer.byteLength(t,"utf8");return r<=Qe?t:JSON.stringify({truncated:!0,originalBytes:r,sha256:U("sha256").update(t).digest("hex")})}function et(e){let t=e.result!=null?String(e.result):null;return{id:String(e.id),user_id:Number(e.user_id),source:String(e.source),status:String(e.status),query:String(e.query),location:e.location!=null?String(e.location):null,result_count:e.result_count!=null?Number(e.result_count):null,result:t?JSON.parse(t):null,error:e.error!=null?String(e.error):null,created_at:String(e.created_at)}}async function Nr(e){let t=N();return await s().execute({sql:`
1119
+ `,args:[e,t,r.contentHash,r.content,r.title,r.contentBytes,r.truncated?1:0]})}var at=32*1024;function ot(e){if(e==null)return null;let t=JSON.stringify(e),r=Buffer.byteLength(t,"utf8");return r<=at?t:JSON.stringify({truncated:!0,originalBytes:r,sha256:v("sha256").update(t).digest("hex")})}function _t(e){let t=e.result!=null?String(e.result):null;return{id:String(e.id),user_id:Number(e.user_id),source:String(e.source),status:String(e.status),query:String(e.query),location:e.location!=null?String(e.location):null,result_count:e.result_count!=null?Number(e.result_count):null,result:t?JSON.parse(t):null,error:e.error!=null?String(e.error):null,created_at:String(e.created_at)}}async function Or(e){let t=N();return await i().execute({sql:`
1076
1120
  INSERT INTO request_events (id, user_id, source, status, query, location, result_count, result, error)
1077
1121
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
1078
- `,args:[t,e.userId,e.source,e.status,e.query,e.location??null,e.resultCount??null,Ze(e.result),e.error??null]}),t}async function gr(e,t=100){return(await s().execute({sql:`
1122
+ `,args:[t,e.userId,e.source,e.status,e.query,e.location??null,e.resultCount??null,ot(e.result),e.error??null]}),t}async function fr(e,t=100){return(await i().execute({sql:`
1079
1123
  SELECT id, user_id, source, status, query, location, result_count, NULL AS result, error, created_at
1080
1124
  FROM request_events
1081
1125
  WHERE user_id = ?
1082
1126
  ORDER BY created_at DESC
1083
1127
  LIMIT ?
1084
- `,args:[e,t]})).rows.map(n=>et(n))}function be(e){if(e==null)return{};try{let t=JSON.parse(String(e));return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}catch{return{}}}function Y(e){return{id:String(e.id),user_id:Number(e.user_id),workflow_id:String(e.workflow_id),name:String(e.name),input:be(e.input_json),cadence:String(e.cadence),cron_expr:e.cron_expr!=null?String(e.cron_expr):null,timezone:String(e.timezone??"UTC"),webhook_url:e.webhook_url!=null?String(e.webhook_url):null,status:String(e.status),next_run_at:e.next_run_at!=null?String(e.next_run_at):null,last_run_at:e.last_run_at!=null?String(e.last_run_at):null,created_at:String(e.created_at),updated_at:String(e.updated_at)}}function K(e){return{id:String(e.id),user_id:Number(e.user_id),schedule_id:e.schedule_id!=null?String(e.schedule_id):null,workflow_id:String(e.workflow_id),input:be(e.input_json),status:String(e.status),manifest:e.manifest_json!=null?F(e.manifest_json):null,error_message:e.error_message!=null?String(e.error_message):null,queued_at:String(e.queued_at),started_at:e.started_at!=null?String(e.started_at):null,completed_at:e.completed_at!=null?String(e.completed_at):null,idempotency_key:e.idempotency_key!=null?String(e.idempotency_key):null,step_index:e.step_index!=null?Number(e.step_index):0,total_steps:e.total_steps!=null?Number(e.total_steps):null,step_log:Se(e.step_log_json),webhook_url:e.webhook_url!=null?String(e.webhook_url):null}}function Se(e){if(e==null)return[];try{let t=JSON.parse(String(e));return Array.isArray(t)?t:[]}catch{return[]}}function Re(e){return{id:String(e.id),run_id:String(e.run_id),user_id:Number(e.user_id),kind:String(e.kind),label:String(e.label),path:String(e.path),content_type:String(e.content_type),bytes:e.bytes!=null?Number(e.bytes):null,rows_count:e.rows_count!=null?Number(e.rows_count):null,content:e.content!=null?String(e.content):null,created_at:String(e.created_at)}}async function Lr(e){let t=N();await s().execute({sql:`
1128
+ `,args:[e,t]})).rows.map(n=>_t(n))}function fe(e){if(e==null)return{};try{let t=JSON.parse(String(e));return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}catch{return{}}}function $(e){return{id:String(e.id),user_id:Number(e.user_id),workflow_id:String(e.workflow_id),name:String(e.name),input:fe(e.input_json),cadence:String(e.cadence),cron_expr:e.cron_expr!=null?String(e.cron_expr):null,timezone:String(e.timezone??"UTC"),webhook_url:e.webhook_url!=null?String(e.webhook_url):null,status:String(e.status),next_run_at:e.next_run_at!=null?String(e.next_run_at):null,last_run_at:e.last_run_at!=null?String(e.last_run_at):null,created_at:String(e.created_at),updated_at:String(e.updated_at)}}function J(e){return{id:String(e.id),user_id:Number(e.user_id),schedule_id:e.schedule_id!=null?String(e.schedule_id):null,workflow_id:String(e.workflow_id),input:fe(e.input_json),status:String(e.status),manifest:e.manifest_json!=null?H(e.manifest_json):null,error_message:e.error_message!=null?String(e.error_message):null,queued_at:String(e.queued_at),started_at:e.started_at!=null?String(e.started_at):null,completed_at:e.completed_at!=null?String(e.completed_at):null,idempotency_key:e.idempotency_key!=null?String(e.idempotency_key):null,step_index:e.step_index!=null?Number(e.step_index):0,total_steps:e.total_steps!=null?Number(e.total_steps):null,step_log:he(e.step_log_json),webhook_url:e.webhook_url!=null?String(e.webhook_url):null}}function he(e){if(e==null)return[];try{let t=JSON.parse(String(e));return Array.isArray(t)?t:[]}catch{return[]}}function Ie(e){return{id:String(e.id),run_id:String(e.run_id),user_id:Number(e.user_id),kind:String(e.kind),label:String(e.label),path:String(e.path),content_type:String(e.content_type),bytes:e.bytes!=null?Number(e.bytes):null,rows_count:e.rows_count!=null?Number(e.rows_count):null,content:e.content!=null?String(e.content):null,created_at:String(e.created_at)}}async function hr(e){let t=N();await i().execute({sql:`
1085
1129
  INSERT INTO workflow_schedules (
1086
1130
  id, user_id, workflow_id, name, input_json, cadence, timezone, webhook_url, next_run_at
1087
1131
  )
1088
1132
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
1089
- `,args:[t,e.userId,e.workflowId,e.name,JSON.stringify(e.workflowInput),e.cadence,e.timezone??"UTC",e.webhookUrl??null,e.nextRunAt??null]});let r=await B(t,e.userId);if(!r)throw new Error("Failed to create workflow schedule");return r}async function B(e,t){let r=t==null?await s().execute({sql:"SELECT * FROM workflow_schedules WHERE id = ? AND status != ? LIMIT 1",args:[e,"deleted"]}):await s().execute({sql:"SELECT * FROM workflow_schedules WHERE id = ? AND user_id = ? AND status != ? LIMIT 1",args:[e,t,"deleted"]});return r.rows[0]?Y(r.rows[0]):null}async function br(e){return(await s().execute({sql:"SELECT * FROM workflow_schedules WHERE user_id = ? AND status != 'deleted' ORDER BY created_at DESC LIMIT 100",args:[e]})).rows.map(r=>Y(r))}async function Sr(e){let t=[],r=[];return e.name!==void 0&&(t.push("name = ?"),r.push(e.name)),e.status!==void 0&&(t.push("status = ?"),r.push(e.status)),e.workflowInput!==void 0&&(t.push("input_json = ?"),r.push(JSON.stringify(e.workflowInput))),e.cadence!==void 0&&(t.push("cadence = ?"),r.push(e.cadence)),e.timezone!==void 0&&(t.push("timezone = ?"),r.push(e.timezone)),e.webhookUrl!==void 0&&(t.push("webhook_url = ?"),r.push(e.webhookUrl)),e.nextRunAt!==void 0&&(t.push("next_run_at = ?"),r.push(e.nextRunAt)),t.length===0||(t.push("updated_at = datetime('now')"),await s().execute({sql:`UPDATE workflow_schedules SET ${t.join(", ")} WHERE id = ? AND user_id = ? AND status != 'deleted'`,args:[...r,e.id,e.userId]})),B(e.id,e.userId)}async function Rr(e,t){return(await s().execute({sql:"UPDATE workflow_schedules SET status = 'deleted', updated_at = datetime('now') WHERE id = ? AND user_id = ? AND status != 'deleted'",args:[e,t]})).rowsAffected>0}async function Ar(e,t=10){return(await s().execute({sql:`
1133
+ `,args:[t,e.userId,e.workflowId,e.name,JSON.stringify(e.workflowInput),e.cadence,e.timezone??"UTC",e.webhookUrl??null,e.nextRunAt??null]});let r=await Y(t,e.userId);if(!r)throw new Error("Failed to create workflow schedule");return r}async function Y(e,t){let r=t==null?await i().execute({sql:"SELECT * FROM workflow_schedules WHERE id = ? AND status != ? LIMIT 1",args:[e,"deleted"]}):await i().execute({sql:"SELECT * FROM workflow_schedules WHERE id = ? AND user_id = ? AND status != ? LIMIT 1",args:[e,t,"deleted"]});return r.rows[0]?$(r.rows[0]):null}async function Ir(e){return(await i().execute({sql:"SELECT * FROM workflow_schedules WHERE user_id = ? AND status != 'deleted' ORDER BY created_at DESC LIMIT 100",args:[e]})).rows.map(r=>$(r))}async function xr(e){let t=[],r=[];return e.name!==void 0&&(t.push("name = ?"),r.push(e.name)),e.status!==void 0&&(t.push("status = ?"),r.push(e.status)),e.workflowInput!==void 0&&(t.push("input_json = ?"),r.push(JSON.stringify(e.workflowInput))),e.cadence!==void 0&&(t.push("cadence = ?"),r.push(e.cadence)),e.timezone!==void 0&&(t.push("timezone = ?"),r.push(e.timezone)),e.webhookUrl!==void 0&&(t.push("webhook_url = ?"),r.push(e.webhookUrl)),e.nextRunAt!==void 0&&(t.push("next_run_at = ?"),r.push(e.nextRunAt)),t.length===0||(t.push("updated_at = datetime('now')"),await i().execute({sql:`UPDATE workflow_schedules SET ${t.join(", ")} WHERE id = ? AND user_id = ? AND status != 'deleted'`,args:[...r,e.id,e.userId]})),Y(e.id,e.userId)}async function yr(e,t){return(await i().execute({sql:"UPDATE workflow_schedules SET status = 'deleted', updated_at = datetime('now') WHERE id = ? AND user_id = ? AND status != 'deleted'",args:[e,t]})).rowsAffected>0}async function Cr(e,t=10){return(await i().execute({sql:`
1090
1134
  SELECT * FROM workflow_schedules
1091
1135
  WHERE status = 'active' AND next_run_at IS NOT NULL AND next_run_at <= ?
1092
1136
  ORDER BY next_run_at ASC
1093
1137
  LIMIT ?
1094
- `,args:[e,t]})).rows.map(n=>Y(n))}async function wr(e,t,r){await s().execute({sql:"UPDATE workflow_schedules SET last_run_at = ?, next_run_at = ?, updated_at = datetime('now') WHERE id = ?",args:[t,r,e]})}async function Or(e){let t=e.id??N(),r=[t,e.userId,e.scheduleId??null,e.workflowId,JSON.stringify(e.workflowInput),e.idempotencyKey??null,e.webhookUrl??null,e.totalSteps??null];try{await s().execute({sql:`
1138
+ `,args:[e,t]})).rows.map(n=>$(n))}async function Ur(e,t,r){await i().execute({sql:"UPDATE workflow_schedules SET last_run_at = ?, next_run_at = ?, updated_at = datetime('now') WHERE id = ?",args:[t,r,e]})}async function Dr(e){let t=e.id??N(),r=[t,e.userId,e.scheduleId??null,e.workflowId,JSON.stringify(e.workflowInput),e.idempotencyKey??null,e.webhookUrl??null,e.totalSteps??null];try{await i().execute({sql:`
1095
1139
  INSERT INTO workflow_runs (id, user_id, schedule_id, workflow_id, input_json, idempotency_key, webhook_url, total_steps)
1096
1140
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
1097
- `,args:r})}catch(i){if(e.idempotencyKey){let a=await rt(e.idempotencyKey);if(a)return a}throw i}let n=await tt(t,e.userId);if(!n)throw new Error("Failed to create workflow run");return n}async function tt(e,t){let r=t==null?await s().execute({sql:"SELECT * FROM workflow_runs WHERE id = ? LIMIT 1",args:[e]}):await s().execute({sql:"SELECT * FROM workflow_runs WHERE id = ? AND user_id = ? LIMIT 1",args:[e,t]});return r.rows[0]?K(r.rows[0]):null}async function rt(e){let t=await s().execute({sql:"SELECT * FROM workflow_runs WHERE idempotency_key = ? LIMIT 1",args:[e]});return t.rows[0]?K(t.rows[0]):null}async function fr(e,t=50){return(await s().execute({sql:"SELECT * FROM workflow_runs WHERE user_id = ? ORDER BY queued_at DESC LIMIT ?",args:[e,t]})).rows.map(n=>K(n))}async function hr(e){await s().execute({sql:"UPDATE workflow_runs SET status = 'running', started_at = COALESCE(started_at, datetime('now')) WHERE id = ?",args:[e]})}async function xr(e,t,r){await s().execute({sql:"UPDATE workflow_runs SET status = ?, manifest_json = ?, completed_at = datetime('now') WHERE id = ?",args:[t,JSON.stringify(r),e]})}async function Ir(e,t,r){await s().execute({sql:"UPDATE workflow_runs SET status = 'failed', error_message = ?, manifest_json = ?, completed_at = datetime('now') WHERE id = ?",args:[t,r==null?null:JSON.stringify(r),e]})}function nt(e){return e==="html_report"?"text/html; charset=utf-8":e==="csv"?"text/csv; charset=utf-8":e==="json"?"application/json; charset=utf-8":"text/plain; charset=utf-8"}async function Ae(e,t,r){await s().execute({sql:`
1141
+ `,args:r})}catch(s){if(e.idempotencyKey){let a=await ct(e.idempotencyKey);if(a)return a}throw s}let n=await ut(t,e.userId);if(!n)throw new Error("Failed to create workflow run");return n}async function ut(e,t){let r=t==null?await i().execute({sql:"SELECT * FROM workflow_runs WHERE id = ? LIMIT 1",args:[e]}):await i().execute({sql:"SELECT * FROM workflow_runs WHERE id = ? AND user_id = ? LIMIT 1",args:[e,t]});return r.rows[0]?J(r.rows[0]):null}async function ct(e){let t=await i().execute({sql:"SELECT * FROM workflow_runs WHERE idempotency_key = ? LIMIT 1",args:[e]});return t.rows[0]?J(t.rows[0]):null}async function vr(e,t=50){return(await i().execute({sql:"SELECT * FROM workflow_runs WHERE user_id = ? ORDER BY queued_at DESC LIMIT ?",args:[e,t]})).rows.map(n=>J(n))}async function kr(e){await i().execute({sql:"UPDATE workflow_runs SET status = 'running', started_at = COALESCE(started_at, datetime('now')) WHERE id = ?",args:[e]})}async function Xr(e,t,r){await i().execute({sql:"UPDATE workflow_runs SET status = ?, manifest_json = ?, completed_at = datetime('now') WHERE id = ?",args:[t,JSON.stringify(r),e]})}async function Mr(e,t,r){await i().execute({sql:"UPDATE workflow_runs SET status = 'failed', error_message = ?, manifest_json = ?, completed_at = datetime('now') WHERE id = ?",args:[t,r==null?null:JSON.stringify(r),e]})}function dt(e){return e==="html_report"?"text/html; charset=utf-8":e==="csv"?"text/csv; charset=utf-8":e==="json"?"application/json; charset=utf-8":"text/plain; charset=utf-8"}async function xe(e,t,r){await i().execute({sql:`
1098
1142
  INSERT INTO workflow_artifacts (id, run_id, user_id, kind, label, path, content_type, bytes, rows_count, content)
1099
1143
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1100
- `,args:[N(),e,t,r.kind,r.label,r.path,nt(r.kind),r.bytes??null,r.rows??null,r.content??null]})}async function yr(e,t,r){await s().execute({sql:"DELETE FROM workflow_artifacts WHERE run_id = ? AND user_id = ?",args:[e,t]});for(let n of r)await Ae(e,t,n);return we(e,t)}async function Cr(e,t,r){for(let n of r)await Ae(e,t,n);return we(e,t)}async function Ur(e,t){let n=(t==null?await s().execute({sql:"SELECT step_index, total_steps, step_state_json, step_log_json FROM workflow_runs WHERE id = ? LIMIT 1",args:[e]}):await s().execute({sql:"SELECT step_index, total_steps, step_state_json, step_log_json FROM workflow_runs WHERE id = ? AND user_id = ? LIMIT 1",args:[e,t]})).rows[0];return n?{stepIndex:n.step_index!=null?Number(n.step_index):0,totalSteps:n.total_steps!=null?Number(n.total_steps):null,state:n.step_state_json!=null?F(n.step_state_json):null,stepLog:Se(n.step_log_json)}:null}async function Dr(e,t){let r=[...t.appendLog,t.logEntry];await s().execute({sql:"UPDATE workflow_runs SET status = ?, step_index = ?, total_steps = ?, step_state_json = ?, step_log_json = ?, started_at = COALESCE(started_at, datetime('now')) WHERE id = ?",args:[t.status,t.stepIndex,t.totalSteps,JSON.stringify(t.state??null),JSON.stringify(r),e]})}async function we(e,t){return(await s().execute({sql:"SELECT * FROM workflow_artifacts WHERE run_id = ? AND user_id = ? ORDER BY created_at ASC",args:[e,t]})).rows.map(n=>Re(n))}async function kr(e,t){let r=await s().execute({sql:"SELECT * FROM workflow_artifacts WHERE id = ? AND user_id = ? LIMIT 1",args:[e,t]});return r.rows[0]?Re(r.rows[0]):null}async function vr(e){await s().execute({sql:`
1144
+ `,args:[N(),e,t,r.kind,r.label,r.path,dt(r.kind),r.bytes??null,r.rows??null,r.content??null]})}async function Fr(e,t,r){await i().execute({sql:"DELETE FROM workflow_artifacts WHERE run_id = ? AND user_id = ?",args:[e,t]});for(let n of r)await xe(e,t,n);return ye(e,t)}async function Pr(e,t,r){for(let n of r)await xe(e,t,n);return ye(e,t)}async function Hr(e,t){let n=(t==null?await i().execute({sql:"SELECT step_index, total_steps, step_state_json, step_log_json FROM workflow_runs WHERE id = ? LIMIT 1",args:[e]}):await i().execute({sql:"SELECT step_index, total_steps, step_state_json, step_log_json FROM workflow_runs WHERE id = ? AND user_id = ? LIMIT 1",args:[e,t]})).rows[0];return n?{stepIndex:n.step_index!=null?Number(n.step_index):0,totalSteps:n.total_steps!=null?Number(n.total_steps):null,state:n.step_state_json!=null?H(n.step_state_json):null,stepLog:he(n.step_log_json)}:null}async function qr(e,t){let r=[...t.appendLog,t.logEntry];await i().execute({sql:"UPDATE workflow_runs SET status = ?, step_index = ?, total_steps = ?, step_state_json = ?, step_log_json = ?, started_at = COALESCE(started_at, datetime('now')) WHERE id = ?",args:[t.status,t.stepIndex,t.totalSteps,JSON.stringify(t.state??null),JSON.stringify(r),e]})}async function ye(e,t){return(await i().execute({sql:"SELECT * FROM workflow_artifacts WHERE run_id = ? AND user_id = ? ORDER BY created_at ASC",args:[e,t]})).rows.map(n=>Ie(n))}async function Wr(e,t){let r=await i().execute({sql:"SELECT * FROM workflow_artifacts WHERE id = ? AND user_id = ? LIMIT 1",args:[e,t]});return r.rows[0]?Ie(r.rows[0]):null}async function jr(e){await i().execute({sql:`
1101
1145
  INSERT INTO workflow_webhook_deliveries (
1102
1146
  id, run_id, schedule_id, user_id, webhook_url, status, attempts, last_error, delivered_at
1103
1147
  )
1104
1148
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
1105
- `,args:[N(),e.runId,e.scheduleId??null,e.userId,e.webhookUrl,e.status,e.attempts,e.lastError??null,e.status==="delivered"?new Date().toISOString():null]})}async function Xr(){let e=await s().execute("SELECT COUNT(*) as n FROM users WHERE active = 1");return Number(e.rows[0]?.n??0)}async function Mr(e){let t=await s().execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND (status = 'pending' OR (status = 'running' AND started_at > datetime('now', '-10 minutes')))",args:[e]});return Number(t.rows[0]?.n??0)}async function Fr(){let e=s(),t=await e.execute(`
1149
+ `,args:[N(),e.runId,e.scheduleId??null,e.userId,e.webhookUrl,e.status,e.attempts,e.lastError??null,e.status==="delivered"?new Date().toISOString():null]})}async function Br(){let e=await i().execute("SELECT COUNT(*) as n FROM users WHERE active = 1");return Number(e.rows[0]?.n??0)}async function Gr(e){let t=await i().execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND (status = 'pending' OR (status = 'running' AND started_at > datetime('now', '-10 minutes')))",args:[e]});return Number(t.rows[0]?.n??0)}async function Yr(){let e=i(),t=await e.execute(`
1106
1150
  SELECT * FROM jobs
1107
1151
  WHERE status = 'pending'
1108
1152
  AND COALESCE(json_extract(options, '$.executionOwner'), 'cron') NOT IN ('direct', 'inngest')
1109
1153
  ORDER BY created_at
1110
1154
  LIMIT 1
1111
- `),r=t.rows[0]?S(t.rows[0]):void 0;return r?(await e.execute({sql:"UPDATE jobs SET status = 'running', started_at = datetime('now') WHERE id = ? AND status = 'pending'",args:[r.id]})).rowsAffected===0?void 0:{...r,status:"running"}:void 0}var $=45e3;async function Pr(e){let t=s(),r=await G(e);if(!r||r.options.executionOwner!=="direct"||r.options.serpOnly===!0)return;let n=Math.max(0,Number(r.options.paaRecoveryCount??0));if(r.status!=="running"){if(r.status==="pending"){let i=N(),a=new Date().toISOString(),u=new Date(Date.now()+$).toISOString();return(await t.execute({sql:`UPDATE jobs
1155
+ `),r=t.rows[0]?R(t.rows[0]):void 0;return r?(await e.execute({sql:"UPDATE jobs SET status = 'running', started_at = datetime('now') WHERE id = ? AND status = 'pending'",args:[r.id]})).rowsAffected===0?void 0:{...r,status:"running"}:void 0}var V=45e3;async function Kr(e){let t=i(),r=await K(e);if(!r||r.options.executionOwner!=="direct"||r.options.serpOnly===!0)return;let n=Math.max(0,Number(r.options.paaRecoveryCount??0));if(r.status!=="running"){if(r.status==="pending"){let s=N(),a=new Date().toISOString(),_=new Date(Date.now()+V).toISOString();return(await t.execute({sql:`UPDATE jobs
1112
1156
  SET status = 'running', started_at = datetime('now'), error = NULL,
1113
1157
  options = json_set(options,
1114
1158
  '$.paaLeaseToken', ?,
1115
1159
  '$.paaLeaseExpiresAt', ?,
1116
1160
  '$.paaLastDispatchAt', ?)
1117
- WHERE id = ? AND status = 'pending'`,args:[i,u,a,e]})).rowsAffected===0?void 0:{job:{...r,status:"running",started_at:a,options:{...r.options,paaLeaseToken:i,paaLeaseExpiresAt:u,paaLastDispatchAt:a}},leaseToken:i,recoveryCount:n}}return{job:r,leaseToken:null,recoveryCount:n}}}async function Hr(e,t){return(await s().execute({sql:"UPDATE jobs SET result = ? WHERE id = ? AND status = 'running'",args:[JSON.stringify(t),e]})).rowsAffected===1}async function Wr(e,t,r){let n=new Date(Date.now()+$).toISOString();return(await s().execute({sql:`UPDATE jobs SET result = ?, options = json_set(options, '$.paaLeaseExpiresAt', ?)
1118
- WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,args:[JSON.stringify(r),n,e,t]})).rowsAffected===1}async function qr(e,t){let r=new Date(Date.now()+$).toISOString();return(await s().execute({sql:`UPDATE jobs SET options = json_set(options, '$.paaLeaseExpiresAt', ?)
1119
- WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,args:[r,e,t]})).rowsAffected===1}async function jr(e,t,r){return(await s().execute({sql:`UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL,
1161
+ WHERE id = ? AND status = 'pending'`,args:[s,_,a,e]})).rowsAffected===0?void 0:{job:{...r,status:"running",started_at:a,options:{...r.options,paaLeaseToken:s,paaLeaseExpiresAt:_,paaLastDispatchAt:a}},leaseToken:s,recoveryCount:n}}return{job:r,leaseToken:null,recoveryCount:n}}}async function $r(e,t){return(await i().execute({sql:"UPDATE jobs SET result = ? WHERE id = ? AND status = 'running'",args:[JSON.stringify(t),e]})).rowsAffected===1}async function Jr(e,t,r){let n=new Date(Date.now()+V).toISOString();return(await i().execute({sql:`UPDATE jobs SET result = ?, options = json_set(options, '$.paaLeaseExpiresAt', ?)
1162
+ WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,args:[JSON.stringify(r),n,e,t]})).rowsAffected===1}async function Vr(e,t){let r=new Date(Date.now()+V).toISOString();return(await i().execute({sql:`UPDATE jobs SET options = json_set(options, '$.paaLeaseExpiresAt', ?)
1163
+ WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,args:[r,e,t]})).rowsAffected===1}async function zr(e,t,r){return(await i().execute({sql:`UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL,
1120
1164
  completed_at = datetime('now'),
1121
1165
  options = json_set(options, '$.paaLeaseExpiresAt', NULL)
1122
- WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,args:[JSON.stringify(r),e,t]})).rowsAffected===1}async function Br(e,t,r,n){return(await s().execute({sql:`UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now'),
1166
+ WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,args:[JSON.stringify(r),e,t]})).rowsAffected===1}async function Qr(e,t,r,n){return(await i().execute({sql:`UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now'),
1123
1167
  options = json_set(options, '$.paaLeaseExpiresAt', NULL)
1124
- WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,args:[r,w(n),e,t]})).rowsAffected===1}async function Gr(e,t){let r=new Date().toISOString();return(await s().execute({sql:`UPDATE jobs SET status = 'pending', started_at = NULL,
1168
+ WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,args:[r,O(n),e,t]})).rowsAffected===1}async function Zr(e,t){let r=new Date().toISOString();return(await i().execute({sql:`UPDATE jobs SET status = 'pending', started_at = NULL,
1125
1169
  result = CASE WHEN json_valid(result) THEN json_set(result,
1126
1170
  '$.progress.lifecycle.discoveryStatus', 'interrupted',
1127
1171
  '$.progress.lifecycle.completionReason', 'The previous worker lease expired; the same job is recovering automatically.',
@@ -1137,28 +1181,29 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1137
1181
  datetime(json_extract(options, '$.paaLeaseExpiresAt')) <= datetime('now')
1138
1182
  OR (json_extract(options, '$.paaLeaseExpiresAt') IS NULL AND started_at <= datetime('now', '-15 minutes'))
1139
1183
  )
1140
- AND COALESCE(json_extract(options, '$.paaRecoveryCount'), 0) < ?`,args:[r,e,Math.max(0,Math.trunc(t))]})).rowsAffected===1}async function Yr(e,t){return(await s().execute({sql:`UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL, completed_at = datetime('now')
1184
+ AND COALESCE(json_extract(options, '$.paaRecoveryCount'), 0) < ?`,args:[r,e,Math.max(0,Math.trunc(t))]})).rowsAffected===1}async function en(e,t){return(await i().execute({sql:`UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL, completed_at = datetime('now')
1141
1185
  WHERE id = ? AND status = 'running'
1142
1186
  AND (
1143
1187
  datetime(json_extract(options, '$.paaLeaseExpiresAt')) <= datetime('now')
1144
1188
  OR (json_extract(options, '$.paaLeaseExpiresAt') IS NULL AND started_at <= datetime('now', '-15 minutes'))
1145
- )`,args:[JSON.stringify(t),e]})).rowsAffected===1}async function Kr(e,t,r){return(await s().execute({sql:`UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now')
1189
+ )`,args:[JSON.stringify(t),e]})).rowsAffected===1}async function tn(e,t,r){return(await i().execute({sql:`UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now')
1146
1190
  WHERE id = ? AND status = 'running'
1147
1191
  AND (
1148
1192
  datetime(json_extract(options, '$.paaLeaseExpiresAt')) <= datetime('now')
1149
1193
  OR (json_extract(options, '$.paaLeaseExpiresAt') IS NULL AND started_at <= datetime('now', '-15 minutes'))
1150
- )`,args:[t,w(r),e]})).rowsAffected===1}async function $r(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await s().execute({sql:`SELECT * FROM jobs
1194
+ )`,args:[t,O(r),e]})).rowsAffected===1}async function rn(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await i().execute({sql:`SELECT * FROM jobs
1151
1195
  WHERE status IN ('done', 'failed', 'cancelled')
1152
1196
  AND json_extract(options, '$.executionOwner') IN ('direct', 'inngest')
1153
1197
  AND json_extract(options, '$.billingDebitKey') IS NOT NULL
1198
+ AND CAST(json_extract(options, '$.billingHoldMc') AS INTEGER) > 0
1154
1199
  AND json_extract(options, '$.billingSettledAt') IS NULL
1155
1200
  ORDER BY completed_at DESC
1156
- LIMIT ?`,args:[t]})).rows.map(n=>O(S(n)))}async function Jr(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await s().execute({sql:`SELECT * FROM jobs
1201
+ LIMIT ?`,args:[t]})).rows.map(n=>h(R(n)))}async function nn(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await i().execute({sql:`SELECT * FROM jobs
1157
1202
  WHERE status = 'running'
1158
1203
  AND started_at <= datetime('now', '-15 minutes')
1159
1204
  AND json_extract(options, '$.executionOwner') IN ('direct', 'inngest')
1160
1205
  ORDER BY started_at
1161
- LIMIT ?`,args:[t]})).rows.map(n=>O(S(n)))}async function zr(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await s().execute({sql:`SELECT * FROM jobs
1206
+ LIMIT ?`,args:[t]})).rows.map(n=>h(R(n)))}async function sn(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await i().execute({sql:`SELECT * FROM jobs
1162
1207
  WHERE json_extract(options, '$.executionOwner') = 'direct'
1163
1208
  AND json_extract(options, '$.serpOnly') IS NOT 1
1164
1209
  AND (
@@ -1171,14 +1216,14 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1171
1216
  AND datetime(COALESCE(json_extract(options, '$.paaLastDispatchAt'), '1970-01-01')) <= datetime('now', '-30 seconds'))
1172
1217
  )
1173
1218
  ORDER BY COALESCE(started_at, created_at)
1174
- LIMIT ?`,args:[t]})).rows.map(n=>O(S(n)))}async function Vr(e,t,r=new Date().toISOString()){if(!Number.isSafeInteger(t)||t<0)throw new Error("job billed amount must be a non-negative integer");return(await s().execute({sql:`UPDATE jobs
1219
+ LIMIT ?`,args:[t]})).rows.map(n=>h(R(n)))}async function an(e,t,r=new Date().toISOString()){if(!Number.isSafeInteger(t)||t<0)throw new Error("job billed amount must be a non-negative integer");return(await i().execute({sql:`UPDATE jobs
1175
1220
  SET options = json_set(options, '$.billingSettledAt', ?, '$.billedMc', ?)
1176
- WHERE id = ?`,args:[r,t,e]})).rowsAffected===1}async function Qr(e,t){await s().execute({sql:"UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL, completed_at = datetime('now') WHERE id = ?",args:[JSON.stringify(t),e]})}async function Zr(e,t){return(await s().execute({sql:`UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL, completed_at = datetime('now')
1177
- WHERE id = ? AND status = 'running'`,args:[JSON.stringify(t),e]})).rowsAffected===1}async function en(e,t,r){await s().execute({sql:"UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now') WHERE id = ?",args:[t,w(r),e]})}async function tn(e,t,r){return(await s().execute({sql:`UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now')
1178
- WHERE id = ? AND status = 'running'`,args:[t,w(r),e]})).rowsAffected===1}async function rn(e,t,r){await s().execute({sql:"UPDATE jobs SET status = 'cancelled', error = ?, public_error_json = ?, completed_at = datetime('now') WHERE id = ?",args:[t,w(r),e]})}function J(e){return{id:String(e.id),user_id:Number(e.user_id),status:String(e.status),entity_name:String(e.entity_name),entity_type:String(e.entity_type),url:e.url!=null?String(e.url):null,request:String(e.request),result:e.result!=null?String(e.result):null,error:e.error!=null?String(e.error):null,created_at:String(e.created_at),updated_at:String(e.updated_at)}}function st(e){return{id:Number(e.id),job_id:String(e.job_id),phase:String(e.phase),output:String(e.output),created_at:String(e.created_at)}}async function nn(e,t,r,n,i,a){await s().execute({sql:"INSERT INTO kpo_jobs (id, user_id, status, entity_name, entity_type, url, request) VALUES (?, ?, 'pending', ?, ?, ?, ?)",args:[e,t,r,n,a??null,JSON.stringify(i)]})}async function sn(){let t=await s().execute("UPDATE kpo_jobs SET status='running', updated_at=datetime('now') WHERE id = (SELECT id FROM kpo_jobs WHERE status='pending' ORDER BY created_at ASC LIMIT 1) RETURNING *");return t.rowsAffected===0?null:t.rows[0]?J(t.rows[0]):null}async function an(e){let t=await s().execute({sql:"SELECT * FROM kpo_jobs WHERE id = ?",args:[e]});return t.rows[0]?J(t.rows[0]):null}async function on(e,t){await s().execute({sql:"UPDATE kpo_jobs SET status = ?, updated_at = datetime('now') WHERE id = ?",args:[t,e]})}async function un(e,t){await s().execute({sql:"UPDATE kpo_jobs SET status = 'done', result = ?, updated_at = datetime('now') WHERE id = ?",args:[JSON.stringify(t),e]})}async function _n(e,t){await s().execute({sql:"UPDATE kpo_jobs SET status = 'failed', error = ?, updated_at = datetime('now') WHERE id = ?",args:[t,e]})}async function cn(e,t,r){await s().execute({sql:"INSERT INTO kpo_phase_log (job_id, phase, output) VALUES (?, ?, ?)",args:[e,t,JSON.stringify(r)]})}async function dn(e){return(await s().execute({sql:"SELECT * FROM kpo_phase_log WHERE job_id = ? ORDER BY created_at ASC",args:[e]})).rows.map(r=>st(r))}async function ln(e){return(e!=null?await s().execute({sql:"SELECT * FROM kpo_jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50",args:[e]}):await s().execute("SELECT * FROM kpo_jobs ORDER BY created_at DESC LIMIT 50")).rows.map(r=>J(r))}async function En(e){let t=await s().execute({sql:"SELECT * FROM users WHERE stripe_customer_id = ? AND active = 1",args:[e]});return t.rows[0]?b(t.rows[0]):void 0}async function Tn(e,t){await s().execute({sql:"UPDATE users SET stripe_customer_id = ? WHERE id = ?",args:[t,e]})}async function pn(e,t){if(!Number.isSafeInteger(t)||t<0)throw new Error("extra concurrency slots must be a non-negative safe integer");await it(e,Math.ceil(t/2))}async function it(e,t){if(!Number.isSafeInteger(t)||t<0)throw new Error("concurrency pack quantity must be a non-negative safe integer");await s().execute({sql:"UPDATE users SET concurrency_pack_quantity = ?, extra_concurrency_slots = ? WHERE id = ?",args:[t,t*2,e]})}async function mn(e,t){await s().execute({sql:"UPDATE users SET concurrency_stripe_sub_id = ? WHERE id = ?",args:[t,e]})}async function Nn(e,t,r,n){await s().execute({sql:"UPDATE users SET subscription_tier = ?, subscription_concurrency = ?, subscription_id = ? WHERE id = ?",args:[t,Math.max(0,Math.round(r)),n,e]})}async function gn(e){if(!e.invoiceId||e.invoiceId.length>500)throw new Error("invoice id is required and must be bounded");if(!Number.isSafeInteger(e.creditsMc)||e.creditsMc<=0)throw new Error("subscription credit amount must be a positive integer");await R(e.userId);let t=s(),r=e.neverExpires?"9999-12-31 23:59:59":null,n=await t.batch([{sql:`INSERT OR IGNORE INTO ledger (user_id, amount_mc, operation, description, stripe_pi)
1221
+ WHERE id = ?`,args:[r,t,e]})).rowsAffected===1}async function on(e,t){await i().execute({sql:"UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL, completed_at = datetime('now') WHERE id = ?",args:[JSON.stringify(t),e]})}async function _n(e,t){return(await i().execute({sql:`UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL, completed_at = datetime('now')
1222
+ WHERE id = ? AND status = 'running'`,args:[JSON.stringify(t),e]})).rowsAffected===1}async function un(e,t,r){await i().execute({sql:"UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now') WHERE id = ?",args:[t,O(r),e]})}async function cn(e,t,r){return(await i().execute({sql:`UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now')
1223
+ WHERE id = ? AND status = 'running'`,args:[t,O(r),e]})).rowsAffected===1}async function dn(e,t,r){await i().execute({sql:"UPDATE jobs SET status = 'cancelled', error = ?, public_error_json = ?, completed_at = datetime('now') WHERE id = ?",args:[t,O(r),e]})}function z(e){return{id:String(e.id),user_id:Number(e.user_id),status:String(e.status),entity_name:String(e.entity_name),entity_type:String(e.entity_type),url:e.url!=null?String(e.url):null,request:String(e.request),result:e.result!=null?String(e.result):null,error:e.error!=null?String(e.error):null,created_at:String(e.created_at),updated_at:String(e.updated_at)}}function lt(e){return{id:Number(e.id),job_id:String(e.job_id),phase:String(e.phase),output:String(e.output),created_at:String(e.created_at)}}async function ln(e,t,r,n,s,a){await i().execute({sql:"INSERT INTO kpo_jobs (id, user_id, status, entity_name, entity_type, url, request) VALUES (?, ?, 'pending', ?, ?, ?, ?)",args:[e,t,r,n,a??null,JSON.stringify(s)]})}async function En(){let t=await i().execute("UPDATE kpo_jobs SET status='running', updated_at=datetime('now') WHERE id = (SELECT id FROM kpo_jobs WHERE status='pending' ORDER BY created_at ASC LIMIT 1) RETURNING *");return t.rowsAffected===0?null:t.rows[0]?z(t.rows[0]):null}async function Tn(e){let t=await i().execute({sql:"SELECT * FROM kpo_jobs WHERE id = ?",args:[e]});return t.rows[0]?z(t.rows[0]):null}async function pn(e,t){await i().execute({sql:"UPDATE kpo_jobs SET status = ?, updated_at = datetime('now') WHERE id = ?",args:[t,e]})}async function mn(e,t){await i().execute({sql:"UPDATE kpo_jobs SET status = 'done', result = ?, updated_at = datetime('now') WHERE id = ?",args:[JSON.stringify(t),e]})}async function Nn(e,t){await i().execute({sql:"UPDATE kpo_jobs SET status = 'failed', error = ?, updated_at = datetime('now') WHERE id = ?",args:[t,e]})}async function gn(e,t,r){await i().execute({sql:"INSERT INTO kpo_phase_log (job_id, phase, output) VALUES (?, ?, ?)",args:[e,t,JSON.stringify(r)]})}async function Ln(e){return(await i().execute({sql:"SELECT * FROM kpo_phase_log WHERE job_id = ? ORDER BY created_at ASC",args:[e]})).rows.map(r=>lt(r))}async function bn(e){return(e!=null?await i().execute({sql:"SELECT * FROM kpo_jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50",args:[e]}):await i().execute("SELECT * FROM kpo_jobs ORDER BY created_at DESC LIMIT 50")).rows.map(r=>z(r))}async function Sn(e){let t=await i().execute({sql:"SELECT * FROM users WHERE stripe_customer_id = ? AND active = 1",args:[e]});return t.rows[0]?S(t.rows[0]):void 0}async function Rn(e,t){await i().execute({sql:"UPDATE users SET stripe_customer_id = ? WHERE id = ?",args:[t,e]})}async function An(e,t){if(!Number.isSafeInteger(t)||t<0)throw new Error("extra concurrency slots must be a non-negative safe integer");await Et(e,Math.ceil(t/2))}async function Et(e,t){if(!Number.isSafeInteger(t)||t<0)throw new Error("concurrency pack quantity must be a non-negative safe integer");await i().execute({sql:"UPDATE users SET concurrency_pack_quantity = ?, extra_concurrency_slots = ? WHERE id = ?",args:[t,t*2,e]})}async function wn(e,t){await i().execute({sql:"UPDATE users SET concurrency_stripe_sub_id = ? WHERE id = ?",args:[t,e]})}async function On(e,t,r,n){await i().execute({sql:"UPDATE users SET subscription_tier = ?, subscription_concurrency = ?, subscription_id = ? WHERE id = ?",args:[t,Math.max(0,Math.round(r)),n,e]})}async function fn(e){if(!e.invoiceId||e.invoiceId.length>500)throw new Error("invoice id is required and must be bounded");if(!Number.isSafeInteger(e.creditsMc)||e.creditsMc<=0)throw new Error("subscription credit amount must be a positive integer");await A(e.userId);let t=i(),r=e.neverExpires?"9999-12-31 23:59:59":null,n=await t.batch([{sql:`INSERT OR IGNORE INTO ledger (user_id, amount_mc, operation, description, stripe_pi)
1179
1224
  VALUES (?, ?, 'subscription', ?, ?)`,args:[e.userId,e.creditsMc,e.description,e.invoiceId]},{sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires)
1180
1225
  SELECT ?, ?, ?, 'subscription', ?, COALESCE(?, datetime('now', ?)), ?
1181
- WHERE changes() = 1`,args:[e.userId,e.creditsMc,e.creditsMc,e.invoiceId,r,C,e.neverExpires?1:0]},{sql:"UPDATE users SET balance_mc = balance_mc + ? WHERE id = ? AND changes() = 1",args:[e.creditsMc,e.userId]},{sql:`UPDATE users
1226
+ WHERE changes() = 1`,args:[e.userId,e.creditsMc,e.creditsMc,e.invoiceId,r,D,e.neverExpires?1:0]},{sql:"UPDATE users SET balance_mc = balance_mc + ? WHERE id = ? AND changes() = 1",args:[e.creditsMc,e.userId]},{sql:`UPDATE users
1182
1227
  SET subscription_tier = ?, subscription_concurrency = ?, subscription_id = ?,
1183
1228
  memory_plan = CASE WHEN ? IS NOT NULL THEN ? ELSE memory_plan END,
1184
1229
  memory_subscription_id = CASE WHEN ? IS NOT NULL THEN NULL ELSE memory_subscription_id END
@@ -1188,7 +1233,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1188
1233
  WHERE stripe_pi = ? AND user_id = ? AND amount_mc = ? AND operation = 'subscription'
1189
1234
  )`,args:[e.tier,Math.max(0,Math.round(e.concurrency)),e.subscriptionId,e.includedMemoryPlan,e.includedMemoryPlan,e.includedMemoryPlan,e.userId,e.invoiceId,e.userId,e.creditsMc]}],"write"),a=(await t.execute({sql:`SELECT l.user_id, l.amount_mc, l.operation, u.balance_mc
1190
1235
  FROM ledger l JOIN users u ON u.id = l.user_id
1191
- WHERE l.stripe_pi = ? LIMIT 1`,args:[e.invoiceId]})).rows[0];if(!a||Number(a.user_id)!==e.userId||Number(a.amount_mc)!==e.creditsMc||String(a.operation)!=="subscription")throw new Error("invoice idempotency key conflicts with an existing grant");return{granted:n[0]?.rowsAffected===1,balance_mc:Number(a.balance_mc??0)}}function at(e){return{user_id:Number(e.user_id),stripe_subscription_id:e.stripe_subscription_id!=null?String(e.stripe_subscription_id):null,stripe_subscription_item_id:e.stripe_subscription_item_id!=null?String(e.stripe_subscription_item_id):null,price_id:e.price_id!=null?String(e.price_id):null,quantity:Math.max(0,Number(e.quantity??0)),status:["pending","synced","blocked","error"].includes(String(e.status))?String(e.status):"error",last_error_code:e.last_error_code!=null?String(e.last_error_code):null,checked_at:String(e.checked_at),synced_at:e.synced_at!=null?String(e.synced_at):null,updated_at:String(e.updated_at)}}async function ot(e){let r=(await s().execute({sql:"SELECT * FROM connected_account_billing WHERE user_id = ? LIMIT 1",args:[e]})).rows[0];return r?at(r):null}async function Ln(e){let t=Math.max(0,Math.round(e.quantity));await s().execute({sql:`INSERT INTO connected_account_billing
1236
+ WHERE l.stripe_pi = ? LIMIT 1`,args:[e.invoiceId]})).rows[0];if(!a||Number(a.user_id)!==e.userId||Number(a.amount_mc)!==e.creditsMc||String(a.operation)!=="subscription")throw new Error("invoice idempotency key conflicts with an existing grant");return{granted:n[0]?.rowsAffected===1,balance_mc:Number(a.balance_mc??0)}}function Tt(e){return{user_id:Number(e.user_id),stripe_subscription_id:e.stripe_subscription_id!=null?String(e.stripe_subscription_id):null,stripe_subscription_item_id:e.stripe_subscription_item_id!=null?String(e.stripe_subscription_item_id):null,price_id:e.price_id!=null?String(e.price_id):null,quantity:Math.max(0,Number(e.quantity??0)),status:["pending","synced","blocked","error"].includes(String(e.status))?String(e.status):"error",last_error_code:e.last_error_code!=null?String(e.last_error_code):null,checked_at:String(e.checked_at),synced_at:e.synced_at!=null?String(e.synced_at):null,updated_at:String(e.updated_at)}}async function pt(e){let r=(await i().execute({sql:"SELECT * FROM connected_account_billing WHERE user_id = ? LIMIT 1",args:[e]})).rows[0];return r?Tt(r):null}async function hn(e){let t=Math.max(0,Math.round(e.quantity));await i().execute({sql:`INSERT INTO connected_account_billing
1192
1237
  (user_id, stripe_subscription_id, stripe_subscription_item_id, price_id, quantity, status, last_error_code, checked_at, synced_at, updated_at)
1193
1238
  VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'), CASE WHEN ? THEN datetime('now') ELSE NULL END, datetime('now'))
1194
1239
  ON CONFLICT(user_id) DO UPDATE SET
@@ -1200,14 +1245,14 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1200
1245
  last_error_code = excluded.last_error_code,
1201
1246
  checked_at = datetime('now'),
1202
1247
  synced_at = CASE WHEN ? THEN datetime('now') ELSE connected_account_billing.synced_at END,
1203
- updated_at = datetime('now')`,args:[e.userId,e.stripeSubscriptionId,e.stripeSubscriptionItemId,e.priceId,t,e.status,e.lastErrorCode??null,e.synced===!0?1:0,e.synced===!0?1:0]});let r=await ot(e.userId);if(!r)throw new Error("connected account billing state was not persisted");return r}async function bn(e=60,t=20){let r=`-${Math.max(1,Math.round(e))} minutes`;return(await s().execute({sql:`SELECT u.*
1248
+ updated_at = datetime('now')`,args:[e.userId,e.stripeSubscriptionId,e.stripeSubscriptionItemId,e.priceId,t,e.status,e.lastErrorCode??null,e.synced===!0?1:0,e.synced===!0?1:0]});let r=await pt(e.userId);if(!r)throw new Error("connected account billing state was not persisted");return r}async function In(e=60,t=20){let r=`-${Math.max(1,Math.round(e))} minutes`;return(await i().execute({sql:`SELECT u.*
1204
1249
  FROM users u
1205
1250
  LEFT JOIN connected_account_billing b ON b.user_id = u.id
1206
1251
  WHERE u.active = 1
1207
1252
  AND u.subscription_id IS NOT NULL
1208
1253
  AND (b.checked_at IS NULL OR b.checked_at <= datetime('now', ?))
1209
1254
  ORDER BY COALESCE(b.checked_at, u.created_at) ASC
1210
- LIMIT ?`,args:[r,Math.max(1,Math.min(100,Math.round(t)))]})).rows.map(i=>b(i))}async function Sn(e,t,r){await s().execute({sql:"UPDATE users SET memory_plan = ?, memory_subscription_id = ? WHERE id = ?",args:[t,r,e]})}async function Rn(e){let r=(await s().execute({sql:"SELECT memory_plan, memory_subscription_id FROM users WHERE id = ?",args:[e]})).rows[0];return{plan:r?.memory_plan!=null?String(r.memory_plan):"free",memory_subscription_id:r?.memory_subscription_id!=null?String(r.memory_subscription_id):null}}async function An(e){let r=(await s().execute({sql:"SELECT memory_provisioned FROM users WHERE id = ?",args:[e]})).rows[0];return Number(r?.memory_provisioned??0)===1}async function wn(e,t){await s().execute({sql:"UPDATE users SET memory_provisioned = ? WHERE id = ?",args:[t?1:0,e]})}async function On(e){let t=await s().execute({sql:"SELECT * FROM users WHERE memory_subscription_id = ? AND active = 1",args:[e]});return t.rows[0]?b(t.rows[0]):void 0}var C="+3 months";async function R(e){return(await s().execute({sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, expires_at)
1255
+ LIMIT ?`,args:[r,Math.max(1,Math.min(100,Math.round(t)))]})).rows.map(s=>S(s))}async function xn(e,t,r){await i().execute({sql:"UPDATE users SET memory_plan = ?, memory_subscription_id = ? WHERE id = ?",args:[t,r,e]})}async function yn(e){let r=(await i().execute({sql:"SELECT memory_plan, memory_subscription_id FROM users WHERE id = ?",args:[e]})).rows[0];return{plan:r?.memory_plan!=null?String(r.memory_plan):"free",memory_subscription_id:r?.memory_subscription_id!=null?String(r.memory_subscription_id):null}}async function Cn(e){let r=(await i().execute({sql:"SELECT memory_provisioned FROM users WHERE id = ?",args:[e]})).rows[0];return Number(r?.memory_provisioned??0)===1}async function Un(e,t){await i().execute({sql:"UPDATE users SET memory_provisioned = ? WHERE id = ?",args:[t?1:0,e]})}async function Dn(e){let t=await i().execute({sql:"SELECT * FROM users WHERE memory_subscription_id = ? AND active = 1",args:[e]});return t.rows[0]?S(t.rows[0]):void 0}var D="+3 months";async function A(e){return(await i().execute({sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, expires_at)
1211
1256
  SELECT ?, legacy.balance_mc, legacy.balance_mc, 'migration', datetime('now', ?)
1212
1257
  FROM (
1213
1258
  SELECT COALESCE(SUM(amount_mc), 0) AS balance_mc
@@ -1221,7 +1266,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1221
1266
  )
1222
1267
  AND NOT EXISTS (
1223
1268
  SELECT 1 FROM credit_lots WHERE user_id = ?
1224
- )`,args:[e,C,e,e,D,e]})).rowsAffected}async function fn(){let e=s(),t=await e.execute({sql:`SELECT id
1269
+ )`,args:[e,D,e,e,k,e]})).rowsAffected}async function vn(){let e=i(),t=await e.execute({sql:`SELECT id
1225
1270
  FROM credit_lots
1226
1271
  WHERE remaining_mc > 0
1227
1272
  AND never_expires = 0
@@ -1241,24 +1286,24 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1241
1286
  )`,args:[d,d,E]}),n.push({sql:`INSERT INTO ledger (user_id, amount_mc, operation, description)
1242
1287
  SELECT user_id, -amount_mc, 'credit_expired', 'credits expired'
1243
1288
  FROM credit_lot_expirations
1244
- WHERE lot_id = ? AND claim_token = ?`,args:[d,E]})}let i=await e.batch(n,"write"),a=r.filter(c=>i[c.insertResultIndex]?.rowsAffected===1).map(c=>c.token);if(a.length===0)return{expired_lots:0,expired_mc:0};let u=a.map(()=>"?").join(", "),_=await e.execute({sql:`SELECT user_id, amount_mc
1289
+ WHERE lot_id = ? AND claim_token = ?`,args:[d,E]})}let s=await e.batch(n,"write"),a=r.filter(c=>s[c.insertResultIndex]?.rowsAffected===1).map(c=>c.token);if(a.length===0)return{expired_lots:0,expired_mc:0};let _=a.map(()=>"?").join(", "),u=await e.execute({sql:`SELECT user_id, amount_mc
1245
1290
  FROM credit_lot_expirations
1246
- WHERE claim_token IN (${u})`,args:a}),o=new Set(_.rows.map(c=>Number(c.user_id)));for(let c of o)await Oe(c);return{expired_lots:_.rows.length,expired_mc:_.rows.reduce((c,d)=>c+Number(d.amount_mc),0)}}async function hn(){let e=s(),t=await e.execute({sql:`SELECT DISTINCT u.id AS user_id
1291
+ WHERE claim_token IN (${_})`,args:a}),o=new Set(u.rows.map(c=>Number(c.user_id)));for(let c of o)await Ce(c);return{expired_lots:u.rows.length,expired_mc:u.rows.reduce((c,d)=>c+Number(d.amount_mc),0)}}async function kn(){let e=i(),t=await e.execute({sql:`SELECT DISTINCT u.id AS user_id
1247
1292
  FROM users u
1248
1293
  JOIN ledger l ON l.user_id = u.id
1249
1294
  WHERE l.created_at < ?
1250
- AND NOT EXISTS (SELECT 1 FROM credit_lots WHERE user_id = u.id)`,args:[D]}),r=0,n=0;for(let i of t.rows){let a=Number(i.user_id);if(await R(a)===0)continue;let _=await e.execute({sql:`SELECT amount_mc FROM credit_lots
1295
+ AND NOT EXISTS (SELECT 1 FROM credit_lots WHERE user_id = u.id)`,args:[k]}),r=0,n=0;for(let s of t.rows){let a=Number(s.user_id);if(await A(a)===0)continue;let u=await e.execute({sql:`SELECT amount_mc FROM credit_lots
1251
1296
  WHERE user_id = ? AND source = 'migration'
1252
- ORDER BY id DESC LIMIT 1`,args:[a]}),o=Number(_.rows[0]?.amount_mc??0);await Oe(a),r+=1,n+=o}return{migrated:r,total_mc:n}}async function xn(e,t,r,n,i,a){let u=s();await R(e);let _=a?.neverExpires;if(_===void 0&&t>0){let E=await u.execute({sql:"SELECT subscription_tier FROM users WHERE id = ? LIMIT 1",args:[e]});_=String(E.rows[0]?.subscription_tier??"").startsWith("sonic")}let o=_?"9999-12-31 23:59:59":null;if(i){let E=[{sql:"INSERT OR IGNORE INTO ledger (user_id, amount_mc, operation, description, stripe_pi) VALUES (?, ?, ?, ?, ?)",args:[e,t,r,n??null,i]}];t>0&&E.push({sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires)
1297
+ ORDER BY id DESC LIMIT 1`,args:[a]}),o=Number(u.rows[0]?.amount_mc??0);await Ce(a),r+=1,n+=o}return{migrated:r,total_mc:n}}async function Xn(e,t,r,n,s,a){let _=i();await A(e);let u=a?.neverExpires;if(u===void 0&&t>0){let E=await _.execute({sql:"SELECT subscription_tier FROM users WHERE id = ? LIMIT 1",args:[e]});u=String(E.rows[0]?.subscription_tier??"").startsWith("sonic")}let o=u?"9999-12-31 23:59:59":null;if(s){let E=[{sql:"INSERT OR IGNORE INTO ledger (user_id, amount_mc, operation, description, stripe_pi) VALUES (?, ?, ?, ?, ?)",args:[e,t,r,n??null,s]}];t>0&&E.push({sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires)
1253
1298
  SELECT ?, ?, ?, ?, ?, COALESCE(?, datetime('now', ?)), ?
1254
- WHERE changes() = 1`,args:[e,t,t,r,i,o,C,_?1:0]}),E.push({sql:"UPDATE users SET balance_mc = balance_mc + ? WHERE id = ? AND changes() = 1",args:[t,e]}),await u.batch(E,"write");let l=await u.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return Number(l.rows[0]?.balance_mc??0)}let c=[];t>0&&c.push({sql:"INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires) VALUES (?, ?, ?, ?, ?, COALESCE(?, datetime('now', ?)), ?)",args:[e,t,t,r,null,o,C,_?1:0]}),c.push({sql:"UPDATE users SET balance_mc = balance_mc + ? WHERE id = ?",args:[t,e]}),c.push({sql:"INSERT INTO ledger (user_id, amount_mc, operation, description, stripe_pi) VALUES (?, ?, ?, ?, ?)",args:[e,t,r,n??null,null]}),await u.batch(c,"write");let d=await u.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return Number(d.rows[0]?.balance_mc??0)}async function In(e,t,r,n,i,a){if(!Number.isSafeInteger(t)||t<=0)throw new Error("idempotent credit amount must be a positive integer");if(!i||i.length>500)throw new Error("idempotent credit key is required and must be bounded");let u=s();await R(e);let _=a?.neverExpires;if(_===void 0){let m=await u.execute({sql:"SELECT subscription_tier FROM users WHERE id = ? LIMIT 1",args:[e]});_=String(m.rows[0]?.subscription_tier??"").startsWith("sonic")}let o=_?"9999-12-31 23:59:59":null,c=async()=>{let m=await u.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return Number(m.rows[0]?.balance_mc??0)},d;try{d=await u.batch([{sql:"INSERT OR IGNORE INTO billing_credits (idempotency_key, user_id, amount_mc, operation, description, status) VALUES (?, ?, ?, ?, ?, 'claimed')",args:[i,e,t,r,n]},{sql:"UPDATE billing_credits SET status = 'applying' WHERE idempotency_key = ? AND user_id = ? AND amount_mc = ? AND operation = ? AND description = ? AND status = 'claimed'",args:[i,e,t,r,n]},{sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires)
1299
+ WHERE changes() = 1`,args:[e,t,t,r,s,o,D,u?1:0]}),E.push({sql:"UPDATE users SET balance_mc = balance_mc + ? WHERE id = ? AND changes() = 1",args:[t,e]}),await _.batch(E,"write");let l=await _.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return Number(l.rows[0]?.balance_mc??0)}let c=[];t>0&&c.push({sql:"INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires) VALUES (?, ?, ?, ?, ?, COALESCE(?, datetime('now', ?)), ?)",args:[e,t,t,r,null,o,D,u?1:0]}),c.push({sql:"UPDATE users SET balance_mc = balance_mc + ? WHERE id = ?",args:[t,e]}),c.push({sql:"INSERT INTO ledger (user_id, amount_mc, operation, description, stripe_pi) VALUES (?, ?, ?, ?, ?)",args:[e,t,r,n??null,null]}),await _.batch(c,"write");let d=await _.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return Number(d.rows[0]?.balance_mc??0)}async function Mn(e,t,r,n,s,a){if(!Number.isSafeInteger(t)||t<=0)throw new Error("idempotent credit amount must be a positive integer");if(!s||s.length>500)throw new Error("idempotent credit key is required and must be bounded");let _=i();await A(e);let u=a?.neverExpires;if(u===void 0){let m=await _.execute({sql:"SELECT subscription_tier FROM users WHERE id = ? LIMIT 1",args:[e]});u=String(m.rows[0]?.subscription_tier??"").startsWith("sonic")}let o=u?"9999-12-31 23:59:59":null,c=async()=>{let m=await _.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return Number(m.rows[0]?.balance_mc??0)},d;try{d=await _.batch([{sql:"INSERT OR IGNORE INTO billing_credits (idempotency_key, user_id, amount_mc, operation, description, status) VALUES (?, ?, ?, ?, ?, 'claimed')",args:[s,e,t,r,n]},{sql:"UPDATE billing_credits SET status = 'applying' WHERE idempotency_key = ? AND user_id = ? AND amount_mc = ? AND operation = ? AND description = ? AND status = 'claimed'",args:[s,e,t,r,n]},{sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires)
1255
1300
  SELECT user_id, amount_mc, amount_mc, operation, NULL, COALESCE(?, datetime('now', ?)), ?
1256
1301
  FROM billing_credits
1257
- WHERE idempotency_key = ? AND status = 'applying'`,args:[o,C,_?1:0,i]},{sql:`UPDATE users
1302
+ WHERE idempotency_key = ? AND status = 'applying'`,args:[o,D,u?1:0,s]},{sql:`UPDATE users
1258
1303
  SET balance_mc = balance_mc + COALESCE((
1259
1304
  SELECT amount_mc FROM billing_credits WHERE idempotency_key = ? AND status = 'applying'
1260
1305
  ), 0)
1261
- WHERE id = ?`,args:[i,e]},{sql:"INSERT INTO ledger (user_id, amount_mc, operation, description) SELECT user_id, amount_mc, operation, description FROM billing_credits WHERE idempotency_key = ? AND status = 'applying'",args:[i]},{sql:"UPDATE billing_credits SET status = 'applied', applied_at = datetime('now') WHERE idempotency_key = ? AND status = 'applying'",args:[i]}],"write")}catch(m){try{let T=(await u.execute({sql:"SELECT user_id, amount_mc, operation, description FROM billing_credits WHERE idempotency_key = ? AND status = 'applied' LIMIT 1",args:[i]})).rows[0];if(T&&Number(T.user_id)===e&&Number(T.amount_mc)===t&&String(T.operation)===r&&String(T.description)===n)return{ok:!0,balance_mc:await c(),duplicate:!0}}catch{}throw m}let l=(await u.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_credits WHERE idempotency_key = ? LIMIT 1",args:[i]})).rows[0];if(!l||Number(l.user_id)!==e||Number(l.amount_mc)!==t||String(l.operation)!==r||String(l.description)!==n)throw new Error("idempotent credit key conflicts with another credit");return{ok:String(l.status)==="applied",balance_mc:await c(),duplicate:d[1]?.rowsAffected===0&&String(l.status)==="applied"}}async function yn(e,t){return(await s().execute({sql:"SELECT 1 FROM ledger WHERE user_id = ? AND operation = ? LIMIT 1",args:[e,t]})).rows.length>0}async function Cn(e,t){return(await s().execute({sql:"INSERT OR IGNORE INTO free_credit_refreshes (user_id, month) VALUES (?, ?)",args:[e,t]})).rowsAffected>0}async function Un(e,t,r,n){let i=await ut(e,t,r,n??"",`debit:${N()}`);return{ok:i.ok,balance_mc:i.balance_mc}}async function ut(e,t,r,n,i){if(!Number.isSafeInteger(t)||t<=0)throw new Error("idempotent debit amount must be a positive integer");if(!i||i.length>500)throw new Error("idempotent debit key is required and must be bounded");let a=s();await R(e);let u;try{u=await a.batch([{sql:"UPDATE billing_debits SET amount_mc = ? WHERE idempotency_key = ? AND user_id = ? AND operation = ? AND description = ? AND status = 'claimed'",args:[t,i,e,r,n]},{sql:"INSERT OR IGNORE INTO billing_debits (idempotency_key, user_id, amount_mc, operation, description, status) VALUES (?, ?, ?, ?, ?, 'claimed')",args:[i,e,t,r,n]},{sql:`UPDATE users
1306
+ WHERE id = ?`,args:[s,e]},{sql:"INSERT INTO ledger (user_id, amount_mc, operation, description) SELECT user_id, amount_mc, operation, description FROM billing_credits WHERE idempotency_key = ? AND status = 'applying'",args:[s]},{sql:"UPDATE billing_credits SET status = 'applied', applied_at = datetime('now') WHERE idempotency_key = ? AND status = 'applying'",args:[s]}],"write")}catch(m){try{let T=(await _.execute({sql:"SELECT user_id, amount_mc, operation, description FROM billing_credits WHERE idempotency_key = ? AND status = 'applied' LIMIT 1",args:[s]})).rows[0];if(T&&Number(T.user_id)===e&&Number(T.amount_mc)===t&&String(T.operation)===r&&String(T.description)===n)return{ok:!0,balance_mc:await c(),duplicate:!0}}catch{}throw m}let l=(await _.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_credits WHERE idempotency_key = ? LIMIT 1",args:[s]})).rows[0];if(!l||Number(l.user_id)!==e||Number(l.amount_mc)!==t||String(l.operation)!==r||String(l.description)!==n)throw new Error("idempotent credit key conflicts with another credit");return{ok:String(l.status)==="applied",balance_mc:await c(),duplicate:d[1]?.rowsAffected===0&&String(l.status)==="applied"}}async function Fn(e,t){return(await i().execute({sql:"SELECT 1 FROM ledger WHERE user_id = ? AND operation = ? LIMIT 1",args:[e,t]})).rows.length>0}async function Pn(e,t){return(await i().execute({sql:"INSERT OR IGNORE INTO free_credit_refreshes (user_id, month) VALUES (?, ?)",args:[e,t]})).rowsAffected>0}async function Hn(e,t,r,n){let s=`debit:${N()}`,a=await mt(e,t,r,n??"",s);return{ok:a.ok,balance_mc:a.balance_mc,billingKey:s}}async function mt(e,t,r,n,s){if(!Number.isSafeInteger(t)||t<=0)throw new Error("idempotent debit amount must be a positive integer");if(!s||s.length>500)throw new Error("idempotent debit key is required and must be bounded");let a=i();await A(e);let _;try{_=await a.batch([{sql:"UPDATE billing_debits SET amount_mc = ? WHERE idempotency_key = ? AND user_id = ? AND operation = ? AND description = ? AND status = 'claimed'",args:[t,s,e,r,n]},{sql:"INSERT OR IGNORE INTO billing_debits (idempotency_key, user_id, amount_mc, operation, description, status) VALUES (?, ?, ?, ?, ?, 'claimed')",args:[s,e,t,r,n]},{sql:`UPDATE users
1262
1307
  SET balance_mc = balance_mc - ?
1263
1308
  WHERE id = ?
1264
1309
  AND balance_mc >= ?
@@ -1267,7 +1312,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1267
1312
  WHERE user_id = ?
1268
1313
  AND remaining_mc > 0
1269
1314
  AND (never_expires = 1 OR expires_at > datetime('now'))) >= ?
1270
- AND EXISTS (SELECT 1 FROM billing_debits WHERE idempotency_key = ? AND user_id = ? AND amount_mc = ? AND operation = ? AND description = ? AND status = 'claimed')`,args:[t,e,t,e,t,i,e,t,r,n]},{sql:"UPDATE billing_debits SET status = 'applying' WHERE idempotency_key = ? AND user_id = ? AND amount_mc = ? AND operation = ? AND description = ? AND status = 'claimed' AND changes() = 1",args:[i,e,t,r,n]},{sql:`INSERT OR IGNORE INTO billing_debit_allocations
1315
+ AND EXISTS (SELECT 1 FROM billing_debits WHERE idempotency_key = ? AND user_id = ? AND amount_mc = ? AND operation = ? AND description = ? AND status = 'claimed')`,args:[t,e,t,e,t,s,e,t,r,n]},{sql:"UPDATE billing_debits SET status = 'applying' WHERE idempotency_key = ? AND user_id = ? AND amount_mc = ? AND operation = ? AND description = ? AND status = 'claimed' AND changes() = 1",args:[s,e,t,r,n]},{sql:`INSERT OR IGNORE INTO billing_debit_allocations
1271
1316
  (debit_idempotency_key, lot_id, user_id, amount_mc, expires_at)
1272
1317
  WITH ordered AS MATERIALIZED (
1273
1318
  SELECT id,
@@ -1286,7 +1331,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1286
1331
  SELECT ?, id, ?, take_mc, expires_at
1287
1332
  FROM allocation
1288
1333
  WHERE take_mc > 0
1289
- AND EXISTS (SELECT 1 FROM billing_debits WHERE idempotency_key = ? AND status = 'applying')`,args:[e,t,i,e,i]},{sql:`UPDATE credit_lots
1334
+ AND EXISTS (SELECT 1 FROM billing_debits WHERE idempotency_key = ? AND status = 'applying')`,args:[e,t,s,e,s]},{sql:`UPDATE credit_lots
1290
1335
  SET remaining_mc = remaining_mc - COALESCE((
1291
1336
  SELECT amount_mc FROM billing_debit_allocations
1292
1337
  WHERE debit_idempotency_key = ? AND lot_id = credit_lots.id
@@ -1294,7 +1339,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1294
1339
  WHERE id IN (
1295
1340
  SELECT lot_id FROM billing_debit_allocations WHERE debit_idempotency_key = ?
1296
1341
  )
1297
- AND EXISTS (SELECT 1 FROM billing_debits WHERE idempotency_key = ? AND status = 'applying')`,args:[i,i,i]},{sql:"INSERT INTO ledger (user_id, amount_mc, operation, description) SELECT user_id, -amount_mc, operation, description FROM billing_debits WHERE idempotency_key = ? AND status = 'applying'",args:[i]},{sql:"UPDATE billing_debits SET status = 'applied', applied_at = datetime('now') WHERE idempotency_key = ? AND status = 'applying'",args:[i]}],"write")}catch(d){try{let l=(await a.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_debits WHERE idempotency_key = ? AND status = 'applied' LIMIT 1",args:[i]})).rows[0];if(l&&Number(l.user_id)===e&&Number(l.amount_mc)===t&&String(l.operation)===r&&String(l.description)===n){let m=await a.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return{ok:!0,balance_mc:Number(m.rows[0]?.balance_mc??0),duplicate:!0}}}catch{}throw d}let o=(await a.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_debits WHERE idempotency_key = ? LIMIT 1",args:[i]})).rows[0];if(!o||Number(o.user_id)!==e||Number(o.amount_mc)!==t||String(o.operation)!==r||String(o.description)!==n)throw new Error("idempotent debit key conflicts with another debit");let c=await a.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return{ok:String(o.status)==="applied",balance_mc:Number(c.rows[0]?.balance_mc??0),duplicate:u[2]?.rowsAffected===0&&String(o.status)==="applied"}}async function Dn(e,t,r,n,i,a){if(!Number.isSafeInteger(r)||r<0)throw new Error("idempotent debit settlement amount must be a non-negative integer");if(!t||t.length>500)throw new Error("idempotent debit settlement key is required and must be bounded");if(!n||!a)throw new Error("idempotent debit settlement operation and source are required");let u=s();await R(e);let _=`debit-settlement:${U("sha256").update(t).digest("hex")}`,o="wallet_hold_settlement",c=N(),d=JSON.stringify({debitIdempotencyKey:t,refundOperation:n,description:i}),E=async()=>{let T=(await u.execute({sql:`SELECT e.user_id,
1342
+ AND EXISTS (SELECT 1 FROM billing_debits WHERE idempotency_key = ? AND status = 'applying')`,args:[s,s,s]},{sql:"INSERT INTO ledger (user_id, amount_mc, operation, description) SELECT user_id, -amount_mc, operation, description FROM billing_debits WHERE idempotency_key = ? AND status = 'applying'",args:[s]},{sql:"UPDATE billing_debits SET status = 'applied', applied_at = datetime('now') WHERE idempotency_key = ? AND status = 'applying'",args:[s]}],"write")}catch(d){try{let l=(await a.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_debits WHERE idempotency_key = ? AND status = 'applied' LIMIT 1",args:[s]})).rows[0];if(l&&Number(l.user_id)===e&&Number(l.amount_mc)===t&&String(l.operation)===r&&String(l.description)===n){let m=await a.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return{ok:!0,balance_mc:Number(m.rows[0]?.balance_mc??0),duplicate:!0}}}catch{}throw d}let o=(await a.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_debits WHERE idempotency_key = ? LIMIT 1",args:[s]})).rows[0];if(!o||Number(o.user_id)!==e||Number(o.amount_mc)!==t||String(o.operation)!==r||String(o.description)!==n)throw new Error("idempotent debit key conflicts with another debit");let c=await a.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return{ok:String(o.status)==="applied",balance_mc:Number(c.rows[0]?.balance_mc??0),duplicate:_[2]?.rowsAffected===0&&String(o.status)==="applied"}}async function qn(e,t,r,n,s,a){if(!Number.isSafeInteger(r)||r<0)throw new Error("idempotent debit settlement amount must be a non-negative integer");if(!t||t.length>500)throw new Error("idempotent debit settlement key is required and must be bounded");if(!n||!a)throw new Error("idempotent debit settlement operation and source are required");let _=i();await A(e);let u=`debit-settlement:${v("sha256").update(t).digest("hex")}`,o="wallet_hold_settlement",c=N(),d=JSON.stringify({debitIdempotencyKey:t,refundOperation:n,description:s}),E=async()=>{let T=(await _.execute({sql:`SELECT e.user_id,
1298
1343
  e.status,
1299
1344
  e.amount_mc AS final_amount_mc,
1300
1345
  e.billing_class,
@@ -1306,7 +1351,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1306
1351
  WHERE e.idempotency_key = ?
1307
1352
  AND d.user_id = e.user_id
1308
1353
  AND d.status = 'applied'
1309
- LIMIT 1`,args:[t,_]})).rows[0];if(!T)return null;if(Number(T.user_id)!==e||String(T.billing_class)!==o||String(T.source_surface)!==a)throw new Error("idempotent debit settlement key conflicts with another settlement");if(String(T.status)!=="settled")return null;let H=Number(T.held_amount_mc),A=Number(T.final_amount_mc);if(!Number.isSafeInteger(H)||!Number.isSafeInteger(A)||A<0||A>H)throw new Error("idempotent debit settlement receipt is invalid");let fe=H-A,z=await u.execute({sql:`WITH ordered AS (
1354
+ LIMIT 1`,args:[t,u]})).rows[0];if(!T)return null;if(Number(T.user_id)!==e||String(T.billing_class)!==o||String(T.source_surface)!==a)throw new Error("idempotent debit settlement key conflicts with another settlement");if(String(T.status)!=="settled")return null;let W=Number(T.held_amount_mc),w=Number(T.final_amount_mc);if(!Number.isSafeInteger(W)||!Number.isSafeInteger(w)||w<0||w>W)throw new Error("idempotent debit settlement receipt is invalid");let Ue=W-w,Q=await _.execute({sql:`WITH ordered AS (
1310
1355
  SELECT a.amount_mc,
1311
1356
  a.expires_at,
1312
1357
  COALESCE(SUM(a.amount_mc) OVER (
@@ -1322,9 +1367,9 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1322
1367
  )
1323
1368
  SELECT (SELECT COUNT(*) FROM ordered) AS allocation_count,
1324
1369
  COALESCE(SUM(CASE WHEN expires_at > ? THEN refund_mc ELSE 0 END), 0) AS credited_refund_mc
1325
- FROM refunds`,args:[t,A,String(T.settled_at)]}),V=Number(z.rows[0]?.allocation_count??0)>0?Number(z.rows[0]?.credited_refund_mc??0):0,he=await u.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return{balance_mc:Number(he.rows[0]?.balance_mc??0),final_amount_mc:A,refund_mc:V,expired_refund_mc:fe-V,duplicate:!0}},l;try{l=await u.batch([{sql:`INSERT OR IGNORE INTO billing_events
1370
+ FROM refunds`,args:[t,w,String(T.settled_at)]}),Z=Number(Q.rows[0]?.allocation_count??0)>0?Number(Q.rows[0]?.credited_refund_mc??0):0,De=await _.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return{balance_mc:Number(De.rows[0]?.balance_mc??0),final_amount_mc:w,refund_mc:Z,expired_refund_mc:Ue-Z,duplicate:!0}},l;try{l=await _.batch([{sql:`INSERT OR IGNORE INTO billing_events
1326
1371
  (id, user_id, idempotency_key, billing_class, source_surface, status, amount_mc, metadata)
1327
- VALUES (?, ?, ?, ?, ?, 'settling', ?, ?)`,args:[c,e,_,o,a,r,d]},{sql:`WITH ordered AS (
1372
+ VALUES (?, ?, ?, ?, ?, 'settling', ?, ?)`,args:[c,e,u,o,a,r,d]},{sql:`WITH ordered AS (
1328
1373
  SELECT a.lot_id,
1329
1374
  a.amount_mc,
1330
1375
  a.expires_at,
@@ -1365,14 +1410,14 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1365
1410
  AND d.user_id = e.user_id
1366
1411
  AND d.status = 'applied'
1367
1412
  AND e.amount_mc BETWEEN 0 AND d.amount_mc
1368
- )`,args:[t,r,e,t,_,e,o,a]},{sql:`UPDATE billing_events
1413
+ )`,args:[t,r,e,t,u,e,o,a]},{sql:`UPDATE billing_events
1369
1414
  SET status = 'applying'
1370
1415
  WHERE idempotency_key = ?
1371
1416
  AND user_id = ?
1372
1417
  AND billing_class = ?
1373
1418
  AND source_surface = ?
1374
1419
  AND status = 'settling'
1375
- AND changes() = 1`,args:[_,e,o,a]},{sql:`WITH ordered AS (
1420
+ AND changes() = 1`,args:[u,e,o,a]},{sql:`WITH ordered AS (
1376
1421
  SELECT a.lot_id,
1377
1422
  a.amount_mc,
1378
1423
  a.expires_at,
@@ -1394,7 +1439,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1394
1439
  SELECT lot_id FROM refunds
1395
1440
  WHERE refund_mc > 0 AND expires_at > datetime('now')
1396
1441
  )
1397
- AND EXISTS (SELECT 1 FROM billing_events WHERE idempotency_key = ? AND status = 'applying')`,args:[t,r,_]},{sql:`WITH ordered AS (
1442
+ AND EXISTS (SELECT 1 FROM billing_events WHERE idempotency_key = ? AND status = 'applying')`,args:[t,r,u]},{sql:`WITH ordered AS (
1398
1443
  SELECT a.amount_mc,
1399
1444
  a.expires_at,
1400
1445
  COALESCE(SUM(a.amount_mc) OVER (
@@ -1427,20 +1472,20 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1427
1472
  ?,
1428
1473
  ?
1429
1474
  FROM credited
1430
- WHERE refund_mc > 0`,args:[t,r,t,_,n,i]},{sql:`UPDATE billing_events
1475
+ WHERE refund_mc > 0`,args:[t,r,t,u,n,s]},{sql:`UPDATE billing_events
1431
1476
  SET status = 'settled', settled_at = datetime('now')
1432
1477
  WHERE idempotency_key = ?
1433
- AND status = 'applying'`,args:[_]}],"write")}catch(g){try{let T=await E();if(T)return T}catch{}throw g}let m=await E();if(!m)throw new Error("idempotent debit settlement did not reach a durable settled state");return{...m,duplicate:l[0]?.rowsAffected===0}}async function kn(e,t=50){return(await s().execute({sql:"SELECT * FROM ledger WHERE user_id = ? ORDER BY created_at DESC LIMIT ?",args:[e,t]})).rows.map(n=>({id:Number(n.id),user_id:Number(n.user_id),amount_mc:Number(n.amount_mc),operation:String(n.operation),description:n.description!=null?String(n.description):null,stripe_pi:n.stripe_pi!=null?String(n.stripe_pi):null,created_at:String(n.created_at)}))}async function vn(e,t,r){let n=s(),i=r.refund.map(()=>"?").join(", "),a=r.grant.map(()=>"?").join(", "),u=r.purchase.map(()=>"?").join(", "),_=await n.execute({sql:`SELECT
1434
- COALESCE(SUM(CASE WHEN amount_mc < 0 AND operation NOT IN (${i}) THEN -amount_mc ELSE 0 END), 0) AS spent_mc,
1435
- COALESCE(SUM(CASE WHEN amount_mc > 0 AND operation IN (${i}) THEN amount_mc ELSE 0 END), 0) AS refunded_mc,
1478
+ AND status = 'applying'`,args:[u]}],"write")}catch(g){try{let T=await E();if(T)return T}catch{}throw g}let m=await E();if(!m)throw new Error("idempotent debit settlement did not reach a durable settled state");return{...m,duplicate:l[0]?.rowsAffected===0}}async function Wn(e,t=50){return(await i().execute({sql:"SELECT * FROM ledger WHERE user_id = ? ORDER BY created_at DESC LIMIT ?",args:[e,t]})).rows.map(n=>({id:Number(n.id),user_id:Number(n.user_id),amount_mc:Number(n.amount_mc),operation:String(n.operation),description:n.description!=null?String(n.description):null,stripe_pi:n.stripe_pi!=null?String(n.stripe_pi):null,created_at:String(n.created_at)}))}async function jn(e,t,r){let n=i(),s=r.refund.map(()=>"?").join(", "),a=r.grant.map(()=>"?").join(", "),_=r.purchase.map(()=>"?").join(", "),u=await n.execute({sql:`SELECT
1479
+ COALESCE(SUM(CASE WHEN amount_mc < 0 AND operation NOT IN (${s}) THEN -amount_mc ELSE 0 END), 0) AS spent_mc,
1480
+ COALESCE(SUM(CASE WHEN amount_mc > 0 AND operation IN (${s}) THEN amount_mc ELSE 0 END), 0) AS refunded_mc,
1436
1481
  COALESCE(SUM(CASE WHEN amount_mc > 0 AND operation IN (${a}) THEN amount_mc ELSE 0 END), 0) AS granted_mc,
1437
- COALESCE(SUM(CASE WHEN amount_mc > 0 AND operation IN (${u}) THEN amount_mc ELSE 0 END), 0) AS purchased_mc,
1482
+ COALESCE(SUM(CASE WHEN amount_mc > 0 AND operation IN (${_}) THEN amount_mc ELSE 0 END), 0) AS purchased_mc,
1438
1483
  COALESCE(SUM(amount_mc), 0) AS net_mc
1439
1484
  FROM ledger WHERE user_id = ? AND created_at >= ?`,args:[...r.refund,...r.refund,...r.grant,...r.purchase,e,t]}),o=await n.execute({sql:`SELECT operation, -SUM(amount_mc) AS mc, COUNT(*) AS count
1440
1485
  FROM ledger
1441
- WHERE user_id = ? AND created_at >= ? AND amount_mc < 0 AND operation NOT IN (${i})
1486
+ WHERE user_id = ? AND created_at >= ? AND amount_mc < 0 AND operation NOT IN (${s})
1442
1487
  GROUP BY operation
1443
- ORDER BY mc DESC, operation ASC`,args:[e,t,...r.refund]}),c=_.rows[0];return{spent_mc:Number(c?.spent_mc??0),refunded_mc:Number(c?.refunded_mc??0),granted_mc:Number(c?.granted_mc??0),purchased_mc:Number(c?.purchased_mc??0),net_mc:Number(c?.net_mc??0),by_operation:o.rows.map(d=>({operation:String(d.operation),mc:Number(d.mc),count:Number(d.count)}))}}async function Xn(e){return(await s().execute({sql:"SELECT 1 FROM ledger WHERE stripe_pi = ? LIMIT 1",args:[e]})).rows.length>0}async function Oe(e,t){let r=s();for(let i=0;i<8;i+=1){let u=(await r.execute({sql:`SELECT
1488
+ ORDER BY mc DESC, operation ASC`,args:[e,t,...r.refund]}),c=u.rows[0];return{spent_mc:Number(c?.spent_mc??0),refunded_mc:Number(c?.refunded_mc??0),granted_mc:Number(c?.granted_mc??0),purchased_mc:Number(c?.purchased_mc??0),net_mc:Number(c?.net_mc??0),by_operation:o.rows.map(d=>({operation:String(d.operation),mc:Number(d.mc),count:Number(d.count)}))}}async function Bn(e){return(await i().execute({sql:"SELECT 1 FROM ledger WHERE stripe_pi = ? LIMIT 1",args:[e]})).rows.length>0}async function Ce(e,t){let r=i();for(let s=0;s<8;s+=1){let _=(await r.execute({sql:`SELECT
1444
1489
  u.balance_mc AS cached_balance_mc,
1445
1490
  COUNT(l.id) AS lot_count,
1446
1491
  COALESCE(SUM(CASE
@@ -1450,4 +1495,4 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as U,rando
1450
1495
  FROM users u
1451
1496
  LEFT JOIN credit_lots l ON l.user_id = u.id
1452
1497
  WHERE u.id = ?
1453
- GROUP BY u.id, u.balance_mc`,args:[e]})).rows[0];if(!u)return 0;if(Number(u.lot_count??0)===0&&(await R(Number(e)),(await r.execute({sql:"SELECT 1 FROM credit_lots WHERE user_id = ? LIMIT 1",args:[e]})).rows.length>0))continue;let _=Number(u.cached_balance_mc??0),o=Number(u.projected_balance_mc??0);if(_===o||(await r.execute({sql:"UPDATE users SET balance_mc = ? WHERE id = ? AND balance_mc = ?",args:[o,e,_]})).rowsAffected===1)return o}let n=await r.execute({sql:"SELECT balance_mc FROM users WHERE id = ? LIMIT 1",args:[e]});return Number(n.rows[0]?.balance_mc??0)}var Mn=p.object({id:p.string(),user_id:p.number(),status:p.string().default("pending"),client_domain:p.string(),session_path:p.string(),request:p.string(),result:p.string().nullable(),error:p.string().nullable(),created_at:p.string(),updated_at:p.string()}),Fn=p.object({id:p.number(),job_id:p.string(),phase:p.string(),completed_at:p.string(),output_summary:p.string()});async function Pn(e){return(await s().execute({sql:"SELECT id, subject, sent_at, opened_at FROM inbox_messages WHERE user_id = ? AND deleted_at IS NULL ORDER BY sent_at DESC, id DESC",args:[e]})).rows.map(r=>({id:String(r.id),subject:String(r.subject),sent_at:String(r.sent_at),opened_at:r.opened_at!=null?String(r.opened_at):null}))}async function Hn(e,t){let n=(await s().execute({sql:"SELECT id, subject, body_md, source, sent_at, opened_at FROM inbox_messages WHERE id = ? AND user_id = ? AND deleted_at IS NULL",args:[t,e]})).rows[0];if(n)return{id:String(n.id),subject:String(n.subject),body_md:String(n.body_md),source:String(n.source),sent_at:String(n.sent_at),opened_at:n.opened_at!=null?String(n.opened_at):null}}async function Wn(e,t){let r=s();await r.execute({sql:"UPDATE inbox_messages SET opened_at = datetime('now') WHERE id = ? AND user_id = ? AND deleted_at IS NULL AND opened_at IS NULL",args:[t,e]});let i=(await r.execute({sql:"SELECT opened_at FROM inbox_messages WHERE id = ? AND user_id = ? AND deleted_at IS NULL",args:[t,e]})).rows[0];return i&&i.opened_at!=null?String(i.opened_at):null}async function qn(e,t){return(await s().execute({sql:"UPDATE inbox_messages SET deleted_at = datetime('now') WHERE id = ? AND user_id = ? AND deleted_at IS NULL",args:[t,e]})).rowsAffected>0}async function jn(e,t,r,n="operator"){let i=N();return await s().execute({sql:"INSERT INTO inbox_messages (id, user_id, subject, body_md, source) VALUES (?, ?, ?, ?, ?)",args:[i,e,t,r,n]}),i}async function Bn(){return(await s().execute("SELECT id FROM users WHERE active = 1")).rows.map(t=>Number(t.id))}export{dt as a,xe as b,Ie as c,w as d,se as e,W as f,Fe as g,Pe as h,ae as i,Q as j,Z as k,ee as l,te as m,re as n,ne as o,D as p,y as q,de as r,bt as s,s as t,St as u,Rt as v,At as w,wt as x,Ot as y,ft as z,ht as A,xt as B,ze as C,It as D,yt as E,Ct as F,Ut as G,Dt as H,kt as I,vt as J,Xt as K,Mt as L,Ft as M,me as N,Ne as O,Pt as P,Ht as Q,Wt as R,qt as S,jt as T,Bt as U,Gt as V,Yt as W,Kt as X,$t as Y,Jt as Z,zt as _,Vt as $,Qt as aa,Zt as ba,er as ca,tr as da,Ve as ea,rr as fa,nr as ga,sr as ha,ir as ia,ar as ja,or as ka,ur as la,_r as ma,cr as na,G as oa,dr as pa,lr as qa,Er as ra,Tr as sa,pr as ta,mr as ua,Nr as va,gr as wa,Lr as xa,B as ya,br as za,Sr as Aa,Rr as Ba,Ar as Ca,wr as Da,Or as Ea,tt as Fa,rt as Ga,fr as Ha,hr as Ia,xr as Ja,Ir as Ka,yr as La,Cr as Ma,Ur as Na,Dr as Oa,we as Pa,kr as Qa,vr as Ra,Xr as Sa,Mr as Ta,Fr as Ua,Pr as Va,Hr as Wa,Wr as Xa,qr as Ya,jr as Za,Br as _a,Gr as $a,Yr as ab,Kr as bb,$r as cb,Jr as db,zr as eb,Vr as fb,Qr as gb,Zr as hb,en as ib,tn as jb,rn as kb,nn as lb,sn as mb,an as nb,on as ob,un as pb,_n as qb,cn as rb,dn as sb,ln as tb,En as ub,Tn as vb,pn as wb,it as xb,mn as yb,Nn as zb,gn as Ab,ot as Bb,Ln as Cb,bn as Db,Sn as Eb,Rn as Fb,An as Gb,wn as Hb,On as Ib,C as Jb,fn as Kb,hn as Lb,xn as Mb,In as Nb,yn as Ob,Cn as Pb,Un as Qb,ut as Rb,Dn as Sb,kn as Tb,vn as Ub,Xn as Vb,Oe as Wb,Mn as Xb,Fn as Yb,Pn as Zb,Hn as _b,Wn as $b,qn as ac,jn as bc,Bn as cc};
1498
+ GROUP BY u.id, u.balance_mc`,args:[e]})).rows[0];if(!_)return 0;if(Number(_.lot_count??0)===0&&(await A(Number(e)),(await r.execute({sql:"SELECT 1 FROM credit_lots WHERE user_id = ? LIMIT 1",args:[e]})).rows.length>0))continue;let u=Number(_.cached_balance_mc??0),o=Number(_.projected_balance_mc??0);if(u===o||(await r.execute({sql:"UPDATE users SET balance_mc = ? WHERE id = ? AND balance_mc = ?",args:[o,e,u]})).rowsAffected===1)return o}let n=await r.execute({sql:"SELECT balance_mc FROM users WHERE id = ? LIMIT 1",args:[e]});return Number(n.rows[0]?.balance_mc??0)}var Gn=p.object({id:p.string(),user_id:p.number(),status:p.string().default("pending"),client_domain:p.string(),session_path:p.string(),request:p.string(),result:p.string().nullable(),error:p.string().nullable(),created_at:p.string(),updated_at:p.string()}),Yn=p.object({id:p.number(),job_id:p.string(),phase:p.string(),completed_at:p.string(),output_summary:p.string()});async function Kn(e){return(await i().execute({sql:"SELECT id, subject, sent_at, opened_at FROM inbox_messages WHERE user_id = ? AND deleted_at IS NULL ORDER BY sent_at DESC, id DESC",args:[e]})).rows.map(r=>({id:String(r.id),subject:String(r.subject),sent_at:String(r.sent_at),opened_at:r.opened_at!=null?String(r.opened_at):null}))}async function $n(e,t){let n=(await i().execute({sql:"SELECT id, subject, body_md, source, sent_at, opened_at FROM inbox_messages WHERE id = ? AND user_id = ? AND deleted_at IS NULL",args:[t,e]})).rows[0];if(n)return{id:String(n.id),subject:String(n.subject),body_md:String(n.body_md),source:String(n.source),sent_at:String(n.sent_at),opened_at:n.opened_at!=null?String(n.opened_at):null}}async function Jn(e,t){let r=i();await r.execute({sql:"UPDATE inbox_messages SET opened_at = datetime('now') WHERE id = ? AND user_id = ? AND deleted_at IS NULL AND opened_at IS NULL",args:[t,e]});let s=(await r.execute({sql:"SELECT opened_at FROM inbox_messages WHERE id = ? AND user_id = ? AND deleted_at IS NULL",args:[t,e]})).rows[0];return s&&s.opened_at!=null?String(s.opened_at):null}async function Vn(e,t){return(await i().execute({sql:"UPDATE inbox_messages SET deleted_at = datetime('now') WHERE id = ? AND user_id = ? AND deleted_at IS NULL",args:[t,e]})).rowsAffected>0}async function zn(e,t,r,n="operator"){let s=N();return await i().execute({sql:"INSERT INTO inbox_messages (id, user_id, subject, body_md, source) VALUES (?, ?, ?, ?, ?)",args:[s,e,t,r,n]}),s}async function Qn(){return(await i().execute("SELECT id FROM users WHERE active = 1")).rows.map(t=>Number(t.id))}export{Lt as a,ve as b,ke as c,O as d,ae as e,j as f,Be as g,Ge as h,_e as i,ee as j,te as k,re as l,ne as m,se as n,ie as o,k as p,U as q,Ee as r,It as s,i as t,xt as u,yt as v,Ct as w,nt as x,Ut as y,Dt as z,vt as A,kt as B,Xt as C,st as D,Mt as E,Ft as F,Pt as G,Ht as H,qt as I,Wt as J,jt as K,Bt as L,Gt as M,Yt as N,Re as O,Ae as P,Kt as Q,$t as R,Jt as S,Vt as T,zt as U,Qt as V,Zt as W,er as X,tr as Y,rr as Z,nr as _,sr as $,ir as aa,ar as ba,or as ca,_r as da,ur as ea,it as fa,cr as ga,dr as ha,lr as ia,Er as ja,Tr as ka,pr as la,mr as ma,Nr as na,gr as oa,K as pa,Lr as qa,br as ra,Sr as sa,Rr as ta,Ar as ua,wr as va,Or as wa,fr as xa,hr as ya,Y as za,Ir as Aa,xr as Ba,yr as Ca,Cr as Da,Ur as Ea,Dr as Fa,ut as Ga,ct as Ha,vr as Ia,kr as Ja,Xr as Ka,Mr as La,Fr as Ma,Pr as Na,Hr as Oa,qr as Pa,ye as Qa,Wr as Ra,jr as Sa,Br as Ta,Gr as Ua,Yr as Va,Kr as Wa,$r as Xa,Jr as Ya,Vr as Za,zr as _a,Qr as $a,Zr as ab,en as bb,tn as cb,rn as db,nn as eb,sn as fb,an as gb,on as hb,_n as ib,un as jb,cn as kb,dn as lb,ln as mb,En as nb,Tn as ob,pn as pb,mn as qb,Nn as rb,gn as sb,Ln as tb,bn as ub,Sn as vb,Rn as wb,An as xb,Et as yb,wn as zb,On as Ab,fn as Bb,pt as Cb,hn as Db,In as Eb,xn as Fb,yn as Gb,Cn as Hb,Un as Ib,Dn as Jb,D as Kb,vn as Lb,kn as Mb,Xn as Nb,Mn as Ob,Fn as Pb,Pn as Qb,Hn as Rb,mt as Sb,qn as Tb,Wn as Ub,jn as Vb,Bn as Wb,Ce as Xb,Gn as Yb,Yn as Zb,Kn as _b,$n as $b,Jn as ac,Vn as bc,zn as cc,Qn as dc};