mcp-scraper 0.89.4 → 0.89.6

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 (44) hide show
  1. package/CHANGELOG.md +27 -1
  2. package/README.md +1 -1
  3. package/dist/{analytics-repository-5CAFUXYD.js → analytics-repository-4UA3WI3U.js} +1 -1
  4. package/dist/bin/api-server.js +1 -1
  5. package/dist/bin/mcp-scraper-cli.js +1 -1
  6. package/dist/bin/mcp-scraper-core.js +1 -1
  7. package/dist/bin/mcp-scraper-install.js +1 -1
  8. package/dist/bin/mcp-stdio-server.js +1 -1
  9. package/dist/bin/paa-harvest.js +1 -1
  10. package/dist/{chunk-K7KMLT33.js → chunk-3H7HU5JI.js} +1 -1
  11. package/dist/{chunk-J7EVLE6H.js → chunk-C6JXNOSF.js} +1 -1
  12. package/dist/chunk-CULFQBFR.js +1 -0
  13. package/dist/chunk-D6BTAT5Y.js +1 -0
  14. package/dist/{chunk-HYQDXTS7.js → chunk-FKSTNWP6.js} +1 -1
  15. package/dist/{chunk-DMCYIWB3.js → chunk-FVSXX43Z.js} +1 -1
  16. package/dist/{chunk-OBDMJCCF.js → chunk-G6GAIXXA.js} +2 -2
  17. package/dist/{chunk-CYOEMHTB.js → chunk-H2I63VAD.js} +1 -1
  18. package/dist/chunk-H3QW5U67.js +41 -0
  19. package/dist/chunk-ISZIA6NE.js +820 -0
  20. package/dist/{chunk-S7RA23GR.js → chunk-KKI2SNB2.js} +1 -1
  21. package/dist/{chunk-OXFWXWQG.js → chunk-PPOI4C3Q.js} +1 -1
  22. package/dist/{chunk-EN66HBAW.js → chunk-VZTFJLOK.js} +1 -1
  23. package/dist/{chunk-D4NOJAUN.js → chunk-WUVMD6ZX.js} +1 -1
  24. package/dist/{chunk-VEJQ4XPI.js → chunk-WXOLIRFJ.js} +1 -1
  25. package/dist/chunk-Y3ITV2OK.js +19 -0
  26. package/dist/{chunk-Z27SYWYD.js → chunk-YCZKKSTT.js} +1 -1
  27. package/dist/{chunk-Z66Z2HV4.js → chunk-YQ5U5C2X.js} +121 -73
  28. package/dist/{chunk-QN3QHTVK.js → chunk-Z45GM22P.js} +190 -190
  29. package/dist/db-IZ5UF33U.js +1 -0
  30. package/dist/{extract-bundle-TXH3VNXH.js → extract-bundle-BTZQJTYV.js} +1 -1
  31. package/dist/gmail-service-ZZDF52KK.js +1 -0
  32. package/dist/index.cjs +19 -19
  33. package/dist/index.js +1 -1
  34. package/dist/{lead-list-enrichment-repository-G7Z5DQZR.js → lead-list-enrichment-repository-K4H5DMSF.js} +1 -1
  35. package/dist/{location-data-repository-TEXZ3I2N.js → location-data-repository-KALKE3FG.js} +1 -1
  36. package/dist/{server-RORLM2FG.js → server-YVNOU3RK.js} +727 -1546
  37. package/dist/{site-extract-repository-MBSCAP4D.js → site-extract-repository-FTTIOWAL.js} +1 -1
  38. package/dist/stripe-event-worker-CURL3RYL.js +1 -0
  39. package/dist/{worker-SUCJKWU2.js → worker-MUHILD2W.js} +1 -1
  40. package/package.json +1 -1
  41. package/dist/chunk-2O3UYISB.js +0 -59
  42. package/dist/chunk-RNDORDA2.js +0 -1
  43. package/dist/db-NLGNTQC3.js +0 -1
  44. package/dist/gmail-service-J2DWSQJX.js +0 -1
