grix-connector 2.0.9 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/claude/claude-bridge-server.js +1 -1
- package/dist/adapter/claude/claude-tools.js +1 -1
- package/dist/adapter/claude/claude-worker-client.js +1 -1
- package/dist/adapter/claude/mcp-http-launcher.js +2 -2
- package/dist/adapter/claude/result-timeout.js +1 -1
- package/dist/adapter/cursor/cursor-adapter.js +5 -5
- package/dist/adapter/opencode/opencode-adapter.js +3 -3
- package/dist/bridge/bridge.js +10 -10
- package/dist/core/aibot/client.js +2 -2
- package/dist/core/file-ops/list-files.js +1 -1
- package/dist/core/files/cert-store.js +40 -0
- package/dist/core/files/file-serve.js +2 -2
- package/dist/core/files/list-handler.js +1 -1
- package/dist/core/mcp/tools.js +1 -1
- package/dist/core/util/host-info.js +1 -0
- package/dist/core/util/index.js +1 -1
- package/dist/default-skills/grix-egg/SKILL.md +90 -0
- package/dist/default-skills/tailnet-file-share/SKILL.md +49 -0
- package/dist/log.js +2 -2
- package/dist/manager.js +1 -1
- package/dist/mcp/stream-http/config.js +1 -1
- package/dist/mcp/stream-http/connection-binding.js +1 -1
- package/dist/mcp/stream-http/tool-executor.js +1 -1
- package/dist/mcp/stream-http/tool-registry.js +1 -1
- package/dist/mcp/stream-http/tool-schemas.js +1 -1
- package/openclaw-plugin/index.js +52 -26
- package/package.json +3 -1
package/dist/manager.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{readFileSync as Q,readdirSync as F,writeFileSync as B}from"node:fs";import{join as A}from"node:path";import{AgentInstance as S}from"./bridge/bridge.js";import{GRIX_PATHS as x,log as c}from"./core/log/index.js";import{resolveClientVersion as L}from"./core/util/client-version.js";import{UpgradeChecker as R}from"./core/upgrade/upgrade-checker.js";import{AgentGlobalConfigStore as z}from"./core/persistence/agent-global-config-store.js";import{scanSkills as G,dedupeSkills as K}from"./adapter/claude/skill-scanner.js";import{scanDefaultSkills as W,logDefaultSkillsCheck as V,cleanupProjectedSkills as D}from"./default-skills/index.js";import{resolveCopilotCommand as q}from"./core/runtime/copilot-resolve.js";import{getCliVersion as J,resolveCliPath as X}from"./core/util/cli-probe.js";import{AgentInstaller as Y}from"./core/installer/installer.js";import{reportInstallFailure as Z}from"./core/observability/sentry.js";const ee=8e3;function te(){const n=q();return[{clientType:"openclaw",command:"openclaw"},{clientType:"claude",command:"claude"},{clientType:"codex",command:"codex"},{clientType:"gemini",command:"gemini"},{clientType:"qwen",command:"qwen"},{clientType:"hermes",command:"hermes"},{clientType:"reasonix",command:"reasonix"},{clientType:"codewhale",command:"codewhale"},{clientType:"opencode",command:"opencode"},{clientType:"cursor",command:"agent"},{clientType:"pi",command:"pi"},{clientType:"openhuman",command:"openhuman-core"},{clientType:"kiro",command:"kiro-cli"},{clientType:"copilot",command:n.command},{clientType:"agy",command:"agy"}]}async function ne(){return Promise.all(te().map(async n=>{const e=await X(n.command);if(!e)return{client_type:n.clientType,command:n.command,installed:!1,path:null,version:null};const t=await J(e,n.versionArgs??["--version"]);return{client_type:n.clientType,command:n.command,installed:!0,path:e,version:t.version,error:t.error}}))}function ae(n){switch(n){case"claude":return{adapterType:"claude",command:"claude"};case"codex":return{adapterType:"codex",command:"codex",options:{sandboxMode:"danger-full-access"}};case"gemini":return{adapterType:"acp",command:"gemini",autoInjectArgs:{acp:!0},enableSessionBinding:!0};case"qwen":return{adapterType:"acp",command:"qwen",adapterHint:"qwen/base",autoInjectArgs:{acp:!0},enableSessionBinding:!0};case"pi":return{adapterType:"pi",command:"pi"};case"cursor":return{adapterType:"cursor",command:"agent"};case"reasonix":return{adapterType:"acp",command:"reasonix",args:["acp"],enableSessionBinding:!0};case"codewhale":return{adapterType:"codewhale",command:"codewhale",enableSessionBinding:!0};case"openhuman":return{adapterType:"openhuman",command:"openhuman-core",enableSessionBinding:!0};case"kiro":return{adapterType:"acp",command:"kiro-cli",args:["acp"],enableSessionBinding:!0};case"opencode":return{adapterType:"opencode",command:"opencode",args:["serve"],enableSessionBinding:!0};case"copilot":{const e=q();return{adapterType:"acp",command:e.command,args:[...e.prefixArgs,"--acp"],enableSessionBinding:!0}}case"agy":return{adapterType:"agy",command:"agy",enableSessionBinding:!0};case"hermes":throw new Error('client_type "hermes" is not handled by grix-connector. Hermes runs as a separate project \u2014 see https://github.com/askie/grix-hermes-python');default:throw new Error(`Unsupported client_type: ${n}`)}}function oe(n){const e=String(n??"").trim().toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")||"default";return A(x.data,`session-bindings-${e}.json`)}function ie(n){const e=String(n??"").trim().toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")||"default";return A(x.data,`active-events-${e}.json`)}function re(...n){const e=[],t=new Set;for(const o of n)for(const a of o??[]){const r=String(a??"").trim(),u=r.toLowerCase();!r||t.has(u)||(t.add(u),e.push(r))}return e.length>0?e:void 0}function se(n,e){const t={claude:{maxConcurrent:1,maxQueued:5,queueTimeoutMs:0},codex:{maxConcurrent:1,maxQueued:5,queueTimeoutMs:0},cursor:{maxConcurrent:1,maxQueued:3,queueTimeoutMs:0},acp:{maxConcurrent:1,maxQueued:3,queueTimeoutMs:0},pi:{maxConcurrent:1,maxQueued:5,queueTimeoutMs:0},codewhale:{maxConcurrent:1,maxQueued:3,queueTimeoutMs:0},openhuman:{maxConcurrent:1,maxQueued:3,queueTimeoutMs:0},opencode:{maxConcurrent:1,maxQueued:3,queueTimeoutMs:0},agy:{maxConcurrent:1,maxQueued:3,queueTimeoutMs:0}},o=t[n]??t.acp;return{maxConcurrent:e?.max_concurrent??o.maxConcurrent??1,maxQueued:e?.max_queued??o.maxQueued??3,queueTimeoutMs:e?.queue_timeout_ms??o.queueTimeoutMs??0,cancelableQueued:!0,cancelableRunning:!0}}function E(n){const e=L(),t=String(n.client_type??"").trim().toLowerCase(),o=ae(t),a=String(n.ws_url??"").trim(),r="get_session_usage",u="get_rate_limits",l="get_agent_global_config";if(!n.name?.trim())throw new Error("agent name is required");if(!a)throw new Error(`agent ${n.name}: ws_url is required`);if(!n.agent_id?.trim())throw new Error(`agent ${n.name}: agent_id is required`);if(!n.api_key?.trim())throw new Error(`agent ${n.name}: api_key is required`);const s=o.adapterType,d=s==="acp",f=t==="qwen",p={...o.options??{}},i=s==="codex"?{capabilities:["local_action_v1","agent_invoke"],localActions:["session_control","get_context","set_model","set_mode","set_reasoning_effort","set_sandbox_mode","exec_approve","exec_reject","file_list","create_folder","turn_interrupt","permission_approve","permission_reject","thread_compact",r,u]}:null,m=s==="claude"?{localActions:["session_control","set_mode","set_model","claude_interaction_reply","exec_approve","exec_reject","file_list","create_folder","thread_compact",r,u]}:null,_=f?{capabilities:["stream_chunk","local_action_v1"],localActions:["exec_approve","exec_reject","permission_approve","permission_reject","session_control","set_model","set_mode","file_list","create_folder",r],adapterHint:"qwen/base"}:null,h=s==="pi"?{adapterHint:"pi/base",capabilities:["local_action_v1"],localActions:["session_control","set_model","get_context","file_list","create_folder",r]}:null,g=s==="openhuman"?{adapterHint:"openhuman/base",capabilities:["local_action_v1"],localActions:["session_control","set_model","file_list","create_folder",r]}:null,w=s==="cursor"?{adapterHint:"cursor/base",capabilities:["stream_chunk","local_action_v1"],localActions:["session_control","set_model","set_mode","get_context","file_list","create_folder",r,u]}:null,b=s==="codewhale"?{capabilities:["stream_chunk","local_action_v1"],localActions:["session_control","set_model","file_list","create_folder",r]}:null,T=s==="opencode"?{adapterHint:"opencode/base",capabilities:["stream_chunk","local_action_v1"],localActions:["exec_approve","exec_reject","permission_approve","permission_reject","session_control","set_model","set_mode","file_list","create_folder",r]}:null,k=s==="agy"?{adapterHint:"agy/base",capabilities:["stream_chunk","local_action_v1"],localActions:["session_control","set_model","file_list","create_folder",r]}:null,P=d&&!f?{localActions:["exec_approve","exec_reject","permission_approve","permission_reject","session_control","set_model","set_mode","file_list","create_folder",r]}:null,H=t==="kiro"?{localActions:["exec_approve","exec_reject","permission_approve","permission_reject","session_control","set_model","set_mode","file_list","create_folder","thread_compact",r,u]}:null,N=s==="codex"||s==="claude"||t==="gemini"?["session_control","set_model","set_mode"]:void 0,O=[r,u];d&&p.raw_transport===void 0&&(p.raw_transport=t==="gemini");const U=`${t}/base`,$=s==="claude"?"claude":s==="codex"?"codex":s==="pi"?"pi":t==="kiro"?"kiro":"gemini";let y;try{const j=$==="kiro"?void 0:process.cwd();y=G({mode:$,projectDir:j})??void 0,y&&y.length===0&&(y=void 0)}catch{}const M=W();if(M.length>0){const v=K([...y??[],...M]),I=v.filter(C=>C.source==="connector").map(C=>C.name);I.length>0&&c.info("manager",`[${n.name}] injecting connector skills: [${I.join(", ")}]`),y=v.length>0?v:void 0}return{name:n.name,adapterType:s,aibot:{url:a,agentId:n.agent_id,apiKey:n.api_key,clientType:t,clientVersion:e,adapterHint:o.adapterHint??_?.adapterHint??h?.adapterHint??g?.adapterHint??w?.adapterHint??T?.adapterHint??k?.adapterHint??U,capabilities:i?.capabilities??b?.capabilities??h?.capabilities??g?.capabilities??w?.capabilities??T?.capabilities??k?.capabilities??_?.capabilities??["stream_chunk","local_action_v1","connector_upgrade"],localActions:re(i?.localActions??b?.localActions??m?.localActions??h?.localActions??g?.localActions??w?.localActions??T?.localActions??k?.localActions??_?.localActions??H?.localActions??P?.localActions??["exec_approve","exec_reject"],N,O,["connector_rollback","connector_upgrade_push",l]),skills:y},agent:{command:o.command,args:o.args,env:void 0},adapterOptions:p,acpAuthMethod:p.auth_method,acpInitialMode:p.initial_mode,acpMcpTools:p.acp_mcp_tools,promptTimeoutMs:n.prompt_timeout_ms,bindingsPath:oe(n.name),activeEventStorePath:ie(n.name),...o.enableSessionBinding||d?{enableSessionBinding:!0}:{},...o.autoInjectArgs?{autoInjectArgs:o.autoInjectArgs}:{},poolMaxSize:n.pool?.maxSize,poolIdleTimeoutMs:n.pool?.idleTimeoutMs,eventQueue:se(s,n.event_queue),logDir:x.log,providerBaseUrl:n.provider_base_url?.trim()||void 0,providerApiKey:n.provider_api_key?.trim()||void 0}}function ce(){const n=process.env.GRIX_AGENT_STARTUP_WAIT_MS,e=Number(n);return Number.isFinite(e)&&e>=500?Math.floor(e):ee}class ke{instances=[];configMap=new Map;upgradeChecker=null;globalConfigStore;configDir=x.config;installer=new Y;async start(e){const t=e??x.config;this.configDir=t,c.info("manager",`Loading configs from ${t}`),V(),D(),this.globalConfigStore=new z(A(x.data,"agent-global-configs.json")),this.globalConfigStore.load();const o=F(t).filter(l=>l.endsWith(".json")).sort();if(o.length===0)throw new Error(`No config files found in ${t}`);const a=[];let r=0;for(const l of o)try{const s=Q(A(t,l),"utf-8"),d=JSON.parse(s);if(Array.isArray(d.agents)){if(d.agents.length===0){c.error("manager",`No agents array found in ${l}`),r++;continue}for(const f of d.agents)try{const p=E(f);a.push({config:p,file:l}),c.info("manager",`Loaded ${p.name} (${p.adapterType??"acp"}) from ${l}`)}catch(p){const i=typeof f?.name=="string"?f.name:"<unknown>";c.error("manager",`Invalid agent config in ${l} (name=${i}): ${p}`),r++}}else c.error("manager",`Unrecognized config format in ${l}`)}catch(s){c.error("manager",`Failed to load ${l}: ${s}`)}let u=0;if(a.length>0){const l=ce();c.info("manager",`Starting ${a.length} agent(s), startup wait=${l}ms`);const s=()=>this.upgradeChecker?.triggerCheck(),d=i=>{this.instances=this.instances.filter(m=>m!==i)},f=a.map(({config:i})=>{const m=new S(i,this.globalConfigStore);return m.setUpgradeTrigger(s),this.instances.push(m),this.configMap.set(i.name,i),{config:i,instance:m,startPromise:m.start()}}),p=await Promise.all(f.map(async i=>{const m=await new Promise(_=>{let h=!1;const g=setTimeout(()=>{h||(h=!0,_({kind:"timeout"}))},l);i.startPromise.then(()=>{h||(h=!0,clearTimeout(g),_({kind:"started"}))}).catch(w=>{h||(h=!0,clearTimeout(g),_({kind:"failed",error:w}))})});return{task:i,outcome:m}}));for(const{task:i,outcome:m}of p)if(m.kind!=="started"){if(m.kind==="failed"){d(i.instance),c.error("manager",`Failed to start ${i.config.name}: ${m.error}`);continue}u++,c.warn("manager",`Startup pending for ${i.config.name}, continue retrying in background`),i.startPromise.then(()=>{c.info("manager",`Delayed start succeeded: ${i.config.name}`)}).catch(_=>{d(i.instance),c.error("manager",`Delayed start failed: ${i.config.name}: ${_}`)})}if(this.instances.length>0){const i=Math.max(0,this.instances.length-u);c.info("manager",`${i}/${a.length} agent(s) running now`)}u>0&&c.warn("manager",`${u} agent(s) still connecting in background`)}if(this.instances.length===0&&a.length>0)throw new Error("All agent configurations failed to start");if(a.length>0){const l=a[0].config;this.upgradeChecker=new R([{apiKey:l.aibot.apiKey,wsUrl:l.aibot.url}],()=>this.instances.some(s=>s.getStatus().busy)),await this.upgradeChecker.start()}}async stop(){c.info("manager","Stopping all agents..."),this.upgradeChecker?.stop(),await Promise.allSettled(this.instances.map(e=>e.stop())),await this.globalConfigStore?.flush(),this.instances=[],D(),c.info("manager","All stopped")}getAgentsStatus(){return this.instances.map(e=>e.getStatus())}async addAgent(e){const t=E(e);if(this.instances.some(a=>a.name===t.name))throw new Error(`Agent "${t.name}" already exists`);const o=new S(t,this.globalConfigStore);o.setUpgradeTrigger(()=>this.upgradeChecker?.triggerCheck()),await o.start(),this.instances.push(o),this.configMap.set(t.name,t),this.persistAgentsConfig(),c.info("manager",`Added agent: ${t.name}`)}async removeAgent(e){const t=this.instances.findIndex(a=>a.name===e);if(t===-1)throw Object.assign(new Error(`Agent "${e}" not found`),{code:"NOT_FOUND"});const o=this.instances[t];this.instances.splice(t,1),this.configMap.delete(e),await o.stop(),this.persistAgentsConfig(),c.info("manager",`Removed agent: ${e}`)}persistAgentsConfig(){const e=A(this.configDir,"agents.json");try{const t=[];for(const[,a]of this.configMap)t.push({name:a.name,ws_url:a.aibot.url,agent_id:a.aibot.agentId,api_key:a.aibot.apiKey,client_type:a.aibot.clientType});B(e,JSON.stringify({agents:t},null,4)+`
|
|
1
|
+
import{readFileSync as Q,readdirSync as F,writeFileSync as B}from"node:fs";import{join as A}from"node:path";import{AgentInstance as S}from"./bridge/bridge.js";import{GRIX_PATHS as x,log as c}from"./core/log/index.js";import{resolveClientVersion as L}from"./core/util/client-version.js";import{UpgradeChecker as R}from"./core/upgrade/upgrade-checker.js";import{AgentGlobalConfigStore as z}from"./core/persistence/agent-global-config-store.js";import{scanSkills as G,dedupeSkills as K}from"./adapter/claude/skill-scanner.js";import{scanDefaultSkills as W,logDefaultSkillsCheck as V,cleanupProjectedSkills as D}from"./default-skills/index.js";import{resolveCopilotCommand as q}from"./core/runtime/copilot-resolve.js";import{getCliVersion as J,resolveCliPath as X}from"./core/util/cli-probe.js";import{AgentInstaller as Y}from"./core/installer/installer.js";import{reportInstallFailure as Z}from"./core/observability/sentry.js";const ee=8e3;function te(){const n=q();return[{clientType:"openclaw",command:"openclaw"},{clientType:"claude",command:"claude"},{clientType:"codex",command:"codex"},{clientType:"gemini",command:"gemini"},{clientType:"qwen",command:"qwen"},{clientType:"hermes",command:"hermes"},{clientType:"reasonix",command:"reasonix"},{clientType:"codewhale",command:"codewhale"},{clientType:"opencode",command:"opencode"},{clientType:"cursor",command:"agent"},{clientType:"pi",command:"pi"},{clientType:"openhuman",command:"openhuman-core"},{clientType:"kiro",command:"kiro-cli"},{clientType:"copilot",command:n.command},{clientType:"agy",command:"agy"}]}async function ne(){return Promise.all(te().map(async n=>{const e=await X(n.command);if(!e)return{client_type:n.clientType,command:n.command,installed:!1,path:null,version:null};const t=await J(e,n.versionArgs??["--version"]);return{client_type:n.clientType,command:n.command,installed:!0,path:e,version:t.version,error:t.error}}))}function ae(n){switch(n){case"claude":return{adapterType:"claude",command:"claude"};case"codex":return{adapterType:"codex",command:"codex",options:{sandboxMode:"danger-full-access"}};case"gemini":return{adapterType:"acp",command:"gemini",autoInjectArgs:{acp:!0},enableSessionBinding:!0};case"qwen":return{adapterType:"acp",command:"qwen",adapterHint:"qwen/base",autoInjectArgs:{acp:!0},enableSessionBinding:!0};case"pi":return{adapterType:"pi",command:"pi"};case"cursor":return{adapterType:"cursor",command:"agent"};case"reasonix":return{adapterType:"acp",command:"reasonix",args:["acp"],enableSessionBinding:!0};case"codewhale":return{adapterType:"codewhale",command:"codewhale",enableSessionBinding:!0};case"openhuman":return{adapterType:"openhuman",command:"openhuman-core",enableSessionBinding:!0};case"kiro":return{adapterType:"acp",command:"kiro-cli",args:["acp"],enableSessionBinding:!0};case"opencode":return{adapterType:"opencode",command:"opencode",args:["serve"],enableSessionBinding:!0};case"copilot":{const e=q();return{adapterType:"acp",command:e.command,args:[...e.prefixArgs,"--acp"],enableSessionBinding:!0}}case"agy":return{adapterType:"agy",command:"agy",enableSessionBinding:!0};case"hermes":throw new Error('client_type "hermes" is not handled by grix-connector. Hermes runs as a separate project \u2014 see https://github.com/askie/grix-hermes-python');default:throw new Error(`Unsupported client_type: ${n}`)}}function oe(n){const e=String(n??"").trim().toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")||"default";return A(x.data,`session-bindings-${e}.json`)}function ie(n){const e=String(n??"").trim().toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")||"default";return A(x.data,`active-events-${e}.json`)}function re(...n){const e=[],t=new Set;for(const o of n)for(const a of o??[]){const r=String(a??"").trim(),u=r.toLowerCase();!r||t.has(u)||(t.add(u),e.push(r))}return e.length>0?e:void 0}function se(n,e){const t={claude:{maxConcurrent:1,maxQueued:5,queueTimeoutMs:0},codex:{maxConcurrent:1,maxQueued:5,queueTimeoutMs:0},cursor:{maxConcurrent:1,maxQueued:3,queueTimeoutMs:0},acp:{maxConcurrent:1,maxQueued:3,queueTimeoutMs:0},pi:{maxConcurrent:1,maxQueued:5,queueTimeoutMs:0},codewhale:{maxConcurrent:1,maxQueued:3,queueTimeoutMs:0},openhuman:{maxConcurrent:1,maxQueued:3,queueTimeoutMs:0},opencode:{maxConcurrent:1,maxQueued:3,queueTimeoutMs:0},agy:{maxConcurrent:1,maxQueued:3,queueTimeoutMs:0}},o=t[n]??t.acp;return{maxConcurrent:e?.max_concurrent??o.maxConcurrent??1,maxQueued:e?.max_queued??o.maxQueued??3,queueTimeoutMs:e?.queue_timeout_ms??o.queueTimeoutMs??0,cancelableQueued:!0,cancelableRunning:!0}}function E(n){const e=L(),t=String(n.client_type??"").trim().toLowerCase(),o=ae(t),a=String(n.ws_url??"").trim(),r="get_session_usage",u="get_rate_limits",l="get_agent_global_config";if(!n.name?.trim())throw new Error("agent name is required");if(!a)throw new Error(`agent ${n.name}: ws_url is required`);if(!n.agent_id?.trim())throw new Error(`agent ${n.name}: agent_id is required`);if(!n.api_key?.trim())throw new Error(`agent ${n.name}: api_key is required`);const s=o.adapterType,d=s==="acp",f=t==="qwen",p={...o.options??{}},i=s==="codex"?{capabilities:["local_action_v1","agent_invoke"],localActions:["session_control","get_context","set_model","set_mode","set_reasoning_effort","set_sandbox_mode","exec_approve","exec_reject","file_list","create_folder","turn_interrupt","permission_approve","permission_reject","thread_compact",r,u]}:null,m=s==="claude"?{localActions:["session_control","set_mode","set_model","claude_interaction_reply","exec_approve","exec_reject","file_list","create_folder","thread_compact",r,u]}:null,_=f?{capabilities:["stream_chunk","local_action_v1"],localActions:["exec_approve","exec_reject","permission_approve","permission_reject","session_control","set_model","set_mode","file_list","create_folder",r],adapterHint:"qwen/base"}:null,h=s==="pi"?{adapterHint:"pi/base",capabilities:["local_action_v1"],localActions:["session_control","set_model","get_context","file_list","create_folder",r]}:null,g=s==="openhuman"?{adapterHint:"openhuman/base",capabilities:["local_action_v1"],localActions:["session_control","set_model","file_list","create_folder",r]}:null,w=s==="cursor"?{adapterHint:"cursor/base",capabilities:["stream_chunk","local_action_v1"],localActions:["session_control","set_model","set_mode","get_context","file_list","create_folder",r,u]}:null,b=s==="codewhale"?{capabilities:["stream_chunk","local_action_v1"],localActions:["session_control","set_model","file_list","create_folder",r]}:null,T=s==="opencode"?{adapterHint:"opencode/base",capabilities:["stream_chunk","local_action_v1"],localActions:["exec_approve","exec_reject","permission_approve","permission_reject","session_control","set_model","set_mode","file_list","create_folder",r]}:null,k=s==="agy"?{adapterHint:"agy/base",capabilities:["stream_chunk","local_action_v1"],localActions:["session_control","set_model","file_list","create_folder",r]}:null,P=d&&!f?{localActions:["exec_approve","exec_reject","permission_approve","permission_reject","session_control","set_model","set_mode","file_list","create_folder",r]}:null,H=t==="kiro"?{localActions:["exec_approve","exec_reject","permission_approve","permission_reject","session_control","set_model","set_mode","file_list","create_folder","thread_compact",r,u]}:null,N=s==="codex"||s==="claude"||t==="gemini"?["session_control","set_model","set_mode"]:void 0,O=[r,u];d&&p.raw_transport===void 0&&(p.raw_transport=t==="gemini");const U=`${t}/base`,$=s==="claude"?"claude":s==="codex"?"codex":s==="pi"?"pi":t==="kiro"?"kiro":"gemini";let y;try{const j=$==="kiro"?void 0:process.cwd();y=G({mode:$,projectDir:j})??void 0,y&&y.length===0&&(y=void 0)}catch{}const M=W();if(M.length>0){const v=K([...y??[],...M]),I=v.filter(C=>C.source==="connector").map(C=>C.name);I.length>0&&c.info("manager",`[${n.name}] injecting connector skills: [${I.join(", ")}]`),y=v.length>0?v:void 0}return{name:n.name,adapterType:s,aibot:{url:a,agentId:n.agent_id,apiKey:n.api_key,clientType:t,clientVersion:e,adapterHint:o.adapterHint??_?.adapterHint??h?.adapterHint??g?.adapterHint??w?.adapterHint??T?.adapterHint??k?.adapterHint??U,capabilities:i?.capabilities??b?.capabilities??h?.capabilities??g?.capabilities??w?.capabilities??T?.capabilities??k?.capabilities??_?.capabilities??["stream_chunk","local_action_v1","connector_upgrade"],localActions:re(i?.localActions??b?.localActions??m?.localActions??h?.localActions??g?.localActions??w?.localActions??T?.localActions??k?.localActions??_?.localActions??H?.localActions??P?.localActions??["exec_approve","exec_reject"],N,O,["connector_rollback","connector_upgrade_push",l]),skills:y},agent:{command:o.command,args:[...o.args??[],...n.args??[]],env:n.env},adapterOptions:p,acpAuthMethod:p.auth_method,acpInitialMode:p.initial_mode,acpMcpTools:p.acp_mcp_tools,promptTimeoutMs:n.prompt_timeout_ms,bindingsPath:oe(n.name),activeEventStorePath:ie(n.name),...o.enableSessionBinding||d?{enableSessionBinding:!0}:{},...o.autoInjectArgs?{autoInjectArgs:o.autoInjectArgs}:{},poolMaxSize:n.pool?.maxSize,poolIdleTimeoutMs:n.pool?.idleTimeoutMs,eventQueue:se(s,n.event_queue),logDir:x.log,providerBaseUrl:n.provider_base_url?.trim()||void 0,providerApiKey:n.provider_api_key?.trim()||void 0}}function ce(){const n=process.env.GRIX_AGENT_STARTUP_WAIT_MS,e=Number(n);return Number.isFinite(e)&&e>=500?Math.floor(e):ee}class ke{instances=[];configMap=new Map;upgradeChecker=null;globalConfigStore;configDir=x.config;installer=new Y;async start(e){const t=e??x.config;this.configDir=t,c.info("manager",`Loading configs from ${t}`),V(),D(),this.globalConfigStore=new z(A(x.data,"agent-global-configs.json")),this.globalConfigStore.load();const o=F(t).filter(l=>l.endsWith(".json")).sort();if(o.length===0)throw new Error(`No config files found in ${t}`);const a=[];let r=0;for(const l of o)try{const s=Q(A(t,l),"utf-8"),d=JSON.parse(s);if(Array.isArray(d.agents)){if(d.agents.length===0){c.error("manager",`No agents array found in ${l}`),r++;continue}for(const f of d.agents)try{const p=E(f);a.push({config:p,file:l}),c.info("manager",`Loaded ${p.name} (${p.adapterType??"acp"}) from ${l}`)}catch(p){const i=typeof f?.name=="string"?f.name:"<unknown>";c.error("manager",`Invalid agent config in ${l} (name=${i}): ${p}`),r++}}else c.error("manager",`Unrecognized config format in ${l}`)}catch(s){c.error("manager",`Failed to load ${l}: ${s}`)}let u=0;if(a.length>0){const l=ce();c.info("manager",`Starting ${a.length} agent(s), startup wait=${l}ms`);const s=()=>this.upgradeChecker?.triggerCheck(),d=i=>{this.instances=this.instances.filter(m=>m!==i)},f=a.map(({config:i})=>{const m=new S(i,this.globalConfigStore);return m.setUpgradeTrigger(s),this.instances.push(m),this.configMap.set(i.name,i),{config:i,instance:m,startPromise:m.start()}}),p=await Promise.all(f.map(async i=>{const m=await new Promise(_=>{let h=!1;const g=setTimeout(()=>{h||(h=!0,_({kind:"timeout"}))},l);i.startPromise.then(()=>{h||(h=!0,clearTimeout(g),_({kind:"started"}))}).catch(w=>{h||(h=!0,clearTimeout(g),_({kind:"failed",error:w}))})});return{task:i,outcome:m}}));for(const{task:i,outcome:m}of p)if(m.kind!=="started"){if(m.kind==="failed"){d(i.instance),c.error("manager",`Failed to start ${i.config.name}: ${m.error}`);continue}u++,c.warn("manager",`Startup pending for ${i.config.name}, continue retrying in background`),i.startPromise.then(()=>{c.info("manager",`Delayed start succeeded: ${i.config.name}`)}).catch(_=>{d(i.instance),c.error("manager",`Delayed start failed: ${i.config.name}: ${_}`)})}if(this.instances.length>0){const i=Math.max(0,this.instances.length-u);c.info("manager",`${i}/${a.length} agent(s) running now`)}u>0&&c.warn("manager",`${u} agent(s) still connecting in background`)}if(this.instances.length===0&&a.length>0)throw new Error("All agent configurations failed to start");if(a.length>0){const l=a[0].config;this.upgradeChecker=new R([{apiKey:l.aibot.apiKey,wsUrl:l.aibot.url}],()=>this.instances.some(s=>s.getStatus().busy)),await this.upgradeChecker.start()}}async stop(){c.info("manager","Stopping all agents..."),this.upgradeChecker?.stop(),await Promise.allSettled(this.instances.map(e=>e.stop())),await this.globalConfigStore?.flush(),this.instances=[],D(),c.info("manager","All stopped")}getAgentsStatus(){return this.instances.map(e=>e.getStatus())}async addAgent(e){const t=E(e);if(this.instances.some(a=>a.name===t.name))throw new Error(`Agent "${t.name}" already exists`);const o=new S(t,this.globalConfigStore);o.setUpgradeTrigger(()=>this.upgradeChecker?.triggerCheck()),await o.start(),this.instances.push(o),this.configMap.set(t.name,t),this.persistAgentsConfig(),c.info("manager",`Added agent: ${t.name}`)}async removeAgent(e){const t=this.instances.findIndex(a=>a.name===e);if(t===-1)throw Object.assign(new Error(`Agent "${e}" not found`),{code:"NOT_FOUND"});const o=this.instances[t];this.instances.splice(t,1),this.configMap.delete(e),await o.stop(),this.persistAgentsConfig(),c.info("manager",`Removed agent: ${e}`)}persistAgentsConfig(){const e=A(this.configDir,"agents.json");try{const t=[];for(const[,a]of this.configMap)t.push({name:a.name,ws_url:a.aibot.url,agent_id:a.aibot.agentId,api_key:a.aibot.apiKey,client_type:a.aibot.clientType});B(e,JSON.stringify({agents:t},null,4)+`
|
|
2
2
|
`,"utf-8")}catch(t){c.error("manager",`Failed to persist agents config: ${t}`)}}async restartAgent(e){const t=this.instances.findIndex(u=>u.name===e);if(t===-1)throw Object.assign(new Error(`Agent "${e}" not found`),{code:"NOT_FOUND"});const o=this.configMap.get(e);if(!o)throw Object.assign(new Error(`Config for "${e}" not found`),{code:"NOT_FOUND"});await this.instances[t].stop();const r=new S(o,this.globalConfigStore);r.setUpgradeTrigger(()=>this.upgradeChecker?.triggerCheck()),await r.start(),this.instances[t]=r,c.info("manager",`Restarted agent: ${e}`)}async checkUpgrade(){return this.upgradeChecker?this.upgradeChecker.checkForUpdate():{available:!1}}triggerUpgrade(){this.upgradeChecker?.triggerCheck()}async probeAll(e={}){return le(this.instances,e)}async probeOne(e,t={}){return de(this.instances,e,t)}listInstallable(){return this.installer.listInstallable()}async installAgent(e){const t=await this.installer.install(e);return Z(t),t}getInstallProgress(e){return this.installer.getProgress(e)??null}}async function le(n,e){const t=e.concurrency??4,o=Date.now(),a=new Array(n.length);await new Promise(d=>{let f=0,p=0;const i=n.length;if(i===0){d();return}function m(g){const w=n[g];w.probe(e).then(b=>{a[g]=b,_()},b=>{a[g]={agent_name:w.name,client_type:"unknown",adapter_type:"acp",ok:!1,status:"error",probed_at:Date.now(),duration_ms:0,cached:!1,cli:{command:"",installed:!1,path:null,version:null,error:{code:"internal",message:b?.message??String(b)}},conversation:{attempted:!1,ok:!1,latency_ms:null},config:{model:null,base_url:null,source:{model:"unknown",base_url:"unknown"}},process:{started:!1,alive:!1,busy:!1}},_()})}function _(){p++,f<i?m(f++):p===i&&d()}const h=Math.min(t,i);for(let g=0;g<h;g++)m(f++)});const r=a.filter(d=>d.status==="healthy").length,u=a.filter(d=>d.status==="degraded").length,l=a.filter(d=>d.status==="unavailable").length,s=await ne();return{ok:r===a.length&&a.length>0,total:a.length,healthy:r,degraded:u,unavailable:l,installed_clients:s,agents:a,probed_at:o,duration_ms:Date.now()-o}}async function de(n,e,t){const o=n.find(a=>a.name===e);if(!o)throw Object.assign(new Error(`Agent "${e}" not found`),{code:"NOT_FOUND"});return o.probe(t)}export{ke as Manager,ne as probeInstalledClientCommands,le as probeInstances,de as probeOneInstance};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as i from"node:net";const e={bind:"127.0.0.1",port:0,endpoint:"/mcp",sessionTimeoutMs:18e5,invokeTimeoutMs:3e4};function n(o){const u={bind:o?.bind??e.bind,port:o?.port??e.port,endpoint:o?.endpoint??e.endpoint,sessionTimeoutMs:o?.sessionTimeoutMs??e.sessionTimeoutMs,invokeTimeoutMs:o?.invokeTimeoutMs??e.invokeTimeoutMs,allowedOrigins:o?.allowedOrigins,allowedHosts:o?.allowedHosts};return s(u.bind),u.port!==0&&t(u.port),r(u.sessionTimeoutMs),u}function s(o){if(!o||!i.isIPv4(o)&&!i.isIPv6(o))throw new Error(`\u914D\u7F6E\u6821\u9A8C\u5931\u8D25: bind \u5730\u5740 "${o}" \u4E0D\u662F\u5408\u6CD5\u7684 IPv4 \u6216 IPv6 \u5730\u5740`)}function t(o){if(!Number.isInteger(o)||o<1||o>65535)throw new Error(`\u914D\u7F6E\u6821\u9A8C\u5931\u8D25: port \u503C ${o} \u4E0D\u5728\u5408\u6CD5\u8303\u56F4 1-65535 \u5185\u6216\u4E0D\u662F\u6574\u6570`)}function r(o){if(!Number.isInteger(o)||o<1e3||o>864e5)throw new Error(`\u914D\u7F6E\u6821\u9A8C\u5931\u8D25: session_timeout_ms \u503C ${o} \u4E0D\u5728\u5408\u6CD5\u8303\u56F4 1000-86400000 \u5185`)}export{n as createDefaultGatewayConfig};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const r=3e4;class c{connectionManager;onDisconnected;bindings=new Map;constructor(n,i){this.connectionManager=n,this.onDisconnected=i}async bind(n,i){if(this.bindings.has(n))throw new Error(`Session ${n} is already bound to a connection`);const e=await this.connectWithTimeout(i),t=[],s=e.onDisconnected(()=>{this.removeBinding(n),this.onDisconnected(n)});return t.push(s),this.bindings.set(n,{sessionId:n,handle:e,subscriptions:t}),e}getHandle(n){return this.bindings.get(n)?.handle}unbind(n){const i=this.bindings.get(n);if(i){this.bindings.delete(n);for(const e of i.subscriptions)e();i.handle.disconnect()}}unbindAll(){const n=[...this.bindings.keys()];for(const i of n)this.unbind(i)}connectWithTimeout(n){return new Promise((i,e)=>{let t=!1;const s=setTimeout(()=>{t||(t=!0,e(new Error("Connection bind timeout after 30000ms")))},3e4);this.connectionManager.connect({agentId:n.agentId,apiKey:n.apiKey,url:n.wsUrl,clientType:n.clientType,capabilities:["agent_invoke"],adapterHint:`${n.clientType}/base`},{maxRetries:0}).then(o=>{t?o.disconnect():(t=!0,clearTimeout(s),i(o))}).catch(o=>{t||(t=!0,clearTimeout(s),e(o))})})}removeBinding(n){const i=this.bindings.get(n);if(i){this.bindings.delete(n);for(const e of i.subscriptions)e()}}}export{c as ConnectionBindingImpl};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{toolCallToInvoke as i}from"../../core/mcp/tools.js";import{ToolRegistryImpl as l}from"./tool-registry.js";import{validateToolArgs as a}from"./tool-schemas.js";import{isEventTool as p,executeEventTool as d}from"./event-tool-executor.js";class y{registry;constructor(){this.registry=new l}async execute(
|
|
1
|
+
import{toolCallToInvoke as i}from"../../core/mcp/tools.js";import{ToolRegistryImpl as l}from"./tool-registry.js";import{validateToolArgs as a}from"./tool-schemas.js";import{isEventTool as p,executeEventTool as d}from"./event-tool-executor.js";class y{registry;constructor(){this.registry=new l}async execute(t,e,r,n){if(!this.registry.hasTool(e))return this.errorResult(`\u672A\u77E5\u5DE5\u5177: ${e}`);const s=a(e,r);if(!s.valid)return this.errorResult(`\u53C2\u6570\u6821\u9A8C\u5931\u8D25: ${s.error}`);if(t.status!=="ready")return this.errorResult(`\u8FDE\u63A5\u4E0D\u53EF\u7528: \u5F53\u524D\u72B6\u6001\u4E3A ${t.status}`);if(p(e))return this.executeEventTool(t,e,r);const o=i(e,r);try{const u=await t.agentInvoke(o.action,o.params,n);return this.normalizeResult(u)}catch(u){const c=u instanceof Error?u.message:String(u);return c.toLowerCase().includes("timeout")?this.errorResult(`\u8C03\u7528\u8D85\u65F6: ${c}`):this.errorResult(`\u8C03\u7528\u5931\u8D25: ${c}`)}}normalizeResult(t){if(t==null||typeof t!="object")return this.successResult(t??null);const e=t,r=typeof e.code=="number"?e.code:0;if(r===0){const s="data"in e?e.data:null;return this.successResult(s??null)}const n=typeof e.msg=="string"?e.msg:"\u672A\u77E5\u9519\u8BEF";return this.errorResult(`\u4E0A\u6E38\u9519\u8BEF [code=${r}]: ${n}`)}successResult(t){return{content:[{type:"text",text:JSON.stringify(t)}],isError:!1}}errorResult(t){return{content:[{type:"text",text:t}],isError:!0}}async executeEventTool(t,e,r){return e==="grix_access_control"?this.executeAccessControl(t,r):d(t,e,r)}async executeAccessControl(t,e){const r=String(e.action??""),n={pair_approve:"pair_approve",pair_deny:"pair_deny",allow_sender:"sender_allow",remove_sender:"sender_remove",set_policy:"policy_set"}[r];if(!n)return this.errorResult(`\u672A\u77E5 access_control action: ${r}`);const s={};e.code!=null&&(s.code=e.code),e.sender_id!=null&&(s.sender_id=e.sender_id),e.policy!=null&&(s.policy=e.policy);try{const o=await t.agentInvoke("claude_access_control",{verb:n,payload:s},3e4);return this.successResult(o)}catch(o){const u=o instanceof Error?o.message:String(o);return this.errorResult(`access_control \u8C03\u7528\u5931\u8D25: ${u}`)}}}export{y as ToolExecutorImpl};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{TOOLS as
|
|
1
|
+
import{TOOLS as s,EVENT_TOOLS as t}from"../../core/mcp/tools.js";const e=new Set(["grix_query","grix_group","grix_message_send","grix_message_unsend","grix_admin"]),r=new Set(["grix_reply","grix_complete","grix_event_ack","grix_composing","grix_access_control","grix_status"]);class a{tools;toolMap;constructor(){this.tools=[...s.filter(o=>e.has(o.name)),...t.filter(o=>r.has(o.name))],this.toolMap=new Map(this.tools.map(o=>[o.name,o]))}getTools(){return this.tools}getTool(o){return this.toolMap.get(o)}hasTool(o){return this.toolMap.has(o)}}export{a as ToolRegistryImpl};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const o={required:["action"],properties:{action:{type:"string",enum:["contact_search","session_search","message_history","message_search"]},id:{type:"string"},keyword:{type:"string",maxLength:200},limit:{type:"integer",minimum:1,maximum:100},offset:{type:"integer",minimum:0},sessionId:{type:"string"},beforeId:{type:"string"}}},a={required:["action"],properties:{action:{type:"string",enum:["create","detail","leave","add_members","remove_members","update_member_role","update_all_members_muted","update_member_speaking","dissolve"]},sessionId:{type:"string"},name:{type:"string",maxLength:128},memberIds:{type:"array",items:{type:"string"},maxItems:100},memberTypes:{type:"array",items:{type:"integer",enum:[1,2]}},memberId:{type:"string"},role:{type:"integer",enum:[1,2]},memberType:{type:"integer"},allMembersMuted:{type:"boolean"},isSpeakMuted:{type:"boolean"},canSpeakWhenAllMuted:{type:"boolean"}}},p={required:["sessionId","content"],properties:{sessionId:{type:"string"},content:{type:"string",maxLength:1e4},msgType:{type:"integer"},quotedMessageId:{type:"string"},threadId:{type:"string"}}},m={required:["sessionId","msgId"],properties:{sessionId:{type:"string"},msgId:{type:"string"}}},g={required:["action"],properties:{action:{type:"string",enum:["create_agent","list_categories","create_category","update_category","assign_category","rotate_api_key"]},agentName:{type:"string"},introduction:{type:"string"},isMain:{type:"boolean"},agentId:{type:"string"},categoryId:{type:"string"},name:{type:"string"},parentId:{type:"string"},sortOrder:{type:"integer"}}},y={required:["session_id","text"],properties:{event_id:{type:"string"},session_id:{type:"string"},text:{type:"string",maxLength:5e4},quoted_message_id:{type:"string"},is_final:{type:"boolean"}}},d={required:["event_id","status"],properties:{event_id:{type:"string"},status:{type:"string",enum:["responded","canceled","failed"]},msg:{type:"string",maxLength:500}}},c={required:["event_id"],properties:{event_id:{type:"string"},session_id:{type:"string"}}},l={required:["session_id","active"],properties:{session_id:{type:"string"},active:{type:"boolean"},event_id:{type:"string"}}},_={required:["action"],properties:{action:{type:"string",enum:["pair_approve","pair_deny","allow_sender","remove_sender","set_policy"]},code:{type:"string"},sender_id:{type:"string"},policy:{type:"string",enum:["allowlist","open","disabled"]}}},f={required:[],properties:{}},C={grix_query:o,grix_group:a,grix_message_send:p,grix_message_unsend:m,grix_admin:g,grix_reply:y,grix_complete:d,grix_event_ack:c,grix_composing:l,grix_access_control:_,grix_status:f};function B(
|
|
1
|
+
const o={required:["action"],properties:{action:{type:"string",enum:["contact_search","session_search","message_history","message_search"]},id:{type:"string"},keyword:{type:"string",maxLength:200},limit:{type:"integer",minimum:1,maximum:100},offset:{type:"integer",minimum:0},sessionId:{type:"string"},beforeId:{type:"string"}}},a={required:["action"],properties:{action:{type:"string",enum:["create","detail","leave","add_members","remove_members","update_member_role","update_all_members_muted","update_member_speaking","dissolve"]},sessionId:{type:"string"},name:{type:"string",maxLength:128},memberIds:{type:"array",items:{type:"string"},maxItems:100},memberTypes:{type:"array",items:{type:"integer",enum:[1,2]}},memberId:{type:"string"},role:{type:"integer",enum:[1,2]},memberType:{type:"integer"},allMembersMuted:{type:"boolean"},isSpeakMuted:{type:"boolean"},canSpeakWhenAllMuted:{type:"boolean"}}},p={required:["sessionId","content"],properties:{sessionId:{type:"string"},content:{type:"string",maxLength:1e4},msgType:{type:"integer"},quotedMessageId:{type:"string"},threadId:{type:"string"}}},m={required:["sessionId","msgId"],properties:{sessionId:{type:"string"},msgId:{type:"string"}}},g={required:["action"],properties:{action:{type:"string",enum:["create_agent","list_categories","create_category","update_category","assign_category","rotate_api_key"]},agentName:{type:"string"},introduction:{type:"string"},isMain:{type:"boolean"},agentId:{type:"string"},categoryId:{type:"string"},name:{type:"string"},parentId:{type:"string"},sortOrder:{type:"integer"}}},y={required:["session_id","text"],properties:{event_id:{type:"string"},session_id:{type:"string"},text:{type:"string",maxLength:5e4},quoted_message_id:{type:"string"},is_final:{type:"boolean"}}},d={required:["event_id","status"],properties:{event_id:{type:"string"},status:{type:"string",enum:["responded","canceled","failed"]},msg:{type:"string",maxLength:500}}},c={required:["event_id"],properties:{event_id:{type:"string"},session_id:{type:"string"}}},l={required:["session_id","active"],properties:{session_id:{type:"string"},active:{type:"boolean"},event_id:{type:"string"}}},_={required:["action"],properties:{action:{type:"string",enum:["pair_approve","pair_deny","allow_sender","remove_sender","set_policy"]},code:{type:"string"},sender_id:{type:"string"},policy:{type:"string",enum:["allowlist","open","disabled"]}}},f={required:[],properties:{}},C={grix_query:o,grix_group:a,grix_message_send:p,grix_message_unsend:m,grix_admin:g,grix_reply:y,grix_complete:d,grix_event_ack:c,grix_composing:l,grix_access_control:_,grix_status:f};function B(u,t){const e=C[u];if(!e)return{valid:!1,error:`\u672A\u77E5\u5DE5\u5177: ${u}`};for(const i of e.required)if(t[i]===void 0||t[i]===null)return{valid:!1,error:`\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570: ${i}`};for(const[i,r]of Object.entries(t)){if(r==null)continue;const n=e.properties[i];if(!n)continue;const s=$(i,r,n);if(s)return{valid:!1,error:s}}return{valid:!0}}function $(u,t,e){switch(e.type){case"string":if(typeof t!="string")return`\u53C2\u6570 ${u} \u7C7B\u578B\u9519\u8BEF: \u671F\u671B string\uFF0C\u5B9E\u9645 ${typeof t}`;if(e.maxLength!==void 0&&t.length>e.maxLength)return`\u53C2\u6570 ${u} \u8D85\u8FC7\u6700\u5927\u957F\u5EA6 ${e.maxLength}\uFF0C\u5B9E\u9645 ${t.length}`;if(e.enum&&!e.enum.includes(t))return`\u53C2\u6570 ${u} \u503C "${t}" \u4E0D\u5728\u5141\u8BB8\u8303\u56F4 [${e.enum.join(", ")}]`;break;case"integer":if(typeof t!="number"||!Number.isInteger(t))return`\u53C2\u6570 ${u} \u7C7B\u578B\u9519\u8BEF: \u671F\u671B integer\uFF0C\u5B9E\u9645 ${typeof t=="number"?"\u6D6E\u70B9\u6570":typeof t}`;if(e.minimum!==void 0&&t<e.minimum)return`\u53C2\u6570 ${u} \u503C ${t} \u5C0F\u4E8E\u6700\u5C0F\u503C ${e.minimum}`;if(e.maximum!==void 0&&t>e.maximum)return`\u53C2\u6570 ${u} \u503C ${t} \u5927\u4E8E\u6700\u5927\u503C ${e.maximum}`;if(e.enum&&!e.enum.includes(t))return`\u53C2\u6570 ${u} \u503C ${t} \u4E0D\u5728\u5141\u8BB8\u8303\u56F4 [${e.enum.join(", ")}]`;break;case"boolean":if(typeof t!="boolean")return`\u53C2\u6570 ${u} \u7C7B\u578B\u9519\u8BEF: \u671F\u671B boolean\uFF0C\u5B9E\u9645 ${typeof t}`;break;case"array":if(!Array.isArray(t))return`\u53C2\u6570 ${u} \u7C7B\u578B\u9519\u8BEF: \u671F\u671B array\uFF0C\u5B9E\u9645 ${typeof t}`;if(e.maxItems!==void 0&&t.length>e.maxItems)return`\u53C2\u6570 ${u} \u8D85\u8FC7\u6700\u5927\u5143\u7D20\u6570 ${e.maxItems}\uFF0C\u5B9E\u9645 ${t.length}`;if(e.items)for(let i=0;i<t.length;i++){const r=t[i];if(e.items.type==="string"&&typeof r!="string")return`\u53C2\u6570 ${u}[${i}] \u7C7B\u578B\u9519\u8BEF: \u671F\u671B string\uFF0C\u5B9E\u9645 ${typeof r}`;if(e.items.type==="integer"){if(typeof r!="number"||!Number.isInteger(r))return`\u53C2\u6570 ${u}[${i}] \u7C7B\u578B\u9519\u8BEF: \u671F\u671B integer\uFF0C\u5B9E\u9645 ${typeof r}`;if(e.items.enum&&!e.items.enum.includes(r))return`\u53C2\u6570 ${u}[${i}] \u503C ${r} \u4E0D\u5728\u5141\u8BB8\u8303\u56F4 [${e.items.enum.join(", ")}]`}}break}}export{B as validateToolArgs};
|
package/openclaw-plugin/index.js
CHANGED
|
@@ -2538,7 +2538,7 @@ function normalizeAibotSessionTarget(raw) {
|
|
|
2538
2538
|
|
|
2539
2539
|
// src/openclaw/client.ts
|
|
2540
2540
|
import { randomUUID } from "node:crypto";
|
|
2541
|
-
import
|
|
2541
|
+
import os6 from "node:os";
|
|
2542
2542
|
|
|
2543
2543
|
// src/openclaw/protocol-send.ts
|
|
2544
2544
|
var AIBOT_PROTOCOL_SEND_RATE_LIMIT = 8;
|
|
@@ -2822,22 +2822,14 @@ async function handleFileListAction(params, context) {
|
|
|
2822
2822
|
const fallbackDir = context.fallbackDir ?? os2.homedir();
|
|
2823
2823
|
const normalizedParentId = params.parent_id ? normalizePlatformPath(params.parent_id) : null;
|
|
2824
2824
|
if (process.platform !== "win32" && normalizedParentId && isWindowsAbsolutePath(normalizedParentId)) {
|
|
2825
|
-
return {
|
|
2826
|
-
status: "failed",
|
|
2827
|
-
error_code: "path_not_found",
|
|
2828
|
-
error_msg: `Directory not found: ${params.parent_id}`
|
|
2829
|
-
};
|
|
2825
|
+
return listHomeFallback(fallbackDir, params, "path_not_found", `Directory not found: ${params.parent_id}`);
|
|
2830
2826
|
}
|
|
2831
2827
|
const targetDir = normalizedParentId ? path2.resolve(normalizedParentId) : cwd || fallbackDir;
|
|
2832
2828
|
let realTarget;
|
|
2833
2829
|
try {
|
|
2834
2830
|
realTarget = await realpath(targetDir);
|
|
2835
2831
|
} catch {
|
|
2836
|
-
return {
|
|
2837
|
-
status: "failed",
|
|
2838
|
-
error_code: "path_not_found",
|
|
2839
|
-
error_msg: `Directory not found: ${targetDir}`
|
|
2840
|
-
};
|
|
2832
|
+
return listHomeFallback(fallbackDir, params, "path_not_found", `Directory not found: ${targetDir}`);
|
|
2841
2833
|
}
|
|
2842
2834
|
if (cwd && !isWinDriveRoot(realTarget)) {
|
|
2843
2835
|
let realCwd;
|
|
@@ -2859,11 +2851,7 @@ async function handleFileListAction(params, context) {
|
|
|
2859
2851
|
realTarget = path2.dirname(realTarget);
|
|
2860
2852
|
}
|
|
2861
2853
|
} catch {
|
|
2862
|
-
return {
|
|
2863
|
-
status: "failed",
|
|
2864
|
-
error_code: "path_not_accessible",
|
|
2865
|
-
error_msg: `Cannot access path: ${targetDir}`
|
|
2866
|
-
};
|
|
2854
|
+
return listHomeFallback(fallbackDir, params, "path_not_accessible", `Cannot access path: ${targetDir}`);
|
|
2867
2855
|
}
|
|
2868
2856
|
try {
|
|
2869
2857
|
const files = await listFiles(realTarget, {
|
|
@@ -2880,6 +2868,23 @@ async function handleFileListAction(params, context) {
|
|
|
2880
2868
|
};
|
|
2881
2869
|
}
|
|
2882
2870
|
}
|
|
2871
|
+
async function listHomeFallback(homeDir, params, errorCode, errorMsg) {
|
|
2872
|
+
try {
|
|
2873
|
+
const realHome = await realpath(homeDir);
|
|
2874
|
+
const files = await listFiles(realHome, {
|
|
2875
|
+
showHidden: params.show_hidden,
|
|
2876
|
+
allowedExtensions: params.allowed_extensions
|
|
2877
|
+
});
|
|
2878
|
+
return {
|
|
2879
|
+
status: "failed",
|
|
2880
|
+
result: { files, current_path: realHome },
|
|
2881
|
+
error_code: errorCode,
|
|
2882
|
+
error_msg: errorMsg
|
|
2883
|
+
};
|
|
2884
|
+
} catch {
|
|
2885
|
+
return { status: "failed", error_code: errorCode, error_msg: errorMsg };
|
|
2886
|
+
}
|
|
2887
|
+
}
|
|
2883
2888
|
function isWithinPath(target, ancestor) {
|
|
2884
2889
|
const normalizedTarget = target.endsWith(path2.sep) ? target : target + path2.sep;
|
|
2885
2890
|
const normalizedAncestor = ancestor.endsWith(path2.sep) ? ancestor : ancestor + path2.sep;
|
|
@@ -2892,8 +2897,29 @@ function isWindowsAbsolutePath(p) {
|
|
|
2892
2897
|
return /^[A-Za-z]:[/\\]/.test(p) || p.startsWith("\\\\");
|
|
2893
2898
|
}
|
|
2894
2899
|
|
|
2900
|
+
// src/core/util/codex-output-policy.ts
|
|
2901
|
+
var DEFAULT_VISIBLE_PHASES = Object.freeze(["commentary", "final_answer"]);
|
|
2902
|
+
var EMPTY_PHASES = Object.freeze([]);
|
|
2903
|
+
function parsePhaseEnvVar(envValue) {
|
|
2904
|
+
if (!envValue || !envValue.trim()) return EMPTY_PHASES;
|
|
2905
|
+
const phases = envValue.split(",").map((phase) => phase.trim().toLowerCase()).filter(Boolean);
|
|
2906
|
+
return phases.length > 0 ? Object.freeze(phases) : EMPTY_PHASES;
|
|
2907
|
+
}
|
|
2908
|
+
function loadVisiblePhases() {
|
|
2909
|
+
const configured = parsePhaseEnvVar(process.env.CODEX_VISIBLE_PHASES);
|
|
2910
|
+
return configured.length > 0 ? configured : DEFAULT_VISIBLE_PHASES;
|
|
2911
|
+
}
|
|
2912
|
+
var USER_VISIBLE_AGENT_MESSAGE_PHASES = loadVisiblePhases();
|
|
2913
|
+
var USER_HIDDEN_AGENT_MESSAGE_PHASES = parsePhaseEnvVar(process.env.CODEX_HIDDEN_PHASES);
|
|
2914
|
+
|
|
2915
|
+
// src/core/util/host-info.ts
|
|
2916
|
+
import os3 from "node:os";
|
|
2917
|
+
function getMachineName() {
|
|
2918
|
+
return os3.hostname();
|
|
2919
|
+
}
|
|
2920
|
+
|
|
2895
2921
|
// src/openclaw/shared/file-operations/create-folder.ts
|
|
2896
|
-
import * as
|
|
2922
|
+
import * as os4 from "node:os";
|
|
2897
2923
|
import * as path3 from "node:path";
|
|
2898
2924
|
async function handleCreateFolderAction(params, context) {
|
|
2899
2925
|
if (!params.name || typeof params.name !== "string") {
|
|
@@ -2919,7 +2945,7 @@ async function handleCreateFolderAction(params, context) {
|
|
|
2919
2945
|
};
|
|
2920
2946
|
}
|
|
2921
2947
|
const cwd = context.resolveCwd ? await context.resolveCwd(params.session_id) : null;
|
|
2922
|
-
const fallbackDir = context.fallbackDir ??
|
|
2948
|
+
const fallbackDir = context.fallbackDir ?? os4.homedir();
|
|
2923
2949
|
const normalizedParentId = params.parent_id ? normalizePlatformPath(params.parent_id) : null;
|
|
2924
2950
|
const parentDir = normalizedParentId ? path3.resolve(normalizedParentId) : cwd || fallbackDir;
|
|
2925
2951
|
let realParent;
|
|
@@ -3254,7 +3280,7 @@ async function handleFileListLocalAction(payload) {
|
|
|
3254
3280
|
return {
|
|
3255
3281
|
action_id: payload.action_id,
|
|
3256
3282
|
status: result.status,
|
|
3257
|
-
result: result.result,
|
|
3283
|
+
result: result.result ? { ...result.result, machine_name: getMachineName() } : result.result,
|
|
3258
3284
|
error_code: result.error_code,
|
|
3259
3285
|
error_msg: result.error_msg
|
|
3260
3286
|
};
|
|
@@ -3369,7 +3395,7 @@ ${lines.join("\n\n")}`;
|
|
|
3369
3395
|
|
|
3370
3396
|
// src/openclaw/shared/file-serve/tailnet-ip.ts
|
|
3371
3397
|
import { execFile } from "node:child_process";
|
|
3372
|
-
import * as
|
|
3398
|
+
import * as os5 from "node:os";
|
|
3373
3399
|
function isTailnetIPv4(addr) {
|
|
3374
3400
|
const parts = addr.split(".");
|
|
3375
3401
|
if (parts.length !== 4) return false;
|
|
@@ -3391,7 +3417,7 @@ function detectViaCLI() {
|
|
|
3391
3417
|
});
|
|
3392
3418
|
}
|
|
3393
3419
|
function detectViaInterfaces() {
|
|
3394
|
-
const interfaces =
|
|
3420
|
+
const interfaces = os5.networkInterfaces();
|
|
3395
3421
|
for (const list of Object.values(interfaces)) {
|
|
3396
3422
|
if (!list) continue;
|
|
3397
3423
|
for (const info of list) {
|
|
@@ -3443,10 +3469,10 @@ function buildAuthPayload(account, authMetadata = {}, tailnetIP) {
|
|
|
3443
3469
|
capabilities: [...STABLE_AUTH_CAPABILITIES],
|
|
3444
3470
|
local_actions: [...STABLE_LOCAL_ACTION_TYPES],
|
|
3445
3471
|
host_meta: {
|
|
3446
|
-
hostname:
|
|
3447
|
-
platform:
|
|
3448
|
-
arch:
|
|
3449
|
-
os_release:
|
|
3472
|
+
hostname: getMachineName(),
|
|
3473
|
+
platform: os6.platform(),
|
|
3474
|
+
arch: os6.arch(),
|
|
3475
|
+
os_release: os6.release(),
|
|
3450
3476
|
...tailnetIP !== void 0 && { tailnet_ip: tailnetIP }
|
|
3451
3477
|
},
|
|
3452
3478
|
skills: scanOpenClawSkills().map((s) => ({ name: s.name, description: s.description, source: s.source }))
|
|
@@ -8974,7 +9000,7 @@ var TOOLS = [
|
|
|
8974
9000
|
},
|
|
8975
9001
|
{
|
|
8976
9002
|
name: "grix_file_link",
|
|
8977
|
-
description: "Create a direct, tailnet-only download link for a local file on this host. Use this whenever the user asks you to send, share, give, or deliver a file that exists on the machine where you run (a report, log, build artifact, export, or any local path). It returns a ready-to-use Markdown link in the `markdown` field \u2014 include that exact Markdown link in your reply so the user can click and download the file directly over the shared Tailscale network. Each link is one-time and expires, so call this again to produce a fresh link every time you deliver a file. Requires this host to be on a tailnet (Tailscale running).",
|
|
9003
|
+
description: "Create a direct, tailnet-only download link for a local file on this host. Use this whenever the user asks you to send, share, give, or deliver a file that exists on the machine where you run (a report, log, build artifact, export, or any local path). It returns a ready-to-use Markdown link in the `markdown` field \u2014 include that exact Markdown link in your reply so the user can click and download the file directly over the shared Tailscale network. Each link is one-time and expires, so call this again to produce a fresh link every time you deliver a file. The download link is HTTPS, served by a built-in self-signed CA. The result also returns `ca_install_url`: the first time you share a link with a user (or whenever their browser warns the cert is untrusted), also give them this CA install link so they can install and trust it once \u2014 after that all download links work without warnings. Requires this host to be on a tailnet (Tailscale running).",
|
|
8978
9004
|
inputSchema: {
|
|
8979
9005
|
type: "object",
|
|
8980
9006
|
properties: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "grix-connector",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Connect local AI coding agents (Claude, Codex, Gemini, Qwen, DeepSeek, Cursor, OpenCode, Pi, OpenHuman, Reasonix) to the Grix scheduling platform. Also serves as an OpenClaw plugin for Grix channel transport.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -68,6 +68,7 @@
|
|
|
68
68
|
"license": "MIT",
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@types/node": "^25.6.0",
|
|
71
|
+
"@types/node-forge": "^1.3.14",
|
|
71
72
|
"@types/ws": "^8.18.1",
|
|
72
73
|
"esbuild": "^0.27.7",
|
|
73
74
|
"fast-check": "^4.8.0",
|
|
@@ -89,6 +90,7 @@
|
|
|
89
90
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
90
91
|
"@sentry/node": "^10.57.0",
|
|
91
92
|
"extract-zip": "^2.0.1",
|
|
93
|
+
"node-forge": "^1.4.0",
|
|
92
94
|
"socket.io-client": "^4.8.3",
|
|
93
95
|
"ws": "^8.20.0"
|
|
94
96
|
},
|