@ai.weget.jp/bot 0.1.20 → 0.1.21

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.
package/dist/src/main.js CHANGED
@@ -1 +1 @@
1
- import t from"node:path";import e from"node:fs/promises";import{existsSync as a}from"node:fs";import{fileURLToPath as i}from"node:url";import{createRequire as s}from"node:module";import{SYSTEM_CONFIG as r}from"./config/systemConfig.js";import{BotWsClient as n}from"./wsClient.js";import{registerIpcHandlers as o}from"./ipc/registerHandlers.js";import{createAuthApiService as l}from"./services/authApiService.js";import{createCodexService as c}from"./services/codexService.js";import{createGatewayFileBridgeService as d}from"./services/gatewayFileBridgeService.js";import{createPlatformApiClient as g}from"./platformApi.js";import{createSkillRuntimeManager as m}from"./skillRuntimeManager.js";import{parseTaskDirective as u,stripWegetControlBlocks as p}from"./services/taskDirective.js";import{createWindowManager as y}from"./services/windowManagerService.js";import{createSkillHostState as S}from"./skillHostState.js";const k=s(import.meta.url),{app:f,BrowserWindow:w,ipcMain:_,nativeImage:b}=k("electron"),v=i(import.meta.url),h=t.dirname(v),x=["trade","ai"],A=()=>t.join(f.getPath("userData"),"login-profile.json"),I=()=>t.join(f.getPath("userData"),"host-config.json"),C=()=>t.join(f.getPath("userData"),"skill-states.json");let O=null,E=null,P={aiModel:"gpt-5.4",logOutputDir:""};const M=new Map;let j=()=>t.join(f.getPath("documents"),"weget-bot-logs");const D=t=>{const e=String(t||"").toLowerCase();return e.includes("debug")||e.includes("[debug]")?"debug":e.includes("error")||e.includes("failed")||e.includes("exception")?"error":"info"},T=async({level:a,source:i,message:s,details:r,ts:n})=>{const o=j();await e.mkdir(o,{recursive:!0});const l=new Date,c=l.getFullYear(),d=String(l.getMonth()+1).padStart(2,"0"),g=String(l.getDate()).padStart(2,"0"),m=t.join(o,`${a}-${c}${d}${g}.log`),u=JSON.stringify({ts:n||l.toISOString(),level:a,source:i,message:s,details:r??null},null,0);await e.appendFile(m,`${u}\n`,"utf8")},B=y({BrowserWindow:w,preloadPath:t.join(h,"preload.cjs"),rendererDir:t.join(h,"renderer"),windowIconPath:t.join(h,"renderer","logo.png")}),L=(t,e)=>{const a=(new Date).toISOString();B.emitBotLog({message:t,data:e||null,ts:a}),T({level:D(t),source:"runtime",message:t,details:e,ts:a}).catch(()=>{})},U=t=>{B.emitChatEvent(t)},R=t=>({taskId:t.taskId,title:t.title,prompt:t.prompt,status:t.status,source:t.source,channel:t.channel,lineUserId:t.lineUserId,conversationId:t.conversationId,startedAt:t.startedAt,lastProgressAt:t.lastProgressAt,canCancel:!t.cancelled}),q=()=>{B.emitTaskRuntime({type:"snapshot",tasks:Array.from(M.values()).map(R)})},N=(t,e)=>{const a=M.get(t);if(!a)return;const i={...a,...e,taskId:t,abortController:e.abortController||a.abortController,lastProgressAt:e.lastProgressAt||(new Date).toISOString()};M.set(t,i),B.emitTaskRuntime({type:"upsert",task:R(i)})},F=t=>{M.has(t)&&(M.delete(t),B.emitTaskRuntime({type:"remove",taskId:t}))},G=(t,e)=>({summary:t?.cancelReason||e,data_json:{reason:t?.cancelReason||e,requested_by_task_id:t?.cancelRequestedByTaskId||null,requested_by_action:t?.cancelRequestedByAction||null,ts:(new Date).toISOString()}}),K=async({taskId:t,directive:e,promptBundle:a})=>{const i=$(a.arbitration_context),s=$(i.active_task),r=String(e.targetTaskId||s.task_id||"").trim();if("cancel_running_task"===e.action){const a=await(async({taskId:t,reason:e,requestedByTaskId:a,requestedByAction:i})=>{const s=String(t||"").trim();if(!s)return{ok:!1,mode:"invalid",error:"task_id is required"};const r=M.get(s);if(r)return r.cancelled=!0,r.cancelReason=e,r.cancelRequestedByTaskId=a,r.cancelRequestedByAction=i,r.abortController.abort(),N(s,{status:"Cancelling..."}),L("[task] cancellation requested",{task_id:s,mode:"local",reason:e,requested_by_task_id:a||"",requested_by_action:i||""}),{ok:!0,mode:"local"};try{return await z.request({method:"POST",path:"/bot/tasks/cancel",body:{task_id:s}}),L("[task] cancellation requested",{task_id:s,mode:"platform",reason:e,requested_by_task_id:a||"",requested_by_action:i||""}),{ok:!0,mode:"platform"}}catch(t){return{ok:!1,mode:"platform",error:t instanceof Error?t.message:String(t)}}})({taskId:r,reason:e.reason||"arbitration_cancelled",requestedByTaskId:t,requestedByAction:e.action});return E?.sendTaskEvent(t,"task_control_action",{action:e.action,target_task_id:r||null,ok:a.ok,mode:a.mode,error:"error"in a?a.error:null,ts:(new Date).toISOString()}),a}return E?.sendTaskEvent(t,"task_control_action",{action:e.action,target_task_id:r||null,ok:!0,mode:"advisory",ts:(new Date).toISOString()}),{ok:!0,mode:"advisory"}},$=t=>t&&"object"==typeof t?t:{},W=S({log:L}),J=l({getEnv:()=>({loginApiUrl:r.loginApiUrl,botUploadApiUrl:r.botUploadApiUrl}),emitLog:L,getCurrentSession:()=>O}),z=g({getBaseUrl:()=>String(r.loginApiUrl||"").trim().replace(/\/login\/?$/i,""),getSession:()=>O,log:L}),H=async t=>{const e=(()=>{const t=String(r.loginApiUrl||"").trim();return t?t.replace(/\/login\/?$/i,"/bot/runtime/line-reply"):""})();if(!e)throw new Error("runtime line reply api url is missing");return J.callBotApi(e,t)},Q=m({installRoot:t.join(f.getPath("userData"),"skills"),botId:()=>String(O?.botId||"").trim()||void 0,log:L,api:z,getRuntimeConfig:()=>({cryptoApiBaseUrl:r.gmoCryptoPrivateApiBaseUrl,fxApiBaseUrl:r.gmoFxPrivateApiBaseUrl,coinPublicBaseUrl:r.gmoCryptoPublicApiBaseUrl,fxPublicBaseUrl:r.gmoFxPublicApiBaseUrl,assetsPath:r.gmoAssetsPath,fxAssetsPath:r.gmoFxAssetsPath,coinMarginPath:r.gmoCoinMarginPath,positionsPath:r.gmoPositionsPath,positionSummaryPath:r.gmoPositionSummaryPath,fxOrderPath:r.gmoFxOrderPath,coinCloseOrderPath:r.gmoCoinCloseOrderPath,fxCloseOrderPath:r.gmoFxCloseOrderPath}),emitSkillEvent:(t,e)=>{if("trade_execution"!==e.type){if("trade_history"===e.type){const a=`trade-${Date.now()}`;E?.sendTaskEvent(a,"trade_history",{package_name:t,...e.payload&&"object"==typeof e.payload?e.payload:{}}),L("[trade] history event sent (execution)",{package_name:t,payload:e.payload})}}else B.emitTradeExecution(e.payload)}}),X=()=>{const t=Q.getLoadedSkill("@ai.weget.jp/skill-gmo-fx")?.runtime;if(!t)throw new Error("GMO FX skill runtime is not installed");return t},Y=()=>{const t=Q.getLoadedSkill("@ai.weget.jp/skill-gmo-coin")?.runtime;if(!t)throw new Error("GMO Coin skill runtime is not installed");return t},V=()=>Q.getLoadedSkill("@ai.weget.jp/skill-gmo-fx")?.runtime,Z=()=>Q.getLoadedSkill("@ai.weget.jp/skill-gmo-coin")?.runtime,tt=()=>{const t=Q.getLoadedSkill("@ai.weget.jp/skill-macro-economy")?.runtime;if(!t)throw new Error("Macro Economy skill runtime is not installed");return t},et=()=>Q.getLoadedSkill("@ai.weget.jp/skill-macro-economy")?.runtime,at=({isLineTask:t,status:e})=>{const a=String(e||"").trim();return a?t?`LINE task: ${a}`:a:""},it=(t,e)=>{const a=t.gateway[e];if("function"!=typeof a)throw new Error(`skill runtime does not implement gateway.${e}`);return a},st=t=>{const e=$(t);return{riskDailyLossLimitJpy:Number(e.riskDailyLossLimitJpy||0),fxApiKey:String(e.fxApiKey||"").trim(),fxApiSecret:String(e.fxApiSecret||"").trim(),aiModel:String(e.aiModel||"").trim()||"gpt-5.4"}},rt=t=>{const e=$(t);return{riskDailyLossLimitJpy:Number(e.riskDailyLossLimitJpy||0),cryptoApiKey:String(e.cryptoApiKey||"").trim(),cryptoApiSecret:String(e.cryptoApiSecret||"").trim(),aiModel:String(e.aiModel||"").trim()||"gpt-5.4"}};j=()=>String(P.logOutputDir||"").trim()||t.join(f.getPath("documents"),"weget-bot-logs");const nt=c({getModel:()=>{const t=V(),e=Z();return P.aiModel||t?.getConfig?.().aiModel||e?.getConfig?.().aiModel||"gpt-5.4"},getWorkingDir:()=>f.getPath("userData"),getLogDir:()=>j(),emitLog:L,getGatewayContext:()=>({activeSkills:W.getManagedSkills().filter(t=>t.enabled).map(t=>({name:t.name,displayName:t.displayName,version:t.version,tools:t.tools})),hostMetadata:{aiModel:P.aiModel||"gpt-5.4",capabilities:x,userDataPath:f.getPath("userData"),platform:process.platform,gmoCoinPublicBaseUrl:r.gmoCryptoPublicApiBaseUrl,gmoFxPublicBaseUrl:r.gmoFxPublicApiBaseUrl},botId:String(O?.botId||"").trim(),platformApiBaseUrl:String(r.loginApiUrl||"").trim().replace(/\/login\/?$/i,""),accessToken:String(O?.accessToken||"").trim(),fileBridgeDir:String(yt.getContext()?.dir||"").trim(),fileBridgeToken:String(yt.getContext()?.token||"").trim()})}),ot=async t=>{const a=$(t);return P={aiModel:String(a.aiModel||P.aiModel||"gpt-5.4").trim()||"gpt-5.4",logOutputDir:String(a.logOutputDir||"").trim()},await e.writeFile(I(),JSON.stringify({...P,updatedAt:(new Date).toISOString()},null,2),"utf8"),P};const lt=async()=>{const t=await Q.refreshLoadedSkills();return W.setAvailableSkills(t.map(t=>t.manifest)),t},ct=async t=>{const e=await lt();L("[skills] reconciled bundled skills",{desired:t.map(t=>({package_name:t.package_name,install_status:t.install_status,enabled:t.enabled,version:t.version})),bundled:e.map(t=>({package_name:t.packageName,version:t.version}))})},dt=()=>{const t=W.isSkillEnabled("@ai.weget.jp/skill-gmo-fx"),e=W.isSkillEnabled("@ai.weget.jp/skill-gmo-coin"),a=V(),i=Z();a&&("connected"===E?.getStatus()&&t?a.startExecutionStreams():a.stopExecutionStreams()),i&&("connected"===E?.getStatus()&&e?i.startExecutionStreams():i.stopExecutionStreams()),L("[skills] applied managed states",{active_skills:W.getActiveSkills().map(t=>t.name)})},gt=async()=>{const t=J.getBotRuntimeConfigApiUrl(),e=String(O?.botId||"").trim();if(!t||!e)return;const a=await J.callBotApi(t,{bot_id:e}),i=String(a.chat_model||"").trim(),s={...i?{aiModel:i}:{}};if(0===Object.keys(s).length)return;await ot({...P,...s});const r=V(),n=Z();r&&await r.saveConfig({...r.getConfig(),...s}),n&&await n.saveConfig({...n.getConfig(),...s}),L("[config] runtime config synced",{chat_model:i||""})},mt=async()=>{const t=J.getBotSkillsListApiUrl(),a=String(O?.botId||"").trim();if(!t||!a)return;const i=await J.callBotApi(t,{bot_id:a}),s=Array.isArray(i.states)?i.states.filter(t=>Boolean(t&&"object"==typeof t)).map(t=>({user_id:String(t.user_id||""),bot_id:String(t.bot_id||""),skill_id:String(t.skill_id||""),package_name:String(t.package_name||""),enabled:Boolean(t.enabled),install_status:String(t.install_status||""),version:t.version?String(t.version):null,config_json:$(t.config_json),created_at:t.created_at?String(t.created_at):void 0,updated_at:t.updated_at?String(t.updated_at):void 0})):[];W.applySnapshots(s),await(async t=>{await e.writeFile(C(),JSON.stringify({updatedAt:(new Date).toISOString(),items:t},null,2),"utf8")})(s),await ct(s),dt(),L("[config] skill states synced",{count:s.length,bot_id:a,enabled:s.filter(t=>t.enabled).length})},ut=t=>{if("fx"===t&&!W.isSkillEnabled("@ai.weget.jp/skill-gmo-fx"))throw new Error("GMO FX skill is disabled");if("coin"===t&&!W.isSkillEnabled("@ai.weget.jp/skill-gmo-coin"))throw new Error("GMO Coin skill is disabled")},pt=()=>{if(!W.isSkillEnabled("@ai.weget.jp/skill-macro-economy"))throw new Error("Macro Economy skill is disabled")},yt=d({getMacroSnapshot:async({force:t}={})=>(pt(),tt().getSnapshot({force:t})),getMacroCalendar:async({dateKey:t})=>(pt(),tt().listCalendar({dateKey:t})),getMacroNews:async({dateKey:t})=>(pt(),tt().listNews({dateKey:t})),emitLog:L,getWorkingDir:()=>f.getPath("userData")}),St={"@ai.weget.jp/skill-gmo-fx":{getConfig:()=>st(X().getConfig()),saveConfig:async t=>{const e=X(),a=await e.saveConfig({...e.getConfig(),...st(t)});return"connected"===E?.getStatus()&&dt(),st(a)}},"@ai.weget.jp/skill-gmo-coin":{getConfig:()=>rt(Y().getConfig()),saveConfig:async t=>{const e=Y(),a=await e.saveConfig({...e.getConfig(),...rt(t)});return"connected"===E?.getStatus()&&dt(),rt(a)}}},kt=t=>{const e=String(t||"").trim(),a=St[e];if(!a)throw new Error(`skill config is not managed by bot host: ${t}`);return a},ft=async()=>{await Q.ensureInstallRoot(),await lt();const t=await async function(){try{const t=await e.readFile(C(),"utf8"),a=JSON.parse(t);return(Array.isArray(a?.items)?a.items:[]).filter(t=>Boolean(t&&"object"==typeof t)).map(t=>({user_id:String(t.user_id||""),bot_id:String(t.bot_id||""),skill_id:String(t.skill_id||""),package_name:String(t.package_name||""),enabled:Boolean(t.enabled),install_status:String(t.install_status||""),version:t.version?String(t.version):null,config_json:$(t.config_json),created_at:t.created_at?String(t.created_at):void 0,updated_at:t.updated_at?String(t.updated_at):void 0}))}catch(t){if("ENOENT"===t?.code)return[];throw t}}();t.length>0&&(W.applySnapshots(t),L("[skills] restored local snapshot",{count:t.length}),await ct(t)),dt()};E=new n({wsUrl:"wss://ws.weget.jp",taskEventApiUrl:String(r.loginApiUrl||"").trim().replace(/\/login\/?$/i,"/bot/runtime/task-event"),version:"0.2.0",capabilities:x,heartbeatSec:30,reconnectMs:3e3,reconnectMaxAttempts:10,wsPingIntervalSec:25,wsPongTimeoutSec:12},{onLog:(t,e)=>L(t,e),onStatus:t=>{B.emitBotStatus({status:t}),dt()},onLineMessage:async t=>{const e=String(t.line_user_id||""),a=String(t.text||"").trim();if(U({type:"line_user",lineUserId:e,text:a}),!a)return{answer:""};try{const t=await nt.runPrompt({prompt:a,contextLabel:"line_message"});return U({type:"line_assistant",lineUserId:e,text:t}),{answer:t}}catch(t){const a=t instanceof Error?t.message:String(t);L("[ai] line reply failed",{error:a});const i=`AI error: ${a}`;return U({type:"line_assistant",lineUserId:e,text:i}),{answer:i}}},onRunTask:async t=>{const e=String(t.task_id||"").trim(),a=String(t.prompt||"").trim(),i=$(t.metadata_json),s=$(t.prompt_bundle),r=$(t.runtime_config),n=String(i.source||s.source||"").trim(),o=String(i.channel||s.channel||"").trim(),l=String(t.skill_id||i.skill_id||s.skill_id||"").trim(),c=String(i.line_user_id||"").trim(),d=String(i.line_reply_token||"").trim(),g="line"===n||"line"===o||Boolean(c&&d),m="bot_host"===n,y=String(t.model||r.chat_model||"").trim(),S=String(r.system_prompt||s.system_prompt||"").trim();if(!e)return void L("[task] run_task missing task_id");const k=(new Date).toISOString();if(M.set(e,{cancelled:!1,abortController:new AbortController,taskId:e,title:String(t.title||a.slice(0,120)||e).trim(),prompt:a,status:"Task received",source:n||"unknown",channel:o||"",lineUserId:c||void 0,conversationId:String(t.conversation_id||"").trim()||void 0,startedAt:k,lastProgressAt:k}),q(),g&&c&&a&&U({type:"line_user",lineUserId:c,text:a}),E?.sendTaskEvent(e,"task_received",{prompt:a,conversation_id:String(t.conversation_id||""),continue_from_task_id:String(t.continue_from_task_id||""),ts:(new Date).toISOString()}),!a)return E?.sendTaskResult(e,"failed",{error:"prompt is required",data_json:{ts:(new Date).toISOString()}}),void M.delete(e);try{if(m||g){const t=at({isLineTask:g,status:"Task received"});U({type:"assistant_status",status:t}),N(e,{status:t})}l&&E?.sendSkillStatus(e,{skill_id:l,status:"running",summary:"task execution started",data_json:{ts:(new Date).toISOString()}}),E?.sendTaskEvent(e,"step_started",{step:"codex_chat",ts:(new Date).toISOString()});const r=await nt.runPrompt({prompt:a,model:y||void 0,systemPrompt:S||void 0,contextLabel:`task:${e}`,promptBundle:s,metadata:i,onStatus:m||g?t=>{const a=at({isLineTask:g,status:t});U({type:"assistant_status",status:a}),N(e,{status:a})}:void 0,abortSignal:M.get(e)?.abortController.signal}),n=u(r),o=n.pendingRequest,k=n.arbitrationAction,f=n.visibleText||p(r),w=M.get(e);if(w?.cancelled)return E?.sendTaskResult(e,"cancelled",G(w,"server_cancelled")),void F(e);let _=null;if(k&&(_=await K({taskId:e,directive:k,promptBundle:s}),!_.ok&&"cancel_running_task"===k.action))throw new Error("error"in _&&_.error||"failed to cancel running task");if(E?.sendTaskEvent(e,"ai_output",{summary:f,action:k?.action||null,ts:(new Date).toISOString()}),m&&U({type:"assistant",text:f}),g&&c&&d){U({type:"line_assistant",lineUserId:c,text:f});const a={bot_id:String(t.bot_id||O?.botId||""),line_user_id:c,line_reply_token:d,text:f};try{await H(a)}catch(t){L("[line] callback line reply failed",{error:t instanceof Error?t.message:String(t)})}E?.sendTaskEvent(e,"line_message_ai_output",{line_user_id:c,answer:f,ts:(new Date).toISOString()})}if(E?.sendTaskEvent(e,"step_finished",{step:"codex_chat",action:k?.action||null,ts:(new Date).toISOString()}),o)return"approval"===o.requestType?E?.requestTaskApproval(e,{prompt:o.prompt,approval_type:o.subtype||"generic",data_json:{prompt:o.prompt,approval_type:o.subtype||"generic",ts:(new Date).toISOString()}}):E?.requestTaskInput(e,{prompt:o.prompt,input_type:o.subtype||"text",data_json:{prompt:o.prompt,input_type:o.subtype||"text",ts:(new Date).toISOString()}}),l&&E?.sendSkillStatus(e,{skill_id:l,status:"approval"===o.requestType?"waiting_approval":"waiting_input",summary:o.prompt.slice(0,200),data_json:{ts:(new Date).toISOString(),request_type:o.requestType}}),void F(e);E?.sendTaskResult(e,"succeeded",{summary:f.slice(0,500),data_json:{ts:(new Date).toISOString(),action:k?.action||null,target_task_id:k?.targetTaskId||null,action_reason:k?.reason||null,action_mode:_?.mode||null}}),l&&E?.sendSkillStatus(e,{skill_id:l,status:"succeeded",summary:f.slice(0,200),data_json:{ts:(new Date).toISOString()}})}catch(a){if(m){const t=`Error: ${a instanceof Error?a.message:String(a)}`;U({type:"assistant",text:t})}const i=M.get(e);if(i?.cancelled)return E?.sendTaskResult(e,"cancelled",G(i,"server_cancelled")),void F(e);if(g&&c&&d){const e=`AI error: ${a instanceof Error?a.message:String(a)}`;U({type:"line_assistant",lineUserId:c,text:e});const i={bot_id:String(t.bot_id||O?.botId||""),line_user_id:c,line_reply_token:d,text:e};try{await H(i)}catch(t){L("[line] callback line reply failed",{error:t instanceof Error?t.message:String(t)})}}E?.sendTaskResult(e,"failed",{error:a instanceof Error?a.message:String(a),data_json:{ts:(new Date).toISOString()}}),l&&E?.sendSkillStatus(e,{skill_id:l,status:"failed",summary:a instanceof Error?a.message:String(a),data_json:{ts:(new Date).toISOString()}})}finally{F(e)}},onTaskControl:async t=>{const e=String(t.task_id||"").trim(),a=String(t.action||"").trim();if(e&&a&&"cancel_task"===a){const a=M.get(e);if(a){a.cancelled=!0,a.cancelReason="server_cancelled",a.cancelRequestedByAction="cancel_task",a.abortController.abort();const i=String(t.skill_id||"").trim();return i&&E?.sendSkillStatus(e,{skill_id:i,status:"cancelled",summary:"server_cancelled",data_json:{ts:(new Date).toISOString()}}),void L("[task] cancel requested",{task_id:e})}E?.sendTaskResult(e,"cancelled",G(void 0,"server_cancelled"))}},onServerConfigUpdate:async t=>{const e=Array.isArray(t.scopes)?t.scopes.map(t=>String(t||"").trim()):[],a=e.length>0?e:["runtime","skills"];a.includes("runtime")&&await gt(),a.includes("skills")&&await mt()}}),o({ipcMain:_,env:{capabilities:x,loginApiUrl:r.loginApiUrl},signInWithLoginApi:J.signInWithLoginApi,saveLoginProfile:async({botId:t,email:a,password:i,remember:s})=>{if(s)await e.writeFile(A(),JSON.stringify({botId:t,email:a,password:i,remember:!0,updatedAt:(new Date).toISOString()},null,2),"utf8");else try{await e.unlink(A())}catch(t){if("ENOENT"!==t?.code)throw t}},readSavedLoginProfile:async()=>{try{const t=await e.readFile(A(),"utf8"),a=JSON.parse(t);return{botId:String(a?.botId||""),email:String(a?.email||""),password:String(a?.password||""),remember:Boolean(a?.remember)}}catch(t){if("ENOENT"===t?.code)return{botId:"",email:"",password:"",remember:!1};throw t}},getSkillConfig:t=>({config:kt(t).getConfig()}),saveSkillConfig:async(t,e)=>({config:await kt(t).saveConfig(e)}),getAiConfig:()=>({aiModel:String(P.aiModel||"gpt-5.4"),logOutputDir:String(P.logOutputDir||"")}),saveAiConfig:async t=>{const e=t&&"object"==typeof t?t:{},a=await ot({...P,...e}),i=V(),s=Z(),r=i?await i.saveConfig({...i.getConfig(),...e}):null;return s&&await s.saveConfig({...s.getConfig(),...e}),{aiModel:String(a.aiModel||r?.aiModel||e.aiModel||"gpt-5.4"),logOutputDir:String(a.logOutputDir||"")}},setCurrentSession:t=>{O=t||null;const e=O?"connected":"disconnected";B.emitBotStatus({status:e})},getCurrentSession:()=>O,getActiveSkills:()=>W.getActiveSkills().map(t=>({name:t.name,displayName:t.displayName,version:t.version})),getCodexAuthStatus:()=>nt.getAuthStatus(),getCodexMcpStatus:t=>nt.getMcpServerStatus(t),getPlaywrightBrowserStatus:()=>nt.getPlaywrightBrowserStatus(),startCodexLogin:()=>nt.startLogin(),installPlaywrightMcp:()=>nt.installWegetGatewayMcp(),getGatewayContextFilePath:()=>nt.getGatewayContextFilePath(),runGatewaySelfTest:t=>nt.runGatewaySelfTest(t),getManagedSkills:()=>W.getManagedSkills().map(t=>({...t,ui:Q.getLoadedSkill(t.name)?.ui||void 0})),getMacroSnapshot:async({force:t}={})=>(pt(),tt().getSnapshot({force:t})),getMacroCalendar:async({dateKey:t})=>(pt(),tt().listCalendar({dateKey:t})),getMacroNews:async({dateKey:t})=>(pt(),tt().listNews({dateKey:t})),emitLog:L,openGmoKlineWindow:async({symbol:t,interval:e,market:a})=>(()=>{const i="fx"===a?"fx":"coin";return ut(i),("fx"===i?X().marketData:Y().marketData).fetchKline({symbol:t,interval:e,market:i})})(),getGmoMarketQuotes:async({market:t,symbols:e})=>(()=>{const a="fx"===t?"fx":"coin";return ut(a),("fx"===a?X().marketData:Y().marketData).fetchQuotes({market:a,symbols:e})})(),getGmoSymbolRules:async({market:t})=>(()=>{const e="fx"===t?"fx":"coin";return ut(e),("fx"===e?X().marketData:Y().marketData).fetchSymbolRules({market:e})})(),getGmoBuyingPower:async({market:t})=>({market:t,availableJpy:await(ut(t),("fx"===t?X().gateway:Y().gateway).getBuyingPower(t))}),getGmoAccountMetrics:async({market:t})=>(ut(t),("fx"===t?X().gateway:Y().gateway).getAccountMetrics(t)),getGmoPositionSummary:async({market:t,symbol:e})=>({market:t,symbol:e,items:await(ut(t),("fx"===t?X().gateway:Y().gateway).getPositionSummary({market:t,symbol:e}))}),getGmoOpenPositions:async({market:t,symbol:e,page:a,prevId:i,count:s})=>({market:t,symbol:e||"",items:await(ut(t),("fx"===t?X().gateway:Y().gateway).getOpenPositions({market:"fx"===t?"fx":"crypto",symbol:e||void 0,page:a,prevId:i,count:s}))}),placeGmoFxOrder:async({symbol:t,side:e,size:a})=>{ut("fx");return await it(X(),"placeFxOrder")({symbol:t,side:e,size:a,executionType:"MARKET"})},placeGmoCoinOrder:async({symbol:t,side:e,size:a})=>{ut("coin");return await it(Y(),"placeCoinOrder")({symbol:t,side:e,size:a,executionType:"MARKET"})},placeGmoFxCloseOrder:async({symbol:t,side:e,positionId:a,size:i})=>{ut("fx");return await it(X(),"placeFxCloseOrder")({symbol:t,side:e,positionId:a,size:i,executionType:"MARKET"})},placeGmoCoinCloseOrder:async({symbol:t,side:e,positionId:a,size:i})=>{ut("coin");return await it(Y(),"placeCoinCloseOrder")({symbol:t,side:e,positionId:a,size:i,executionType:"MARKET"})},getGmoApiState:t=>{const e="fx"===t?V():Z();return e?.status.getApiState()||"unknown"},testGmoApi:t=>(ut(t),"fx"===t?X().status.testApi():Y().status.testApi()),buildTradeStatusSnapshot:t=>(ut(t),"fx"===t?X().status.buildSnapshot():Y().status.buildSnapshot()),closeTradeWindows:()=>{},startWsClient:t=>{E?.start(t),gt().catch(t=>{L("[config] runtime sync failed after login",{error:t instanceof Error?t.message:String(t)})}),mt().catch(t=>{L("[config] skill sync failed after login",{error:t instanceof Error?t.message:String(t)})}),dt()},stopWsClient:()=>{V()?.stopExecutionStreams(),Z()?.stopExecutionStreams(),et()?.stop?.(),E?.stop(),q()},handleBotChatMessage:async({text:t})=>{const e=String(t||"").trim(),a=String(O?.botId||"").trim();if(!e)throw new Error("message is required");if(!a)throw new Error("bot session is not ready");U({type:"assistant_status",status:"Submitting task"});const i=await z.request({method:"POST",path:"/bot/tasks",body:{source:"bot_host",bot_id:a,prompt:e,title:e.slice(0,80),channel:"desktop",metadata_json:{source:"bot_host",channel:"desktop"}}}),s=$(i.dispatch_result);if(!1===s.delivered)throw new Error(`task queued but bot is offline (${String(s.status||"offline")})`);return{answer:"",taskId:String($(i.task).task_id||"")}},getActiveTaskRuntimes:()=>Array.from(M.values()).map(R),cancelActiveTaskRuntime:async t=>{const e=M.get(String(t||"").trim());return e?(e.cancelled=!0,e.cancelReason="local_cancelled",e.cancelRequestedByAction="cancel_task",e.abortController.abort(),N(e.taskId,{status:"Cancelling..."}),L("[task] local cancel requested",{task_id:e.taskId}),{ok:!0}):{ok:!1,error:"task not found"}},writeErrorLog:async({source:t,message:e,details:a})=>{await(async({source:t,message:e,details:a})=>{await T({level:"error",source:t,message:e,details:a})})({source:t,message:e,details:a})},writeRuntimeLog:async({level:t,source:e,message:a,details:i})=>{await T({level:t,source:e,message:a,details:i})}});const wt=t.join(h,"renderer","logo.png");f.whenReady().then(async()=>{(()=>{if("darwin"!==process.platform)return;if(!a(wt))return;const t=b.createFromPath(wt);t.isEmpty()||f.dock.setIcon(t)})(),await(async()=>{try{const t=await e.readFile(I(),"utf8"),a=JSON.parse(t);P={aiModel:String(a?.aiModel||"gpt-5.4").trim()||"gpt-5.4",logOutputDir:String(a?.logOutputDir||"").trim()}}catch(t){if("ENOENT"!==t?.code)throw t;P={aiModel:"gpt-5.4",logOutputDir:""}}return P})();try{await yt.ensureStarted()}catch(t){L("[gateway-file-bridge] startup failed",{error:t instanceof Error?t.message:String(t)})}try{await ft()}catch(t){L("[skills] local initialization failed",{error:t instanceof Error?t.message:String(t)})}B.createMainWindow(),q(),f.on("activate",()=>{0===w.getAllWindows().length&&(B.createMainWindow(),q())})}),f.on("window-all-closed",()=>{V()?.stopExecutionStreams(),Z()?.stopExecutionStreams(),et()?.stop?.(),yt.stop().catch(()=>{}),E?.stop(),"darwin"!==process.platform&&f.quit()});
1
+ import t from"node:path";import e from"node:fs/promises";import{existsSync as a}from"node:fs";import{fileURLToPath as i}from"node:url";import{createRequire as r}from"node:module";import{SYSTEM_CONFIG as s}from"./config/systemConfig.js";import{BotWsClient as n}from"./wsClient.js";import{registerIpcHandlers as o}from"./ipc/registerHandlers.js";import{createAuthApiService as l}from"./services/authApiService.js";import{createCodexService as c}from"./services/codexService.js";import{createGatewayFileBridgeService as d}from"./services/gatewayFileBridgeService.js";import{createPlatformApiClient as g}from"./platformApi.js";import{createSkillRuntimeManager as m}from"./skillRuntimeManager.js";import{parseTaskDirective as u,stripWegetControlBlocks as p}from"./services/taskDirective.js";import{createWindowManager as k}from"./services/windowManagerService.js";import{createSkillHostState as y}from"./skillHostState.js";const S=r(import.meta.url),{app:f,BrowserWindow:_,ipcMain:w,nativeImage:b}=S("electron"),v=i(import.meta.url),h=t.dirname(v),I=["trade","ai"],x=()=>t.join(f.getPath("userData"),"login-profile.json"),A=()=>t.join(f.getPath("userData"),"host-config.json"),C=()=>t.join(f.getPath("userData"),"skill-states.json");let O=null,E=null,P={aiModel:"gpt-5.4",logOutputDir:""};const M=new Map;let j=()=>t.join(f.getPath("documents"),"weget-bot-logs");const T=t=>{const e=String(t||"").toLowerCase();return e.includes("debug")||e.includes("[debug]")?"debug":e.includes("error")||e.includes("failed")||e.includes("exception")?"error":"info"},D=async({level:a,source:i,message:r,details:s,ts:n})=>{const o=j();await e.mkdir(o,{recursive:!0});const l=new Date,c=l.getFullYear(),d=String(l.getMonth()+1).padStart(2,"0"),g=String(l.getDate()).padStart(2,"0"),m=t.join(o,`${a}-${c}${d}${g}.log`),u=JSON.stringify({ts:n||l.toISOString(),level:a,source:i,message:r,details:s??null},null,0);await e.appendFile(m,`${u}\n`,"utf8")},B=k({BrowserWindow:_,preloadPath:t.join(h,"preload.cjs"),rendererDir:t.join(h,"renderer"),windowIconPath:t.join(h,"renderer","logo.png")}),q=(t,e)=>{const a=(new Date).toISOString();B.emitBotLog({message:t,data:e||null,ts:a}),D({level:T(t),source:"runtime",message:t,details:e,ts:a}).catch(()=>{})},L=t=>{B.emitChatEvent(t)},U=t=>({taskId:t.taskId,title:t.title,prompt:t.prompt,status:t.status,source:t.source,channel:t.channel,lineUserId:t.lineUserId,conversationId:t.conversationId,startedAt:t.startedAt,lastProgressAt:t.lastProgressAt,canCancel:!t.cancelled}),R=()=>{B.emitTaskRuntime({type:"snapshot",tasks:Array.from(M.values()).map(U)})},N=(t,e)=>{const a=M.get(t);if(!a)return;const i={...a,...e,taskId:t,abortController:e.abortController||a.abortController,lastProgressAt:e.lastProgressAt||(new Date).toISOString()};M.set(t,i),B.emitTaskRuntime({type:"upsert",task:U(i)})},F=t=>{M.has(t)&&(M.delete(t),B.emitTaskRuntime({type:"remove",taskId:t}))},G=(t,e)=>({summary:t?.cancelReason||e,data_json:{reason:t?.cancelReason||e,requested_by_task_id:t?.cancelRequestedByTaskId||null,requested_by_action:t?.cancelRequestedByAction||null,ts:(new Date).toISOString()}}),K=async({taskId:t,directive:e,promptBundle:a})=>{const i=$(a.arbitration_context),r=$(i.active_task),s=String(e.targetTaskId||r.task_id||"").trim();if("cancel_running_task"===e.action){const a=await(async({taskId:t,reason:e,requestedByTaskId:a,requestedByAction:i})=>{const r=String(t||"").trim();if(!r)return{ok:!1,mode:"invalid",error:"task_id is required"};const s=M.get(r);if(s)return s.cancelled=!0,s.cancelReason=e,s.cancelRequestedByTaskId=a,s.cancelRequestedByAction=i,s.abortController.abort(),N(r,{status:"Cancelling..."}),q("[task] cancellation requested",{task_id:r,mode:"local",reason:e,requested_by_task_id:a||"",requested_by_action:i||""}),{ok:!0,mode:"local"};try{return await z.request({method:"POST",path:"/bot/tasks/cancel",body:{task_id:r}}),q("[task] cancellation requested",{task_id:r,mode:"platform",reason:e,requested_by_task_id:a||"",requested_by_action:i||""}),{ok:!0,mode:"platform"}}catch(t){return{ok:!1,mode:"platform",error:t instanceof Error?t.message:String(t)}}})({taskId:s,reason:e.reason||"arbitration_cancelled",requestedByTaskId:t,requestedByAction:e.action});return E?.sendTaskEvent(t,"task_control_action",{action:e.action,target_task_id:s||null,ok:a.ok,mode:a.mode,error:"error"in a?a.error:null,ts:(new Date).toISOString()}),a}return E?.sendTaskEvent(t,"task_control_action",{action:e.action,target_task_id:s||null,ok:!0,mode:"advisory",ts:(new Date).toISOString()}),{ok:!0,mode:"advisory"}},$=t=>t&&"object"==typeof t?t:{},W=y({log:q}),J=l({getEnv:()=>({loginApiUrl:s.loginApiUrl,botUploadApiUrl:s.botUploadApiUrl}),emitLog:q,getCurrentSession:()=>O}),z=g({getBaseUrl:()=>String(s.loginApiUrl||"").trim().replace(/\/login\/?$/i,""),getSession:()=>O,log:q}),H=async t=>{const e=(()=>{const t=String(s.loginApiUrl||"").trim();return t?t.replace(/\/login\/?$/i,"/bot/runtime/line-reply"):""})();if(!e)throw new Error("runtime line reply api url is missing");return J.callBotApi(e,t)},Q=m({installRoot:t.join(f.getPath("userData"),"skills"),botId:()=>String(O?.botId||"").trim()||void 0,log:q,api:z,getRuntimeConfig:()=>({cryptoApiBaseUrl:s.gmoCryptoPrivateApiBaseUrl,fxApiBaseUrl:s.gmoFxPrivateApiBaseUrl,coinPublicBaseUrl:s.gmoCryptoPublicApiBaseUrl,fxPublicBaseUrl:s.gmoFxPublicApiBaseUrl,assetsPath:s.gmoAssetsPath,fxAssetsPath:s.gmoFxAssetsPath,coinMarginPath:s.gmoCoinMarginPath,positionsPath:s.gmoPositionsPath,positionSummaryPath:s.gmoPositionSummaryPath,fxOrderPath:s.gmoFxOrderPath,coinCloseOrderPath:s.gmoCoinCloseOrderPath,fxCloseOrderPath:s.gmoFxCloseOrderPath}),emitSkillEvent:(t,e)=>{if("trade_execution"!==e.type){if("trade_history"===e.type){const a=`trade-${Date.now()}`;E?.sendTaskEvent(a,"trade_history",{package_name:t,...e.payload&&"object"==typeof e.payload?e.payload:{}}),q("[trade] history event sent (execution)",{package_name:t,payload:e.payload})}}else B.emitTradeExecution(e.payload)}}),X=()=>{const t=Q.getLoadedSkill("@ai.weget.jp/skill-gmo-fx")?.runtime;if(!t)throw new Error("GMO FX skill runtime is not installed");return t},Y=()=>{const t=Q.getLoadedSkill("@ai.weget.jp/skill-gmo-coin")?.runtime;if(!t)throw new Error("GMO Coin skill runtime is not installed");return t},V=()=>Q.getLoadedSkill("@ai.weget.jp/skill-gmo-fx")?.runtime,Z=()=>Q.getLoadedSkill("@ai.weget.jp/skill-gmo-coin")?.runtime,tt=()=>{const t=Q.getLoadedSkill("@ai.weget.jp/skill-macro-economy")?.runtime;if(!t)throw new Error("Macro Economy skill runtime is not installed");return t},et=()=>Q.getLoadedSkill("@ai.weget.jp/skill-macro-economy")?.runtime,at=({isLineTask:t,status:e})=>{const a=String(e||"").trim();return a?t?`LINE task: ${a}`:a:""},it=(t,e)=>{const a=t.gateway[e];if("function"!=typeof a)throw new Error(`skill runtime does not implement gateway.${e}`);return a},rt=t=>{const e=$(t);return{riskDailyLossLimitJpy:Number(e.riskDailyLossLimitJpy||0),fxApiKey:String(e.fxApiKey||"").trim(),fxApiSecret:String(e.fxApiSecret||"").trim(),aiModel:String(e.aiModel||"").trim()||"gpt-5.4"}},st=t=>{const e=$(t);return{riskDailyLossLimitJpy:Number(e.riskDailyLossLimitJpy||0),cryptoApiKey:String(e.cryptoApiKey||"").trim(),cryptoApiSecret:String(e.cryptoApiSecret||"").trim(),aiModel:String(e.aiModel||"").trim()||"gpt-5.4"}};j=()=>String(P.logOutputDir||"").trim()||t.join(f.getPath("documents"),"weget-bot-logs");const nt=c({getModel:()=>{const t=V(),e=Z();return P.aiModel||t?.getConfig?.().aiModel||e?.getConfig?.().aiModel||"gpt-5.4"},getWorkingDir:()=>f.getPath("userData"),getLogDir:()=>j(),emitLog:q,getGatewayContext:()=>({activeSkills:W.getManagedSkills().filter(t=>t.enabled).map(t=>({name:t.name,displayName:t.displayName,version:t.version,tools:t.tools})),hostMetadata:{aiModel:P.aiModel||"gpt-5.4",capabilities:I,userDataPath:f.getPath("userData"),platform:process.platform,gmoCoinPublicBaseUrl:s.gmoCryptoPublicApiBaseUrl,gmoFxPublicBaseUrl:s.gmoFxPublicApiBaseUrl},botId:String(O?.botId||"").trim(),platformApiBaseUrl:String(s.loginApiUrl||"").trim().replace(/\/login\/?$/i,""),accessToken:String(O?.accessToken||"").trim(),fileBridgeDir:String(kt.getContext()?.dir||"").trim(),fileBridgeToken:String(kt.getContext()?.token||"").trim()})}),ot=async t=>{const a=$(t);return P={aiModel:String(a.aiModel||P.aiModel||"gpt-5.4").trim()||"gpt-5.4",logOutputDir:String(a.logOutputDir||"").trim()},await e.writeFile(A(),JSON.stringify({...P,updatedAt:(new Date).toISOString()},null,2),"utf8"),P};const lt=async()=>{const t=await Q.refreshLoadedSkills();return W.setAvailableSkills(t.map(t=>t.manifest)),t},ct=async t=>{const e=await lt();q("[skills] reconciled bundled skills",{desired:t.map(t=>({package_name:t.package_name,install_status:t.install_status,enabled:t.enabled,version:t.version})),bundled:e.map(t=>({package_name:t.packageName,version:t.version}))})},dt=()=>{const t=W.isSkillEnabled("@ai.weget.jp/skill-gmo-fx"),e=W.isSkillEnabled("@ai.weget.jp/skill-gmo-coin"),a=V(),i=Z();a&&("connected"===E?.getStatus()&&t?a.startExecutionStreams():a.stopExecutionStreams()),i&&("connected"===E?.getStatus()&&e?i.startExecutionStreams():i.stopExecutionStreams()),q("[skills] applied managed states",{active_skills:W.getActiveSkills().map(t=>t.name)})},gt=async()=>{const t=J.getBotRuntimeConfigApiUrl(),e=String(O?.botId||"").trim();if(!t||!e)return;const a=await J.callBotApi(t,{bot_id:e}),i=String(a.chat_model||"").trim(),r={...i?{aiModel:i}:{}};if(0===Object.keys(r).length)return;await ot({...P,...r});const s=V(),n=Z();s&&await s.saveConfig({...s.getConfig(),...r}),n&&await n.saveConfig({...n.getConfig(),...r}),q("[config] runtime config synced",{chat_model:i||""})},mt=async()=>{const t=J.getBotSkillsListApiUrl(),a=String(O?.botId||"").trim();if(!t||!a)return;const i=await J.callBotApi(t,{bot_id:a}),r=Array.isArray(i.states)?i.states.filter(t=>Boolean(t&&"object"==typeof t)).map(t=>({user_id:String(t.user_id||""),bot_id:String(t.bot_id||""),skill_id:String(t.skill_id||""),package_name:String(t.package_name||""),enabled:Boolean(t.enabled),install_status:String(t.install_status||""),version:t.version?String(t.version):null,config_json:$(t.config_json),created_at:t.created_at?String(t.created_at):void 0,updated_at:t.updated_at?String(t.updated_at):void 0})):[];W.applySnapshots(r),await(async t=>{await e.writeFile(C(),JSON.stringify({updatedAt:(new Date).toISOString(),items:t},null,2),"utf8")})(r),await ct(r),dt(),q("[config] skill states synced",{count:r.length,bot_id:a,enabled:r.filter(t=>t.enabled).length})},ut=t=>{if("fx"===t&&!W.isSkillEnabled("@ai.weget.jp/skill-gmo-fx"))throw new Error("GMO FX skill is disabled");if("coin"===t&&!W.isSkillEnabled("@ai.weget.jp/skill-gmo-coin"))throw new Error("GMO Coin skill is disabled")},pt=()=>{if(!W.isSkillEnabled("@ai.weget.jp/skill-macro-economy"))throw new Error("Macro Economy skill is disabled")},kt=d({getMacroSnapshot:async({force:t}={})=>(pt(),tt().getSnapshot({force:t})),getMacroCalendar:async({dateKey:t})=>(pt(),tt().listCalendar({dateKey:t})),getMacroNews:async({dateKey:t})=>(pt(),tt().listNews({dateKey:t})),emitLog:q,getWorkingDir:()=>f.getPath("userData")}),yt={"@ai.weget.jp/skill-gmo-fx":{getConfig:()=>rt(X().getConfig()),saveConfig:async t=>{const e=X(),a=await e.saveConfig({...e.getConfig(),...rt(t)});return"connected"===E?.getStatus()&&dt(),rt(a)}},"@ai.weget.jp/skill-gmo-coin":{getConfig:()=>st(Y().getConfig()),saveConfig:async t=>{const e=Y(),a=await e.saveConfig({...e.getConfig(),...st(t)});return"connected"===E?.getStatus()&&dt(),st(a)}}},St=t=>{const e=String(t||"").trim(),a=yt[e];if(!a)throw new Error(`skill config is not managed by bot host: ${t}`);return a},ft=async()=>{await Q.ensureInstallRoot(),await lt();const t=await async function(){try{const t=await e.readFile(C(),"utf8"),a=JSON.parse(t);return(Array.isArray(a?.items)?a.items:[]).filter(t=>Boolean(t&&"object"==typeof t)).map(t=>({user_id:String(t.user_id||""),bot_id:String(t.bot_id||""),skill_id:String(t.skill_id||""),package_name:String(t.package_name||""),enabled:Boolean(t.enabled),install_status:String(t.install_status||""),version:t.version?String(t.version):null,config_json:$(t.config_json),created_at:t.created_at?String(t.created_at):void 0,updated_at:t.updated_at?String(t.updated_at):void 0}))}catch(t){if("ENOENT"===t?.code)return[];throw t}}();t.length>0&&(W.applySnapshots(t),q("[skills] restored local snapshot",{count:t.length}),await ct(t)),dt()};E=new n({wsUrl:"wss://ws.weget.jp",taskEventApiUrl:String(s.loginApiUrl||"").trim().replace(/\/login\/?$/i,"/bot/runtime/task-event"),version:"0.2.0",capabilities:I,heartbeatSec:30,reconnectMs:3e3,reconnectMaxAttempts:10,wsPingIntervalSec:25,wsPongTimeoutSec:12},{onLog:(t,e)=>q(t,e),onStatus:t=>{B.emitBotStatus({status:t}),dt()},onLineMessage:async t=>{const e=String(t.line_user_id||""),a=String(t.text||"").trim();if(L({type:"line_user",lineUserId:e,text:a}),!a)return{answer:""};try{const t=await nt.runPrompt({prompt:a,contextLabel:"line_message"});return L({type:"line_assistant",lineUserId:e,text:t}),{answer:t}}catch(t){const a=t instanceof Error?t.message:String(t);q("[ai] line reply failed",{error:a});const i=`AI error: ${a}`;return L({type:"line_assistant",lineUserId:e,text:i}),{answer:i}}},onRunTask:async t=>{const e=String(t.task_id||"").trim(),a=String(t.prompt||"").trim(),i=$(t.metadata_json),r=$(t.prompt_bundle),s=$(t.runtime_config),n=String(i.source||r.source||"").trim(),o=String(i.channel||r.channel||"").trim(),l=String(t.skill_id||i.skill_id||r.skill_id||"").trim(),c=String(t.bot_id||O?.botId||"").trim(),d=String(i.line_user_id||"").trim(),g=String(i.line_reply_token||"").trim(),m="line"===n||"line"===o||Boolean(d&&g),k="bot_host"===n,y=String(t.model||s.chat_model||"").trim(),S=String(s.system_prompt||r.system_prompt||"").trim();if(!e)return void q("[task] run_task missing task_id");const f=(new Date).toISOString();if(M.set(e,{cancelled:!1,abortController:new AbortController,taskId:e,title:String(t.title||a.slice(0,120)||e).trim(),prompt:a,status:"Task received",source:n||"unknown",channel:o||"",lineUserId:d||void 0,conversationId:String(t.conversation_id||"").trim()||void 0,startedAt:f,lastProgressAt:f}),R(),m&&d&&a&&L({type:"line_user",lineUserId:d,text:a}),E?.sendTaskEvent(e,"task_received",{prompt:a,conversation_id:String(t.conversation_id||""),continue_from_task_id:String(t.continue_from_task_id||""),ts:(new Date).toISOString()}),!a)return E?.sendTaskResult(e,"failed",{error:"prompt is required",data_json:{ts:(new Date).toISOString()}}),void M.delete(e);try{if(k||m){const t=at({isLineTask:m,status:"Task received"});L({type:"assistant_status",status:t}),N(e,{status:t})}l&&E?.sendSkillStatus(e,{skill_id:l,status:"running",summary:"task execution started",data_json:{ts:(new Date).toISOString()}}),E?.sendTaskEvent(e,"step_started",{step:"codex_chat",ts:(new Date).toISOString()});const f=await nt.runPrompt({prompt:a,model:y||void 0,systemPrompt:S||void 0,contextLabel:`task:${e}`,promptBundle:r,metadata:i,onStatus:k||m?t=>{const a=at({isLineTask:m,status:t});L({type:"assistant_status",status:a}),N(e,{status:a})}:void 0,abortSignal:M.get(e)?.abortController.signal}),_=u(f),w=_.pendingRequest,b=_.arbitrationAction,v=_.visibleText||p(f),h=M.get(e);if(h?.cancelled)return E?.sendTaskResult(e,"cancelled",G(h,"server_cancelled")),void F(e);let I=null;if(b){if(I=await K({taskId:e,directive:b,promptBundle:r}),!I.ok&&"cancel_running_task"===b.action)throw new Error("error"in I&&I.error||"failed to cancel running task");if("start_new_task"===b.action){const t=await(async({taskId:t,prompt:e,visibleAnswer:a,source:i,channel:r,botId:s,skillId:n,runtimeConfig:o,promptBundle:l,metadata:c})=>{const d=String(l.conversation_id||"").trim();if(!d)return{ok:!1,error:"conversation_id is required for start_new_task"};const g={...c,arbitration_parent_task_id:t,arbitration_decision:"start_new_task",arbitration_visible_answer:a},m=await z.request({method:"POST",path:"/bot/tasks",body:{source:i||null,channel:r||null,bot_id:s,skill_id:n||void 0,prompt:e,title:e.slice(0,80),conversation_id:d,continue_from_task_id:t,model:String(o.chat_model||"").trim()||void 0,sandbox_mode:String(o.sandbox_mode||"").trim()||void 0,approval_policy:String(o.approval_policy||"").trim()||void 0,metadata_json:g}});return{ok:!0,taskId:String($(m.task).task_id||"").trim()||null,dispatch:$(m.dispatch_result)}})({taskId:e,prompt:a,visibleAnswer:v,source:n,channel:o,botId:c,skillId:l||void 0,runtimeConfig:s,promptBundle:r,metadata:i});if(!t.ok)throw new Error(t.error||"failed to queue arbitrated new task");I={ok:!0,mode:"local"===I.mode||"platform"===I.mode||"advisory"===I.mode?I.mode:"advisory",queuedTaskId:t.taskId,dispatch:t.dispatch}}}if(E?.sendTaskEvent(e,"ai_output",{summary:v,action:b?.action||null,ts:(new Date).toISOString()}),k&&L({type:"assistant",text:v}),m&&d&&g){L({type:"line_assistant",lineUserId:d,text:v});const a={bot_id:String(t.bot_id||O?.botId||""),line_user_id:d,line_reply_token:g,text:v};try{await H(a)}catch(t){q("[line] callback line reply failed",{error:t instanceof Error?t.message:String(t)})}E?.sendTaskEvent(e,"line_message_ai_output",{line_user_id:d,answer:v,ts:(new Date).toISOString()})}if(E?.sendTaskEvent(e,"step_finished",{step:"codex_chat",action:b?.action||null,ts:(new Date).toISOString()}),w)return"approval"===w.requestType?E?.requestTaskApproval(e,{prompt:w.prompt,approval_type:w.subtype||"generic",data_json:{prompt:w.prompt,approval_type:w.subtype||"generic",ts:(new Date).toISOString()}}):E?.requestTaskInput(e,{prompt:w.prompt,input_type:w.subtype||"text",data_json:{prompt:w.prompt,input_type:w.subtype||"text",ts:(new Date).toISOString()}}),l&&E?.sendSkillStatus(e,{skill_id:l,status:"approval"===w.requestType?"waiting_approval":"waiting_input",summary:w.prompt.slice(0,200),data_json:{ts:(new Date).toISOString(),request_type:w.requestType}}),void F(e);E?.sendTaskResult(e,"succeeded",{summary:v.slice(0,500),data_json:{ts:(new Date).toISOString(),action:b?.action||null,target_task_id:b?.targetTaskId||null,action_reason:b?.reason||null,action_mode:I?.mode||null,queued_task_id:I?.queuedTaskId||null}}),l&&E?.sendSkillStatus(e,{skill_id:l,status:"succeeded",summary:v.slice(0,200),data_json:{ts:(new Date).toISOString()}})}catch(a){if(k){const t=`Error: ${a instanceof Error?a.message:String(a)}`;L({type:"assistant",text:t})}const i=M.get(e);if(i?.cancelled)return E?.sendTaskResult(e,"cancelled",G(i,"server_cancelled")),void F(e);if(m&&d&&g){const e=`AI error: ${a instanceof Error?a.message:String(a)}`;L({type:"line_assistant",lineUserId:d,text:e});const i={bot_id:String(t.bot_id||O?.botId||""),line_user_id:d,line_reply_token:g,text:e};try{await H(i)}catch(t){q("[line] callback line reply failed",{error:t instanceof Error?t.message:String(t)})}}E?.sendTaskResult(e,"failed",{error:a instanceof Error?a.message:String(a),data_json:{ts:(new Date).toISOString()}}),l&&E?.sendSkillStatus(e,{skill_id:l,status:"failed",summary:a instanceof Error?a.message:String(a),data_json:{ts:(new Date).toISOString()}})}finally{F(e)}},onTaskControl:async t=>{const e=String(t.task_id||"").trim(),a=String(t.action||"").trim();if(e&&a&&"cancel_task"===a){const a=M.get(e);if(a){a.cancelled=!0,a.cancelReason="server_cancelled",a.cancelRequestedByAction="cancel_task",a.abortController.abort();const i=String(t.skill_id||"").trim();return i&&E?.sendSkillStatus(e,{skill_id:i,status:"cancelled",summary:"server_cancelled",data_json:{ts:(new Date).toISOString()}}),void q("[task] cancel requested",{task_id:e})}E?.sendTaskResult(e,"cancelled",G(void 0,"server_cancelled"))}},onServerConfigUpdate:async t=>{const e=Array.isArray(t.scopes)?t.scopes.map(t=>String(t||"").trim()):[],a=e.length>0?e:["runtime","skills"];a.includes("runtime")&&await gt(),a.includes("skills")&&await mt()}}),o({ipcMain:w,env:{capabilities:I,loginApiUrl:s.loginApiUrl},signInWithLoginApi:J.signInWithLoginApi,saveLoginProfile:async({botId:t,email:a,password:i,remember:r})=>{if(r)await e.writeFile(x(),JSON.stringify({botId:t,email:a,password:i,remember:!0,updatedAt:(new Date).toISOString()},null,2),"utf8");else try{await e.unlink(x())}catch(t){if("ENOENT"!==t?.code)throw t}},readSavedLoginProfile:async()=>{try{const t=await e.readFile(x(),"utf8"),a=JSON.parse(t);return{botId:String(a?.botId||""),email:String(a?.email||""),password:String(a?.password||""),remember:Boolean(a?.remember)}}catch(t){if("ENOENT"===t?.code)return{botId:"",email:"",password:"",remember:!1};throw t}},getSkillConfig:t=>({config:St(t).getConfig()}),saveSkillConfig:async(t,e)=>({config:await St(t).saveConfig(e)}),getAiConfig:()=>({aiModel:String(P.aiModel||"gpt-5.4"),logOutputDir:String(P.logOutputDir||"")}),saveAiConfig:async t=>{const e=t&&"object"==typeof t?t:{},a=await ot({...P,...e}),i=V(),r=Z(),s=i?await i.saveConfig({...i.getConfig(),...e}):null;return r&&await r.saveConfig({...r.getConfig(),...e}),{aiModel:String(a.aiModel||s?.aiModel||e.aiModel||"gpt-5.4"),logOutputDir:String(a.logOutputDir||"")}},setCurrentSession:t=>{O=t||null;const e=O?"connected":"disconnected";B.emitBotStatus({status:e})},getCurrentSession:()=>O,getActiveSkills:()=>W.getActiveSkills().map(t=>({name:t.name,displayName:t.displayName,version:t.version})),getCodexAuthStatus:()=>nt.getAuthStatus(),getCodexMcpStatus:t=>nt.getMcpServerStatus(t),getPlaywrightBrowserStatus:()=>nt.getPlaywrightBrowserStatus(),startCodexLogin:()=>nt.startLogin(),installPlaywrightMcp:()=>nt.installWegetGatewayMcp(),getGatewayContextFilePath:()=>nt.getGatewayContextFilePath(),runGatewaySelfTest:t=>nt.runGatewaySelfTest(t),getManagedSkills:()=>W.getManagedSkills().map(t=>({...t,ui:Q.getLoadedSkill(t.name)?.ui||void 0})),getMacroSnapshot:async({force:t}={})=>(pt(),tt().getSnapshot({force:t})),getMacroCalendar:async({dateKey:t})=>(pt(),tt().listCalendar({dateKey:t})),getMacroNews:async({dateKey:t})=>(pt(),tt().listNews({dateKey:t})),emitLog:q,openGmoKlineWindow:async({symbol:t,interval:e,market:a})=>(()=>{const i="fx"===a?"fx":"coin";return ut(i),("fx"===i?X().marketData:Y().marketData).fetchKline({symbol:t,interval:e,market:i})})(),getGmoMarketQuotes:async({market:t,symbols:e})=>(()=>{const a="fx"===t?"fx":"coin";return ut(a),("fx"===a?X().marketData:Y().marketData).fetchQuotes({market:a,symbols:e})})(),getGmoSymbolRules:async({market:t})=>(()=>{const e="fx"===t?"fx":"coin";return ut(e),("fx"===e?X().marketData:Y().marketData).fetchSymbolRules({market:e})})(),getGmoBuyingPower:async({market:t})=>({market:t,availableJpy:await(ut(t),("fx"===t?X().gateway:Y().gateway).getBuyingPower(t))}),getGmoAccountMetrics:async({market:t})=>(ut(t),("fx"===t?X().gateway:Y().gateway).getAccountMetrics(t)),getGmoPositionSummary:async({market:t,symbol:e})=>({market:t,symbol:e,items:await(ut(t),("fx"===t?X().gateway:Y().gateway).getPositionSummary({market:t,symbol:e}))}),getGmoOpenPositions:async({market:t,symbol:e,page:a,prevId:i,count:r})=>({market:t,symbol:e||"",items:await(ut(t),("fx"===t?X().gateway:Y().gateway).getOpenPositions({market:"fx"===t?"fx":"crypto",symbol:e||void 0,page:a,prevId:i,count:r}))}),placeGmoFxOrder:async({symbol:t,side:e,size:a})=>{ut("fx");return await it(X(),"placeFxOrder")({symbol:t,side:e,size:a,executionType:"MARKET"})},placeGmoCoinOrder:async({symbol:t,side:e,size:a})=>{ut("coin");return await it(Y(),"placeCoinOrder")({symbol:t,side:e,size:a,executionType:"MARKET"})},placeGmoFxCloseOrder:async({symbol:t,side:e,positionId:a,size:i})=>{ut("fx");return await it(X(),"placeFxCloseOrder")({symbol:t,side:e,positionId:a,size:i,executionType:"MARKET"})},placeGmoCoinCloseOrder:async({symbol:t,side:e,positionId:a,size:i})=>{ut("coin");return await it(Y(),"placeCoinCloseOrder")({symbol:t,side:e,positionId:a,size:i,executionType:"MARKET"})},getGmoApiState:t=>{const e="fx"===t?V():Z();return e?.status.getApiState()||"unknown"},testGmoApi:t=>(ut(t),"fx"===t?X().status.testApi():Y().status.testApi()),buildTradeStatusSnapshot:t=>(ut(t),"fx"===t?X().status.buildSnapshot():Y().status.buildSnapshot()),closeTradeWindows:()=>{},startWsClient:t=>{E?.start(t),gt().catch(t=>{q("[config] runtime sync failed after login",{error:t instanceof Error?t.message:String(t)})}),mt().catch(t=>{q("[config] skill sync failed after login",{error:t instanceof Error?t.message:String(t)})}),dt()},stopWsClient:()=>{V()?.stopExecutionStreams(),Z()?.stopExecutionStreams(),et()?.stop?.(),E?.stop(),R()},handleBotChatMessage:async({text:t})=>{const e=String(t||"").trim(),a=String(O?.botId||"").trim();if(!e)throw new Error("message is required");if(!a)throw new Error("bot session is not ready");L({type:"assistant_status",status:"Submitting task"});const i=await z.request({method:"POST",path:"/bot/tasks",body:{source:"bot_host",bot_id:a,prompt:e,title:e.slice(0,80),channel:"desktop",metadata_json:{source:"bot_host",channel:"desktop"}}}),r=$(i.dispatch_result);if(!1===r.delivered)throw new Error(`task queued but bot is offline (${String(r.status||"offline")})`);return{answer:"",taskId:String($(i.task).task_id||"")}},getActiveTaskRuntimes:()=>Array.from(M.values()).map(U),cancelActiveTaskRuntime:async t=>{const e=M.get(String(t||"").trim());return e?(e.cancelled=!0,e.cancelReason="local_cancelled",e.cancelRequestedByAction="cancel_task",e.abortController.abort(),N(e.taskId,{status:"Cancelling..."}),q("[task] local cancel requested",{task_id:e.taskId}),{ok:!0}):{ok:!1,error:"task not found"}},writeErrorLog:async({source:t,message:e,details:a})=>{await(async({source:t,message:e,details:a})=>{await D({level:"error",source:t,message:e,details:a})})({source:t,message:e,details:a})},writeRuntimeLog:async({level:t,source:e,message:a,details:i})=>{await D({level:t,source:e,message:a,details:i})}});const _t=t.join(h,"renderer","logo.png");f.whenReady().then(async()=>{(()=>{if("darwin"!==process.platform)return;if(!a(_t))return;const t=b.createFromPath(_t);t.isEmpty()||f.dock.setIcon(t)})(),await(async()=>{try{const t=await e.readFile(A(),"utf8"),a=JSON.parse(t);P={aiModel:String(a?.aiModel||"gpt-5.4").trim()||"gpt-5.4",logOutputDir:String(a?.logOutputDir||"").trim()}}catch(t){if("ENOENT"!==t?.code)throw t;P={aiModel:"gpt-5.4",logOutputDir:""}}return P})();try{await kt.ensureStarted()}catch(t){q("[gateway-file-bridge] startup failed",{error:t instanceof Error?t.message:String(t)})}try{await ft()}catch(t){q("[skills] local initialization failed",{error:t instanceof Error?t.message:String(t)})}B.createMainWindow(),R(),f.on("activate",()=>{0===_.getAllWindows().length&&(B.createMainWindow(),R())})}),f.on("window-all-closed",()=>{V()?.stopExecutionStreams(),Z()?.stopExecutionStreams(),et()?.stop?.(),kt.stop().catch(()=>{}),E?.stop(),"darwin"!==process.platform&&f.quit()});
@@ -1 +1 @@
1
- const t=t=>String(t||"").trim();export const stripWegetControlBlocks=t=>String(t||"").replace(/```weget_result\s*[\s\S]*?```/gi,"").replace(/```weget_pending_request\s*[\s\S]*?```/gi,"").trim();export const parseTaskDirective=e=>{const n=String(e||""),i=stripWegetControlBlocks(n),r=n.match(/```weget_result\s*([\s\S]*?)```/i);if(r?.[1])try{const e=JSON.parse(r[1].trim()),n=t(e.status).toLowerCase(),s=e.pending_request&&"object"==typeof e.pending_request?e.pending_request:{};if("pending_request"===n){const n=t(s.type).toLowerCase(),r=t(s.prompt),o=t(s.subtype);if(("input"===n||"approval"===n)&&r)return{visibleText:i,payload:e,pendingRequest:{visibleText:i,requestType:n,prompt:r,subtype:o||void 0},arbitrationAction:null}}const o=(e=>{const n=t(e).toLowerCase();return"report_progress"===n||"cancel_running_task"===n||"continue_current_task"===n||"start_new_task"===n?n:null})(e.action);return o?{visibleText:i,payload:e,arbitrationAction:{visibleText:i,action:o,targetTaskId:t(e.target_task_id)||void 0,reason:t(e.reason)||void 0},pendingRequest:null}:{visibleText:i,payload:e,pendingRequest:null,arbitrationAction:null}}catch{return{visibleText:i,payload:null,pendingRequest:null,arbitrationAction:null}}const s=n.match(/```weget_pending_request\s*([\s\S]*?)```/i);if(!s?.[1])return{visibleText:i,payload:null,pendingRequest:null,arbitrationAction:null};try{const e=JSON.parse(s[1].trim()),n=t(e.type).toLowerCase(),r=t(e.prompt),o=t(e.subtype);if(("input"===n||"approval"===n)&&r)return{visibleText:i,payload:e,pendingRequest:{visibleText:i,requestType:n,prompt:r,subtype:o||void 0},arbitrationAction:null}}catch{}return{visibleText:i,payload:null,pendingRequest:null,arbitrationAction:null}};
1
+ const t=t=>String(t||"").trim();export const stripWegetControlBlocks=t=>String(t||"").replace(/```weget_result\s*[\s\S]*?```/gi,"").replace(/```weget_pending_request\s*[\s\S]*?```/gi,"").trim();export const parseTaskDirective=e=>{const n=String(e||""),i=stripWegetControlBlocks(n),r=n.match(/```weget_result\s*([\s\S]*?)```/i);if(r?.[1])try{const e=JSON.parse(r[1].trim()),n=t(e.status).toLowerCase(),s=e.pending_request&&"object"==typeof e.pending_request?e.pending_request:{};if("pending_request"===n){const n=t(s.type).toLowerCase(),r=t(s.prompt),o=t(s.subtype);if(("input"===n||"approval"===n)&&r)return{visibleText:i,payload:e,pendingRequest:{visibleText:i,requestType:n,prompt:r,subtype:o||void 0},arbitrationAction:null}}const o=(e=>{const n=t(e).toLowerCase();return"report_progress"===n||"cancel_running_task"===n||"continue_current_task"===n||"start_new_task"===n?n:null})(e.action);return o?{visibleText:i,payload:e,arbitrationAction:{visibleText:i,action:o,targetTaskId:t(e.target_task_id)||void 0,reason:t(e.reason)||void 0},pendingRequest:null}:{visibleText:i,payload:e,pendingRequest:null,arbitrationAction:null}}catch{return{visibleText:i,payload:null,pendingRequest:null,arbitrationAction:null}}const s=n.match(/```weget_pending_request\s*([\s\S]*?)```/i);if(!s?.[1])return{visibleText:i,payload:null,pendingRequest:null,arbitrationAction:null};try{const e=JSON.parse(s[1].trim()),n=t(e.type).toLowerCase(),r=t(e.prompt),o=t(e.subtype);if(("input"===n||"approval"===n)&&r)return{visibleText:i,payload:e,pendingRequest:{visibleText:i,requestType:n,prompt:r,subtype:o||void 0},arbitrationAction:null}}catch{}return{visibleText:i,payload:null,pendingRequest:null,arbitrationAction:null}};export const shouldQueueArbitratedNewTask=e=>"start_new_task"===e.arbitrationAction?.action&&Boolean(t(e.visibleText));
@@ -1 +1 @@
1
- import t from"node:test";import e from"node:assert/strict";import{parseTaskDirective as i,stripWegetControlBlocks as a}from"./taskDirective.js";t("taskDirective strips control blocks from visible text",()=>{const t=["Working on it.","","```weget_result",'{"status":"completed"}',"```"].join("\n");e.equal(a(t),"Working on it.")}),t("taskDirective parses pending request directive",()=>{const t=["Need your confirmation.","","```weget_result",'{"status":"pending_request","pending_request":{"type":"approval","prompt":"Proceed?","subtype":"generic"}}',"```"].join("\n"),a=i(t);e.equal(a.visibleText,"Need your confirmation."),e.equal(a.pendingRequest?.requestType,"approval"),e.equal(a.pendingRequest?.prompt,"Proceed?"),e.equal(a.pendingRequest?.subtype,"generic"),e.equal(a.arbitrationAction,null)}),t("taskDirective parses arbitration cancel action",()=>{const t=["I will stop the current task and summarize the completed work.","","```weget_result",'{"status":"completed","action":"cancel_running_task","target_task_id":"t-active","reason":"user_requested_cancel"}',"```"].join("\n"),a=i(t);e.equal(a.pendingRequest,null),e.equal(a.arbitrationAction?.action,"cancel_running_task"),e.equal(a.arbitrationAction?.targetTaskId,"t-active"),e.equal(a.arbitrationAction?.reason,"user_requested_cancel")}),t("taskDirective parses arbitration progress action",()=>{const t=["The active task is still collecting logs.","","```weget_result",'{"status":"completed","action":"report_progress"}',"```"].join("\n"),a=i(t);e.equal(a.arbitrationAction?.action,"report_progress"),e.equal(a.visibleText,"The active task is still collecting logs.")}),t("taskDirective parses continue current task action",()=>{const t=["I will keep the current task running with your added instruction in mind.","","```weget_result",'{"status":"completed","action":"continue_current_task","target_task_id":"t-active"}',"```"].join("\n"),a=i(t);e.equal(a.arbitrationAction?.action,"continue_current_task"),e.equal(a.arbitrationAction?.targetTaskId,"t-active")}),t("taskDirective parses start new task action",()=>{const t=["This is a separate request, so I will treat it as a new task.","","```weget_result",'{"status":"completed","action":"start_new_task"}',"```"].join("\n"),a=i(t);e.equal(a.arbitrationAction?.action,"start_new_task"),e.equal(a.visibleText,"This is a separate request, so I will treat it as a new task.")});
1
+ import t from"node:test";import e from"node:assert/strict";import{parseTaskDirective as i,shouldQueueArbitratedNewTask as a,stripWegetControlBlocks as s}from"./taskDirective.js";t("taskDirective strips control blocks from visible text",()=>{const t=["Working on it.","","```weget_result",'{"status":"completed"}',"```"].join("\n");e.equal(s(t),"Working on it.")}),t("taskDirective parses pending request directive",()=>{const t=["Need your confirmation.","","```weget_result",'{"status":"pending_request","pending_request":{"type":"approval","prompt":"Proceed?","subtype":"generic"}}',"```"].join("\n"),a=i(t);e.equal(a.visibleText,"Need your confirmation."),e.equal(a.pendingRequest?.requestType,"approval"),e.equal(a.pendingRequest?.prompt,"Proceed?"),e.equal(a.pendingRequest?.subtype,"generic"),e.equal(a.arbitrationAction,null)}),t("taskDirective parses arbitration cancel action",()=>{const t=["I will stop the current task and summarize the completed work.","","```weget_result",'{"status":"completed","action":"cancel_running_task","target_task_id":"t-active","reason":"user_requested_cancel"}',"```"].join("\n"),a=i(t);e.equal(a.pendingRequest,null),e.equal(a.arbitrationAction?.action,"cancel_running_task"),e.equal(a.arbitrationAction?.targetTaskId,"t-active"),e.equal(a.arbitrationAction?.reason,"user_requested_cancel")}),t("taskDirective parses arbitration progress action",()=>{const t=["The active task is still collecting logs.","","```weget_result",'{"status":"completed","action":"report_progress"}',"```"].join("\n"),a=i(t);e.equal(a.arbitrationAction?.action,"report_progress"),e.equal(a.visibleText,"The active task is still collecting logs.")}),t("taskDirective parses continue current task action",()=>{const t=["I will keep the current task running with your added instruction in mind.","","```weget_result",'{"status":"completed","action":"continue_current_task","target_task_id":"t-active"}',"```"].join("\n"),a=i(t);e.equal(a.arbitrationAction?.action,"continue_current_task"),e.equal(a.arbitrationAction?.targetTaskId,"t-active")}),t("taskDirective parses start new task action",()=>{const t=["This is a separate request, so I will treat it as a new task.","","```weget_result",'{"status":"completed","action":"start_new_task"}',"```"].join("\n"),s=i(t);e.equal(s.arbitrationAction?.action,"start_new_task"),e.equal(s.visibleText,"This is a separate request, so I will treat it as a new task."),e.equal(a(s),!0)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai.weget.jp/bot",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "WeGet bot host for Codex-centered skill runtime ",