@@ -1,4 +1,4 @@
1
- import{createClient as Be}from"@libsql/client/http";import{createHash as y,randomBytes as M,randomUUID as g,scryptSync as Te,timingSafeEqual as Ge}from"crypto";import{z as p}from"zod";var C="2026-06-26 21:58:03";var dt="Google returned a CAPTCHA. Run with --headless=false to re-warm the browser profile, then retry.",xe="This operation is temporarily unavailable. Please retry later.",ye=["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"],Ie=["request_aborted","captcha","location_mismatch","connection","timeout","extraction","concurrency_limit","unauthorized","forbidden","invalid_request","rate_limit","billing","service_unavailable"];function R(e){return e?JSON.stringify(e):null}function se(e){if(e==null)return null;try{let t=typeof e=="string"?JSON.parse(e):e;if(!t||typeof t!="object"||Array.isArray(t))return null;let r=t;if(typeof r.error_code!="string"||!ne.has(r.error_code))return null;let s=Pe({errorCode:r.error_code,errorType:r.error_type,retryable:r.retryable,retryAfterSeconds:r.retry_after_seconds,chargeStatus:r.charge_status,details:r.details});if(typeof r.message=="string"){let i=ie(r.message).trim().slice(0,1e3);i&&!/https?:\/\//i.test(i)&&(s.message=i)}return s}catch{return null}}var ne=new Set(ye),Ce=new Set(Ie),ke=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"]),Ue=12,De=500;function P(e){return typeof e=="string"&&ne.has(e)?e:"service_unavailable"}function ve(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t={};for(let[r,s]of Object.entries(e)){if(Object.keys(t).length>=Ue)break;if(ke.has(r))if(typeof s=="string"){if((r==="upgrade_url"||r==="topup_url")&&!Xe(s))continue;let i=ie(s).slice(0,De);i&&(t[r]=i)}else(typeof s=="number"&&Number.isFinite(s)||typeof s=="boolean"||s===null)&&(t[r]=s)}return Object.keys(t).length>0?t:void 0}function Xe(e){if(e.startsWith("/")&&!e.startsWith("//"))return!0;try{let t=new URL(e);return t.protocol==="https:"&&(t.hostname==="mcpscraper.dev"||t.hostname.endsWith(".mcpscraper.dev"))}catch{return!1}}function Me(e){let t=P(e);switch(t){case"captcha_exhausted":case"captcha_or_blocked":return"captcha";case"proxy_tunnel_failed":case"proxy_unavailable":case"response_lost":return"connection";case"harvest_timeout":case"mcp_request_timeout":return"timeout";case"concurrency_limit_exceeded":return"concurrency_limit";case"rate_limited":case"upstream_rate_limited":return"rate_limit";case"extraction_failed":case"page_not_found":case"page_forbidden":case"page_rate_limited":case"page_server_error":case"page_http_error":case"bot_check_unresolved":case"page_too_large":case"page_unreachable":case"browser_session_interrupted":case"site_export_not_found":case"site_export_format_unavailable":case"site_export_read_failed":case"site_export_image_not_found":return"extraction";case"image_url_invalid":case"image_url_not_https":case"image_host_unresolvable":case"image_host_blocked":case"image_redirect_invalid":case"image_source_unavailable":case"image_too_large":case"image_redirect_limit":case"image_base64_invalid":case"image_source_missing":case"image_source_ambiguous":case"image_source_type_invalid":case"image_artifact_not_found":case"image_page_too_large":case"page_image_not_found":case"page_image_candidates_unusable":case"image_format_unsupported":case"image_storage_unconfigured":case"featured_image_unhostable":return"invalid_request";case"insufficient_balance":return"billing";case"vendor_unavailable":case"mcp_http_error":return"service_unavailable";default:return t}}function Fe(e){switch(P(e)){case"request_aborted":return"The request was cancelled before it completed.";case"captcha_exhausted":case"captcha_or_blocked":return"The target site returned a verification challenge. Heavy traffic can temporarily increase these challenges; retry in a few minutes.";case"location_mismatch":return"The target site returned results for a different location. Please retry.";case"proxy_tunnel_failed":case"proxy_unavailable":return"The web request could not establish a working connection. Please retry later.";case"harvest_timeout":return"The request timed out before it completed. Please retry with a smaller request.";case"mcp_request_timeout":return"The MCP caller stopped waiting before a final response arrived. Durable work may still be running; continue with the returned Task or job handle instead of restarting it.";case"concurrency_limit_exceeded":return"The service is available, but this account has reached its parallel-operation limit. Wait for an active operation to finish or add capacity.";case"unauthorized":return"Authentication is required to perform this operation.";case"forbidden":return"This account does not have permission to perform this operation.";case"invalid_request":return"The request is invalid. Check the supplied inputs and try again.";case"rate_limited":return"This account is sending requests too quickly. Wait briefly and retry.";case"upstream_rate_limited":return"The connected provider is temporarily rate-limiting requests. Wait briefly and retry.";case"mcp_http_error":return"The API returned an unexpected HTTP response.";case"insufficient_balance":return"This account does not have enough Credits for the operation.";case"extraction_failed":return"The target could not be extracted. Please retry later.";case"response_lost":return"The connection was lost before the response arrived. The operation may have already completed and been billed on our side \u2014 check credits_info before retrying blind.";case"vendor_unavailable":return"MCP Scraper's internal browser services require MCP Scraper team attention. Servers or IPs are down until this is fixed \u2014 this is not caused by your request. Please retry in a few minutes.";case"page_not_found":return"The page could not be found. It may have been moved or deleted.";case"page_forbidden":return"The site refused the request.";case"page_rate_limited":return"The site is rate-limiting requests right now. Retrying after a short wait usually works.";case"page_server_error":return"The page's own server returned an error. This is on the target site's side, not something a retry here can fix.";case"page_http_error":return"The page returned an unexpected HTTP response.";case"bot_check_unresolved":return"This site has automated-traffic protection (a bot/CAPTCHA check) that could not be resolved in time. Some sites are simply not extractable this way.";case"page_too_large":return"The page is larger than we can safely process.";case"page_unreachable":return"The page did not respond in time, or the connection could not be completed.";case"browser_session_interrupted":return"The browser session closed before extraction completed. MCP Scraper will retry once with a fresh session; retry the request if this persists.";case"site_export_not_found":return"The site export or requested page was not found, expired, or does not belong to this account.";case"site_export_format_unavailable":return"That representation was not retained for this export page. Read the export manifest and request one of the formats marked available.";case"site_export_read_failed":return"The stored site export could not be read or did not pass its integrity check.";case"site_export_image_not_found":return"The requested site-export image was not found, expired, or does not belong to this account.";case"image_url_invalid":return"The image source is not a valid URL. Use a stable public HTTPS URL or inline image bytes.";case"image_url_not_https":return"Commons image sources must use a public HTTPS URL or inline image bytes.";case"image_host_unresolvable":return"The image host could not be resolved. Use a different stable public URL or inline image bytes.";case"image_host_blocked":return"The image source resolves to a network address Commons cannot fetch safely.";case"image_redirect_invalid":return"The image source redirected to an invalid or unsafe destination.";case"image_source_unavailable":return"The image source could not be fetched. Host a different stable public URL or provide inline image bytes.";case"image_too_large":return"The image exceeds the Commons image size limit.";case"image_redirect_limit":return"The image source exceeded the Commons redirect limit.";case"image_base64_invalid":return"The supplied inline image bytes are invalid.";case"image_source_missing":return"Provide exactly one of a public image or webpage URL, inline image bytes, or an owner-scoped image artifact.";case"image_source_ambiguous":return"Provide only one image source: sourceUrl, imageBase64, or artifactId.";case"image_source_type_invalid":return"Use sourceType only with inline image bytes or an owner-scoped image artifact.";case"image_artifact_not_found":return"The image artifact was not found, expired, or does not belong to this account.";case"image_page_too_large":return"The webpage is too large for bounded Commons image discovery.";case"page_image_not_found":return"The webpage did not expose a usable featured or content image.";case"page_image_candidates_unusable":return"The webpage exposed image candidates, but none returned supported public image bytes.";case"image_format_unsupported":return"Commons accepts JPEG, PNG, GIF, or WebP image bytes.";case"image_storage_unconfigured":return"Commons image storage is temporarily unavailable.";case"featured_image_unhostable":return"The required featured image could not be hosted for Commons publication.";default:return xe}}function Pe(e){let t=P(e.errorCode),r=typeof e.retryAfterSeconds=="number"&&Number.isFinite(e.retryAfterSeconds)?Math.max(1,Math.min(86400,Math.trunc(e.retryAfterSeconds))):void 0,s=e.chargeStatus==="not_charged"||e.chargeStatus==="refund_pending"||e.chargeStatus==="refunded"||e.chargeStatus==="charged"?e.chargeStatus:void 0,i=typeof e.errorType=="string"&&Ce.has(e.errorType)?e.errorType:void 0,a=ve(e.details);return{error_code:t,error_type:i??Me(t),message:Fe(t),retryable:e.retryable===!0,...r?{retry_after_seconds:r}:{},...s?{charge_status:s}:{},...a?{details:a}:{}}}function ie(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 z=class extends Error{constructor(r){super(`CAPTCHA detected. ${r}`);this.instructions=r}instructions;name="CaptchaError"},Q=class extends Error{constructor(r,s){super(r);this.cause=s}cause;name="ExtractionError"},Z=class extends Error{constructor(r){super(`Google Maps search did not reach a complete result state (${r})`);this.pageState=r}pageState;name="MapsSearchIncompletePageError"},ee=class extends Error{name="RequestAbortedError";constructor(t="Request aborted before harvest completed"){super(t)}},te=class extends Error{name="PaaInteractionInterruptedError"},re=class extends Error{name="LocationMismatchError";constructor(t="Google returned results for a different location than requested"){super(t)}};var f=["oauth_store_metadata","oauth_clients","oauth_client_redirect_uris","oauth_codes","oauth_code_exchanges","oauth_refresh_families","oauth_refresh_tokens","oauth_refresh_rotations","oauth_security_events","oauth_rate_limit_buckets"],O=["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"],ae={oauth_clients:"oauth_clients_legacy_raw",oauth_codes:"oauth_codes_legacy_raw",oauth_tokens:"oauth_tokens_legacy_raw"},b="strftime('%Y-%m-%dT%H:%M:%fZ','now')";async function h(e,t,r=!1){try{await e.execute(t)}catch(s){let i=s.code;if(!r||i!=="SQL_PARSE_ERROR")throw s}}var He=[`CREATE TABLE IF NOT EXISTS oauth_store_metadata (
1
+ import{createClient as Be}from"@libsql/client/http";import{createHash as C,randomBytes as P,randomUUID as g,scryptSync as Te,timingSafeEqual as Ge}from"crypto";import{z as p}from"zod";var k="2026-06-26 21:58:03";var dt="Google returned a CAPTCHA. Run with --headless=false to re-warm the browser profile, then retry.",xe="This operation is temporarily unavailable. Please retry later.",ye=["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"],Ie=["request_aborted","captcha","location_mismatch","connection","timeout","extraction","concurrency_limit","unauthorized","forbidden","invalid_request","rate_limit","billing","service_unavailable"];function A(e){return e?JSON.stringify(e):null}function se(e){if(e==null)return null;try{let t=typeof e=="string"?JSON.parse(e):e;if(!t||typeof t!="object"||Array.isArray(t))return null;let r=t;if(typeof r.error_code!="string"||!ne.has(r.error_code))return null;let s=Pe({errorCode:r.error_code,errorType:r.error_type,retryable:r.retryable,retryAfterSeconds:r.retry_after_seconds,chargeStatus:r.charge_status,details:r.details});if(typeof r.message=="string"){let i=ie(r.message).trim().slice(0,1e3);i&&!/https?:\/\//i.test(i)&&(s.message=i)}return s}catch{return null}}var ne=new Set(ye),Ce=new Set(Ie),Ue=new Set(["active","limit","operation","upgrade_url","topup_url","upgrade_command","slots_per_pack","pack_price_usd","balance_credits","required_credits","retry_guidance","http_status"]),ke=12,De=500;function W(e){return typeof e=="string"&&ne.has(e)?e:"service_unavailable"}function ve(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t={};for(let[r,s]of Object.entries(e)){if(Object.keys(t).length>=ke)break;if(Ue.has(r))if(typeof s=="string"){if((r==="upgrade_url"||r==="topup_url")&&!Xe(s))continue;let i=ie(s).slice(0,De);i&&(t[r]=i)}else(typeof s=="number"&&Number.isFinite(s)||typeof s=="boolean"||s===null)&&(t[r]=s)}return Object.keys(t).length>0?t:void 0}function Xe(e){if(e.startsWith("/")&&!e.startsWith("//"))return!0;try{let t=new URL(e);return t.protocol==="https:"&&(t.hostname==="mcpscraper.dev"||t.hostname.endsWith(".mcpscraper.dev"))}catch{return!1}}function Me(e){let t=W(e);switch(t){case"captcha_exhausted":case"captcha_or_blocked":return"captcha";case"proxy_tunnel_failed":case"proxy_unavailable":case"response_lost":return"connection";case"harvest_timeout":case"mcp_request_timeout":return"timeout";case"concurrency_limit_exceeded":return"concurrency_limit";case"rate_limited":case"upstream_rate_limited":return"rate_limit";case"extraction_failed":case"page_not_found":case"page_forbidden":case"page_rate_limited":case"page_server_error":case"page_http_error":case"bot_check_unresolved":case"page_too_large":case"page_unreachable":case"browser_session_interrupted":case"site_export_not_found":case"site_export_format_unavailable":case"site_export_read_failed":case"site_export_image_not_found":return"extraction";case"image_url_invalid":case"image_url_not_https":case"image_host_unresolvable":case"image_host_blocked":case"image_redirect_invalid":case"image_source_unavailable":case"image_too_large":case"image_redirect_limit":case"image_base64_invalid":case"image_source_missing":case"image_source_ambiguous":case"image_source_type_invalid":case"image_artifact_not_found":case"image_page_too_large":case"page_image_not_found":case"page_image_candidates_unusable":case"image_format_unsupported":case"image_storage_unconfigured":case"featured_image_unhostable":return"invalid_request";case"insufficient_balance":return"billing";case"vendor_unavailable":case"mcp_http_error":return"service_unavailable";default:return t}}function Fe(e){switch(W(e)){case"request_aborted":return"The request was cancelled before it completed.";case"captcha_exhausted":case"captcha_or_blocked":return"The target site returned a verification challenge. Heavy traffic can temporarily increase these challenges; retry in a few minutes.";case"location_mismatch":return"The target site returned results for a different location. Please retry.";case"proxy_tunnel_failed":case"proxy_unavailable":return"The web request could not establish a working connection. Please retry later.";case"harvest_timeout":return"The request timed out before it completed. Please retry with a smaller request.";case"mcp_request_timeout":return"The MCP caller stopped waiting before a final response arrived. Durable work may still be running; continue with the returned Task or job handle instead of restarting it.";case"concurrency_limit_exceeded":return"The service is available, but this account has reached its parallel-operation limit. Wait for an active operation to finish or add capacity.";case"unauthorized":return"Authentication is required to perform this operation.";case"forbidden":return"This account does not have permission to perform this operation.";case"invalid_request":return"The request is invalid. Check the supplied inputs and try again.";case"rate_limited":return"This account is sending requests too quickly. Wait briefly and retry.";case"upstream_rate_limited":return"The connected provider is temporarily rate-limiting requests. Wait briefly and retry.";case"mcp_http_error":return"The API returned an unexpected HTTP response.";case"insufficient_balance":return"This account does not have enough Credits for the operation.";case"extraction_failed":return"The target could not be extracted. Please retry later.";case"response_lost":return"The connection was lost before the response arrived. The operation may have already completed and been billed on our side \u2014 check credits_info before retrying blind.";case"vendor_unavailable":return"MCP Scraper's internal browser services require MCP Scraper team attention. Servers or IPs are down until this is fixed \u2014 this is not caused by your request. Please retry in a few minutes.";case"page_not_found":return"The page could not be found. It may have been moved or deleted.";case"page_forbidden":return"The site refused the request.";case"page_rate_limited":return"The site is rate-limiting requests right now. Retrying after a short wait usually works.";case"page_server_error":return"The page's own server returned an error. This is on the target site's side, not something a retry here can fix.";case"page_http_error":return"The page returned an unexpected HTTP response.";case"bot_check_unresolved":return"This site has automated-traffic protection (a bot/CAPTCHA check) that could not be resolved in time. Some sites are simply not extractable this way.";case"page_too_large":return"The page is larger than we can safely process.";case"page_unreachable":return"The page did not respond in time, or the connection could not be completed.";case"browser_session_interrupted":return"The browser session closed before extraction completed. MCP Scraper will retry once with a fresh session; retry the request if this persists.";case"site_export_not_found":return"The site export or requested page was not found, expired, or does not belong to this account.";case"site_export_format_unavailable":return"That representation was not retained for this export page. Read the export manifest and request one of the formats marked available.";case"site_export_read_failed":return"The stored site export could not be read or did not pass its integrity check.";case"site_export_image_not_found":return"The requested site-export image was not found, expired, or does not belong to this account.";case"image_url_invalid":return"The image source is not a valid URL. Use a stable public HTTPS URL or inline image bytes.";case"image_url_not_https":return"Commons image sources must use a public HTTPS URL or inline image bytes.";case"image_host_unresolvable":return"The image host could not be resolved. Use a different stable public URL or inline image bytes.";case"image_host_blocked":return"The image source resolves to a network address Commons cannot fetch safely.";case"image_redirect_invalid":return"The image source redirected to an invalid or unsafe destination.";case"image_source_unavailable":return"The image source could not be fetched. Host a different stable public URL or provide inline image bytes.";case"image_too_large":return"The image exceeds the Commons image size limit.";case"image_redirect_limit":return"The image source exceeded the Commons redirect limit.";case"image_base64_invalid":return"The supplied inline image bytes are invalid.";case"image_source_missing":return"Provide exactly one of a public image or webpage URL, inline image bytes, or an owner-scoped image artifact.";case"image_source_ambiguous":return"Provide only one image source: sourceUrl, imageBase64, or artifactId.";case"image_source_type_invalid":return"Use sourceType only with inline image bytes or an owner-scoped image artifact.";case"image_artifact_not_found":return"The image artifact was not found, expired, or does not belong to this account.";case"image_page_too_large":return"The webpage is too large for bounded Commons image discovery.";case"page_image_not_found":return"The webpage did not expose a usable featured or content image.";case"page_image_candidates_unusable":return"The webpage exposed image candidates, but none returned supported public image bytes.";case"image_format_unsupported":return"Commons accepts JPEG, PNG, GIF, or WebP image bytes.";case"image_storage_unconfigured":return"Commons image storage is temporarily unavailable.";case"featured_image_unhostable":return"The required featured image could not be hosted for Commons publication.";default:return xe}}function Pe(e){let t=W(e.errorCode),r=typeof e.retryAfterSeconds=="number"&&Number.isFinite(e.retryAfterSeconds)?Math.max(1,Math.min(86400,Math.trunc(e.retryAfterSeconds))):void 0,s=e.chargeStatus==="not_charged"||e.chargeStatus==="refund_pending"||e.chargeStatus==="refunded"||e.chargeStatus==="charged"?e.chargeStatus:void 0,i=typeof e.errorType=="string"&&Ce.has(e.errorType)?e.errorType:void 0,a=ve(e.details);return{error_code:t,error_type:i??Me(t),message:Fe(t),retryable:e.retryable===!0,...r?{retry_after_seconds:r}:{},...s?{charge_status:s}:{},...a?{details:a}:{}}}function ie(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 z=class extends Error{constructor(r){super(`CAPTCHA detected. ${r}`);this.instructions=r}instructions;name="CaptchaError"},Q=class extends Error{constructor(r,s){super(r);this.cause=s}cause;name="ExtractionError"},Z=class extends Error{constructor(r){super(`Google Maps search did not reach a complete result state (${r})`);this.pageState=r}pageState;name="MapsSearchIncompletePageError"},ee=class extends Error{name="RequestAbortedError";constructor(t="Request aborted before harvest completed"){super(t)}},te=class extends Error{name="PaaInteractionInterruptedError"},re=class extends Error{name="LocationMismatchError";constructor(t="Google returned results for a different location than requested"){super(t)}};var f=["oauth_store_metadata","oauth_clients","oauth_client_redirect_uris","oauth_codes","oauth_code_exchanges","oauth_refresh_families","oauth_refresh_tokens","oauth_refresh_rotations","oauth_security_events","oauth_rate_limit_buckets"],O=["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"],ae={oauth_clients:"oauth_clients_legacy_raw",oauth_codes:"oauth_codes_legacy_raw",oauth_tokens:"oauth_tokens_legacy_raw"},b="strftime('%Y-%m-%dT%H:%M:%fZ','now')";async function h(e,t,r=!1){try{await e.execute(t)}catch(s){let i=s.code;if(!r||i!=="SQL_PARSE_ERROR")throw s}}var He=[`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),
@@ -99,7 +99,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
99
99
  retain_until TEXT NOT NULL
100
100
  ) STRICT`,"CREATE INDEX IF NOT EXISTS oauth_clients_inactivity_idx ON oauth_clients(status, last_used_at, client_id)","CREATE INDEX IF NOT EXISTS oauth_codes_expiry_idx ON oauth_codes(expires_at, code_digest)","CREATE INDEX IF NOT EXISTS oauth_code_exchanges_replay_expiry_idx ON oauth_code_exchanges(replay_expires_at, code_digest)","CREATE INDEX IF NOT EXISTS oauth_refresh_families_lifecycle_idx ON oauth_refresh_families(status, expires_at, family_id)","CREATE INDEX IF NOT EXISTS oauth_refresh_families_user_status_idx ON oauth_refresh_families(user_id, status)","CREATE INDEX IF NOT EXISTS oauth_refresh_tokens_expiry_idx ON oauth_refresh_tokens(expires_at, family_id, generation)","CREATE INDEX IF NOT EXISTS oauth_refresh_rotations_replay_expiry_idx ON oauth_refresh_rotations(replay_expires_at, family_id, predecessor_generation)","CREATE INDEX IF NOT EXISTS oauth_security_events_retention_idx ON oauth_security_events(retain_until, event_id)"],oe=["CREATE INDEX IF NOT EXISTS oauth_clients_cleanup_idx ON oauth_clients(COALESCE(last_used_at,created_at), client_id)","CREATE INDEX IF NOT EXISTS oauth_codes_client_idx ON oauth_codes(client_id, code_digest)","CREATE INDEX IF NOT EXISTS oauth_refresh_families_client_idx ON oauth_refresh_families(client_id, family_id)",`CREATE INDEX IF NOT EXISTS oauth_refresh_families_cleanup_idx
101
101
  ON oauth_refresh_families(COALESCE(compromised_at,revoked_at,expires_at), family_id)
102
- WHERE status!='active'`],H=[`CREATE TABLE IF NOT EXISTS oauth_rate_limit_buckets (
102
+ WHERE status!='active'`],q=[`CREATE TABLE IF NOT EXISTS oauth_rate_limit_buckets (
103
103
  scope TEXT NOT NULL CHECK (length(scope) BETWEEN 1 AND 80),
104
104
  key_digest BLOB NOT NULL CHECK (typeof(key_digest) = 'blob' AND length(key_digest) = 32),
105
105
  window_start INTEGER NOT NULL CHECK (window_start >= 0),
@@ -109,7 +109,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
109
109
  updated_at TEXT NOT NULL DEFAULT (${b}),
110
110
  PRIMARY KEY (scope, key_digest, window_start, window_seconds)
111
111
  ) STRICT`,`CREATE INDEX IF NOT EXISTS oauth_rate_limit_buckets_expiry_idx
112
- ON oauth_rate_limit_buckets(expires_at, scope, key_digest, window_start, window_seconds)`],k=[...He,...oe,...H];async function qe(e){if(await h(e,"PRAGMA foreign_keys = ON"),await h(e,"PRAGMA busy_timeout = 5000",!0),(await e.execute("SELECT name FROM pragma_table_info('oauth_codes')")).rows.some(u=>String(u.name)==="code"))throw new Error("Legacy raw OAuth tables require the explicit maintenance-mode coexistence migration");let s=(await e.execute("SELECT 1 present FROM sqlite_master WHERE type='table' AND name='oauth_store_metadata'")).rows.length>0?await e.execute("SELECT schema_version FROM oauth_store_metadata WHERE id=1"):void 0,i=s?.rows[0]?.schema_version==null?void 0:Number(s.rows[0].schema_version);if(i!==void 0&&(!Number.isSafeInteger(i)||i<1||i>3))throw new Error("OAuth store schema version cannot be migrated by this runtime");let a=i===void 0?k:i===1?[...oe,...H]:i===2?H:[];for(let u of a)await e.execute(u);if(i!==void 0&&i<3&&(await e.execute({sql:`UPDATE oauth_store_metadata SET schema_version=?,updated_at=${b} WHERE id=1 AND schema_version=?`,args:[3,i]})).rowsAffected!==1)throw new Error("OAuth store schema version changed during migration");await h(e,"PRAGMA optimize",!0)}async function ue(e){await h(e,"PRAGMA foreign_keys = ON"),await h(e,"PRAGMA busy_timeout = 5000",!0);let t=await e.execute("SELECT name FROM pragma_table_info('oauth_codes')");if(!t.rows.some(a=>String(a.name)==="code")){let a=t.rows.some(u=>String(u.name)==="code_digest");return await qe(e),a?"current":"created"}if((await e.execute({sql:"SELECT name FROM sqlite_master WHERE type='table' AND name IN (?,?,?)",args:Object.values(ae)})).rows.length>0)throw new Error("Legacy OAuth archive names already exist; refusing ambiguous migration");let i=await e.transaction("write");try{for(let[a,u]of Object.entries(ae))(await i.execute({sql:"SELECT 1 present FROM sqlite_master WHERE type='table' AND name=?",args:[a]})).rows.length>0&&await i.execute({sql:`ALTER TABLE ${a} RENAME TO ${u}`,args:[]});for(let a of k)await i.execute({sql:a,args:[]});await i.commit()}finally{i.close()}return"archived_legacy"}var We={oauth_store_metadata:["id","store_id","schema_version","authority_epoch","authority_state","updated_at"],oauth_clients:["client_id","client_name","client_type","token_endpoint_auth_method","status","created_at","last_used_at","expires_at"],oauth_client_redirect_uris:["client_id","redirect_uri","redirect_kind"],oauth_codes:["code_digest","lookup_key_id","client_id","redirect_uri","code_challenge","challenge_method","user_id","scope","resource","issued_at","expires_at"],oauth_code_exchanges:["code_digest","request_fingerprint","client_id","family_id","grant_scope","grant_resource","scope","resource","sealed_refresh","sealed_nonce","sealed_tag","replay_key_id","completed_at","replay_expires_at"],oauth_refresh_families:["family_id","user_id","client_id","issuer","scope","resource","status","current_generation","created_at","expires_at","revoked_at","compromised_at"],oauth_refresh_tokens:["family_id","generation","token_digest","lookup_key_id","token_prefix","predecessor_generation","issued_at","expires_at","used_at","revoked_at"],oauth_refresh_rotations:["family_id","predecessor_generation","request_fingerprint","successor_generation","sealed_successor","sealed_nonce","sealed_tag","replay_key_id","rotated_at","replay_expires_at"],oauth_security_events:["event_id","family_id","event_type","reason_code","occurred_at","retain_until"],oauth_rate_limit_buckets:["scope","key_digest","window_start","window_seconds","count","expires_at","updated_at"]},je={oauth_clients_inactivity_idx:["status","last_used_at","client_id"],oauth_clients_cleanup_idx:[null,"client_id"],oauth_codes_expiry_idx:["expires_at","code_digest"],oauth_codes_client_idx:["client_id","code_digest"],oauth_code_exchanges_replay_expiry_idx:["replay_expires_at","code_digest"],oauth_refresh_families_lifecycle_idx:["status","expires_at","family_id"],oauth_refresh_families_user_status_idx:["user_id","status"],oauth_refresh_families_client_idx:["client_id","family_id"],oauth_refresh_families_cleanup_idx:[null,"family_id"],oauth_refresh_tokens_expiry_idx:["expires_at","family_id","generation"],oauth_refresh_rotations_replay_expiry_idx:["replay_expires_at","family_id","predecessor_generation"],oauth_security_events_retention_idx:["retain_until","event_id"],oauth_rate_limit_buckets_expiry_idx:["expires_at","scope","key_digest","window_start","window_seconds"]};async function ce(e){let t=await e.execute({sql:`SELECT name FROM sqlite_master WHERE type = 'table' AND name IN (${f.map(()=>"?").join(",")})`,args:[...f]}),r=await e.execute({sql:`SELECT name FROM sqlite_master WHERE type = 'index' AND name IN (${O.map(()=>"?").join(",")})`,args:[...O]}),s=new Set(t.rows.map(o=>String(o.name))),i=new Set(r.rows.map(o=>String(o.name))),a=await e.execute("PRAGMA foreign_keys"),u=[],c=o=>o.replace(/\bIF\s+NOT\s+EXISTS\b/gi,"").replace(/\s+/g," ").trim().toLowerCase();for(let o of f){if(!s.has(o))continue;let d=(await e.execute(`PRAGMA table_info('${o}')`)).rows.map(N=>String(N.name));JSON.stringify(d)!==JSON.stringify(We[o])&&u.push(`${o}:columns`);let E=await e.execute({sql:"SELECT sql FROM sqlite_master WHERE type='table' AND name=?",args:[o]}),l=String(E.rows[0]?.sql??""),m=k.find(N=>c(N).startsWith(`create table ${o} `));(!m||c(l)!==c(m))&&u.push(`${o}:definition`)}for(let o of O){if(!i.has(o))continue;let d=(await e.execute(`PRAGMA index_info('${o}')`)).rows.map(N=>N.name==null?null:String(N.name));JSON.stringify(d)!==JSON.stringify(je[o])&&u.push(`${o}:columns`);let E=await e.execute({sql:"SELECT sql FROM sqlite_master WHERE type='index' AND name=?",args:[o]}),l=String(E.rows[0]?.sql??""),m=k.find(N=>c(N).startsWith(`create index ${o} `));(!m||c(l)!==c(m))&&u.push(`${o}:definition`)}return{ok:f.every(o=>s.has(o))&&O.every(o=>i.has(o))&&Number(a.rows[0]?.foreign_keys??0)===1&&u.length===0,missingTables:f.filter(o=>!s.has(o)),missingIndexes:O.filter(o=>!i.has(o)),foreignKeysEnabled:Number(a.rows[0]?.foreign_keys??0)===1,problems:u}}var Ye=process.env.TURSO_DATABASE_URL??"file:./paa-api.db",Je=process.env.TURSO_AUTH_TOKEN,D=null,q="2026-08-27.1",_e="data-2026-07-28-site-extract-counters.1",de=["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","page_snapshots","password_reset_tokens","rate_limits","request_events","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"],le=["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","page_snapshots_user_checked_at","prt_user_id","request_events_created_at","request_events_user_created_at","scheduled_run_view_links_expiry","scheduled_run_view_links_owner_run","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"],Ee=["credit_lots_bounds_insert","credit_lots_bounds_update","credit_lots_one_migration_insert","credit_lots_one_migration_update"],$e={credit_lots:["never_expires"],harvest_attempts:["debug_json","browser_provider","provider_session_id","provider_session_observed_at","provider_lookup_status","provider_status","provider_error_code","provider_error_message","provider_reason_source","provider_duration_ms","provider_bandwidth_bytes","provider_captcha","provider_checked_at","provider_detail_json","provider_disconnect_observed","provider_disconnect_message"],jobs:["public_error_json"],oauth_tokens:["replaced_by","rotated_at"],site_extract_jobs:["attempted_urls","successful_urls","failed_urls","idempotency_key","request_fingerprint","dispatch_attempts","next_dispatch_at","dispatch_error","settlement_attempts","next_settlement_at","settlement_error","public_error_json"],stripe_events:["attempt_count","claim_token","last_error","status","updated_at"],users:["balance_mc","concurrency_stripe_sub_id","concurrency_pack_quantity","extra_concurrency_slots","key_active","memory_identity","memory_key","memory_plan","memory_provisioned","memory_subscription_id","password_hash","stripe_customer_id","subscription_concurrency","subscription_id","subscription_tier"],workshop_registrations:["field_notes_email_id","reminder_48h_email_id","reminder_24h_email_id","reminder_1h_email_id"],workflow_artifacts:["content"],workflow_runs:["step_index","step_log_json","step_state_json","total_steps","webhook_url"]};function U(e){return e.map(t=>`'${t.replaceAll("'","''")}'`).join(", ")}async function W(e){let t=[`(SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name IN (${U(de)})) = ${de.length}`,`(SELECT COUNT(*) FROM sqlite_master WHERE type = 'index' AND name IN (${U(le)})) = ${le.length}`,`(SELECT COUNT(*) FROM sqlite_master WHERE type = 'trigger' AND name IN (${U(Ee)})) = ${Ee.length}`,...Object.entries($e).map(([s,i])=>`(SELECT COUNT(*) FROM pragma_table_info('${s}') WHERE name IN (${U(i)})) = ${i.length}`)],r=await e.execute(`SELECT ${t.join(" AND ")} AS ready`);return Number(r.rows[0]?.ready??0)===1}async function Ke(e){await e.execute(`
112
+ ON oauth_rate_limit_buckets(expires_at, scope, key_digest, window_start, window_seconds)`],D=[...He,...oe,...q];async function We(e){if(await h(e,"PRAGMA foreign_keys = ON"),await h(e,"PRAGMA busy_timeout = 5000",!0),(await e.execute("SELECT name FROM pragma_table_info('oauth_codes')")).rows.some(u=>String(u.name)==="code"))throw new Error("Legacy raw OAuth tables require the explicit maintenance-mode coexistence migration");let s=(await e.execute("SELECT 1 present FROM sqlite_master WHERE type='table' AND name='oauth_store_metadata'")).rows.length>0?await e.execute("SELECT schema_version FROM oauth_store_metadata WHERE id=1"):void 0,i=s?.rows[0]?.schema_version==null?void 0:Number(s.rows[0].schema_version);if(i!==void 0&&(!Number.isSafeInteger(i)||i<1||i>3))throw new Error("OAuth store schema version cannot be migrated by this runtime");let a=i===void 0?D:i===1?[...oe,...q]:i===2?q:[];for(let u of a)await e.execute(u);if(i!==void 0&&i<3&&(await e.execute({sql:`UPDATE oauth_store_metadata SET schema_version=?,updated_at=${b} WHERE id=1 AND schema_version=?`,args:[3,i]})).rowsAffected!==1)throw new Error("OAuth store schema version changed during migration");await h(e,"PRAGMA optimize",!0)}async function ue(e){await h(e,"PRAGMA foreign_keys = ON"),await h(e,"PRAGMA busy_timeout = 5000",!0);let t=await e.execute("SELECT name FROM pragma_table_info('oauth_codes')");if(!t.rows.some(a=>String(a.name)==="code")){let a=t.rows.some(u=>String(u.name)==="code_digest");return await We(e),a?"current":"created"}if((await e.execute({sql:"SELECT name FROM sqlite_master WHERE type='table' AND name IN (?,?,?)",args:Object.values(ae)})).rows.length>0)throw new Error("Legacy OAuth archive names already exist; refusing ambiguous migration");let i=await e.transaction("write");try{for(let[a,u]of Object.entries(ae))(await i.execute({sql:"SELECT 1 present FROM sqlite_master WHERE type='table' AND name=?",args:[a]})).rows.length>0&&await i.execute({sql:`ALTER TABLE ${a} RENAME TO ${u}`,args:[]});for(let a of D)await i.execute({sql:a,args:[]});await i.commit()}finally{i.close()}return"archived_legacy"}var qe={oauth_store_metadata:["id","store_id","schema_version","authority_epoch","authority_state","updated_at"],oauth_clients:["client_id","client_name","client_type","token_endpoint_auth_method","status","created_at","last_used_at","expires_at"],oauth_client_redirect_uris:["client_id","redirect_uri","redirect_kind"],oauth_codes:["code_digest","lookup_key_id","client_id","redirect_uri","code_challenge","challenge_method","user_id","scope","resource","issued_at","expires_at"],oauth_code_exchanges:["code_digest","request_fingerprint","client_id","family_id","grant_scope","grant_resource","scope","resource","sealed_refresh","sealed_nonce","sealed_tag","replay_key_id","completed_at","replay_expires_at"],oauth_refresh_families:["family_id","user_id","client_id","issuer","scope","resource","status","current_generation","created_at","expires_at","revoked_at","compromised_at"],oauth_refresh_tokens:["family_id","generation","token_digest","lookup_key_id","token_prefix","predecessor_generation","issued_at","expires_at","used_at","revoked_at"],oauth_refresh_rotations:["family_id","predecessor_generation","request_fingerprint","successor_generation","sealed_successor","sealed_nonce","sealed_tag","replay_key_id","rotated_at","replay_expires_at"],oauth_security_events:["event_id","family_id","event_type","reason_code","occurred_at","retain_until"],oauth_rate_limit_buckets:["scope","key_digest","window_start","window_seconds","count","expires_at","updated_at"]},je={oauth_clients_inactivity_idx:["status","last_used_at","client_id"],oauth_clients_cleanup_idx:[null,"client_id"],oauth_codes_expiry_idx:["expires_at","code_digest"],oauth_codes_client_idx:["client_id","code_digest"],oauth_code_exchanges_replay_expiry_idx:["replay_expires_at","code_digest"],oauth_refresh_families_lifecycle_idx:["status","expires_at","family_id"],oauth_refresh_families_user_status_idx:["user_id","status"],oauth_refresh_families_client_idx:["client_id","family_id"],oauth_refresh_families_cleanup_idx:[null,"family_id"],oauth_refresh_tokens_expiry_idx:["expires_at","family_id","generation"],oauth_refresh_rotations_replay_expiry_idx:["replay_expires_at","family_id","predecessor_generation"],oauth_security_events_retention_idx:["retain_until","event_id"],oauth_rate_limit_buckets_expiry_idx:["expires_at","scope","key_digest","window_start","window_seconds"]};async function ce(e){let t=await e.execute({sql:`SELECT name FROM sqlite_master WHERE type = 'table' AND name IN (${f.map(()=>"?").join(",")})`,args:[...f]}),r=await e.execute({sql:`SELECT name FROM sqlite_master WHERE type = 'index' AND name IN (${O.map(()=>"?").join(",")})`,args:[...O]}),s=new Set(t.rows.map(o=>String(o.name))),i=new Set(r.rows.map(o=>String(o.name))),a=await e.execute("PRAGMA foreign_keys"),u=[],c=o=>o.replace(/\bIF\s+NOT\s+EXISTS\b/gi,"").replace(/\s+/g," ").trim().toLowerCase();for(let o of f){if(!s.has(o))continue;let d=(await e.execute(`PRAGMA table_info('${o}')`)).rows.map(N=>String(N.name));JSON.stringify(d)!==JSON.stringify(qe[o])&&u.push(`${o}:columns`);let E=await e.execute({sql:"SELECT sql FROM sqlite_master WHERE type='table' AND name=?",args:[o]}),l=String(E.rows[0]?.sql??""),m=D.find(N=>c(N).startsWith(`create table ${o} `));(!m||c(l)!==c(m))&&u.push(`${o}:definition`)}for(let o of O){if(!i.has(o))continue;let d=(await e.execute(`PRAGMA index_info('${o}')`)).rows.map(N=>N.name==null?null:String(N.name));JSON.stringify(d)!==JSON.stringify(je[o])&&u.push(`${o}:columns`);let E=await e.execute({sql:"SELECT sql FROM sqlite_master WHERE type='index' AND name=?",args:[o]}),l=String(E.rows[0]?.sql??""),m=D.find(N=>c(N).startsWith(`create index ${o} `));(!m||c(l)!==c(m))&&u.push(`${o}:definition`)}return{ok:f.every(o=>s.has(o))&&O.every(o=>i.has(o))&&Number(a.rows[0]?.foreign_keys??0)===1&&u.length===0,missingTables:f.filter(o=>!s.has(o)),missingIndexes:O.filter(o=>!i.has(o)),foreignKeysEnabled:Number(a.rows[0]?.foreign_keys??0)===1,problems:u}}var Ye=process.env.TURSO_DATABASE_URL??"file:./paa-api.db",Je=process.env.TURSO_AUTH_TOKEN,X=null,y="2026-09-18.1",_e="data-2026-07-28-site-extract-counters.1",de=["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","page_snapshots","password_reset_tokens","rate_limits","request_events","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"],le=["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","page_snapshots_user_checked_at","prt_user_id","request_events_created_at","request_events_user_created_at","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"],Ee=["credit_lots_bounds_insert","credit_lots_bounds_update","credit_lots_one_migration_insert","credit_lots_one_migration_update"],$e={credit_lots:["never_expires"],harvest_attempts:["debug_json","browser_provider","provider_session_id","provider_session_observed_at","provider_lookup_status","provider_status","provider_error_code","provider_error_message","provider_reason_source","provider_duration_ms","provider_bandwidth_bytes","provider_captcha","provider_checked_at","provider_detail_json","provider_disconnect_observed","provider_disconnect_message"],jobs:["public_error_json"],oauth_tokens:["replaced_by","rotated_at"],site_extract_jobs:["attempted_urls","successful_urls","failed_urls","idempotency_key","request_fingerprint","dispatch_attempts","next_dispatch_at","dispatch_error","settlement_attempts","next_settlement_at","settlement_error","public_error_json"],stripe_events:["attempt_count","claim_token","claimed_at","completed_at","event_type","last_error","last_error_code","next_attempt_at","received_at","status","stripe_created_at","updated_at"],users:["balance_mc","concurrency_stripe_sub_id","concurrency_pack_quantity","extra_concurrency_slots","key_active","memory_identity","memory_key","memory_plan","memory_provisioned","memory_subscription_id","password_hash","stripe_customer_id","subscription_concurrency","subscription_id","subscription_tier"],workshop_registrations:["field_notes_email_id","reminder_48h_email_id","reminder_24h_email_id","reminder_1h_email_id"],workflow_artifacts:["content"],workflow_runs:["step_index","step_log_json","step_state_json","total_steps","webhook_url"]};function v(e){return e.map(t=>`'${t.replaceAll("'","''")}'`).join(", ")}async function M(e){let t=[`(SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name IN (${v(de)})) = ${de.length}`,`(SELECT COUNT(*) FROM sqlite_master WHERE type = 'index' AND name IN (${v(le)})) = ${le.length}`,`(SELECT COUNT(*) FROM sqlite_master WHERE type = 'trigger' AND name IN (${v(Ee)})) = ${Ee.length}`,...Object.entries($e).map(([s,i])=>`(SELECT COUNT(*) FROM pragma_table_info('${s}') WHERE name IN (${v(i)})) = ${i.length}`)],r=await e.execute(`SELECT ${t.join(" AND ")} AS ready`);return Number(r.rows[0]?.ready??0)===1}async function Lt(e=n()){let t=!1;try{t=(await e.execute({sql:"SELECT 1 AS applied FROM schema_migrations WHERE version = ? LIMIT 1",args:[y]})).rows.length===1}catch(s){let i=s instanceof Error?s.message.toLowerCase():String(s).toLowerCase();if(!i.includes("no such table")||!i.includes("schema_migrations"))throw s}let r=t?await M(e):!1;return{coreSchemaVersion:y,migrationApplied:t,schemaReady:r}}async function Ke(e){await e.execute(`
113
113
  UPDATE site_extract_jobs SET
114
114
  attempted_urls = done_urls,
115
115
  successful_urls = (
@@ -146,12 +146,12 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
146
146
  AND attempted_urls = 0
147
147
  AND successful_urls = 0
148
148
  AND failed_urls = 0
149
- `)}async function j(e){(await e.execute({sql:"SELECT 1 AS applied FROM schema_migrations WHERE version = ? LIMIT 1",args:[_e]})).rows.length>0||(await Ke(e),await e.execute({sql:"INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",args:[_e]}))}function n(){return D||(D=Be({url:Ye,authToken:Je})),D}function Lt(e){D=e}async function St(e=n()){if(process.env.OAUTH_MAINTENANCE_MODE!=="true")throw new Error("Secured main OAuth schema migration requires OAUTH_MAINTENANCE_MODE=true");await ue(e)}async function Rt(e=n()){return ce(e)}async function At(e={}){let t=n(),r;try{r=await t.execute({sql:"SELECT 1 AS applied FROM schema_migrations WHERE version = ? LIMIT 1",args:[q]})}catch(s){let i=s instanceof Error?s.message.toLowerCase():String(s).toLowerCase();if(!i.includes("no such table")||!i.includes("schema_migrations"))throw s;await t.execute(`
149
+ `)}async function j(e){(await e.execute({sql:"SELECT 1 AS applied FROM schema_migrations WHERE version = ? LIMIT 1",args:[_e]})).rows.length>0||(await Ke(e),await e.execute({sql:"INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",args:[_e]}))}function n(){return X||(X=Be({url:Ye,authToken:Je})),X}function St(e){X=e}async function Rt(e=n()){if(process.env.OAUTH_MAINTENANCE_MODE!=="true")throw new Error("Secured main OAuth schema migration requires OAUTH_MAINTENANCE_MODE=true");await ue(e)}async function At(e=n()){return ce(e)}async function wt(e={}){let t=n(),r;try{r=await t.execute({sql:"SELECT 1 AS applied FROM schema_migrations WHERE version = ? LIMIT 1",args:[y]})}catch(s){let i=s instanceof Error?s.message.toLowerCase():String(s).toLowerCase();if(!i.includes("no such table")||!i.includes("schema_migrations"))throw s;await t.execute(`
150
150
  CREATE TABLE IF NOT EXISTS schema_migrations (
151
151
  version TEXT PRIMARY KEY,
152
152
  applied_at TEXT NOT NULL DEFAULT (datetime('now'))
153
153
  )
154
- `),r={rows:[]}}if(r.rows.length>0){if(!e.verifyCurrentSchema)return;if(await W(t)){e.runDataRepairs&&await j(t);return}}if(await W(t)){await j(t),await t.execute({sql:"INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",args:[q]});return}await t.execute(`
154
+ `),r={rows:[]}}if(r.rows.length>0){if(!e.verifyCurrentSchema)return;if(await M(t)){e.runDataRepairs&&await j(t);return}}if(await M(t)){await j(t),await t.execute({sql:"INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",args:[y]});return}await t.execute(`
155
155
  CREATE TABLE IF NOT EXISTS users (
156
156
  id INTEGER PRIMARY KEY AUTOINCREMENT,
157
157
  email TEXT UNIQUE NOT NULL,
@@ -645,19 +645,37 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
645
645
  status TEXT NOT NULL DEFAULT 'processed',
646
646
  attempt_count INTEGER NOT NULL DEFAULT 1,
647
647
  claim_token TEXT,
648
+ event_type TEXT,
649
+ stripe_created_at INTEGER,
650
+ received_at TEXT NOT NULL DEFAULT (datetime('now')),
651
+ claimed_at TEXT,
652
+ next_attempt_at TEXT,
653
+ completed_at TEXT,
648
654
  last_error TEXT,
655
+ last_error_code TEXT,
649
656
  processed_at TEXT NOT NULL DEFAULT (datetime('now')),
650
657
  updated_at TEXT NOT NULL DEFAULT (datetime('now'))
651
658
  )
652
- `);for(let s of["status TEXT NOT NULL DEFAULT 'processed'","attempt_count INTEGER NOT NULL DEFAULT 1","claim_token TEXT","last_error TEXT","updated_at TEXT"])try{await t.execute(`ALTER TABLE stripe_events ADD COLUMN ${s}`)}catch{}await t.execute(`
659
+ `);for(let s of["status TEXT NOT NULL DEFAULT 'processed'","attempt_count INTEGER NOT NULL DEFAULT 1","claim_token TEXT","event_type TEXT","stripe_created_at INTEGER","received_at TEXT","claimed_at TEXT","next_attempt_at TEXT","completed_at TEXT","last_error TEXT","last_error_code TEXT","updated_at TEXT"])try{await t.execute(`ALTER TABLE stripe_events ADD COLUMN ${s}`)}catch{}await t.execute(`
653
660
  UPDATE stripe_events
654
661
  SET updated_at = COALESCE(updated_at, processed_at),
655
- status = COALESCE(status, 'processed'),
656
- attempt_count = MAX(1, COALESCE(attempt_count, 1))
662
+ received_at = COALESCE(received_at, processed_at, updated_at, datetime('now')),
663
+ claimed_at = CASE WHEN status = 'processing' THEN COALESCE(claimed_at, updated_at, processed_at) ELSE claimed_at END,
664
+ next_attempt_at = CASE WHEN status = 'failed' THEN COALESCE(next_attempt_at, datetime('now')) ELSE next_attempt_at END,
665
+ completed_at = CASE WHEN status = 'processed' THEN COALESCE(completed_at, processed_at, updated_at) ELSE completed_at END,
666
+ status = CASE WHEN status = 'failed' THEN 'retryable' ELSE COALESCE(status, 'processed') END,
667
+ attempt_count = CASE WHEN status = 'pending' THEN MAX(0, COALESCE(attempt_count, 0)) ELSE MAX(1, COALESCE(attempt_count, 1)) END
657
668
  WHERE updated_at IS NULL
669
+ OR received_at IS NULL
658
670
  OR status IS NULL
671
+ OR status = 'failed'
672
+ OR (status = 'processing' AND claimed_at IS NULL)
673
+ OR (status = 'processed' AND completed_at IS NULL)
659
674
  OR attempt_count IS NULL
660
- OR attempt_count < 1
675
+ OR attempt_count < 0
676
+ `),await t.execute(`
677
+ CREATE INDEX IF NOT EXISTS stripe_events_due
678
+ ON stripe_events(status, next_attempt_at, claimed_at, received_at)
661
679
  `),await t.execute(`
662
680
  CREATE TABLE IF NOT EXISTS oauth_clients (
663
681
  client_id TEXT PRIMARY KEY,
@@ -762,45 +780,62 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
762
780
  `),await t.execute(`
763
781
  CREATE UNIQUE INDEX IF NOT EXISTS serp_identities_user_name
764
782
  ON serp_identities(user_id, name)
765
- `),!await W(t))throw new Error("core schema migration finished without all required tables, indexes, and columns");await j(t),await t.execute({sql:"INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",args:[q]})}async function wt(e,t,r){await n().execute({sql:"INSERT INTO oauth_clients (client_id, redirect_uris, name) VALUES (?, ?, ?)",args:[e,JSON.stringify(t),r]})}async function ft(e){let r=(await n().execute({sql:"SELECT * FROM oauth_clients WHERE client_id = ?",args:[e]})).rows[0];if(!r)return;let s=[];try{let i=JSON.parse(String(r.redirect_uris));Array.isArray(i)&&(s=i.filter(a=>typeof a=="string"))}catch{s=[]}return{client_id:String(r.client_id),redirect_uris:s,name:r.name!=null?String(r.name):null,created_at:String(r.created_at)}}async function Ot(e){await n().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 ht(e){let t=n(),s=(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]}),!!s)return{code:String(s.code),client_id:String(s.client_id),redirect_uri:String(s.redirect_uri),code_challenge:String(s.code_challenge),identity:String(s.identity),scope:String(s.scope),resource:s.resource!=null?String(s.resource):null,expires_at:String(s.expires_at)}}async function Ve(e){await n().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 xt(e){let r=(await n().execute({sql:"SELECT * FROM oauth_tokens WHERE refresh_token = ?",args:[e]})).rows[0];if(r)return{refresh_token:String(r.refresh_token),client_id:String(r.client_id),identity:String(r.identity),scope:String(r.scope),resource:r.resource!=null?String(r.resource):null,expires_at:String(r.expires_at),revoked:Number(r.revoked??0),replaced_by:r.replaced_by!=null?String(r.replaced_by):null,rotated_at:r.rotated_at!=null?String(r.rotated_at):null}}async function yt(e){await n().execute({sql:"UPDATE oauth_tokens SET revoked = 1 WHERE refresh_token = ?",args:[e]})}async function It(e,t){await Ve(t),await n().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 Ct(e){let t=g();if((await n().execute({sql:`INSERT INTO stripe_events
766
- (event_id, status, attempt_count, claim_token, last_error, processed_at, updated_at)
767
- VALUES (?, 'processing', 1, ?, NULL, datetime('now'), datetime('now'))
768
- ON CONFLICT(event_id) DO UPDATE SET
769
- status = 'processing',
770
- attempt_count = stripe_events.attempt_count + 1,
771
- claim_token = excluded.claim_token,
772
- last_error = NULL,
773
- updated_at = datetime('now')
774
- WHERE stripe_events.status = 'failed'
775
- OR (
776
- stripe_events.status = 'processing'
777
- AND stripe_events.updated_at <= datetime('now', '-10 minutes')
778
- )`,args:[e,t]})).rowsAffected>0)return{state:"claimed",token:t};let s=await n().execute({sql:"SELECT status FROM stripe_events WHERE event_id = ? LIMIT 1",args:[e]});return{state:String(s.rows[0]?.status)==="processed"?"processed":"processing"}}async function kt(e,t){return(await n().execute({sql:`UPDATE stripe_events
783
+ `),!await M(t))throw new Error("core schema migration finished without all required tables, indexes, and columns");await j(t),await t.execute({sql:"INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",args:[y]})}async function ft(e,t,r){await n().execute({sql:"INSERT INTO oauth_clients (client_id, redirect_uris, name) VALUES (?, ?, ?)",args:[e,JSON.stringify(t),r]})}async function Ot(e){let r=(await n().execute({sql:"SELECT * FROM oauth_clients WHERE client_id = ?",args:[e]})).rows[0];if(!r)return;let s=[];try{let i=JSON.parse(String(r.redirect_uris));Array.isArray(i)&&(s=i.filter(a=>typeof a=="string"))}catch{s=[]}return{client_id:String(r.client_id),redirect_uris:s,name:r.name!=null?String(r.name):null,created_at:String(r.created_at)}}async function ht(e){await n().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=n(),s=(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]}),!!s)return{code:String(s.code),client_id:String(s.client_id),redirect_uri:String(s.redirect_uri),code_challenge:String(s.code_challenge),identity:String(s.identity),scope:String(s.scope),resource:s.resource!=null?String(s.resource):null,expires_at:String(s.expires_at)}}async function Ve(e){await n().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 yt(e){let r=(await n().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 It(e){await n().execute({sql:"UPDATE oauth_tokens SET revoked = 1 WHERE refresh_token = ?",args:[e]})}async function Ct(e,t){await Ve(t),await n().execute({sql:"UPDATE oauth_tokens SET revoked = 1, replaced_by = ?, rotated_at = ? WHERE refresh_token = ?",args:[t.refresh_token,new Date().toISOString(),e]})}async function Ut(e,t,r){return(await n().execute({sql:`INSERT OR IGNORE INTO stripe_events
784
+ (event_id, event_type, stripe_created_at, status, attempt_count, received_at, next_attempt_at, processed_at, updated_at)
785
+ VALUES (?, ?, ?, 'pending', 0, datetime('now'), datetime('now'), datetime('now'), datetime('now'))`,args:[e,t,r]})).rowsAffected===1?"queued":"duplicate"}async function kt(e=50,t=300){let r=Math.max(1,Math.min(500,Math.trunc(e))),s=await n().execute({sql:`SELECT event_id
786
+ FROM stripe_events
787
+ WHERE (status IN ('pending', 'retryable') AND COALESCE(next_attempt_at, received_at) <= datetime('now'))
788
+ OR (status = 'processing' AND claimed_at <= datetime('now', '-' || ? || ' seconds'))
789
+ ORDER BY COALESCE(next_attempt_at, received_at), received_at
790
+ LIMIT ?`,args:[t,r]}),i=[];for(let a of s.rows){let u=String(a.event_id),c=g();if((await n().execute({sql:`UPDATE stripe_events
791
+ SET status = 'processing', attempt_count = attempt_count + 1,
792
+ claim_token = ?, claimed_at = datetime('now'), last_error = NULL,
793
+ last_error_code = NULL, updated_at = datetime('now')
794
+ WHERE event_id = ?
795
+ AND ((status IN ('pending', 'retryable') AND COALESCE(next_attempt_at, received_at) <= datetime('now'))
796
+ OR (status = 'processing' AND claimed_at <= datetime('now', '-' || ? || ' seconds')))`,args:[c,u,t]})).rowsAffected!==1)continue;let _=await n().execute({sql:"SELECT event_type, attempt_count FROM stripe_events WHERE event_id = ? LIMIT 1",args:[u]});i.push({eventId:u,eventType:_.rows[0]?.event_type!=null?String(_.rows[0].event_type):null,attemptCount:Number(_.rows[0]?.attempt_count??1),token:c})}return i}async function Dt(e,t){return(await n().execute({sql:`UPDATE stripe_events
779
797
  SET status = 'processed',
780
798
  claim_token = NULL,
799
+ claimed_at = NULL,
800
+ next_attempt_at = NULL,
801
+ completed_at = datetime('now'),
781
802
  last_error = NULL,
782
803
  processed_at = datetime('now'),
783
804
  updated_at = datetime('now')
784
- WHERE event_id = ? AND status = 'processing' AND claim_token = ?`,args:[e,t]})).rowsAffected===1}async function Ut(e,t,r){return(await n().execute({sql:`UPDATE stripe_events
785
- SET status = 'failed',
805
+ WHERE event_id = ? AND status = 'processing' AND claim_token = ?`,args:[e,t]})).rowsAffected===1}async function vt(e,t,r,s,i){return(await n().execute({sql:`UPDATE stripe_events
806
+ SET status = 'retryable',
786
807
  claim_token = NULL,
808
+ claimed_at = NULL,
787
809
  last_error = ?,
810
+ last_error_code = ?,
811
+ next_attempt_at = datetime('now', '+' || ? || ' seconds'),
788
812
  updated_at = datetime('now')
789
- WHERE event_id = ? AND status = 'processing' AND claim_token = ?`,args:[r.slice(0,500),e,t]})).rowsAffected===1}async function Dt(e){return(await n().execute({sql:"SELECT 1 FROM stripe_events WHERE event_id = ? AND status = 'processed' LIMIT 1",args:[e]})).rows.length>0}function pe(){return"sk_"+M(24).toString("hex")}function me(e){let t=M(16).toString("hex"),r=Te(e,t,64);return`${t}:${r.toString("hex")}`}function vt(e,t){let[r,s]=t.split(":"),i=Buffer.from(s,"hex"),a=Te(e,r,64);return Ge(i,a)}function L(e){return{id:Number(e.id),email:String(e.email),name:e.name!=null?String(e.name):null,api_key:String(e.api_key),key_active:Number(e.key_active??1),password_hash:e.password_hash!=null?String(e.password_hash):null,created_at:String(e.created_at),active:Number(e.active),stripe_customer_id:e.stripe_customer_id!=null?String(e.stripe_customer_id):null,balance_mc:Number(e.balance_mc??0),extra_concurrency_slots:Number(e.extra_concurrency_slots??0),concurrency_stripe_sub_id:e.concurrency_stripe_sub_id!=null?String(e.concurrency_stripe_sub_id):null,concurrency_pack_quantity:Number(e.concurrency_pack_quantity??0),subscription_concurrency:Number(e.subscription_concurrency??0),subscription_tier:e.subscription_tier!=null?String(e.subscription_tier):null,subscription_id:e.subscription_id!=null?String(e.subscription_id):null,memory_plan:e.memory_plan!=null?String(e.memory_plan):"free",memory_subscription_id:e.memory_subscription_id!=null?String(e.memory_subscription_id):null,memory_provisioned:Number(e.memory_provisioned??0)}}async function Xt(e){let t=await n().execute({sql:"SELECT * FROM users WHERE email = ? AND active = 1",args:[e]});return t.rows[0]?L(t.rows[0]):void 0}async function Mt(e){let t=await n().execute({sql:"SELECT * FROM users WHERE api_key = ? AND active = 1 AND key_active = 1",args:[e]});return t.rows[0]?L(t.rows[0]):void 0}async function Ft(e){let t=await n().execute({sql:"SELECT * FROM users WHERE id = ? AND active = 1",args:[e]});return t.rows[0]?L(t.rows[0]):void 0}async function Pt(e){let r=(await n().execute({sql:"SELECT memory_key, memory_identity FROM users WHERE id = ?",args:[e]})).rows[0];return{memory_key:r?.memory_key!=null?String(r.memory_key):null,memory_identity:r?.memory_identity!=null?String(r.memory_identity):null}}async function Ht(e,t,r){await n().execute({sql:"UPDATE users SET memory_key = ?, memory_identity = ? WHERE id = ?",args:[t,r,e]})}async function qt(e,t){await n().execute({sql:"UPDATE users SET password_hash = ? WHERE id = ?",args:[me(t),e]})}async function Wt(e){let t=n(),[r,s,i,a,u]=await Promise.all([t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ?",args:[e]}),t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'done'",args:[e]}),t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'failed'",args:[e]}),t.execute({sql:"SELECT COALESCE(SUM(json_extract(result, '$.totalQuestions')), 0) as n FROM jobs WHERE user_id = ? AND status = 'done'",args:[e]}),t.execute({sql:"SELECT MAX(created_at) as t FROM jobs WHERE user_id = ?",args:[e]})]);return{total:Number(r.rows[0]?.n??0),done:Number(s.rows[0]?.n??0),failed:Number(i.rows[0]?.n??0),totalQuestions:Number(a.rows[0]?.n??0),lastUsed:u.rows[0]?.t!=null?String(u.rows[0].t):null}}async function jt(e,t,r,s){let i=n(),a=pe(),u=r??M(6).toString("hex"),c=me(u);return{id:(await i.execute({sql:"INSERT INTO users (email, name, api_key, password_hash, stripe_customer_id) VALUES (?, ?, ?, ?, ?)",args:[e,t??null,a,c,s??null]})).lastInsertRowid,email:e,name:t,api_key:a,password:u}}async function Bt(e,t,r,s){let i=Math.floor(Date.now()/1e3),a=Math.floor(i/s)*s,u=y("sha256").update(t).digest("hex"),o=await n().execute({sql:`
813
+ WHERE event_id = ? AND status = 'processing' AND claim_token = ?`,args:[r.slice(0,500),s.slice(0,100),Math.max(0,Math.trunc(i)),e,t]})).rowsAffected===1}async function Xt(e,t,r,s){return(await n().execute({sql:`UPDATE stripe_events
814
+ SET status = 'dead_letter', claim_token = NULL, claimed_at = NULL,
815
+ last_error = ?, last_error_code = ?, next_attempt_at = NULL, updated_at = datetime('now')
816
+ WHERE event_id = ? AND status = 'processing' AND claim_token = ?`,args:[r.slice(0,500),s.slice(0,100),e,t]})).rowsAffected===1}async function Mt(){let t=(await n().execute(`
817
+ SELECT
818
+ SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) AS pending,
819
+ SUM(CASE WHEN status = 'processing' THEN 1 ELSE 0 END) AS processing,
820
+ SUM(CASE WHEN status = 'retryable' THEN 1 ELSE 0 END) AS retryable,
821
+ SUM(CASE WHEN status = 'dead_letter' THEN 1 ELSE 0 END) AS dead_letter,
822
+ MIN(CASE WHEN status IN ('pending', 'retryable') THEN COALESCE(next_attempt_at, received_at) END) AS oldest_due_at
823
+ FROM stripe_events
824
+ `)).rows[0];return{pending:Number(t?.pending??0),processing:Number(t?.processing??0),retryable:Number(t?.retryable??0),dead_letter:Number(t?.dead_letter??0),oldest_due_at:t?.oldest_due_at!=null?String(t.oldest_due_at):null}}async function Ft(e){return(await n().execute({sql:"SELECT 1 FROM stripe_events WHERE event_id = ? AND status = 'processed' LIMIT 1",args:[e]})).rows.length>0}function pe(){return"sk_"+P(24).toString("hex")}function me(e){let t=P(16).toString("hex"),r=Te(e,t,64);return`${t}:${r.toString("hex")}`}function Pt(e,t){let[r,s]=t.split(":"),i=Buffer.from(s,"hex"),a=Te(e,r,64);return Ge(i,a)}function L(e){return{id:Number(e.id),email:String(e.email),name:e.name!=null?String(e.name):null,api_key:String(e.api_key),key_active:Number(e.key_active??1),password_hash:e.password_hash!=null?String(e.password_hash):null,created_at:String(e.created_at),active:Number(e.active),stripe_customer_id:e.stripe_customer_id!=null?String(e.stripe_customer_id):null,balance_mc:Number(e.balance_mc??0),extra_concurrency_slots:Number(e.extra_concurrency_slots??0),concurrency_stripe_sub_id:e.concurrency_stripe_sub_id!=null?String(e.concurrency_stripe_sub_id):null,concurrency_pack_quantity:Number(e.concurrency_pack_quantity??0),subscription_concurrency:Number(e.subscription_concurrency??0),subscription_tier:e.subscription_tier!=null?String(e.subscription_tier):null,subscription_id:e.subscription_id!=null?String(e.subscription_id):null,memory_plan:e.memory_plan!=null?String(e.memory_plan):"free",memory_subscription_id:e.memory_subscription_id!=null?String(e.memory_subscription_id):null,memory_provisioned:Number(e.memory_provisioned??0)}}async function Ht(e){let t=await n().execute({sql:"SELECT * FROM users WHERE email = ? AND active = 1",args:[e]});return t.rows[0]?L(t.rows[0]):void 0}async function Wt(e){let t=await n().execute({sql:"SELECT * FROM users WHERE api_key = ? AND active = 1 AND key_active = 1",args:[e]});return t.rows[0]?L(t.rows[0]):void 0}async function qt(e){let t=await n().execute({sql:"SELECT * FROM users WHERE id = ? AND active = 1",args:[e]});return t.rows[0]?L(t.rows[0]):void 0}async function jt(e){let r=(await n().execute({sql:"SELECT memory_key, memory_identity FROM users WHERE id = ?",args:[e]})).rows[0];return{memory_key:r?.memory_key!=null?String(r.memory_key):null,memory_identity:r?.memory_identity!=null?String(r.memory_identity):null}}async function Bt(e,t,r){await n().execute({sql:"UPDATE users SET memory_key = ?, memory_identity = ? WHERE id = ?",args:[t,r,e]})}async function Gt(e,t){await n().execute({sql:"UPDATE users SET password_hash = ? WHERE id = ?",args:[me(t),e]})}async function Yt(e){let t=n(),[r,s,i,a,u]=await Promise.all([t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ?",args:[e]}),t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'done'",args:[e]}),t.execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND status = 'failed'",args:[e]}),t.execute({sql:"SELECT COALESCE(SUM(json_extract(result, '$.totalQuestions')), 0) as n FROM jobs WHERE user_id = ? AND status = 'done'",args:[e]}),t.execute({sql:"SELECT MAX(created_at) as t FROM jobs WHERE user_id = ?",args:[e]})]);return{total:Number(r.rows[0]?.n??0),done:Number(s.rows[0]?.n??0),failed:Number(i.rows[0]?.n??0),totalQuestions:Number(a.rows[0]?.n??0),lastUsed:u.rows[0]?.t!=null?String(u.rows[0].t):null}}async function Jt(e,t,r,s){let i=n(),a=pe(),u=r??P(6).toString("hex"),c=me(u);return{id:(await i.execute({sql:"INSERT INTO users (email, name, api_key, password_hash, stripe_customer_id) VALUES (?, ?, ?, ?, ?)",args:[e,t??null,a,c,s??null]})).lastInsertRowid,email:e,name:t,api_key:a,password:u}}async function $t(e,t,r,s){let i=Math.floor(Date.now()/1e3),a=Math.floor(i/s)*s,u=C("sha256").update(t).digest("hex"),o=await n().execute({sql:`
790
825
  INSERT INTO rate_limits (scope, key_hash, window_start, count)
791
826
  VALUES (?, ?, ?, 1)
792
827
  ON CONFLICT(scope, key_hash, window_start)
793
828
  DO UPDATE SET count = count + 1, updated_at = datetime('now')
794
829
  RETURNING count
795
- `,args:[e,u,a]}),_=Number(o.rows[0]?.count);if(!Number.isSafeInteger(_)||_<1)throw new Error("Rate-limit bucket mutation did not return a valid count");return{allowed:_<=r,count:_,remaining:Math.max(0,r-_),resetSeconds:Math.max(1,a+s-i)}}async function Gt(e){let t=M(32).toString("hex"),r=y("sha256").update(t).digest("hex"),s=new Date(Date.now()+3600*1e3).toISOString();return await n().execute({sql:"INSERT INTO password_reset_tokens (token, user_id, expires_at) VALUES (?, ?, ?)",args:[r,e,s]}),t}async function Yt(e){let t=n(),r=y("sha256").update(e).digest("hex"),i=(await t.execute({sql:"SELECT user_id, expires_at, used FROM password_reset_tokens WHERE token = ?",args:[r]})).rows[0];return!i||Number(i.used)||new Date(String(i.expires_at))<new Date?null:(await t.execute({sql:"UPDATE password_reset_tokens SET used = 1 WHERE token = ?",args:[r]}),Number(i.user_id))}async function Jt(e){let t=pe();return await n().execute({sql:"UPDATE users SET api_key = ?, key_active = 1 WHERE id = ?",args:[t,e]}),t}async function $t(e){await n().execute({sql:"UPDATE users SET key_active = 0 WHERE id = ?",args:[e]})}async function Kt(){return(await n().execute("SELECT id, email, name, created_at, active FROM users ORDER BY created_at DESC")).rows.map(t=>L({...t,api_key:"",key_active:1}))}async function Vt(e){await n().execute({sql:"UPDATE users SET active = 0 WHERE id = ?",args:[e]})}function A(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 x(e){return e==null?null:Number(e)===1}function v(e){if(e==null)return null;try{return JSON.parse(String(e))}catch{return null}}function ge(e){return{id:String(e.id),job_id:String(e.job_id),user_id:Number(e.user_id),attempt_number:Number(e.attempt_number),max_attempts:Number(e.max_attempts),query:String(e.query),location:e.location!=null?String(e.location):null,max_questions:Number(e.max_questions),status:String(e.status),outcome:e.outcome!=null?String(e.outcome):null,\u006b\u0065\u0072\u006e\u0065\u006c_session_id:e.\u006b\u0065\u0072\u006e\u0065\u006c_session_id!=null?String(e.\u006b\u0065\u0072\u006e\u0065\u006c_session_id):null,question_count:e.question_count!=null?Number(e.question_count):null,duration_ms:e.duration_ms!=null?Number(e.duration_ms):null,error:e.error!=null?String(e.error):null,will_retry:x(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:x(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:x(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:x(e.provider_captcha),provider_checked_at:e.provider_checked_at!=null?String(e.provider_checked_at):null,provider_detail:v(e.provider_detail_json),provider_disconnect_observed:x(e.provider_disconnect_observed),provider_disconnect_message:e.provider_disconnect_message!=null?String(e.provider_disconnect_message):null,debug:v(e.debug_json),created_at:String(e.created_at),completed_at:e.completed_at!=null?String(e.completed_at):null}}function I(e){let{public_error_json:t,...r}=e;return{...r,options:JSON.parse(e.options),result:e.result?JSON.parse(e.result):null,publicError:se(t)}}async function zt(e,t,r,s){let i=g();return await ze(i,e,t,r,s),i}async function ze(e,t,r,s,i){if(!/^[a-zA-Z0-9-]{1,100}$/.test(e))throw new Error("job id is invalid");await n().execute({sql:"INSERT INTO jobs (id, user_id, query, options, callback_url) VALUES (?, ?, ?, ?, ?)",args:[e,t,r,JSON.stringify(s),i??null]})}async function Qt(e,t,r){let s=g();return await n().execute({sql:"INSERT INTO jobs (id, user_id, query, options, status, started_at) VALUES (?, ?, ?, ?, 'running', datetime('now'))",args:[s,e,t,JSON.stringify(r)]}),s}async function Zt(e,t,r,s){let i=await n().execute({sql:`INSERT INTO jobs (id, user_id, query, options, status, started_at)
830
+ `,args:[e,u,a]}),_=Number(o.rows[0]?.count);if(!Number.isSafeInteger(_)||_<1)throw new Error("Rate-limit bucket mutation did not return a valid count");return{allowed:_<=r,count:_,remaining:Math.max(0,r-_),resetSeconds:Math.max(1,a+s-i)}}async function Kt(e){let t=P(32).toString("hex"),r=C("sha256").update(t).digest("hex"),s=new Date(Date.now()+3600*1e3).toISOString();return await n().execute({sql:"INSERT INTO password_reset_tokens (token, user_id, expires_at) VALUES (?, ?, ?)",args:[r,e,s]}),t}async function Vt(e){let t=n(),r=C("sha256").update(e).digest("hex"),i=(await t.execute({sql:"SELECT user_id, expires_at, used FROM password_reset_tokens WHERE token = ?",args:[r]})).rows[0];return!i||Number(i.used)||new Date(String(i.expires_at))<new Date?null:(await t.execute({sql:"UPDATE password_reset_tokens SET used = 1 WHERE token = ?",args:[r]}),Number(i.user_id))}async function zt(e){let t=pe();return await n().execute({sql:"UPDATE users SET api_key = ?, key_active = 1 WHERE id = ?",args:[t,e]}),t}async function Qt(e){await n().execute({sql:"UPDATE users SET key_active = 0 WHERE id = ?",args:[e]})}async function Zt(){return(await n().execute("SELECT id, email, name, created_at, active FROM users ORDER BY created_at DESC")).rows.map(t=>L({...t,api_key:"",key_active:1}))}async function er(e){await n().execute({sql:"UPDATE users SET active = 0 WHERE id = ?",args:[e]})}function w(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 x(e){return e==null?null:Number(e)===1}function F(e){if(e==null)return null;try{return JSON.parse(String(e))}catch{return null}}function ge(e){return{id:String(e.id),job_id:String(e.job_id),user_id:Number(e.user_id),attempt_number:Number(e.attempt_number),max_attempts:Number(e.max_attempts),query:String(e.query),location:e.location!=null?String(e.location):null,max_questions:Number(e.max_questions),status:String(e.status),outcome:e.outcome!=null?String(e.outcome):null,\u006b\u0065\u0072\u006e\u0065\u006c_session_id:e.\u006b\u0065\u0072\u006e\u0065\u006c_session_id!=null?String(e.\u006b\u0065\u0072\u006e\u0065\u006c_session_id):null,question_count:e.question_count!=null?Number(e.question_count):null,duration_ms:e.duration_ms!=null?Number(e.duration_ms):null,error:e.error!=null?String(e.error):null,will_retry:x(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:x(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:x(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:x(e.provider_captcha),provider_checked_at:e.provider_checked_at!=null?String(e.provider_checked_at):null,provider_detail:F(e.provider_detail_json),provider_disconnect_observed:x(e.provider_disconnect_observed),provider_disconnect_message:e.provider_disconnect_message!=null?String(e.provider_disconnect_message):null,debug:F(e.debug_json),created_at:String(e.created_at),completed_at:e.completed_at!=null?String(e.completed_at):null}}function U(e){let{public_error_json:t,...r}=e;return{...r,options:JSON.parse(e.options),result:e.result?JSON.parse(e.result):null,publicError:se(t)}}async function tr(e,t,r,s){let i=g();return await ze(i,e,t,r,s),i}async function ze(e,t,r,s,i){if(!/^[a-zA-Z0-9-]{1,100}$/.test(e))throw new Error("job id is invalid");await n().execute({sql:"INSERT INTO jobs (id, user_id, query, options, callback_url) VALUES (?, ?, ?, ?, ?)",args:[e,t,r,JSON.stringify(s),i??null]})}async function rr(e,t,r){let s=g();return await n().execute({sql:"INSERT INTO jobs (id, user_id, query, options, status, started_at) VALUES (?, ?, ?, ?, 'running', datetime('now'))",args:[s,e,t,JSON.stringify(r)]}),s}async function sr(e,t,r,s){let i=await n().execute({sql:`INSERT INTO jobs (id, user_id, query, options, status, started_at)
796
831
  VALUES (?, ?, ?, ?, 'running', datetime('now'))
797
- ON CONFLICT(id) DO NOTHING`,args:[e,t,r,JSON.stringify(s)]}),a=await be(e,t);if(!a)throw new Error(`getOrCreateRunningJob: row missing immediately after insert/lookup for ${e}`);return{job:a,created:i.rowsAffected===1}}async function er(e){await n().execute({sql:`
832
+ ON CONFLICT(id) DO NOTHING`,args:[e,t,r,JSON.stringify(s)]}),a=await be(e,t);if(!a)throw new Error(`getOrCreateRunningJob: row missing immediately after insert/lookup for ${e}`);return{job:a,created:i.rowsAffected===1}}async function nr(e){await n().execute({sql:`
798
833
  INSERT INTO harvest_attempts (
799
834
  id, job_id, user_id, attempt_number, max_attempts, query, location, max_questions, status, created_at
800
835
  )
801
836
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'running', ?)
802
837
  ON CONFLICT(job_id, attempt_number) DO NOTHING
803
- `,args:[g(),e.jobId,e.userId,e.attemptNumber,e.maxAttempts,e.query,e.location,e.maxQuestions,e.startedAt]})}async function tr(e){return(await n().execute({sql:`
838
+ `,args:[g(),e.jobId,e.userId,e.attemptNumber,e.maxAttempts,e.query,e.location,e.maxQuestions,e.startedAt]})}async function ir(e){return(await n().execute({sql:`
804
839
  UPDATE harvest_attempts SET
805
840
  browser_provider = ?,
806
841
  provider_session_id = ?,
@@ -810,7 +845,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
810
845
  ELSE 'pending'
811
846
  END
812
847
  WHERE job_id = ? AND attempt_number = ? AND status = 'running'
813
- `,args:[e.browserProvider,e.providerSessionId,e.observedAt,e.jobId,e.attemptNumber]})).rowsAffected===1}async function rr(e,t,r=new Date().toISOString()){return(await n().execute({sql:`
848
+ `,args:[e.browserProvider,e.providerSessionId,e.observedAt,e.jobId,e.attemptNumber]})).rowsAffected===1}async function ar(e,t,r=new Date().toISOString()){return(await n().execute({sql:`
814
849
  UPDATE harvest_attempts SET
815
850
  status = 'finished',
816
851
  outcome = COALESCE(outcome, 'timeout'),
@@ -823,7 +858,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
823
858
  provider_reason_source = COALESCE(provider_reason_source, 'client_runtime'),
824
859
  completed_at = COALESCE(completed_at, ?)
825
860
  WHERE job_id = ? AND status = 'running'
826
- `,args:[r,t?1:0,r,e]})).rowsAffected}async function sr(e){await n().execute({sql:`
861
+ `,args:[r,t?1:0,r,e]})).rowsAffected}async function or(e){await n().execute({sql:`
827
862
  UPDATE harvest_attempts SET
828
863
  status = 'finished',
829
864
  outcome = ?,
@@ -866,7 +901,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
866
901
  debug_json = ?,
867
902
  completed_at = ?
868
903
  WHERE job_id = ? AND attempt_number = ?
869
- `,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:Ne(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 Ne(e,t=4096){let r=JSON.stringify(e);return r.length<=t?r:JSON.stringify({truncated:!0})}async function nr(e){return(await n().execute({sql:`
904
+ `,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:Ne(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 Ne(e,t=4096){let r=JSON.stringify(e);return r.length<=t?r:JSON.stringify({truncated:!0})}async function ur(e){return(await n().execute({sql:`
870
905
  UPDATE harvest_attempts SET
871
906
  provider_lookup_status = ?,
872
907
  provider_status = ?,
@@ -884,20 +919,20 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
884
919
  AND browser_provider = '\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api'
885
920
  AND provider_session_id = ?
886
921
  AND COALESCE(provider_lookup_status, '') <> 'complete'
887
- `,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:Ne(e.detail),e.attemptId,e.jobId,e.userId,e.providerSessionId]})).rowsAffected===1}async function ir(e=25){let t=Math.max(1,Math.min(100,Math.trunc(e)));return(await n().execute({sql:`
922
+ `,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:Ne(e.detail),e.attemptId,e.jobId,e.userId,e.providerSessionId]})).rowsAffected===1}async function cr(e=25){let t=Math.max(1,Math.min(100,Math.trunc(e)));return(await n().execute({sql:`
888
923
  SELECT * FROM harvest_attempts
889
924
  WHERE browser_provider = '\u0062\u0072\u0069\u0067\u0068\u0074_\u0064\u0061\u0074\u0061_browser_api'
890
925
  AND provider_session_id IS NOT NULL
891
926
  AND provider_lookup_status IN ('pending', 'temporary_error')
892
927
  ORDER BY COALESCE(provider_checked_at, created_at) ASC
893
928
  LIMIT ?
894
- `,args:[t]})).rows.map(s=>ge(s))}async function ar(e,t){return(t==null?await n().execute({sql:"SELECT * FROM harvest_attempts WHERE job_id = ? ORDER BY attempt_number ASC",args:[e]}):await n().execute({sql:`
929
+ `,args:[t]})).rows.map(s=>ge(s))}async function _r(e,t){return(t==null?await n().execute({sql:"SELECT * FROM harvest_attempts WHERE job_id = ? ORDER BY attempt_number ASC",args:[e]}):await n().execute({sql:`
895
930
  SELECT ha.*
896
931
  FROM harvest_attempts ha
897
932
  INNER JOIN jobs j ON j.id = ha.job_id
898
933
  WHERE ha.job_id = ? AND j.user_id = ?
899
934
  ORDER BY ha.attempt_number ASC
900
- `,args:[e,t]})).rows.map(s=>ge(s))}async function be(e,t){let r=n(),s=t?await r.execute({sql:"SELECT * FROM jobs WHERE id = ? AND user_id = ?",args:[e,t]}):await r.execute({sql:"SELECT * FROM jobs WHERE id = ?",args:[e]});return s.rows[0]?I(A(s.rows[0])):void 0}async function or(e){return(await n().execute({sql:"SELECT * FROM jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50",args:[e]})).rows.map(r=>I(A(r)))}async function ur(e,t){let s=(await n().execute({sql:"SELECT content_hash, content, title, content_bytes, truncated, checked_at FROM page_snapshots WHERE user_id = ? AND url = ?",args:[e,t]})).rows[0];return s?{contentHash:String(s.content_hash),content:String(s.content),title:s.title==null?null:String(s.title),contentBytes:Number(s.content_bytes),truncated:Number(s.truncated)===1,checkedAt:String(s.checked_at)}:null}async function cr(e,t,r){await n().execute({sql:`
935
+ `,args:[e,t]})).rows.map(s=>ge(s))}async function be(e,t){let r=n(),s=t?await r.execute({sql:"SELECT * FROM jobs WHERE id = ? AND user_id = ?",args:[e,t]}):await r.execute({sql:"SELECT * FROM jobs WHERE id = ?",args:[e]});return s.rows[0]?U(w(s.rows[0])):void 0}async function dr(e){return(await n().execute({sql:"SELECT * FROM jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50",args:[e]})).rows.map(r=>U(w(r)))}async function lr(e,t){let s=(await n().execute({sql:"SELECT content_hash, content, title, content_bytes, truncated, checked_at FROM page_snapshots WHERE user_id = ? AND url = ?",args:[e,t]})).rows[0];return s?{contentHash:String(s.content_hash),content:String(s.content),title:s.title==null?null:String(s.title),contentBytes:Number(s.content_bytes),truncated:Number(s.truncated)===1,checkedAt:String(s.checked_at)}:null}async function Er(e,t,r){await n().execute({sql:`
901
936
  INSERT INTO page_snapshots (user_id, url, content_hash, content, title, content_bytes, truncated, checked_at)
902
937
  VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'))
903
938
  ON CONFLICT(user_id, url) DO UPDATE SET
@@ -907,56 +942,56 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
907
942
  content_bytes = excluded.content_bytes,
908
943
  truncated = excluded.truncated,
909
944
  checked_at = excluded.checked_at
910
- `,args:[e,t,r.contentHash,r.content,r.title,r.contentBytes,r.truncated?1:0]})}var Qe=32*1024;function Ze(e){if(e==null)return null;let t=JSON.stringify(e),r=Buffer.byteLength(t,"utf8");return r<=Qe?t:JSON.stringify({truncated:!0,originalBytes:r,sha256:y("sha256").update(t).digest("hex")})}function et(e){let t=e.result!=null?String(e.result):null;return{id:String(e.id),user_id:Number(e.user_id),source:String(e.source),status:String(e.status),query:String(e.query),location:e.location!=null?String(e.location):null,result_count:e.result_count!=null?Number(e.result_count):null,result:t?JSON.parse(t):null,error:e.error!=null?String(e.error):null,created_at:String(e.created_at)}}async function _r(e){let t=g();return await n().execute({sql:`
945
+ `,args:[e,t,r.contentHash,r.content,r.title,r.contentBytes,r.truncated?1:0]})}var Qe=32*1024;function Ze(e){if(e==null)return null;let t=JSON.stringify(e),r=Buffer.byteLength(t,"utf8");return r<=Qe?t:JSON.stringify({truncated:!0,originalBytes:r,sha256:C("sha256").update(t).digest("hex")})}function et(e){let t=e.result!=null?String(e.result):null;return{id:String(e.id),user_id:Number(e.user_id),source:String(e.source),status:String(e.status),query:String(e.query),location:e.location!=null?String(e.location):null,result_count:e.result_count!=null?Number(e.result_count):null,result:t?JSON.parse(t):null,error:e.error!=null?String(e.error):null,created_at:String(e.created_at)}}async function Tr(e){let t=g();return await n().execute({sql:`
911
946
  INSERT INTO request_events (id, user_id, source, status, query, location, result_count, result, error)
912
947
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
913
- `,args:[t,e.userId,e.source,e.status,e.query,e.location??null,e.resultCount??null,Ze(e.result),e.error??null]}),t}async function dr(e,t=100){return(await n().execute({sql:`
948
+ `,args:[t,e.userId,e.source,e.status,e.query,e.location??null,e.resultCount??null,Ze(e.result),e.error??null]}),t}async function pr(e,t=100){return(await n().execute({sql:`
914
949
  SELECT id, user_id, source, status, query, location, result_count, NULL AS result, error, created_at
915
950
  FROM request_events
916
951
  WHERE user_id = ?
917
952
  ORDER BY created_at DESC
918
953
  LIMIT ?
919
- `,args:[e,t]})).rows.map(s=>et(s))}function Le(e){if(e==null)return{};try{let t=JSON.parse(String(e));return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}catch{return{}}}function G(e){return{id:String(e.id),user_id:Number(e.user_id),workflow_id:String(e.workflow_id),name:String(e.name),input:Le(e.input_json),cadence:String(e.cadence),cron_expr:e.cron_expr!=null?String(e.cron_expr):null,timezone:String(e.timezone??"UTC"),webhook_url:e.webhook_url!=null?String(e.webhook_url):null,status:String(e.status),next_run_at:e.next_run_at!=null?String(e.next_run_at):null,last_run_at:e.last_run_at!=null?String(e.last_run_at):null,created_at:String(e.created_at),updated_at:String(e.updated_at)}}function Y(e){return{id:String(e.id),user_id:Number(e.user_id),schedule_id:e.schedule_id!=null?String(e.schedule_id):null,workflow_id:String(e.workflow_id),input:Le(e.input_json),status:String(e.status),manifest:e.manifest_json!=null?v(e.manifest_json):null,error_message:e.error_message!=null?String(e.error_message):null,queued_at:String(e.queued_at),started_at:e.started_at!=null?String(e.started_at):null,completed_at:e.completed_at!=null?String(e.completed_at):null,idempotency_key:e.idempotency_key!=null?String(e.idempotency_key):null,step_index:e.step_index!=null?Number(e.step_index):0,total_steps:e.total_steps!=null?Number(e.total_steps):null,step_log:Se(e.step_log_json),webhook_url:e.webhook_url!=null?String(e.webhook_url):null}}function Se(e){if(e==null)return[];try{let t=JSON.parse(String(e));return Array.isArray(t)?t:[]}catch{return[]}}function Re(e){return{id:String(e.id),run_id:String(e.run_id),user_id:Number(e.user_id),kind:String(e.kind),label:String(e.label),path:String(e.path),content_type:String(e.content_type),bytes:e.bytes!=null?Number(e.bytes):null,rows_count:e.rows_count!=null?Number(e.rows_count):null,content:e.content!=null?String(e.content):null,created_at:String(e.created_at)}}async function lr(e){let t=g();await n().execute({sql:`
954
+ `,args:[e,t]})).rows.map(s=>et(s))}function Le(e){if(e==null)return{};try{let t=JSON.parse(String(e));return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}catch{return{}}}function G(e){return{id:String(e.id),user_id:Number(e.user_id),workflow_id:String(e.workflow_id),name:String(e.name),input:Le(e.input_json),cadence:String(e.cadence),cron_expr:e.cron_expr!=null?String(e.cron_expr):null,timezone:String(e.timezone??"UTC"),webhook_url:e.webhook_url!=null?String(e.webhook_url):null,status:String(e.status),next_run_at:e.next_run_at!=null?String(e.next_run_at):null,last_run_at:e.last_run_at!=null?String(e.last_run_at):null,created_at:String(e.created_at),updated_at:String(e.updated_at)}}function Y(e){return{id:String(e.id),user_id:Number(e.user_id),schedule_id:e.schedule_id!=null?String(e.schedule_id):null,workflow_id:String(e.workflow_id),input:Le(e.input_json),status:String(e.status),manifest:e.manifest_json!=null?F(e.manifest_json):null,error_message:e.error_message!=null?String(e.error_message):null,queued_at:String(e.queued_at),started_at:e.started_at!=null?String(e.started_at):null,completed_at:e.completed_at!=null?String(e.completed_at):null,idempotency_key:e.idempotency_key!=null?String(e.idempotency_key):null,step_index:e.step_index!=null?Number(e.step_index):0,total_steps:e.total_steps!=null?Number(e.total_steps):null,step_log:Se(e.step_log_json),webhook_url:e.webhook_url!=null?String(e.webhook_url):null}}function Se(e){if(e==null)return[];try{let t=JSON.parse(String(e));return Array.isArray(t)?t:[]}catch{return[]}}function Re(e){return{id:String(e.id),run_id:String(e.run_id),user_id:Number(e.user_id),kind:String(e.kind),label:String(e.label),path:String(e.path),content_type:String(e.content_type),bytes:e.bytes!=null?Number(e.bytes):null,rows_count:e.rows_count!=null?Number(e.rows_count):null,content:e.content!=null?String(e.content):null,created_at:String(e.created_at)}}async function mr(e){let t=g();await n().execute({sql:`
920
955
  INSERT INTO workflow_schedules (
921
956
  id, user_id, workflow_id, name, input_json, cadence, timezone, webhook_url, next_run_at
922
957
  )
923
958
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
924
- `,args:[t,e.userId,e.workflowId,e.name,JSON.stringify(e.workflowInput),e.cadence,e.timezone??"UTC",e.webhookUrl??null,e.nextRunAt??null]});let r=await B(t,e.userId);if(!r)throw new Error("Failed to create workflow schedule");return r}async function B(e,t){let r=t==null?await n().execute({sql:"SELECT * FROM workflow_schedules WHERE id = ? AND status != ? LIMIT 1",args:[e,"deleted"]}):await n().execute({sql:"SELECT * FROM workflow_schedules WHERE id = ? AND user_id = ? AND status != ? LIMIT 1",args:[e,t,"deleted"]});return r.rows[0]?G(r.rows[0]):null}async function Er(e){return(await n().execute({sql:"SELECT * FROM workflow_schedules WHERE user_id = ? AND status != 'deleted' ORDER BY created_at DESC LIMIT 100",args:[e]})).rows.map(r=>G(r))}async function Tr(e){let t=[],r=[];return e.name!==void 0&&(t.push("name = ?"),r.push(e.name)),e.status!==void 0&&(t.push("status = ?"),r.push(e.status)),e.workflowInput!==void 0&&(t.push("input_json = ?"),r.push(JSON.stringify(e.workflowInput))),e.cadence!==void 0&&(t.push("cadence = ?"),r.push(e.cadence)),e.timezone!==void 0&&(t.push("timezone = ?"),r.push(e.timezone)),e.webhookUrl!==void 0&&(t.push("webhook_url = ?"),r.push(e.webhookUrl)),e.nextRunAt!==void 0&&(t.push("next_run_at = ?"),r.push(e.nextRunAt)),t.length===0||(t.push("updated_at = datetime('now')"),await n().execute({sql:`UPDATE workflow_schedules SET ${t.join(", ")} WHERE id = ? AND user_id = ? AND status != 'deleted'`,args:[...r,e.id,e.userId]})),B(e.id,e.userId)}async function pr(e,t){return(await n().execute({sql:"UPDATE workflow_schedules SET status = 'deleted', updated_at = datetime('now') WHERE id = ? AND user_id = ? AND status != 'deleted'",args:[e,t]})).rowsAffected>0}async function mr(e,t=10){return(await n().execute({sql:`
959
+ `,args:[t,e.userId,e.workflowId,e.name,JSON.stringify(e.workflowInput),e.cadence,e.timezone??"UTC",e.webhookUrl??null,e.nextRunAt??null]});let r=await B(t,e.userId);if(!r)throw new Error("Failed to create workflow schedule");return r}async function B(e,t){let r=t==null?await n().execute({sql:"SELECT * FROM workflow_schedules WHERE id = ? AND status != ? LIMIT 1",args:[e,"deleted"]}):await n().execute({sql:"SELECT * FROM workflow_schedules WHERE id = ? AND user_id = ? AND status != ? LIMIT 1",args:[e,t,"deleted"]});return r.rows[0]?G(r.rows[0]):null}async function gr(e){return(await n().execute({sql:"SELECT * FROM workflow_schedules WHERE user_id = ? AND status != 'deleted' ORDER BY created_at DESC LIMIT 100",args:[e]})).rows.map(r=>G(r))}async function Nr(e){let t=[],r=[];return e.name!==void 0&&(t.push("name = ?"),r.push(e.name)),e.status!==void 0&&(t.push("status = ?"),r.push(e.status)),e.workflowInput!==void 0&&(t.push("input_json = ?"),r.push(JSON.stringify(e.workflowInput))),e.cadence!==void 0&&(t.push("cadence = ?"),r.push(e.cadence)),e.timezone!==void 0&&(t.push("timezone = ?"),r.push(e.timezone)),e.webhookUrl!==void 0&&(t.push("webhook_url = ?"),r.push(e.webhookUrl)),e.nextRunAt!==void 0&&(t.push("next_run_at = ?"),r.push(e.nextRunAt)),t.length===0||(t.push("updated_at = datetime('now')"),await n().execute({sql:`UPDATE workflow_schedules SET ${t.join(", ")} WHERE id = ? AND user_id = ? AND status != 'deleted'`,args:[...r,e.id,e.userId]})),B(e.id,e.userId)}async function br(e,t){return(await n().execute({sql:"UPDATE workflow_schedules SET status = 'deleted', updated_at = datetime('now') WHERE id = ? AND user_id = ? AND status != 'deleted'",args:[e,t]})).rowsAffected>0}async function Lr(e,t=10){return(await n().execute({sql:`
925
960
  SELECT * FROM workflow_schedules
926
961
  WHERE status = 'active' AND next_run_at IS NOT NULL AND next_run_at <= ?
927
962
  ORDER BY next_run_at ASC
928
963
  LIMIT ?
929
- `,args:[e,t]})).rows.map(s=>G(s))}async function gr(e,t,r){await n().execute({sql:"UPDATE workflow_schedules SET last_run_at = ?, next_run_at = ?, updated_at = datetime('now') WHERE id = ?",args:[t,r,e]})}async function Nr(e){let t=e.id??g(),r=[t,e.userId,e.scheduleId??null,e.workflowId,JSON.stringify(e.workflowInput),e.idempotencyKey??null,e.webhookUrl??null,e.totalSteps??null];try{await n().execute({sql:`
964
+ `,args:[e,t]})).rows.map(s=>G(s))}async function Sr(e,t,r){await n().execute({sql:"UPDATE workflow_schedules SET last_run_at = ?, next_run_at = ?, updated_at = datetime('now') WHERE id = ?",args:[t,r,e]})}async function Rr(e){let t=e.id??g(),r=[t,e.userId,e.scheduleId??null,e.workflowId,JSON.stringify(e.workflowInput),e.idempotencyKey??null,e.webhookUrl??null,e.totalSteps??null];try{await n().execute({sql:`
930
965
  INSERT INTO workflow_runs (id, user_id, schedule_id, workflow_id, input_json, idempotency_key, webhook_url, total_steps)
931
966
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
932
- `,args:r})}catch(i){if(e.idempotencyKey){let a=await rt(e.idempotencyKey);if(a)return a}throw i}let s=await tt(t,e.userId);if(!s)throw new Error("Failed to create workflow run");return s}async function tt(e,t){let r=t==null?await n().execute({sql:"SELECT * FROM workflow_runs WHERE id = ? LIMIT 1",args:[e]}):await n().execute({sql:"SELECT * FROM workflow_runs WHERE id = ? AND user_id = ? LIMIT 1",args:[e,t]});return r.rows[0]?Y(r.rows[0]):null}async function rt(e){let t=await n().execute({sql:"SELECT * FROM workflow_runs WHERE idempotency_key = ? LIMIT 1",args:[e]});return t.rows[0]?Y(t.rows[0]):null}async function br(e,t=50){return(await n().execute({sql:"SELECT * FROM workflow_runs WHERE user_id = ? ORDER BY queued_at DESC LIMIT ?",args:[e,t]})).rows.map(s=>Y(s))}async function Lr(e){await n().execute({sql:"UPDATE workflow_runs SET status = 'running', started_at = COALESCE(started_at, datetime('now')) WHERE id = ?",args:[e]})}async function Sr(e,t,r){await n().execute({sql:"UPDATE workflow_runs SET status = ?, manifest_json = ?, completed_at = datetime('now') WHERE id = ?",args:[t,JSON.stringify(r),e]})}async function Rr(e,t,r){await n().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 st(e){return e==="html_report"?"text/html; charset=utf-8":e==="csv"?"text/csv; charset=utf-8":e==="json"?"application/json; charset=utf-8":"text/plain; charset=utf-8"}async function Ae(e,t,r){await n().execute({sql:`
967
+ `,args:r})}catch(i){if(e.idempotencyKey){let a=await rt(e.idempotencyKey);if(a)return a}throw i}let s=await tt(t,e.userId);if(!s)throw new Error("Failed to create workflow run");return s}async function tt(e,t){let r=t==null?await n().execute({sql:"SELECT * FROM workflow_runs WHERE id = ? LIMIT 1",args:[e]}):await n().execute({sql:"SELECT * FROM workflow_runs WHERE id = ? AND user_id = ? LIMIT 1",args:[e,t]});return r.rows[0]?Y(r.rows[0]):null}async function rt(e){let t=await n().execute({sql:"SELECT * FROM workflow_runs WHERE idempotency_key = ? LIMIT 1",args:[e]});return t.rows[0]?Y(t.rows[0]):null}async function Ar(e,t=50){return(await n().execute({sql:"SELECT * FROM workflow_runs WHERE user_id = ? ORDER BY queued_at DESC LIMIT ?",args:[e,t]})).rows.map(s=>Y(s))}async function wr(e){await n().execute({sql:"UPDATE workflow_runs SET status = 'running', started_at = COALESCE(started_at, datetime('now')) WHERE id = ?",args:[e]})}async function fr(e,t,r){await n().execute({sql:"UPDATE workflow_runs SET status = ?, manifest_json = ?, completed_at = datetime('now') WHERE id = ?",args:[t,JSON.stringify(r),e]})}async function Or(e,t,r){await n().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 st(e){return e==="html_report"?"text/html; charset=utf-8":e==="csv"?"text/csv; charset=utf-8":e==="json"?"application/json; charset=utf-8":"text/plain; charset=utf-8"}async function Ae(e,t,r){await n().execute({sql:`
933
968
  INSERT INTO workflow_artifacts (id, run_id, user_id, kind, label, path, content_type, bytes, rows_count, content)
934
969
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
935
- `,args:[g(),e,t,r.kind,r.label,r.path,st(r.kind),r.bytes??null,r.rows??null,r.content??null]})}async function Ar(e,t,r){await n().execute({sql:"DELETE FROM workflow_artifacts WHERE run_id = ? AND user_id = ?",args:[e,t]});for(let s of r)await Ae(e,t,s);return we(e,t)}async function wr(e,t,r){for(let s of r)await Ae(e,t,s);return we(e,t)}async function fr(e,t){let s=(t==null?await n().execute({sql:"SELECT step_index, total_steps, step_state_json, step_log_json FROM workflow_runs WHERE id = ? LIMIT 1",args:[e]}):await n().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 s?{stepIndex:s.step_index!=null?Number(s.step_index):0,totalSteps:s.total_steps!=null?Number(s.total_steps):null,state:s.step_state_json!=null?v(s.step_state_json):null,stepLog:Se(s.step_log_json)}:null}async function Or(e,t){let r=[...t.appendLog,t.logEntry];await n().execute({sql:"UPDATE workflow_runs SET status = ?, step_index = ?, total_steps = ?, step_state_json = ?, step_log_json = ?, started_at = COALESCE(started_at, datetime('now')) WHERE id = ?",args:[t.status,t.stepIndex,t.totalSteps,JSON.stringify(t.state??null),JSON.stringify(r),e]})}async function we(e,t){return(await n().execute({sql:"SELECT * FROM workflow_artifacts WHERE run_id = ? AND user_id = ? ORDER BY created_at ASC",args:[e,t]})).rows.map(s=>Re(s))}async function hr(e,t){let r=await n().execute({sql:"SELECT * FROM workflow_artifacts WHERE id = ? AND user_id = ? LIMIT 1",args:[e,t]});return r.rows[0]?Re(r.rows[0]):null}async function xr(e){await n().execute({sql:`
970
+ `,args:[g(),e,t,r.kind,r.label,r.path,st(r.kind),r.bytes??null,r.rows??null,r.content??null]})}async function hr(e,t,r){await n().execute({sql:"DELETE FROM workflow_artifacts WHERE run_id = ? AND user_id = ?",args:[e,t]});for(let s of r)await Ae(e,t,s);return we(e,t)}async function xr(e,t,r){for(let s of r)await Ae(e,t,s);return we(e,t)}async function yr(e,t){let s=(t==null?await n().execute({sql:"SELECT step_index, total_steps, step_state_json, step_log_json FROM workflow_runs WHERE id = ? LIMIT 1",args:[e]}):await n().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 s?{stepIndex:s.step_index!=null?Number(s.step_index):0,totalSteps:s.total_steps!=null?Number(s.total_steps):null,state:s.step_state_json!=null?F(s.step_state_json):null,stepLog:Se(s.step_log_json)}:null}async function Ir(e,t){let r=[...t.appendLog,t.logEntry];await n().execute({sql:"UPDATE workflow_runs SET status = ?, step_index = ?, total_steps = ?, step_state_json = ?, step_log_json = ?, started_at = COALESCE(started_at, datetime('now')) WHERE id = ?",args:[t.status,t.stepIndex,t.totalSteps,JSON.stringify(t.state??null),JSON.stringify(r),e]})}async function we(e,t){return(await n().execute({sql:"SELECT * FROM workflow_artifacts WHERE run_id = ? AND user_id = ? ORDER BY created_at ASC",args:[e,t]})).rows.map(s=>Re(s))}async function Cr(e,t){let r=await n().execute({sql:"SELECT * FROM workflow_artifacts WHERE id = ? AND user_id = ? LIMIT 1",args:[e,t]});return r.rows[0]?Re(r.rows[0]):null}async function Ur(e){await n().execute({sql:`
936
971
  INSERT INTO workflow_webhook_deliveries (
937
972
  id, run_id, schedule_id, user_id, webhook_url, status, attempts, last_error, delivered_at
938
973
  )
939
974
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
940
- `,args:[g(),e.runId,e.scheduleId??null,e.userId,e.webhookUrl,e.status,e.attempts,e.lastError??null,e.status==="delivered"?new Date().toISOString():null]})}async function yr(){let e=await n().execute("SELECT COUNT(*) as n FROM users WHERE active = 1");return Number(e.rows[0]?.n??0)}async function Ir(e){let t=await n().execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND (status = 'pending' OR (status = 'running' AND started_at > datetime('now', '-10 minutes')))",args:[e]});return Number(t.rows[0]?.n??0)}async function Cr(){let e=n(),t=await e.execute(`
975
+ `,args:[g(),e.runId,e.scheduleId??null,e.userId,e.webhookUrl,e.status,e.attempts,e.lastError??null,e.status==="delivered"?new Date().toISOString():null]})}async function kr(){let e=await n().execute("SELECT COUNT(*) as n FROM users WHERE active = 1");return Number(e.rows[0]?.n??0)}async function Dr(e){let t=await n().execute({sql:"SELECT COUNT(*) as n FROM jobs WHERE user_id = ? AND (status = 'pending' OR (status = 'running' AND started_at > datetime('now', '-10 minutes')))",args:[e]});return Number(t.rows[0]?.n??0)}async function vr(){let e=n(),t=await e.execute(`
941
976
  SELECT * FROM jobs
942
977
  WHERE status = 'pending'
943
978
  AND COALESCE(json_extract(options, '$.executionOwner'), 'cron') NOT IN ('direct', 'inngest')
944
979
  ORDER BY created_at
945
980
  LIMIT 1
946
- `),r=t.rows[0]?A(t.rows[0]):void 0;return r?(await e.execute({sql:"UPDATE jobs SET status = 'running', started_at = datetime('now') WHERE id = ? AND status = 'pending'",args:[r.id]})).rowsAffected===0?void 0:{...r,status:"running"}:void 0}var J=45e3;async function kr(e){let t=n(),r=await be(e);if(!r||r.options.executionOwner!=="direct"||r.options.serpOnly===!0)return;let s=Math.max(0,Number(r.options.paaRecoveryCount??0));if(r.status!=="running"){if(r.status==="pending"){let i=g(),a=new Date().toISOString(),u=new Date(Date.now()+J).toISOString();return(await t.execute({sql:`UPDATE jobs
981
+ `),r=t.rows[0]?w(t.rows[0]):void 0;return r?(await e.execute({sql:"UPDATE jobs SET status = 'running', started_at = datetime('now') WHERE id = ? AND status = 'pending'",args:[r.id]})).rowsAffected===0?void 0:{...r,status:"running"}:void 0}var J=45e3;async function Xr(e){let t=n(),r=await be(e);if(!r||r.options.executionOwner!=="direct"||r.options.serpOnly===!0)return;let s=Math.max(0,Number(r.options.paaRecoveryCount??0));if(r.status!=="running"){if(r.status==="pending"){let i=g(),a=new Date().toISOString(),u=new Date(Date.now()+J).toISOString();return(await t.execute({sql:`UPDATE jobs
947
982
  SET status = 'running', started_at = datetime('now'), error = NULL,
948
983
  options = json_set(options,
949
984
  '$.paaLeaseToken', ?,
950
985
  '$.paaLeaseExpiresAt', ?,
951
986
  '$.paaLastDispatchAt', ?)
952
- WHERE id = ? AND status = 'pending'`,args:[i,u,a,e]})).rowsAffected===0?void 0:{job:{...r,status:"running",started_at:a,options:{...r.options,paaLeaseToken:i,paaLeaseExpiresAt:u,paaLastDispatchAt:a}},leaseToken:i,recoveryCount:s}}return{job:r,leaseToken:null,recoveryCount:s}}}async function Ur(e,t){return(await n().execute({sql:"UPDATE jobs SET result = ? WHERE id = ? AND status = 'running'",args:[JSON.stringify(t),e]})).rowsAffected===1}async function Dr(e,t,r){let s=new Date(Date.now()+J).toISOString();return(await n().execute({sql:`UPDATE jobs SET result = ?, options = json_set(options, '$.paaLeaseExpiresAt', ?)
953
- WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,args:[JSON.stringify(r),s,e,t]})).rowsAffected===1}async function vr(e,t){let r=new Date(Date.now()+J).toISOString();return(await n().execute({sql:`UPDATE jobs SET options = json_set(options, '$.paaLeaseExpiresAt', ?)
954
- WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,args:[r,e,t]})).rowsAffected===1}async function Xr(e,t,r){return(await n().execute({sql:`UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL,
987
+ WHERE id = ? AND status = 'pending'`,args:[i,u,a,e]})).rowsAffected===0?void 0:{job:{...r,status:"running",started_at:a,options:{...r.options,paaLeaseToken:i,paaLeaseExpiresAt:u,paaLastDispatchAt:a}},leaseToken:i,recoveryCount:s}}return{job:r,leaseToken:null,recoveryCount:s}}}async function Mr(e,t){return(await n().execute({sql:"UPDATE jobs SET result = ? WHERE id = ? AND status = 'running'",args:[JSON.stringify(t),e]})).rowsAffected===1}async function Fr(e,t,r){let s=new Date(Date.now()+J).toISOString();return(await n().execute({sql:`UPDATE jobs SET result = ?, options = json_set(options, '$.paaLeaseExpiresAt', ?)
988
+ WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,args:[JSON.stringify(r),s,e,t]})).rowsAffected===1}async function Pr(e,t){let r=new Date(Date.now()+J).toISOString();return(await n().execute({sql:`UPDATE jobs SET options = json_set(options, '$.paaLeaseExpiresAt', ?)
989
+ WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,args:[r,e,t]})).rowsAffected===1}async function Hr(e,t,r){return(await n().execute({sql:`UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL,
955
990
  completed_at = datetime('now'),
956
991
  options = json_set(options, '$.paaLeaseExpiresAt', NULL)
957
- WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,args:[JSON.stringify(r),e,t]})).rowsAffected===1}async function Mr(e,t,r,s){return(await n().execute({sql:`UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now'),
992
+ WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,args:[JSON.stringify(r),e,t]})).rowsAffected===1}async function Wr(e,t,r,s){return(await n().execute({sql:`UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now'),
958
993
  options = json_set(options, '$.paaLeaseExpiresAt', NULL)
959
- WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,args:[r,R(s),e,t]})).rowsAffected===1}async function Fr(e,t){let r=new Date().toISOString();return(await n().execute({sql:`UPDATE jobs SET status = 'pending', started_at = NULL,
994
+ WHERE id = ? AND status = 'running' AND json_extract(options, '$.paaLeaseToken') = ?`,args:[r,A(s),e,t]})).rowsAffected===1}async function qr(e,t){let r=new Date().toISOString();return(await n().execute({sql:`UPDATE jobs SET status = 'pending', started_at = NULL,
960
995
  result = CASE WHEN json_valid(result) THEN json_set(result,
961
996
  '$.progress.lifecycle.discoveryStatus', 'interrupted',
962
997
  '$.progress.lifecycle.completionReason', 'The previous worker lease expired; the same job is recovering automatically.',
@@ -972,28 +1007,28 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
972
1007
  datetime(json_extract(options, '$.paaLeaseExpiresAt')) <= datetime('now')
973
1008
  OR (json_extract(options, '$.paaLeaseExpiresAt') IS NULL AND started_at <= datetime('now', '-15 minutes'))
974
1009
  )
975
- AND COALESCE(json_extract(options, '$.paaRecoveryCount'), 0) < ?`,args:[r,e,Math.max(0,Math.trunc(t))]})).rowsAffected===1}async function Pr(e,t){return(await n().execute({sql:`UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL, completed_at = datetime('now')
1010
+ AND COALESCE(json_extract(options, '$.paaRecoveryCount'), 0) < ?`,args:[r,e,Math.max(0,Math.trunc(t))]})).rowsAffected===1}async function jr(e,t){return(await n().execute({sql:`UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL, completed_at = datetime('now')
976
1011
  WHERE id = ? AND status = 'running'
977
1012
  AND (
978
1013
  datetime(json_extract(options, '$.paaLeaseExpiresAt')) <= datetime('now')
979
1014
  OR (json_extract(options, '$.paaLeaseExpiresAt') IS NULL AND started_at <= datetime('now', '-15 minutes'))
980
- )`,args:[JSON.stringify(t),e]})).rowsAffected===1}async function Hr(e,t,r){return(await n().execute({sql:`UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now')
1015
+ )`,args:[JSON.stringify(t),e]})).rowsAffected===1}async function Br(e,t,r){return(await n().execute({sql:`UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now')
981
1016
  WHERE id = ? AND status = 'running'
982
1017
  AND (
983
1018
  datetime(json_extract(options, '$.paaLeaseExpiresAt')) <= datetime('now')
984
1019
  OR (json_extract(options, '$.paaLeaseExpiresAt') IS NULL AND started_at <= datetime('now', '-15 minutes'))
985
- )`,args:[t,R(r),e]})).rowsAffected===1}async function qr(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await n().execute({sql:`SELECT * FROM jobs
1020
+ )`,args:[t,A(r),e]})).rowsAffected===1}async function Gr(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await n().execute({sql:`SELECT * FROM jobs
986
1021
  WHERE status IN ('done', 'failed', 'cancelled')
987
1022
  AND json_extract(options, '$.executionOwner') IN ('direct', 'inngest')
988
1023
  AND json_extract(options, '$.billingDebitKey') IS NOT NULL
989
1024
  AND json_extract(options, '$.billingSettledAt') IS NULL
990
1025
  ORDER BY completed_at DESC
991
- LIMIT ?`,args:[t]})).rows.map(s=>I(A(s)))}async function Wr(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await n().execute({sql:`SELECT * FROM jobs
1026
+ LIMIT ?`,args:[t]})).rows.map(s=>U(w(s)))}async function Yr(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await n().execute({sql:`SELECT * FROM jobs
992
1027
  WHERE status = 'running'
993
1028
  AND started_at <= datetime('now', '-15 minutes')
994
1029
  AND json_extract(options, '$.executionOwner') IN ('direct', 'inngest')
995
1030
  ORDER BY started_at
996
- LIMIT ?`,args:[t]})).rows.map(s=>I(A(s)))}async function jr(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await n().execute({sql:`SELECT * FROM jobs
1031
+ LIMIT ?`,args:[t]})).rows.map(s=>U(w(s)))}async function Jr(e=25){let t=Math.max(1,Math.min(100,Math.floor(e)));return(await n().execute({sql:`SELECT * FROM jobs
997
1032
  WHERE json_extract(options, '$.executionOwner') = 'direct'
998
1033
  AND json_extract(options, '$.serpOnly') IS NOT 1
999
1034
  AND (
@@ -1006,11 +1041,24 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
1006
1041
  AND datetime(COALESCE(json_extract(options, '$.paaLastDispatchAt'), '1970-01-01')) <= datetime('now', '-30 seconds'))
1007
1042
  )
1008
1043
  ORDER BY COALESCE(started_at, created_at)
1009
- LIMIT ?`,args:[t]})).rows.map(s=>I(A(s)))}async function Br(e,t,r=new Date().toISOString()){if(!Number.isSafeInteger(t)||t<0)throw new Error("job billed amount must be a non-negative integer");return(await n().execute({sql:`UPDATE jobs
1044
+ LIMIT ?`,args:[t]})).rows.map(s=>U(w(s)))}async function $r(e,t,r=new Date().toISOString()){if(!Number.isSafeInteger(t)||t<0)throw new Error("job billed amount must be a non-negative integer");return(await n().execute({sql:`UPDATE jobs
1010
1045
  SET options = json_set(options, '$.billingSettledAt', ?, '$.billedMc', ?)
1011
- WHERE id = ?`,args:[r,t,e]})).rowsAffected===1}async function Gr(e,t){await n().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 Yr(e,t){return(await n().execute({sql:`UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL, completed_at = datetime('now')
1012
- WHERE id = ? AND status = 'running'`,args:[JSON.stringify(t),e]})).rowsAffected===1}async function Jr(e,t,r){await n().execute({sql:"UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now') WHERE id = ?",args:[t,R(r),e]})}async function $r(e,t,r){return(await n().execute({sql:`UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now')
1013
- WHERE id = ? AND status = 'running'`,args:[t,R(r),e]})).rowsAffected===1}async function Kr(e,t,r){await n().execute({sql:"UPDATE jobs SET status = 'cancelled', error = ?, public_error_json = ?, completed_at = datetime('now') WHERE id = ?",args:[t,R(r),e]})}function $(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 nt(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 Vr(e,t,r,s,i,a){await n().execute({sql:"INSERT INTO kpo_jobs (id, user_id, status, entity_name, entity_type, url, request) VALUES (?, ?, 'pending', ?, ?, ?, ?)",args:[e,t,r,s,a??null,JSON.stringify(i)]})}async function zr(){let t=await n().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]?$(t.rows[0]):null}async function Qr(e){let t=await n().execute({sql:"SELECT * FROM kpo_jobs WHERE id = ?",args:[e]});return t.rows[0]?$(t.rows[0]):null}async function Zr(e,t){await n().execute({sql:"UPDATE kpo_jobs SET status = ?, updated_at = datetime('now') WHERE id = ?",args:[t,e]})}async function es(e,t){await n().execute({sql:"UPDATE kpo_jobs SET status = 'done', result = ?, updated_at = datetime('now') WHERE id = ?",args:[JSON.stringify(t),e]})}async function ts(e,t){await n().execute({sql:"UPDATE kpo_jobs SET status = 'failed', error = ?, updated_at = datetime('now') WHERE id = ?",args:[t,e]})}async function rs(e,t,r){await n().execute({sql:"INSERT INTO kpo_phase_log (job_id, phase, output) VALUES (?, ?, ?)",args:[e,t,JSON.stringify(r)]})}async function ss(e){return(await n().execute({sql:"SELECT * FROM kpo_phase_log WHERE job_id = ? ORDER BY created_at ASC",args:[e]})).rows.map(r=>nt(r))}async function ns(e){return(e!=null?await n().execute({sql:"SELECT * FROM kpo_jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50",args:[e]}):await n().execute("SELECT * FROM kpo_jobs ORDER BY created_at DESC LIMIT 50")).rows.map(r=>$(r))}async function is(e){let t=await n().execute({sql:"SELECT * FROM users WHERE stripe_customer_id = ? AND active = 1",args:[e]});return t.rows[0]?L(t.rows[0]):void 0}async function as(e,t){await n().execute({sql:"UPDATE users SET stripe_customer_id = ? WHERE id = ?",args:[t,e]})}async function os(e,t){if(!Number.isSafeInteger(t)||t<0)throw new Error("extra concurrency slots must be a non-negative safe integer");await it(e,Math.ceil(t/2))}async function it(e,t){if(!Number.isSafeInteger(t)||t<0)throw new Error("concurrency pack quantity must be a non-negative safe integer");await n().execute({sql:"UPDATE users SET concurrency_pack_quantity = ?, extra_concurrency_slots = ? WHERE id = ?",args:[t,t*2,e]})}async function us(e,t){await n().execute({sql:"UPDATE users SET concurrency_stripe_sub_id = ? WHERE id = ?",args:[t,e]})}async function cs(e,t,r,s){await n().execute({sql:"UPDATE users SET subscription_tier = ?, subscription_concurrency = ?, subscription_id = ? WHERE id = ?",args:[t,Math.max(0,Math.round(r)),s,e]})}function at(e){return{user_id:Number(e.user_id),stripe_subscription_id:e.stripe_subscription_id!=null?String(e.stripe_subscription_id):null,stripe_subscription_item_id:e.stripe_subscription_item_id!=null?String(e.stripe_subscription_item_id):null,price_id:e.price_id!=null?String(e.price_id):null,quantity:Math.max(0,Number(e.quantity??0)),status:["pending","synced","blocked","error"].includes(String(e.status))?String(e.status):"error",last_error_code:e.last_error_code!=null?String(e.last_error_code):null,checked_at:String(e.checked_at),synced_at:e.synced_at!=null?String(e.synced_at):null,updated_at:String(e.updated_at)}}async function ot(e){let r=(await n().execute({sql:"SELECT * FROM connected_account_billing WHERE user_id = ? LIMIT 1",args:[e]})).rows[0];return r?at(r):null}async function _s(e){let t=Math.max(0,Math.round(e.quantity));await n().execute({sql:`INSERT INTO connected_account_billing
1046
+ WHERE id = ?`,args:[r,t,e]})).rowsAffected===1}async function Kr(e,t){await n().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 Vr(e,t){return(await n().execute({sql:`UPDATE jobs SET status = 'done', result = ?, error = NULL, public_error_json = NULL, completed_at = datetime('now')
1047
+ WHERE id = ? AND status = 'running'`,args:[JSON.stringify(t),e]})).rowsAffected===1}async function zr(e,t,r){await n().execute({sql:"UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now') WHERE id = ?",args:[t,A(r),e]})}async function Qr(e,t,r){return(await n().execute({sql:`UPDATE jobs SET status = 'failed', error = ?, public_error_json = ?, completed_at = datetime('now')
1048
+ WHERE id = ? AND status = 'running'`,args:[t,A(r),e]})).rowsAffected===1}async function Zr(e,t,r){await n().execute({sql:"UPDATE jobs SET status = 'cancelled', error = ?, public_error_json = ?, completed_at = datetime('now') WHERE id = ?",args:[t,A(r),e]})}function $(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 nt(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 es(e,t,r,s,i,a){await n().execute({sql:"INSERT INTO kpo_jobs (id, user_id, status, entity_name, entity_type, url, request) VALUES (?, ?, 'pending', ?, ?, ?, ?)",args:[e,t,r,s,a??null,JSON.stringify(i)]})}async function ts(){let t=await n().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]?$(t.rows[0]):null}async function rs(e){let t=await n().execute({sql:"SELECT * FROM kpo_jobs WHERE id = ?",args:[e]});return t.rows[0]?$(t.rows[0]):null}async function ss(e,t){await n().execute({sql:"UPDATE kpo_jobs SET status = ?, updated_at = datetime('now') WHERE id = ?",args:[t,e]})}async function ns(e,t){await n().execute({sql:"UPDATE kpo_jobs SET status = 'done', result = ?, updated_at = datetime('now') WHERE id = ?",args:[JSON.stringify(t),e]})}async function is(e,t){await n().execute({sql:"UPDATE kpo_jobs SET status = 'failed', error = ?, updated_at = datetime('now') WHERE id = ?",args:[t,e]})}async function as(e,t,r){await n().execute({sql:"INSERT INTO kpo_phase_log (job_id, phase, output) VALUES (?, ?, ?)",args:[e,t,JSON.stringify(r)]})}async function os(e){return(await n().execute({sql:"SELECT * FROM kpo_phase_log WHERE job_id = ? ORDER BY created_at ASC",args:[e]})).rows.map(r=>nt(r))}async function us(e){return(e!=null?await n().execute({sql:"SELECT * FROM kpo_jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50",args:[e]}):await n().execute("SELECT * FROM kpo_jobs ORDER BY created_at DESC LIMIT 50")).rows.map(r=>$(r))}async function cs(e){let t=await n().execute({sql:"SELECT * FROM users WHERE stripe_customer_id = ? AND active = 1",args:[e]});return t.rows[0]?L(t.rows[0]):void 0}async function _s(e,t){await n().execute({sql:"UPDATE users SET stripe_customer_id = ? WHERE id = ?",args:[t,e]})}async function ds(e,t){if(!Number.isSafeInteger(t)||t<0)throw new Error("extra concurrency slots must be a non-negative safe integer");await it(e,Math.ceil(t/2))}async function it(e,t){if(!Number.isSafeInteger(t)||t<0)throw new Error("concurrency pack quantity must be a non-negative safe integer");await n().execute({sql:"UPDATE users SET concurrency_pack_quantity = ?, extra_concurrency_slots = ? WHERE id = ?",args:[t,t*2,e]})}async function ls(e,t){await n().execute({sql:"UPDATE users SET concurrency_stripe_sub_id = ? WHERE id = ?",args:[t,e]})}async function Es(e,t,r,s){await n().execute({sql:"UPDATE users SET subscription_tier = ?, subscription_concurrency = ?, subscription_id = ? WHERE id = ?",args:[t,Math.max(0,Math.round(r)),s,e]})}async function Ts(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 S(e.userId);let t=n(),r=e.neverExpires?"9999-12-31 23:59:59":null,s=await t.batch([{sql:`INSERT OR IGNORE INTO ledger (user_id, amount_mc, operation, description, stripe_pi)
1049
+ 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)
1050
+ SELECT ?, ?, ?, 'subscription', ?, COALESCE(?, datetime('now', ?)), ?
1051
+ WHERE changes() = 1`,args:[e.userId,e.creditsMc,e.creditsMc,e.invoiceId,r,I,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
1052
+ SET subscription_tier = ?, subscription_concurrency = ?, subscription_id = ?,
1053
+ memory_plan = CASE WHEN ? IS NOT NULL THEN ? ELSE memory_plan END,
1054
+ memory_subscription_id = CASE WHEN ? IS NOT NULL THEN NULL ELSE memory_subscription_id END
1055
+ WHERE id = ?
1056
+ AND EXISTS (
1057
+ SELECT 1 FROM ledger
1058
+ WHERE stripe_pi = ? AND user_id = ? AND amount_mc = ? AND operation = 'subscription'
1059
+ )`,args:[e.tier,Math.max(0,Math.round(e.concurrency)),e.subscriptionId,e.includedMemoryPlan,e.includedMemoryPlan,e.includedMemoryPlan,e.userId,e.invoiceId,e.userId,e.creditsMc]}],"write"),a=(await t.execute({sql:`SELECT l.user_id, l.amount_mc, l.operation, u.balance_mc
1060
+ FROM ledger l JOIN users u ON u.id = l.user_id
1061
+ WHERE l.stripe_pi = ? LIMIT 1`,args:[e.invoiceId]})).rows[0];if(!a||Number(a.user_id)!==e.userId||Number(a.amount_mc)!==e.creditsMc||String(a.operation)!=="subscription")throw new Error("invoice idempotency key conflicts with an existing grant");return{granted:s[0]?.rowsAffected===1,balance_mc:Number(a.balance_mc??0)}}function at(e){return{user_id:Number(e.user_id),stripe_subscription_id:e.stripe_subscription_id!=null?String(e.stripe_subscription_id):null,stripe_subscription_item_id:e.stripe_subscription_item_id!=null?String(e.stripe_subscription_item_id):null,price_id:e.price_id!=null?String(e.price_id):null,quantity:Math.max(0,Number(e.quantity??0)),status:["pending","synced","blocked","error"].includes(String(e.status))?String(e.status):"error",last_error_code:e.last_error_code!=null?String(e.last_error_code):null,checked_at:String(e.checked_at),synced_at:e.synced_at!=null?String(e.synced_at):null,updated_at:String(e.updated_at)}}async function ot(e){let r=(await n().execute({sql:"SELECT * FROM connected_account_billing WHERE user_id = ? LIMIT 1",args:[e]})).rows[0];return r?at(r):null}async function ps(e){let t=Math.max(0,Math.round(e.quantity));await n().execute({sql:`INSERT INTO connected_account_billing
1014
1062
  (user_id, stripe_subscription_id, stripe_subscription_item_id, price_id, quantity, status, last_error_code, checked_at, synced_at, updated_at)
1015
1063
  VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'), CASE WHEN ? THEN datetime('now') ELSE NULL END, datetime('now'))
1016
1064
  ON CONFLICT(user_id) DO UPDATE SET
@@ -1022,14 +1070,14 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
1022
1070
  last_error_code = excluded.last_error_code,
1023
1071
  checked_at = datetime('now'),
1024
1072
  synced_at = CASE WHEN ? THEN datetime('now') ELSE connected_account_billing.synced_at END,
1025
- updated_at = datetime('now')`,args:[e.userId,e.stripeSubscriptionId,e.stripeSubscriptionItemId,e.priceId,t,e.status,e.lastErrorCode??null,e.synced===!0?1:0,e.synced===!0?1:0]});let r=await ot(e.userId);if(!r)throw new Error("connected account billing state was not persisted");return r}async function ds(e=60,t=20){let r=`-${Math.max(1,Math.round(e))} minutes`;return(await n().execute({sql:`SELECT u.*
1073
+ updated_at = datetime('now')`,args:[e.userId,e.stripeSubscriptionId,e.stripeSubscriptionItemId,e.priceId,t,e.status,e.lastErrorCode??null,e.synced===!0?1:0,e.synced===!0?1:0]});let r=await ot(e.userId);if(!r)throw new Error("connected account billing state was not persisted");return r}async function ms(e=60,t=20){let r=`-${Math.max(1,Math.round(e))} minutes`;return(await n().execute({sql:`SELECT u.*
1026
1074
  FROM users u
1027
1075
  LEFT JOIN connected_account_billing b ON b.user_id = u.id
1028
1076
  WHERE u.active = 1
1029
1077
  AND u.subscription_id IS NOT NULL
1030
1078
  AND (b.checked_at IS NULL OR b.checked_at <= datetime('now', ?))
1031
1079
  ORDER BY COALESCE(b.checked_at, u.created_at) ASC
1032
- LIMIT ?`,args:[r,Math.max(1,Math.min(100,Math.round(t)))]})).rows.map(i=>L(i))}async function ls(e,t,r){await n().execute({sql:"UPDATE users SET memory_plan = ?, memory_subscription_id = ? WHERE id = ?",args:[t,r,e]})}async function Es(e){let r=(await n().execute({sql:"SELECT memory_plan, memory_subscription_id FROM users WHERE id = ?",args:[e]})).rows[0];return{plan:r?.memory_plan!=null?String(r.memory_plan):"free",memory_subscription_id:r?.memory_subscription_id!=null?String(r.memory_subscription_id):null}}async function Ts(e){let r=(await n().execute({sql:"SELECT memory_provisioned FROM users WHERE id = ?",args:[e]})).rows[0];return Number(r?.memory_provisioned??0)===1}async function ps(e,t){await n().execute({sql:"UPDATE users SET memory_provisioned = ? WHERE id = ?",args:[t?1:0,e]})}async function ms(e){let t=await n().execute({sql:"SELECT * FROM users WHERE memory_subscription_id = ? AND active = 1",args:[e]});return t.rows[0]?L(t.rows[0]):void 0}var X="+3 months";async function w(e){return(await n().execute({sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, expires_at)
1080
+ LIMIT ?`,args:[r,Math.max(1,Math.min(100,Math.round(t)))]})).rows.map(i=>L(i))}async function gs(e,t,r){await n().execute({sql:"UPDATE users SET memory_plan = ?, memory_subscription_id = ? WHERE id = ?",args:[t,r,e]})}async function Ns(e){let r=(await n().execute({sql:"SELECT memory_plan, memory_subscription_id FROM users WHERE id = ?",args:[e]})).rows[0];return{plan:r?.memory_plan!=null?String(r.memory_plan):"free",memory_subscription_id:r?.memory_subscription_id!=null?String(r.memory_subscription_id):null}}async function bs(e){let r=(await n().execute({sql:"SELECT memory_provisioned FROM users WHERE id = ?",args:[e]})).rows[0];return Number(r?.memory_provisioned??0)===1}async function Ls(e,t){await n().execute({sql:"UPDATE users SET memory_provisioned = ? WHERE id = ?",args:[t?1:0,e]})}async function Ss(e){let t=await n().execute({sql:"SELECT * FROM users WHERE memory_subscription_id = ? AND active = 1",args:[e]});return t.rows[0]?L(t.rows[0]):void 0}var I="+3 months";async function S(e){return(await n().execute({sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, expires_at)
1033
1081
  SELECT ?, legacy.balance_mc, legacy.balance_mc, 'migration', datetime('now', ?)
1034
1082
  FROM (
1035
1083
  SELECT COALESCE(SUM(amount_mc), 0) AS balance_mc
@@ -1043,7 +1091,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
1043
1091
  )
1044
1092
  AND NOT EXISTS (
1045
1093
  SELECT 1 FROM credit_lots WHERE user_id = ?
1046
- )`,args:[e,X,e,e,C,e]})).rowsAffected}async function gs(){let e=n(),t=await e.execute({sql:`SELECT id
1094
+ )`,args:[e,I,e,e,k,e]})).rowsAffected}async function Rs(){let e=n(),t=await e.execute({sql:`SELECT id
1047
1095
  FROM credit_lots
1048
1096
  WHERE remaining_mc > 0
1049
1097
  AND never_expires = 0
@@ -1065,22 +1113,22 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
1065
1113
  FROM credit_lot_expirations
1066
1114
  WHERE lot_id = ? AND claim_token = ?`,args:[d,E]})}let i=await e.batch(s,"write"),a=r.filter(_=>i[_.insertResultIndex]?.rowsAffected===1).map(_=>_.token);if(a.length===0)return{expired_lots:0,expired_mc:0};let u=a.map(()=>"?").join(", "),c=await e.execute({sql:`SELECT user_id, amount_mc
1067
1115
  FROM credit_lot_expirations
1068
- WHERE claim_token IN (${u})`,args:a}),o=new Set(c.rows.map(_=>Number(_.user_id)));for(let _ of o)await fe(_);return{expired_lots:c.rows.length,expired_mc:c.rows.reduce((_,d)=>_+Number(d.amount_mc),0)}}async function Ns(){let e=n(),t=await e.execute({sql:`SELECT DISTINCT u.id AS user_id
1116
+ WHERE claim_token IN (${u})`,args:a}),o=new Set(c.rows.map(_=>Number(_.user_id)));for(let _ of o)await fe(_);return{expired_lots:c.rows.length,expired_mc:c.rows.reduce((_,d)=>_+Number(d.amount_mc),0)}}async function As(){let e=n(),t=await e.execute({sql:`SELECT DISTINCT u.id AS user_id
1069
1117
  FROM users u
1070
1118
  JOIN ledger l ON l.user_id = u.id
1071
1119
  WHERE l.created_at < ?
1072
- AND NOT EXISTS (SELECT 1 FROM credit_lots WHERE user_id = u.id)`,args:[C]}),r=0,s=0;for(let i of t.rows){let a=Number(i.user_id);if(await w(a)===0)continue;let c=await e.execute({sql:`SELECT amount_mc FROM credit_lots
1120
+ AND NOT EXISTS (SELECT 1 FROM credit_lots WHERE user_id = u.id)`,args:[k]}),r=0,s=0;for(let i of t.rows){let a=Number(i.user_id);if(await S(a)===0)continue;let c=await e.execute({sql:`SELECT amount_mc FROM credit_lots
1073
1121
  WHERE user_id = ? AND source = 'migration'
1074
- ORDER BY id DESC LIMIT 1`,args:[a]}),o=Number(c.rows[0]?.amount_mc??0);await fe(a),r+=1,s+=o}return{migrated:r,total_mc:s}}async function bs(e,t,r,s,i,a){let u=n();await w(e);let c=a?.neverExpires;if(c===void 0&&t>0){let E=await u.execute({sql:"SELECT subscription_tier FROM users WHERE id = ? LIMIT 1",args:[e]});c=String(E.rows[0]?.subscription_tier??"").startsWith("sonic")}let o=c?"9999-12-31 23:59:59":null;if(i){let E=[{sql:"INSERT OR IGNORE INTO ledger (user_id, amount_mc, operation, description, stripe_pi) VALUES (?, ?, ?, ?, ?)",args:[e,t,r,s??null,i]}];t>0&&E.push({sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires)
1122
+ ORDER BY id DESC LIMIT 1`,args:[a]}),o=Number(c.rows[0]?.amount_mc??0);await fe(a),r+=1,s+=o}return{migrated:r,total_mc:s}}async function ws(e,t,r,s,i,a){let u=n();await S(e);let c=a?.neverExpires;if(c===void 0&&t>0){let E=await u.execute({sql:"SELECT subscription_tier FROM users WHERE id = ? LIMIT 1",args:[e]});c=String(E.rows[0]?.subscription_tier??"").startsWith("sonic")}let o=c?"9999-12-31 23:59:59":null;if(i){let E=[{sql:"INSERT OR IGNORE INTO ledger (user_id, amount_mc, operation, description, stripe_pi) VALUES (?, ?, ?, ?, ?)",args:[e,t,r,s??null,i]}];t>0&&E.push({sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires)
1075
1123
  SELECT ?, ?, ?, ?, ?, COALESCE(?, datetime('now', ?)), ?
1076
- WHERE changes() = 1`,args:[e,t,t,r,i,o,X,c?1:0]}),E.push({sql:"UPDATE users SET balance_mc = balance_mc + ? WHERE id = ? AND changes() = 1",args:[t,e]}),await u.batch(E,"write");let l=await u.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return Number(l.rows[0]?.balance_mc??0)}let _=[];t>0&&_.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,X,c?1:0]}),_.push({sql:"UPDATE users SET balance_mc = balance_mc + ? WHERE id = ?",args:[t,e]}),_.push({sql:"INSERT INTO ledger (user_id, amount_mc, operation, description, stripe_pi) VALUES (?, ?, ?, ?, ?)",args:[e,t,r,s??null,null]}),await u.batch(_,"write");let d=await u.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return Number(d.rows[0]?.balance_mc??0)}async function Ls(e,t,r,s,i,a){if(!Number.isSafeInteger(t)||t<=0)throw new Error("idempotent credit amount must be a positive integer");if(!i||i.length>500)throw new Error("idempotent credit key is required and must be bounded");let u=n();await w(e);let c=a?.neverExpires;if(c===void 0){let m=await u.execute({sql:"SELECT subscription_tier FROM users WHERE id = ? LIMIT 1",args:[e]});c=String(m.rows[0]?.subscription_tier??"").startsWith("sonic")}let o=c?"9999-12-31 23:59:59":null,_=async()=>{let m=await u.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return Number(m.rows[0]?.balance_mc??0)},d;try{d=await u.batch([{sql:"INSERT OR IGNORE INTO billing_credits (idempotency_key, user_id, amount_mc, operation, description, status) VALUES (?, ?, ?, ?, ?, 'claimed')",args:[i,e,t,r,s]},{sql:"UPDATE billing_credits SET status = 'applying' WHERE idempotency_key = ? AND user_id = ? AND amount_mc = ? AND operation = ? AND description = ? AND status = 'claimed'",args:[i,e,t,r,s]},{sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires)
1124
+ WHERE changes() = 1`,args:[e,t,t,r,i,o,I,c?1:0]}),E.push({sql:"UPDATE users SET balance_mc = balance_mc + ? WHERE id = ? AND changes() = 1",args:[t,e]}),await u.batch(E,"write");let l=await u.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return Number(l.rows[0]?.balance_mc??0)}let _=[];t>0&&_.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,I,c?1:0]}),_.push({sql:"UPDATE users SET balance_mc = balance_mc + ? WHERE id = ?",args:[t,e]}),_.push({sql:"INSERT INTO ledger (user_id, amount_mc, operation, description, stripe_pi) VALUES (?, ?, ?, ?, ?)",args:[e,t,r,s??null,null]}),await u.batch(_,"write");let d=await u.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return Number(d.rows[0]?.balance_mc??0)}async function fs(e,t,r,s,i,a){if(!Number.isSafeInteger(t)||t<=0)throw new Error("idempotent credit amount must be a positive integer");if(!i||i.length>500)throw new Error("idempotent credit key is required and must be bounded");let u=n();await S(e);let c=a?.neverExpires;if(c===void 0){let m=await u.execute({sql:"SELECT subscription_tier FROM users WHERE id = ? LIMIT 1",args:[e]});c=String(m.rows[0]?.subscription_tier??"").startsWith("sonic")}let o=c?"9999-12-31 23:59:59":null,_=async()=>{let m=await u.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return Number(m.rows[0]?.balance_mc??0)},d;try{d=await u.batch([{sql:"INSERT OR IGNORE INTO billing_credits (idempotency_key, user_id, amount_mc, operation, description, status) VALUES (?, ?, ?, ?, ?, 'claimed')",args:[i,e,t,r,s]},{sql:"UPDATE billing_credits SET status = 'applying' WHERE idempotency_key = ? AND user_id = ? AND amount_mc = ? AND operation = ? AND description = ? AND status = 'claimed'",args:[i,e,t,r,s]},{sql:`INSERT INTO credit_lots (user_id, amount_mc, remaining_mc, source, stripe_pi, expires_at, never_expires)
1077
1125
  SELECT user_id, amount_mc, amount_mc, operation, NULL, COALESCE(?, datetime('now', ?)), ?
1078
1126
  FROM billing_credits
1079
- WHERE idempotency_key = ? AND status = 'applying'`,args:[o,X,c?1:0,i]},{sql:`UPDATE users
1127
+ WHERE idempotency_key = ? AND status = 'applying'`,args:[o,I,c?1:0,i]},{sql:`UPDATE users
1080
1128
  SET balance_mc = balance_mc + COALESCE((
1081
1129
  SELECT amount_mc FROM billing_credits WHERE idempotency_key = ? AND status = 'applying'
1082
1130
  ), 0)
1083
- WHERE id = ?`,args:[i,e]},{sql:"INSERT INTO ledger (user_id, amount_mc, operation, description) SELECT user_id, amount_mc, operation, description FROM billing_credits WHERE idempotency_key = ? AND status = 'applying'",args:[i]},{sql:"UPDATE billing_credits SET status = 'applied', applied_at = datetime('now') WHERE idempotency_key = ? AND status = 'applying'",args:[i]}],"write")}catch(m){try{let T=(await u.execute({sql:"SELECT user_id, amount_mc, operation, description FROM billing_credits WHERE idempotency_key = ? AND status = 'applied' LIMIT 1",args:[i]})).rows[0];if(T&&Number(T.user_id)===e&&Number(T.amount_mc)===t&&String(T.operation)===r&&String(T.description)===s)return{ok:!0,balance_mc:await _(),duplicate:!0}}catch{}throw m}let l=(await u.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_credits WHERE idempotency_key = ? LIMIT 1",args:[i]})).rows[0];if(!l||Number(l.user_id)!==e||Number(l.amount_mc)!==t||String(l.operation)!==r||String(l.description)!==s)throw new Error("idempotent credit key conflicts with another credit");return{ok:String(l.status)==="applied",balance_mc:await _(),duplicate:d[1]?.rowsAffected===0&&String(l.status)==="applied"}}async function Ss(e,t){return(await n().execute({sql:"SELECT 1 FROM ledger WHERE user_id = ? AND operation = ? LIMIT 1",args:[e,t]})).rows.length>0}async function Rs(e,t){return(await n().execute({sql:"INSERT OR IGNORE INTO free_credit_refreshes (user_id, month) VALUES (?, ?)",args:[e,t]})).rowsAffected>0}async function As(e,t,r,s){let i=await ut(e,t,r,s??"",`debit:${g()}`);return{ok:i.ok,balance_mc:i.balance_mc}}async function ut(e,t,r,s,i){if(!Number.isSafeInteger(t)||t<=0)throw new Error("idempotent debit amount must be a positive integer");if(!i||i.length>500)throw new Error("idempotent debit key is required and must be bounded");let a=n();await w(e);let u;try{u=await a.batch([{sql:"UPDATE billing_debits SET amount_mc = ? WHERE idempotency_key = ? AND user_id = ? AND operation = ? AND description = ? AND status = 'claimed'",args:[t,i,e,r,s]},{sql:"INSERT OR IGNORE INTO billing_debits (idempotency_key, user_id, amount_mc, operation, description, status) VALUES (?, ?, ?, ?, ?, 'claimed')",args:[i,e,t,r,s]},{sql:`UPDATE users
1131
+ WHERE id = ?`,args:[i,e]},{sql:"INSERT INTO ledger (user_id, amount_mc, operation, description) SELECT user_id, amount_mc, operation, description FROM billing_credits WHERE idempotency_key = ? AND status = 'applying'",args:[i]},{sql:"UPDATE billing_credits SET status = 'applied', applied_at = datetime('now') WHERE idempotency_key = ? AND status = 'applying'",args:[i]}],"write")}catch(m){try{let T=(await u.execute({sql:"SELECT user_id, amount_mc, operation, description FROM billing_credits WHERE idempotency_key = ? AND status = 'applied' LIMIT 1",args:[i]})).rows[0];if(T&&Number(T.user_id)===e&&Number(T.amount_mc)===t&&String(T.operation)===r&&String(T.description)===s)return{ok:!0,balance_mc:await _(),duplicate:!0}}catch{}throw m}let l=(await u.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_credits WHERE idempotency_key = ? LIMIT 1",args:[i]})).rows[0];if(!l||Number(l.user_id)!==e||Number(l.amount_mc)!==t||String(l.operation)!==r||String(l.description)!==s)throw new Error("idempotent credit key conflicts with another credit");return{ok:String(l.status)==="applied",balance_mc:await _(),duplicate:d[1]?.rowsAffected===0&&String(l.status)==="applied"}}async function Os(e,t){return(await n().execute({sql:"SELECT 1 FROM ledger WHERE user_id = ? AND operation = ? LIMIT 1",args:[e,t]})).rows.length>0}async function hs(e,t){return(await n().execute({sql:"INSERT OR IGNORE INTO free_credit_refreshes (user_id, month) VALUES (?, ?)",args:[e,t]})).rowsAffected>0}async function xs(e,t,r,s){let i=await ut(e,t,r,s??"",`debit:${g()}`);return{ok:i.ok,balance_mc:i.balance_mc}}async function ut(e,t,r,s,i){if(!Number.isSafeInteger(t)||t<=0)throw new Error("idempotent debit amount must be a positive integer");if(!i||i.length>500)throw new Error("idempotent debit key is required and must be bounded");let a=n();await S(e);let u;try{u=await a.batch([{sql:"UPDATE billing_debits SET amount_mc = ? WHERE idempotency_key = ? AND user_id = ? AND operation = ? AND description = ? AND status = 'claimed'",args:[t,i,e,r,s]},{sql:"INSERT OR IGNORE INTO billing_debits (idempotency_key, user_id, amount_mc, operation, description, status) VALUES (?, ?, ?, ?, ?, 'claimed')",args:[i,e,t,r,s]},{sql:`UPDATE users
1084
1132
  SET balance_mc = balance_mc - ?
1085
1133
  WHERE id = ?
1086
1134
  AND balance_mc >= ?
@@ -1116,7 +1164,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
1116
1164
  WHERE id IN (
1117
1165
  SELECT lot_id FROM billing_debit_allocations WHERE debit_idempotency_key = ?
1118
1166
  )
1119
- AND EXISTS (SELECT 1 FROM billing_debits WHERE idempotency_key = ? AND status = 'applying')`,args:[i,i,i]},{sql:"INSERT INTO ledger (user_id, amount_mc, operation, description) SELECT user_id, -amount_mc, operation, description FROM billing_debits WHERE idempotency_key = ? AND status = 'applying'",args:[i]},{sql:"UPDATE billing_debits SET status = 'applied', applied_at = datetime('now') WHERE idempotency_key = ? AND status = 'applying'",args:[i]}],"write")}catch(d){try{let l=(await a.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_debits WHERE idempotency_key = ? AND status = 'applied' LIMIT 1",args:[i]})).rows[0];if(l&&Number(l.user_id)===e&&Number(l.amount_mc)===t&&String(l.operation)===r&&String(l.description)===s){let m=await a.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return{ok:!0,balance_mc:Number(m.rows[0]?.balance_mc??0),duplicate:!0}}}catch{}throw d}let o=(await a.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_debits WHERE idempotency_key = ? LIMIT 1",args:[i]})).rows[0];if(!o||Number(o.user_id)!==e||Number(o.amount_mc)!==t||String(o.operation)!==r||String(o.description)!==s)throw new Error("idempotent debit key conflicts with another debit");let _=await a.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return{ok:String(o.status)==="applied",balance_mc:Number(_.rows[0]?.balance_mc??0),duplicate:u[2]?.rowsAffected===0&&String(o.status)==="applied"}}async function ws(e,t,r,s,i,a){if(!Number.isSafeInteger(r)||r<0)throw new Error("idempotent debit settlement amount must be a non-negative integer");if(!t||t.length>500)throw new Error("idempotent debit settlement key is required and must be bounded");if(!s||!a)throw new Error("idempotent debit settlement operation and source are required");let u=n();await w(e);let c=`debit-settlement:${y("sha256").update(t).digest("hex")}`,o="wallet_hold_settlement",_=g(),d=JSON.stringify({debitIdempotencyKey:t,refundOperation:s,description:i}),E=async()=>{let T=(await u.execute({sql:`SELECT e.user_id,
1167
+ AND EXISTS (SELECT 1 FROM billing_debits WHERE idempotency_key = ? AND status = 'applying')`,args:[i,i,i]},{sql:"INSERT INTO ledger (user_id, amount_mc, operation, description) SELECT user_id, -amount_mc, operation, description FROM billing_debits WHERE idempotency_key = ? AND status = 'applying'",args:[i]},{sql:"UPDATE billing_debits SET status = 'applied', applied_at = datetime('now') WHERE idempotency_key = ? AND status = 'applying'",args:[i]}],"write")}catch(d){try{let l=(await a.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_debits WHERE idempotency_key = ? AND status = 'applied' LIMIT 1",args:[i]})).rows[0];if(l&&Number(l.user_id)===e&&Number(l.amount_mc)===t&&String(l.operation)===r&&String(l.description)===s){let m=await a.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return{ok:!0,balance_mc:Number(m.rows[0]?.balance_mc??0),duplicate:!0}}}catch{}throw d}let o=(await a.execute({sql:"SELECT user_id, amount_mc, operation, description, status FROM billing_debits WHERE idempotency_key = ? LIMIT 1",args:[i]})).rows[0];if(!o||Number(o.user_id)!==e||Number(o.amount_mc)!==t||String(o.operation)!==r||String(o.description)!==s)throw new Error("idempotent debit key conflicts with another debit");let _=await a.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return{ok:String(o.status)==="applied",balance_mc:Number(_.rows[0]?.balance_mc??0),duplicate:u[2]?.rowsAffected===0&&String(o.status)==="applied"}}async function ys(e,t,r,s,i,a){if(!Number.isSafeInteger(r)||r<0)throw new Error("idempotent debit settlement amount must be a non-negative integer");if(!t||t.length>500)throw new Error("idempotent debit settlement key is required and must be bounded");if(!s||!a)throw new Error("idempotent debit settlement operation and source are required");let u=n();await S(e);let c=`debit-settlement:${C("sha256").update(t).digest("hex")}`,o="wallet_hold_settlement",_=g(),d=JSON.stringify({debitIdempotencyKey:t,refundOperation:s,description:i}),E=async()=>{let T=(await u.execute({sql:`SELECT e.user_id,
1120
1168
  e.status,
1121
1169
  e.amount_mc AS final_amount_mc,
1122
1170
  e.billing_class,
@@ -1128,7 +1176,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
1128
1176
  WHERE e.idempotency_key = ?
1129
1177
  AND d.user_id = e.user_id
1130
1178
  AND d.status = 'applied'
1131
- LIMIT 1`,args:[t,c]})).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 F=Number(T.held_amount_mc),S=Number(T.final_amount_mc);if(!Number.isSafeInteger(F)||!Number.isSafeInteger(S)||S<0||S>F)throw new Error("idempotent debit settlement receipt is invalid");let Oe=F-S,K=await u.execute({sql:`WITH ordered AS (
1179
+ LIMIT 1`,args:[t,c]})).rows[0];if(!T)return null;if(Number(T.user_id)!==e||String(T.billing_class)!==o||String(T.source_surface)!==a)throw new Error("idempotent debit settlement key conflicts with another settlement");if(String(T.status)!=="settled")return null;let H=Number(T.held_amount_mc),R=Number(T.final_amount_mc);if(!Number.isSafeInteger(H)||!Number.isSafeInteger(R)||R<0||R>H)throw new Error("idempotent debit settlement receipt is invalid");let Oe=H-R,K=await u.execute({sql:`WITH ordered AS (
1132
1180
  SELECT a.amount_mc,
1133
1181
  a.expires_at,
1134
1182
  COALESCE(SUM(a.amount_mc) OVER (
@@ -1144,7 +1192,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
1144
1192
  )
1145
1193
  SELECT (SELECT COUNT(*) FROM ordered) AS allocation_count,
1146
1194
  COALESCE(SUM(CASE WHEN expires_at > ? THEN refund_mc ELSE 0 END), 0) AS credited_refund_mc
1147
- FROM refunds`,args:[t,S,String(T.settled_at)]}),V=Number(K.rows[0]?.allocation_count??0)>0?Number(K.rows[0]?.credited_refund_mc??0):0,he=await u.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return{balance_mc:Number(he.rows[0]?.balance_mc??0),final_amount_mc:S,refund_mc:V,expired_refund_mc:Oe-V,duplicate:!0}},l;try{l=await u.batch([{sql:`INSERT OR IGNORE INTO billing_events
1195
+ FROM refunds`,args:[t,R,String(T.settled_at)]}),V=Number(K.rows[0]?.allocation_count??0)>0?Number(K.rows[0]?.credited_refund_mc??0):0,he=await u.execute({sql:"SELECT balance_mc FROM users WHERE id = ?",args:[e]});return{balance_mc:Number(he.rows[0]?.balance_mc??0),final_amount_mc:R,refund_mc:V,expired_refund_mc:Oe-V,duplicate:!0}},l;try{l=await u.batch([{sql:`INSERT OR IGNORE INTO billing_events
1148
1196
  (id, user_id, idempotency_key, billing_class, source_surface, status, amount_mc, metadata)
1149
1197
  VALUES (?, ?, ?, ?, ?, 'settling', ?, ?)`,args:[_,e,c,o,a,r,d]},{sql:`WITH ordered AS (
1150
1198
  SELECT a.lot_id,
@@ -1252,7 +1300,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
1252
1300
  WHERE refund_mc > 0`,args:[t,r,t,c,s,i]},{sql:`UPDATE billing_events
1253
1301
  SET status = 'settled', settled_at = datetime('now')
1254
1302
  WHERE idempotency_key = ?
1255
- AND status = 'applying'`,args:[c]}],"write")}catch(N){try{let T=await E();if(T)return T}catch{}throw N}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 fs(e,t=50){return(await n().execute({sql:"SELECT * FROM ledger WHERE user_id = ? ORDER BY created_at DESC LIMIT ?",args:[e,t]})).rows.map(s=>({id:Number(s.id),user_id:Number(s.user_id),amount_mc:Number(s.amount_mc),operation:String(s.operation),description:s.description!=null?String(s.description):null,stripe_pi:s.stripe_pi!=null?String(s.stripe_pi):null,created_at:String(s.created_at)}))}async function Os(e,t,r){let s=n(),i=r.refund.map(()=>"?").join(", "),a=r.grant.map(()=>"?").join(", "),u=r.purchase.map(()=>"?").join(", "),c=await s.execute({sql:`SELECT
1303
+ AND status = 'applying'`,args:[c]}],"write")}catch(N){try{let T=await E();if(T)return T}catch{}throw N}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 Is(e,t=50){return(await n().execute({sql:"SELECT * FROM ledger WHERE user_id = ? ORDER BY created_at DESC LIMIT ?",args:[e,t]})).rows.map(s=>({id:Number(s.id),user_id:Number(s.user_id),amount_mc:Number(s.amount_mc),operation:String(s.operation),description:s.description!=null?String(s.description):null,stripe_pi:s.stripe_pi!=null?String(s.stripe_pi):null,created_at:String(s.created_at)}))}async function Cs(e,t,r){let s=n(),i=r.refund.map(()=>"?").join(", "),a=r.grant.map(()=>"?").join(", "),u=r.purchase.map(()=>"?").join(", "),c=await s.execute({sql:`SELECT
1256
1304
  COALESCE(SUM(CASE WHEN amount_mc < 0 AND operation NOT IN (${i}) THEN -amount_mc ELSE 0 END), 0) AS spent_mc,
1257
1305
  COALESCE(SUM(CASE WHEN amount_mc > 0 AND operation IN (${i}) THEN amount_mc ELSE 0 END), 0) AS refunded_mc,
1258
1306
  COALESCE(SUM(CASE WHEN amount_mc > 0 AND operation IN (${a}) THEN amount_mc ELSE 0 END), 0) AS granted_mc,
@@ -1262,7 +1310,7 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
1262
1310
  FROM ledger
1263
1311
  WHERE user_id = ? AND created_at >= ? AND amount_mc < 0 AND operation NOT IN (${i})
1264
1312
  GROUP BY operation
1265
- ORDER BY mc DESC, operation ASC`,args:[e,t,...r.refund]}),_=c.rows[0];return{spent_mc:Number(_?.spent_mc??0),refunded_mc:Number(_?.refunded_mc??0),granted_mc:Number(_?.granted_mc??0),purchased_mc:Number(_?.purchased_mc??0),net_mc:Number(_?.net_mc??0),by_operation:o.rows.map(d=>({operation:String(d.operation),mc:Number(d.mc),count:Number(d.count)}))}}async function hs(e){return(await n().execute({sql:"SELECT 1 FROM ledger WHERE stripe_pi = ? LIMIT 1",args:[e]})).rows.length>0}async function fe(e,t){let r=n();for(let i=0;i<8;i+=1){let u=(await r.execute({sql:`SELECT
1313
+ ORDER BY mc DESC, operation ASC`,args:[e,t,...r.refund]}),_=c.rows[0];return{spent_mc:Number(_?.spent_mc??0),refunded_mc:Number(_?.refunded_mc??0),granted_mc:Number(_?.granted_mc??0),purchased_mc:Number(_?.purchased_mc??0),net_mc:Number(_?.net_mc??0),by_operation:o.rows.map(d=>({operation:String(d.operation),mc:Number(d.mc),count:Number(d.count)}))}}async function Us(e){return(await n().execute({sql:"SELECT 1 FROM ledger WHERE stripe_pi = ? LIMIT 1",args:[e]})).rows.length>0}async function fe(e,t){let r=n();for(let i=0;i<8;i+=1){let u=(await r.execute({sql:`SELECT
1266
1314
  u.balance_mc AS cached_balance_mc,
1267
1315
  COUNT(l.id) AS lot_count,
1268
1316
  COALESCE(SUM(CASE
@@ -1272,4 +1320,4 @@ import{createClient as Be}from"@libsql/client/http";import{createHash as y,rando
1272
1320
  FROM users u
1273
1321
  LEFT JOIN credit_lots l ON l.user_id = u.id
1274
1322
  WHERE u.id = ?
1275
- GROUP BY u.id, u.balance_mc`,args:[e]})).rows[0];if(!u)return 0;if(Number(u.lot_count??0)===0&&(await w(Number(e)),(await r.execute({sql:"SELECT 1 FROM credit_lots WHERE user_id = ? LIMIT 1",args:[e]})).rows.length>0))continue;let c=Number(u.cached_balance_mc??0),o=Number(u.projected_balance_mc??0);if(c===o||(await r.execute({sql:"UPDATE users SET balance_mc = ? WHERE id = ? AND balance_mc = ?",args:[o,e,c]})).rowsAffected===1)return o}let s=await r.execute({sql:"SELECT balance_mc FROM users WHERE id = ? LIMIT 1",args:[e]});return Number(s.rows[0]?.balance_mc??0)}var xs=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()}),ys=p.object({id:p.number(),job_id:p.string(),phase:p.string(),completed_at:p.string(),output_summary:p.string()});async function Is(e){return(await n().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 Cs(e,t){let s=(await n().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(s)return{id:String(s.id),subject:String(s.subject),body_md:String(s.body_md),source:String(s.source),sent_at:String(s.sent_at),opened_at:s.opened_at!=null?String(s.opened_at):null}}async function ks(e,t){let r=n();await r.execute({sql:"UPDATE inbox_messages SET opened_at = datetime('now') WHERE id = ? AND user_id = ? AND deleted_at IS NULL AND opened_at IS NULL",args:[t,e]});let i=(await r.execute({sql:"SELECT opened_at FROM inbox_messages WHERE id = ? AND user_id = ? AND deleted_at IS NULL",args:[t,e]})).rows[0];return i&&i.opened_at!=null?String(i.opened_at):null}async function Us(e,t){return(await n().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 Ds(e,t,r,s="operator"){let i=g();return await n().execute({sql:"INSERT INTO inbox_messages (id, user_id, subject, body_md, source) VALUES (?, ?, ?, ?, ?)",args:[i,e,t,r,s]}),i}async function vs(){return(await n().execute("SELECT id FROM users WHERE active = 1")).rows.map(t=>Number(t.id))}export{dt as a,xe as b,ye as c,R as d,se as e,P as f,Fe as g,Pe as h,ie as i,z as j,Q as k,Z as l,ee as m,te as n,re as o,C as p,q,_e as r,n as s,Lt as t,St as u,Rt as v,At as w,wt as x,ft as y,Ot as z,ht as A,Ve as B,xt as C,yt as D,It as E,Ct as F,kt as G,Ut as H,Dt as I,pe as J,me as K,vt as L,Xt as M,Mt as N,Ft as O,Pt as P,Ht as Q,qt as R,Wt as S,jt as T,Bt as U,Gt as V,Yt as W,Jt as X,$t as Y,Kt as Z,Vt as _,zt as $,ze as aa,Qt as ba,Zt as ca,er as da,tr as ea,rr as fa,sr as ga,nr as ha,ir as ia,ar as ja,be as ka,or as la,ur as ma,cr as na,_r as oa,dr as pa,lr as qa,B as ra,Er as sa,Tr as ta,pr as ua,mr as va,gr as wa,Nr as xa,tt as ya,rt as za,br as Aa,Lr as Ba,Sr as Ca,Rr as Da,Ar as Ea,wr as Fa,fr as Ga,Or as Ha,we as Ia,hr as Ja,xr as Ka,yr as La,Ir as Ma,Cr as Na,kr as Oa,Ur as Pa,Dr as Qa,vr as Ra,Xr as Sa,Mr as Ta,Fr as Ua,Pr as Va,Hr as Wa,qr as Xa,Wr as Ya,jr as Za,Br as _a,Gr as $a,Yr as ab,Jr as bb,$r as cb,Kr as db,Vr as eb,zr as fb,Qr as gb,Zr as hb,es as ib,ts as jb,rs as kb,ss as lb,ns as mb,is as nb,as as ob,os as pb,it as qb,us as rb,cs as sb,ot as tb,_s as ub,ds as vb,ls as wb,Es as xb,Ts as yb,ps as zb,ms as Ab,X as Bb,gs as Cb,Ns as Db,bs as Eb,Ls as Fb,Ss as Gb,Rs as Hb,As as Ib,ut as Jb,ws as Kb,fs as Lb,Os as Mb,hs as Nb,fe as Ob,xs as Pb,ys as Qb,Is as Rb,Cs as Sb,ks as Tb,Us as Ub,Ds as Vb,vs as Wb};
1323
+ GROUP BY u.id, u.balance_mc`,args:[e]})).rows[0];if(!u)return 0;if(Number(u.lot_count??0)===0&&(await S(Number(e)),(await r.execute({sql:"SELECT 1 FROM credit_lots WHERE user_id = ? LIMIT 1",args:[e]})).rows.length>0))continue;let c=Number(u.cached_balance_mc??0),o=Number(u.projected_balance_mc??0);if(c===o||(await r.execute({sql:"UPDATE users SET balance_mc = ? WHERE id = ? AND balance_mc = ?",args:[o,e,c]})).rowsAffected===1)return o}let s=await r.execute({sql:"SELECT balance_mc FROM users WHERE id = ? LIMIT 1",args:[e]});return Number(s.rows[0]?.balance_mc??0)}var ks=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()}),Ds=p.object({id:p.number(),job_id:p.string(),phase:p.string(),completed_at:p.string(),output_summary:p.string()});async function vs(e){return(await n().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 Xs(e,t){let s=(await n().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(s)return{id:String(s.id),subject:String(s.subject),body_md:String(s.body_md),source:String(s.source),sent_at:String(s.sent_at),opened_at:s.opened_at!=null?String(s.opened_at):null}}async function Ms(e,t){let r=n();await r.execute({sql:"UPDATE inbox_messages SET opened_at = datetime('now') WHERE id = ? AND user_id = ? AND deleted_at IS NULL AND opened_at IS NULL",args:[t,e]});let i=(await r.execute({sql:"SELECT opened_at FROM inbox_messages WHERE id = ? AND user_id = ? AND deleted_at IS NULL",args:[t,e]})).rows[0];return i&&i.opened_at!=null?String(i.opened_at):null}async function Fs(e,t){return(await n().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 Ps(e,t,r,s="operator"){let i=g();return await n().execute({sql:"INSERT INTO inbox_messages (id, user_id, subject, body_md, source) VALUES (?, ?, ?, ?, ?)",args:[i,e,t,r,s]}),i}async function Hs(){return(await n().execute("SELECT id FROM users WHERE active = 1")).rows.map(t=>Number(t.id))}export{dt as a,xe as b,ye as c,A as d,se as e,W as f,Fe as g,Pe as h,ie as i,z as j,Q as k,Z as l,ee as m,te as n,re as o,k as p,y as q,_e as r,Lt as s,n as t,St as u,Rt as v,At as w,wt as x,ft as y,Ot as z,ht as A,xt as B,Ve as C,yt as D,It as E,Ct as F,Ut as G,kt as H,Dt as I,vt as J,Xt as K,Mt as L,Ft as M,pe as N,me as O,Pt as P,Ht as Q,Wt as R,qt as S,jt as T,Bt as U,Gt as V,Yt as W,Jt as X,$t as Y,Kt as Z,Vt as _,zt as $,Qt as aa,Zt as ba,er as ca,tr as da,ze as ea,rr as fa,sr as ga,nr as ha,ir as ia,ar as ja,or as ka,ur as la,cr as ma,_r as na,be as oa,dr as pa,lr as qa,Er as ra,Tr as sa,pr as ta,mr as ua,B as va,gr as wa,Nr as xa,br as ya,Lr as za,Sr as Aa,Rr as Ba,tt as Ca,rt as Da,Ar as Ea,wr as Fa,fr as Ga,Or as Ha,hr as Ia,xr as Ja,yr as Ka,Ir as La,we as Ma,Cr as Na,Ur as Oa,kr as Pa,Dr as Qa,vr as Ra,Xr as Sa,Mr as Ta,Fr as Ua,Pr as Va,Hr as Wa,Wr as Xa,qr as Ya,jr as Za,Br as _a,Gr as $a,Yr as ab,Jr as bb,$r as cb,Kr as db,Vr as eb,zr as fb,Qr as gb,Zr as hb,es as ib,ts as jb,rs as kb,ss as lb,ns as mb,is as nb,as as ob,os as pb,us as qb,cs as rb,_s as sb,ds as tb,it as ub,ls as vb,Es as wb,Ts as xb,ot as yb,ps as zb,ms as Ab,gs as Bb,Ns as Cb,bs as Db,Ls as Eb,Ss as Fb,I as Gb,Rs as Hb,As as Ib,ws as Jb,fs as Kb,Os as Lb,hs as Mb,xs as Nb,ut as Ob,ys as Pb,Is as Qb,Cs as Rb,Us as Sb,fe as Tb,ks as Ub,Ds as Vb,vs as Wb,Xs as Xb,Ms as Yb,Fs as Zb,Ps as _b,Hs as $b};