Spaces:
Running
Running
github-actions[bot]
commited on
Commit
·
101c6cb
1
Parent(s):
05a57f8
Deploy: Update from GitHub Actions build
Browse files- dist/index.js +8 -8
- public/health.html +331 -0
- public/index.html +1 -331
dist/index.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
-
var Me=Object.defineProperty;var oe=(t,e)=>()=>(t&&(e=t(t=0)),e);var ke=(t,e)=>{for(var o in e)Me(t,o,{get:e[o],enumerable:!0})};import K from"node:fs";function Le(){K.existsSync(
|
2 |
-
`;try{await K.promises.appendFile(R.logFile,a)}catch(s){console.error("\u5199\u5165\u65E5\u5FD7\u6587\u4EF6\u5931\u8D25:",s)}}function De(t,...e){if(!R.enableConsole)return;let o={[P.DEBUG]:console.debug,[P.INFO]:console.log,[P.WARN]:console.warn,[P.ERROR]:console.error}[t]||console.log,a=new Date().toLocaleTimeString();o(`[${a}] [${t}]`,...e)}function W(t,...e){let o=He(...e);De(t,...e),Fe(t,o)}var P,R,r,_,p,$=oe(()=>{P={DEBUG:"DEBUG",INFO:"INFO",WARN:"WARN",ERROR:"ERROR"},R={logFile:"./logs/app.log",logDir:"./logs",enableConsole:!0,enableFile:!0,logLevel:process.env.LOG_LEVEL||P.INFO};r=(...t)=>W(P.INFO,...t),_=(...t)=>W(P.WARN,...t),p=(...t)=>W(P.ERROR,...t)});var ne={};ke(ne,{checkCookieAvailability:()=>Ge,ensureDirectoryExists:()=>ae,getHumanReadableTimestamp:()=>re,loadCookies:()=>X,saveScreenshot:()=>V,waitForUserInput:()=>qe});import A from"node:fs";import Be from"node:path";import Ue from"node:readline";function re(){return new Date().toISOString().replace(/T/,"_").replace(/:/g,"-").replace(/\..+/,"")}function ae(t){A.existsSync(t)||(A.mkdirSync(t,{recursive:!0}),r(`\u5DF2\u521B\u5EFA\u76EE\u5F55: ${t}`))}function Ge(t,e){if(e)try{return JSON.parse(e),r("\u53D1\u73B0\u5E76\u9A8C\u8BC1\u4E86\u73AF\u5883\u53D8\u91CF\u4E2D\u7684 COOKIES\u3002"),!0}catch(o){p("\u73AF\u5883\u53D8\u91CF COOKIES \u683C\u5F0F\u65E0\u6548 (\u5FC5\u987B\u662F JSON \u6570\u7EC4\u5B57\u7B26\u4E32):",o.message)}return A.existsSync(t)?(r(`\u53D1\u73B0 Cookie \u6587\u4EF6: ${t}`),!0):(p(`Cookie \u6587\u4EF6\u4E0D\u5B58\u5728: ${t}\uFF0C\u4E14\u672A\u8BBE\u7F6E COOKIES \u73AF\u5883\u53D8\u91CF\u3002`),r("\u8BF7\u5148\u8FD0\u884C `npm run login` \u6216\u8BBE\u7F6E COOKIES \u73AF\u5883\u53D8\u91CF\u3002"),!1)}function X(t,e){try{if(e)return r("\u4ECE\u73AF\u5883\u53D8\u91CF COOKIES \u52A0\u8F7D Cookie..."),JSON.parse(e);if(A.existsSync(t))return r(`\u4ECE\u6587\u4EF6\u52A0\u8F7D Cookie: ${t}`),JSON.parse(A.readFileSync(t,"utf8"))}catch(o){throw p("\u52A0\u8F7D Cookie \u5931\u8D25:",o),new Error("\u65E0\u6CD5\u52A0\u8F7D\u6216\u89E3\u6790 Cookie\u3002")}return[]}async function V(t,e,o="screenshot",a=!0){if(ae(e),a){let n=re();o=`${o}_${n}`}let s=Be.join(e,`${o}.png`);return await t.screenshot({path:s,fullPage:!0}),r(`\u622A\u56FE\u5DF2\u4FDD\u5B58: ${s}`),s}function qe(){let t=Ue.createInterface({input:process.stdin,output:process.stdout});return new Promise(e=>{t.question("",()=>{t.close(),e()})})}var F=oe(()=>{$()});import{H3 as at,serve as nt,serveStatic as ve}from"h3";import{stat as Ce,readFile as Te}from"node:fs/promises";import{join as Re}from"node:path";import{chromium as je}from"playwright";import{newInjectedContext as ze}from"fingerprint-injector";import{FingerprintGenerator as Ke}from"fingerprint-generator";import Oe from"dotenv";Oe.config();var Ne={server:{port:parseInt(process.env.PORT||"3096",10),host:process.env.HOST||"localhost"},browser:{headless:(process.env.HEADLESS||"true").toLowerCase()!=="false",timeout:parseInt(process.env.TIMEOUT||"30000",10),executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH,args:["--disable-blink-features=AutomationControlled","--no-sandbox","--disable-dev-shm-usage","--disable-infobars","--disable-extensions"]},cookieFile:"./cookies.json",cookiesFromEnv:process.env.COOKIES,screenshotDir:"./screenshots",aiStudio:{url:process.env.AI_STUDIO_URL||"https://aistudio.google.com/prompts/new_chat",responseTimeout:parseInt(process.env.RESPONSE_TIMEOUT||"600000",10),pageTimeout:parseInt(process.env.PAGE_TIMEOUT||"30000",10)},api:{defaultModel:process.env.DEFAULT_MODEL||"gemini-pro",maxTokens:65536,temperature:1,token:process.env.API_TOKEN},models:{"gemini-2.5-pro":{displayName:"Gemini 2.5 Pro",id:"gemini-2.5-pro",object:"model",created:1704067200,owned_by:"google",permission:[],root:"gemini-2.5-pro",parent:null},"gemini-2.5-flash":{displayName:"Gemini 2.5 Flash",id:"gemini-2.5-flash",object:"model",created:1704067200,owned_by:"google",permission:[],root:"gemini-2.5-flash",parent:null},"gemini-pro":{displayName:"Gemini Pro",id:"gemini-pro",object:"model",created:1701388800,owned_by:"google",permission:[],root:"gemini-pro",parent:null},"gemini-flash":{displayName:"Gemini Flash",id:"gemini-flash",object:"model",created:1701388800,owned_by:"google",permission:[],root:"gemini-flash",parent:null}},debug:{logRequests:process.env.DEBUG_REQUESTS==="true",logResponses:process.env.DEBUG_RESPONSES==="true",saveScreenshots:process.env.SAVE_SCREENSHOTS==="true"},enableHumanSimulation:(process.env.ENABLE_HUMAN_SIMULATION||"false").toLowerCase()==="true"},c=Ne;F();$();var v=null,T=null,D=class{constructor(e=5){this.maxSize=e,this.availablePages=[],this.busyPages=new Set,this.totalPages=0}async getPage(){if(this.availablePages.length>0){let e=this.availablePages.pop();return this.busyPages.add(e),r(`\u4ECE\u9875\u9762\u6C60\u83B7\u53D6\u9875\u9762\uFF0C\u5F53\u524D\u5FD9\u788C\u9875\u9762\u6570: ${this.busyPages.size}`),e}if(this.totalPages<this.maxSize){let{context:e}=await We(),o=await e.newPage();return this.busyPages.add(o),this.totalPages++,r(`\u521B\u5EFA\u65B0\u9875\u9762\uFF0C\u603B\u9875\u9762\u6570: ${this.totalPages}\uFF0C\u5FD9\u788C\u9875\u9762\u6570: ${this.busyPages.size}`),o}return r("\u9875\u9762\u6C60\u5DF2\u6EE1\uFF0C\u7B49\u5F85\u9875\u9762\u91CA\u653E..."),new Promise(e=>{let o=()=>{if(this.availablePages.length>0){let a=this.availablePages.pop();this.busyPages.add(a),r(`\u7B49\u5F85\u540E\u83B7\u53D6\u5230\u9875\u9762\uFF0C\u5F53\u524D\u5FD9\u788C\u9875\u9762\u6570: ${this.busyPages.size}`),e(a)}else setTimeout(o,100)};o()})}async releasePage(e){if(!this.busyPages.has(e)){r("\u5C1D\u8BD5\u91CA\u653E\u4E0D\u5728\u5FD9\u788C\u5217\u8868\u4E2D\u7684\u9875\u9762");return}try{await this.cleanupPage(e),this.busyPages.delete(e),this.availablePages.push(e),r(`\u9875\u9762\u5DF2\u91CA\u653E\u56DE\u6C60\u4E2D\uFF0C\u53EF\u7528\u9875\u9762\u6570: ${this.availablePages.length}\uFF0C\u5FD9\u788C\u9875\u9762\u6570: ${this.busyPages.size}`)}catch(o){p(`\u6E05\u7406\u9875\u9762\u65F6\u51FA\u9519\uFF0C\u5C06\u5173\u95ED\u8BE5\u9875\u9762: ${o.message}`),await this.removePage(e)}}async cleanupPage(e){try{e.removeAllListeners();try{await e.evaluate(()=>{Object.keys(window).forEach(a=>{(a.startsWith("__handleStreamChunk")||a.startsWith("__onStreamChunk")||a.startsWith("__onStreamEnd"))&&delete window[a]}),window.__streamInterceptor&&(typeof window.__streamInterceptor.deactivate=="function"&&window.__streamInterceptor.deactivate(),delete window.__streamInterceptor),delete window.__handleStreamChunk,delete window.__onStreamChunk,delete window.__onStreamEnd,delete window.__streamCallbacks})}catch(o){r(`\u6E05\u7406\u9875\u9762\u72B6\u6001\u65F6\u51FA\u73B0evaluate\u9519\u8BEF: ${o.message}`)}r("\u9875\u9762\u72B6\u6001\u5DF2\u6E05\u7406")}catch(o){throw new Error(`\u6E05\u7406\u9875\u9762\u5931\u8D25: ${o.message}`)}}async removePage(e){try{this.busyPages.delete(e);let o=this.availablePages.indexOf(e);o>-1&&this.availablePages.splice(o,1),await e.close(),this.totalPages--,r(`\u9875\u9762\u5DF2\u4ECE\u6C60\u4E2D\u79FB\u9664\uFF0C\u603B\u9875\u9762\u6570: ${this.totalPages}`)}catch(o){p(`\u5173\u95ED\u9875\u9762\u65F6\u51FA\u9519: ${o.message}`)}}async cleanup(){r("\u5F00\u59CB\u6E05\u7406\u9875\u9762\u6C60...");for(let e of this.busyPages)try{await e.close()}catch(o){p(`\u5173\u95ED\u5FD9\u788C\u9875\u9762\u65F6\u51FA\u9519: ${o.message}`)}for(let e of this.availablePages)try{await e.close()}catch(o){p(`\u5173\u95ED\u53EF\u7528\u9875\u9762\u65F6\u51FA\u9519: ${o.message}`)}this.busyPages.clear(),this.availablePages=[],this.totalPages=0,r("\u9875\u9762\u6C60\u6E05\u7406\u5B8C\u6210")}getStatus(){return{total:this.totalPages,available:this.availablePages.length,busy:this.busyPages.size,maxSize:this.maxSize}}},I=null;async function We(){if(!v){v=await je.launch({headless:c.browser.headless,timeout:c.browser.timeout,args:c.browser.args,executablePath:c.browser.executablePath});let t=new Ke().getFingerprint({devices:["desktop"],operatingSystems:["windows"],browsers:[{name:"chrome"}]});T=await ze(v,{fingerprint:t,newContextOptions:{locale:"zh-CN",serviceWorkers:"allow",javaScriptEnabled:!0,bypassCSP:!1}});let e=X(c.cookieFile,c.cookiesFromEnv);await T.addCookies(e)}return{browser:v,context:T}}function ie(t=5){return I||(I=new D(t),r(`\u9875\u9762\u6C60\u5DF2\u521D\u59CB\u5316\uFF0C\u6700\u5927\u9875\u9762\u6570: ${t}`)),I}function ce(){return I||(I=new D,r("\u9875\u9762\u6C60\u5DF2\u81EA\u52A8\u521D\u59CB\u5316\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E")),I}async function B(){let e=await ce().getPage();return await e.bringToFront(),e}async function M(t){await ce().releasePage(t)}function k(){return I?I.getStatus():{total:0,available:0,busy:0,maxSize:0}}async function U(t,e,o={}){let a=t.url();r("\u5F53\u524D\u9875\u9762URL:",a),r("\u76EE\u6807URL:",e);try{return a!==e?(r("\u9875\u9762URL\u4E0D\u5339\u914D\uFF0C\u9700\u8981\u5BFC\u822A..."),await t.goto(e,{waitUntil:"load",timeout:3e4,...o}),r("\u9875\u9762\u5BFC\u822A\u5B8C\u6210"),!0):(r("\u9875\u9762\u5DF2\u5728\u76EE\u6807URL\uFF0C\u8FDB\u884C\u5237\u65B0\u4EE5\u786E\u4FDD\u6700\u65B0\u72B6\u6001..."),await t.bringToFront(),await t.reload({waitUntil:"load",timeout:3e4,...o}),r("\u9875\u9762\u5237\u65B0\u5B8C\u6210"),!0)}catch{}return!1}async function O(t,e={}){let{minClicks:o=1,maxClicks:a=3,minDelay:s=300,maxDelay:n=500,referenceElement:u=null}=e;try{r("\u5F00\u59CB\u6A21\u62DF\u4EBA\u7C7B\u968F\u673A\u70B9\u51FB\u884C\u4E3A...");let h=Math.floor(Math.random()*(a-o+1))+o;r(`\u5C06\u8FDB\u884C ${h} \u6B21\u968F\u673A\u70B9\u51FB`);let l=null;if(u)try{let i=await u.boundingBox();i&&(l={x:i.x-50,y:Math.max(0,i.y-200),width:i.width+50,height:300},r(`\u4F7F\u7528\u8F93\u5165\u6846\u9644\u8FD1\u7684\u5B89\u5168\u533A\u57DF: x=${l.x}, y=${l.y}, w=${l.width}, h=${l.height}`))}catch(i){p(`\u83B7\u53D6\u53C2\u8003\u5143\u7D20\u4F4D\u7F6E\u5931\u8D25\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u5B89\u5168\u533A\u57DF: ${i.message}`)}if(!l){let i=t.viewportSize(),d=i?.width||1280,m=i?.height||720;l={x:d*.3,y:m*.3,width:d*.4,height:m*.2},r(`\u4F7F\u7528\u9ED8\u8BA4\u5B89\u5168\u533A\u57DF: x=${l.x}, y=${l.y}, w=${l.width}, h=${l.height}`)}for(let i=0;i<h;i++)try{let d=Math.floor(Math.random()*l.width)+l.x,m=Math.floor(Math.random()*l.height)+l.y;r(`\u7B2C ${i+1} \u6B21\u5B89\u5168\u70B9\u51FB: (${d}, ${m})`);let f=await t.locator("*").first().evaluate((g,x)=>{let w=document.elementFromPoint(x.x,x.y);if(!w)return{safe:!0};let S=w.tagName.toLowerCase(),b=w.hasAttribute("href"),y=w.hasAttribute("onclick")||w.onclick,E=S==="button"||w.type==="button",ee=S==="a"||b,te=["input","textarea","select"].includes(S);return{safe:!E&&!ee&&!y&&!te,tagName:S,hasHref:b,hasOnClick:y,isButton:E,isLink:ee,isInput:te}},{x:d,y:m});if(f.safe?(await t.mouse.move(d,m,{steps:Math.floor(Math.random()*10)+5}),await t.waitForTimeout(Math.floor(Math.random()*200)+100),await t.mouse.click(d,m),r(`\u5B89\u5168\u70B9\u51FB\u5B8C\u6210: (${d}, ${m})`)):r(`\u8DF3\u8FC7\u4E0D\u5B89\u5168\u7684\u70B9\u51FB\u4F4D\u7F6E (${d}, ${m}): ${f.tagName}`),i<h-1){let g=Math.floor(Math.random()*(n-s+1))+s;r(`\u7B49\u5F85 ${g}ms \u540E\u8FDB\u884C\u4E0B\u4E00\u6B21\u70B9\u51FB`),await t.waitForTimeout(g)}}catch(d){r(`\u7B2C ${i+1} \u6B21\u70B9\u51FB\u51FA\u73B0\u9519\u8BEF\uFF0C\u7EE7\u7EED\u4E0B\u4E00\u6B21: ${d.message}`)}r("\u5B89\u5168\u968F\u673A\u70B9\u51FB\u6A21\u62DF\u5B8C\u6210")}catch(h){p(`\u6A21\u62DF\u5B89\u5168\u968F\u673A\u70B9\u51FB\u65F6\u51FA\u73B0\u9519\u8BEF: ${h.message}`)}}async function G(t,e=5e3){try{r("\u68C0\u67E5\u662F\u5426\u6709\u6B22\u8FCE\u5BF9\u8BDD\u6846\u9700\u8981\u5173\u95ED...");let o="mat-dialog-container",a='button[mat-dialog-close][aria-label="close"]';if(await t.locator(o).first().isVisible({timeout:e})){r("\u53D1\u73B0\u6B22\u8FCE\u5BF9\u8BDD\u6846\uFF0C\u5C1D\u8BD5\u5173\u95ED...");let n=t.locator(a).first();return await n.isVisible({timeout:2e3})?(await n.click(),r("\u5DF2\u901A\u8FC7\u5173\u95ED\u6309\u94AE\u5173\u95ED\u6B22\u8FCE\u5BF9\u8BDD\u6846"),await t.waitForTimeout(1e3),!0):(r("\u672A\u627E\u5230\u5173\u95ED\u6309\u94AE\uFF0C\u5C1D\u8BD5\u6309ESC\u952E\u5173\u95ED\u5BF9\u8BDD\u6846"),await t.keyboard.press("Escape"),await t.waitForTimeout(1e3),!0)}else return r("\u672A\u53D1\u73B0\u6B22\u8FCE\u5BF9\u8BDD\u6846"),!1}catch(o){return r("\u5904\u7406\u6B22\u8FCE\u5BF9\u8BDD\u6846\u65F6\u51FA\u73B0\u9519\u8BEF\uFF0C\u7EE7\u7EED\u6267\u884C:",o.message),!1}}var se=!1;async function Xe(){if(!v){r("\u6D4F\u89C8\u5668\u5B9E\u4F8B\u4E0D\u5B58\u5728\uFF0C\u65E0\u9700\u6E05\u7406\u3002");return}r("\u{1F9F9} \u5F00\u59CB\u6E05\u7406\u6D4F\u89C8\u5668\u8D44\u6E90..."),I&&(await I.cleanup(),I=null,r("\u2705 \u9875\u9762\u6C60\u5DF2\u6E05\u7406\u3002")),T&&(await T.close(),T=null,r("\u2705 \u6D4F\u89C8\u5668\u4E0A\u4E0B\u6587\u5DF2\u5173\u95ED\u3002")),v&&(await v.close(),v=null,r("\u2705 \u6D4F\u89C8\u5668\u5B9E\u4F8B\u5DF2\u5173\u95ED\u3002")),r("\u2728 \u6240\u6709\u8D44\u6E90\u5747\u5DF2\u6210\u529F\u91CA\u653E\u3002")}async function Y(t){if(se){r("\u6E05\u7406\u5DF2\u5728\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7A0D\u5019...");return}se=!0,r(`
|
3 |
-
\u{1F6A8} \u6536\u5230\u4FE1\u53F7 ${t}\u3002\u5F00\u59CB\u4F18\u96C5\u505C\u673A...`);try{await Xe(),process.exit(0)}catch(e){p("\u274C \u5728\u4F18\u96C5\u505C\u673A\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:",e),process.exit(1)}}function le(){process.once("SIGUSR2",()=>
|
4 |
--- \u9875\u9762\u6C60\u72B6\u6001 @ ${e} ---
|
5 |
\u603B\u9875\u9762\u6570: ${t.total}
|
6 |
\u53EF\u7528\u9875\u9762\u6570: ${t.available}
|
@@ -8,17 +8,17 @@ var Me=Object.defineProperty;var oe=(t,e)=>()=>(t&&(e=t(t=0)),e);var ke=(t,e)=>{
|
|
8 |
\u6700\u5927\u9875\u9762\u6570: ${t.maxSize}
|
9 |
\u4F7F\u7528\u7387: ${o}%
|
10 |
------------------------------------
|
11 |
-
`)}function de(t){let e=t.node.res.getHeaders();if(e["access-control-allow-origin"]||t.node.res.setHeader("Access-Control-Allow-Origin",process.env.CORS_ORIGIN||"*"),e["access-control-allow-methods"]||t.node.res.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, OPTIONS"),e["access-control-allow-headers"]||t.node.res.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization"),e["access-control-max-age"]||t.node.res.setHeader("Access-Control-Max-Age","86400"),t.node.req.method==="OPTIONS")return t.node.res.statusCode=204,t.node.res.end()}function he(t){t.node.res.setHeader("Content-Type","text/event-stream"),t.node.res.setHeader("Cache-Control","no-cache"),t.node.res.setHeader("Connection","keep-alive"),t.node.res.setHeader("Access-Control-Allow-Origin",process.env.CORS_ORIGIN||"*"),t.node.res.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization")}function fe(t){let e=k(),o=e.total>0?Math.round(e.busy/e.total*100):0;return{status:"ok",timestamp:new Date().toISOString(),version:process.env.npm_package_version||"1.0.0",pagePool:{...e,utilization:`${o}%`}}}import{readBody as ot,createError as rt}from"h3";import{createError as Ve}from"h3";function
|
12 |
|
13 |
`+i:n=i:u.push({role:l.role,content:i}))}return{prompt:u.map(l=>`${l.role}: ${l.content}`).join(`
|
14 |
|
15 |
-
`),systemPrompt:n,stream:o,model:a,temperature:s,messages:e}}import{createError as J}from"h3";function ge(t){if(!c.api.token){process.env.NODE_ENV==="production"&&console.warn("\u8B66\u544A: API_TOKEN \u672A\u5728\u751F\u4EA7\u73AF\u5883\u4E2D\u914D\u7F6E\uFF0CAPI \u5BF9\u5916\u5F00\u653E\uFF01");return}let e=t.node.req.headers.authorization;if(!e)throw J({statusCode:401,statusMessage:"Unauthorized: Missing Authorization header."});let[o,a]=e.split(" ");if(o!=="Bearer"||!a)throw J({statusCode:401,statusMessage:"Unauthorized: Invalid Authorization header format. Expected: Bearer <token>."});if(a!==c.api.token)throw J({statusCode:401,statusMessage:"Unauthorized: Invalid API token."})}$();var N=class{constructor(e,o={}){this.page=e,this.options={enableHumanSimulation:!1,...o},this.modelMapping=Object.fromEntries(Object.entries(c.models).map(([a,s])=>[a,s.displayName]))}async waitForPageLoad(){try{return await this.page.waitForSelector("body",{timeout:15e3}),await G(this.page),!0}catch(e){return p("\u9875\u9762\u52A0\u8F7D\u8D85\u65F6\u6216\u5931\u8D25:",e),!1}}async findInputElement(){try{await this.page.waitForSelector("footer ms-prompt-input-wrapper",{timeout:1e4}),r("\u8F93\u5165\u6846\u7684\u7236\u5BB9\u5668\u5DF2\u52A0\u8F7D\u3002")}catch{_("\u7B49\u5F85\u8F93\u5165\u6846\u7236\u5BB9\u5668\u8D85\u65F6\uFF0C\u5C06\u7EE7\u7EED\u5C1D\u8BD5\u67E5\u627E...")}let e=['ms-prompt-input-wrapper textarea[aria-label*="prompt"]','textarea[placeholder="Start typing a prompt"]','textarea[aria-label="Start typing a prompt"]',"footer textarea",'textarea[placeholder*="prompt"]','textarea[aria-label*="prompt"]','div[contenteditable="true"]',"textarea"];for(let o of e)try{let a=this.page.locator(o),s=await a.count();if(s>0){r(`\u9009\u62E9\u5668 "${o}" \u627E\u5230\u4E86 ${s} \u4E2A\u5143\u7D20\u3002\u6B63\u5728\u68C0\u67E5\u53EF\u89C1\u6027\u548C\u53EF\u7528\u6027...`);for(let n=0;n<s;n++){let u=a.nth(n);if(await u.isVisible()&&await u.isEnabled())return r(`\u6210\u529F\u627E\u5230\u53EF\u7528\u8F93\u5165\u6846: ${o} (\u7D22\u5F15 ${n})`),u}r(`\u9009\u62E9\u5668 "${o}" \u627E\u5230\u7684\u5143\u7D20\u5747\u4E0D\u53EF\u89C1\u6216\u4E0D\u53EF\u7528\u3002`)}}catch(a){_(`\u4F7F\u7528\u9009\u62E9\u5668 "${o}" \u67E5\u627E\u65F6\u51FA\u9519: ${a.message}`)}if(p("\u5173\u952E\u9519\u8BEF: \u5C1D\u8BD5\u4E86\u6240\u6709\u9009\u62E9\u5668\u540E\uFF0C\u4ECD\u672A\u627E\u5230\u4EFB\u4F55\u53EF\u7528\u7684\u8F93\u5165\u5143\u7D20\u3002"),c.debug.saveScreenshots){let{saveScreenshot:o}=await Promise.resolve().then(()=>(F(),ne));await o(this.page,c.screenshotDir,"find-input-failed")}return null}async findSendButton(){let e=['button[aria-label="Run"]',"button.run-button",'button[aria-label*="Send"]','button[data-testid*="send"]'];for(let o of e){let a=this.page.locator(o);if(await a.count()>0){let s=a.first();if(!await s.isDisabled())return s}}return p("\u672A\u627E\u5230\u4EFB\u4F55\u53EF\u7528\u7684\u53D1\u9001\u6309\u94AE\u3002"),null}async fillMessage(e){let o=await this.findInputElement();if(!o)throw new Error("\u65E0\u6CD5\u627E\u5230\u8F93\u5165\u6846\u3002");try{return this.options.enableHumanSimulation&&await O(this.page,{referenceElement:o}),await o.fill(e),await this.page.waitForTimeout(200),r("\u6D88\u606F\u586B\u5145\u5B8C\u6210\u3002"),!0}catch(a){return p("\u586B\u5145\u6D88\u606F\u5931\u8D25:",a),!1}}async waitForSendButtonEnabled(e=1e4){try{return await this.page.locator('button[aria-label="Run"]:not([disabled]), button.run-button:not([disabled])').waitFor({state:"visible",timeout:e}),r("\u53D1\u9001\u6309\u94AE\u5DF2\u53EF\u7528\u3002"),!0}catch{return _("\u7B49\u5F85\u53D1\u9001\u6309\u94AE\u53EF\u7528\u8D85\u65F6\uFF0C\u5C06\u7EE7\u7EED\u5C1D\u8BD5\u3002"),!1}}async sendMessage(){if(this.options.enableHumanSimulation){let o=await this.findInputElement();await O(this.page,{referenceElement:o})}let e=await this.findSendButton();if(!e)throw new Error("\u65E0\u6CD5\u627E\u5230\u53EF\u7528\u7684\u53D1\u9001\u6309\u94AE\u3002");try{return await e.click(),r("\u6D88\u606F\u5DF2\u53D1\u9001\u3002"),!0}catch(o){p("\u70B9\u51FB\u53D1\u9001\u6309\u94AE\u5931\u8D25:",o);try{return r("\u5C1D\u8BD5\u4F7F\u7528\u952E\u76D8\u5FEB\u6377\u952E (Ctrl+Enter) \u53D1\u9001..."),await this.page.keyboard.press("Control+Enter"),r("\u5DF2\u4F7F\u7528\u952E\u76D8\u5FEB\u6377\u952E\u53D1\u9001\u3002"),!0}catch(a){return p("\u952E\u76D8\u5FEB\u6377\u952E\u53D1\u9001\u4E5F\u5931\u8D25:",a),!1}}}async setModel(e){try{let o=this.modelMapping[e]||e,a=this.page.locator("ms-model-selector-two-column");if(await a.count()===0)return r("\u672A\u627E\u5230\u6A21\u578B\u9009\u62E9\u5668\uFF0C\u8DF3\u8FC7\u6A21\u578B\u8BBE\u7F6E\u3002"),!1;if((await a.locator(".model-option-content .gmat-body-medium").textContent())?.trim()===o)return r("\u5F53\u524D\u5DF2\u662F\u76EE\u6807\u6A21\u578B\uFF0C\u65E0\u9700\u5207\u6362\u3002"),!0;await a.click({timeout:5e3});let n=this.page.locator(".mat-mdc-select-panel");await n.waitFor({state:"visible",timeout:5e3});let u=n.locator("mat-option.model-option",{hasText:o});return await u.count()>0?(await u.first().click({timeout:5e3}),await this.page.waitForTimeout(1e3),r(`\u6A21\u578B\u5DF2\u6210\u529F\u8BBE\u7F6E\u4E3A: ${o}`),!0):(r(`\u672A\u5728\u4E0B\u62C9\u83DC\u5355\u4E2D\u627E\u5230\u76EE\u6807\u6A21\u578B: ${o}`),await this.page.keyboard.press("Escape"),!1)}catch(o){p("\u8BBE\u7F6E\u6A21\u578B\u65F6\u53D1\u751F\u9519\u8BEF:",o);try{await this.page.keyboard.press("Escape")}catch{}return!1}}async setTemperature(e){try{let o=this.page.locator('[data-test-id="temperatureSliderContainer"]');if(await o.count()===0)return r("\u672A\u627E\u5230\u6E29\u5EA6\u8BBE\u7F6E\u5BB9\u5668\uFF0C\u8DF3\u8FC7\u3002"),!1;let a=o.locator('input[type="number"]');return await a.count()>0?(await a.fill(e.toString()),await a.dispatchEvent("change"),r(`\u6E29\u5EA6\u5DF2\u8BBE\u7F6E\u4E3A: ${e}`),!0):(r("\u672A\u627E\u5230\u6E29\u5EA6\u6570\u5B57\u8F93\u5165\u6846\uFF0C\u8DF3\u8FC7\u8BBE\u7F6E\u3002"),!1)}catch(o){return p("\u8BBE\u7F6E\u6E29\u5EA6\u65F6\u51FA\u9519:",o),!1}}async setSystemInstructions(e){try{let o=this.page.locator('button[mat-icon-button][aria-label="System instructions"]');if(await o.count()===0)return r("\u672A\u627E\u5230\u7CFB\u7EDF\u6307\u4EE4\u6309\u94AE\uFF0C\u8DF3\u8FC7\u7CFB\u7EDF\u6307\u4EE4\u8BBE\u7F6E\u3002"),!1;await o.click({timeout:5e3}),r("\u5DF2\u70B9\u51FB\u7CFB\u7EDF\u6307\u4EE4\u6309\u94AE\u3002");let a=this.page.locator('ms-system-instructions textarea[aria-label="System instructions"]');return await a.waitFor({state:"visible",timeout:5e3}),await a.fill(e),await this.page.waitForTimeout(200),r(`\u7CFB\u7EDF\u6307\u4EE4\u5DF2\u8BBE\u7F6E: ${e.substring(0,50)}${e.length>50?"...":""}`),!0}catch(o){return p("\u8BBE\u7F6E\u7CFB\u7EDF\u6307\u4EE4\u65F6\u53D1\u751F\u9519\u8BEF:",o),!1}}async processMessage(e,o={}){if(r("\u5F00\u59CB\u5904\u7406\u6D88\u606F..."),!await this.waitForPageLoad())throw new Error("\u9875\u9762\u52A0\u8F7D\u5931\u8D25\u3002");if(o.model&&await this.setModel(o.model),o.temperature!==void 0&&await this.setTemperature(o.temperature),o.systemPrompt&&await this.setSystemInstructions(o.systemPrompt),!await this.fillMessage(e))throw new Error("\u6D88\u606F\u586B\u5199\u5931\u8D25\u3002");if(await this.waitForSendButtonEnabled(),!await this.sendMessage())throw new Error("\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002");return r("\u6D88\u606F\u53D1\u9001\u6210\u529F\uFF0C\u7B49\u5F85\u7F51\u7EDC\u62E6\u622A\u83B7\u53D6\u54CD\u5E94\u3002"),!0}};$();var q=class{TARGET_URL_PATTERNS=["MakerSuiteService/GenerateContent"];FINAL_BLOCK_SIGNATURE_STR='\\[\\s*null\\s*,\\s*null\\s*,\\s*null\\s*,\\s*\\[\\s*"';constructor(e,o,a){this.page=e,this.onStreamChunk=o,this.onStreamEnd=a,this.uniqueId=`interceptor_${Date.now()}_${Math.random().toString(36).substring(2,9)}`,this.chunkCallbackName=`__onStreamChunk_${this.uniqueId}`,this.endCallbackName=`__onStreamEnd_${this.uniqueId}`,this.isInjected=!1,this.isActive=!1}async _inject(){if(this.isInjected)return;r(`[Interceptor] \u6CE8\u5165\u6D41\u5F0F\u62E6\u622A\u811A\u672C (ID: ${this.uniqueId})...`),await this.page.exposeFunction(this.chunkCallbackName,this.onStreamChunk),await this.page.exposeFunction(this.endCallbackName,this.onStreamEnd);let e={TARGET_URL_PATTERNS:this.TARGET_URL_PATTERNS,FINAL_BLOCK_SIGNATURE_STR:this.FINAL_BLOCK_SIGNATURE_STR,chunkCallbackName:this.chunkCallbackName,endCallbackName:this.endCallbackName},o=this._getBrowserScript();await this.page.evaluate(o,e),this.isInjected=!0,r(`[Interceptor] \u811A\u672C\u6CE8\u5165\u548C\u56DE\u8C03\u8FDE\u63A5\u5DF2\u4E00\u6B21\u6027\u5B8C\u6210 (ID: ${this.uniqueId})`)}async activate(){this.isActive||(await this._inject(),r(`[Interceptor] \u6FC0\u6D3B\u62E6\u622A\u5668 (ID: ${this.uniqueId})...`),await this.page.evaluate(()=>{window.__streamInterceptor&&window.__streamInterceptor.activate()}),this.isActive=!0,r(`[Interceptor] \u62E6\u622A\u5668\u5DF2\u6FC0\u6D3B (ID: ${this.uniqueId})`))}async deactivate(){if(this.isActive){r(`[Interceptor] \u505C\u7528\u62E6\u622A\u5668 (ID: ${this.uniqueId})...`);try{await this.page.evaluate(()=>{window.__streamInterceptor&&window.__streamInterceptor.deactivate()}),this.isActive=!1,r(`[Interceptor] \u62E6\u622A\u5668\u5DF2\u505C\u7528 (ID: ${this.uniqueId})`)}catch(e){p(`[Interceptor] \u505C\u7528\u65F6\u53D1\u751F\u9519\u8BEF (\u53EF\u80FD\u9875\u9762\u5DF2\u5173\u95ED): ${e.message}`)}}}_getBrowserScript(){return e=>{window.__streamInterceptor&&typeof window.__streamInterceptor.deactivate=="function"&&window.__streamInterceptor.deactivate();let{TARGET_URL_PATTERNS:o,FINAL_BLOCK_SIGNATURE_STR:a,chunkCallbackName:s,endCallbackName:n}=e,u=new RegExp(a),h=window.XMLHttpRequest.prototype.open,l=window.XMLHttpRequest.prototype.send,i=window[s],d=window[n];console.log(`[Interceptor] \u56DE\u8C03\u5DF2\u5728\u6CE8\u5165\u65F6\u76F4\u63A5\u83B7\u53D6: ${s}, ${n}`);let m=!1;window.__streamInterceptor={activate:()=>{m||(console.log("\u{1F3AF} [Interceptor] \u6FC0\u6D3B XHR \u8865\u4E01..."),m=!0,window.XMLHttpRequest.prototype.open=function(f,g,...x){return this._url=g,h.apply(this,[f,g,...x])},window.XMLHttpRequest.prototype.send=function(...f){let g=this._url?this._url.toString():"";if(o.some(w=>g.includes(w))&&m){console.log("\u{1F3AF} [Interceptor] \u62E6\u622A\u5230\u76EE\u6807\u8BF7\u6C42:",g);let w=0,S="",b=!1,y=()=>{if(b)return;b=!0,console.log("\u{1F3C1} [Interceptor] \u5224\u5B9A\u6D41\u5DF2\u7ED3\u675F\uFF0C\u6B63\u5728\u89E6\u53D1\u6700\u7EC8\u56DE\u8C03...");let E=S.slice(w);E&&i&&i(E),d&&d()};this.addEventListener("progress",()=>{if(b)return;S=this.responseText||"";let E=S.slice(w);E&&(i&&i(E),w=S.length,u.test(E)&&(console.log("\u2705 [Interceptor] \u68C0\u6D4B\u5230\u6700\u7EC8\u7B7E\u540D\uFF0C\u7ED3\u675F\u6D41"),y()))}),this.addEventListener("readystatechange",()=>{this.readyState===4&&!b&&(console.log(`[Interceptor] \u8BF7\u6C42\u5B8C\u6210 (readyState=4), HTTP\u72B6\u6001: ${this.status}`),y())}),this.addEventListener("error",E=>{console.error("[Interceptor] XHR \u8BF7\u6C42\u51FA\u9519:",E),b||y()}),this.addEventListener("abort",()=>{console.warn("[Interceptor] XHR \u8BF7\u6C42\u88AB\u4E2D\u6B62"),b||y()})}return l.apply(this,f)})},deactivate:()=>{m&&(console.log("\u{1F504} [Interceptor] \u505C\u7528 XHR \u8865\u4E01..."),window.XMLHttpRequest.prototype.open=h,window.XMLHttpRequest.prototype.send=l,m=!1)}}}}};$();function Je(t){return t.includes("The caller does not have permission")?{type:"error",content:"The caller does not have permission"}:t.includes("You exceeded your current quota")?{type:"error",content:"You exceeded your current quota, please check your plan and billing details. For more information on this error, head to: https://ai.google.dev/gemini-api/docs/rate-limits."}:null}function Qe(t){if(!Array.isArray(t))return null;let e=t[0];for(;Array.isArray(e)&&Array.isArray(e[0]);)e=e[0];return Array.isArray(e)&&e.length>=2&&e[0]===null&&typeof e[1]=="string"?e:null}function Ze(t){if(t.length===4&&t[0]===null&&t[1]===null&&t[2]===null)return{type:"done",content:"Stream finished"};if(t.length===3){let e=Qe(t);if(e){let o=e[1];return{type:e.length===2?"text":"thinking",content:o}}}return null}function Q(t){let e=Je(t);if(e)return{parsedItems:[e],remainingBuffer:""};let o=[],a=/(\d+\]\]),(\[\[\[\[\[\[)/g,s=/(\d+\]\]),(\[null,null,null,)/g,n="__ELEMENT_SEPARATOR__",u=t.replace(a,`$1,${n}$2`);u=u.replace(s,`$1,${n}$2`);let h=u.split(n);if(h.length===1)return{parsedItems:[],remainingBuffer:t};let l=h.pop()||"",i=h;for(let d of i){let m=d.trim();m.endsWith(",")&&(m=m.slice(0,-1)),m.startsWith("[[[[[[[[")&&(m=m.substring(2));try{let f=JSON.parse(m),g=Ze(f);g&&o.push(g)}catch(f){_(`\u89E3\u6790\u5143\u7D20\u5931\u8D25\uFF0C\u8DF3\u8FC7\u8BE5\u5757\u3002\u9519\u8BEF: ${f.message}, \u5143\u7D20\u5185\u5BB9: "${m}"`)}}return{parsedItems:o,remainingBuffer:l}}function Z(t,e,o="gemini-pro"){return{id:`chatcmpl-${Date.now()}`,object:"chat.completion.chunk",created:Math.floor(Date.now()/1e3),model:o,choices:[{index:0,delta:{content:t||"",type:e||"text"},logprobs:null,finish_reason:null}]}}function ye(t,e="gemini-pro"){return{object:"error",message:t,type:"invalid_request_error",model:e}}function Se(t,e="gemini-pro"){return{id:`chatcmpl-${Date.now()}`,object:"chat.completion",created:Math.floor(Date.now()/1e3),model:e,choices:[{index:0,message:{role:"assistant",content:t},finish_reason:"stop"}],usage:{prompt_tokens:0,completion_tokens:0,total_tokens:0}}}$();var j=3,be=1e3;function et(t){let e=t.message.toLowerCase();return["timeout","navigation failed","page crashed","target closed","element not found","is not visible","\u65E0\u6CD5\u627E\u5230","not find","cannot find"].some(a=>e.includes(a))}function tt(t){let e=t.message.toLowerCase();return["permission","unauthorized","quota","cookie"].some(a=>e.includes(a))}async function Ee(t,e,o){let a=null,s=null;try{a=await B();for(let n=1;n<=j;n++)try{r(`\u{1F310} [\u5C1D\u8BD5 ${n}/${j}] \u5F00\u59CB\u5904\u7406\u8BF7\u6C42...`),await U(a,c.aiStudio.url,{timeout:c.aiStudio.pageTimeout}),c.enableHumanSimulation&&(r("\u542F\u7528\u4E86\u4EBA\u7C7B\u884C\u4E3A\u6A21\u62DF\uFF0C\u7B49\u5F85\u51E0\u767E\u6BEB\u79D2\u540E\u8FDB\u884C\u968F\u673A\u70B9\u51FB..."),await a.waitForTimeout(Math.floor(Math.random()*300)+200),await O(a));let u=await o(a,t,e);return await M(a),u}catch(u){if(s=u,_(`\u274C [\u5C1D\u8BD5 ${n}/${j}] \u5931\u8D25: ${u.message}`),(tt(u)||et(u))&&n<j)r(`\u68C0\u6D4B\u5230\u53EF\u91CD\u8BD5\u7684\u9519\u8BEF\uFF08\u6743\u9650\u6216\u9875\u9762\u72B6\u6001\uFF09\uFF0C\u5C06\u5728 ${be}ms \u540E\u91CD\u8BD5...`),await new Promise(h=>setTimeout(h,be));else throw p("\u9519\u8BEF\u4E0D\u53EF\u91CD\u8BD5\u6216\u5DF2\u8FBE\u5230\u6700\u5927\u91CD\u8BD5\u6B21\u6570\uFF0C\u5C06\u629B\u51FA\u5F02\u5E38\u3002"),u}}catch(n){throw p("\u5904\u7406 AI Studio \u8BF7\u6C42\u6700\u7EC8\u5931\u8D25:",n),a&&await M(a),s||n}}async function Ie(t,e,o={}){let a=o.model||c.api.defaultModel;try{await Ee(t,o,async(s,n,u)=>new Promise(async(h,l)=>{let i=!1,d=null,m="",f=w=>{i||(i=!0,d&&d.deactivate().catch(p),w?l(w):h())},g=w=>{if(i)return;m+=w;let{parsedItems:S,remainingBuffer:b}=Q(m);if(m=b,S.length>0)for(let y of S){if(y.type==="error")return f(new Error(y.content));if(y.type==="done"){x();return}y.content?.trim()&&e.enqueue(`data: ${JSON.stringify(Z(y.content,y.type,a))}
|
16 |
|
17 |
-
`)}},
|
18 |
|
19 |
-
`),e.close(),f())};try{d=new q(s,
|
20 |
|
21 |
`),e.enqueue(`data: [DONE]
|
22 |
|
23 |
-
`),e.close()}catch(n){p("\u5173\u95ED\u6D41\u63A7\u5236\u5668\u65F6\u51FA\u9519:",n)}}}async function
|
24 |
\u{1F4CA} \u521D\u59CB\u9875\u9762\u6C60\u72B6\u6001:`),pe()},1e3);setTimeout(()=>{st()},2e3);
|
|
|
1 |
+
var Me=Object.defineProperty;var oe=(t,e)=>()=>(t&&(e=t(t=0)),e);var ke=(t,e)=>{for(var o in e)Me(t,o,{get:e[o],enumerable:!0})};import K from"node:fs";function Le(){K.existsSync(T.logDir)||K.mkdirSync(T.logDir,{recursive:!0})}function He(...t){return t.map(e=>typeof e=="object"&&e!==null?JSON.stringify(e,null,2):String(e)).join(" ")}async function De(t,e){if(!T.enableFile)return;Le();let a=`[${new Date().toISOString()}] [${t}] ${e}
|
2 |
+
`;try{await K.promises.appendFile(T.logFile,a)}catch(s){console.error("\u5199\u5165\u65E5\u5FD7\u6587\u4EF6\u5931\u8D25:",s)}}function Fe(t,...e){if(!T.enableConsole)return;let o={[x.DEBUG]:console.debug,[x.INFO]:console.log,[x.WARN]:console.warn,[x.ERROR]:console.error}[t]||console.log,a=new Date().toLocaleTimeString();o(`[${a}] [${t}]`,...e)}function W(t,...e){let o=He(...e);Fe(t,...e),De(t,o)}var x,T,r,v,p,P=oe(()=>{x={DEBUG:"DEBUG",INFO:"INFO",WARN:"WARN",ERROR:"ERROR"},T={logFile:"./logs/app.log",logDir:"./logs",enableConsole:!0,enableFile:!0,logLevel:process.env.LOG_LEVEL||x.ERROR};r=(...t)=>W(x.INFO,...t),v=(...t)=>W(x.WARN,...t),p=(...t)=>W(x.ERROR,...t)});var ne={};ke(ne,{checkCookieAvailability:()=>Ge,ensureDirectoryExists:()=>ae,getHumanReadableTimestamp:()=>re,loadCookies:()=>X,saveScreenshot:()=>V,waitForUserInput:()=>qe});import A from"node:fs";import Ue from"node:path";import Be from"node:readline";function re(){return new Date().toISOString().replace(/T/,"_").replace(/:/g,"-").replace(/\..+/,"")}function ae(t){A.existsSync(t)||(A.mkdirSync(t,{recursive:!0}),r(`\u5DF2\u521B\u5EFA\u76EE\u5F55: ${t}`))}function Ge(t,e){if(e)try{return JSON.parse(e),r("\u53D1\u73B0\u5E76\u9A8C\u8BC1\u4E86\u73AF\u5883\u53D8\u91CF\u4E2D\u7684 COOKIES\u3002"),!0}catch(o){p("\u73AF\u5883\u53D8\u91CF COOKIES \u683C\u5F0F\u65E0\u6548 (\u5FC5\u987B\u662F JSON \u6570\u7EC4\u5B57\u7B26\u4E32):",o.message)}return A.existsSync(t)?(r(`\u53D1\u73B0 Cookie \u6587\u4EF6: ${t}`),!0):(p(`Cookie \u6587\u4EF6\u4E0D\u5B58\u5728: ${t}\uFF0C\u4E14\u672A\u8BBE\u7F6E COOKIES \u73AF\u5883\u53D8\u91CF\u3002`),r("\u8BF7\u5148\u8FD0\u884C `npm run login` \u6216\u8BBE\u7F6E COOKIES \u73AF\u5883\u53D8\u91CF\u3002"),!1)}function X(t,e){try{if(e)return r("\u4ECE\u73AF\u5883\u53D8\u91CF COOKIES \u52A0\u8F7D Cookie..."),JSON.parse(e);if(A.existsSync(t))return r(`\u4ECE\u6587\u4EF6\u52A0\u8F7D Cookie: ${t}`),JSON.parse(A.readFileSync(t,"utf8"))}catch(o){throw p("\u52A0\u8F7D Cookie \u5931\u8D25:",o),new Error("\u65E0\u6CD5\u52A0\u8F7D\u6216\u89E3\u6790 Cookie\u3002")}return[]}async function V(t,e,o="screenshot",a=!0){if(ae(e),a){let n=re();o=`${o}_${n}`}let s=Ue.join(e,`${o}.png`);return await t.screenshot({path:s,fullPage:!0}),r(`\u622A\u56FE\u5DF2\u4FDD\u5B58: ${s}`),s}function qe(){let t=Be.createInterface({input:process.stdin,output:process.stdout});return new Promise(e=>{t.question("",()=>{t.close(),e()})})}var D=oe(()=>{P()});import{H3 as at,serve as nt,serveStatic as $e}from"h3";import{stat as Ce,readFile as Re}from"node:fs/promises";import{join as Te}from"node:path";import{chromium as je}from"playwright";import{newInjectedContext as ze}from"fingerprint-injector";import{FingerprintGenerator as Ke}from"fingerprint-generator";import Oe from"dotenv";Oe.config();var Ne={server:{port:parseInt(process.env.PORT||"3096",10),host:process.env.HOST||"localhost"},browser:{headless:(process.env.HEADLESS||"true").toLowerCase()!=="false",timeout:parseInt(process.env.TIMEOUT||"30000",10),executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH,args:["--disable-blink-features=AutomationControlled","--no-sandbox","--disable-dev-shm-usage","--disable-infobars","--disable-extensions"]},cookieFile:"./cookies.json",cookiesFromEnv:(()=>{if(process.env.COOKIES)return process.env.COOKIES;if(process.env.SECURE_3PSID&&process.env.SECURE_3PAPISID)return JSON.stringify([{name:"__Secure-3PSID",value:process.env.SECURE_3PSID,domain:".google.com",path:"/",expires:-1,httpOnly:!0,secure:!0,sameSite:"None"},{name:"__Secure-3PAPISID",value:process.env.SECURE_3PAPISID,domain:".google.com",path:"/",expires:-1,httpOnly:!1,secure:!0,sameSite:"None"}])})(),screenshotDir:"./screenshots",aiStudio:{url:process.env.AI_STUDIO_URL||"https://aistudio.google.com/prompts/new_chat",responseTimeout:parseInt(process.env.RESPONSE_TIMEOUT||"600000",10),pageTimeout:parseInt(process.env.PAGE_TIMEOUT||"30000",10)},api:{defaultModel:process.env.DEFAULT_MODEL||"gemini-pro",maxTokens:65536,temperature:1,token:process.env.API_TOKEN},models:{"gemini-2.5-pro":{displayName:"Gemini 2.5 Pro",id:"gemini-2.5-pro",object:"model",created:1704067200,owned_by:"google",permission:[],root:"gemini-2.5-pro",parent:null},"gemini-2.5-flash":{displayName:"Gemini 2.5 Flash",id:"gemini-2.5-flash",object:"model",created:1704067200,owned_by:"google",permission:[],root:"gemini-2.5-flash",parent:null},"gemini-pro":{displayName:"Gemini Pro",id:"gemini-pro",object:"model",created:1701388800,owned_by:"google",permission:[],root:"gemini-pro",parent:null},"gemini-flash":{displayName:"Gemini Flash",id:"gemini-flash",object:"model",created:1701388800,owned_by:"google",permission:[],root:"gemini-flash",parent:null}},debug:{logRequests:process.env.DEBUG_REQUESTS==="true",logResponses:process.env.DEBUG_RESPONSES==="true",saveScreenshots:process.env.SAVE_SCREENSHOTS==="true"},enableHumanSimulation:(process.env.ENABLE_HUMAN_SIMULATION||"false").toLowerCase()==="true"},c=Ne;D();P();var $=null,R=null,F=class{constructor(e=5){this.maxSize=e,this.availablePages=[],this.busyPages=new Set,this.totalPages=0}async getPage(){if(this.availablePages.length>0){let e=this.availablePages.pop();return this.busyPages.add(e),r(`\u4ECE\u9875\u9762\u6C60\u83B7\u53D6\u9875\u9762\uFF0C\u5F53\u524D\u5FD9\u788C\u9875\u9762\u6570: ${this.busyPages.size}`),e}if(this.totalPages<this.maxSize){let{context:e}=await We(),o=await e.newPage();return this.busyPages.add(o),this.totalPages++,r(`\u521B\u5EFA\u65B0\u9875\u9762\uFF0C\u603B\u9875\u9762\u6570: ${this.totalPages}\uFF0C\u5FD9\u788C\u9875\u9762\u6570: ${this.busyPages.size}`),o}return r("\u9875\u9762\u6C60\u5DF2\u6EE1\uFF0C\u7B49\u5F85\u9875\u9762\u91CA\u653E..."),new Promise(e=>{let o=()=>{if(this.availablePages.length>0){let a=this.availablePages.pop();this.busyPages.add(a),r(`\u7B49\u5F85\u540E\u83B7\u53D6\u5230\u9875\u9762\uFF0C\u5F53\u524D\u5FD9\u788C\u9875\u9762\u6570: ${this.busyPages.size}`),e(a)}else setTimeout(o,100)};o()})}async releasePage(e){if(!this.busyPages.has(e)){r("\u5C1D\u8BD5\u91CA\u653E\u4E0D\u5728\u5FD9\u788C\u5217\u8868\u4E2D\u7684\u9875\u9762");return}try{await this.cleanupPage(e),this.busyPages.delete(e),this.availablePages.push(e),r(`\u9875\u9762\u5DF2\u91CA\u653E\u56DE\u6C60\u4E2D\uFF0C\u53EF\u7528\u9875\u9762\u6570: ${this.availablePages.length}\uFF0C\u5FD9\u788C\u9875\u9762\u6570: ${this.busyPages.size}`)}catch(o){p(`\u6E05\u7406\u9875\u9762\u65F6\u51FA\u9519\uFF0C\u5C06\u5173\u95ED\u8BE5\u9875\u9762: ${o.message}`),await this.removePage(e)}}async cleanupPage(e){try{e.removeAllListeners();try{await e.evaluate(()=>{Object.keys(window).forEach(a=>{(a.startsWith("__handleStreamChunk")||a.startsWith("__onStreamChunk")||a.startsWith("__onStreamEnd"))&&delete window[a]}),window.__streamInterceptor&&(typeof window.__streamInterceptor.deactivate=="function"&&window.__streamInterceptor.deactivate(),delete window.__streamInterceptor),delete window.__handleStreamChunk,delete window.__onStreamChunk,delete window.__onStreamEnd,delete window.__streamCallbacks})}catch(o){r(`\u6E05\u7406\u9875\u9762\u72B6\u6001\u65F6\u51FA\u73B0evaluate\u9519\u8BEF: ${o.message}`)}r("\u9875\u9762\u72B6\u6001\u5DF2\u6E05\u7406")}catch(o){throw new Error(`\u6E05\u7406\u9875\u9762\u5931\u8D25: ${o.message}`)}}async removePage(e){try{this.busyPages.delete(e);let o=this.availablePages.indexOf(e);o>-1&&this.availablePages.splice(o,1),await e.close(),this.totalPages--,r(`\u9875\u9762\u5DF2\u4ECE\u6C60\u4E2D\u79FB\u9664\uFF0C\u603B\u9875\u9762\u6570: ${this.totalPages}`)}catch(o){p(`\u5173\u95ED\u9875\u9762\u65F6\u51FA\u9519: ${o.message}`)}}async cleanup(){r("\u5F00\u59CB\u6E05\u7406\u9875\u9762\u6C60...");for(let e of this.busyPages)try{await e.close()}catch(o){p(`\u5173\u95ED\u5FD9\u788C\u9875\u9762\u65F6\u51FA\u9519: ${o.message}`)}for(let e of this.availablePages)try{await e.close()}catch(o){p(`\u5173\u95ED\u53EF\u7528\u9875\u9762\u65F6\u51FA\u9519: ${o.message}`)}this.busyPages.clear(),this.availablePages=[],this.totalPages=0,r("\u9875\u9762\u6C60\u6E05\u7406\u5B8C\u6210")}getStatus(){return{total:this.totalPages,available:this.availablePages.length,busy:this.busyPages.size,maxSize:this.maxSize}}},I=null;async function We(){if(!$){$=await je.launch({headless:c.browser.headless,timeout:c.browser.timeout,args:c.browser.args,executablePath:c.browser.executablePath});let t=new Ke().getFingerprint({devices:["desktop"],operatingSystems:["windows"],browsers:[{name:"chrome"}]});R=await ze($,{fingerprint:t,newContextOptions:{locale:"zh-CN",serviceWorkers:"allow",javaScriptEnabled:!0,bypassCSP:!1}});let e=X(c.cookieFile,c.cookiesFromEnv);await R.addCookies(e)}return{browser:$,context:R}}function ie(t=5){return I||(I=new F(t),r(`\u9875\u9762\u6C60\u5DF2\u521D\u59CB\u5316\uFF0C\u6700\u5927\u9875\u9762\u6570: ${t}`)),I}function ce(){return I||(I=new F,r("\u9875\u9762\u6C60\u5DF2\u81EA\u52A8\u521D\u59CB\u5316\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E")),I}async function U(){let e=await ce().getPage();return await e.bringToFront(),e}async function M(t){await ce().releasePage(t)}function k(){return I?I.getStatus():{total:0,available:0,busy:0,maxSize:0}}async function B(t,e,o={}){let a=t.url();r("\u5F53\u524D\u9875\u9762URL:",a),r("\u76EE\u6807URL:",e);try{return a!==e?(r("\u9875\u9762URL\u4E0D\u5339\u914D\uFF0C\u9700\u8981\u5BFC\u822A..."),await t.goto(e,{waitUntil:"load",timeout:3e4,...o}),r("\u9875\u9762\u5BFC\u822A\u5B8C\u6210"),!0):(r("\u9875\u9762\u5DF2\u5728\u76EE\u6807URL\uFF0C\u8FDB\u884C\u5237\u65B0\u4EE5\u786E\u4FDD\u6700\u65B0\u72B6\u6001..."),await t.bringToFront(),await t.reload({waitUntil:"load",timeout:3e4,...o}),r("\u9875\u9762\u5237\u65B0\u5B8C\u6210"),!0)}catch{}return!1}async function O(t,e={}){let{minClicks:o=1,maxClicks:a=3,minDelay:s=300,maxDelay:n=500,referenceElement:u=null}=e;try{r("\u5F00\u59CB\u6A21\u62DF\u4EBA\u7C7B\u968F\u673A\u70B9\u51FB\u884C\u4E3A...");let h=Math.floor(Math.random()*(a-o+1))+o;r(`\u5C06\u8FDB\u884C ${h} \u6B21\u968F\u673A\u70B9\u51FB`);let l=null;if(u)try{let i=await u.boundingBox();i&&(l={x:i.x-50,y:Math.max(0,i.y-200),width:i.width+50,height:300},r(`\u4F7F\u7528\u8F93\u5165\u6846\u9644\u8FD1\u7684\u5B89\u5168\u533A\u57DF: x=${l.x}, y=${l.y}, w=${l.width}, h=${l.height}`))}catch(i){p(`\u83B7\u53D6\u53C2\u8003\u5143\u7D20\u4F4D\u7F6E\u5931\u8D25\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u5B89\u5168\u533A\u57DF: ${i.message}`)}if(!l){let i=t.viewportSize(),d=i?.width||1280,m=i?.height||720;l={x:d*.3,y:m*.3,width:d*.4,height:m*.2},r(`\u4F7F\u7528\u9ED8\u8BA4\u5B89\u5168\u533A\u57DF: x=${l.x}, y=${l.y}, w=${l.width}, h=${l.height}`)}for(let i=0;i<h;i++)try{let d=Math.floor(Math.random()*l.width)+l.x,m=Math.floor(Math.random()*l.height)+l.y;r(`\u7B2C ${i+1} \u6B21\u5B89\u5168\u70B9\u51FB: (${d}, ${m})`);let f=await t.locator("*").first().evaluate((w,_)=>{let g=document.elementFromPoint(_.x,_.y);if(!g)return{safe:!0};let S=g.tagName.toLowerCase(),b=g.hasAttribute("href"),y=g.hasAttribute("onclick")||g.onclick,E=S==="button"||g.type==="button",ee=S==="a"||b,te=["input","textarea","select"].includes(S);return{safe:!E&&!ee&&!y&&!te,tagName:S,hasHref:b,hasOnClick:y,isButton:E,isLink:ee,isInput:te}},{x:d,y:m});if(f.safe?(await t.mouse.move(d,m,{steps:Math.floor(Math.random()*10)+5}),await t.waitForTimeout(Math.floor(Math.random()*200)+100),await t.mouse.click(d,m),r(`\u5B89\u5168\u70B9\u51FB\u5B8C\u6210: (${d}, ${m})`)):r(`\u8DF3\u8FC7\u4E0D\u5B89\u5168\u7684\u70B9\u51FB\u4F4D\u7F6E (${d}, ${m}): ${f.tagName}`),i<h-1){let w=Math.floor(Math.random()*(n-s+1))+s;r(`\u7B49\u5F85 ${w}ms \u540E\u8FDB\u884C\u4E0B\u4E00\u6B21\u70B9\u51FB`),await t.waitForTimeout(w)}}catch(d){r(`\u7B2C ${i+1} \u6B21\u70B9\u51FB\u51FA\u73B0\u9519\u8BEF\uFF0C\u7EE7\u7EED\u4E0B\u4E00\u6B21: ${d.message}`)}r("\u5B89\u5168\u968F\u673A\u70B9\u51FB\u6A21\u62DF\u5B8C\u6210")}catch(h){p(`\u6A21\u62DF\u5B89\u5168\u968F\u673A\u70B9\u51FB\u65F6\u51FA\u73B0\u9519\u8BEF: ${h.message}`)}}async function G(t,e=5e3){try{r("\u68C0\u67E5\u662F\u5426\u6709\u6B22\u8FCE\u5BF9\u8BDD\u6846\u9700\u8981\u5173\u95ED...");let o="mat-dialog-container",a='button[mat-dialog-close][aria-label="close"]';if(await t.locator(o).first().isVisible({timeout:e})){r("\u53D1\u73B0\u6B22\u8FCE\u5BF9\u8BDD\u6846\uFF0C\u5C1D\u8BD5\u5173\u95ED...");let n=t.locator(a).first();return await n.isVisible({timeout:2e3})?(await n.click(),r("\u5DF2\u901A\u8FC7\u5173\u95ED\u6309\u94AE\u5173\u95ED\u6B22\u8FCE\u5BF9\u8BDD\u6846"),await t.waitForTimeout(1e3),!0):(r("\u672A\u627E\u5230\u5173\u95ED\u6309\u94AE\uFF0C\u5C1D\u8BD5\u6309ESC\u952E\u5173\u95ED\u5BF9\u8BDD\u6846"),await t.keyboard.press("Escape"),await t.waitForTimeout(1e3),!0)}else return r("\u672A\u53D1\u73B0\u6B22\u8FCE\u5BF9\u8BDD\u6846"),!1}catch(o){return r("\u5904\u7406\u6B22\u8FCE\u5BF9\u8BDD\u6846\u65F6\u51FA\u73B0\u9519\u8BEF\uFF0C\u7EE7\u7EED\u6267\u884C:",o.message),!1}}var se=!1;async function Xe(){if(!$){r("\u6D4F\u89C8\u5668\u5B9E\u4F8B\u4E0D\u5B58\u5728\uFF0C\u65E0\u9700\u6E05\u7406\u3002");return}r("\u{1F9F9} \u5F00\u59CB\u6E05\u7406\u6D4F\u89C8\u5668\u8D44\u6E90..."),I&&(await I.cleanup(),I=null,r("\u2705 \u9875\u9762\u6C60\u5DF2\u6E05\u7406\u3002")),R&&(await R.close(),R=null,r("\u2705 \u6D4F\u89C8\u5668\u4E0A\u4E0B\u6587\u5DF2\u5173\u95ED\u3002")),$&&(await $.close(),$=null,r("\u2705 \u6D4F\u89C8\u5668\u5B9E\u4F8B\u5DF2\u5173\u95ED\u3002")),r("\u2728 \u6240\u6709\u8D44\u6E90\u5747\u5DF2\u6210\u529F\u91CA\u653E\u3002")}async function J(t){if(se){r("\u6E05\u7406\u5DF2\u5728\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7A0D\u5019...");return}se=!0,r(`
|
3 |
+
\u{1F6A8} \u6536\u5230\u4FE1\u53F7 ${t}\u3002\u5F00\u59CB\u4F18\u96C5\u505C\u673A...`);try{await Xe(),process.exit(0)}catch(e){p("\u274C \u5728\u4F18\u96C5\u505C\u673A\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:",e),process.exit(1)}}function le(){process.once("SIGUSR2",()=>J("SIGUSR2")),process.on("SIGINT",()=>J("SIGINT")),process.on("SIGTERM",()=>J("SIGTERM"))}P();var ue=null;function me(t=1e4){if(ue){r("\u9875\u9762\u6C60\u76D1\u63A7\u5DF2\u5728\u8FD0\u884C\u4E2D\u3002");return}r(`\u5F00\u59CB\u76D1\u63A7\u9875\u9762\u6C60\u72B6\u6001\uFF0C\u95F4\u9694: ${t}ms`),ue=setInterval(()=>{let e=k(),o=new Date().toLocaleTimeString(),a=e.total>0?(e.busy/e.total*100).toFixed(1):0;r(`[${o}] \u9875\u9762\u6C60\u72B6\u6001: \u603B\u8BA1=${e.total}, \u53EF\u7528=${e.available}, \u5FD9\u788C=${e.busy}, \u4F7F\u7528\u7387=${a}%`)},t)}function pe(){let t=k(),e=new Date().toLocaleString(),o=t.total>0?(t.busy/t.total*100).toFixed(1):0;r(`
|
4 |
--- \u9875\u9762\u6C60\u72B6\u6001 @ ${e} ---
|
5 |
\u603B\u9875\u9762\u6570: ${t.total}
|
6 |
\u53EF\u7528\u9875\u9762\u6570: ${t.available}
|
|
|
8 |
\u6700\u5927\u9875\u9762\u6570: ${t.maxSize}
|
9 |
\u4F7F\u7528\u7387: ${o}%
|
10 |
------------------------------------
|
11 |
+
`)}function de(t){let e=t.node.res.getHeaders();if(e["access-control-allow-origin"]||t.node.res.setHeader("Access-Control-Allow-Origin",process.env.CORS_ORIGIN||"*"),e["access-control-allow-methods"]||t.node.res.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, OPTIONS"),e["access-control-allow-headers"]||t.node.res.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization"),e["access-control-max-age"]||t.node.res.setHeader("Access-Control-Max-Age","86400"),t.node.req.method==="OPTIONS")return t.node.res.statusCode=204,t.node.res.end()}function he(t){t.node.res.setHeader("Content-Type","text/event-stream"),t.node.res.setHeader("Cache-Control","no-cache"),t.node.res.setHeader("Connection","keep-alive"),t.node.res.setHeader("Access-Control-Allow-Origin",process.env.CORS_ORIGIN||"*"),t.node.res.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization")}function fe(t){let e=k(),o=e.total>0?Math.round(e.busy/e.total*100):0;return{status:"ok",timestamp:new Date().toISOString(),version:process.env.npm_package_version||"1.0.0",pagePool:{...e,utilization:`${o}%`}}}import{readBody as ot,createError as rt}from"h3";import{createError as Ve}from"h3";function Je(t){return typeof t=="string"?t:Array.isArray(t)?t.map(e=>{if(e.type==="text"){if(typeof e.text=="string")return e.text;if(e.text&&typeof e.text.value=="string")return e.text.value}return""}).filter(e=>e.trim()).join(" "):""}function ge(t){let{messages:e,stream:o=!1,model:a=c.api.defaultModel,temperature:s=c.api.temperature}=t;if(!e||!Array.isArray(e)||e.length===0)throw Ve({statusCode:400,statusMessage:"Invalid request: `messages` must be a non-empty array."});let n="",u=[];for(let l of e){if(!l.role||!l.content)continue;let i=Je(l.content);i.trim()&&(l.role==="system"?n?n+=`
|
12 |
|
13 |
`+i:n=i:u.push({role:l.role,content:i}))}return{prompt:u.map(l=>`${l.role}: ${l.content}`).join(`
|
14 |
|
15 |
+
`),systemPrompt:n,stream:o,model:a,temperature:s,messages:e}}import{createError as Y}from"h3";function we(t){if(!c.api.token){process.env.NODE_ENV==="production"&&console.warn("\u8B66\u544A: API_TOKEN \u672A\u5728\u751F\u4EA7\u73AF\u5883\u4E2D\u914D\u7F6E\uFF0CAPI \u5BF9\u5916\u5F00\u653E\uFF01");return}let e=t.node.req.headers.authorization;if(!e)throw Y({statusCode:401,statusMessage:"Unauthorized: Missing Authorization header."});let[o,a]=e.split(" ");if(o!=="Bearer"||!a)throw Y({statusCode:401,statusMessage:"Unauthorized: Invalid Authorization header format. Expected: Bearer <token>."});if(a!==c.api.token)throw Y({statusCode:401,statusMessage:"Unauthorized: Invalid API token."})}P();var N=class{constructor(e,o={}){this.page=e,this.options={enableHumanSimulation:!1,...o},this.modelMapping=Object.fromEntries(Object.entries(c.models).map(([a,s])=>[a,s.displayName]))}async waitForPageLoad(){try{return await this.page.waitForSelector("body",{timeout:15e3}),await G(this.page),!0}catch(e){return p("\u9875\u9762\u52A0\u8F7D\u8D85\u65F6\u6216\u5931\u8D25:",e),!1}}async findInputElement(){try{await this.page.waitForSelector("footer ms-prompt-input-wrapper",{timeout:1e4}),r("\u8F93\u5165\u6846\u7684\u7236\u5BB9\u5668\u5DF2\u52A0\u8F7D\u3002")}catch{v("\u7B49\u5F85\u8F93\u5165\u6846\u7236\u5BB9\u5668\u8D85\u65F6\uFF0C\u5C06\u7EE7\u7EED\u5C1D\u8BD5\u67E5\u627E...")}let e=['ms-prompt-input-wrapper textarea[aria-label*="prompt"]','textarea[placeholder="Start typing a prompt"]','textarea[aria-label="Start typing a prompt"]',"footer textarea",'textarea[placeholder*="prompt"]','textarea[aria-label*="prompt"]','div[contenteditable="true"]',"textarea"];for(let o of e)try{let a=this.page.locator(o),s=await a.count();if(s>0){r(`\u9009\u62E9\u5668 "${o}" \u627E\u5230\u4E86 ${s} \u4E2A\u5143\u7D20\u3002\u6B63\u5728\u68C0\u67E5\u53EF\u89C1\u6027\u548C\u53EF\u7528\u6027...`);for(let n=0;n<s;n++){let u=a.nth(n);if(await u.isVisible()&&await u.isEnabled())return r(`\u6210\u529F\u627E\u5230\u53EF\u7528\u8F93\u5165\u6846: ${o} (\u7D22\u5F15 ${n})`),u}r(`\u9009\u62E9\u5668 "${o}" \u627E\u5230\u7684\u5143\u7D20\u5747\u4E0D\u53EF\u89C1\u6216\u4E0D\u53EF\u7528\u3002`)}}catch(a){v(`\u4F7F\u7528\u9009\u62E9\u5668 "${o}" \u67E5\u627E\u65F6\u51FA\u9519: ${a.message}`)}if(p("\u5173\u952E\u9519\u8BEF: \u5C1D\u8BD5\u4E86\u6240\u6709\u9009\u62E9\u5668\u540E\uFF0C\u4ECD\u672A\u627E\u5230\u4EFB\u4F55\u53EF\u7528\u7684\u8F93\u5165\u5143\u7D20\u3002"),c.debug.saveScreenshots){let{saveScreenshot:o}=await Promise.resolve().then(()=>(D(),ne));await o(this.page,c.screenshotDir,"find-input-failed")}return null}async findSendButton(){let e=['button[aria-label="Run"]',"button.run-button",'button[aria-label*="Send"]','button[data-testid*="send"]'];for(let o of e){let a=this.page.locator(o);if(await a.count()>0){let s=a.first();if(!await s.isDisabled())return s}}return p("\u672A\u627E\u5230\u4EFB\u4F55\u53EF\u7528\u7684\u53D1\u9001\u6309\u94AE\u3002"),null}async fillMessage(e){let o=await this.findInputElement();if(!o)throw new Error("\u65E0\u6CD5\u627E\u5230\u8F93\u5165\u6846\u3002");try{return this.options.enableHumanSimulation&&await O(this.page,{referenceElement:o}),await o.fill(e),await this.page.waitForTimeout(200),r("\u6D88\u606F\u586B\u5145\u5B8C\u6210\u3002"),!0}catch(a){return p("\u586B\u5145\u6D88\u606F\u5931\u8D25:",a),!1}}async waitForSendButtonEnabled(e=1e4){try{return await this.page.locator('button[aria-label="Run"]:not([disabled]), button.run-button:not([disabled])').waitFor({state:"visible",timeout:e}),r("\u53D1\u9001\u6309\u94AE\u5DF2\u53EF\u7528\u3002"),!0}catch{return v("\u7B49\u5F85\u53D1\u9001\u6309\u94AE\u53EF\u7528\u8D85\u65F6\uFF0C\u5C06\u7EE7\u7EED\u5C1D\u8BD5\u3002"),!1}}async sendMessage(){if(this.options.enableHumanSimulation){let o=await this.findInputElement();await O(this.page,{referenceElement:o})}let e=await this.findSendButton();if(!e)throw new Error("\u65E0\u6CD5\u627E\u5230\u53EF\u7528\u7684\u53D1\u9001\u6309\u94AE\u3002");try{return await e.click(),r("\u6D88\u606F\u5DF2\u53D1\u9001\u3002"),!0}catch(o){p("\u70B9\u51FB\u53D1\u9001\u6309\u94AE\u5931\u8D25:",o);try{return r("\u5C1D\u8BD5\u4F7F\u7528\u952E\u76D8\u5FEB\u6377\u952E (Ctrl+Enter) \u53D1\u9001..."),await this.page.keyboard.press("Control+Enter"),r("\u5DF2\u4F7F\u7528\u952E\u76D8\u5FEB\u6377\u952E\u53D1\u9001\u3002"),!0}catch(a){return p("\u952E\u76D8\u5FEB\u6377\u952E\u53D1\u9001\u4E5F\u5931\u8D25:",a),!1}}}async setModel(e){try{let o=this.modelMapping[e]||e,a=this.page.locator("ms-model-selector-two-column");if(await a.count()===0)return r("\u672A\u627E\u5230\u6A21\u578B\u9009\u62E9\u5668\uFF0C\u8DF3\u8FC7\u6A21\u578B\u8BBE\u7F6E\u3002"),!1;if((await a.locator(".model-option-content .gmat-body-medium").textContent())?.trim()===o)return r("\u5F53\u524D\u5DF2\u662F\u76EE\u6807\u6A21\u578B\uFF0C\u65E0\u9700\u5207\u6362\u3002"),!0;await a.click({timeout:5e3});let n=this.page.locator(".mat-mdc-select-panel");await n.waitFor({state:"visible",timeout:5e3});let u=n.locator("mat-option.model-option",{hasText:o});return await u.count()>0?(await u.first().click({timeout:5e3}),await this.page.waitForTimeout(1e3),r(`\u6A21\u578B\u5DF2\u6210\u529F\u8BBE\u7F6E\u4E3A: ${o}`),!0):(r(`\u672A\u5728\u4E0B\u62C9\u83DC\u5355\u4E2D\u627E\u5230\u76EE\u6807\u6A21\u578B: ${o}`),await this.page.keyboard.press("Escape"),!1)}catch(o){p("\u8BBE\u7F6E\u6A21\u578B\u65F6\u53D1\u751F\u9519\u8BEF:",o);try{await this.page.keyboard.press("Escape")}catch{}return!1}}async setTemperature(e){try{let o=this.page.locator('[data-test-id="temperatureSliderContainer"]');if(await o.count()===0)return r("\u672A\u627E\u5230\u6E29\u5EA6\u8BBE\u7F6E\u5BB9\u5668\uFF0C\u8DF3\u8FC7\u3002"),!1;let a=o.locator('input[type="number"]');return await a.count()>0?(await a.fill(e.toString()),await a.dispatchEvent("change"),r(`\u6E29\u5EA6\u5DF2\u8BBE\u7F6E\u4E3A: ${e}`),!0):(r("\u672A\u627E\u5230\u6E29\u5EA6\u6570\u5B57\u8F93\u5165\u6846\uFF0C\u8DF3\u8FC7\u8BBE\u7F6E\u3002"),!1)}catch(o){return p("\u8BBE\u7F6E\u6E29\u5EA6\u65F6\u51FA\u9519:",o),!1}}async setSystemInstructions(e){try{let o=this.page.locator('button[mat-icon-button][aria-label="System instructions"]');if(await o.count()===0)return r("\u672A\u627E\u5230\u7CFB\u7EDF\u6307\u4EE4\u6309\u94AE\uFF0C\u8DF3\u8FC7\u7CFB\u7EDF\u6307\u4EE4\u8BBE\u7F6E\u3002"),!1;await o.click({timeout:5e3}),r("\u5DF2\u70B9\u51FB\u7CFB\u7EDF\u6307\u4EE4\u6309\u94AE\u3002");let a=this.page.locator('ms-system-instructions textarea[aria-label="System instructions"]');return await a.waitFor({state:"visible",timeout:5e3}),await a.fill(e),await this.page.waitForTimeout(200),r(`\u7CFB\u7EDF\u6307\u4EE4\u5DF2\u8BBE\u7F6E: ${e.substring(0,50)}${e.length>50?"...":""}`),!0}catch(o){return p("\u8BBE\u7F6E\u7CFB\u7EDF\u6307\u4EE4\u65F6\u53D1\u751F\u9519\u8BEF:",o),!1}}async processMessage(e,o={}){if(r("\u5F00\u59CB\u5904\u7406\u6D88\u606F..."),!await this.waitForPageLoad())throw new Error("\u9875\u9762\u52A0\u8F7D\u5931\u8D25\u3002");if(o.model&&await this.setModel(o.model),o.temperature!==void 0&&await this.setTemperature(o.temperature),o.systemPrompt&&await this.setSystemInstructions(o.systemPrompt),!await this.fillMessage(e))throw new Error("\u6D88\u606F\u586B\u5199\u5931\u8D25\u3002");if(await this.waitForSendButtonEnabled(),!await this.sendMessage())throw new Error("\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002");return r("\u6D88\u606F\u53D1\u9001\u6210\u529F\uFF0C\u7B49\u5F85\u7F51\u7EDC\u62E6\u622A\u83B7\u53D6\u54CD\u5E94\u3002"),!0}};P();var q=class{TARGET_URL_PATTERNS=["MakerSuiteService/GenerateContent"];FINAL_BLOCK_SIGNATURE_STR='\\[\\s*null\\s*,\\s*null\\s*,\\s*null\\s*,\\s*\\[\\s*"';constructor(e,o,a){this.page=e,this.onStreamChunk=o,this.onStreamEnd=a,this.uniqueId=`interceptor_${Date.now()}_${Math.random().toString(36).substring(2,9)}`,this.chunkCallbackName=`__onStreamChunk_${this.uniqueId}`,this.endCallbackName=`__onStreamEnd_${this.uniqueId}`,this.isInjected=!1,this.isActive=!1}async _inject(){if(this.isInjected)return;r(`[Interceptor] \u6CE8\u5165\u6D41\u5F0F\u62E6\u622A\u811A\u672C (ID: ${this.uniqueId})...`),await this.page.exposeFunction(this.chunkCallbackName,this.onStreamChunk),await this.page.exposeFunction(this.endCallbackName,this.onStreamEnd);let e={TARGET_URL_PATTERNS:this.TARGET_URL_PATTERNS,FINAL_BLOCK_SIGNATURE_STR:this.FINAL_BLOCK_SIGNATURE_STR,chunkCallbackName:this.chunkCallbackName,endCallbackName:this.endCallbackName},o=this._getBrowserScript();await this.page.evaluate(o,e),this.isInjected=!0,r(`[Interceptor] \u811A\u672C\u6CE8\u5165\u548C\u56DE\u8C03\u8FDE\u63A5\u5DF2\u4E00\u6B21\u6027\u5B8C\u6210 (ID: ${this.uniqueId})`)}async activate(){this.isActive||(await this._inject(),r(`[Interceptor] \u6FC0\u6D3B\u62E6\u622A\u5668 (ID: ${this.uniqueId})...`),await this.page.evaluate(()=>{window.__streamInterceptor&&window.__streamInterceptor.activate()}),this.isActive=!0,r(`[Interceptor] \u62E6\u622A\u5668\u5DF2\u6FC0\u6D3B (ID: ${this.uniqueId})`))}async deactivate(){if(this.isActive){r(`[Interceptor] \u505C\u7528\u62E6\u622A\u5668 (ID: ${this.uniqueId})...`);try{await this.page.evaluate(()=>{window.__streamInterceptor&&window.__streamInterceptor.deactivate()}),this.isActive=!1,r(`[Interceptor] \u62E6\u622A\u5668\u5DF2\u505C\u7528 (ID: ${this.uniqueId})`)}catch(e){p(`[Interceptor] \u505C\u7528\u65F6\u53D1\u751F\u9519\u8BEF (\u53EF\u80FD\u9875\u9762\u5DF2\u5173\u95ED): ${e.message}`)}}}_getBrowserScript(){return e=>{window.__streamInterceptor&&typeof window.__streamInterceptor.deactivate=="function"&&window.__streamInterceptor.deactivate();let{TARGET_URL_PATTERNS:o,FINAL_BLOCK_SIGNATURE_STR:a,chunkCallbackName:s,endCallbackName:n}=e,u=new RegExp(a),h=window.XMLHttpRequest.prototype.open,l=window.XMLHttpRequest.prototype.send,i=window[s],d=window[n];console.log(`[Interceptor] \u56DE\u8C03\u5DF2\u5728\u6CE8\u5165\u65F6\u76F4\u63A5\u83B7\u53D6: ${s}, ${n}`);let m=!1;window.__streamInterceptor={activate:()=>{m||(console.log("\u{1F3AF} [Interceptor] \u6FC0\u6D3B XHR \u8865\u4E01..."),m=!0,window.XMLHttpRequest.prototype.open=function(f,w,..._){return this._url=w,h.apply(this,[f,w,..._])},window.XMLHttpRequest.prototype.send=function(...f){let w=this._url?this._url.toString():"";if(o.some(g=>w.includes(g))&&m){console.log("\u{1F3AF} [Interceptor] \u62E6\u622A\u5230\u76EE\u6807\u8BF7\u6C42:",w);let g=0,S="",b=!1,y=()=>{if(b)return;b=!0,console.log("\u{1F3C1} [Interceptor] \u5224\u5B9A\u6D41\u5DF2\u7ED3\u675F\uFF0C\u6B63\u5728\u89E6\u53D1\u6700\u7EC8\u56DE\u8C03...");let E=S.slice(g);E&&i&&i(E),d&&d()};this.addEventListener("progress",()=>{if(b)return;S=this.responseText||"";let E=S.slice(g);E&&(i&&i(E),g=S.length,u.test(E)&&(console.log("\u2705 [Interceptor] \u68C0\u6D4B\u5230\u6700\u7EC8\u7B7E\u540D\uFF0C\u7ED3\u675F\u6D41"),y()))}),this.addEventListener("readystatechange",()=>{this.readyState===4&&!b&&(console.log(`[Interceptor] \u8BF7\u6C42\u5B8C\u6210 (readyState=4), HTTP\u72B6\u6001: ${this.status}`),y())}),this.addEventListener("error",E=>{console.error("[Interceptor] XHR \u8BF7\u6C42\u51FA\u9519:",E),b||y()}),this.addEventListener("abort",()=>{console.warn("[Interceptor] XHR \u8BF7\u6C42\u88AB\u4E2D\u6B62"),b||y()})}return l.apply(this,f)})},deactivate:()=>{m&&(console.log("\u{1F504} [Interceptor] \u505C\u7528 XHR \u8865\u4E01..."),window.XMLHttpRequest.prototype.open=h,window.XMLHttpRequest.prototype.send=l,m=!1)}}}}};P();function Ye(t){return t.includes("The caller does not have permission")?{type:"error",content:"The caller does not have permission"}:t.includes("You exceeded your current quota")?{type:"error",content:"You exceeded your current quota, please check your plan and billing details. For more information on this error, head to: https://ai.google.dev/gemini-api/docs/rate-limits."}:null}function Qe(t){if(!Array.isArray(t))return null;let e=t[0];for(;Array.isArray(e)&&Array.isArray(e[0]);)e=e[0];return Array.isArray(e)&&e.length>=2&&e[0]===null&&typeof e[1]=="string"?e:null}function Ze(t){if(t.length===4&&t[0]===null&&t[1]===null&&t[2]===null)return{type:"done",content:"Stream finished"};if(t.length===3){let e=Qe(t);if(e){let o=e[1];return{type:e.length===2?"text":"thinking",content:o}}}return null}function Q(t){let e=Ye(t);if(e)return{parsedItems:[e],remainingBuffer:""};let o=[],a=/(\d+\]\]),(\[\[\[\[\[\[)/g,s=/(\d+\]\]),(\[null,null,null,)/g,n="__ELEMENT_SEPARATOR__",u=t.replace(a,`$1,${n}$2`);u=u.replace(s,`$1,${n}$2`);let h=u.split(n);if(h.length===1)return{parsedItems:[],remainingBuffer:t};let l=h.pop()||"",i=h;for(let d of i){let m=d.trim();m.endsWith(",")&&(m=m.slice(0,-1)),m.startsWith("[[[[[[[[")&&(m=m.substring(2));try{let f=JSON.parse(m),w=Ze(f);w&&o.push(w)}catch(f){v(`\u89E3\u6790\u5143\u7D20\u5931\u8D25\uFF0C\u8DF3\u8FC7\u8BE5\u5757\u3002\u9519\u8BEF: ${f.message}, \u5143\u7D20\u5185\u5BB9: "${m}"`)}}return{parsedItems:o,remainingBuffer:l}}function Z(t,e,o="gemini-pro"){return{id:`chatcmpl-${Date.now()}`,object:"chat.completion.chunk",created:Math.floor(Date.now()/1e3),model:o,choices:[{index:0,delta:{content:t||"",type:e||"text"},logprobs:null,finish_reason:null}]}}function ye(t,e="gemini-pro"){return{object:"error",message:t,type:"invalid_request_error",model:e}}function Se(t,e="gemini-pro"){return{id:`chatcmpl-${Date.now()}`,object:"chat.completion",created:Math.floor(Date.now()/1e3),model:e,choices:[{index:0,message:{role:"assistant",content:t},finish_reason:"stop"}],usage:{prompt_tokens:0,completion_tokens:0,total_tokens:0}}}P();var j=3,be=1e3;function et(t){let e=t.message.toLowerCase();return["timeout","navigation failed","page crashed","target closed","element not found","is not visible","\u65E0\u6CD5\u627E\u5230","not find","cannot find"].some(a=>e.includes(a))}function tt(t){let e=t.message.toLowerCase();return["permission","unauthorized","quota","cookie"].some(a=>e.includes(a))}async function Ee(t,e,o){let a=null,s=null;try{a=await U();for(let n=1;n<=j;n++)try{r(`\u{1F310} [\u5C1D\u8BD5 ${n}/${j}] \u5F00\u59CB\u5904\u7406\u8BF7\u6C42...`),await B(a,c.aiStudio.url,{timeout:c.aiStudio.pageTimeout}),c.enableHumanSimulation&&(r("\u542F\u7528\u4E86\u4EBA\u7C7B\u884C\u4E3A\u6A21\u62DF\uFF0C\u7B49\u5F85\u51E0\u767E\u6BEB\u79D2\u540E\u8FDB\u884C\u968F\u673A\u70B9\u51FB..."),await a.waitForTimeout(Math.floor(Math.random()*300)+200),await O(a));let u=await o(a,t,e);return await M(a),u}catch(u){if(s=u,v(`\u274C [\u5C1D\u8BD5 ${n}/${j}] \u5931\u8D25: ${u.message}`),(tt(u)||et(u))&&n<j)r(`\u68C0\u6D4B\u5230\u53EF\u91CD\u8BD5\u7684\u9519\u8BEF\uFF08\u6743\u9650\u6216\u9875\u9762\u72B6\u6001\uFF09\uFF0C\u5C06\u5728 ${be}ms \u540E\u91CD\u8BD5...`),await new Promise(h=>setTimeout(h,be));else throw p("\u9519\u8BEF\u4E0D\u53EF\u91CD\u8BD5\u6216\u5DF2\u8FBE\u5230\u6700\u5927\u91CD\u8BD5\u6B21\u6570\uFF0C\u5C06\u629B\u51FA\u5F02\u5E38\u3002"),u}}catch(n){throw p("\u5904\u7406 AI Studio \u8BF7\u6C42\u6700\u7EC8\u5931\u8D25:",n),a&&await M(a),s||n}}async function Ie(t,e,o={}){let a=o.model||c.api.defaultModel;try{await Ee(t,o,async(s,n,u)=>new Promise(async(h,l)=>{let i=!1,d=null,m="",f=g=>{i||(i=!0,d&&d.deactivate().catch(p),g?l(g):h())},w=g=>{if(i)return;m+=g;let{parsedItems:S,remainingBuffer:b}=Q(m);if(m=b,S.length>0)for(let y of S){if(y.type==="error")return f(new Error(y.content));if(y.type==="done"){_();return}y.content?.trim()&&e.enqueue(`data: ${JSON.stringify(Z(y.content,y.type,a))}
|
16 |
|
17 |
+
`)}},_=()=>{i||(r("\u6D41\u5DF2\u7ED3\u675F\uFF0C\u53D1\u9001 [DONE] \u4FE1\u53F7\u3002"),e.enqueue(`data: [DONE]
|
18 |
|
19 |
+
`),e.close(),f())};try{d=new q(s,w,_),await d.activate(),await new N(s,{enableHumanSimulation:c.enableHumanSimulation}).processMessage(n,u),setTimeout(()=>{i||f(new Error("AI Studio \u54CD\u5E94\u8D85\u65F6\u3002"))},c.aiStudio.responseTimeout)}catch(g){f(g)}}))}catch(s){if(e.desiredSize!==null)try{e.enqueue(`data: ${JSON.stringify(Z(s.message,"text",a))}
|
20 |
|
21 |
`),e.enqueue(`data: [DONE]
|
22 |
|
23 |
+
`),e.close()}catch(n){p("\u5173\u95ED\u6D41\u63A7\u5236\u5668\u65F6\u51FA\u9519:",n)}}}async function Pe(t,e={}){let o=e.model||c.api.defaultModel;try{return await Ee(t,e,async(a,s,n)=>new Promise(async(u,h)=>{let l="",i=async d=>{if(d.url().includes("GenerateContent"))try{let m=await d.text(),f=Q(m);if(f?.permissionError)return h(new Error(f.content));Array.isArray(f)&&(l+=f.filter(w=>w.type==="text").map(w=>w.content).join("")),a.removeListener("response",i),u(Se(l,o))}catch(m){h(m)}};a.on("response",i);try{await new N(a,{enableHumanSimulation:c.enableHumanSimulation}).processMessage(s,n),setTimeout(()=>{a.removeListener("response",i),h(new Error("AI Studio \u54CD\u5E94\u8D85\u65F6\u3002"))},c.aiStudio.responseTimeout)}catch(d){a.removeListener("response",i),h(d)}}))}catch(a){return ye(a.message,o)}}async function _e(t){try{we(t);let e=await ot(t),{prompt:o,systemPrompt:a,stream:s,model:n,temperature:u}=ge(e);return s?(he(t),new ReadableStream({start(l){Ie(o,l,{model:n,temperature:u,systemPrompt:a})}})):await Pe(o,{model:n,temperature:u,systemPrompt:a})}catch(e){throw console.error("\u5904\u7406\u804A\u5929\u8BF7\u6C42\u65F6\u51FA\u9519:",e),e.statusCode?e:rt({statusCode:500,statusMessage:e.message||"An internal server error occurred."})}}import{createError as z}from"h3";async function xe(t){try{let e=Object.values(c.models).map(o=>({id:o.id,object:o.object,created:o.created,owned_by:o.owned_by,permission:o.permission,root:o.root,parent:o.parent}));return e.sort((o,a)=>a.created-o.created),{object:"list",data:e}}catch(e){throw console.error("\u83B7\u53D6\u6A21\u578B\u5217\u8868\u65F6\u51FA\u9519:",e),z({statusCode:500,statusMessage:"Failed to retrieve models list."})}}async function ve(t){try{let e=t.context.params?.model;if(!e)throw z({statusCode:400,statusMessage:"Model ID is required."});let o=c.models[e];if(!o)throw z({statusCode:404,statusMessage:`Model '${e}' not found.`});return{id:o.id,object:o.object,created:o.created,owned_by:o.owned_by,permission:o.permission,root:o.root,parent:o.parent}}catch(e){throw console.error(`\u83B7\u53D6\u6A21\u578B '${t.context.params?.model}' \u4FE1\u606F\u65F6\u51FA\u9519:`,e),e.statusCode?e:z({statusCode:500,statusMessage:"Failed to retrieve model information."})}}D();P();var C=new at,Ae=process.cwd();le();C.use("*",de);C.get("/health",fe);C.get("/v1/models",xe);C.get("/v1/models/:model",ve);C.post("/v1/chat/completions",_e);C.get("/screenshots/**",t=>{let e=t.path.substring(12),o=Te(Ae,"screenshots",e);return $e(t,{getContents:()=>Re(o),getMeta:async()=>{let a=await Ce(o).catch(()=>{});if(a?.isFile())return{size:a.size,mtime:a.mtimeMs}}})});C.get("/**",t=>{let e=t.path==="/"?"index.html":t.path,o=Te(Ae,"public",e);return $e(t,{getContents:()=>Re(o),getMeta:async()=>{let a=await Ce(o).catch(()=>{});if(a?.isFile())return{size:a.size,mtime:a.mtimeMs}}})});r("\u{1F527} \u521D\u59CB\u5316\u9875\u9762\u6C60...");ie(5);process.env.NODE_ENV!=="production"&&(r("\u{1F4CA} \u542F\u52A8\u9875\u9762\u6C60\u76D1\u63A7..."),me(1e4));var L=c.server.port,H=c.server.host;nt(C,{port:L,host:H});r(`\u{1F680} \u670D\u52A1\u5668\u8FD0\u884C\u5728 http://${H}:${L}`);r(`\u{1F3E0} \u7BA1\u7406\u9762\u677F: http://${H}:${L}/`);r(`\u{1F4CB} \u5065\u5EB7\u68C0\u67E5: http://${H}:${L}/health`);r(`\u{1F4AC} \u804A\u5929\u7AEF\u70B9: http://${H}:${L}/v1/chat/completions`);r(`\u{1F3AF} AI Studio URL: ${c.aiStudio.url}`);r(`\u{1F30D} \u73AF\u5883: ${process.env.NODE_ENV||"development"}`);async function st(){let t;try{r("\u{1F4F8} \u5F00\u59CB\u83B7\u53D6AI Studio\u9875\u9762\u622A\u56FE..."),t=await U(),r(`\u667A\u80FD\u5BFC\u822A\u5230: ${c.aiStudio.url}`),await B(t,c.aiStudio.url,{timeout:c.aiStudio.pageTimeout}),await G(t),await t.waitForTimeout(2e3);let e=await V(t,"./screenshots","aistudio-startup",!1);r(`\u2705 AI Studio\u622A\u56FE\u5DF2\u4FDD\u5B58: ${e}`)}catch(e){p("\u274C \u622A\u56FEAI Studio\u9875\u9762\u65F6\u51FA\u9519:",e.message)}finally{t&&(await M(t),r("\u{1F504} \u9875\u9762\u5DF2\u91CA\u653E\u56DE\u6C60\u4E2D"))}}setTimeout(()=>{r(`
|
24 |
\u{1F4CA} \u521D\u59CB\u9875\u9762\u6C60\u72B6\u6001:`),pe()},1e3);setTimeout(()=>{st()},2e3);
|
public/health.html
ADDED
@@ -0,0 +1,331 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="zh-CN">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>AI Studio 2 API - 管理面板</title>
|
7 |
+
<style>
|
8 |
+
* {
|
9 |
+
margin: 0;
|
10 |
+
padding: 0;
|
11 |
+
box-sizing: border-box;
|
12 |
+
}
|
13 |
+
|
14 |
+
body {
|
15 |
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
16 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
17 |
+
min-height: 100vh;
|
18 |
+
color: #333;
|
19 |
+
}
|
20 |
+
|
21 |
+
.container {
|
22 |
+
max-width: 1200px;
|
23 |
+
margin: 0 auto;
|
24 |
+
padding: 20px;
|
25 |
+
}
|
26 |
+
|
27 |
+
.header {
|
28 |
+
text-align: center;
|
29 |
+
margin-bottom: 40px;
|
30 |
+
color: white;
|
31 |
+
}
|
32 |
+
|
33 |
+
.header h1 {
|
34 |
+
font-size: 2.5rem;
|
35 |
+
margin-bottom: 10px;
|
36 |
+
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
|
37 |
+
}
|
38 |
+
|
39 |
+
.header p {
|
40 |
+
font-size: 1.2rem;
|
41 |
+
opacity: 0.9;
|
42 |
+
}
|
43 |
+
|
44 |
+
.main-content {
|
45 |
+
display: grid;
|
46 |
+
grid-template-columns: 1fr 1fr;
|
47 |
+
gap: 30px;
|
48 |
+
margin-bottom: 40px;
|
49 |
+
}
|
50 |
+
|
51 |
+
.card {
|
52 |
+
background: white;
|
53 |
+
border-radius: 15px;
|
54 |
+
padding: 25px;
|
55 |
+
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
|
56 |
+
transition: transform 0.3s ease;
|
57 |
+
}
|
58 |
+
|
59 |
+
.card:hover {
|
60 |
+
transform: translateY(-5px);
|
61 |
+
}
|
62 |
+
|
63 |
+
.card h2 {
|
64 |
+
color: #4a5568;
|
65 |
+
margin-bottom: 20px;
|
66 |
+
font-size: 1.5rem;
|
67 |
+
border-bottom: 2px solid #e2e8f0;
|
68 |
+
padding-bottom: 10px;
|
69 |
+
}
|
70 |
+
|
71 |
+
.screenshot-container {
|
72 |
+
text-align: center;
|
73 |
+
}
|
74 |
+
|
75 |
+
.screenshot {
|
76 |
+
max-width: 100%;
|
77 |
+
height: auto;
|
78 |
+
border-radius: 10px;
|
79 |
+
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
|
80 |
+
margin-bottom: 15px;
|
81 |
+
}
|
82 |
+
|
83 |
+
.config-item {
|
84 |
+
display: flex;
|
85 |
+
justify-content: space-between;
|
86 |
+
align-items: center;
|
87 |
+
padding: 12px 0;
|
88 |
+
border-bottom: 1px solid #e2e8f0;
|
89 |
+
}
|
90 |
+
|
91 |
+
.config-item:last-child {
|
92 |
+
border-bottom: none;
|
93 |
+
}
|
94 |
+
|
95 |
+
.config-label {
|
96 |
+
font-weight: 600;
|
97 |
+
color: #4a5568;
|
98 |
+
}
|
99 |
+
|
100 |
+
.config-value {
|
101 |
+
color: #2d3748;
|
102 |
+
font-family: 'Courier New', monospace;
|
103 |
+
background: #f7fafc;
|
104 |
+
padding: 4px 8px;
|
105 |
+
border-radius: 4px;
|
106 |
+
font-size: 0.9rem;
|
107 |
+
}
|
108 |
+
|
109 |
+
.status-indicator {
|
110 |
+
display: inline-block;
|
111 |
+
width: 10px;
|
112 |
+
height: 10px;
|
113 |
+
border-radius: 50%;
|
114 |
+
margin-right: 8px;
|
115 |
+
}
|
116 |
+
|
117 |
+
.status-online {
|
118 |
+
background-color: #48bb78;
|
119 |
+
animation: pulse 2s infinite;
|
120 |
+
}
|
121 |
+
|
122 |
+
.status-offline {
|
123 |
+
background-color: #f56565;
|
124 |
+
}
|
125 |
+
|
126 |
+
@keyframes pulse {
|
127 |
+
0% { opacity: 1; }
|
128 |
+
50% { opacity: 0.5; }
|
129 |
+
100% { opacity: 1; }
|
130 |
+
}
|
131 |
+
|
132 |
+
.api-endpoints {
|
133 |
+
grid-column: 1 / -1;
|
134 |
+
}
|
135 |
+
|
136 |
+
.endpoint-list {
|
137 |
+
display: grid;
|
138 |
+
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
139 |
+
gap: 15px;
|
140 |
+
}
|
141 |
+
|
142 |
+
.endpoint {
|
143 |
+
background: #f8f9fa;
|
144 |
+
padding: 15px;
|
145 |
+
border-radius: 8px;
|
146 |
+
border-left: 4px solid #667eea;
|
147 |
+
}
|
148 |
+
|
149 |
+
.endpoint-method {
|
150 |
+
font-weight: bold;
|
151 |
+
color: #667eea;
|
152 |
+
margin-right: 10px;
|
153 |
+
}
|
154 |
+
|
155 |
+
.endpoint-url {
|
156 |
+
font-family: 'Courier New', monospace;
|
157 |
+
color: #2d3748;
|
158 |
+
}
|
159 |
+
|
160 |
+
.endpoint-desc {
|
161 |
+
font-size: 0.9rem;
|
162 |
+
color: #718096;
|
163 |
+
margin-top: 5px;
|
164 |
+
}
|
165 |
+
|
166 |
+
.footer {
|
167 |
+
text-align: center;
|
168 |
+
color: white;
|
169 |
+
opacity: 0.8;
|
170 |
+
margin-top: 40px;
|
171 |
+
}
|
172 |
+
|
173 |
+
@media (max-width: 768px) {
|
174 |
+
.main-content {
|
175 |
+
grid-template-columns: 1fr;
|
176 |
+
}
|
177 |
+
|
178 |
+
.header h1 {
|
179 |
+
font-size: 2rem;
|
180 |
+
}
|
181 |
+
|
182 |
+
.container {
|
183 |
+
padding: 15px;
|
184 |
+
}
|
185 |
+
}
|
186 |
+
</style>
|
187 |
+
</head>
|
188 |
+
<body>
|
189 |
+
<div class="container">
|
190 |
+
<div class="header">
|
191 |
+
<h1>🤖 AI Studio 2 API</h1>
|
192 |
+
<p>Google AI Studio 到 OpenAI API 格式的转换服务</p>
|
193 |
+
</div>
|
194 |
+
|
195 |
+
<div class="main-content">
|
196 |
+
<div class="card screenshot-container">
|
197 |
+
<h2>📸 AI Studio 状态截图</h2>
|
198 |
+
<img src="/screenshots/aistudio-startup.png" alt="AI Studio 启动截图" class="screenshot" id="screenshot">
|
199 |
+
<p style="color: #718096; font-size: 0.9rem;">最后更新: <span id="lastUpdate">加载中...</span></p>
|
200 |
+
</div>
|
201 |
+
|
202 |
+
<div class="card">
|
203 |
+
<h2>⚙️ 基础配置</h2>
|
204 |
+
<div class="config-item">
|
205 |
+
<span class="config-label">服务状态</span>
|
206 |
+
<span class="config-value">
|
207 |
+
<span class="status-indicator status-online"></span>
|
208 |
+
运行中
|
209 |
+
</span>
|
210 |
+
</div>
|
211 |
+
<div class="config-item">
|
212 |
+
<span class="config-label">服务端口</span>
|
213 |
+
<span class="config-value" id="serverPort">加载中...</span>
|
214 |
+
</div>
|
215 |
+
<div class="config-item">
|
216 |
+
<span class="config-label">AI Studio URL</span>
|
217 |
+
<span class="config-value" id="aiStudioUrl">加载中...</span>
|
218 |
+
</div>
|
219 |
+
<div class="config-item">
|
220 |
+
<span class="config-label">默认模型</span>
|
221 |
+
<span class="config-value" id="defaultModel">加载中...</span>
|
222 |
+
</div>
|
223 |
+
<div class="config-item">
|
224 |
+
<span class="config-label">浏览器模式</span>
|
225 |
+
<span class="config-value" id="browserMode">加载中...</span>
|
226 |
+
</div>
|
227 |
+
<div class="config-item">
|
228 |
+
<span class="config-label">页面超时</span>
|
229 |
+
<span class="config-value" id="pageTimeout">加载中...</span>
|
230 |
+
</div>
|
231 |
+
</div>
|
232 |
+
|
233 |
+
<div class="card api-endpoints">
|
234 |
+
<h2>🔗 API 端点</h2>
|
235 |
+
<div class="endpoint-list">
|
236 |
+
<div class="endpoint">
|
237 |
+
<div>
|
238 |
+
<span class="endpoint-method">GET</span>
|
239 |
+
<span class="endpoint-url">/health</span>
|
240 |
+
</div>
|
241 |
+
<div class="endpoint-desc">健康检查端点</div>
|
242 |
+
</div>
|
243 |
+
<div class="endpoint">
|
244 |
+
<div>
|
245 |
+
<span class="endpoint-method">GET</span>
|
246 |
+
<span class="endpoint-url">/v1/models</span>
|
247 |
+
</div>
|
248 |
+
<div class="endpoint-desc">获取可用模型列表</div>
|
249 |
+
</div>
|
250 |
+
<div class="endpoint">
|
251 |
+
<div>
|
252 |
+
<span class="endpoint-method">GET</span>
|
253 |
+
<span class="endpoint-url">/v1/models/{model}</span>
|
254 |
+
</div>
|
255 |
+
<div class="endpoint-desc">获取特定模型信息</div>
|
256 |
+
</div>
|
257 |
+
<div class="endpoint">
|
258 |
+
<div>
|
259 |
+
<span class="endpoint-method">POST</span>
|
260 |
+
<span class="endpoint-url">/v1/chat/completions</span>
|
261 |
+
</div>
|
262 |
+
<div class="endpoint-desc">聊天完成 API (兼容 OpenAI 格式)</div>
|
263 |
+
</div>
|
264 |
+
</div>
|
265 |
+
</div>
|
266 |
+
</div>
|
267 |
+
|
268 |
+
<div class="footer">
|
269 |
+
<p>© 2024 AI Studio 2 API - 基于 H3 v2 构建</p>
|
270 |
+
</div>
|
271 |
+
</div>
|
272 |
+
|
273 |
+
<script>
|
274 |
+
// 获取配置信息
|
275 |
+
async function loadConfig() {
|
276 |
+
try {
|
277 |
+
// 从健康检查端点获取基本信息
|
278 |
+
const healthResponse = await fetch('/health');
|
279 |
+
const healthData = await healthResponse.json();
|
280 |
+
|
281 |
+
// 更新页面信息
|
282 |
+
document.getElementById('serverPort').textContent = window.location.port || '7860';
|
283 |
+
document.getElementById('aiStudioUrl').textContent = 'https://aistudio.google.com/prompts/new_chat';
|
284 |
+
document.getElementById('defaultModel').textContent = 'gemini-pro';
|
285 |
+
document.getElementById('browserMode').textContent = 'Headless';
|
286 |
+
document.getElementById('pageTimeout').textContent = '30000ms';
|
287 |
+
|
288 |
+
// 更新截图时间戳
|
289 |
+
updateScreenshotTimestamp();
|
290 |
+
|
291 |
+
} catch (err) {
|
292 |
+
console.error('加载配置失败:', err);
|
293 |
+
// 设置默认值
|
294 |
+
document.getElementById('serverPort').textContent = window.location.port || '7860';
|
295 |
+
document.getElementById('aiStudioUrl').textContent = 'https://aistudio.google.com/prompts/new_chat';
|
296 |
+
document.getElementById('defaultModel').textContent = 'gemini-pro';
|
297 |
+
document.getElementById('browserMode').textContent = 'Headless';
|
298 |
+
document.getElementById('pageTimeout').textContent = '30000ms';
|
299 |
+
}
|
300 |
+
}
|
301 |
+
|
302 |
+
// 更新截图时间戳
|
303 |
+
function updateScreenshotTimestamp() {
|
304 |
+
const now = new Date();
|
305 |
+
const timestamp = now.toLocaleString('zh-CN', {
|
306 |
+
year: 'numeric',
|
307 |
+
month: '2-digit',
|
308 |
+
day: '2-digit',
|
309 |
+
hour: '2-digit',
|
310 |
+
minute: '2-digit',
|
311 |
+
second: '2-digit'
|
312 |
+
});
|
313 |
+
document.getElementById('lastUpdate').textContent = timestamp;
|
314 |
+
}
|
315 |
+
|
316 |
+
// 处理截图加载错误
|
317 |
+
document.getElementById('screenshot').onerror = function() {
|
318 |
+
this.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjMwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZjBmMGYwIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIxOCIgZmlsbD0iIzk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPuaIquWbvuS4jeWPr+eUqDwvdGV4dD48L3N2Zz4=';
|
319 |
+
this.alt = '截图不可用';
|
320 |
+
};
|
321 |
+
|
322 |
+
// 页面加载完成后执行
|
323 |
+
document.addEventListener('DOMContentLoaded', function() {
|
324 |
+
loadConfig();
|
325 |
+
|
326 |
+
// 每30秒刷新一次截图时间戳
|
327 |
+
setInterval(updateScreenshotTimestamp, 30000);
|
328 |
+
});
|
329 |
+
</script>
|
330 |
+
</body>
|
331 |
+
</html>
|
public/index.html
CHANGED
@@ -1,331 +1 @@
|
|
1 |
-
|
2 |
-
<html lang="zh-CN">
|
3 |
-
<head>
|
4 |
-
<meta charset="UTF-8">
|
5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
-
<title>AI Studio 2 API - 管理面板</title>
|
7 |
-
<style>
|
8 |
-
* {
|
9 |
-
margin: 0;
|
10 |
-
padding: 0;
|
11 |
-
box-sizing: border-box;
|
12 |
-
}
|
13 |
-
|
14 |
-
body {
|
15 |
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
16 |
-
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
17 |
-
min-height: 100vh;
|
18 |
-
color: #333;
|
19 |
-
}
|
20 |
-
|
21 |
-
.container {
|
22 |
-
max-width: 1200px;
|
23 |
-
margin: 0 auto;
|
24 |
-
padding: 20px;
|
25 |
-
}
|
26 |
-
|
27 |
-
.header {
|
28 |
-
text-align: center;
|
29 |
-
margin-bottom: 40px;
|
30 |
-
color: white;
|
31 |
-
}
|
32 |
-
|
33 |
-
.header h1 {
|
34 |
-
font-size: 2.5rem;
|
35 |
-
margin-bottom: 10px;
|
36 |
-
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
|
37 |
-
}
|
38 |
-
|
39 |
-
.header p {
|
40 |
-
font-size: 1.2rem;
|
41 |
-
opacity: 0.9;
|
42 |
-
}
|
43 |
-
|
44 |
-
.main-content {
|
45 |
-
display: grid;
|
46 |
-
grid-template-columns: 1fr 1fr;
|
47 |
-
gap: 30px;
|
48 |
-
margin-bottom: 40px;
|
49 |
-
}
|
50 |
-
|
51 |
-
.card {
|
52 |
-
background: white;
|
53 |
-
border-radius: 15px;
|
54 |
-
padding: 25px;
|
55 |
-
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
|
56 |
-
transition: transform 0.3s ease;
|
57 |
-
}
|
58 |
-
|
59 |
-
.card:hover {
|
60 |
-
transform: translateY(-5px);
|
61 |
-
}
|
62 |
-
|
63 |
-
.card h2 {
|
64 |
-
color: #4a5568;
|
65 |
-
margin-bottom: 20px;
|
66 |
-
font-size: 1.5rem;
|
67 |
-
border-bottom: 2px solid #e2e8f0;
|
68 |
-
padding-bottom: 10px;
|
69 |
-
}
|
70 |
-
|
71 |
-
.screenshot-container {
|
72 |
-
text-align: center;
|
73 |
-
}
|
74 |
-
|
75 |
-
.screenshot {
|
76 |
-
max-width: 100%;
|
77 |
-
height: auto;
|
78 |
-
border-radius: 10px;
|
79 |
-
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
|
80 |
-
margin-bottom: 15px;
|
81 |
-
}
|
82 |
-
|
83 |
-
.config-item {
|
84 |
-
display: flex;
|
85 |
-
justify-content: space-between;
|
86 |
-
align-items: center;
|
87 |
-
padding: 12px 0;
|
88 |
-
border-bottom: 1px solid #e2e8f0;
|
89 |
-
}
|
90 |
-
|
91 |
-
.config-item:last-child {
|
92 |
-
border-bottom: none;
|
93 |
-
}
|
94 |
-
|
95 |
-
.config-label {
|
96 |
-
font-weight: 600;
|
97 |
-
color: #4a5568;
|
98 |
-
}
|
99 |
-
|
100 |
-
.config-value {
|
101 |
-
color: #2d3748;
|
102 |
-
font-family: 'Courier New', monospace;
|
103 |
-
background: #f7fafc;
|
104 |
-
padding: 4px 8px;
|
105 |
-
border-radius: 4px;
|
106 |
-
font-size: 0.9rem;
|
107 |
-
}
|
108 |
-
|
109 |
-
.status-indicator {
|
110 |
-
display: inline-block;
|
111 |
-
width: 10px;
|
112 |
-
height: 10px;
|
113 |
-
border-radius: 50%;
|
114 |
-
margin-right: 8px;
|
115 |
-
}
|
116 |
-
|
117 |
-
.status-online {
|
118 |
-
background-color: #48bb78;
|
119 |
-
animation: pulse 2s infinite;
|
120 |
-
}
|
121 |
-
|
122 |
-
.status-offline {
|
123 |
-
background-color: #f56565;
|
124 |
-
}
|
125 |
-
|
126 |
-
@keyframes pulse {
|
127 |
-
0% { opacity: 1; }
|
128 |
-
50% { opacity: 0.5; }
|
129 |
-
100% { opacity: 1; }
|
130 |
-
}
|
131 |
-
|
132 |
-
.api-endpoints {
|
133 |
-
grid-column: 1 / -1;
|
134 |
-
}
|
135 |
-
|
136 |
-
.endpoint-list {
|
137 |
-
display: grid;
|
138 |
-
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
139 |
-
gap: 15px;
|
140 |
-
}
|
141 |
-
|
142 |
-
.endpoint {
|
143 |
-
background: #f8f9fa;
|
144 |
-
padding: 15px;
|
145 |
-
border-radius: 8px;
|
146 |
-
border-left: 4px solid #667eea;
|
147 |
-
}
|
148 |
-
|
149 |
-
.endpoint-method {
|
150 |
-
font-weight: bold;
|
151 |
-
color: #667eea;
|
152 |
-
margin-right: 10px;
|
153 |
-
}
|
154 |
-
|
155 |
-
.endpoint-url {
|
156 |
-
font-family: 'Courier New', monospace;
|
157 |
-
color: #2d3748;
|
158 |
-
}
|
159 |
-
|
160 |
-
.endpoint-desc {
|
161 |
-
font-size: 0.9rem;
|
162 |
-
color: #718096;
|
163 |
-
margin-top: 5px;
|
164 |
-
}
|
165 |
-
|
166 |
-
.footer {
|
167 |
-
text-align: center;
|
168 |
-
color: white;
|
169 |
-
opacity: 0.8;
|
170 |
-
margin-top: 40px;
|
171 |
-
}
|
172 |
-
|
173 |
-
@media (max-width: 768px) {
|
174 |
-
.main-content {
|
175 |
-
grid-template-columns: 1fr;
|
176 |
-
}
|
177 |
-
|
178 |
-
.header h1 {
|
179 |
-
font-size: 2rem;
|
180 |
-
}
|
181 |
-
|
182 |
-
.container {
|
183 |
-
padding: 15px;
|
184 |
-
}
|
185 |
-
}
|
186 |
-
</style>
|
187 |
-
</head>
|
188 |
-
<body>
|
189 |
-
<div class="container">
|
190 |
-
<div class="header">
|
191 |
-
<h1>🤖 AI Studio 2 API</h1>
|
192 |
-
<p>Google AI Studio 到 OpenAI API 格式的转换服务</p>
|
193 |
-
</div>
|
194 |
-
|
195 |
-
<div class="main-content">
|
196 |
-
<div class="card screenshot-container">
|
197 |
-
<h2>📸 AI Studio 状态截图</h2>
|
198 |
-
<img src="/screenshots/aistudio-startup.png" alt="AI Studio 启动截图" class="screenshot" id="screenshot">
|
199 |
-
<p style="color: #718096; font-size: 0.9rem;">最后更新: <span id="lastUpdate">加载中...</span></p>
|
200 |
-
</div>
|
201 |
-
|
202 |
-
<div class="card">
|
203 |
-
<h2>⚙️ 基础配置</h2>
|
204 |
-
<div class="config-item">
|
205 |
-
<span class="config-label">服务状态</span>
|
206 |
-
<span class="config-value">
|
207 |
-
<span class="status-indicator status-online"></span>
|
208 |
-
运行中
|
209 |
-
</span>
|
210 |
-
</div>
|
211 |
-
<div class="config-item">
|
212 |
-
<span class="config-label">服务端口</span>
|
213 |
-
<span class="config-value" id="serverPort">加载中...</span>
|
214 |
-
</div>
|
215 |
-
<div class="config-item">
|
216 |
-
<span class="config-label">AI Studio URL</span>
|
217 |
-
<span class="config-value" id="aiStudioUrl">加载中...</span>
|
218 |
-
</div>
|
219 |
-
<div class="config-item">
|
220 |
-
<span class="config-label">默认模型</span>
|
221 |
-
<span class="config-value" id="defaultModel">加载中...</span>
|
222 |
-
</div>
|
223 |
-
<div class="config-item">
|
224 |
-
<span class="config-label">浏览器模式</span>
|
225 |
-
<span class="config-value" id="browserMode">加载中...</span>
|
226 |
-
</div>
|
227 |
-
<div class="config-item">
|
228 |
-
<span class="config-label">页面超时</span>
|
229 |
-
<span class="config-value" id="pageTimeout">加载中...</span>
|
230 |
-
</div>
|
231 |
-
</div>
|
232 |
-
|
233 |
-
<div class="card api-endpoints">
|
234 |
-
<h2>🔗 API 端点</h2>
|
235 |
-
<div class="endpoint-list">
|
236 |
-
<div class="endpoint">
|
237 |
-
<div>
|
238 |
-
<span class="endpoint-method">GET</span>
|
239 |
-
<span class="endpoint-url">/health</span>
|
240 |
-
</div>
|
241 |
-
<div class="endpoint-desc">健康检查端点</div>
|
242 |
-
</div>
|
243 |
-
<div class="endpoint">
|
244 |
-
<div>
|
245 |
-
<span class="endpoint-method">GET</span>
|
246 |
-
<span class="endpoint-url">/v1/models</span>
|
247 |
-
</div>
|
248 |
-
<div class="endpoint-desc">获取可用模型列表</div>
|
249 |
-
</div>
|
250 |
-
<div class="endpoint">
|
251 |
-
<div>
|
252 |
-
<span class="endpoint-method">GET</span>
|
253 |
-
<span class="endpoint-url">/v1/models/{model}</span>
|
254 |
-
</div>
|
255 |
-
<div class="endpoint-desc">获取特定模型信息</div>
|
256 |
-
</div>
|
257 |
-
<div class="endpoint">
|
258 |
-
<div>
|
259 |
-
<span class="endpoint-method">POST</span>
|
260 |
-
<span class="endpoint-url">/v1/chat/completions</span>
|
261 |
-
</div>
|
262 |
-
<div class="endpoint-desc">聊天完成 API (兼容 OpenAI 格式)</div>
|
263 |
-
</div>
|
264 |
-
</div>
|
265 |
-
</div>
|
266 |
-
</div>
|
267 |
-
|
268 |
-
<div class="footer">
|
269 |
-
<p>© 2024 AI Studio 2 API - 基于 H3 v2 构建</p>
|
270 |
-
</div>
|
271 |
-
</div>
|
272 |
-
|
273 |
-
<script>
|
274 |
-
// 获取配置信息
|
275 |
-
async function loadConfig() {
|
276 |
-
try {
|
277 |
-
// 从健康检查端点获取基本信息
|
278 |
-
const healthResponse = await fetch('/health');
|
279 |
-
const healthData = await healthResponse.json();
|
280 |
-
|
281 |
-
// 更新页面信息
|
282 |
-
document.getElementById('serverPort').textContent = window.location.port || '7860';
|
283 |
-
document.getElementById('aiStudioUrl').textContent = 'https://aistudio.google.com/prompts/new_chat';
|
284 |
-
document.getElementById('defaultModel').textContent = 'gemini-pro';
|
285 |
-
document.getElementById('browserMode').textContent = 'Headless';
|
286 |
-
document.getElementById('pageTimeout').textContent = '30000ms';
|
287 |
-
|
288 |
-
// 更新截图时间戳
|
289 |
-
updateScreenshotTimestamp();
|
290 |
-
|
291 |
-
} catch (err) {
|
292 |
-
console.error('加载配置失败:', err);
|
293 |
-
// 设置默认值
|
294 |
-
document.getElementById('serverPort').textContent = window.location.port || '7860';
|
295 |
-
document.getElementById('aiStudioUrl').textContent = 'https://aistudio.google.com/prompts/new_chat';
|
296 |
-
document.getElementById('defaultModel').textContent = 'gemini-pro';
|
297 |
-
document.getElementById('browserMode').textContent = 'Headless';
|
298 |
-
document.getElementById('pageTimeout').textContent = '30000ms';
|
299 |
-
}
|
300 |
-
}
|
301 |
-
|
302 |
-
// 更新截图时间戳
|
303 |
-
function updateScreenshotTimestamp() {
|
304 |
-
const now = new Date();
|
305 |
-
const timestamp = now.toLocaleString('zh-CN', {
|
306 |
-
year: 'numeric',
|
307 |
-
month: '2-digit',
|
308 |
-
day: '2-digit',
|
309 |
-
hour: '2-digit',
|
310 |
-
minute: '2-digit',
|
311 |
-
second: '2-digit'
|
312 |
-
});
|
313 |
-
document.getElementById('lastUpdate').textContent = timestamp;
|
314 |
-
}
|
315 |
-
|
316 |
-
// 处理截图加载错误
|
317 |
-
document.getElementById('screenshot').onerror = function() {
|
318 |
-
this.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjMwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZjBmMGYwIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIxOCIgZmlsbD0iIzk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPuaIquWbvuS4jeWPr+eUqDwvdGV4dD48L3N2Zz4=';
|
319 |
-
this.alt = '截图不可用';
|
320 |
-
};
|
321 |
-
|
322 |
-
// 页面加载完成后执行
|
323 |
-
document.addEventListener('DOMContentLoaded', function() {
|
324 |
-
loadConfig();
|
325 |
-
|
326 |
-
// 每30秒刷新一次截图时间戳
|
327 |
-
setInterval(updateScreenshotTimestamp, 30000);
|
328 |
-
});
|
329 |
-
</script>
|
330 |
-
</body>
|
331 |
-
</html>
|
|
|
1 |
+
hello world!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|