mcp-scraper 0.93.3 → 0.94.0

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 (57) hide show
  1. package/CHANGELOG.md +67 -28
  2. package/README.md +5 -5
  3. package/THIRD_PARTY_NOTICES.html +203 -0
  4. package/dist/{analytics-repository-IHOFBSUV.js → analytics-repository-A7VMA24D.js} +1 -1
  5. package/dist/bin/api-server.js +1 -1
  6. package/dist/bin/mcp-scraper-cli.js +1 -1
  7. package/dist/bin/mcp-scraper-core.js +1 -1
  8. package/dist/bin/mcp-scraper-install.js +1 -1
  9. package/dist/bin/mcp-stdio-server.js +1 -1
  10. package/dist/bin/paa-harvest.js +1 -1
  11. package/dist/{chunk-BS4V4CVX.js → chunk-2GEVQBI6.js} +1 -1
  12. package/dist/chunk-4SNU2TWB.js +1 -0
  13. package/dist/{chunk-LI7WHOII.js → chunk-56C243PX.js} +1 -1
  14. package/dist/{chunk-NLKA6SHC.js → chunk-72MWPIMR.js} +1 -1
  15. package/dist/{chunk-4FGLXXZ2.js → chunk-ASP7YHUY.js} +187 -185
  16. package/dist/{chunk-IJF4VXJ7.js → chunk-BRNTVOCW.js} +1 -1
  17. package/dist/{chunk-DFJT2YX6.js → chunk-C5MWTMRD.js} +4 -4
  18. package/dist/chunk-DOJMTFLB.js +1 -0
  19. package/dist/{chunk-LSFDB5XE.js → chunk-DYKSPHHR.js} +1 -1
  20. package/dist/chunk-I46JRG5B.js +1 -0
  21. package/dist/{chunk-QTDLZTQ7.js → chunk-L552AQQY.js} +1 -1
  22. package/dist/chunk-LCFZSD37.js +6 -0
  23. package/dist/{chunk-M5VZVMPC.js → chunk-LZEBDJHY.js} +6 -6
  24. package/dist/chunk-M5QHXNFZ.js +3 -3
  25. package/dist/{chunk-2SP57VCG.js → chunk-NA76FFGD.js} +15 -15
  26. package/dist/chunk-NZSDHDX3.js +1 -0
  27. package/dist/{chunk-AFFMCO7R.js → chunk-QDP3XTES.js} +2 -2
  28. package/dist/{chunk-X7GZJU5P.js → chunk-QQ7OD7BJ.js} +1 -1
  29. package/dist/{chunk-IK5BG7MO.js → chunk-RJPQCPDX.js} +1 -1
  30. package/dist/chunk-SH5KB4P7.js +1 -1
  31. package/dist/{chunk-W2T4NTCE.js → chunk-SJRXG3LV.js} +1 -1
  32. package/dist/chunk-ZGITQEFC.js +1 -0
  33. package/dist/{chunk-WJ4XFLS4.js → chunk-ZPK5LYEN.js} +105 -38
  34. package/dist/{chunk-5JKBFNYF.js → chunk-ZTEDLK3Y.js} +1 -1
  35. package/dist/{chunk-ORB4RHCK.js → chunk-ZUGTYD2I.js} +5 -5
  36. package/dist/{db-B5XJTOGN.js → db-B6RNXKEI.js} +1 -1
  37. package/dist/{extract-bundle-C3N6E6V7.js → extract-bundle-GMRZ2CW3.js} +1 -1
  38. package/dist/{gmail-service-6V5MFBYH.js → gmail-service-U7NP5IMY.js} +1 -1
  39. package/dist/index.cjs +41 -41
  40. package/dist/index.d.cts +14 -14
  41. package/dist/index.d.ts +14 -14
  42. package/dist/index.js +1 -1
  43. package/dist/{lead-list-enrichment-repository-AWZZMY2H.js → lead-list-enrichment-repository-SXYSS7ZX.js} +1 -1
  44. package/dist/{location-data-repository-6XAVI65Z.js → location-data-repository-NWWKDYG6.js} +1 -1
  45. package/dist/{operation-metering-DB5F7SXN.js → operation-metering-OBKSWJVJ.js} +1 -1
  46. package/dist/{server-G2ZCSWXW.js → server-SH6KWIEA.js} +537 -486
  47. package/dist/{site-extract-repository-2LFDP6FZ.js → site-extract-repository-DUBZXCRG.js} +1 -1
  48. package/dist/{stripe-event-worker-IJXA6T37.js → stripe-event-worker-2KOMIZXB.js} +1 -1
  49. package/dist/worker-V53ZJGJS.js +1 -0
  50. package/package.json +17 -136
  51. package/dist/chunk-DT2FYN6N.js +0 -1
  52. package/dist/chunk-RK2VCTZI.js +0 -1
  53. package/dist/chunk-SWCAKYBP.js +0 -1
  54. package/dist/chunk-UN6FVDJQ.js +0 -1
  55. package/dist/chunk-Y6MKMSOC.js +0 -1
  56. package/dist/chunk-ZG52SKGD.js +0 -6
  57. package/dist/worker-P2BICG36.js +0 -1
