@ai.weget.jp/bot 0.1.18 → 0.1.19
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"node:fs/promises";import{existsSync as e}from"node:fs";import{createRequire as r}from"node:module";import s from"node:os";import n from"node:path";import{spawn as i,spawnSync as o}from"node:child_process";const a="gpt-5.4",c=r(import.meta.url);let d=null,l=null,u=null,g=null,m=null,p=null;const w=async t=>{if(!t)return"";const e=[];for await(const r of t)e.push(Buffer.isBuffer(r)?r:Buffer.from(String(r)));return Buffer.concat(e).toString("utf8")},f=t=>String(t||"").replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g,""),y=t=>{let e="";return{push:r=>{if(!t)return;e+=f(Buffer.isBuffer(r)?r.toString("utf8"):String(r));const s=e.split(/\r?\n/);e=s.pop()||"";for(const e of s){const r=String(e||"").trim();r&&t(r)}},flush:()=>{if(!t)return;const r=String(e||"").trim();r&&t(r),e=""}}},h=t=>{const e=f(String(t||"")).trim();return e?/^[{}[\],:]+$/.test(e)||/^["']?[a-zA-Z0-9_-]+["']?\s*:\s*$/.test(e)||/^`{3,}|^#{1,6}\s*$/.test(e)||/^Assistant:?\s*$/i.test(e)||/^Warning: no last agent message/i.test(e)?"":/^ERROR:\s*unexpected status\s+\d+/i.test(e)?"Tool call failed":e:""},x=(t,e)=>{const r=f(String(t||"")).replace(/\s+/g," ").trim();return r?r.length>180?`${r.slice(0,177)}...`:r:e},S=t=>t&&"object"==typeof t?t:{},_=t=>String(t||"").trim(),v=t=>{const e=S(t);if(0===Object.keys(e).length)return"";const r=S(e.waiting),s=[`- source task: ${_(e.task_id)||"-"}`,`- status: ${_(e.status)||"-"}`,`- title: ${_(e.title)||"-"}`,`- user prompt: ${_(e.user_prompt)||"-"}`,`- summary: ${_(e.summary)||"-"}`,`- latest output: ${_(e.latest_output)||"-"}`,`- last event: ${_(e.last_event_type)||"-"}`];return Object.keys(r).length>0&&(s.push(`- waiting type: ${_(r.type)||"-"}`),s.push(`- waiting subtype: ${_(r.subtype)||"-"}`),s.push(`- waiting prompt: ${_(r.prompt)||"-"}`)),s.join("\n")},C=e=>{const r=(new Date).toISOString(),s=`exec-${Date.now()}`;let i="",o="",a=!1,c=Promise.resolve();const d=[],l=async()=>{if(a)return o;const r=n.join(e,"codex-sessions");await t.mkdir(r,{recursive:!0});const c=String(i||s||"").trim().replace(/[^a-zA-Z0-9._-]+/g,"_");return o=n.join(r,`${c}.log`),a=!0,d.length>0&&(await t.appendFile(o,d.join(""),"utf8"),d.length=0),o},u=(e,r={})=>{(e=>{c=c.then(async()=>{if(!a&&!i)return void d.push(e);const r=await l();await t.appendFile(r,e,"utf8")}).catch(()=>{})})(`${JSON.stringify({ts:(new Date).toISOString(),event:e,...r},null,0)}\n`)};return{get startedAt(){return r},get sessionId(){return i},setSessionId:t=>{const e=String(t||"").trim();e&&i!==e&&(i=e,u("session_identified",{sessionId:e}))},write:u,flush:async()=>(a||await l(),await c,o)}},$=()=>{if(l)return l;const t=[n.join(String(process.env.ProgramFiles||"C:\\Program Files"),"nodejs","npx.cmd"),n.join(String(process.env["ProgramFiles(x86)"]||"C:\\Program Files (x86)"),"nodejs","npx.cmd"),n.join(String(process.env.APPDATA||""),"npm","npx.cmd")].filter(Boolean);for(const r of t)if(e(r))return l=r,r;const r=o("where.exe",["npx.cmd"],{windowsHide:!0,encoding:"utf8"}),s=String(r.stdout||"").split(/\r?\n/).map(t=>t.trim()).find(Boolean);return s?(l=s,s):"npx.cmd"},k=()=>{if(u)return u;const t=[n.join(String(process.env.ProgramFiles||"C:\\Program Files"),"nodejs","node.exe"),n.join(String(process.env["ProgramFiles(x86)"]||"C:\\Program Files (x86)"),"nodejs","node.exe")];for(const r of t)if(e(r))return u=r,r;return u="node",u},P=()=>{if(g)return g;try{const t=c.resolve("@ai.weget.jp/weget-gateway-mcp/dist/index.js");return g=t,t}catch{}const t=[n.join(String(process.env.APPDATA||""),"npm","node_modules","@ai.weget.jp","weget-gateway-mcp","dist","index.js"),n.join(String(process.env.ProgramFiles||"C:\\Program Files"),"nodejs","node_modules","@ai.weget.jp","weget-gateway-mcp","dist","index.js"),n.join(String(process.env["ProgramFiles(x86)"]||"C:\\Program Files (x86)"),"nodejs","node_modules","@ai.weget.jp","weget-gateway-mcp","dist","index.js")].filter(Boolean);for(const r of t)if(e(r))return g=r,r;return g=n.join(String(process.env.APPDATA||""),"npm","node_modules","@ai.weget.jp","weget-gateway-mcp","dist","index.js"),g},O=t=>{const e=n.join(t,"weget-gateway-context.json");return"win32"===process.platform?{command:k(),args:[P(),"--context-file",e]}:{command:"npx",args:["-y","@ai.weget.jp/weget-gateway-mcp@latest","--context-file",e]}},j=t=>String(t||"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),E=(t,e)=>{const r=String(t||""),s=O(e);if("win32"===process.platform){const t=new RegExp(`command:\\s+${j(s.command)}`,"i"),e=new RegExp(j(String(s.args[0]||"")),"i"),n=new RegExp(j(String(s.args[2]||"")),"i");return t.test(r)&&e.test(r)&&n.test(r)}return new RegExp(`command:\\s+${j(s.command)}`,"i").test(r)&&r.includes(String(s.args[0]||""))},b=async({args:t,stdinText:r,cwd:s,extraEnv:a,onStdoutLine:c,onStderrLine:l})=>new Promise((u,g)=>{const m=(()=>{if(d)return d;if("win32"===process.platform){const t=[String(process.env.ProgramFiles||"C:\\Program Files"),String(process.env["ProgramFiles(x86)"]||"C:\\Program Files (x86)")];for(const r of t){const t=n.join(r,"nodejs","node.exe"),s=n.join(r,"nodejs","node_modules","@openai","codex","bin","codex.js");if(e(t)&&e(s))return d={command:t,baseArgs:[s]},d}const r=["codex.cmd","codex"];for(const t of r){const e=o("where.exe",[t],{windowsHide:!0,encoding:"utf8"}),r=String(e.stdout||"").split(/\r?\n/).map(t=>t.trim()).find(Boolean);if(r)return d={command:r,baseArgs:[]},d}}return d={command:"codex",baseArgs:[]},d})(),p={...process.env,...a||{},NO_COLOR:"1",FORCE_COLOR:"0",CLICOLOR:"0"},f=i(m.command,[...m.baseArgs,...t],{cwd:s,stdio:["pipe","pipe","pipe"],windowsHide:!0,env:p});let h=!1;const x=t=>{h||(h=!0,t())},S=w(f.stdout),_=w(f.stderr),v=y(c),C=y(l);f.stdout?.on("data",t=>v.push(t)),f.stderr?.on("data",t=>C.push(t)),f.on("error",t=>{x(()=>g(t))}),f.on("close",async t=>{v.flush(),C.flush();const[e,r]=await Promise.all([S,_]);x(()=>u({stdout:e,stderr:r,exitCode:Number.isFinite(t)?Number(t):1}))}),"string"==typeof r&&f.stdin.write(r),f.stdin.end()}),A=async({command:t,args:e,cwd:r})=>new Promise((s,n)=>{const o=i(t,e,{cwd:r,stdio:["pipe","pipe","pipe"],windowsHide:!0,env:{...process.env,NO_COLOR:"1",FORCE_COLOR:"0",CLICOLOR:"0"}});let a=!1;const c=t=>{a||(a=!0,t())},d=w(o.stdout),l=w(o.stderr);o.on("error",t=>c(()=>n(t))),o.on("close",async t=>{const[e,r]=await Promise.all([d,l]);c(()=>s({stdout:e,stderr:r,exitCode:Number.isFinite(t)?Number(t):1}))})}),F=async t=>null!==m?m:(p||(p=(async(t,e)=>{const r=String(t||"").trim();if(!r)return!1;try{const t=await b({cwd:e,args:["features","list"]});return 0===t.exitCode&&f(`${t.stdout||""}\n${t.stderr||""}`).split(/\r?\n/).map(t=>t.trim()).some(t=>t.startsWith(`${r} `)||t===r)}catch{return!1}})("rmcp_client",t).then(t=>(m=t,t)).finally(()=>{p=null})),p),I=async({cwd:t,model:e,outputPath:r})=>{const s=["exec"];return await F(t)&&s.push("--enable","rmcp_client"),s.push("--dangerously-bypass-approvals-and-sandbox","-C",t,"--skip-git-repo-check","-m",e,"-o",r,"-"),s};export const createCodexService=({getModel:e,getWorkingDir:r,getLogDir:o,emitLog:c,getGatewayContext:d})=>{const l=()=>n.join(o(),"codex-session-bindings.json"),u=async()=>{try{const e=await t.readFile(l(),"utf8"),r=JSON.parse(e);return Object.fromEntries(Object.entries(r||{}).map(([t,e])=>[String(t||"").trim(),String(e||"").trim()]).filter(([t,e])=>t&&e))}catch{return{}}},g=async e=>{await t.mkdir(o(),{recursive:!0}),await t.writeFile(l(),`${JSON.stringify(e,null,2)}\n`,"utf8")},m=()=>{const t=d?.()||{},e={WEGET_ACTIVE_SKILLS:JSON.stringify(Array.isArray(t.activeSkills)?t.activeSkills:[]),WEGET_HOST_METADATA:JSON.stringify(t.hostMetadata&&"object"==typeof t.hostMetadata?t.hostMetadata:{})},r=String(t.botId||"").trim(),s=String(t.platformApiBaseUrl||"").trim(),n=String(t.accessToken||"").trim(),i=String(t.fileBridgeDir||"").trim(),o=String(t.fileBridgeToken||"").trim();return r&&(e.WEGET_BOT_ID=r),s&&(e.WEGET_PLATFORM_API_BASE_URL=s),n&&(e.WEGET_PLATFORM_API_ACCESS_TOKEN=n),i&&(e.WEGET_FILE_BRIDGE_DIR=i),o&&(e.WEGET_FILE_BRIDGE_TOKEN=o),e},p=()=>n.join(r(),"weget-gateway-context.json"),w=async()=>{const e=d?.()||{};await t.mkdir(r(),{recursive:!0}),await t.writeFile(p(),JSON.stringify({activeSkills:Array.isArray(e.activeSkills)?e.activeSkills:[],hostMetadata:e.hostMetadata&&"object"==typeof e.hostMetadata?e.hostMetadata:{},botId:String(e.botId||"").trim(),platformApiBaseUrl:String(e.platformApiBaseUrl||"").trim(),accessToken:String(e.accessToken||"").trim(),fileBridgeDir:String(e.fileBridgeDir||"").trim(),fileBridgeToken:String(e.fileBridgeToken||"").trim(),logDir:o(),updatedAt:(new Date).toISOString()},null,2),"utf8")},f=async({target:e,payload:r})=>{const s=n.join(o(),"gateway-tests");await t.mkdir(s,{recursive:!0});const i=n.join(s,`${e}-${Date.now()}.log`);return await t.writeFile(i,`${JSON.stringify(r,null,2)}\n`,"utf8"),i},y=async({userPrompt:t,systemPrompt:r,contextLabel:s,promptBundle:n,metadata:i})=>{const o=d?.()||{},c=Array.isArray(o.activeSkills)?o.activeSkills:[],l=o.hostMetadata&&"object"==typeof o.hostMetadata?o.hostMetadata:{},[u,g]=await Promise.all([k("weget-gateway"),P()]),m=c.length?c.map(t=>{const e=Array.isArray(t.tools)&&t.tools.length?` tools=${t.tools.join(", ")}`:"",r=String(t.version||"").trim()?` v${String(t.version||"").trim()}`:"";return`- ${String(t.name||"").trim()}${r}${e}`}):["- none"],p=[`- weget-gateway MCP: ${u.status}`,`- browser runtime: ${g.status}`,`- context: ${String(s||"").trim()||"general"}`,`- default model: ${String(l.aiModel||e()||a).trim()||a}`],w=(t=>{const e=String(t||"").trim().toLowerCase();return!!e&&[/macro/,/economic/,/economy/,/calendar/,/news/,/usd\s*\/\s*jpy/,/usd_jpy/,/risk sentiment/,/economic situation/,/macro snapshot/,/经济/,/宏观/,/日历/,/新闻/,/形势/,/経済/,/マクロ/,/ニュース/,/カレンダー/,/相場/].some(t=>t.test(e))})(t)?["","Macro tool routing hint:","- This request matches macro intent.","- Before answering, use the WeGet macro tools to fetch snapshot, calendar, and news if available.","- Prefer gateway tool calls such as weget_macro_get_snapshot, weget_macro_list_calendar, and weget_macro_list_news.","- Base the summary on fetched tool results rather than unsupported memory."]:[],f=String(r||"").trim(),y=S(n),h=S(i),x=v(y.latest_continuation_state),C=(t=>{const e=Array.isArray(t)?t:[];return e.length?e.slice(-6).map((t,e)=>{const r=S(t),s=v(r.continuation_state);return[`History ${e+1}:`,`- task_id: ${_(r.task_id)||"-"}`,`- title: ${_(r.title)||"-"}`,`- status: ${_(r.status)||"-"}`,`- prompt: ${_(r.prompt)||"-"}`,`- summary: ${_(r.summary)||"-"}`,...s?["- continuation state:",...s.split("\n").map(t=>` ${t}`)]:[]].join("\n")}).join("\n\n"):""})(y.conversation_context);return["You are running inside WeGet Bot Host.","","Active skills:",...m,"","Runtime status:",...p,"","Tool policy:","- Prefer direct reasoning for simple text-only requests.","- When the user asks about macro conditions, economic situation, calendar, or news, prefer the WeGet macro tools before summarizing.","- Use WeGet browser tools only for website access, page extraction, navigation, or screenshots.","- If browser runtime or gateway MCP is unavailable, state that limitation explicitly instead of pretending the task was executed.","- For trading or any action with side effects, do not claim execution unless a concrete tool call actually performed it.","- After the user-visible answer, always append a fenced control block using ```weget_result with compact JSON.",'- The JSON must be {"status":"completed"} for a finished task.','- If you must pause and wait for a user reply before continuing, output {"status":"pending_request","pending_request":{"type":"input","prompt":"...","subtype":"text"}}.','- For approvals, use {"status":"pending_request","pending_request":{"type":"approval","prompt":"...","subtype":"generic"}}.',"- Only use status=pending_request when the task truly cannot continue without the user.","- Keep the final answer plain text only.",...w,...f?["","System prompt:",f]:[],"","Task context:",...[`- conversation id: ${_(y.conversation_id)||"-"}`,`- continue from task id: ${_(y.continue_from_task_id)||"-"}`,`- source: ${_(y.source)||_(h.source)||"-"}`,`- channel: ${_(y.channel)||_(h.channel)||"-"}`],...x?["","Latest continuation state:",x]:[],...C?["","Recent conversation context:",C]:[],..._(h.pending_request_id)||_(h.pending_request_type)?["","Pending request context:",`- request id: ${_(h.pending_request_id)||"-"}`,`- request type: ${_(h.pending_request_type)||"-"}`,`- response via: ${_(h.pending_response_via)||"-"}`,`- response text: ${_(h.pending_response_text)||"-"}`]:[],"","User request:",String(t||"").trim(),"","Respond as plain text only."].join("\n")},k=async t=>{const e=String(t||"").trim();if(!e)return{status:"unknown",detail:"MCP server name is required"};try{"weget-gateway"===e&&await w().catch(()=>{});const t=await b({cwd:r(),args:["mcp","get",e],extraEnv:m()}),s=String(t.stdout||t.stderr||"").trim();return 0!==t.exitCode?/No MCP server named/i.test(s)?{status:"missing",detail:s}:{status:"unknown",detail:s||"codex mcp list failed"}:"playwright"!==e||(t=>{const e=String(t||"");return"win32"===process.platform?/command:\s+.*node(?:\.exe)?/i.test(e)&&/@playwright[\\\/]mcp[\\\/]cli\.js/i.test(e)&&/args:\s+.*--headless/i.test(e):/command:\s+npx/i.test(e)&&/@playwright\/mcp@latest/i.test(e)&&/args:\s+.*--headless/i.test(e)})(s)?"weget-gateway"!==e||E(s,r())?{status:"configured",detail:s||`${e} is configured`}:{status:"missing",detail:"WeGet Gateway MCP exists but points to an outdated launch path. Reinstall it from the host UI."}:{status:"missing",detail:"Playwright MCP exists but uses an unsupported Windows wrapper. Click Install Playwright MCP to repair it."}}catch(t){return{status:"unknown",detail:t instanceof Error?t.message:String(t)}}},P=async()=>{try{const t="win32"===process.platform?"powershell.exe":"npx",e="win32"===process.platform?["-NoProfile","-Command",`& '${$().replace(/'/g,"''")}' playwright install --list`]:["playwright","install","--list"],s=await A({command:t,args:e,cwd:r()}),n=String(s.stdout||s.stderr||"").trim();return 0!==s.exitCode?{status:"unknown",detail:n||"playwright install --list failed"}:/chromium-\d+/i.test(n)||/\\ms-playwright\\chromium-/i.test(n)?{status:"installed",detail:n}:{status:"missing",detail:n||"Chromium is not installed for Playwright."}}catch(t){return{status:"unknown",detail:t instanceof Error?t.message:String(t)}}};return{runPrompt:async({prompt:i,model:d,systemPrompt:l,contextLabel:f,promptBundle:x,metadata:_,onStatus:v})=>{const $=String(d||e()||a).trim()||a,k=r(),P=String(S(x).conversation_id||"").trim();await w().catch(()=>{});const O=C(o()),j=await t.mkdtemp(n.join(s.tmpdir(),"weget-codex-")),E=n.join(j,"last-message.txt"),A=await y({userPrompt:String(i||"").trim(),systemPrompt:String(l||"").trim(),contextLabel:f,promptBundle:x,metadata:_});O.write("exec_start",{model:$,cwd:k,context:String(f||"").trim(),prompt:String(i||"").trim(),instruction:A,outputPath:E,tempDir:j,gatewayContextFile:p(),traceStartedAt:O.startedAt}),v?.("Preparing request"),c("[codex] exec start",{model:$,cwd:k,context:String(f||"").trim(),conversationId:P||void 0});try{const e=async(t,e)=>b({cwd:k,extraEnv:m(),args:t,stdinText:e,onStdoutLine:t=>{O.write("stdout_line",{line:t});const e=h(t);if(e)return/^re-connecting/i.test(e)||/checking tools|tool use|using tool|calling tool/i.test(e)?(O.write("status",{source:"stdout",status:e}),void v?.(e)):void(/reading data|fetching|loading|snapshot|calendar|news/i.test(e)&&(O.write("status",{source:"stdout",status:e}),v?.(e)))},onStderrLine:t=>{O.write("stderr_line",{line:t});const e=String(t||"").match(/session id:\s*([a-zA-Z0-9-]+)/i);e?.[1]&&O.setSessionId(e[1]);const r=h(t);if(r&&!/^--------$/.test(r)&&!/^user$/i.test(r))return/^OpenAI Codex/i.test(r)?(O.write("status",{source:"stderr",status:"Starting Codex"}),void v?.("Starting Codex")):void(/workdir:|model:|provider:|approval:|sandbox:|reasoning effort:|reasoning summaries:|session id:/i.test(r)||(O.write("status",{source:"stderr",status:r}),v?.(r)))}}),r=P?await(async t=>{const e=String(t||"").trim();if(!e)return"";const r=await u();return String(r[e]||"").trim()})(P):"";let s=!1,n=null;if(r&&(s=!0,O.write("resume_attempt",{conversationId:P,sessionId:r}),v?.("Resuming previous Codex session"),n=await e((({cwd:t,sessionId:e,outputPath:r})=>["exec","resume","--dangerously-bypass-approvals-and-sandbox","-C",t,"--skip-git-repo-check","-o",r,e,"-"])({cwd:k,sessionId:r,outputPath:E}),A),0!==n.exitCode&&(O.write("resume_failed",{conversationId:P,sessionId:r,stdout:n.stdout,stderr:n.stderr}),await(async t=>{const e=String(t||"").trim();if(!e)return;const r=await u();r[e]&&(delete r[e],await g(r))})(P).catch(()=>{}),s=!1)),!s){const t=await I({cwd:k,model:$,outputPath:E});n=await e(t,A)}if(!n)throw new Error("codex execution result is missing");O.write("status",{source:"host",status:"Finalizing reply"}),v?.("Finalizing reply");const i=await t.readFile(E,"utf8").catch(()=>"");if(0!==n.exitCode)throw O.write("exec_error",{exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr,lastMessage:i}),new Error((n.stderr||n.stdout||`codex exec failed with code ${n.exitCode}`).trim());const o=String(i||n.stdout||"").trim();if(!o)throw O.write("exec_error",{exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr,lastMessage:i,error:"codex returned empty output"}),new Error("codex returned empty output");return O.write("exec_completed",{exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr,lastMessage:i,finalAnswer:o}),c("[codex] exec completed",{model:$,context:String(f||"").trim(),resumed:s,conversationId:P||void 0}),P&&O.sessionId&&await(async({conversationId:t,sessionId:e})=>{const r=String(t||"").trim(),s=String(e||"").trim();if(!r||!s)return;const n=await u();n[r]=s,await g(n)})({conversationId:P,sessionId:O.sessionId}).catch(()=>{}),o}catch(t){throw O.write("exec_exception",{error:t instanceof Error?t.message:String(t)}),t}finally{const e=await O.flush().catch(()=>"");e&&c("[codex] session trace written",{context:String(f||"").trim(),tracePath:e}),await t.rm(j,{recursive:!0,force:!0}).catch(()=>{})}},getAuthStatus:async()=>{try{const t=await b({cwd:r(),args:["login","status"]}),e=String(t.stdout||t.stderr||"").trim();return 0!==t.exitCode?{status:"unknown",detail:e||"codex login status failed"}:/logged in/i.test(e)?{status:"logged_in",detail:e}:/not logged in|logged out/i.test(e)?{status:"logged_out",detail:e}:{status:"unknown",detail:e||"unknown codex auth state"}}catch(t){return{status:"unknown",detail:t instanceof Error?t.message:String(t)}}},startLogin:async()=>{const e=r();try{if("win32"===process.platform){const r=String(e||"").replace(/'/g,"''"),o=n.join(s.tmpdir(),`weget-codex-login-${Date.now()}.ps1`),a=["$OutputEncoding = [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)","chcp 65001 > $null",'$env:NO_COLOR = "1"','$env:FORCE_COLOR = "0"','$env:CLICOLOR = "0"','$env:LANG = "en_US.UTF-8"','$env:LC_ALL = "en_US.UTF-8"',`Set-Location -LiteralPath '${r}'`,"$stripAnsi = {"," param([string]$line)",' if ($null -eq $line) { return "" }',' return ($line -replace "`e\\[[0-9;?]*[ -/]*[@-~]", "")',"}","codex login --device-auth 2>&1 | ForEach-Object { & $stripAnsi ([string]$_) }"].join(`${s.EOL}`);await t.writeFile(o,a,"utf8");const c=["$script = @()",'$script += "-NoExit"','$script += "-ExecutionPolicy"','$script += "Bypass"','$script += "-File"',`$script += '${o.replace(/'/g,"''")}'`,`Start-Process -FilePath 'powershell.exe' -WorkingDirectory '${r}' -ArgumentList $script`].join("; ");return i("powershell.exe",["-NoProfile","-ExecutionPolicy","Bypass","-Command",c],{cwd:e,stdio:"ignore",windowsHide:!0}).unref(),{ok:!0,detail:"Started `codex login --device-auth` in a new PowerShell window with UTF-8 output."}}if("darwin"===process.platform){const t=`cd ${JSON.stringify(e)} && codex login --device-auth`;return i("open",["-a","Terminal",t],{cwd:e,detached:!0,stdio:"ignore"}).unref(),{ok:!0,detail:"Started `codex login --device-auth` in Terminal."}}const r=`cd ${JSON.stringify(e)} && codex login --device-auth; exec $SHELL`,o=[["x-terminal-emulator",["-e","bash","-lc",r]],["gnome-terminal",["--","bash","-lc",r]],["konsole",["-e","bash","-lc",r]]];for(const[t,r]of o)try{return i(t,r,{cwd:e,detached:!0,stdio:"ignore"}).unref(),{ok:!0,detail:`Started \`codex login --device-auth\` using ${t}.`}}catch{}return{ok:!1,detail:"No supported terminal launcher was found. Run `codex login --device-auth` manually."}}catch(t){const e=t instanceof Error?t.message:String(t);return c("[codex] login launch failed",{error:e}),{ok:!1,detail:e}}},getMcpServerStatus:k,installWegetGatewayMcp:async()=>{try{await w();const t=await k("weget-gateway");if("configured"===t.status&&E(t.detail,r()))return{ok:!0,detail:t.detail||"WeGet Gateway MCP is already configured."};const e=await b({cwd:r(),args:["mcp","remove","weget-gateway"],extraEnv:m()});if(0!==e.exitCode){const t=String(e.stdout||e.stderr||"").trim().toLowerCase();if(!(t.includes("no mcp server named")||t.includes("not found")||t.includes("no server named")))return{ok:!1,detail:String(e.stdout||e.stderr||"").trim()||"Failed to remove existing WeGet Gateway MCP entry."}}const s=O(r()),n=await b({cwd:r(),args:["mcp","add","weget-gateway",s.command,...s.args],extraEnv:m()}),i=String(n.stdout||n.stderr||"").trim();if(0!==n.exitCode)return{ok:!1,detail:i||"Failed to add WeGet Gateway MCP to Codex."};const o=await k("weget-gateway");return"configured"===o.status?{ok:!0,detail:o.detail||"WeGet Gateway MCP configured."}:{ok:!0,detail:i||"WeGet Gateway MCP add command completed, but verification returned no explicit entry."}}catch(t){const e=t instanceof Error?t.message:String(t);return c("[codex] weget gateway mcp install failed",{error:e}),{ok:!1,detail:e}}},getPlaywrightBrowserStatus:P,getGatewayContextFilePath:p,runGatewaySelfTest:async e=>{if("codex_macro"===e){const i=(new Date).toISOString().slice(0,10);await w().catch(()=>{});const c=C(o()),d=await t.mkdtemp(n.join(s.tmpdir(),"weget-codex-test-")),l=n.join(d,"last-message.txt"),u=["You are running a WeGet gateway chain self-test.","Use WeGet gateway MCP tools only.",`Call weget_macro_get_snapshot, weget_macro_list_calendar with dateKey=${i}, and weget_macro_list_news with dateKey=${i}.`,"If all three tool calls succeed, reply with exactly: OK macro chain","If any tool call fails, reply with exactly: NG macro chain: <short reason>","Respond as plain text only."].join("\n");c.write("exec_start",{model:a,cwd:r(),context:"gateway_self_test:codex_macro",prompt:"codex macro chain self-test",instruction:u,outputPath:l,tempDir:d,gatewayContextFile:p(),traceStartedAt:c.startedAt});try{const s=await I({cwd:r(),model:a,outputPath:l}),n=await b({cwd:r(),extraEnv:m(),args:s,stdinText:u,onStdoutLine:t=>{c.write("stdout_line",{line:t})},onStderrLine:t=>{c.write("stderr_line",{line:t});const e=String(t||"").match(/session id:\s*([a-zA-Z0-9-]+)/i);e?.[1]&&c.setSessionId(e[1])}}),o=await t.readFile(l,"utf8").catch(()=>""),g=String(o||n.stdout||"").trim(),w=String(n.stderr||""),y=String(n.stdout||""),h=/tool weget-gateway\.weget_macro_get_snapshot\(\{\}\)/i.test(w),S=new RegExp(`tool weget-gateway\\.weget_macro_list_calendar\\(\\{"dateKey":"${j(i)}"\\}\\)`,"i").test(w),_=new RegExp(`tool weget-gateway\\.weget_macro_list_news\\(\\{"dateKey":"${j(i)}"\\}\\)`,"i").test(w),v=/weget-gateway\.weget_macro_get_snapshot\(\{\}\) success/i.test(w),C=/weget-gateway\.weget_macro_list_calendar\(\{\"dateKey\":\"\d{4}-\d{2}-\d{2}\"\}\) success/i.test(w),$=/weget-gateway\.weget_macro_list_news\(\{\"dateKey\":\"\d{4}-\d{2}-\d{2}\"\}\) success/i.test(w),k=0===n.exitCode&&/^OK macro chain$/i.test(g)&&h&&S&&_&&v&&C&&$;c.write(k?"exec_completed":"exec_error",{exitCode:n.exitCode,stdout:y,stderr:w,lastMessage:o,finalAnswer:g,invokedSnapshot:h,invokedCalendar:S,invokedNews:_,succeededSnapshot:v,succeededCalendar:C,succeededNews:$});const P=await c.flush().catch(()=>""),O={target:e,ok:k,summary:k?"Codex gateway macro chain OK":"Codex gateway macro chain failed",contextFilePath:p(),tracePath:P,codex:{exitCode:n.exitCode,stdout:y,stderr:w,finalAnswer:g},assertions:{invokedSnapshot:h,invokedCalendar:S,invokedNews:_,succeededSnapshot:v,succeededCalendar:C,succeededNews:$},ts:(new Date).toISOString()},E=await f({target:e,payload:O});return await t.rm(d,{recursive:!0,force:!0}).catch(()=>{}),{ok:k,summary:k?"Codex gateway macro chain OK":x(g||w,"Codex gateway macro chain failed"),detail:g||w||y,logPath:E,result:O}}catch(r){c.write("exec_exception",{error:r instanceof Error?r.message:String(r)});const s=await c.flush().catch(()=>""),n=r instanceof Error?r.message:String(r),i=await f({target:e,payload:{target:e,ok:!1,summary:"Codex gateway macro chain failed",contextFilePath:p(),tracePath:s,error:n,ts:(new Date).toISOString()}});return await t.rm(d,{recursive:!0,force:!0}).catch(()=>{}),{ok:!1,summary:x(n,"Codex gateway macro chain failed"),detail:n,logPath:i}}}await w();const c=O(r());let d,l=null;try{d=await A({command:c.command,args:[...c.args,"--self-test","--test-target",e],cwd:r()}),"gateway"===e&&(l=await(async({command:t,args:e,cwd:r,timeoutMs:s=2500})=>new Promise((n,o)=>{const a=i(t,e,{cwd:r,stdio:["ignore","pipe","pipe"],windowsHide:!0,env:{...process.env,NO_COLOR:"1",FORCE_COLOR:"0",CLICOLOR:"0"}}),c=[],d=[];let l=!1;const u=t=>{l||(l=!0,n(t))};a.stdout.on("data",t=>c.push(Buffer.from(t))),a.stderr.on("data",t=>d.push(Buffer.from(t))),a.on("error",t=>{l||(l=!0,o(t))}),a.on("close",t=>{u({ok:!1,exitCode:Number.isFinite(t)?Number(t):1,stdout:Buffer.concat(c).toString("utf8"),stderr:Buffer.concat(d).toString("utf8"),responseText:""})}),setTimeout(()=>{const t=a.stdin;t?.write(`${JSON.stringify({jsonrpc:"2.0",id:1,method:"initialize",params:{protocolVersion:"2024-11-05",capabilities:{},clientInfo:{name:"weget-gateway-probe",version:"0.1.0"}}})}\n`)},150),setTimeout(()=>{if(l)return;const t=Buffer.concat(c).toString("utf8"),e=Buffer.concat(d).toString("utf8"),r=t.trim(),s=/"result"\s*:/.test(r)&&/"protocolVersion"\s*:/.test(r);a.kill(),u({ok:s,exitCode:null,stdout:t,stderr:e,responseText:r})},Math.max(250,s))}))({command:c.command,args:c.args,cwd:r()}))}catch(t){const r=t instanceof Error?t.message:String(t),s=await f({target:e,payload:{target:e,launch:c,contextFilePath:p(),failure:"spawn_exception",error:r,ts:(new Date).toISOString()}});return{ok:!1,summary:x(r,`${e} test failed`),detail:r,logPath:s}}const u=String(d.stdout||d.stderr||"").trim();let g;if(u)try{g=JSON.parse(u)}catch{}let y=0===d.exitCode&&Boolean(!g||!1!==g.ok),h=x(u,`${e} self-test completed`);"gateway"===e&&l&&!l.ok?(y=!1,h=x(l.stderr||l.stdout,"Gateway handshake probe failed.")):"gateway"===e&&l?.ok&&(h="Gateway MCP handshake OK");const S={target:e,ok:y,summary:h,launch:c,contextFilePath:p(),selfTest:{exitCode:d.exitCode,stdout:d.stdout,stderr:d.stderr,result:g??null},handshakeProbe:l?{ok:l.ok,exitCode:l.exitCode,stdout:l.stdout,stderr:l.stderr,responseText:l.responseText}:null,ts:(new Date).toISOString()};return{ok:y,summary:h,detail:u||h,logPath:await f({target:e,payload:S}),result:g}}}};
|
|
1
|
+
import t from"node:fs/promises";import{existsSync as e}from"node:fs";import{createRequire as r}from"node:module";import s from"node:os";import n from"node:path";import{spawn as i,spawnSync as o}from"node:child_process";const a="gpt-5.4",c=r(import.meta.url);let d=null,l=null,u=null,g=null,m=null,p=null;const w=async t=>{if(!t)return"";const e=[];for await(const r of t)e.push(Buffer.isBuffer(r)?r:Buffer.from(String(r)));return Buffer.concat(e).toString("utf8")},f=t=>String(t||"").replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g,""),y=t=>{let e="";return{push:r=>{if(!t)return;e+=f(Buffer.isBuffer(r)?r.toString("utf8"):String(r));const s=e.split(/\r?\n/);e=s.pop()||"";for(const e of s){const r=String(e||"").trim();r&&t(r)}},flush:()=>{if(!t)return;const r=String(e||"").trim();r&&t(r),e=""}}},h=t=>{const e=f(String(t||"")).trim();return e?/^[{}[\],:]+$/.test(e)||/^["']?[a-zA-Z0-9_-]+["']?\s*:\s*$/.test(e)||/^`{3,}|^#{1,6}\s*$/.test(e)||/^Assistant:?\s*$/i.test(e)||/^Warning: no last agent message/i.test(e)?"":/^ERROR:\s*unexpected status\s+\d+/i.test(e)?"Tool call failed":e:""},x=(t,e)=>{const r=f(String(t||"")).replace(/\s+/g," ").trim();return r?r.length>180?`${r.slice(0,177)}...`:r:e},S=t=>t&&"object"==typeof t?t:{},_=t=>String(t||"").trim(),C=t=>{const e=S(t);if(0===Object.keys(e).length)return"";const r=S(e.waiting),s=[`- source task: ${_(e.task_id)||"-"}`,`- status: ${_(e.status)||"-"}`,`- title: ${_(e.title)||"-"}`,`- user prompt: ${_(e.user_prompt)||"-"}`,`- summary: ${_(e.summary)||"-"}`,`- latest output: ${_(e.latest_output)||"-"}`,`- last event: ${_(e.last_event_type)||"-"}`];return Object.keys(r).length>0&&(s.push(`- waiting type: ${_(r.type)||"-"}`),s.push(`- waiting subtype: ${_(r.subtype)||"-"}`),s.push(`- waiting prompt: ${_(r.prompt)||"-"}`)),s.join("\n")},v=e=>{const r=(new Date).toISOString(),s=`exec-${Date.now()}`;let i="",o="",a=!1,c=Promise.resolve();const d=[],l=async()=>{if(a)return o;const r=n.join(e,"codex-sessions");await t.mkdir(r,{recursive:!0});const c=String(i||s||"").trim().replace(/[^a-zA-Z0-9._-]+/g,"_");return o=n.join(r,`${c}.log`),a=!0,d.length>0&&(await t.appendFile(o,d.join(""),"utf8"),d.length=0),o},u=(e,r={})=>{(e=>{c=c.then(async()=>{if(!a&&!i)return void d.push(e);const r=await l();await t.appendFile(r,e,"utf8")}).catch(()=>{})})(`${JSON.stringify({ts:(new Date).toISOString(),event:e,...r},null,0)}\n`)};return{get startedAt(){return r},get sessionId(){return i},setSessionId:t=>{const e=String(t||"").trim();e&&i!==e&&(i=e,u("session_identified",{sessionId:e}))},write:u,flush:async()=>(a||await l(),await c,o)}},$=()=>{if(l)return l;const t=[n.join(String(process.env.ProgramFiles||"C:\\Program Files"),"nodejs","npx.cmd"),n.join(String(process.env["ProgramFiles(x86)"]||"C:\\Program Files (x86)"),"nodejs","npx.cmd"),n.join(String(process.env.APPDATA||""),"npm","npx.cmd")].filter(Boolean);for(const r of t)if(e(r))return l=r,r;const r=o("where.exe",["npx.cmd"],{windowsHide:!0,encoding:"utf8"}),s=String(r.stdout||"").split(/\r?\n/).map(t=>t.trim()).find(Boolean);return s?(l=s,s):"npx.cmd"},P=()=>{if(u)return u;const t=[n.join(String(process.env.ProgramFiles||"C:\\Program Files"),"nodejs","node.exe"),n.join(String(process.env["ProgramFiles(x86)"]||"C:\\Program Files (x86)"),"nodejs","node.exe")];for(const r of t)if(e(r))return u=r,r;return u="node",u},k=()=>{if(g)return g;try{const t=c.resolve("@ai.weget.jp/weget-gateway-mcp/dist/index.js");return g=t,t}catch{}const t=[n.join(String(process.env.APPDATA||""),"npm","node_modules","@ai.weget.jp","weget-gateway-mcp","dist","index.js"),n.join(String(process.env.ProgramFiles||"C:\\Program Files"),"nodejs","node_modules","@ai.weget.jp","weget-gateway-mcp","dist","index.js"),n.join(String(process.env["ProgramFiles(x86)"]||"C:\\Program Files (x86)"),"nodejs","node_modules","@ai.weget.jp","weget-gateway-mcp","dist","index.js")].filter(Boolean);for(const r of t)if(e(r))return g=r,r;return g=n.join(String(process.env.APPDATA||""),"npm","node_modules","@ai.weget.jp","weget-gateway-mcp","dist","index.js"),g},O=t=>{const e=n.join(t,"weget-gateway-context.json");return"win32"===process.platform?{command:P(),args:[k(),"--context-file",e]}:{command:"npx",args:["-y","@ai.weget.jp/weget-gateway-mcp@latest","--context-file",e]}},j=t=>String(t||"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),E=(t,e)=>{const r=String(t||""),s=O(e);if("win32"===process.platform){const t=new RegExp(`command:\\s+${j(s.command)}`,"i"),e=new RegExp(j(String(s.args[0]||"")),"i"),n=new RegExp(j(String(s.args[2]||"")),"i");return t.test(r)&&e.test(r)&&n.test(r)}return new RegExp(`command:\\s+${j(s.command)}`,"i").test(r)&&r.includes(String(s.args[0]||""))},b=async({args:t,stdinText:r,cwd:s,extraEnv:a,onStdoutLine:c,onStderrLine:l})=>new Promise((u,g)=>{const m=t=>{const e="object"==typeof t&&t&&"code"in t?String(t.code||""):"";return"EPIPE"===e||"ERR_STREAM_DESTROYED"===e},p=(()=>{if(d)return d;if("win32"===process.platform){const t=[String(process.env.ProgramFiles||"C:\\Program Files"),String(process.env["ProgramFiles(x86)"]||"C:\\Program Files (x86)")];for(const r of t){const t=n.join(r,"nodejs","node.exe"),s=n.join(r,"nodejs","node_modules","@openai","codex","bin","codex.js");if(e(t)&&e(s))return d={command:t,baseArgs:[s]},d}const r=["codex.cmd","codex"];for(const t of r){const e=o("where.exe",[t],{windowsHide:!0,encoding:"utf8"}),r=String(e.stdout||"").split(/\r?\n/).map(t=>t.trim()).find(Boolean);if(r)return d={command:r,baseArgs:[]},d}}return d={command:"codex",baseArgs:[]},d})(),f={...process.env,...a||{},NO_COLOR:"1",FORCE_COLOR:"0",CLICOLOR:"0"},h=i(p.command,[...p.baseArgs,...t],{cwd:s,stdio:["pipe","pipe","pipe"],windowsHide:!0,env:f});let x=!1;const S=t=>{x||(x=!0,t())},_=w(h.stdout),C=w(h.stderr),v=y(c),$=y(l);h.stdout?.on("data",t=>v.push(t)),h.stderr?.on("data",t=>$.push(t)),h.on("error",t=>{S(()=>g(t))}),h.stdin?.on("error",t=>{m(t)||S(()=>g(t))}),h.on("close",async t=>{v.flush(),$.flush();const[e,r]=await Promise.all([_,C]);S(()=>u({stdout:e,stderr:r,exitCode:Number.isFinite(t)?Number(t):1}))}),"string"==typeof r&&h.stdin?.writable?h.stdin.write(r,t=>{!t||m(t)?h.stdin?.end():S(()=>g(t))}):h.stdin?.end()}),A=async({command:t,args:e,cwd:r})=>new Promise((s,n)=>{const o=i(t,e,{cwd:r,stdio:["pipe","pipe","pipe"],windowsHide:!0,env:{...process.env,NO_COLOR:"1",FORCE_COLOR:"0",CLICOLOR:"0"}});let a=!1;const c=t=>{a||(a=!0,t())},d=w(o.stdout),l=w(o.stderr);o.on("error",t=>c(()=>n(t))),o.on("close",async t=>{const[e,r]=await Promise.all([d,l]);c(()=>s({stdout:e,stderr:r,exitCode:Number.isFinite(t)?Number(t):1}))})}),F=async t=>null!==m?m:(p||(p=(async(t,e)=>{const r=String(t||"").trim();if(!r)return!1;try{const t=await b({cwd:e,args:["features","list"]});return 0===t.exitCode&&f(`${t.stdout||""}\n${t.stderr||""}`).split(/\r?\n/).map(t=>t.trim()).some(t=>t.startsWith(`${r} `)||t===r)}catch{return!1}})("rmcp_client",t).then(t=>(m=t,t)).finally(()=>{p=null})),p),I=async({cwd:t,model:e,outputPath:r})=>{const s=["exec"];return await F(t)&&s.push("--enable","rmcp_client"),s.push("--dangerously-bypass-approvals-and-sandbox","-C",t,"--skip-git-repo-check","-m",e,"-o",r,"-"),s};export const buildCodexResumeArgs=({cwd:t,sessionId:e,outputPath:r})=>["exec","--dangerously-bypass-approvals-and-sandbox","-C",t,"--skip-git-repo-check","-o",r,"resume",e,"-"];export const createCodexService=({getModel:e,getWorkingDir:r,getLogDir:o,emitLog:c,getGatewayContext:d})=>{const l=()=>n.join(o(),"codex-session-bindings.json"),u=async()=>{try{const e=await t.readFile(l(),"utf8"),r=JSON.parse(e);return Object.fromEntries(Object.entries(r||{}).map(([t,e])=>[String(t||"").trim(),String(e||"").trim()]).filter(([t,e])=>t&&e))}catch{return{}}},g=async e=>{await t.mkdir(o(),{recursive:!0}),await t.writeFile(l(),`${JSON.stringify(e,null,2)}\n`,"utf8")},m=()=>{const t=d?.()||{},e={WEGET_ACTIVE_SKILLS:JSON.stringify(Array.isArray(t.activeSkills)?t.activeSkills:[]),WEGET_HOST_METADATA:JSON.stringify(t.hostMetadata&&"object"==typeof t.hostMetadata?t.hostMetadata:{})},r=String(t.botId||"").trim(),s=String(t.platformApiBaseUrl||"").trim(),n=String(t.accessToken||"").trim(),i=String(t.fileBridgeDir||"").trim(),o=String(t.fileBridgeToken||"").trim();return r&&(e.WEGET_BOT_ID=r),s&&(e.WEGET_PLATFORM_API_BASE_URL=s),n&&(e.WEGET_PLATFORM_API_ACCESS_TOKEN=n),i&&(e.WEGET_FILE_BRIDGE_DIR=i),o&&(e.WEGET_FILE_BRIDGE_TOKEN=o),e},p=()=>n.join(r(),"weget-gateway-context.json"),w=async()=>{const e=d?.()||{};await t.mkdir(r(),{recursive:!0}),await t.writeFile(p(),JSON.stringify({activeSkills:Array.isArray(e.activeSkills)?e.activeSkills:[],hostMetadata:e.hostMetadata&&"object"==typeof e.hostMetadata?e.hostMetadata:{},botId:String(e.botId||"").trim(),platformApiBaseUrl:String(e.platformApiBaseUrl||"").trim(),accessToken:String(e.accessToken||"").trim(),fileBridgeDir:String(e.fileBridgeDir||"").trim(),fileBridgeToken:String(e.fileBridgeToken||"").trim(),logDir:o(),updatedAt:(new Date).toISOString()},null,2),"utf8")},f=async({target:e,payload:r})=>{const s=n.join(o(),"gateway-tests");await t.mkdir(s,{recursive:!0});const i=n.join(s,`${e}-${Date.now()}.log`);return await t.writeFile(i,`${JSON.stringify(r,null,2)}\n`,"utf8"),i},y=async({userPrompt:t,systemPrompt:r,contextLabel:s,promptBundle:n,metadata:i})=>{const o=d?.()||{},c=Array.isArray(o.activeSkills)?o.activeSkills:[],l=o.hostMetadata&&"object"==typeof o.hostMetadata?o.hostMetadata:{},[u,g]=await Promise.all([P("weget-gateway"),k()]),m=c.length?c.map(t=>{const e=Array.isArray(t.tools)&&t.tools.length?` tools=${t.tools.join(", ")}`:"",r=String(t.version||"").trim()?` v${String(t.version||"").trim()}`:"";return`- ${String(t.name||"").trim()}${r}${e}`}):["- none"],p=[`- weget-gateway MCP: ${u.status}`,`- browser runtime: ${g.status}`,`- context: ${String(s||"").trim()||"general"}`,`- default model: ${String(l.aiModel||e()||a).trim()||a}`],w=(t=>{const e=String(t||"").trim().toLowerCase();return!!e&&[/macro/,/economic/,/economy/,/calendar/,/news/,/usd\s*\/\s*jpy/,/usd_jpy/,/risk sentiment/,/economic situation/,/macro snapshot/,/经济/,/宏观/,/日历/,/新闻/,/形势/,/経済/,/マクロ/,/ニュース/,/カレンダー/,/相場/].some(t=>t.test(e))})(t)?["","Macro tool routing hint:","- This request matches macro intent.","- Before answering, use the WeGet macro tools to fetch snapshot, calendar, and news if available.","- Prefer gateway tool calls such as weget_macro_get_snapshot, weget_macro_list_calendar, and weget_macro_list_news.","- Base the summary on fetched tool results rather than unsupported memory."]:[],f=String(r||"").trim(),y=S(n),h=S(i),x=C(y.latest_continuation_state),v=(t=>{const e=Array.isArray(t)?t:[];return e.length?e.slice(-6).map((t,e)=>{const r=S(t),s=C(r.continuation_state);return[`History ${e+1}:`,`- task_id: ${_(r.task_id)||"-"}`,`- title: ${_(r.title)||"-"}`,`- status: ${_(r.status)||"-"}`,`- prompt: ${_(r.prompt)||"-"}`,`- summary: ${_(r.summary)||"-"}`,...s?["- continuation state:",...s.split("\n").map(t=>` ${t}`)]:[]].join("\n")}).join("\n\n"):""})(y.conversation_context);return["You are running inside WeGet Bot Host.","","Active skills:",...m,"","Runtime status:",...p,"","Tool policy:","- Prefer direct reasoning for simple text-only requests.","- When the user asks about macro conditions, economic situation, calendar, or news, prefer the WeGet macro tools before summarizing.","- Use WeGet browser tools only for website access, page extraction, navigation, or screenshots.","- If browser runtime or gateway MCP is unavailable, state that limitation explicitly instead of pretending the task was executed.","- For trading or any action with side effects, do not claim execution unless a concrete tool call actually performed it.","- After the user-visible answer, always append a fenced control block using ```weget_result with compact JSON.",'- The JSON must be {"status":"completed"} for a finished task.','- If you must pause and wait for a user reply before continuing, output {"status":"pending_request","pending_request":{"type":"input","prompt":"...","subtype":"text"}}.','- For approvals, use {"status":"pending_request","pending_request":{"type":"approval","prompt":"...","subtype":"generic"}}.',"- Only use status=pending_request when the task truly cannot continue without the user.","- Keep the final answer plain text only.",...w,...f?["","System prompt:",f]:[],"","Task context:",...[`- conversation id: ${_(y.conversation_id)||"-"}`,`- continue from task id: ${_(y.continue_from_task_id)||"-"}`,`- source: ${_(y.source)||_(h.source)||"-"}`,`- channel: ${_(y.channel)||_(h.channel)||"-"}`],...x?["","Latest continuation state:",x]:[],...v?["","Recent conversation context:",v]:[],..._(h.pending_request_id)||_(h.pending_request_type)?["","Pending request context:",`- request id: ${_(h.pending_request_id)||"-"}`,`- request type: ${_(h.pending_request_type)||"-"}`,`- response via: ${_(h.pending_response_via)||"-"}`,`- response text: ${_(h.pending_response_text)||"-"}`]:[],"","User request:",String(t||"").trim(),"","Respond as plain text only."].join("\n")},P=async t=>{const e=String(t||"").trim();if(!e)return{status:"unknown",detail:"MCP server name is required"};try{"weget-gateway"===e&&await w().catch(()=>{});const t=await b({cwd:r(),args:["mcp","get",e],extraEnv:m()}),s=String(t.stdout||t.stderr||"").trim();return 0!==t.exitCode?/No MCP server named/i.test(s)?{status:"missing",detail:s}:{status:"unknown",detail:s||"codex mcp list failed"}:"playwright"!==e||(t=>{const e=String(t||"");return"win32"===process.platform?/command:\s+.*node(?:\.exe)?/i.test(e)&&/@playwright[\\\/]mcp[\\\/]cli\.js/i.test(e)&&/args:\s+.*--headless/i.test(e):/command:\s+npx/i.test(e)&&/@playwright\/mcp@latest/i.test(e)&&/args:\s+.*--headless/i.test(e)})(s)?"weget-gateway"!==e||E(s,r())?{status:"configured",detail:s||`${e} is configured`}:{status:"missing",detail:"WeGet Gateway MCP exists but points to an outdated launch path. Reinstall it from the host UI."}:{status:"missing",detail:"Playwright MCP exists but uses an unsupported Windows wrapper. Click Install Playwright MCP to repair it."}}catch(t){return{status:"unknown",detail:t instanceof Error?t.message:String(t)}}},k=async()=>{try{const t="win32"===process.platform?"powershell.exe":"npx",e="win32"===process.platform?["-NoProfile","-Command",`& '${$().replace(/'/g,"''")}' playwright install --list`]:["playwright","install","--list"],s=await A({command:t,args:e,cwd:r()}),n=String(s.stdout||s.stderr||"").trim();return 0!==s.exitCode?{status:"unknown",detail:n||"playwright install --list failed"}:/chromium-\d+/i.test(n)||/\\ms-playwright\\chromium-/i.test(n)?{status:"installed",detail:n}:{status:"missing",detail:n||"Chromium is not installed for Playwright."}}catch(t){return{status:"unknown",detail:t instanceof Error?t.message:String(t)}}};return{runPrompt:async({prompt:i,model:d,systemPrompt:l,contextLabel:f,promptBundle:x,metadata:_,onStatus:C})=>{const $=String(d||e()||a).trim()||a,P=r(),k=String(S(x).conversation_id||"").trim();await w().catch(()=>{});const O=v(o()),j=await t.mkdtemp(n.join(s.tmpdir(),"weget-codex-")),E=n.join(j,"last-message.txt"),A=await y({userPrompt:String(i||"").trim(),systemPrompt:String(l||"").trim(),contextLabel:f,promptBundle:x,metadata:_});O.write("exec_start",{model:$,cwd:P,context:String(f||"").trim(),prompt:String(i||"").trim(),instruction:A,outputPath:E,tempDir:j,gatewayContextFile:p(),traceStartedAt:O.startedAt}),C?.("Preparing request"),c("[codex] exec start",{model:$,cwd:P,context:String(f||"").trim(),conversationId:k||void 0});try{const e=async(t,e)=>b({cwd:P,extraEnv:m(),args:t,stdinText:e,onStdoutLine:t=>{O.write("stdout_line",{line:t});const e=h(t);if(e)return/^re-connecting/i.test(e)||/checking tools|tool use|using tool|calling tool/i.test(e)?(O.write("status",{source:"stdout",status:e}),void C?.(e)):void(/reading data|fetching|loading|snapshot|calendar|news/i.test(e)&&(O.write("status",{source:"stdout",status:e}),C?.(e)))},onStderrLine:t=>{O.write("stderr_line",{line:t});const e=String(t||"").match(/session id:\s*([a-zA-Z0-9-]+)/i);e?.[1]&&O.setSessionId(e[1]);const r=h(t);if(r&&!/^--------$/.test(r)&&!/^user$/i.test(r))return/^OpenAI Codex/i.test(r)?(O.write("status",{source:"stderr",status:"Starting Codex"}),void C?.("Starting Codex")):void(/workdir:|model:|provider:|approval:|sandbox:|reasoning effort:|reasoning summaries:|session id:/i.test(r)||(O.write("status",{source:"stderr",status:r}),C?.(r)))}}),r=k?await(async t=>{const e=String(t||"").trim();if(!e)return"";const r=await u();return String(r[e]||"").trim()})(k):"";let s=!1,n=null;if(r&&(s=!0,O.write("resume_attempt",{conversationId:k,sessionId:r}),C?.("Resuming previous Codex session"),n=await e(buildCodexResumeArgs({cwd:P,sessionId:r,outputPath:E}),A),0!==n.exitCode&&(O.write("resume_failed",{conversationId:k,sessionId:r,stdout:n.stdout,stderr:n.stderr}),await(async t=>{const e=String(t||"").trim();if(!e)return;const r=await u();r[e]&&(delete r[e],await g(r))})(k).catch(()=>{}),s=!1)),!s){const t=await I({cwd:P,model:$,outputPath:E});n=await e(t,A)}if(!n)throw new Error("codex execution result is missing");O.write("status",{source:"host",status:"Finalizing reply"}),C?.("Finalizing reply");const i=await t.readFile(E,"utf8").catch(()=>"");if(0!==n.exitCode)throw O.write("exec_error",{exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr,lastMessage:i}),new Error((n.stderr||n.stdout||`codex exec failed with code ${n.exitCode}`).trim());const o=String(i||n.stdout||"").trim();if(!o)throw O.write("exec_error",{exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr,lastMessage:i,error:"codex returned empty output"}),new Error("codex returned empty output");return O.write("exec_completed",{exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr,lastMessage:i,finalAnswer:o}),c("[codex] exec completed",{model:$,context:String(f||"").trim(),resumed:s,conversationId:k||void 0}),k&&O.sessionId&&await(async({conversationId:t,sessionId:e})=>{const r=String(t||"").trim(),s=String(e||"").trim();if(!r||!s)return;const n=await u();n[r]=s,await g(n)})({conversationId:k,sessionId:O.sessionId}).catch(()=>{}),o}catch(t){throw O.write("exec_exception",{error:t instanceof Error?t.message:String(t)}),t}finally{const e=await O.flush().catch(()=>"");e&&c("[codex] session trace written",{context:String(f||"").trim(),tracePath:e}),await t.rm(j,{recursive:!0,force:!0}).catch(()=>{})}},getAuthStatus:async()=>{try{const t=await b({cwd:r(),args:["login","status"]}),e=String(t.stdout||t.stderr||"").trim();return 0!==t.exitCode?{status:"unknown",detail:e||"codex login status failed"}:/logged in/i.test(e)?{status:"logged_in",detail:e}:/not logged in|logged out/i.test(e)?{status:"logged_out",detail:e}:{status:"unknown",detail:e||"unknown codex auth state"}}catch(t){return{status:"unknown",detail:t instanceof Error?t.message:String(t)}}},startLogin:async()=>{const e=r();try{if("win32"===process.platform){const r=String(e||"").replace(/'/g,"''"),o=n.join(s.tmpdir(),`weget-codex-login-${Date.now()}.ps1`),a=["$OutputEncoding = [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)","chcp 65001 > $null",'$env:NO_COLOR = "1"','$env:FORCE_COLOR = "0"','$env:CLICOLOR = "0"','$env:LANG = "en_US.UTF-8"','$env:LC_ALL = "en_US.UTF-8"',`Set-Location -LiteralPath '${r}'`,"$stripAnsi = {"," param([string]$line)",' if ($null -eq $line) { return "" }',' return ($line -replace "`e\\[[0-9;?]*[ -/]*[@-~]", "")',"}","codex login --device-auth 2>&1 | ForEach-Object { & $stripAnsi ([string]$_) }"].join(`${s.EOL}`);await t.writeFile(o,a,"utf8");const c=["$script = @()",'$script += "-NoExit"','$script += "-ExecutionPolicy"','$script += "Bypass"','$script += "-File"',`$script += '${o.replace(/'/g,"''")}'`,`Start-Process -FilePath 'powershell.exe' -WorkingDirectory '${r}' -ArgumentList $script`].join("; ");return i("powershell.exe",["-NoProfile","-ExecutionPolicy","Bypass","-Command",c],{cwd:e,stdio:"ignore",windowsHide:!0}).unref(),{ok:!0,detail:"Started `codex login --device-auth` in a new PowerShell window with UTF-8 output."}}if("darwin"===process.platform){const t=`cd ${JSON.stringify(e)} && codex login --device-auth`;return i("open",["-a","Terminal",t],{cwd:e,detached:!0,stdio:"ignore"}).unref(),{ok:!0,detail:"Started `codex login --device-auth` in Terminal."}}const r=`cd ${JSON.stringify(e)} && codex login --device-auth; exec $SHELL`,o=[["x-terminal-emulator",["-e","bash","-lc",r]],["gnome-terminal",["--","bash","-lc",r]],["konsole",["-e","bash","-lc",r]]];for(const[t,r]of o)try{return i(t,r,{cwd:e,detached:!0,stdio:"ignore"}).unref(),{ok:!0,detail:`Started \`codex login --device-auth\` using ${t}.`}}catch{}return{ok:!1,detail:"No supported terminal launcher was found. Run `codex login --device-auth` manually."}}catch(t){const e=t instanceof Error?t.message:String(t);return c("[codex] login launch failed",{error:e}),{ok:!1,detail:e}}},getMcpServerStatus:P,installWegetGatewayMcp:async()=>{try{await w();const t=await P("weget-gateway");if("configured"===t.status&&E(t.detail,r()))return{ok:!0,detail:t.detail||"WeGet Gateway MCP is already configured."};const e=await b({cwd:r(),args:["mcp","remove","weget-gateway"],extraEnv:m()});if(0!==e.exitCode){const t=String(e.stdout||e.stderr||"").trim().toLowerCase();if(!(t.includes("no mcp server named")||t.includes("not found")||t.includes("no server named")))return{ok:!1,detail:String(e.stdout||e.stderr||"").trim()||"Failed to remove existing WeGet Gateway MCP entry."}}const s=O(r()),n=await b({cwd:r(),args:["mcp","add","weget-gateway",s.command,...s.args],extraEnv:m()}),i=String(n.stdout||n.stderr||"").trim();if(0!==n.exitCode)return{ok:!1,detail:i||"Failed to add WeGet Gateway MCP to Codex."};const o=await P("weget-gateway");return"configured"===o.status?{ok:!0,detail:o.detail||"WeGet Gateway MCP configured."}:{ok:!0,detail:i||"WeGet Gateway MCP add command completed, but verification returned no explicit entry."}}catch(t){const e=t instanceof Error?t.message:String(t);return c("[codex] weget gateway mcp install failed",{error:e}),{ok:!1,detail:e}}},getPlaywrightBrowserStatus:k,getGatewayContextFilePath:p,runGatewaySelfTest:async e=>{if("codex_macro"===e){const i=(new Date).toISOString().slice(0,10);await w().catch(()=>{});const c=v(o()),d=await t.mkdtemp(n.join(s.tmpdir(),"weget-codex-test-")),l=n.join(d,"last-message.txt"),u=["You are running a WeGet gateway chain self-test.","Use WeGet gateway MCP tools only.",`Call weget_macro_get_snapshot, weget_macro_list_calendar with dateKey=${i}, and weget_macro_list_news with dateKey=${i}.`,"If all three tool calls succeed, reply with exactly: OK macro chain","If any tool call fails, reply with exactly: NG macro chain: <short reason>","Respond as plain text only."].join("\n");c.write("exec_start",{model:a,cwd:r(),context:"gateway_self_test:codex_macro",prompt:"codex macro chain self-test",instruction:u,outputPath:l,tempDir:d,gatewayContextFile:p(),traceStartedAt:c.startedAt});try{const s=await I({cwd:r(),model:a,outputPath:l}),n=await b({cwd:r(),extraEnv:m(),args:s,stdinText:u,onStdoutLine:t=>{c.write("stdout_line",{line:t})},onStderrLine:t=>{c.write("stderr_line",{line:t});const e=String(t||"").match(/session id:\s*([a-zA-Z0-9-]+)/i);e?.[1]&&c.setSessionId(e[1])}}),o=await t.readFile(l,"utf8").catch(()=>""),g=String(o||n.stdout||"").trim(),w=String(n.stderr||""),y=String(n.stdout||""),h=/tool weget-gateway\.weget_macro_get_snapshot\(\{\}\)/i.test(w),S=new RegExp(`tool weget-gateway\\.weget_macro_list_calendar\\(\\{"dateKey":"${j(i)}"\\}\\)`,"i").test(w),_=new RegExp(`tool weget-gateway\\.weget_macro_list_news\\(\\{"dateKey":"${j(i)}"\\}\\)`,"i").test(w),C=/weget-gateway\.weget_macro_get_snapshot\(\{\}\) success/i.test(w),v=/weget-gateway\.weget_macro_list_calendar\(\{\"dateKey\":\"\d{4}-\d{2}-\d{2}\"\}\) success/i.test(w),$=/weget-gateway\.weget_macro_list_news\(\{\"dateKey\":\"\d{4}-\d{2}-\d{2}\"\}\) success/i.test(w),P=0===n.exitCode&&/^OK macro chain$/i.test(g)&&h&&S&&_&&C&&v&&$;c.write(P?"exec_completed":"exec_error",{exitCode:n.exitCode,stdout:y,stderr:w,lastMessage:o,finalAnswer:g,invokedSnapshot:h,invokedCalendar:S,invokedNews:_,succeededSnapshot:C,succeededCalendar:v,succeededNews:$});const k=await c.flush().catch(()=>""),O={target:e,ok:P,summary:P?"Codex gateway macro chain OK":"Codex gateway macro chain failed",contextFilePath:p(),tracePath:k,codex:{exitCode:n.exitCode,stdout:y,stderr:w,finalAnswer:g},assertions:{invokedSnapshot:h,invokedCalendar:S,invokedNews:_,succeededSnapshot:C,succeededCalendar:v,succeededNews:$},ts:(new Date).toISOString()},E=await f({target:e,payload:O});return await t.rm(d,{recursive:!0,force:!0}).catch(()=>{}),{ok:P,summary:P?"Codex gateway macro chain OK":x(g||w,"Codex gateway macro chain failed"),detail:g||w||y,logPath:E,result:O}}catch(r){c.write("exec_exception",{error:r instanceof Error?r.message:String(r)});const s=await c.flush().catch(()=>""),n=r instanceof Error?r.message:String(r),i=await f({target:e,payload:{target:e,ok:!1,summary:"Codex gateway macro chain failed",contextFilePath:p(),tracePath:s,error:n,ts:(new Date).toISOString()}});return await t.rm(d,{recursive:!0,force:!0}).catch(()=>{}),{ok:!1,summary:x(n,"Codex gateway macro chain failed"),detail:n,logPath:i}}}await w();const c=O(r());let d,l=null;try{d=await A({command:c.command,args:[...c.args,"--self-test","--test-target",e],cwd:r()}),"gateway"===e&&(l=await(async({command:t,args:e,cwd:r,timeoutMs:s=2500})=>new Promise((n,o)=>{const a=i(t,e,{cwd:r,stdio:["ignore","pipe","pipe"],windowsHide:!0,env:{...process.env,NO_COLOR:"1",FORCE_COLOR:"0",CLICOLOR:"0"}}),c=[],d=[];let l=!1;const u=t=>{l||(l=!0,n(t))};a.stdout.on("data",t=>c.push(Buffer.from(t))),a.stderr.on("data",t=>d.push(Buffer.from(t))),a.on("error",t=>{l||(l=!0,o(t))}),a.on("close",t=>{u({ok:!1,exitCode:Number.isFinite(t)?Number(t):1,stdout:Buffer.concat(c).toString("utf8"),stderr:Buffer.concat(d).toString("utf8"),responseText:""})}),setTimeout(()=>{const t=a.stdin;t?.write(`${JSON.stringify({jsonrpc:"2.0",id:1,method:"initialize",params:{protocolVersion:"2024-11-05",capabilities:{},clientInfo:{name:"weget-gateway-probe",version:"0.1.0"}}})}\n`)},150),setTimeout(()=>{if(l)return;const t=Buffer.concat(c).toString("utf8"),e=Buffer.concat(d).toString("utf8"),r=t.trim(),s=/"result"\s*:/.test(r)&&/"protocolVersion"\s*:/.test(r);a.kill(),u({ok:s,exitCode:null,stdout:t,stderr:e,responseText:r})},Math.max(250,s))}))({command:c.command,args:c.args,cwd:r()}))}catch(t){const r=t instanceof Error?t.message:String(t),s=await f({target:e,payload:{target:e,launch:c,contextFilePath:p(),failure:"spawn_exception",error:r,ts:(new Date).toISOString()}});return{ok:!1,summary:x(r,`${e} test failed`),detail:r,logPath:s}}const u=String(d.stdout||d.stderr||"").trim();let g;if(u)try{g=JSON.parse(u)}catch{}let y=0===d.exitCode&&Boolean(!g||!1!==g.ok),h=x(u,`${e} self-test completed`);"gateway"===e&&l&&!l.ok?(y=!1,h=x(l.stderr||l.stdout,"Gateway handshake probe failed.")):"gateway"===e&&l?.ok&&(h="Gateway MCP handshake OK");const S={target:e,ok:y,summary:h,launch:c,contextFilePath:p(),selfTest:{exitCode:d.exitCode,stdout:d.stdout,stderr:d.stderr,result:g??null},handshakeProbe:l?{ok:l.ok,exitCode:l.exitCode,stdout:l.stdout,stderr:l.stderr,responseText:l.responseText}:null,ts:(new Date).toISOString()};return{ok:y,summary:h,detail:u||h,logPath:await f({target:e,payload:S}),result:g}}}};
|