mcp-scraper 0.97.1 → 0.99.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/CHANGELOG.md +11 -2434
  2. package/README.md +16 -412
  3. package/dist/bin/api-server.js +3 -2
  4. package/dist/bin/mcp-scraper-cli.js +33 -27
  5. package/dist/bin/mcp-scraper-core.js +9 -1
  6. package/dist/bin/mcp-scraper-install.js +17 -2
  7. package/dist/bin/mcp-stdio-server.js +9 -1
  8. package/dist/bin/paa-harvest.js +8 -1
  9. package/dist/index.cjs +5 -21830
  10. package/dist/index.d.ts +14 -607
  11. package/dist/index.js +5 -39
  12. package/dist/transport.d.ts +35 -0
  13. package/package.json +11 -51
  14. package/THIRD_PARTY_NOTICES.html +0 -203
  15. package/dist/actions-5X5CQAKO.js +0 -1
  16. package/dist/artifacts-4ZDNP2JW.js +0 -1
  17. package/dist/artifacts-N62OPIT5.js +0 -1
  18. package/dist/artifacts-PSADD5OC.js +0 -1
  19. package/dist/artifacts-RUR3OHAK.js +0 -1
  20. package/dist/blob-store-GIH26EDO.js +0 -1
  21. package/dist/bundle-GS657HXG.js +0 -1
  22. package/dist/chunk-24YDQ3EO.js +0 -5
  23. package/dist/chunk-2L7CHN5N.js +0 -4
  24. package/dist/chunk-3F7AFM53.js +0 -1
  25. package/dist/chunk-4AEW53RU.js +0 -954
  26. package/dist/chunk-4HZXATHB.js +0 -27
  27. package/dist/chunk-4YZ74SJ6.js +0 -1
  28. package/dist/chunk-4ZVO6GX4.js +0 -1
  29. package/dist/chunk-55ZANTHL.js +0 -3
  30. package/dist/chunk-5RQWFYXY.js +0 -930
  31. package/dist/chunk-5TQINRZN.js +0 -12
  32. package/dist/chunk-5UQAL7HV.js +0 -41
  33. package/dist/chunk-6D25Q5BR.js +0 -21728
  34. package/dist/chunk-6N5EC7ZO.js +0 -1
  35. package/dist/chunk-7POHNTVW.js +0 -1
  36. package/dist/chunk-7SR7MEU5.js +0 -62
  37. package/dist/chunk-ANQ4JJVI.js +0 -71
  38. package/dist/chunk-B3JRL45T.js +0 -1
  39. package/dist/chunk-B4ZKPLSP.js +0 -1
  40. package/dist/chunk-B5Y26E3A.js +0 -1
  41. package/dist/chunk-C3JWX6KM.js +0 -10
  42. package/dist/chunk-C7MGJUTU.js +0 -1
  43. package/dist/chunk-CNSVZTTT.js +0 -13
  44. package/dist/chunk-EYGA6LOU.js +0 -1
  45. package/dist/chunk-F3M7INSN.js +0 -41
  46. package/dist/chunk-FLAWC5PF.js +0 -5
  47. package/dist/chunk-FM7BX2LU.js +0 -159
  48. package/dist/chunk-HCK6PLM3.js +0 -3
  49. package/dist/chunk-HNNYXMSI.js +0 -1
  50. package/dist/chunk-IFPION5D.js +0 -121
  51. package/dist/chunk-IPQOBOFY.js +0 -1
  52. package/dist/chunk-J7XDXIB6.js +0 -163
  53. package/dist/chunk-JHDD6R3O.js +0 -8
  54. package/dist/chunk-JMZIDHYQ.js +0 -2
  55. package/dist/chunk-K3VDGJNK.js +0 -1
  56. package/dist/chunk-KBZY2OGP.js +0 -11
  57. package/dist/chunk-KJQXUZ4Y.js +0 -4
  58. package/dist/chunk-KXJCGV3H.js +0 -1
  59. package/dist/chunk-NALXKTUU.js +0 -1
  60. package/dist/chunk-NNOX3FYG.js +0 -198
  61. package/dist/chunk-NQFTETVC.js +0 -189
  62. package/dist/chunk-OILOHQNL.js +0 -2
  63. package/dist/chunk-OLYPLX5C.js +0 -1
  64. package/dist/chunk-P6CDR3RM.js +0 -1
  65. package/dist/chunk-PKQHHCO4.js +0 -20
  66. package/dist/chunk-QCBCOEH5.js +0 -1
  67. package/dist/chunk-QER2ELZP.js +0 -1
  68. package/dist/chunk-RDHGQ2WZ.js +0 -1
  69. package/dist/chunk-SDQW7IJN.js +0 -1
  70. package/dist/chunk-SEZETSB3.js +0 -1
  71. package/dist/chunk-SJNSTO3C.js +0 -42
  72. package/dist/chunk-TZYITYL4.js +0 -2
  73. package/dist/chunk-UIOSADPB.js +0 -1718
  74. package/dist/chunk-UNEJYZ4T.js +0 -102
  75. package/dist/chunk-UUJYICAJ.js +0 -1
  76. package/dist/chunk-VVSHZV5S.js +0 -73
  77. package/dist/chunk-WNUXMPVX.js +0 -1
  78. package/dist/chunk-XNTAHMPA.js +0 -218
  79. package/dist/chunk-ZDECILF6.js +0 -16
  80. package/dist/chunk-ZNPGM3XE.js +0 -4
  81. package/dist/compatibility-UPPKZ4KY.js +0 -1
  82. package/dist/contracts-GUXGFCVV.js +0 -1
  83. package/dist/core-schema-Y47YFKH2.js +0 -899
  84. package/dist/direct-completion-ZVPPEBDU.js +0 -1
  85. package/dist/dispatch-GRMMPKQD.js +0 -1
  86. package/dist/editorial-reading-room/assets/app.js +0 -433
  87. package/dist/editorial-reading-room/assets/index.html +0 -139
  88. package/dist/editorial-reading-room/assets/styles.css +0 -1091
  89. package/dist/index.d.cts +0 -607
  90. package/dist/jobs-NRZHGQ7I.js +0 -1
  91. package/dist/media-artifacts-67CJWI7O.js +0 -1
  92. package/dist/metering-YHZ46GV4.js +0 -1
  93. package/dist/migrations-3AKEC5QE.js +0 -1
  94. package/dist/queue-2VKW7SGH.js +0 -1
  95. package/dist/reconciliation-QC6SILLR.js +0 -1
  96. package/dist/report-artifact-offload-PQNFDNPL.js +0 -1
  97. package/dist/repository-CYXVMYAI.js +0 -1
  98. package/dist/repository-UKDA4IWP.js +0 -1
  99. package/dist/server-EYMJROPX.js +0 -5544
  100. package/dist/settlement-47EUTSGX.js +0 -1
  101. package/dist/vendor-errors-647LSH6H.js +0 -1
  102. package/dist/worker-AWJF7UYR.js +0 -1
  103. package/public/.well-known/xray-install.json +0 -183
  104. package/public/agent-install.md +0 -200