@@ -1,4 +1,4 @@
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(/https?:\/\/[^\s]*(?:brightdata|onkernel|kernel\.sh)[^\s]*/gi,"the service").replace(/bright\s*data/gi,"the service").replace(/brightdata/gi,"the service").replace(/kernel\.sh\s+sessions?/gi,"sessions").replace(/kernel\.sh\s+session/gi,"this session").replace(/kernel\.sh/gi,"the service").replace(/kernel\s+sessions?/gi,"sessions").replace(/kernel\s+session/gi,"this session").replace(/\b(?:sub|cus|sess|proxy)_[A-Za-z0-9_-]+\b/g,"[redacted]").replace(/\b(?:KERNEL|BRIGHTDATA|BRIGHT_DATA)_[A-Z0-9_]*API_KEY\b/g,"BROWSER_SERVICE_API_KEY").replace(/\bkernel\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 (
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),Fe=new Set(Xe),Me=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 W(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(Me.has(r))if(typeof n=="string"){if((r==="upgrade_url"||r==="topup_url")&&!je(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 je(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 We(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 Be(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 ve}}function Ge(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,s=typeof e.errorType=="string"&&Fe.has(e.errorType)?e.errorType:void 0,a=qe(e.details);return{error_code:t,error_type:s??We(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),
@@ -109,7 +109,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,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)`],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`
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 Ee(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 l=await e.execute({sql:"SELECT sql FROM sqlite_master WHERE type='table' AND name=?",args:[o]}),E=String(l.rows[0]?.sql??""),m=X.find(g=>u(g).startsWith(`create table ${o} `));(!m||u(E)!==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 l=await e.execute({sql:"SELECT sql FROM sqlite_master WHERE type='index' AND name=?",args:[o]}),E=String(l.rows[0]?.sql??""),m=X.find(g=>u(g).startsWith(`create index ${o} `));(!m||u(E)!==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,M=null,U="2026-09-25.1",le="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","maps_place_runs","maps_place_attempts","maps_place_run_events","maps_place_reviews","maps_place_images","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","maps_place_runs_owner_key","maps_place_runs_status_lease","maps_place_attempts_run_number","maps_place_reviews_order","maps_place_images_order","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={maps_place_runs:["request_fingerprint","field_states_json","core_json","checkpoint_revision","current_attempt_id","current_fence_token","lease_expires_at","billing_state"],maps_place_attempts:["attempt_number","resume_key_hash","fence_token","hold_key","held_amount_mc","final_amount_mc","billing_state"],maps_place_reviews:["review_key","record_json"],maps_place_images:["media_key","record_json"],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
113
  CREATE TABLE IF NOT EXISTS ${e} (
114
114
  id TEXT PRIMARY KEY,
115
115
  attempt_id TEXT NOT NULL REFERENCES operation_attempts(id) ON DELETE CASCADE,
@@ -151,7 +151,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
151
151
  CHECK (cost_state <> 'measured' OR (amount_usd_nanos IS NOT NULL
152
152
  AND (amount_usd_nanos > 0 OR zero_cost_reason IS NOT NULL)))
153
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(`
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 F(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 (${F(Te)})) = ${Te.length}`,`(SELECT COUNT(*) FROM sqlite_master WHERE type = 'index' AND name IN (${F(pe)})) = ${pe.length}`,`(SELECT COUNT(*) FROM sqlite_master WHERE type = 'trigger' AND name IN (${F(me)})) = ${me.length}`,...Object.entries(et).map(([n,s])=>`(SELECT COUNT(*) FROM pragma_table_info('${n}') WHERE name IN (${F(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(`
155
155
  UPDATE site_extract_jobs SET
156
156
  attempted_urls = done_urls,
157
157
  successful_urls = (
@@ -188,7 +188,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
188
188
  AND attempted_urls = 0
189
189
  AND successful_urls = 0
190
190
  AND failed_urls = 0
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(`
191
+ `)}async function G(e){(await e.execute({sql:"SELECT 1 AS applied FROM schema_migrations WHERE version = ? LIMIT 1",args:[le]})).rows.length>0||(await rt(e),await e.execute({sql:"INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",args:[le]}))}function i(){return M||(M=Ve({url:Qe,authToken:Ze})),M}function xt(e){M=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 Ee(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(`
192
192
  CREATE TABLE IF NOT EXISTS schema_migrations (
193
193
  version TEXT PRIMARY KEY,
194
194
  applied_at TEXT NOT NULL DEFAULT (datetime('now'))
@@ -230,14 +230,14 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
230
230
  max_questions INTEGER NOT NULL,
231
231
  status TEXT NOT NULL,
232
232
  outcome TEXT,
233
- kernel_session_id TEXT,
233
+ \u006b\u0065\u0072\u006e\u0065\u006c_session_id TEXT,
234
234
  question_count INTEGER,
235
235
  duration_ms INTEGER,
236
236
  error TEXT,
237
237
  will_retry INTEGER,
238
- kernel_delete_started INTEGER NOT NULL DEFAULT 0,
239
- kernel_delete_succeeded INTEGER,
240
- kernel_delete_error TEXT,
238
+ \u006b\u0065\u0072\u006e\u0065\u006c_delete_started INTEGER NOT NULL DEFAULT 0,
239
+ \u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded INTEGER,
240
+ \u006b\u0065\u0072\u006e\u0065\u006c_delete_error TEXT,
241
241
  browser_close_succeeded INTEGER,
242
242
  browser_close_error TEXT,
243
243
  debug_json TEXT,
@@ -509,6 +509,73 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
509
509
  CHECK ((status = 'running' AND ended_at IS NULL) OR (status <> 'running' AND ended_at IS NOT NULL))
510
510
  )
511
511
  `),await t.execute("CREATE UNIQUE INDEX IF NOT EXISTS operation_runs_idempotency_scope ON operation_runs(idempotency_scope_hash) WHERE idempotency_scope_hash IS NOT NULL"),await t.execute("CREATE INDEX IF NOT EXISTS operation_runs_user_started ON operation_runs(user_id, started_at DESC)"),await t.execute("CREATE INDEX IF NOT EXISTS operation_runs_tool_started ON operation_runs(tool, started_at DESC)"),await t.execute("CREATE INDEX IF NOT EXISTS operation_runs_status_started ON operation_runs(status, started_at)"),await t.execute(`
512
+ CREATE TABLE IF NOT EXISTS maps_place_runs (
513
+ id TEXT PRIMARY KEY,
514
+ user_id INTEGER NOT NULL REFERENCES users(id),
515
+ idempotency_key_hash TEXT NOT NULL,
516
+ request_fingerprint TEXT NOT NULL,
517
+ declaration_json TEXT NOT NULL CHECK (json_valid(declaration_json)),
518
+ status TEXT NOT NULL DEFAULT 'queued' CHECK (status IN ('queued','running','interrupted','complete','partial','failed','cancelled')),
519
+ billing_state TEXT NOT NULL DEFAULT 'unreserved' CHECK (billing_state IN ('unreserved','held','settling','settled','refunded','pending_reconciliation')),
520
+ field_states_json TEXT NOT NULL CHECK (json_valid(field_states_json)),
521
+ core_json TEXT CHECK (core_json IS NULL OR json_valid(core_json)),
522
+ verified INTEGER NOT NULL DEFAULT 0 CHECK (verified IN (0,1)),
523
+ checkpoint_revision INTEGER NOT NULL DEFAULT 0 CHECK (checkpoint_revision >= 0),
524
+ current_attempt_id TEXT,
525
+ current_fence_token TEXT,
526
+ lease_expires_at TEXT,
527
+ operation_run_id TEXT,
528
+ concurrency_lock_id TEXT,
529
+ error_code TEXT,
530
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
531
+ updated_at TEXT NOT NULL DEFAULT (datetime('now')),
532
+ UNIQUE(user_id, idempotency_key_hash)
533
+ )
534
+ `),await t.execute("CREATE UNIQUE INDEX IF NOT EXISTS maps_place_runs_owner_key ON maps_place_runs(user_id,idempotency_key_hash)"),await t.execute("CREATE INDEX IF NOT EXISTS maps_place_runs_status_lease ON maps_place_runs(status,lease_expires_at)"),await t.execute(`
535
+ CREATE TABLE IF NOT EXISTS maps_place_attempts (
536
+ id TEXT PRIMARY KEY,
537
+ run_id TEXT NOT NULL REFERENCES maps_place_runs(id) ON DELETE CASCADE,
538
+ attempt_number INTEGER NOT NULL CHECK (attempt_number > 0),
539
+ resume_key_hash TEXT,
540
+ fence_token TEXT NOT NULL,
541
+ status TEXT NOT NULL CHECK (status IN ('running','complete','partial','failed','interrupted','cancelled')),
542
+ lease_expires_at TEXT NOT NULL,
543
+ hold_key TEXT NOT NULL,
544
+ held_amount_mc INTEGER NOT NULL DEFAULT 0,
545
+ final_amount_mc INTEGER,
546
+ billing_state TEXT NOT NULL DEFAULT 'unreserved',
547
+ started_at TEXT NOT NULL DEFAULT (datetime('now')),
548
+ ended_at TEXT,
549
+ UNIQUE(run_id,attempt_number),
550
+ UNIQUE(run_id,resume_key_hash)
551
+ )
552
+ `),await t.execute("CREATE UNIQUE INDEX IF NOT EXISTS maps_place_attempts_run_number ON maps_place_attempts(run_id,attempt_number)"),await t.execute(`
553
+ CREATE TABLE IF NOT EXISTS maps_place_run_events (
554
+ id TEXT PRIMARY KEY,
555
+ run_id TEXT NOT NULL REFERENCES maps_place_runs(id) ON DELETE CASCADE,
556
+ attempt_id TEXT,
557
+ revision INTEGER NOT NULL,
558
+ event_type TEXT NOT NULL,
559
+ details_json TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(details_json)),
560
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
561
+ )
562
+ `),await t.execute(`
563
+ CREATE TABLE IF NOT EXISTS maps_place_reviews (
564
+ run_id TEXT NOT NULL REFERENCES maps_place_runs(id) ON DELETE CASCADE,
565
+ review_key TEXT NOT NULL,
566
+ ordinal INTEGER NOT NULL,
567
+ record_json TEXT NOT NULL CHECK (json_valid(record_json)),
568
+ PRIMARY KEY(run_id,review_key)
569
+ )
570
+ `),await t.execute("CREATE INDEX IF NOT EXISTS maps_place_reviews_order ON maps_place_reviews(run_id,ordinal,review_key)"),await t.execute(`
571
+ CREATE TABLE IF NOT EXISTS maps_place_images (
572
+ run_id TEXT NOT NULL REFERENCES maps_place_runs(id) ON DELETE CASCADE,
573
+ media_key TEXT NOT NULL,
574
+ ordinal INTEGER NOT NULL,
575
+ record_json TEXT NOT NULL CHECK (json_valid(record_json)),
576
+ PRIMARY KEY(run_id,media_key)
577
+ )
578
+ `),await t.execute("CREATE INDEX IF NOT EXISTS maps_place_images_order ON maps_place_images(run_id,ordinal,media_key)"),await t.execute(`
512
579
  CREATE TABLE IF NOT EXISTS operation_attempts (
513
580
  id TEXT PRIMARY KEY,
514
581
  run_id TEXT NOT NULL REFERENCES operation_runs(id) ON DELETE CASCADE,
@@ -922,8 +989,8 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
922
989
  id TEXT PRIMARY KEY,
923
990
  user_id INTEGER NOT NULL REFERENCES users(id),
924
991
  name TEXT NOT NULL,
925
- kernel_profile_name TEXT NOT NULL,
926
- kernel_proxy_id TEXT NOT NULL,
992
+ \u006b\u0065\u0072\u006e\u0065\u006c_profile_name TEXT NOT NULL,
993
+ \u006b\u0065\u0072\u006e\u0065\u006c_proxy_id TEXT NOT NULL,
927
994
  proxy_type TEXT NOT NULL DEFAULT 'isp',
928
995
  country TEXT NOT NULL DEFAULT 'US',
929
996
  status TEXT NOT NULL DEFAULT 'ready',
@@ -935,7 +1002,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
935
1002
  `),await t.execute(`
936
1003
  CREATE UNIQUE INDEX IF NOT EXISTS serp_identities_user_name
937
1004
  ON serp_identities(user_id, name)
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
1005
+ `),!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 Ft(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 Mt(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
939
1006
  (event_id, event_type, stripe_created_at, status, attempt_count, received_at, next_attempt_at, processed_at, updated_at)
940
1007
  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
941
1008
  FROM stripe_events
@@ -948,7 +1015,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
948
1015
  last_error_code = NULL, updated_at = datetime('now')
949
1016
  WHERE event_id = ?
950
1017
  AND ((status IN ('pending', 'retryable') AND COALESCE(next_attempt_at, received_at) <= datetime('now'))
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
1018
+ 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 jt(e,t){return(await i().execute({sql:`UPDATE stripe_events
952
1019
  SET status = 'processed',
953
1020
  claim_token = NULL,
954
1021
  claimed_at = NULL,
@@ -957,7 +1024,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
957
1024
  last_error = NULL,
958
1025
  processed_at = datetime('now'),
959
1026
  updated_at = datetime('now')
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
1027
+ WHERE event_id = ? AND status = 'processing' AND claim_token = ?`,args:[e,t]})).rowsAffected===1}async function Wt(e,t,r,n,s){return(await i().execute({sql:`UPDATE stripe_events
961
1028
  SET status = 'retryable',
962
1029
  claim_token = NULL,
963
1030
  claimed_at = NULL,
@@ -982,15 +1049,15 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
982
1049
  ON CONFLICT(scope, key_hash, window_start)
983
1050
  DO UPDATE SET count = count + 1, updated_at = datetime('now')
984
1051
  RETURNING count
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,kernel_session_id:e.kernel_session_id!=null?String(e.kernel_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),kernel_delete_started:Number(e.kernel_delete_started??0)===1,kernel_delete_succeeded:C(e.kernel_delete_succeeded),kernel_delete_error:e.kernel_delete_error!=null?String(e.kernel_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)
1052
+ `,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)
986
1053
  VALUES (?, ?, ?, ?, 'running', datetime('now'))
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:`
1054
+ 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 Er(e){await i().execute({sql:`
988
1055
  INSERT INTO harvest_attempts (
989
1056
  id, job_id, user_id, attempt_number, max_attempts, query, location, max_questions, status, created_at
990
1057
  )
991
1058
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'running', ?)
992
1059
  ON CONFLICT(job_id, attempt_number) DO NOTHING
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:`
1060
+ `,args:[N(),e.jobId,e.userId,e.attemptNumber,e.maxAttempts,e.query,e.location,e.maxQuestions,e.startedAt]})}async function lr(e){return(await i().execute({sql:`
994
1061
  UPDATE harvest_attempts SET
995
1062
  browser_provider = ?,
996
1063
  provider_session_id = ?,
@@ -1017,14 +1084,14 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1017
1084
  UPDATE harvest_attempts SET
1018
1085
  status = 'finished',
1019
1086
  outcome = ?,
1020
- kernel_session_id = ?,
1087
+ \u006b\u0065\u0072\u006e\u0065\u006c_session_id = ?,
1021
1088
  question_count = ?,
1022
1089
  duration_ms = ?,
1023
1090
  error = ?,
1024
1091
  will_retry = ?,
1025
- kernel_delete_started = ?,
1026
- kernel_delete_succeeded = ?,
1027
- kernel_delete_error = ?,
1092
+ \u006b\u0065\u0072\u006e\u0065\u006c_delete_started = ?,
1093
+ \u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded = ?,
1094
+ \u006b\u0065\u0072\u006e\u0065\u006c_delete_error = ?,
1028
1095
  browser_close_succeeded = ?,
1029
1096
  browser_close_error = ?,
1030
1097
  browser_provider = COALESCE(browser_provider, ?),
@@ -1056,7 +1123,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1056
1123
  debug_json = ?,
1057
1124
  completed_at = ?
1058
1125
  WHERE job_id = ? AND attempt_number = ?
1059
- `,args:[e.outcome,e.kernelSessionId,e.questionCount,e.durationMs,e.error,e.willRetry?1:0,e.kernelDeleteStarted?1:0,e.kernelDeleteSucceeded==null?null:e.kernelDeleteSucceeded?1:0,e.kernelDeleteError,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:`
1126
+ `,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:`
1060
1127
  UPDATE harvest_attempts SET
1061
1128
  provider_lookup_status = ?,
1062
1129
  provider_status = ?,
@@ -1071,12 +1138,12 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1071
1138
  WHERE id = ?
1072
1139
  AND job_id = ?
1073
1140
  AND user_id = ?
1074
- AND browser_provider = 'bright_data_browser_api'
1141
+ AND browser_provider = '\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api'
1075
1142
  AND provider_session_id = ?
1076
1143
  AND COALESCE(provider_lookup_status, '') <> 'complete'
1077
1144
  `,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:`
1078
1145
  SELECT * FROM harvest_attempts
1079
- WHERE browser_provider = 'bright_data_browser_api'
1146
+ WHERE browser_provider = '\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api'
1080
1147
  AND provider_session_id IS NOT NULL
1081
1148
  AND provider_lookup_status IN ('pending', 'temporary_error')
1082
1149
  ORDER BY COALESCE(provider_checked_at, created_at) ASC
@@ -1138,10 +1205,10 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1138
1205
  `,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:`
1139
1206
  INSERT INTO workflow_runs (id, user_id, schedule_id, workflow_id, input_json, idempotency_key, webhook_url, total_steps)
1140
1207
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
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:`
1208
+ `,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 Fr(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:`
1142
1209
  INSERT INTO workflow_artifacts (id, run_id, user_id, kind, label, path, content_type, bytes, rows_count, content)
1143
1210
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
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:`
1211
+ `,args:[N(),e,t,r.kind,r.label,r.path,dt(r.kind),r.bytes??null,r.rows??null,r.content??null]})}async function Mr(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 jr(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 Wr(e){await i().execute({sql:`
1145
1212
  INSERT INTO workflow_webhook_deliveries (
1146
1213
  id, run_id, schedule_id, user_id, webhook_url, status, attempts, last_error, delivered_at
1147
1214
  )
@@ -1220,7 +1287,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1220
1287
  SET options = json_set(options, '$.billingSettledAt', ?, '$.billedMc', ?)
1221
1288
  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
1289
  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)
1290
+ 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 Et(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 En(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 ln(){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=>Et(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 lt(e,Math.ceil(t/2))}async function lt(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)
1224
1291
  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)
1225
1292
  SELECT ?, ?, ?, 'subscription', ?, COALESCE(?, datetime('now', ?)), ?
1226
1293
  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
@@ -1271,22 +1338,22 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1271
1338
  WHERE remaining_mc > 0
1272
1339
  AND never_expires = 0
1273
1340
  AND expires_at <= datetime('now')
1274
- LIMIT 500`});if(t.rows.length===0)return{expired_lots:0,expired_mc:0};let r=[],n=[];for(let c of t.rows){let d=Number(c.id),E=N();r.push({token:E,insertResultIndex:n.length}),n.push({sql:`INSERT OR IGNORE INTO credit_lot_expirations (lot_id, user_id, amount_mc, claim_token)
1341
+ LIMIT 500`});if(t.rows.length===0)return{expired_lots:0,expired_mc:0};let r=[],n=[];for(let c of t.rows){let d=Number(c.id),l=N();r.push({token:l,insertResultIndex:n.length}),n.push({sql:`INSERT OR IGNORE INTO credit_lot_expirations (lot_id, user_id, amount_mc, claim_token)
1275
1342
  SELECT id, user_id, remaining_mc, ?
1276
1343
  FROM credit_lots
1277
1344
  WHERE id = ?
1278
1345
  AND remaining_mc > 0
1279
1346
  AND never_expires = 0
1280
- AND expires_at <= datetime('now')`,args:[E,d]}),n.push({sql:`UPDATE credit_lots
1347
+ AND expires_at <= datetime('now')`,args:[l,d]}),n.push({sql:`UPDATE credit_lots
1281
1348
  SET remaining_mc = 0
1282
1349
  WHERE id = ?
1283
1350
  AND EXISTS (
1284
1351
  SELECT 1 FROM credit_lot_expirations
1285
1352
  WHERE lot_id = ? AND claim_token = ?
1286
- )`,args:[d,d,E]}),n.push({sql:`INSERT INTO ledger (user_id, amount_mc, operation, description)
1353
+ )`,args:[d,d,l]}),n.push({sql:`INSERT INTO ledger (user_id, amount_mc, operation, description)
1287
1354
  SELECT user_id, -amount_mc, 'credit_expired', 'credits expired'
1288
1355
  FROM credit_lot_expirations
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
1356
+ WHERE lot_id = ? AND claim_token = ?`,args:[d,l]})}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
1290
1357
  FROM credit_lot_expirations
1291
1358
  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
1292
1359
  FROM users u
@@ -1294,16 +1361,16 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1294
1361
  WHERE l.created_at < ?
1295
1362
  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
1296
1363
  WHERE user_id = ? AND source = 'migration'
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)
1364
+ 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 l=await _.execute({sql:"SELECT subscription_tier FROM users WHERE id = ? LIMIT 1",args:[e]});u=String(l.rows[0]?.subscription_tier??"").startsWith("sonic")}let o=u?"9999-12-31 23:59:59":null;if(s){let l=[{sql:"INSERT OR IGNORE INTO ledger (user_id, amount_mc, operation, description, stripe_pi) VALUES (?, ?, ?, ?, ?)",args:[e,t,r,n??null,s]}];t>0&&l.push({sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires)
1298
1365
  SELECT ?, ?, ?, ?, ?, COALESCE(?, datetime('now', ?)), ?
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)
1366
+ WHERE changes() = 1`,args:[e,t,t,r,s,o,D,u?1:0]}),l.push({sql:"UPDATE users SET balance_mc = balance_mc + ? WHERE id = ? AND changes() = 1",args:[t,e]}),await _.batch(l,"write");let E=await _.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return Number(E.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 Fn(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)
1300
1367
  SELECT user_id, amount_mc, amount_mc, operation, NULL, COALESCE(?, datetime('now', ?)), ?
1301
1368
  FROM billing_credits
1302
1369
  WHERE idempotency_key = ? AND status = 'applying'`,args:[o,D,u?1:0,s]},{sql:`UPDATE users
1303
1370
  SET balance_mc = balance_mc + COALESCE((
1304
1371
  SELECT amount_mc FROM billing_credits WHERE idempotency_key = ? AND status = 'applying'
1305
1372
  ), 0)
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
1373
+ 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 E=(await _.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_credits WHERE idempotency_key = ? LIMIT 1",args:[s]})).rows[0];if(!E||Number(E.user_id)!==e||Number(E.amount_mc)!==t||String(E.operation)!==r||String(E.description)!==n)throw new Error("idempotent credit key conflicts with another credit");return{ok:String(E.status)==="applied",balance_mc:await c(),duplicate:d[1]?.rowsAffected===0&&String(E.status)==="applied"}}async function Mn(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
1307
1374
  SET balance_mc = balance_mc - ?
1308
1375
  WHERE id = ?
1309
1376
  AND balance_mc >= ?
@@ -1339,7 +1406,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1339
1406
  WHERE id IN (
1340
1407
  SELECT lot_id FROM billing_debit_allocations WHERE debit_idempotency_key = ?
1341
1408
  )
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,
1409
+ 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 E=(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(E&&Number(E.user_id)===e&&Number(E.amount_mc)===t&&String(E.operation)===r&&String(E.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}),l=async()=>{let T=(await _.execute({sql:`SELECT e.user_id,
1343
1410
  e.status,
1344
1411
  e.amount_mc AS final_amount_mc,
1345
1412
  e.billing_class,
@@ -1351,7 +1418,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1351
1418
  WHERE e.idempotency_key = ?
1352
1419
  AND d.user_id = e.user_id
1353
1420
  AND d.status = 'applied'
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 (
1421
+ 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 j=Number(T.held_amount_mc),w=Number(T.final_amount_mc);if(!Number.isSafeInteger(j)||!Number.isSafeInteger(w)||w<0||w>j)throw new Error("idempotent debit settlement receipt is invalid");let Ue=j-w,Q=await _.execute({sql:`WITH ordered AS (
1355
1422
  SELECT a.amount_mc,
1356
1423
  a.expires_at,
1357
1424
  COALESCE(SUM(a.amount_mc) OVER (
@@ -1367,7 +1434,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1367
1434
  )
1368
1435
  SELECT (SELECT COUNT(*) FROM ordered) AS allocation_count,
1369
1436
  COALESCE(SUM(CASE WHEN expires_at > ? THEN refund_mc ELSE 0 END), 0) AS credited_refund_mc
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
1437
+ 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}},E;try{E=await _.batch([{sql:`INSERT OR IGNORE INTO billing_events
1371
1438
  (id, user_id, idempotency_key, billing_class, source_surface, status, amount_mc, metadata)
1372
1439
  VALUES (?, ?, ?, ?, ?, 'settling', ?, ?)`,args:[c,e,u,o,a,r,d]},{sql:`WITH ordered AS (
1373
1440
  SELECT a.lot_id,
@@ -1475,7 +1542,7 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1475
1542
  WHERE refund_mc > 0`,args:[t,r,t,u,n,s]},{sql:`UPDATE billing_events
1476
1543
  SET status = 'settled', settled_at = datetime('now')
1477
1544
  WHERE idempotency_key = ?
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
1545
+ AND status = 'applying'`,args:[u]}],"write")}catch(g){try{let T=await l();if(T)return T}catch{}throw g}let m=await l();if(!m)throw new Error("idempotent debit settlement did not reach a durable settled state");return{...m,duplicate:E[0]?.rowsAffected===0}}async function jn(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 Wn(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
1546
  COALESCE(SUM(CASE WHEN amount_mc < 0 AND operation NOT IN (${s}) THEN -amount_mc ELSE 0 END), 0) AS spent_mc,
1480
1547
  COALESCE(SUM(CASE WHEN amount_mc > 0 AND operation IN (${s}) THEN amount_mc ELSE 0 END), 0) AS refunded_mc,
1481
1548
  COALESCE(SUM(CASE WHEN amount_mc > 0 AND operation IN (${a}) THEN amount_mc ELSE 0 END), 0) AS granted_mc,
@@ -1495,4 +1562,4 @@ import{createClient as Ve}from"@libsql/client/http";import{createHash as v,rando
1495
1562
  FROM users u
1496
1563
  LEFT JOIN credit_lots l ON l.user_id = u.id
1497
1564
  WHERE u.id = ?
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};
1565
+ 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,W 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,le 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,Ft as E,Mt as F,Pt as G,Ht as H,qt as I,jt as J,Wt 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,Er as ia,lr 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,Fr as La,Mr as Ma,Pr as Na,Hr as Oa,qr as Pa,ye as Qa,jr as Ra,Wr 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,En as mb,ln 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,lt 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,Fn as Ob,Mn as Pb,Pn as Qb,Hn as Rb,mt as Sb,qn as Tb,jn as Ub,Wn 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};