@@ -1,189 +0,0 @@
1
- import{i as T,m as j}from"./chunk-KXJCGV3H.js";import{n as f,r as w}from"./chunk-ANQ4JJVI.js";import{d as E,e as C,i as p}from"./chunk-C7MGJUTU.js";import{a as o}from"./chunk-WNUXMPVX.js";import{createHash as U}from"crypto";import{gunzipSync as k,gzipSync as $}from"zlib";var H=10,m=20*1024*1024;function g(t){return U("sha256").update(t).digest("hex")}function W(t){return!t.acquiredHtml||t.extractionStatus==="failed"?null:{pageId:t.pageId??g(t.archivedUrl??t.url),url:t.archivedUrl??t.url,html:t.acquiredHtml,mainHtml:t.mainHtml??"",markdown:t.bodyMarkdown,htmlSha256:t.htmlSha256??g(t.acquiredHtml),markdownSha256:t.markdownSha256??g(t.bodyMarkdown)}}function A(t){return Buffer.from(JSON.stringify({version:"site-extract-content.v1",pages:t}))}async function I(t){let e=t.pages.flatMap(i=>{let c=W(i);return c?[c]:[]}),n=new Map,r=[],a=0,s=async()=>{if(!r.length)return;let i=A(r);if(i.length>m)throw new Error(`site export content chunk exceeds ${m} bytes`);let c=g(r.map(l=>l.pageId).join("\0")).slice(0,16),u=await T({ownerId:t.ownerId,jobId:t.jobId,createdAt:t.createdAt,chunkKey:`content-${String(a).padStart(4,"0")}-${c}`,content:$(i,{level:6})});for(let l of r)n.set(l.url,{artifactId:u.artifactId,artifactSha256:u.sha256,pageId:l.pageId,uncompressedBytes:i.length});a++,r=[]};for(let i of e){let c=[...r,i];if(r.length>0&&(c.length>H||A(c).length>m)&&await s(),r.push(i),A(r).length>m)throw new Error(`page ${i.pageId} exceeds the durable content chunk limit`)}return await s(),n}function Y(t){let e=new Map;return async n=>{let r=e.get(n.artifactId);if(r&&r.digest!==n.artifactSha256)throw new Error("site export content chunk checksum mismatch");let a=r?.chunk;if(!a){let i=await j({artifactId:n.artifactId,ownerId:t});if(!i)throw new Error("site export content chunk is missing or unauthorized");if(g(i)!==n.artifactSha256)throw new Error("site export content chunk checksum mismatch");let c=k(i);if(c.length>m)throw new Error("site export content chunk exceeds its read limit");if(a=JSON.parse(c.toString("utf8")),a.version!=="site-extract-content.v1"||!Array.isArray(a.pages))throw new Error("site export content chunk has an unsupported contract");for(e.set(n.artifactId,{digest:n.artifactSha256,chunk:a});e.size>2;)e.delete(e.keys().next().value)}let s=a.pages.find(i=>i.pageId===n.pageId);if(!s)throw new Error("site export page is missing from its content chunk");if(g(s.html)!==s.htmlSha256||g(s.markdown)!==s.markdownSha256)throw new Error("site export page checksum mismatch");return s}}import{randomUUID as J}from"crypto";function x(t,e,n=!1){if(!e)return{sql:`NOT EXISTS (SELECT 1 FROM operation_executions x JOIN operation_runs r ON r.id=x.run_id
2
- WHERE r.id='extract-site:' || site_extract_jobs.id AND r.tool='extract_site')`,args:[]};if(e.workflow.runId!==`extract-site:${t}`||n&&(!e.phase||e.recovery))return{sql:"0",args:[]};let r=f(e.workflow,{tool:"extract_site",jobId:t,recovery:e.recovery}),a="site_extract_jobs.user_id = ?";if(!e.phase)return{sql:`(${r.sql} AND ${a})`,args:[...r.args,e.workflow.userId]};if(e.phase.userId!==e.workflow.userId)return{sql:"0",args:[]};let s=f(e.phase,{tool:"extract_site_phase",jobId:t});return{sql:`(${r.sql} AND ${a} AND ${s.sql})`,args:[...r.args,e.workflow.userId,...s.args]}}function h(t="site_extract_jobs."){return`(${w(`${t}id`,`${t}user_id`,"extract_site")}
3
- AND ${w(`${t}id`,`${t}user_id`,"extract_site_phase")})`}function y(){return w("site_extract_jobs.id","site_extract_jobs.user_id","extract_site_phase")}function D(t="site_extract_jobs."){return`(${t}status='running' OR (${t}status='pending' AND ${t}execution_generation=0 AND (
4
- EXISTS (SELECT 1 FROM operation_runs r WHERE r.id='extract-site:' || ${t}id AND r.user_id=${t}user_id AND r.tool='extract_site')
5
- OR COALESCE(json_extract(${t}options,'$.__websiteExecutionProtocol'),0) <> 1)))`}var q="xray_entitlement";function st(t){let e=Math.max(1,Number(t.options.effectiveMaxPages??t.options.maxPages??1)),n=Math.max(e,Number(t.options.requestedMaxPages??e)),r=n>e;return{requestedMaxPages:n,effectiveMaxPages:e,creditLimited:r,creditTruncated:r&&t.totalUrls>=e}}function it(t,e=!1){return t.successfulUrls===0?"failed":t.failedUrls>0||t.remainingUrls>0||e?"partial":"complete"}function _(t){let e=Number(t.total_urls??0),n=t.attempted_urls==null,r=Number(n?t.done_urls??0:t.attempted_urls),a=Number(n?t.done_urls??0:t.successful_urls??0),s=Number(t.failed_urls??Math.max(0,r-a)),i=t.options?JSON.parse(String(t.options)):{},c=i.__websiteExecutionProtocol;delete i.__websiteExecutionProtocol;let u={id:String(t.id),userId:t.user_id!=null?Number(t.user_id):null,idempotencyKey:t.idempotency_key!=null?String(t.idempotency_key):null,requestFingerprint:t.request_fingerprint!=null?String(t.request_fingerprint):null,status:t.status!=null?String(t.status):"pending",executionGeneration:Number(t.execution_generation??0),refinalizeUntil:t.refinalize_until==null?null:String(t.refinalize_until),settlementPlan:t.settlement_plan_json?JSON.parse(String(t.settlement_plan_json)):null,settlementReceipt:t.settlement_receipt_json?JSON.parse(String(t.settlement_receipt_json)):null,dispatchClaimToken:t.dispatch_claim_token==null?null:String(t.dispatch_claim_token),dispatchClaimUntil:t.dispatch_claim_until==null?null:String(t.dispatch_claim_until),dispatchedAt:t.dispatched_at==null?null:String(t.dispatched_at),dispatchAttempts:Number(t.dispatch_attempts??0),dispatchError:t.dispatch_error==null?null:String(t.dispatch_error),startUrl:String(t.start_url??""),options:i,totalUrls:e,doneUrls:r,attemptedUrls:r,successfulUrls:a,failedUrls:s,remainingUrls:Math.max(0,e-r),artifacts:t.artifacts?JSON.parse(String(t.artifacts)):null,error:t.error!=null?String(t.error):null,publicError:C(t.public_error_json),billedMc:t.billed_mc!=null?Number(t.billed_mc):null,createdAt:String(t.created_at??""),updatedAt:String(t.updated_at??"")};return c===1&&Object.defineProperty(u,"executionProtocol",{value:1,enumerable:!1}),u}async function v(t,e){let r=await o().execute({sql:"SELECT * FROM site_extract_jobs WHERE user_id = ? AND idempotency_key = ? LIMIT 1",args:[t,e]});return r.rows[0]?_(r.rows[0]):null}async function ot(t){let n=await o().execute({sql:`INSERT OR IGNORE INTO site_extract_jobs
6
- (id, user_id, status, start_url, options, idempotency_key, request_fingerprint, created_at, updated_at)
7
- VALUES (?, ?, 'pending', ?, ?, ?, ?, datetime('now'), datetime('now'))`,args:[t.jobId,t.userId,t.startUrl,JSON.stringify({...t.options,__websiteExecutionProtocol:1}),t.idempotencyKey,t.requestFingerprint]}),r=await v(t.userId,t.idempotencyKey);if(!r)throw new Error("idempotent extract job was not persisted");return{job:r,created:n.rowsAffected===1,conflict:r.requestFingerprint!==t.requestFingerprint}}async function P(t){let n=await o().execute({sql:"SELECT * FROM site_extract_jobs WHERE id = ?",args:[t]});return n.rows[0]?_(n.rows[0]):null}async function ct(t=25){return(await o().execute({sql:`SELECT * FROM site_extract_jobs
8
- WHERE billed_mc IS NULL AND status IN ('complete', 'partial', 'failed')
9
- AND (next_settlement_at IS NULL OR next_settlement_at <= datetime('now'))
10
- ORDER BY updated_at ASC LIMIT ?`,args:[Math.max(1,Math.min(100,Math.round(t)))]})).rows.map(r=>_(r))}var N=`(
11
- EXISTS (SELECT 1 FROM billing_debits d
12
- WHERE d.idempotency_key = json_extract(site_extract_jobs.options, '$.debitKey')
13
- AND d.user_id = site_extract_jobs.user_id AND d.status = 'applied'
14
- AND d.operation = 'extract_site_hold'
15
- AND json_type(options, '$.heldMc') = 'integer'
16
- AND json_extract(options, '$.heldMc') > 0
17
- AND json_extract(options, '$.heldMc') <= 9007199254740991
18
- AND d.amount_mc = json_extract(options, '$.heldMc')
19
- AND COALESCE(json_extract(options, '$.billingClass'), 'credits') = 'credits')
20
- OR (json_extract(options, '$.billingClass') = 'xray_entitlement'
21
- AND json_type(options, '$.heldMc') IN ('integer', 'real')
22
- AND json_extract(options, '$.heldMc') = 0 AND json_extract(options, '$.debitKey') IS NULL
23
- AND json_extract(options, '$.xraySetupReceipt.billingClass') = 'xray_entitlement'
24
- AND json_type(options, '$.xraySetupReceipt.consumesMcpScraperCredits') = 'false'
25
- AND json_type(options, '$.xraySetupReceipt.heldMc') IN ('integer', 'real')
26
- AND json_extract(options, '$.xraySetupReceipt.heldMc') = 0
27
- AND json_type(options, '$.xraySetupReceipt.billedMc') IN ('integer', 'real')
28
- AND json_extract(options, '$.xraySetupReceipt.billedMc') = 0))`;async function ut(t){let e=await o().execute({sql:`SELECT * FROM site_extract_jobs WHERE id = ? AND user_id > 0
29
- AND status IN ('pending', 'running') AND billed_mc IS NULL
30
- AND execution_generation = 0 AND ${N}`,args:[t]});return e.rows[0]?_(e.rows[0]):null}async function F(t=25,e=2){let n=Math.max(1,Math.min(60,Math.round(e)));return(await o().execute({sql:`SELECT * FROM site_extract_jobs WHERE status = 'pending' AND billed_mc IS NULL
31
- AND execution_generation = 0 AND dispatched_at IS NULL AND ${N}
32
- AND (dispatch_claim_token IS NULL OR dispatch_claim_until <= datetime('now'))
33
- AND (next_dispatch_at IS NULL OR next_dispatch_at <= datetime('now'))
34
- AND updated_at <= datetime('now', ?) ORDER BY updated_at, id LIMIT ?`,args:[`-${n} minutes`,Math.max(1,Math.min(100,Math.round(t)))]})).rows.map(a=>_(a))}async function lt(t=25){return(await o().execute({sql:`SELECT * FROM site_extract_jobs WHERE status IN ('pending', 'running') AND billed_mc IS NULL
35
- AND execution_generation = 0 AND ${N}
36
- AND (
37
- (dispatched_at <= datetime('now', '-30 seconds') AND NOT EXISTS (SELECT 1 FROM operation_executions e WHERE e.run_id = 'extract-site:' || site_extract_jobs.id))
38
- OR EXISTS (SELECT 1 FROM operation_executions e JOIN operation_runs r ON r.id = e.run_id
39
- WHERE e.run_id = 'extract-site:' || site_extract_jobs.id AND r.status = 'running'
40
- AND e.phase = 'claimed' AND e.expires_at_ms <= CAST((julianday('now') - 2440587.5) * 86400000 AS INTEGER))
41
- ) ORDER BY updated_at, id LIMIT ?`,args:[Math.max(1,Math.min(100,Math.round(t)))]})).rows.map(n=>_(n))}async function dt(t={}){let e=t.jobId?[t.jobId]:(await F(t.limit)).map(r=>r.id),n=[];for(let r of e){let a=J(),i=(await o().execute({sql:`UPDATE site_extract_jobs SET dispatch_claim_token = ?, dispatch_claim_until = datetime('now', ?),
42
- dispatch_attempts = dispatch_attempts + 1, dispatch_error = NULL, next_dispatch_at = NULL,
43
- updated_at = datetime('now')
44
- WHERE id = ? AND status = 'pending' AND billed_mc IS NULL AND execution_generation = 0
45
- AND dispatched_at IS NULL AND ${N}
46
- AND (dispatch_claim_token IS NULL OR dispatch_claim_until <= datetime('now'))
47
- AND (next_dispatch_at IS NULL OR next_dispatch_at <= datetime('now'))
48
- RETURNING id, dispatch_claim_token, dispatch_attempts`,args:[a,`+${Math.max(15,Math.min(3600,Math.round(t.leaseSeconds??300)))} seconds`,r]})).rows[0];i&&n.push({id:String(i.id),claimToken:String(i.dispatch_claim_token),attempts:Number(i.dispatch_attempts)})}return n}async function _t(t,e){return(await o().execute({sql:`SELECT id FROM site_extract_jobs WHERE id = ? AND status = 'pending' AND billed_mc IS NULL
49
- AND execution_generation = 0 AND dispatched_at IS NULL AND dispatch_claim_token = ?
50
- AND dispatch_claim_until > datetime('now') AND ${N}`,args:[t,e]})).rows.length===1}async function gt(t,e){return(await o().execute({sql:`UPDATE site_extract_jobs SET dispatched_at = datetime('now'), dispatch_claim_token = NULL,
51
- dispatch_claim_until = NULL, next_dispatch_at = NULL, dispatch_error = NULL, updated_at = datetime('now')
52
- WHERE id = ? AND execution_generation = 0 AND dispatched_at IS NULL
53
- AND dispatch_claim_token = ? AND dispatch_claim_until > datetime('now')`,args:[t,e]})).rowsAffected===1}async function pt(t,e,n,r){return(await o().execute({sql:`UPDATE site_extract_jobs SET dispatch_error = ?, next_dispatch_at = datetime('now', ?),
54
- dispatch_claim_token = NULL, dispatch_claim_until = NULL, updated_at = datetime('now')
55
- WHERE id = ? AND status = 'pending' AND billed_mc IS NULL AND execution_generation = 0
56
- AND dispatched_at IS NULL AND dispatch_claim_token = ? AND dispatch_claim_until > datetime('now')`,args:[n.slice(0,2e3),`+${Math.max(15,Math.min(3600,Math.round(r)))} seconds`,t,e]})).rowsAffected===1}async function Et(t,e,n=0){await o().execute({sql:`UPDATE site_extract_jobs SET
57
- settlement_attempts = settlement_attempts + 1,
58
- settlement_error = ?,
59
- next_settlement_at = datetime('now', '+15 minutes'),
60
- updated_at = datetime('now')
61
- WHERE id = ? AND billed_mc IS NULL AND execution_generation = ? AND status IN ('complete', 'partial', 'failed')`,args:[p(e).slice(0,1e3),t,n]})}function O(t=""){return`((${t}execution_generation = 0 AND ${t}updated_at <= datetime('now', ?))
62
- OR (${t}execution_generation > 0 AND ${t}refinalize_until <= datetime('now')))`}async function mt(t=25,e=60){let n=o(),r=Math.max(15,Math.min(1440,Math.round(e)));return(await n.execute({sql:`SELECT j.* FROM site_extract_jobs j
63
- LEFT JOIN billing_debits d
64
- ON d.idempotency_key = json_extract(j.options, '$.debitKey')
65
- AND d.user_id = j.user_id
66
- AND d.status = 'applied'
67
- WHERE ${D("j.")}
68
- AND j.billed_mc IS NULL
69
- AND (
70
- json_extract(j.options, '$.debitKey') IS NULL
71
- OR d.idempotency_key IS NOT NULL
72
- )
73
- AND ${O("j.")} AND ${h("j.")}
74
- ORDER BY j.updated_at ASC LIMIT ?`,args:[`-${r} minutes`,Math.max(1,Math.min(100,Math.round(t)))]})).rows.map(s=>_(s))}async function xt(t,e=60){let n=o(),r=Math.max(15,Math.min(1440,Math.round(e)));return(await n.execute({sql:`UPDATE site_extract_jobs
75
- SET status = 'failed',
76
- error = 'Background extraction attempt expired; completed pages were preserved and settlement is pending.',
77
- public_error_json = ?,
78
- updated_at = datetime('now')
79
- WHERE id = ?
80
- AND ${D()}
81
- AND billed_mc IS NULL
82
- AND ${O()} AND ${h()}`,args:[E({error_code:"extraction_failed",error_type:"extraction",message:"The background extraction attempt expired. Completed pages were preserved; retry after settlement completes.",retryable:!0,charge_status:"refund_pending"}),t,`-${r} minutes`]})).rowsAffected===1}async function Nt(t){let e=await o().execute({sql:`UPDATE site_extract_jobs
83
- SET status = 'running', execution_generation = execution_generation + 1,
84
- refinalize_until = datetime('now', '+60 minutes'), updated_at = datetime('now')
85
- WHERE id = ? AND (settlement_plan_json IS NULL OR billed_mc IS NOT NULL) AND (status = 'failed' OR (
86
- status = 'running' AND execution_generation > 0 AND refinalize_until <= datetime('now')
87
- )) RETURNING *`,args:[t]});return e.rows[0]?_(e.rows[0]):null}async function z(t,e=0){return(await o().execute({sql:`SELECT 1 FROM site_extract_jobs WHERE id = ? AND status IN ('pending', 'running')
88
- AND execution_generation = ? AND (execution_generation = 0 OR refinalize_until > datetime('now'))`,args:[t,e]})).rows.length===1}async function bt(t,e,n=0){await o().execute({sql:`UPDATE site_extract_jobs SET billed_mc = 0, settlement_error = ?, updated_at = datetime('now')
89
- WHERE id = ? AND billed_mc IS NULL AND execution_generation = ? AND status IN ('complete', 'partial', 'failed')`,args:[p(e).slice(0,1e3),t,n]})}async function wt(t,e,n){let r=o(),a=x(t,n);await r.execute({sql:`UPDATE site_extract_jobs
90
- SET status = 'running', total_urls = MAX(total_urls, ?), updated_at = datetime('now')
91
- WHERE id = ? AND status IN ('pending', 'running') AND execution_generation = 0 AND ${a.sql}`,args:[e,t,...a.args]})}async function St(t,e,n){if(e.length===0)return;let r=o(),a=await P(t);if(!a||!await z(t)){if(n)throw Error("site_crawl_page_write_not_current");return}let s=x(t,n,!0);if(!(await r.execute({sql:`SELECT 1 FROM site_extract_jobs WHERE id=? AND ${s.sql}`,args:[t,...s.args]})).rows.length){if(n)throw Error("site_crawl_page_write_not_current");return}let c=a?.userId!=null?await I({ownerId:String(a.userId),jobId:t,createdAt:a.createdAt,pages:e}):new Map,u=e.map(d=>{let{discoveryLinks:M,acquiredHtml:b,mainHtml:R,...L}=d;return L.contentRef=c.get(d.archivedUrl??d.url)??d.contentRef,{sql:`INSERT INTO site_extract_pages (job_id, url, page)
92
- SELECT ?, ?, ?
93
- WHERE EXISTS (
94
- SELECT 1 FROM site_extract_jobs
95
- WHERE id = ? AND status IN ('pending', 'running') AND execution_generation = 0 AND ${s.sql}
96
- )
97
- ON CONFLICT(job_id, url) DO UPDATE SET page = excluded.page
98
- WHERE NOT CASE
99
- WHEN json_valid(site_extract_pages.page) = 0 THEN 0
100
- WHEN json_extract(site_extract_pages.page, '$.extractionStatus') IS NOT NULL
101
- THEN json_extract(site_extract_pages.page, '$.extractionStatus') = 'successful'
102
- ELSE COALESCE(
103
- json_extract(site_extract_pages.page, '$.status') >= 200
104
- AND json_extract(site_extract_pages.page, '$.status') < 300
105
- AND json_extract(site_extract_pages.page, '$.wordCount') > 0,
106
- 0
107
- )
108
- END
109
- OR CASE
110
- WHEN json_valid(excluded.page) = 0 THEN 0
111
- WHEN json_extract(excluded.page, '$.extractionStatus') IS NOT NULL
112
- THEN json_extract(excluded.page, '$.extractionStatus') = 'successful'
113
- ELSE COALESCE(
114
- json_extract(excluded.page, '$.status') >= 200
115
- AND json_extract(excluded.page, '$.status') < 300
116
- AND json_extract(excluded.page, '$.wordCount') > 0,
117
- 0
118
- )
119
- END`,args:[t,d.archivedUrl??d.url,JSON.stringify(L),t,...s.args]}}),l,S;try{S=await r.batch([...u,{sql:`UPDATE site_extract_jobs SET
120
- done_urls = (SELECT COUNT(*) FROM site_extract_pages WHERE job_id = ?),
121
- attempted_urls = (SELECT COUNT(*) FROM site_extract_pages WHERE job_id = ?),
122
- successful_urls = (
123
- SELECT COUNT(*) FROM site_extract_pages
124
- WHERE job_id = ? AND CASE
125
- WHEN json_extract(page, '$.extractionStatus') IS NOT NULL
126
- THEN json_extract(page, '$.extractionStatus') = 'successful'
127
- ELSE json_extract(page, '$.status') >= 200
128
- AND json_extract(page, '$.status') < 300
129
- AND json_extract(page, '$.wordCount') > 0
130
- END
131
- ),
132
- failed_urls = (
133
- SELECT COUNT(*) FROM site_extract_pages
134
- WHERE job_id = ? AND NOT CASE
135
- WHEN json_extract(page, '$.extractionStatus') IS NOT NULL
136
- THEN json_extract(page, '$.extractionStatus') = 'successful'
137
- ELSE COALESCE(
138
- json_extract(page, '$.status') >= 200
139
- AND json_extract(page, '$.status') < 300
140
- AND json_extract(page, '$.wordCount') > 0,
141
- 0
142
- )
143
- END
144
- ),
145
- updated_at = datetime('now')
146
- WHERE id = ? AND status IN ('pending', 'running') AND execution_generation = 0 AND ${s.sql}`,args:[t,t,t,t,t,...s.args]}],"write")}catch(d){l=d}if(l){let d=await Promise.all(u.map(b=>r.execute({sql:"SELECT page FROM site_extract_pages WHERE job_id=? AND url=?",args:b.args.slice(0,2)})));if(!(await r.execute({sql:`SELECT 1 FROM site_extract_jobs WHERE id=? AND ${s.sql}
147
- AND attempted_urls=(SELECT COUNT(*) FROM site_extract_pages WHERE job_id=?)
148
- AND successful_urls=(SELECT COUNT(*) FROM site_extract_pages WHERE job_id=site_extract_jobs.id AND CASE
149
- WHEN json_extract(page,'$.extractionStatus') IS NOT NULL THEN json_extract(page,'$.extractionStatus')='successful'
150
- ELSE COALESCE(json_extract(page,'$.status')>=200 AND json_extract(page,'$.status')<300 AND json_extract(page,'$.wordCount')>0,0) END)
151
- AND failed_urls=attempted_urls-successful_urls`,args:[t,...s.args,t]})).rows.length||d.some((b,R)=>b.rows[0]?.page!==u[R].args[2]))throw l}else if(n&&S?.at(-1)?.rowsAffected!==1)throw Error("site_crawl_page_write_not_current")}async function ft(t){return(await o().execute({sql:"SELECT page FROM site_extract_pages WHERE job_id = ? ORDER BY rowid",args:[t]})).rows.map(r=>JSON.parse(String(r.page)))}async function At(t,e=181){let n=o(),r=Math.max(1,Math.min(5001,Math.round(e)));return(await n.execute({sql:`SELECT DISTINCT CAST(images.value AS TEXT) AS url
152
- FROM site_extract_pages p,
153
- json_each(CASE WHEN json_valid(p.page) THEN p.page ELSE '{}' END, '$.imageLinks') images
154
- WHERE p.job_id = ?
155
- AND images.type = 'text'
156
- AND length(CAST(images.value AS TEXT)) BETWEEN 1 AND 4096
157
- LIMIT ?`,args:[t,r]})).rows.map(s=>String(s.url))}async function ht(t){let n=await o().execute({sql:`SELECT COUNT(*) AS n FROM site_extract_pages
158
- WHERE job_id = ? AND CASE
159
- WHEN json_extract(page, '$.extractionStatus') IS NOT NULL
160
- THEN json_extract(page, '$.extractionStatus') = 'successful'
161
- ELSE COALESCE(
162
- json_extract(page, '$.status') >= 200
163
- AND json_extract(page, '$.status') < 300
164
- AND json_extract(page, '$.wordCount') > 0,
165
- 0
166
- )
167
- END`,args:[t]});return Number(n.rows[0]?.n??0)}async function Dt(t,e,n,r=null,a=!1,s=null,i=0,c){let u=o(),l=x(t,c,!0);return(await u.execute({sql:`UPDATE site_extract_jobs
168
- SET status = ?, artifacts = ?, error = ?, public_error_json = ?, updated_at = datetime('now')
169
- WHERE id = ? AND execution_generation = ? AND (settlement_plan_json IS NULL OR billed_mc IS NOT NULL)
170
- AND (
171
- (execution_generation = 0 AND (status IN ('pending', 'running') OR (? = 1 AND status = 'failed')))
172
- OR (execution_generation > 0 AND status = 'running' AND refinalize_until > datetime('now'))
173
- ) AND (execution_generation > 0 OR ${l.sql})`,args:[n,JSON.stringify(e??[]),r?p(r).slice(0,2e3):null,E(s),t,i,a?1:0,...l.args]})).rowsAffected===1}async function Rt(t,e,n,r=0,a){let s=x(t,a);return(await o().execute({sql:`UPDATE site_extract_jobs
174
- SET status = 'failed', error = ?, public_error_json = ?, updated_at = datetime('now')
175
- WHERE id = ? AND status IN ('pending', 'running') AND execution_generation = ?
176
- AND (execution_generation = 0 OR refinalize_until > datetime('now'))
177
- AND (execution_generation > 0 OR (${s.sql} AND ${y()}))`,args:[p(e).slice(0,2e3),E(n),t,r,...s.args]})).rowsAffected===1}async function Lt(t,e,n){await o().execute({sql:`UPDATE site_extract_jobs
178
- SET status = 'failed', billed_mc = 0, error = ?, public_error_json = ?, updated_at = datetime('now')
179
- WHERE id = ? AND status = 'pending' AND billed_mc IS NULL`,args:[p(e).slice(0,2e3),E(n),t]})}async function Ct(t){return await o().execute({sql:`UPDATE site_extract_jobs SET settlement_plan_json = ?, updated_at = datetime('now')
180
- WHERE id = ? AND user_id = ? AND execution_generation = ? AND status = ?
181
- AND billed_mc IS NULL AND settlement_plan_json IS NULL`,args:[JSON.stringify(t),t.jobId,t.userId,t.generation,t.status]}),P(t.jobId)}async function Tt(t,e){let n=t.billingClass===q?"not_charged":e.netChargeMc>0?"charged":e.refundMc>0?"refunded":"not_charged";await o().execute({sql:`UPDATE site_extract_jobs SET billed_mc = ?, settlement_receipt_json = ?,
182
- public_error_json = CASE WHEN json_valid(public_error_json) THEN json_set(public_error_json, '$.charge_status', ?) ELSE public_error_json END,
183
- updated_at = datetime('now')
184
- WHERE id = ? AND user_id = ? AND execution_generation = ? AND status = ?
185
- AND billed_mc IS NULL AND settlement_plan_json = ?`,args:[e.netChargeMc,JSON.stringify(e),n,t.jobId,t.userId,t.generation,t.status,JSON.stringify(t)]})}async function jt(t,e,n,r,a,s=0){let{settleExtractJobCharge:i}=await import("./settlement-47EUTSGX.js");return i(t,e,n,r,a,s)}var B=25;async function*It(t){let e=o(),n=0;for(;;){let r=await e.execute({sql:`SELECT rowid AS cursor_id, page
186
- FROM site_extract_pages
187
- WHERE job_id = ? AND rowid > ?
188
- ORDER BY rowid
189
- LIMIT ${B}`,args:[t,n]});if(!r.rows.length)return;if(n=Number(r.rows.at(-1)?.cursor_id??n),!Number.isSafeInteger(n)||n<=0)throw new Error("site extract page cursor is invalid");yield r.rows.map(a=>JSON.parse(String(a.page)))}}export{Y as a,q as b,st as c,it as d,v as e,ot as f,P as g,ct as h,ut as i,lt as j,dt as k,_t as l,gt as m,pt as n,Et as o,mt as p,xt as q,Nt as r,z as s,bt as t,wt as u,St as v,ft as w,At as x,ht as y,Dt as z,Rt as A,Lt as B,Ct as C,Tt as D,jt as E,B as F,It as G};
@@ -1,2 +0,0 @@
1
- import{mkdirSync as p,openSync as f,writeFileSync as m,closeSync as c,unlinkSync as g}from"fs";import{homedir as S}from"os";import{join as s}from"path";var u=!0;function w(r){u=r}function d(r){return r.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,80)||"mcp-scraper-report"}function R(r){return r.split(`
2
- `).find(t=>t.startsWith("# "))?.replace(/^#\s+/,"").trim()||"MCP Scraper Report"}function v(r){return r?.trim()||process.env.MCP_SCRAPER_OUTPUT_DIR?.trim()||s(S(),"Downloads","mcp-scraper")}function C(r){if(!y())return null;let o=v(),t=null,e=null;try{p(o,{recursive:!0});let a=`${new Date().toISOString().replace(/[:.]/g,"-")}-${d(R(r))}`;for(let n=0;n<1e3;n++){let i=s(o,`${a}${n?"-"+n:""}.md`);try{t=f(i,"wx"),e=i;break}catch(l){if(l.code!=="EEXIST")throw l}}return t===null?null:(m(t,r,"utf8"),c(t),t=null,e)}catch{if(t!==null)try{c(t)}catch{}if(e!==null)try{g(e)}catch{}return null}}function y(){return u&&process.env.MCP_SCRAPER_SAVE_REPORTS!=="false"}export{w as a,d as b,v as c,C as d,y as e};
@@ -1 +0,0 @@
1
- import{load as w}from"cheerio";var T="script,style,noscript,svg,iframe,canvas,nav,header,footer,aside",_=4096;function l(r){return(r??"").replace(/\s+/g," ").trim()}function C(r){let e=r.replace(/[\x00-\x09\x0b\x0c\x0e-\x1f]/g," ").trim();if(!e)return null;try{return JSON.parse(e)}catch(a){let o=/at position (\d+)/.exec(a instanceof Error?a.message:"")?.[1];if(!o)return null;try{return JSON.parse(e.slice(0,Number(o)))}catch{return null}}}function f(r,e,a={value:2e3}){if(a.value--<=0||r==null)return;if(Array.isArray(r)){for(let d of r)f(d,e,a);return}if(typeof r!="object")return;let o=r,c=o["@type"];if(typeof c=="string"&&c&&e.add(c),Array.isArray(c))for(let d of c)typeof d=="string"&&d&&e.add(d);Array.isArray(o["@graph"])&&f(o["@graph"],e,a)}function N(r){let e=r("main").first();if(e.length)return e;let a=r("article").first();if(a.length)return a;let o=r("body").first();return o.length?o:r.root()}function x(r,e){let a=Number(r.attr(e)??0);return Number.isFinite(a)&&a>0?a:null}function P(r){let e=w(r),a={};e("meta").each((m,s)=>{let t=e(s),n=l(t.attr("name")??t.attr("property")).toLowerCase(),i=l(t.attr("content"));n&&i&&(a[n]=i)});let o=[];e("h1,h2,h3,h4,h5,h6").each((m,s)=>{let t=e(s),n=l(t.text());n&&o.push({level:Number(s.tagName.slice(1)),text:n})});let c=[],d=new Set;e('script[type="application/ld+json"]').each((m,s)=>{let t=C(e(s).text());t!=null&&(Array.isArray(t)?c.push(...t):c.push(t),f(t,d))});let g=new Set;e("[itemtype]").each((m,s)=>{let t=e(s).attr("itemtype")??"";for(let n of t.split(/\s+/))try{let i=new URL(n);if(i.hostname==="schema.org"||i.hostname==="www.schema.org"){let h=i.pathname.replace(/^\/+/,"");h&&g.add(h)}}catch{}});let u=N(e).clone();u.find(T).remove(),u.find("[href],[src],[srcset],[data-src],[data-srcset]").each((m,s)=>{let t=e(s);for(let n of["href","src","srcset","data-src","data-srcset"]){let i=t.attr(n);i&&i.length>_&&t.removeAttr(n)}}),u.find("img").each((m,s)=>{let t=e(s),n=t.attr("src");if(!n||n.startsWith("data:")){let i=t.attr("data-src")??t.attr("data-lazy-src")??t.attr("data-original");i&&t.attr("src",i)}});let b=u.html()??"",A=l(u.text()),p=[];e("a[href]").each((m,s)=>{let t=e(s),n=l(t.attr("href"));n&&p.push({href:n,text:l(t.text()),rel:l(t.attr("rel")).toLowerCase()||null})});let y=[];return e("img").each((m,s)=>{let t=e(s),n=Object.fromEntries(Object.entries(s.attribs??{}).map(([i,h])=>[i.toLowerCase(),h]));y.push({src:t.attr("src")??t.attr("data-src")??t.attr("data-lazy-src")??t.attr("data-original")??null,srcset:t.attr("srcset")??t.attr("data-srcset")??null,alt:t.attr("alt")??null,width:x(t,"width"),height:x(t,"height"),attributes:n})}),{$:e,sourceHtml:r,title:l(e("title").first().text())||null,meta:a,headings:o,schema:c,schemaTypes:[...d],microdataTypes:[...g],canonicalUrl:l(e('link[rel~="canonical"]').first().attr("href"))||null,mainHtml:b,mainText:A,bodyClass:e("body").first().attr("class")??"",links:p,images:y}}export{P as a};
@@ -1 +0,0 @@
1
- import{c as j}from"./chunk-5TQINRZN.js";import{k as X}from"./chunk-F3M7INSN.js";import{A as F,c as A,d as $,g as b,h as C,o as K,p as U,q as G,r as M,s as D,t as W,z as q}from"./chunk-NQFTETVC.js";import{a as B,b as L,c as H}from"./chunk-QER2ELZP.js";import{b as k,c as S,d as y,e as x,f as O,g as I,i as h,j as m,l as E,p as N}from"./chunk-ANQ4JJVI.js";import{h as v,i as z}from"./chunk-C7MGJUTU.js";import{a as d,b as J,c as T,d as R}from"./chunk-HNNYXMSI.js";import{randomUUID as oe}from"crypto";import{createHash as Q,randomUUID as V}from"crypto";function _(e,i=new Set){if(e===null||typeof e=="string"||typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e))return e;if(typeof e!="object"||!e)throw new d("Operation inputs must be finite JSON data");if(i.has(e))throw new d("Operation inputs cannot be cyclic");if(!Array.isArray(e)&&![Object.prototype,null].includes(Object.getPrototypeOf(e)))throw new d("Operation inputs must be plain JSON data");i.add(e);try{return Array.isArray(e)?e.map(t=>_(t,i)):Object.fromEntries(Object.keys(e).sort().map(t=>[t,_(e[t],i)]))}finally{i.delete(e)}}async function P(e){if(!Number.isSafeInteger(e.userId)||e.userId<=0)throw new d("Authenticated operation principal is required");if(e.jobId!=null&&(!e.jobId.trim()||e.jobId.length>512))throw new d("Operation job ID is invalid");let i=e.tool.trim();if(!i||i.length>100)throw new d("Operation tool is required and bounded");if(e.idempotencyKey!=null&&(!e.idempotencyKey.trim()||e.idempotencyKey.length>512))throw new d("Operation idempotency key is invalid");let t=e.leaseMs??3e5;if(!Number.isSafeInteger(t)||t<1e3||t>36e5)throw new d("Execution lease must be between one second and one hour");let n=JSON.stringify(_(e.normalizedInput));if(Buffer.byteLength(n)>64*1024)throw new d("Operation inputs exceed 64 KiB");let r=e.idempotencyKey?.trim()??V();return E({userId:e.userId,ownerScope:`user:${e.userId}`,tool:i,jobId:e.jobId??null,normalizedFlags:e.normalizedInput,idempotencyKey:r,requestFingerprint:Q("sha256").update(n).digest("hex")},V(),t,e.storeGate)}async function Y(e){let i=JSON.stringify(_(e.normalizedInput));if(!Number.isSafeInteger(e.userId)||e.userId<=0||Buffer.byteLength(i)>64*1024)throw new d("Invalid operation receipt principal/input");let{readOperationIntentResult:t}=await import("./repository-UKDA4IWP.js"),{operationIdentityHash:n}=await import("./contracts-GUXGFCVV.js");return t(e.userId,n(`user:${e.userId}\0${e.tool}\0${e.idempotencyKey}`),Q("sha256").update(i).digest("hex"))}async function we(e){let i=Date.now()+27e4,t=e.idempotencyKey?.trim()??oe();if(!t||t.length>512)return{status:400,body:{error_code:"invalid_request",message:"Idempotency-Key must contain 1 to 512 characters"}};let n=(a,c,p)=>({...a,body:{...a.body,operation:{runId:c,idempotencyKey:t,state:p}}}),r=(a,c,p)=>n({status:c==="pending"?202:503,headers:{"Retry-After":"2"},body:{...v({errorCode:"response_lost",retryable:!0,chargeStatus:p,details:{retry_guidance:"Retry the identical request with the returned idempotencyKey. Pending work is not started again; a saved response replays. Unknown work permits compensation only."}}),message:c==="pending"?"This operation is still running. Retry with the same idempotencyKey.":"The execution outcome is unknown. Retry with the same idempotencyKey for result or compensation recovery."}},a,c),s;try{s=await P({...e,idempotencyKey:t,leaseMs:3e5})}catch(a){return a instanceof d?n({status:400,body:{error_code:"invalid_request",message:a.message,retryable:!1}},null,"not_started"):a instanceof J?n({status:409,body:{error_code:"idempotency_conflict",message:a.message,retryable:!1}},null,"conflict"):r(null,"unknown")}let o=s.kind==="claimed"?s.claim.runId:s.runId;if(s.kind==="replay"){let a=JSON.parse(s.result.json);return!a||typeof a.status!="number"||!a.body||typeof a.body!="object"?r(o,"unknown"):n(a,o,"replayed")}if(s.kind==="pending")return r(o,"pending");if(s.kind==="unknown")try{let a=await y(o,e.userId);if(!a)return r(o,"unknown");let c=await e.recover(a);if(c.recover)return await h(a),n(c.reply,o,"unknown");let p=n(c.reply,o,"recovered_unknown"),l={json:JSON.stringify(p),status:"unknown"};return await O(a,l)?p:r(o,"unknown")}catch{return r(o,"unknown","refund_pending")}if(s.kind!=="claimed")return r(o,"unknown");let u=s.claim,f;try{if(f=await e.prepare(),f.rejection)return await I(u),n(f.rejection,o,"not_started");if(!await k(u))return r(o,"unknown");let a={claim:u,deadlineAt:i,assertActive:async()=>{if(B(i),!await m(u))throw Error("Execution ownership is no longer current")}},c;try{c=await e.execute(a,f.value)}catch{return await h(u),r(o,"unknown","refund_pending")}if(c.recover)return await h(u),n(c.reply,o,"unknown");let p=n(c.reply,o,c.reply.status<400?"succeeded":"failed");try{return await x(u,{json:JSON.stringify(p),status:p.status<400?"succeeded":"failed"})?p:r(o,"unknown")}catch{return await h(u).catch(()=>{}),r(o,"unknown")}}catch{return await I(u).catch(()=>{}),r(o,"unknown")}finally{await f?.release().catch(()=>{})}}var g=3e5;function ee(e){if(!e?.trim()||e.length>512)throw new d("A bounded framework workflow ID is required");return T(`workflow:${e}`)}async function ye(e){if(!Number.isSafeInteger(e.userId)||e.userId<=0)throw new d("Workflow principal is required");let i=ee(e.workflowId),t=await E(e,i,g);if(t.kind==="claimed"){let n;try{n=await k(t.claim)}catch(r){if(!await m(t.claim))throw r;n=!0}if(!n)throw Error("workflow_execution_start_unknown");return t}if(t.kind==="pending"){let n={runId:t.runId,userId:e.userId,token:i};if(await m(n)&&await S(n,g))return{kind:"claimed",claim:n}}return t}var te=e=>`${e.workflow.runId}:${e.phase}`;async function he(e){if(!await S(e.workflow,g))throw Error("workflow_execution_not_current");let i=te(e),t=await P({userId:e.workflow.userId,tool:e.tool,jobId:e.jobId,normalizedInput:e.normalizedInput,idempotencyKey:i,leaseMs:g});if(t.kind==="replay"){if(t.result.status!=="succeeded")throw Error(`operation_phase_unknown:${t.runId}`);return JSON.parse(t.result.json)}if(t.kind!=="claimed")throw Error(`operation_phase_${t.kind}:${t.runId}`);let n=t.claim;try{await e.prepare()}catch(r){throw await I(n).catch(()=>{}),r}try{let r;try{r=await k(n)}catch(a){if(!await m(n))throw a;r=!0}if(!r)throw Error("operation_phase_start_unknown");let s=Date.now()+g,o=async()=>{if(Date.now()>=s)throw new L(e.phase);if(!await m(e.workflow)||!await m(n))throw Error("operation_phase_claim_not_current")};await o();let u=await H(s,()=>e.execute({claim:n,deadlineAt:s,assertActive:o}),e.phase);await o();let f=JSON.stringify(u);if(f==null||!await x(n,{status:"succeeded",json:f}))throw Error("operation_phase_publication_unknown");return u}catch(r){await h(n).catch(()=>{});let s=await y(n.runId,n.userId).catch(()=>null);throw s&&await O(s,{status:"unknown",json:JSON.stringify({phase:e.phase,outcome:"unknown"})}).catch(()=>{}),r}}async function be(e,i){let t=await Y({userId:e.workflow.userId,tool:e.tool,idempotencyKey:te(e),normalizedInput:e.normalizedInput});if(!t||t.result.status!=="succeeded"||R({value:JSON.parse(t.result.json)})!==R({value:i}))throw Error("operation_phase_cache_receipt_unknown")}async function ge(e,i,t){let n={runId:e,userId:i,token:ee(t)};if(await m(n))return{claim:n,recovery:!1};let r=await y(e,i);return r?{claim:r,recovery:!0}:null}async function re(e,i,t){let n={json:JSON.stringify(i),status:e.recovery?"unknown":t};if(!(e.recovery?await O(e.claim,n,e.settlementGate):await x(e.claim,n)))throw Error("workflow_result_publication_unknown")}async function je(e){if(!await b(e))return{kind:"missing",body:{error:"job not found"}};let t=await M(e);if(!t)return{kind:"conflict",body:{error:"Only failed or expired recovery jobs can be re-finalized.",status:(await b(e))?.status??"missing"}};let n=t.executionGeneration;if(!await D(e,n))return{kind:"conflict",body:{error:"job state changed during re-finalization claim"}};let r;try{r=await X(t,{})}catch(l){throw await F(e,l instanceof Error?l.message:String(l),void 0,n).catch(()=>!1),l}let s=A(t),o=$(t,s.creditTruncated),u=o==="failed"?`No pages were extracted successfully (${t.failedUrls} failed, ${t.remainingUrls} remaining).`:o==="partial"?`${t.successfulUrls} pages succeeded; ${t.failedUrls} failed and ${t.remainingUrls} remain.${s.creditTruncated?` Credit availability limited this request from ${s.requestedMaxPages} to ${s.effectiveMaxPages} pages.`:""}`:null,f;try{f=await q(e,r,o,u,!1,null,n)}catch(l){let w=await b(e).catch(()=>null);if(!w||w.id!==e||w.executionGeneration!==n||w.status!==o||JSON.stringify(w.artifacts)!==JSON.stringify(r)||w.error!==(u?z(u).slice(0,2e3):null)||w.publicError!==null)throw l;f=!0}if(!f)return{kind:"conflict",body:{error:"job state changed during re-finalization"}};let a=await b(e);if(!a||a.executionGeneration!==n||a.status!==o)return{kind:"conflict",body:{error:"job state changed before re-finalization settlement"}};let c="already_settled_or_refunded";if(a.billedMc==null&&a.userId!=null){let l=await j(a);if(!l)throw Error("extract_settlement_acknowledgment_unknown");c=`settled: billed ${l.netChargeMc} mc, refunded ${l.refundMc} mc${l.expiredRefundMc?`, expired refund ${l.expiredRefundMc} mc`:""}`}let p=r.find(l=>l.contentType==="application/zip"||l.filename?.endsWith(".zip"));return{kind:"complete",body:{ok:!0,jobId:e,artifacts:r.length,settlement:c,bundleUrl:p?.url??null,bundleBytes:p?.bytes??null}}}async function Pe(e=25){let i=await U(e);for(let r of i)await G(r.id).catch(()=>!1);let t=await C(e),n={checked:new Set([...i,...t].map(r=>r.id)).size,settled:0,failed:0};for(let r of t){if(r.userId==null){await W(r.id,"Settlement abandoned because the legacy job has no user owner.",r.executionGeneration??0),n.failed+=1;continue}try{if(!await j(r))throw Error("extract_settlement_acknowledgment_unknown");if(r.executionGeneration===0&&await N(`extract-site:${r.id}`,r.userId)){let o=await y(`extract-site:${r.id}`,r.userId);o&&await re({claim:o,recovery:!0},{jobId:r.id,status:r.status,artifacts:r.artifacts??[]},"unknown")}n.settled+=1}catch(s){n.failed+=1;let o=s instanceof Error?s.message:String(s);await K(r.id,o,r.executionGeneration??0).catch(()=>{}),console.warn("[site-extract/reconcile]",r.id,o)}}return n}export{P as a,we as b,g as c,ee as d,ye as e,he as f,be as g,ge as h,re as i,je as j,Pe as k};
@@ -1,20 +0,0 @@
1
- var a="2026-10-10-operation-physical-attempts.1",s="operation_physical_attempts";async function r(t){let[i,_,p,E,c]=await Promise.all([t.execute(`PRAGMA table_info(${s})`),t.execute("PRAGMA index_info(operation_physical_identity)"),t.execute(`PRAGMA foreign_key_list(${s})`),t.execute("SELECT name,sql FROM sqlite_master WHERE name IN ('operation_physical_attempts','operation_physical_unresolved','operation_physical_identity')"),t.execute({sql:"SELECT 1 FROM schema_migrations WHERE version=?",args:[a]})]),n=e=>String(E.rows.find(o=>o.name===e)?.sql??"").replace(/\s+/g," ");return["id","parent_run_id","user_id","controller_token","claim_token","scope","attempt_number","provider","profile","intent_json","state","effects_json","resources_json","created_at","updated_at"].every(e=>i.rows.some(o=>o.name===e&&Number(o.notnull)===1))&&i.rows.some(e=>e.name==="id"&&Number(e.pk)===1)&&i.rows.some(e=>e.name==="receipt_json")&&_.rows.map(e=>e.name).join(",")==="parent_run_id,scope,attempt_number"&&p.rows.some(e=>e.table==="operation_runs"&&e.from==="parent_run_id"&&e.to==="id"&&e.on_delete==="CASCADE")&&n(s).includes("state IN ('prepared','effects_started','terminated','not_started','unknown')")&&n(s).includes("CHECK (json_valid(intent_json))")&&n(s).includes("CHECK (json_valid(effects_json))")&&n(s).includes("CHECK (json_valid(resources_json))")&&n(s).includes("CHECK (receipt_json IS NULL OR json_valid(receipt_json))")&&n(s).includes("CHECK ((state IN ('terminated','not_started','unknown') AND receipt_json IS NOT NULL)")&&n("operation_physical_identity").includes("CREATE UNIQUE INDEX")&&n("operation_physical_unresolved").includes("CREATE UNIQUE INDEX")&&n("operation_physical_unresolved").includes("WHERE state IN ('prepared','effects_started','unknown')")&&c.rows.length===1}async function l(t){if(!await r(t)){try{await t.batch([`CREATE TABLE IF NOT EXISTS operation_physical_attempts (
2
- id TEXT NOT NULL PRIMARY KEY,
3
- parent_run_id TEXT NOT NULL REFERENCES operation_runs(id) ON DELETE CASCADE,
4
- user_id INTEGER NOT NULL CHECK (user_id > 0),
5
- controller_token TEXT NOT NULL,
6
- claim_token TEXT NOT NULL,
7
- scope TEXT NOT NULL,
8
- attempt_number INTEGER NOT NULL CHECK (attempt_number > 0),
9
- provider TEXT NOT NULL CHECK (length(provider) BETWEEN 1 AND 100),
10
- profile TEXT NOT NULL CHECK (profile IN ('customer-funded','funded-parent')),
11
- intent_json TEXT NOT NULL CHECK (json_valid(intent_json)),
12
- state TEXT NOT NULL CHECK (state IN ('prepared','effects_started','terminated','not_started','unknown')),
13
- effects_json TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(effects_json)),
14
- resources_json TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(resources_json)),
15
- receipt_json TEXT CHECK (receipt_json IS NULL OR json_valid(receipt_json)),
16
- created_at TEXT NOT NULL DEFAULT (datetime('now')),
17
- updated_at TEXT NOT NULL DEFAULT (datetime('now')),
18
- CHECK ((state IN ('terminated','not_started','unknown') AND receipt_json IS NOT NULL)
19
- OR (state IN ('prepared','effects_started') AND receipt_json IS NULL))
20
- )`,"CREATE UNIQUE INDEX IF NOT EXISTS operation_physical_identity ON operation_physical_attempts(parent_run_id,scope,attempt_number)","CREATE UNIQUE INDEX IF NOT EXISTS operation_physical_unresolved ON operation_physical_attempts(parent_run_id) WHERE state IN ('prepared','effects_started','unknown')",{sql:"INSERT OR IGNORE INTO schema_migrations(version) VALUES (?)",args:[a]}],"write")}catch(i){if(!await r(t).catch(()=>!1))throw i}if(!await r(t))throw Error("Physical attempt schema is incomplete")}}export{l as a};
@@ -1 +0,0 @@
1
- import{g as t,i as d}from"./chunk-C7MGJUTU.js";var p={\u006b\u0065\u0072\u006e\u0065\u006c:"browserRuntime"},c=/error|message/i,_=(new RegExp("(?:spending|billing|organization|account).{0,80}(?:cap|limit|blocked|disabled|suspended)|(?:quota|capacity).{0,40}(?:reached|exceeded)|https?:\\/\\/\\S*(?:dashboard|on\u006b\u0065\u0072\u006e\u0065\u006c)", "i")),u=/\b(?:ENOENT|ENOTDIR|EACCES|EPERM|EISDIR|EMFILE|ENFILE)\b|\b(?:mkdir|open|stat|lstat|readFile|writeFile)\s+['"]?(?:\/|[A-Za-z]:\\)|(?:^|[\s'"])(?:\/Users|\/home|\/tmp|\/var|\/private|\/opt|\/srv|\/root)\//i,l=new Set(["\u006b\u0065\u0072\u006e\u0065\u006c_session_id","browser_session_id","\u006b\u0065\u0072\u006e\u0065\u006cSessionId","browserSessionId","sessionId","\u006b\u0065\u0072\u006e\u0065\u006c_delete_started","session_cleanup_started","\u006b\u0065\u0072\u006e\u0065\u006cDeleteStarted","sessionCleanupStarted","\u006b\u0065\u0072\u006e\u0065\u006c_delete_succeeded","session_cleanup_succeeded","\u006b\u0065\u0072\u006e\u0065\u006cDeleteSucceeded","sessionCleanupSucceeded","\u006b\u0065\u0072\u006e\u0065\u006c_delete_error","session_cleanup_error","\u006b\u0065\u0072\u006e\u0065\u006cDeleteError","sessionCleanupError","\u006b\u0065\u0072\u006e\u0065\u006cProxyId","proxyId","requestedProxyIdSuffix","retrievedProxyIdSuffix","provider","capture","providerName","fallbackFrom","acquisitionProvider","providerSessionObservedAt","reasonSource","outboundProviderMethod","service","serviceName","vendor","vendorName","organization","organizationId","accountId","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","provider_detail_json","provider_disconnect_observed","provider_disconnect_message","browserProvider","providerSessionId","providerLookupStatus","providerStatus","providerErrorCode","providerErrorMessage","providerReasonSource","providerDurationMs","providerBandwidthBytes","providerCaptcha","providerCheckedAt","providerDetail","providerDisconnectObserved","providerDisconnectMessage"]),v=new Set(["hosted_url","hostedUrl","live_view_url","liveViewUrl","cdp_ws_url","cdpWsUrl","browser_live_view_url"]),E=(new RegExp("\\b(?:wss?|https?):\\/\\/[^\\s\"'<>]*\\bon\u006b\u0065\u0072\u006e\u0065\u006c\\.com[^\\s\"'<>]*", "gi"));function b(e){return e.replace(E,"[browser-service]")}function n(e,o=""){if(typeof e=="string"){let r=b(e);return c.test(o)&&(_.test(e)||u.test(e))?r=t("service_unavailable"):c.test(o)&&(r=d(r)),r}if(Array.isArray(e))return e.map(r=>n(r,o));if(e!==null&&typeof e=="object"){let r={};for(let[s,a]of Object.entries(e)){if(l.has(s))continue;let i=p[s]??s;if(v.has(s)){r[i]=null;continue}r[i]=n(a,s)}return r}return e}function R(e){return e.map(o=>n(o))}function f(e){let o=e?.diagnostics;if(!o)return n(e);let r=o.serpCompleteness,s=r?.queryIntegrity;return!o.debug&&!s?n(e):n({...e,diagnostics:{...o,...o.debug?{debug:n(o.debug)}:{},...s?{serpCompleteness:{...r,queryIntegrity:{...s,outboundProviderMethod:"search"}}}:{}}})}export{n as a,R as b,f as c};
@@ -1 +0,0 @@
1
- function u(e){if(Date.now()>=e)throw new Error("Reddit request deadline exhausted")}var t=class extends Error{constructor(n){super(`${n} deadline exceeded`),this.name="DeadlineExceededError"}};async function w(e,n,r,s=Number.POSITIVE_INFINITY){let o=Math.min(e-Date.now(),s);if(o<=0)throw new t(r);let T=Date.now()+o,i,a=Promise.resolve().then(()=>{if(Date.now()>=e)throw new t(r);return n()});try{let E=await Promise.race([a,new Promise((_,D)=>{i=setTimeout(()=>D(new t(r)),o)})]);if(Date.now()>=Math.min(e,T))throw new t(r);return E}finally{i&&clearTimeout(i)}}export{u as a,t as b,w as c};
@@ -1 +0,0 @@
1
- import{c as f,d,e as p,h as u,i as A,j as m}from"./chunk-SEZETSB3.js";import{c as s,i as l}from"./chunk-SDQW7IJN.js";import{randomUUID as D}from"crypto";var x="connected-data-exports/",_=10080*60*1e3,b=900*1e3;function C(){return process.env.CONNECTED_DATA_READ_WRITE_TOKEN?.trim()||process.env.CONNECTED_DATA_BLOB_READ_WRITE_TOKEN?.trim()||null}function r(){return{prefix:x,artifactTtlMs:_,downloadTtlMs:b,token:C()}}function i(t){return(t.toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"connected-data-export").slice(0,120)}function N(t){return l(t,x)}function w(t){return f(t,r())}function O(t,e=Date.now()){let n=w(t);return!n||n.getTime()<=e}async function P(t){return g({...t,contentType:"application/x-ndjson"})}async function g(t){let e=t.stableCreatedAt?Date.parse(t.stableCreatedAt):NaN,n=Number.isFinite(e)?e:Date.now(),c=i(t.filename),y=t.stableKey?i(t.stableKey):D(),a;try{a=await p({policy:r(),ownerId:t.ownerId,artifactKey:`${i(t.exportId)}-${y}--${c}`,createdAt:n,filename:c,contentType:t.contentType,content:typeof t.content=="string"?t.content:Buffer.from(t.content)})}catch(o){throw o instanceof Error&&o.message==="private_artifact_blob_not_configured"?new Error("connected_data_private_blob_not_configured"):o}return{...a,...a.capabilities.includes("text")?{readback:{tool:"report_artifact_read",arguments:{artifactId:a.artifactId,offset:0,maxBytes:2e4},continuation:"Repeat with offset set to the previous result nextOffset until nextOffset is null."}}:{}}}async function B(t){return u({...t,policy:r()})}async function R(t,e,n){return A({policy:r(),artifactId:t,offset:e,maxBytes:n})}async function U(t){try{return await m({...t,policy:r(),maxBytes:t.maxBytes??25*1024*1024})}catch(e){if(e instanceof s&&e.code==="read_limit")return null;throw e}}async function h(t={}){let e=t.now??new Date,n=r();return n.token?!t.force&&!(e.getUTCHours()===3&&e.getUTCMinutes()===17)?{deleted:0,store:"private-vercel-blob",skipped:!0}:d({policy:n,now:e,includeLegacy:!0,maxObjects:2e4}):{deleted:0,store:process.env.VERCEL==="1"||process.env.NODE_ENV==="production"?"none":"local"}}export{x as a,_ as b,b as c,r as d,N as e,w as f,O as g,P as h,g as i,B as j,R as k,U as l,h as m};
@@ -1 +0,0 @@
1
- import{createHash as w}from"crypto";import{createReadStream as R}from"fs";import{createHash as A}from"crypto";var g=/--v1-([a-f0-9]{64})(?:\.[a-zA-Z0-9]{1,16})?$/,m=class extends Error{constructor(e,n,a){super(`private_artifact_storage_${n}`,{cause:a});this.artifactId=e;this.outcome=n}artifactId;outcome;name="ArtifactStorageError"},d=class extends Error{constructor(e,n){super(n);this.code=e}code;name="ArtifactReadError"};function P(t){let r=t.toLowerCase().split(";")[0].trim(),e=["download"],n=t.match(/;\s*charset\s*=\s*"?([^;"\s]+)/i)?.[1]?.toLowerCase();return(n===void 0||n==="utf-8"||n==="utf8")&&(r.startsWith("text/")||["application/json","application/x-ndjson","application/ndjson","application/xml","application/javascript","message/rfc822"].includes(r)||r.endsWith("+json")||r.endsWith("+xml"))&&e.push("text"),r==="application/zip"&&e.push("archive"),r.startsWith("image/")&&e.push("image"),r.startsWith("audio/")&&e.push("audio"),r.startsWith("video/")&&e.push("video"),e}function _(t){return(t.trim().replace(/[^a-zA-Z0-9_.-]+/g,"-").replace(/^-+|-+$/g,"")||"artifact").slice(0,160)}function T(t){let r=t.replace(/^\/+/,"").replace(/\/+$/,"");if(!r||r.includes("..")||!/^[a-zA-Z0-9/_-]+$/.test(r))throw new Error("private artifact prefix is invalid");return`${r}/`}function x(t,r){let e=t.trim();if(!/^[a-zA-Z0-9_-]{1,160}$/.test(e)||e==="_metadata")throw new Error(`${r} must contain only letters, numbers, underscores, or hyphens`);return e}function B(t){let r=t.trim();if(!/^[a-zA-Z0-9_.-]{1,600}$/.test(r)||r.includes(".."))throw new Error("private artifact key is invalid");return r}function O(t,r){let e=T(r);if(!t.startsWith(e))return null;let n=t.slice(e.length).split("/");if(n.length<2)return null;try{let a=x(n[0],"ownerId");return n.slice(1,-1).forEach(s=>x(s,"scope")),B(n.at(-1)),/^\d{13}-/.test(n.at(-1))?a:null}catch{return null}}function S(t){let r=t.split("/").at(-1)?.match(/^(\d{13})-/),e=r?Number(r[1]):NaN;return Number.isSafeInteger(e)&&e>0?e:null}function M(t,r,e,n){if(r>n||t.length&&(t[0]&192)===128)throw new d("invalid_offset","private artifact offset falls inside a UTF-8 character or exceeds content");let a=Math.min(e,t.length);for(;a>0&&a<t.length&&(t[a]&192)===128;)a--;if(a===0&&r<n)throw new d("window_too_small","private artifact maxBytes is too small for the next UTF-8 character");let s;try{s=new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(t.subarray(0,a))}catch{throw new d("invalid_utf8","private artifact is not valid UTF-8 text")}return{text:s,consumedBytes:a,nextOffset:r+a<n?r+a:null}}function N(t){return A("sha256").update(JSON.stringify(t)).digest("hex")}function U(t,r){let e=t;if(!e||e.version!==1||e.artifactId!==r||r.match(g)?.[1]!==e.fingerprint||!/^[a-f0-9]{64}$/.test(e.sha256)||!Number.isSafeInteger(e.bytes)||e.bytes<0||typeof e.filename!="string"||_(e.filename)!==e.filename||typeof e.contentType!="string"||!Number.isFinite(Date.parse(e.createdAt))||!Number.isFinite(Date.parse(e.expiresAt)))return!1;let{artifactId:n,fingerprint:a,...s}=e;return N(s)===a&&JSON.stringify(e.capabilities)===JSON.stringify(P(e.contentType))&&Date.parse(e.createdAt)===S(r)}function I(t,r){return`${r}_metadata/${t.slice(r.length)}.json`}async function k(t,r){let e=t.getReader(),n=[],a=0;try{for(;;){let{done:s,value:i}=await e.read();if(s)break;if(a+=i.byteLength,a>r)throw new d("read_limit","private artifact exceeds read limit");n.push(Buffer.from(i))}return Buffer.concat(n,a)}finally{await e.cancel().catch(()=>{}),e.releaseLock()}}async function y(t,r,e){let n=r.backend?null:await import("@vercel/blob"),a=r.backend?await r.backend.get(t,e):await n.get(t,{access:"private",token:r.token,useCache:!1,...e?{headers:{Range:`bytes=${e.start}-${e.end}`}}:{}});if(!a||"statusCode"in a&&a.statusCode!==200)return null;if(a.blob?.pathname!==t)throw await a.stream.cancel().catch(()=>{}),new d("integrity_mismatch","private artifact returned a different object identity");if(e){let i=a.headers?.get("content-range")?.match(/^bytes (\d+)-(\d+)\/(\d+)$/);if(!i||i.slice(1).some(c=>!Number.isSafeInteger(Number(c)))||Number(i[1])!==e.start||Number(i[2])>e.end||Number(i[2])<e.start||Number(i[3])<=Number(i[2]))throw await a.stream.cancel().catch(()=>{}),new d("range_unavailable","private artifact backend did not acknowledge the requested bounded range");return{...a,totalBytes:Number(i[3]),rangeBytes:Number(i[2])-e.start+1}}let s=a.blob.size;if(!r.backend&&(!Number.isSafeInteger(s)||s<0||s===0&&a.headers.get("content-length")!=="0"))try{let i=await n.head(t,{token:r.token});if(i.pathname!==t||!Number.isSafeInteger(i.size)||i.size<0)throw new d("integrity_mismatch","private artifact length metadata is invalid");s=i.size}catch(i){throw await a.stream.cancel().catch(()=>{}),i}return{...a,blob:{...a.blob,size:s},totalBytes:s,rangeBytes:s}}async function F(t){let r=R(t.file);try{if((t.policy.backend?await t.policy.backend.put({id:t.id,body:r,bytes:t.bytes,sha256:t.sha256,contentType:t.contentType}):await(await import("@vercel/blob")).put(t.id,r,{access:"private",token:t.policy.token,contentType:t.contentType,addRandomSuffix:!1,allowOverwrite:!1,cacheControlMaxAge:60,multipart:t.bytes>104857600})).pathname!==t.id)throw new Error("private artifact put returned a different object identity")}catch(e){r.destroy();try{let n=await y(t.id,t.policy);if(!n)throw e;if(n.totalBytes!==t.bytes||n.blob.contentType.split(";")[0]!==t.contentType.split(";")[0])throw await n.stream.cancel().catch(()=>{}),e;let a=n.stream.getReader(),s=w("sha256"),i=0;try{for(;;){let c=await a.read();if(c.done)break;if(i+=c.value.byteLength,i>t.bytes)throw e;s.update(c.value)}}finally{await a.cancel().catch(()=>{}),a.releaseLock()}if(i!==t.bytes||s.digest("hex")!==t.sha256)throw e}catch{throw new m(t.id,"unknown",e)}}finally{r.destroy()}}async function W(t,r,e,n){try{if((e.backend?await e.backend.put({id:t,body:Buffer.from(r),bytes:Buffer.byteLength(r),sha256:w("sha256").update(r).digest("hex"),contentType:"application/json"}):await(await import("@vercel/blob")).put(t,r,{access:"private",token:e.token,contentType:"application/json",addRandomSuffix:!1,allowOverwrite:!1,cacheControlMaxAge:60})).pathname!==t)throw new Error("private artifact metadata put returned a different identity")}catch(a){try{let s=await y(t,e);if(!s||(await k(s.stream,8192)).toString()!==r)throw a}catch{throw new m(n,"bytes-stored-metadata-pending",a)}}}async function L(t,r,e){if(e.backend){let u=await e.backend.sign(t,r);if(!u.startsWith("https://"))throw Error("private artifact download URL must use HTTPS");return u}let{getDownloadUrl:n,issueSignedToken:a,presignUrl:s}=await import("@vercel/blob"),i=await a({token:e.token,pathname:t,operations:["get"],validUntil:r}),c=await s(i,{access:"private",operation:"get",pathname:t,validUntil:r});if(!c.presignedUrl.startsWith("https://"))throw new Error("private artifact download URL must use HTTPS");return n(c.presignedUrl)}async function D(t,r,e){let n=t.backend?o=>t.backend.list(o.prefix,o.cursor,o.limit):(await import("@vercel/blob")).list,a=t.backend?o=>t.backend.delete(Array.isArray(o)?o:[o]):(await import("@vercel/blob")).del,s=t.backend?.kind??"private-vercel-blob",i=`${t.prefix}_cleanup/cursor.json`,c,u=0,h=0,f=!1,v=await y(i,t);if(v)try{let o=JSON.parse((await k(v.stream,8192)).toString());o.version===1&&o.prefix===t.prefix&&typeof o.cursor=="string"&&o.cursor.length>0&&o.cursor.length<=4096&&(c=o.cursor)}catch{return{deleted:0,store:s,pending:!0}}do{let o=await n({prefix:t.prefix,token:t.token,limit:Math.min(1e3,e-u),cursor:c});u+=o.blobs.length;let p=[];for(let l of o.blobs)await r(l.pathname)&&p.push(l.pathname);if(p.length)try{await a(p,{token:t.token}),h+=p.length;let l=p.filter(b=>g.test(b)).map(b=>I(b,t.prefix));l.length&&await a(l,{token:t.token})}catch{return{deleted:h,store:s,pending:!0}}if(f=o.hasMore,!f){if(c)try{await a(i,{token:t.token})}catch{f=!0}break}if(!o.cursor||o.cursor===c){f=!0;break}if(c=o.cursor,u>=e){try{if(c.length>4096)throw Error("private artifact cleanup cursor exceeds limit");let l=JSON.stringify({version:1,prefix:t.prefix,cursor:c});if((t.backend?await t.backend.put({id:i,body:Buffer.from(l),bytes:Buffer.byteLength(l),sha256:w("sha256").update(l).digest("hex"),contentType:"application/json",overwrite:!0}):await(await import("@vercel/blob")).put(i,l,{access:"private",token:t.token,contentType:"application/json",addRandomSuffix:!1,allowOverwrite:!0,cacheControlMaxAge:0})).pathname!==i)throw Error("private artifact cleanup cursor identity mismatch")}catch{f=!0}break}}while(!0);return{deleted:h,store:s,pending:f}}export{g as a,m as b,d as c,P as d,_ as e,T as f,x as g,B as h,O as i,S as j,M as k,N as l,U as m,I as n,k as o,y as p,F as q,W as r,L as s,D as t};
@@ -1 +0,0 @@
1
- import{a as T,b as K,c as u,d as F,e as Z,f as q,g as J,h as G,i as h,j as Q,k as tt,l as et,m as B,n as C,o as R,p as k,q as at,r as it,s as z}from"./chunk-SDQW7IJN.js";import{c as O}from"./chunk-OILOHQNL.js";import{opendir as rt,readFile as nt,rm as X,stat as ut}from"fs/promises";import{join as b}from"path";var kt=7*864e5,Mt=15*6e4,$="9999-12-31T23:59:59.999Z";function g(e){if(e.artifactTtlMs!==null&&(!Number.isSafeInteger(e.artifactTtlMs)||e.artifactTtlMs<=0))throw new Error("private artifact TTL must be a positive integer");if(!Number.isSafeInteger(e.downloadTtlMs)||e.downloadTtlMs<=0)throw new Error("private artifact download TTL must be a positive integer");return{...e,token:e.token?.trim()||null,prefix:q(e.prefix)}}function N(e,t){let a=g(t);if(h(e,a.prefix)===null||a.artifactTtlMs===null)return null;let i=Q(e);return i===null?null:new Date(i+a.artifactTtlMs)}function D(e,t,a,i=Date.now()){let r=h(e,t.prefix);if(!r||a!==void 0&&r!==a)return!1;let n=N(e,t);return t.artifactTtlMs===null||n!==null&&n.getTime()>i}function E(e){return e.hosted??(process.env.VERCEL==="1"||process.env.NODE_ENV==="production")}function Y(e,t,a=Date.now()){let i=Math.min(a+t.downloadTtlMs,Date.parse(e));return i>a?i:null}async function Ft(e){let t=g(e.policy),a=(e.now??new Date).getTime(),i=e.maxObjects??1e3;if(!Number.isSafeInteger(i)||i<1||i>2e4||!Number.isFinite(a))throw new Error("private artifact cleanup budget/time is invalid");let r=d=>e.includeLegacy===!0&&D(d,t,void 0,a)===!1&&h(d,t.prefix)!==null,n=(d,m)=>B(d,m)&&h(m,t.prefix)===d.ownerId&&Date.parse(d.expiresAt)<=a,o=d=>T.test(d)&&h(d,t.prefix)!==null&&(N(d,t)?.getTime()??1/0)<=a;if(t.artifactTtlMs===null)return{deleted:0,store:t.backend?.kind??(t.token?"private-vercel-blob":E(t)?"none":"local"),pending:!1};if(t.backend||t.token?.trim()){let{cleanupPrivateBlobObjects:d,getPrivateBlob:m,metadataBlobId:v,consumePrivateBlob:c}=await import("./blob-store-GIH26EDO.js");return d(t,async s=>{if(s.startsWith(`${t.prefix}_metadata/`)&&s.endsWith(".json")){let y=`${t.prefix}${s.slice(`${t.prefix}_metadata/`.length,-5)}`;if(!o(y))return!1;let _=await m(s,t);if(!_)return!1;try{return n(JSON.parse((await c(_.stream,8192)).toString()),y)}catch{return!1}}if(!h(s,t.prefix))return!1;if(!T.test(s))return r(s);if(!o(s))return!1;let f=await m(v(s,t.prefix),t);if(!f)return o(s);try{return n(JSON.parse((await c(f.stream,8192)).toString()),s)}catch{return!1}},i)}if(E(t))return{deleted:0,store:"none",pending:!0};let l=O(t.localBaseDir),w=0,x=0,p=!1;async function I(d,m=""){let v=await rt(d).catch(c=>{if(c.code==="ENOENT")return null;throw c});if(v)for await(let c of v){let s=m?`${m}/${c.name}`:c.name;if(c.isDirectory())await I(b(d,c.name),s);else if(c.isFile()){let f=`${t.prefix}${s}`;if(!o(f)&&!r(f))continue;if(w>=i){p=!0;return}if(w++,T.test(f)){let y=await nt(b(l,"artifact-metadata",`${f}.json`),"utf8").catch(()=>null);if(y){let _;try{_=JSON.parse(y)}catch{p=!0;continue}if(!n(_,f)){(!B(_,f)||h(f,t.prefix)!==_.ownerId)&&(p=!0);continue}}}else if(!r(f))continue;try{await X(b(l,"blobs",f)),x++,await X(b(l,"artifact-metadata",`${f}.json`),{force:!0})}catch{p=!0}}}}await I(b(l,"blobs",t.prefix));async function P(d,m=""){let v=await rt(d).catch(c=>{if(c.code==="ENOENT")return null;throw c});if(v)for await(let c of v){let s=m?`${m}/${c.name}`:c.name;if(c.isDirectory())await P(b(d,c.name),s);else if(c.isFile()&&s.endsWith(".json")){let f=`${t.prefix}${s.slice(0,-5)}`;if(!o(f)||await ut(b(l,"blobs",f)).then(()=>!0,y=>{if(y.code==="ENOENT")return!1;throw y}))continue;if(w>=i){p=!0;return}w++;try{let y=JSON.parse(await nt(b(d,c.name),"utf8"));if(!n(y,f)){(!B(y,f)||h(f,t.prefix)!==y.ownerId)&&(p=!0);continue}await X(b(d,c.name)),x++}catch{p=!0}}}}return await P(b(l,"artifact-metadata",t.prefix)),{deleted:x,store:"local",pending:p}}import{createHash as H}from"crypto";import{constants as A,createWriteStream as mt}from"fs";import{link as ot,mkdir as V,mkdtemp as pt,open as M,readFile as wt,rm as yt,writeFile as ht}from"fs/promises";import{tmpdir as vt}from"os";import{dirname as ct,join as S}from"path";import{Readable as xt,Transform as bt}from"stream";import{pipeline as At}from"stream/promises";var L=T,Pt=1e5,Et=e=>H("sha256").update(e).digest("hex"),U=(e,t)=>S(O(e.localBaseDir),"blobs",t),st=(e,t)=>S(O(e.localBaseDir),"artifact-metadata",`${t}.json`);function It(e){let t=typeof e=="string"&&/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(e)?`${e.replace(" ","T")}Z`:e,a=t instanceof Date?t.getTime():typeof t=="number"?t:Date.parse(t);if(!Number.isSafeInteger(a)||a<1e12||a>9999999999999)throw new Error("private artifact createdAt is invalid");return a}function _t(e,t,a){let i=e;if(!B(i,t)||!t.startsWith(`${a.prefix}${i.ownerId}/`)||i.expiresAt!==(N(t,a)?.toISOString()??$))throw new u("integrity_mismatch","private artifact metadata does not match its identity/policy");return i}async function j(e,t){if(!L.test(e))return null;let a;if(t.backend||t.token?.trim()){let i=await k(C(e,t.prefix),t);if(!i)return null;a=await R(i.stream,8192)}else{if(E(t))return null;let i=await M(st(t,e),A.O_RDONLY|A.O_NOFOLLOW).catch(r=>{if(r.code==="ENOENT")return null;throw r});if(!i)return null;try{let r=await i.stat();if(!r.isFile()||r.size>8192)throw new u("integrity_mismatch","private artifact metadata exceeds limit");a=await i.readFile()}finally{await i.close()}}try{return _t(JSON.parse(a.toString("utf8")),e,t)}catch(i){throw i instanceof u?i:new u("integrity_mismatch","private artifact metadata is not valid JSON")}}async function ft(e,t){if(Date.parse(e.expiresAt)<=Date.now())return{downloadUrl:null,downloadUrlExpiresAt:null,downloadState:"unavailable"};if(t.backend?.localPath)return{downloadUrl:null,downloadUrlExpiresAt:null,downloadState:"local"};if(!(t.backend||t.token?.trim()))return{downloadUrl:null,downloadUrlExpiresAt:null,downloadState:E(t)?"unavailable":"local"};let a=Y(e.expiresAt,t);if(!a)return{downloadUrl:null,downloadUrlExpiresAt:null,downloadState:"unavailable"};try{return{downloadUrl:await z(e.artifactId,a,t),downloadUrlExpiresAt:new Date(a).toISOString(),downloadState:"available"}}catch{return{downloadUrl:null,downloadUrlExpiresAt:null,downloadState:"unavailable"}}}async function gt(e,t,a,i){let r=U(a,t.artifactId),n=st(a,t.artifactId),o=JSON.stringify(t);await V(ct(r),{recursive:!0}),await V(ct(n),{recursive:!0});let l=S(i,"metadata.json");await ht(l,o,{flag:"wx",mode:384});try{await ot(l,n)}catch(w){if(w.code!=="EEXIST")throw w;if(await wt(n,"utf8")!==o)throw new u("integrity_mismatch","private artifact metadata collision")}try{await ot(e,r)}catch(w){if(w.code!=="EEXIST")throw w;let x=H("sha256"),p=0,I=await M(r,A.O_RDONLY|A.O_NOFOLLOW);try{for await(let P of I.createReadStream()){if(p+=P.length,p>t.bytes)throw new u("integrity_mismatch","private artifact data collision");x.update(P)}if(p!==t.bytes||x.digest("hex")!==t.sha256)throw new u("integrity_mismatch","private artifact data collision")}finally{await I.close()}}}async function Kt(e){return St({...e,content:xt.from([Buffer.isBuffer(e.content)?e.content:Buffer.from(e.content)])})}async function St(e){let t=g(e.policy),a=J(e.ownerId,"ownerId"),i=G(e.artifactKey);if(i.length>400)throw new Error("private artifact key is too long");let r=(e.scopeSegments??[]).map(m=>J(m,"scopeSegments")),n=It(e.createdAt),o=Z(e.filename),l=e.contentType.trim().toLowerCase();if(l.length>256||!/^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+(?:;[\x20-\x7e]+)?$/.test(l))throw new Error("private artifact contentType is invalid");if(!(t.backend||t.token?.trim())&&E(t))throw new Error("private_artifact_blob_not_configured");let w=!(t.backend||t.token?.trim())||t.localBaseDir?S(O(t.localBaseDir),".artifact-staging"):S(vt(),"mcp-private-artifacts");await V(w,{recursive:!0,mode:448});let x=await pt(S(w,"write-")),p=S(x,"bytes"),I=H("sha256"),P=0,d=new bt({transform(m,v,c){P+=m.length,I.update(m),c(null,m)}});try{await At(e.content,d,mt(p,{flags:"wx",mode:384}));let m={version:1,ownerId:a,filename:o,contentType:l,bytes:P,sha256:I.digest("hex"),createdAt:new Date(n).toISOString(),expiresAt:t.artifactTtlMs===null?$:new Date(n+t.artifactTtlMs).toISOString(),capabilities:F(l)},v=o.match(/\.([a-zA-Z0-9]{1,16})$/)?.[1],c=et(m),s=`${t.prefix}${a}/${r.length?r.join("/")+"/":""}${n}-${i}--v1-${c}${v?"."+v:""}`;if(h(s,t.prefix)!==a)throw new Error("private artifact identity is invalid");let f={...m,artifactId:s,fingerprint:c};if(t.backend||t.token?.trim())await at({id:s,file:p,bytes:P,sha256:f.sha256,contentType:l,policy:t}),await it(C(s,t.prefix),JSON.stringify(f),t,s);else try{await gt(p,f,t,x)}catch(W){throw W instanceof u?W:new K(s,"unknown",W)}let{version:y,fingerprint:_,...dt}=f;return{...dt,...await ft(f,t)}}finally{await yt(x,{recursive:!0,force:!0})}}async function lt(e,t){if(t.backend||t.token?.trim()){let i=await k(e.artifactId,t);return i?(await i.stream.cancel().catch(()=>{}),i.totalBytes===e.bytes):!1}if(E(t))return!1;let a=await M(U(t,e.artifactId),A.O_RDONLY|A.O_NOFOLLOW).catch(i=>{if(i.code==="ENOENT")return null;throw i});if(!a)return!1;try{let i=await a.stat();return i.isFile()&&i.size===e.bytes}finally{await a.close()}}async function Zt(e){let t=g(e.policy);if(!D(e.artifactId,t,e.ownerId))return null;let a=await j(e.artifactId,t);if(!a||!await lt(a,t))return null;let{version:i,fingerprint:r,...n}=a;return{...n,...await ft(a,t)}}async function qt(e){let t=g(e.policy);if(!D(e.artifactId,t,e.ownerId)||!(t.backend||t.token?.trim()))return null;let a=await j(e.artifactId,t);if(L.test(e.artifactId)&&(!a||!await lt(a,t)))return null;let i=a?.expiresAt??N(e.artifactId,t)?.toISOString()??$,r=Y(i,t);return r?{downloadUrl:await z(e.artifactId,r,t),downloadUrlExpiresAt:new Date(r).toISOString(),expiresAt:i}:null}function Ot(e){let t=e.split(".").at(-1)?.toLowerCase();return{txt:"text/plain",md:"text/markdown",html:"text/html",csv:"text/csv",json:"application/json",jsonl:"application/x-ndjson",xml:"application/xml",eml:"message/rfc822"}[t??""]??"application/octet-stream"}async function Gt(e){let t=g(e.policy);if(!D(e.artifactId,t,e.ownerId))return null;if(!Number.isSafeInteger(e.offset)||e.offset<0)throw new u("invalid_offset","private artifact offset is invalid");if(!Number.isSafeInteger(e.maxBytes)||e.maxBytes<1||e.maxBytes>Pt||!Number.isSafeInteger(e.offset+e.maxBytes+1))throw new Error("private artifact maxBytes is invalid");let a=await j(e.artifactId,t);if(L.test(e.artifactId)&&!a)return null;let i=a?.contentType??Ot(e.artifactId),r,n;if(a&&!a.capabilities.includes("text"))throw new u("unsupported_text","private artifact does not support text reads; use its download/archive/media capability");if(t.backend||t.token?.trim()){if(a&&e.offset>a.bytes)throw new u("invalid_offset","private artifact offset exceeds content");if(a&&e.offset===a.bytes)return{text:"",totalBytes:a.bytes,offset:e.offset,consumedBytes:0,nextOffset:null,contentType:i,sha256:a.sha256};let o=await k(e.artifactId,t,{start:e.offset,end:e.offset+e.maxBytes});if(!o)return null;if(i=o.blob.contentType,n=o.totalBytes,!F(i).includes("text")||a&&n!==a.bytes)throw await o.stream.cancel().catch(()=>{}),new u(a&&n!==a.bytes?"integrity_mismatch":"unsupported_text","private artifact range metadata/capability is invalid");if(r=await R(o.stream,e.maxBytes+1),r.length!==o.rangeBytes)throw new u("integrity_mismatch","private artifact range body is incomplete")}else{if(E(t))return null;if(!F(i).includes("text"))throw new u("unsupported_text","private artifact does not support text reads; use its download/archive/media capability");let o=await M(U(t,e.artifactId),A.O_RDONLY|A.O_NOFOLLOW).catch(l=>{if(l.code==="ENOENT")return null;throw l});if(!o)return null;try{let l=await o.stat();if(n=l.size,!l.isFile()||a&&a.bytes!==n)throw new u("integrity_mismatch","private artifact bytes do not match metadata");if(e.offset>n)throw new u("invalid_offset","private artifact offset exceeds content");r=Buffer.alloc(Math.min(e.maxBytes+1,n-e.offset));let{bytesRead:w}=await o.read(r,0,r.length,e.offset);r=r.subarray(0,w)}finally{await o.close()}}return{...tt(r,e.offset,e.maxBytes,n),totalBytes:n,offset:e.offset,contentType:i,sha256:a?.sha256??null}}async function Qt(e){let t=g(e.policy);if(!D(e.artifactId,t,e.ownerId))return null;if(!Number.isSafeInteger(e.maxBytes)||e.maxBytes<1)throw new Error("private artifact maxBytes is invalid");let a=await j(e.artifactId,t);if(L.test(e.artifactId)&&!a)return null;let i;if(t.backend||t.token?.trim()){let r=await k(e.artifactId,t);if(!r)return null;if(a&&r.totalBytes!==a.bytes||r.totalBytes>e.maxBytes)throw await r.stream.cancel().catch(()=>{}),new u("read_limit","private artifact exceeds read limit or metadata size");i=await R(r.stream,e.maxBytes)}else{if(E(t))return null;let r=await M(U(t,e.artifactId),A.O_RDONLY|A.O_NOFOLLOW).catch(n=>{if(n.code==="ENOENT")return null;throw n});if(!r)return null;try{let n=await r.stat();if(!n.isFile()||a&&n.size!==a.bytes)throw new u("integrity_mismatch","private artifact bytes do not match metadata");if(n.size>e.maxBytes)throw new u("read_limit","private artifact exceeds read limit");i=Buffer.alloc(n.size);let o=0;for(;o<i.length;){let{bytesRead:l}=await r.read(i,o,i.length-o,o);if(!l)break;o+=l}if(o!==i.length)throw new u("integrity_mismatch","private artifact bytes changed during read")}finally{await r.close()}}if(a&&(i.length!==a.bytes||Et(i)!==a.sha256))throw new u("integrity_mismatch","private artifact digest mismatch");return i}export{kt as a,Mt as b,N as c,Ft as d,Kt as e,St as f,Zt as g,qt as h,Gt as i,Qt as j};