aws-runtime-bridge 1.9.145 → 1.9.146
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/routes/launch.js +14 -14
- package/dist/services/auto-register.d.ts +1 -0
- package/dist/services/auto-register.js +1 -1
- package/dist/services/launch-manager.d.ts +12 -0
- package/dist/services/launch-manager.js +6 -6
- package/dist/services/update-notifier.js +2 -2
- package/package/acode/dist/background-command-manager.js +2 -2
- package/package/acode/dist/built-in-file-tools.js +2 -2
- package/package/acode/dist/builtins/shellCommandRunner.js +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +1 -1
- package/package.json +1 -1
package/dist/routes/launch.js
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import b from"node:fs/promises";import w from"node:path";import{Router as M}from"express";import{validateToken as
|
|
2
|
-
`,"utf-8"),await b.rename(s,n),
|
|
1
|
+
import b from"node:fs/promises";import w from"node:path";import{Router as M}from"express";import{validateToken as l}from"../middleware/auth.js";import{getLaunchManager as c,LaunchAlreadyRunningError as P}from"../services/launch-manager.js";import{METRICS_HISTORY_CAPACITY as v}from"../services/launch-metrics.js";import{getLaunchStreamHub as j}from"../services/launch-streams.js";import{createLogger as N}from"../utils/logger.js";const d=N("launch"),m=M(),k=3e5,I=20;m.put("/launch-configs/file",l,async(a,t)=>{try{const r=a.body||{},e=typeof r.workspacePath=="string"?r.workspacePath.trim():"";if(!e||!w.isAbsolute(e)){t.status(400).json({error:"workspacePath must be a non-empty absolute path"});return}if(!r.content||typeof r.content!="object"||Array.isArray(r.content)){t.status(400).json({error:"content must be an object"});return}const n=w.join(e,".agentswork","launcher","launcher-config.json");await b.mkdir(w.dirname(n),{recursive:!0});const s=`${n}.${process.pid}.tmp`;await b.writeFile(s,JSON.stringify(r.content,null,2)+`
|
|
2
|
+
`,"utf-8"),await b.rename(s,n),d.info(`[launch/file] \u542F\u52A8\u9879\u5FEB\u7167\u5DF2\u5199\u5165: ${n}`),t.json({ok:!0,path:n})}catch(r){const e=r;d.error("[launch/file] Error:",e),t.status(500).json({error:e.message})}}),m.get("/launch-configs/file",l,async(a,t)=>{try{const r=typeof a.query.workspacePath=="string"?a.query.workspacePath.trim():"";if(!r||!w.isAbsolute(r)){t.status(400).json({error:"workspacePath must be a non-empty absolute path"});return}const e=w.join(r,".agentswork","launcher","launcher-config.json");try{const n=await b.readFile(e,"utf-8");t.json({ok:!0,found:!0,path:e,content:JSON.parse(n)})}catch(n){if(n.code==="ENOENT"){t.json({ok:!0,found:!1,path:e});return}throw n}}catch(r){const e=r;d.error("[launch/file:read] Error:",e),t.status(500).json({error:e.message})}}),m.get("/launch-configs/runs",l,async(a,t)=>{try{const r=await c().listRuns();t.json({ok:!0,runs:r})}catch(r){const e=r;d.error("[launch/runs] Error:",e),t.status(500).json({error:e.message})}}),m.post("/launch-configs/:id/start",l,async(a,t)=>{const r=a.params.id;try{const e=a.body||{},n=Number(e.waitTimeoutMs),s=Number.isFinite(n)&&n>0?Math.min(n,k):0;let o;try{o=await c().start({configId:r,command:e.command,cwd:e.cwd,env:e.env,jdkPath:e.jdkPath,workspacePath:e.workspacePath,readinessPattern:e.readinessPattern,startedBy:e.startedBy})}catch(i){if(i instanceof P){t.json({ok:!0,skipped:!0,message:"\u5F53\u524D\u5DF2\u5904\u4E8E\u542F\u52A8/\u6B63\u5728\u542F\u52A8\u72B6\u6001\uFF0C\u8DF3\u8FC7",run:i.existing});return}throw i}if(s>0){const i=await c().waitStartupResult(r,s);t.json({ok:!0,run:o,wait:i});return}t.json({ok:!0,run:o})}catch(e){const n=e;d.warn(`[launch/start] configId=${r}, error=${n.message}`),t.status(400).json({error:n.message})}}),m.post("/launch-configs/:id/restart",l,async(a,t)=>{const r=a.params.id;try{const e=a.body||{},n=Number(e.waitTimeoutMs),s=Number.isFinite(n)&&n>0?Math.min(n,k):0,o=await c().restart({configId:r,command:e.command,cwd:e.cwd,env:e.env,jdkPath:e.jdkPath,workspacePath:e.workspacePath,readinessPattern:e.readinessPattern,startedBy:e.startedBy});if(s>0){const i=await c().waitStartupResult(r,s);t.json({ok:!0,run:o,wait:i});return}t.json({ok:!0,run:o})}catch(e){const n=e;d.warn(`[launch/restart] configId=${r}, error=${n.message}`),t.status(400).json({error:n.message})}}),m.post("/launch-configs/start-batch",l,async(a,t)=>{try{const r=a.body||{};if(!Array.isArray(r.items)||r.items.length===0){t.status(400).json({error:"items must be a non-empty array"});return}if(r.items.length>I){t.status(400).json({error:`items exceeds limit ${I}`});return}const e=Number(r.waitTimeoutMs),n=Number.isFinite(e)&&e>0?Math.min(e,k):0,s=await c().startBatch(r.items,n);t.json({ok:!0,...s})}catch(r){const e=r;d.warn(`[launch/start-batch] error=${e.message}`),t.status(400).json({error:e.message})}}),m.post("/launch-configs/stop-all",l,async(a,t)=>{try{const r=await c().stopAll();t.json({ok:!0,...r})}catch(r){const e=r;d.warn(`[launch/stop-all] error: ${e.message}`),t.status(500).json({error:e.message})}}),m.post("/launch-configs/:id/stop",l,async(a,t)=>{const r=a.params.id;try{const e=a.body?.actor,n=typeof e=="string"&&e.trim()?e.trim():void 0,s=await c().stop(r,"manual",n);t.json({ok:s.success,...s})}catch(e){const n=e;d.warn(`[launch/stop] configId=${r}, error=${n.message}`),t.status(400).json({error:n.message})}}),m.get("/launch-configs/:id/logs",l,async(a,t)=>{const r=a.params.id,e=Number(a.query.since)||0;try{const n=await c().getLogs(r,e);if(!n){t.status(404).json({error:"launch run not found"});return}t.json({ok:!0,...n})}catch(n){const s=n;d.error(`[launch/logs] configId=${r}, error:`,s),t.status(500).json({error:s.message})}}),m.get("/launch-configs/:id/metrics",l,async(a,t)=>{const r=a.params.id,e=Number(a.query.limit),n=Number.isFinite(e)&&e>0?Math.min(Math.floor(e),v):v;try{const s=c().getRun(r);if(!s){t.status(404).json({error:"launch run not found"});return}const o=c().getMetrics(r,n);t.json({ok:!0,configId:r,state:s.state,metrics:o})}catch(s){const o=s;d.error(`[launch/metrics] configId=${r}, error:`,o),t.status(500).json({error:o.message})}}),m.get("/launch-configs/:id/logs/stream",l,async(a,t)=>{const r=a.params.id;if(!c().getRun(r)){t.status(404).json({error:"launch run not found"});return}const n=Number(a.headers["last-event-id"]),s=Number.isFinite(n)&&n>=0?n:-1;t.on("error",()=>{});let o=null,i=null;try{t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"}),t.write(`: connected
|
|
3
3
|
|
|
4
|
-
`);const g=
|
|
4
|
+
`);const g=f=>{t.destroyed||t.write(f)};let h=-1,y=!1;if(o=j().subscribe(r,"logs",f=>{if(t.destroyed)return;g(f),f.startsWith("event: run_state")&&(y=!0);const p=/^id: (\d+)\n/.exec(f);p&&(h=Math.max(h,Number(p[1])))}),a.on("close",()=>{o?.(),i&&clearInterval(i);try{t.end()}catch{}}),s>=-1){const f=await c().getLogs(r,Math.max(s,h));if(f)for(const p of f.entries)p.index<=h||g(`id: ${p.index}
|
|
5
5
|
data: ${JSON.stringify(p.data)}
|
|
6
6
|
|
|
7
|
-
`)}const
|
|
8
|
-
data: ${JSON.stringify(
|
|
7
|
+
`)}const u=c().getRun(r);if(!y&&u&&u.state!=="running"){const f={configId:r,state:u.state};u.state==="exited"&&(f.exitCode=u.exitCode??null),g(`event: run_state
|
|
8
|
+
data: ${JSON.stringify(f)}
|
|
9
9
|
|
|
10
|
-
`)}
|
|
10
|
+
`)}i=setInterval(()=>{g(`: heartbeat
|
|
11
11
|
|
|
12
|
-
`)},15e3)}catch(g){const
|
|
12
|
+
`)},15e3)}catch(g){const h=g;if(d.error(`[launch/logs/stream] configId=${r}, error:`,h),o?.(),i&&clearInterval(i),t.headersSent){t.end();return}t.status(500).json({error:h.message})}}),m.get("/launch-configs/:id/metrics/stream",l,(a,t)=>{const r=a.params.id;if(!c().getRun(r)){t.status(404).json({error:"launch run not found"});return}const n=Number(a.headers["last-event-id"]),s=Number.isFinite(n)&&n>=0?n:-1;t.on("error",()=>{}),t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"}),t.write(`: connected
|
|
13
13
|
|
|
14
|
-
`);const o=
|
|
15
|
-
data: ${JSON.stringify(
|
|
14
|
+
`);const o=u=>{t.destroyed||t.write(u)};if(s>=0)for(const u of c().getMetricsSince(r,s))o(`id: ${u.index}
|
|
15
|
+
data: ${JSON.stringify(u.sample)}
|
|
16
16
|
|
|
17
|
-
`);let
|
|
18
|
-
data: ${JSON.stringify(
|
|
17
|
+
`);let i=!1,g=null,h=null;g=j().subscribe(r,"metrics",u=>{t.destroyed||(o(u),u.startsWith("event: run_state")&&(i=!0))}),a.on("close",()=>{g?.(),h&&clearInterval(h);try{t.end()}catch{}});const y=c().getRun(r);if(!i&&y&&y.state!=="running"){const u={configId:r,state:y.state};y.state==="exited"&&(u.exitCode=y.exitCode??null),o(`event: run_state
|
|
18
|
+
data: ${JSON.stringify(u)}
|
|
19
19
|
|
|
20
|
-
`)}
|
|
20
|
+
`)}h=setInterval(()=>{o(`: heartbeat
|
|
21
21
|
|
|
22
|
-
`)},15e3)}),
|
|
22
|
+
`)},15e3)}),m.get("/launch-configs/status/stream",l,async(a,t)=>{t.on("error",()=>{});let r=null,e=null;try{t.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"}),t.write(`: connected
|
|
23
23
|
|
|
24
24
|
`);const n=o=>{t.destroyed||t.write(o)};r=j().subscribeStatus(o=>{t.destroyed||n(o)}),a.on("close",()=>{r?.(),e&&clearInterval(e);try{t.end()}catch{}});const s=await c().listRuns();t.destroyed||n(`event: snapshot
|
|
25
25
|
data: ${JSON.stringify({runs:s})}
|
|
26
26
|
|
|
27
27
|
`),e=setInterval(()=>{n(`: heartbeat
|
|
28
28
|
|
|
29
|
-
`)},15e3)}catch(n){const s=n;if(
|
|
29
|
+
`)},15e3)}catch(n){const s=n;if(d.error("[launch/status/stream] error:",s),r?.(),e&&clearInterval(e),t.headersSent){t.end();return}t.status(500).json({error:s.message})}});export{I as MAX_BATCH_START_ITEMS,k as MAX_START_WAIT_MS,m as launchRouter};
|
|
30
30
|
|
|
@@ -46,6 +46,7 @@ export { getAutoRegisterConfigFilePath };
|
|
|
46
46
|
export declare function loadConfig(): AutoRegisterConfig;
|
|
47
47
|
export declare function loadConfigs(): AutoRegisterConfig[];
|
|
48
48
|
export declare function isTunnelConfig(config?: AutoRegisterConfig): boolean;
|
|
49
|
+
export declare function resolveRuntimeBridgeBaseUrl(config: AutoRegisterConfig): string;
|
|
49
50
|
export declare function loadPrimaryLifecycleConfig(): AutoRegisterConfig;
|
|
50
51
|
|
|
51
52
|
export declare function resolveSchedulerBaseUrlFromToken(token: unknown): string | undefined;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import g from"node:fs";import A from"node:os";import I from"axios";import{v4 as G}from"uuid";import{getActiveBridgeHttpPort as M,getAutoRegisterConfigFilePath as m,schedulerBaseUrl as d}from"../config.js";import{runExclusiveConfigWrite as z}from"../utils/config-write-queue.js";import{logger as i}from"../utils/logger.js";import{clearRuntimeBinding as J,clearScopedRuntimeAccessToken as Y,getRuntimeAccessToken as E,getRuntimeBindingPublicState as w,getScopedRuntimeAccessToken as q,loadRuntimeBinding as h,normalizeSchedulerBaseUrl as p,saveRuntimeBinding as K,saveScopedRuntimeAccessToken as C}from"./runtime-binding.js";const P={enabled:!1,serverUrl:d,preferSameLanIp:!0,maxRetries:3,retryInterval:2e3},u={registered:!1,registrations:{}};let b=[];function Ae(){return[...b]}const H=3e4;function W(){const e=Number(process.env.AWS_REGISTER_BACKGROUND_RETRY_INTERVAL);return Number.isFinite(e)&&e>0?e:H}const R=new Map;function L(e){const r=e.serverUrl||d,t=p(r)||r;if(R.has(t))return;const n=setTimeout(()=>{R.delete(t),V(e,t)},W());n.unref?.(),R.set(t,n)}async function V(e,r){try{const t=S().find(n=>(p(n.serverUrl||d)||n.serverUrl||d)===r)||e;await $(t,{backgroundRetry:!0})}catch(t){i.warn(`[AutoRegister] \u540E\u53F0\u91CD\u8BD5\u6CE8\u518C\u5F02\u5E38: ${t.message}`),L(e)}}function Ie(){for(const e of R.values())clearTimeout(e);R.clear()}function f(e){return e==null?void 0:String(e).trim()||void 0}function O(e){return p(e)}function v(e){if(typeof e=="boolean")return e;if(typeof e=="string"){const r=e.trim().toLowerCase();if(["true","1","yes","y"].includes(r))return!0;if(["false","0","no","n"].includes(r))return!1}}function x(e){if(e==null||e==="")return;const r=Number(e);return Number.isFinite(r)?r:void 0}function k(e){const r=f(e.serverUrl)||f(e.schedulerBaseUrl),t=f(e.connectionKey)||f(e.password);return{enabled:v(e.enabled),serverUrl:r,tenantId:f(e.tenantId),userKey:f(e.userKey),connectionKey:t,instanceName:f(e.instanceName),instanceId:f(e.instanceId),projectId:f(e.projectId),roleName:f(e.roleName),workspacePath:f(e.workspacePath),registerAddr:f(e.registerAddr),registerIp:f(e.registerIp),virtualIp:f(e.virtualIp),tunnel:v(e.tunnel),preferSameLanIp:v(e.preferSameLanIp),maxRetries:x(e.maxRetries),retryInterval:x(e.retryInterval)}}function j(){const e=m();try{if(!g.existsSync(e))return i.debug(`[AutoRegister] \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728: ${e}`),null;const r=g.readFileSync(e,"utf-8"),t=JSON.parse(r);return i.info(`[AutoRegister] \u4ECE\u914D\u7F6E\u6587\u4EF6\u52A0\u8F7D\u914D\u7F6E: ${e}`),k(t)}catch(r){const t=r;return i.warn(`[AutoRegister] \u8BFB\u53D6\u914D\u7F6E\u6587\u4EF6\u5931\u8D25: ${e}, error: ${t.message}`),null}}function X(){const e=m();try{if(!g.existsSync(e))return[];const r=g.readFileSync(e,"utf-8"),t=JSON.parse(r),n=k(t),o=Array.isArray(t.autoRegisterTargets)?t.autoRegisterTargets:[];return o.length===0?n.userKey?[n]:[]:o.filter(s=>!!(s&&typeof s=="object"&&!Array.isArray(s))).map(s=>{const a=k(s);return{...n,...a,connectionKey:a.connectionKey||n.connectionKey}})}catch(r){const t=r;return i.warn(`[AutoRegister] \u8BFB\u53D6\u81EA\u52A8\u6CE8\u518C\u76EE\u6807\u5931\u8D25: ${e}, error: ${t.message}`),[]}}function F(){const e={};return process.env.AWS_AUTO_REGISTER==="true"&&(e.enabled=!0),process.env.AWS_RUNTIME_SCHEDULER_BASE_URL&&(e.serverUrl=process.env.AWS_RUNTIME_SCHEDULER_BASE_URL),process.env.AWS_TENANT_ID&&(e.tenantId=process.env.AWS_TENANT_ID),process.env.AWS_USER_KEY&&(e.userKey=process.env.AWS_USER_KEY),process.env.AWS_BRIDGE_CONNECTION_KEY&&(e.connectionKey=process.env.AWS_BRIDGE_CONNECTION_KEY),process.env.AWS_INSTANCE_NAME&&(e.instanceName=process.env.AWS_INSTANCE_NAME),process.env.AWS_PROJECT_NAME&&(e.projectId=process.env.AWS_PROJECT_NAME),process.env.AWS_ROLE_NAME&&(e.roleName=process.env.AWS_ROLE_NAME),process.env.AWS_WORKSPACE_PATH&&(e.workspacePath=process.env.AWS_WORKSPACE_PATH),process.env.AWS_REGISTER_ADDR&&(e.registerAddr=process.env.AWS_REGISTER_ADDR),process.env.AWS_REGISTER_IP&&(e.registerIp=process.env.AWS_REGISTER_IP),process.env.AWS_VIRTUAL_IP&&(e.virtualIp=process.env.AWS_VIRTUAL_IP),process.env.AWS_PREFER_SAME_LAN_IP&&(e.preferSameLanIp=v(process.env.AWS_PREFER_SAME_LAN_IP)??!0),process.env.AWS_REGISTER_MAX_RETRIES&&(e.maxRetries=parseInt(process.env.AWS_REGISTER_MAX_RETRIES,10)),process.env.AWS_REGISTER_RETRY_INTERVAL&&(e.retryInterval=parseInt(process.env.AWS_REGISTER_RETRY_INTERVAL,10)),e}function T(){const e=j(),r=F(),t={...P,...e||{},...r},n=t.instanceName||A.hostname();let o=!1;return process.env.AWS_AUTO_REGISTER!==void 0?o=process.env.AWS_AUTO_REGISTER==="true":e&&(o=!0),{enabled:o,serverUrl:t.serverUrl||d,tenantId:t.tenantId||"",userKey:t.userKey||"",connectionKey:t.connectionKey,instanceName:n,instanceId:t.instanceId,projectId:t.projectId,roleName:t.roleName,workspacePath:t.workspacePath,registerAddr:t.registerAddr,registerIp:t.registerIp,virtualIp:t.virtualIp,tunnel:typeof t.tunnel=="boolean"?t.tunnel:void 0,preferSameLanIp:t.preferSameLanIp!==!1,maxRetries:t.maxRetries,retryInterval:t.retryInterval}}function S(){const e=X(),r=F(),n=(e.length>0?e:[j()||{}]).map(o=>{const s={...P,...o,...r};let a=!1;return process.env.AWS_AUTO_REGISTER!==void 0?a=process.env.AWS_AUTO_REGISTER==="true":a=e.length>0||!!s.userKey,{enabled:a,serverUrl:s.serverUrl||d,tenantId:s.tenantId||"",userKey:s.userKey||"",connectionKey:s.connectionKey,instanceName:s.instanceName||A.hostname(),instanceId:s.instanceId,projectId:s.projectId,roleName:s.roleName,workspacePath:s.workspacePath,registerAddr:s.registerAddr,registerIp:s.registerIp,virtualIp:s.virtualIp,tunnel:typeof s.tunnel=="boolean"?s.tunnel:void 0,preferSameLanIp:s.preferSameLanIp!==!1,maxRetries:s.maxRetries,retryInterval:s.retryInterval}});return b=n.map(o=>o.connectionKey).filter(o=>!!(o&&o.trim())),n}function Q(){const e=A.networkInterfaces(),r=[];for(const t of Object.keys(e)){const n=e[t];if(n)for(const o of n)o.family==="IPv4"&&!o.internal&&r.push({address:o.address,netmask:o.netmask,name:t})}return r}function N(e){const r=e.split(".").map(Number);return(r[0]<<24)+(r[1]<<16)+(r[2]<<8)+r[3]}function Z(e,r,t){const n=N(e),o=N(r),s=N(t);return(n&s)===(o&s)}function ee(e){try{const r=new URL(e);return r.hostname==="localhost"||r.hostname==="127.0.0.1"?"127.0.0.1":/^(\d{1,3}\.){3}\d{1,3}$/.test(r.hostname)?r.hostname:null}catch{return null}}function re(e){return e==="127.0.0.1"}function te(e){const r=Q();if(r.length===0)return i.warn("[AutoRegister] \u672A\u627E\u5230\u4EFB\u4F55\u975E\u5185\u90E8 IP \u5730\u5740\uFF0C\u4F7F\u7528 127.0.0.1"),"127.0.0.1";const t=ee(e);if(t){if(re(t))return"127.0.0.1";for(const n of r)if(Z(n.address,t,n.netmask))return i.info(`[AutoRegister] \u627E\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u540C\u5B50\u7F51\u7684 IP: ${n.address} (\u7F51\u5361: ${n.name}, \u5B50\u7F51\u63A9\u7801: ${n.netmask})`),n.address;i.warn(`[AutoRegister] \u672A\u627E\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3 (${t}) \u540C\u5B50\u7F51\u7684\u672C\u673A IP\uFF0C\u4F7F\u7528 127.0.0.1`)}else i.warn("[AutoRegister] \u65E0\u6CD5\u89E3\u6790\u8C03\u5EA6\u4E2D\u5FC3 IP\uFF0C\u4F7F\u7528 127.0.0.1");return"127.0.0.1"}function ne(e=d){return te(e)}function D(e){const r=e||T();return!r.enabled||!r.userKey?!1:r.tunnel===!0?!0:r.tunnel===!1?!1:!r.registerAddr&&!r.registerIp&&!r.virtualIp}function U(e){const r=M();if(D(e)){const s=e.serverUrl||d;try{const a=new URL(s);if(!e.instanceId)i.warn("[AutoRegister] \u96A7\u9053\u6A21\u5F0F\u4F46\u7F3A\u5C11 instanceId\uFF0C\u964D\u7EA7\u4E3A\u76F4\u8FDE\u6A21\u5F0F");else return`${a.protocol}//${a.host}/tunnel/${e.instanceId}`}catch{i.warn("[AutoRegister] serverUrl \u89E3\u6790\u5931\u8D25\uFF0C\u964D\u7EA7\u4E3A\u76F4\u8FDE\u6A21\u5F0F")}}const t=e.preferSameLanIp===!1?"127.0.0.1":ne(e.serverUrl||d),n=e.registerAddr||e.registerIp||e.virtualIp||t;return n?/^https?:\/\//i.test(n)?n:/:[0-9]+$/.test(n)?`http://${n}`:`http://${n}:${r}`:`http://127.0.0.1:${r}`}function y(){return S()[0]||T()}function Re(e){const r=String(e||"").trim();if(!r)return;const t=[];for(const o of S())o?.serverUrl&&t.push(o.serverUrl);const n=h();n.schedulerBaseUrl&&t.push(n.schedulerBaseUrl);for(const o of t){const s=q(o);if(s&&s===r)return p(o)}}function se(e){return e?Object.entries(u.registrations).find(([,t])=>t===e)?.[0]:void 0}function _(e,r){const t=se(r);if(t)return t;const n=f(e.serverUrl);if(n&&(n!==d||process.env.AWS_RUNTIME_SCHEDULER_BASE_URL))return n;const o=h(),s=f(o.schedulerBaseUrl);return o.status==="paired"&&s?s:n||d}async function oe(e){const r=e.instanceName||A.hostname(),t=e.serverUrl||d,n={tenantId:e.tenantId,userKey:e.userKey,instanceId:e.instanceId,instanceName:r,hostname:A.hostname(),virtualIp:e.registerAddr||e.registerIp||e.virtualIp,runtimeBridgeBaseUrl:U(e),connectionKey:e.connectionKey,workspacePath:e.workspacePath,projectId:e.projectId,roleName:e.roleName};return i.info(`[AutoRegister] \u6B63\u5728\u6CE8\u518C\u5B9E\u4F8B: ${r}`),i.info(`[AutoRegister] \u8C03\u5EA6\u4E2D\u5FC3: ${t}`),i.info(`[AutoRegister] \u7528\u6237 Key: ${e.userKey?"****"+e.userKey.slice(-4):"(\u672A\u8BBE\u7F6E)"}`),i.info(`[AutoRegister] \u79DF\u6237 ID: ${e.tenantId||"(\u81EA\u52A8\u63A8\u5BFC)"}`),(await I.post(`${t}/api/instances/register`,n,{headers:{"Content-Type":"application/json"},timeout:1e4})).data}function ie(e,r){const t=m();return z(t,()=>{if(!g.existsSync(t))return;const n=g.readFileSync(t,"utf-8"),o=JSON.parse(n),s=p(e);if(!s)return;let a=!1;const l=c=>{p(String(c.serverUrl||c.schedulerBaseUrl||""))===s&&r&&c.instanceId!==r&&(c.instanceId=r,a=!0)};if(Array.isArray(o.autoRegisterTargets))for(const c of o.autoRegisterTargets)c&&typeof c=="object"&&!Array.isArray(c)&&l(c);else l(o);a&&(g.writeFileSync(t,JSON.stringify(o,null,2),"utf-8"),i.info(`[AutoRegister] \u5DF2\u56DE\u5199 instanceId \u5230 config.json (serverUrl=${e})`))})}async function ae(e){const r=_(y(),e),t=E(r);if(!t)throw new Error("runtimeAccessToken is required to unregister bridge instance");return(await I.post(`${r}/api/instances/unregister`,{instanceId:e},{headers:{"Content-Type":"application/json","X-Runtime-Token":t},timeout:1e4})).data}async function Se(e){const r=e?[{...T(),...e}]:S(),n=(r.length>1?await Promise.all(r.map(s=>$(s))):[await $(r[0]||T())]).every(Boolean),o=r.every(s=>!s.enabled||!s.userKey);if(!e&&(n||o)){const{stopTunnelClientsExcept:s}=await import("./tunnel-client.js");s(r.map(a=>a.serverUrl).filter(a=>!!a))}return n}async function $(e,r){if(!e.enabled)return i.info("[AutoRegister] \u81EA\u52A8\u6CE8\u518C\u672A\u542F\u7528"),i.info(`[AutoRegister] \u8981\u542F\u7528\u81EA\u52A8\u6CE8\u518C\uFF0C\u8BF7\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6 ${m()} \u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF AWS_AUTO_REGISTER=true`),!1;if(!e.userKey)return i.error("[AutoRegister] \u7F3A\u5C11\u7528\u6237 Key\uFF08\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u8BBE\u7F6E userKey \u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF AWS_USER_KEY\uFF09"),!1;const t=D(e);t&&!e.instanceId&&(e={...e,instanceId:`bridge-${G().replace(/-/g,"").slice(0,12)}`},i.info(`[AutoRegister] \u96A7\u9053\u6A21\u5F0F\uFF1A\u5DF2\u9884\u58F0\u660E instanceId=${e.instanceId}`));const n=r?.backgroundRetry?1:e.maxRetries??3,o=e.retryInterval??2e3;for(let s=1;s<=n;s++){try{u.lastAttempt=new Date;const a=await oe(e);if(a.success){if(u.registered=!0,u.instanceId=a.instanceId,a.instanceId&&(u.registrations[e.serverUrl||d]=a.instanceId),u.error=void 0,i.info("[AutoRegister] \u2713 \u6CE8\u518C\u6210\u529F\uFF01"),i.info(`[AutoRegister] \u5B9E\u4F8B ID: ${a.instanceId}`),i.info(`[AutoRegister] \u6D88\u606F: ${a.message}`),i.info(`[AutoRegister] \u66F4\u65B0: ${a.isUpdate?"\u662F":"\u5426"}`),a.runtimeAccessToken)try{const l=e.serverUrl||d;K({accessToken:a.runtimeAccessToken,instanceId:a.instanceId,userId:a.userId,schedulerBaseUrl:l});const c=p(a.serverUrl);c&&c!==p(l)&&(C({serverBaseUrl:c,accessToken:a.runtimeAccessToken}),i.info(`[AutoRegister] \u68C0\u6D4B\u5230 server \u4E0B\u53D1\u5730\u5740(${c})\u4E0E\u8FDE\u63A5\u5730\u5740(${l})\u4E0D\u540C\uFF0C\u5DF2\u6309\u4E24\u4E2A\u5730\u5740\u5206\u522B\u4FDD\u5B58 scoped token`)),i.info("[AutoRegister] \u5DF2\u4FDD\u5B58\u8C03\u5EA6\u4E2D\u5FC3\u4E0B\u53D1\u7684 runtime access token"),a.instanceId&&ie(e.serverUrl||d,a.instanceId).catch(B=>{i.warn(`[AutoRegister] \u56DE\u5199 instanceId \u5230 config.json \u5931\u8D25: ${B.message}`)})}catch(l){const c=l;return i.error(`[AutoRegister] \u4FDD\u5B58 runtime access token \u5931\u8D25: ${c.message}`),u.error=c.message,!1}else i.warn("[AutoRegister] \u6CE8\u518C\u54CD\u5E94\u672A\u5305\u542B runtime access token\uFF0CMCP \u5C06\u65E0\u6CD5\u8BBF\u95EE\u8C03\u5EA6\u4E2D\u5FC3\uFF0C\u8BF7\u68C0\u67E5 server \u7684 bridge \u5B9E\u4F8B token \u9881\u53D1\u903B\u8F91");if(t&&a.instanceId&&a.runtimeAccessToken){const{startTunnelClient:l}=await import("./tunnel-client.js"),c=e.serverUrl||d;l(c,a.instanceId),i.info(`[AutoRegister] \u96A7\u9053\u5BA2\u6237\u7AEF\u5DF2\u542F\u52A8: server=${c}, instanceId=${a.instanceId}`)}return!0}else i.warn(`[AutoRegister] \u6CE8\u518C\u5931\u8D25: ${a.message}`),u.error=a.message}catch(a){const l=a,c=l.response?.data?JSON.stringify(l.response.data):l.message;i.error(`[AutoRegister] \u6CE8\u518C\u8BF7\u6C42\u5931\u8D25 (\u5C1D\u8BD5 ${s}/${n}): ${c}`),u.error=c}s<n&&(i.info(`[AutoRegister] ${o/1e3} \u79D2\u540E\u91CD\u8BD5...`),await new Promise(a=>setTimeout(a,o)))}return r?.backgroundRetry?i.warn(`[AutoRegister] \u540E\u53F0\u91CD\u8BD5\u6CE8\u518C\u4ECD\u672A\u6210\u529F (server=${e.serverUrl||d}): ${u.error||"\u672A\u77E5"}`):(i.error("[AutoRegister] \u2717 \u6CE8\u518C\u5931\u8D25\uFF0C\u5DF2\u8FBE\u6700\u5927\u91CD\u8BD5\u6B21\u6570"),i.error("[AutoRegister] ========================================"),i.error("[AutoRegister] \u81EA\u52A8\u6CE8\u518C\u5DF2\u542F\u7528\u4F46\u6CE8\u518C\u5931\u8D25\uFF0C\u5B9E\u4F8B\u6682\u65F6\u65E0\u6CD5\u6B63\u5E38\u5DE5\u4F5C"),i.error("[AutoRegister] \u8BF7\u68C0\u67E5\u4EE5\u4E0B\u914D\u7F6E\uFF1A"),i.error(`[AutoRegister] - \u7528\u6237 Key (userKey): ${e.userKey?"****"+e.userKey.slice(-4):"(\u672A\u8BBE\u7F6E)"}`),i.error(`[AutoRegister] - \u79DF\u6237 ID (tenantId): ${e.tenantId||"(\u53EF\u9009\uFF0C\u5C06\u81EA\u52A8\u63A8\u5BFC)"}`),i.error(`[AutoRegister] - \u5B9E\u4F8B\u540D (instanceName): ${e.instanceName||"(\u4F7F\u7528\u4E3B\u673A\u540D)"}`),i.error(`[AutoRegister] - \u8C03\u5EA6\u4E2D\u5FC3\u5730\u5740: ${e.serverUrl||d}`),i.error(`[AutoRegister] - \u6700\u540E\u9519\u8BEF: ${u.error||"\u672A\u77E5"}`),i.error("[AutoRegister] ========================================"),i.error(`[AutoRegister] \u914D\u7F6E\u6765\u6E90\uFF1A${m()} \u6216\u73AF\u5883\u53D8\u91CF`),i.warn(`[AutoRegister] \u5C06\u5728\u540E\u53F0\u6301\u7EED\u91CD\u8BD5\u6CE8\u518C\uFF08\u6BCF ${Math.round(W()/1e3)} \u79D2\uFF09\uFF0C\u76F4\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u5EFA\u7ACB\u8FDE\u63A5`)),L(e),!1}async function ye(){const e=y();if(!e.userKey)return{success:!1,error:"userKey is required for runtime token refresh"};const r=w(),t=_(e),n=U(e);try{const o=await I.post(`${t}/api/instances/runtime-tokens/refresh`,{tenantId:e.tenantId,userKey:e.userKey,instanceId:r.instanceId,instanceName:e.instanceName,runtimeBridgeBaseUrl:n},{headers:{"Content-Type":"application/json"},timeout:1e4});if(!o.data.success||!o.data.runtimeAccessToken)return{success:!1,error:o.data.message||"scheduler did not return runtimeAccessToken"};const a=E()!==o.data.runtimeAccessToken;return K({accessToken:o.data.runtimeAccessToken,instanceId:r.instanceId,userId:o.data.userId||e.userKey,schedulerBaseUrl:t}),{success:!0,runtimeAccessToken:o.data.runtimeAccessToken,updated:a}}catch(o){const s=o;return{success:!1,error:s.response?.data?JSON.stringify(s.response.data):s.message}}}async function ve(e){const r=O(e);if(!r)return{success:!1,error:"serverUrl is required for runtime token refresh"};const t=S().find(s=>O(s.serverUrl)===r)||y();if(!t.userKey)return{success:!1,error:"userKey is required for runtime token refresh"};const n=w(),o=U(t);try{const s=await I.post(`${r}/api/instances/runtime-tokens/refresh`,{tenantId:t.tenantId,userKey:t.userKey,instanceId:n.instanceId,instanceName:t.instanceName,runtimeBridgeBaseUrl:o},{headers:{"Content-Type":"application/json"},timeout:1e4});if(!s.data.success||!s.data.runtimeAccessToken)return{success:!1,error:s.data.message||"scheduler did not return runtimeAccessToken"};const l=E(r)!==s.data.runtimeAccessToken;return C({serverBaseUrl:r,accessToken:s.data.runtimeAccessToken}),{success:!0,runtimeAccessToken:s.data.runtimeAccessToken,updated:l}}catch(s){const a=s;return{success:!1,error:a.response?.data?JSON.stringify(a.response.data):a.message}}}async function Te(){if(!u.registered||!u.instanceId)return i.info("[AutoRegister] \u5B9E\u4F8B\u672A\u6CE8\u518C\uFF0C\u65E0\u9700\u6CE8\u9500"),!0;try{const e=await ae(u.instanceId);if(e.success){i.info(`[AutoRegister] \u2713 \u6CE8\u9500\u6210\u529F: ${u.instanceId}`);const r=_(y(),u.instanceId);h().schedulerBaseUrl&&Y(r),J();try{const{stopTunnelClientForServer:n}=await import("./tunnel-client.js");n(r)}catch(n){i.warn(`[AutoRegister] \u6CE8\u9500\u540E\u505C\u6B62\u96A7\u9053\u5931\u8D25: ${n.message}`)}return u.registered=!1,u.instanceId=void 0,!0}else return i.warn(`[AutoRegister] \u6CE8\u9500\u5931\u8D25: ${e.message}`),!1}catch(e){const r=e;return i.error(`[AutoRegister] \u6CE8\u9500\u8BF7\u6C42\u5931\u8D25: ${r.message}`),!1}}function Ue(){return{...u}}function _e(){return u.registered}function Ee(){return u.instanceId}async function he(){const e=y(),r=u.instanceId,t=_(e,r),n={};if(r&&(n.instanceId=r),e.enabled&&(n.runtimeBridgeBaseUrl=U(e)),!n.instanceId&&!n.runtimeBridgeBaseUrl)return i.info("[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\uFF1A\u6CA1\u6709 instanceId \u6216 runtimeBridgeBaseUrl\uFF0C\u8DF3\u8FC7\u6E05\u7406"),{success:!0,agentCount:0};try{i.info("[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\uFF1A\u6B63\u5728\u901A\u77E5\u8C03\u5EA6\u4E2D\u5FC3..."),i.info(`[AutoRegister] instanceId: ${n.instanceId||"(\u65E0)"}`),i.info(`[AutoRegister] runtimeBridgeBaseUrl: ${n.runtimeBridgeBaseUrl||"(\u65E0)"}`);const o=await I.post(`${t}/api/instances/bridge-restart-cleanup`,n,{headers:{"Content-Type":"application/json"},timeout:1e4});return o.data.success?(i.info(`[AutoRegister] \u2713 Bridge \u91CD\u542F\u6E05\u7406\u6210\u529F\uFF1A${o.data.message}`),i.info(`[AutoRegister] \u6E05\u7406\u4E86 ${o.data.agentCount||0} \u4E2A Agent`),{success:!0,agentCount:o.data.agentCount||0}):(i.warn(`[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\u5931\u8D25\uFF1A${o.data.message}`),{success:!1,error:o.data.message})}catch(o){const s=o,a=s.response?.data?JSON.stringify(s.response.data):s.message;return i.warn(`[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\u8BF7\u6C42\u5931\u8D25\uFF1A${a}`),{success:!1,error:a}}}export{Se as autoRegister,he as bridgeRestartCleanup,Ie as cancelBackgroundRegisterRetries,m as getAutoRegisterConfigFilePath,Ae as getConfiguredConnectionKeys,Ee as getInstanceId,Ue as getRegistrationState,_e as isRegistered,D as isTunnelConfig,T as loadConfig,S as loadConfigs,y as loadPrimaryLifecycleConfig,ye as requestRuntimeAccessTokenRefresh,ve as requestRuntimeAccessTokenRefreshForServer,Re as resolveSchedulerBaseUrlFromToken,Te as unregister};
|
|
1
|
+
import g from"node:fs";import A from"node:os";import I from"axios";import{v4 as G}from"uuid";import{getActiveBridgeHttpPort as M,getAutoRegisterConfigFilePath as m,schedulerBaseUrl as d}from"../config.js";import{runExclusiveConfigWrite as z}from"../utils/config-write-queue.js";import{logger as i}from"../utils/logger.js";import{clearRuntimeBinding as J,clearScopedRuntimeAccessToken as Y,getRuntimeAccessToken as E,getRuntimeBindingPublicState as w,getScopedRuntimeAccessToken as q,loadRuntimeBinding as h,normalizeSchedulerBaseUrl as p,saveRuntimeBinding as K,saveScopedRuntimeAccessToken as C}from"./runtime-binding.js";const P={enabled:!1,serverUrl:d,preferSameLanIp:!0,maxRetries:3,retryInterval:2e3},u={registered:!1,registrations:{}};let b=[];function Ae(){return[...b]}const H=3e4;function W(){const e=Number(process.env.AWS_REGISTER_BACKGROUND_RETRY_INTERVAL);return Number.isFinite(e)&&e>0?e:H}const R=new Map;function L(e){const r=e.serverUrl||d,t=p(r)||r;if(R.has(t))return;const n=setTimeout(()=>{R.delete(t),V(e,t)},W());n.unref?.(),R.set(t,n)}async function V(e,r){try{const t=S().find(n=>(p(n.serverUrl||d)||n.serverUrl||d)===r)||e;await $(t,{backgroundRetry:!0})}catch(t){i.warn(`[AutoRegister] \u540E\u53F0\u91CD\u8BD5\u6CE8\u518C\u5F02\u5E38: ${t.message}`),L(e)}}function Ie(){for(const e of R.values())clearTimeout(e);R.clear()}function f(e){return e==null?void 0:String(e).trim()||void 0}function x(e){return p(e)}function v(e){if(typeof e=="boolean")return e;if(typeof e=="string"){const r=e.trim().toLowerCase();if(["true","1","yes","y"].includes(r))return!0;if(["false","0","no","n"].includes(r))return!1}}function O(e){if(e==null||e==="")return;const r=Number(e);return Number.isFinite(r)?r:void 0}function k(e){const r=f(e.serverUrl)||f(e.schedulerBaseUrl),t=f(e.connectionKey)||f(e.password);return{enabled:v(e.enabled),serverUrl:r,tenantId:f(e.tenantId),userKey:f(e.userKey),connectionKey:t,instanceName:f(e.instanceName),instanceId:f(e.instanceId),projectId:f(e.projectId),roleName:f(e.roleName),workspacePath:f(e.workspacePath),registerAddr:f(e.registerAddr),registerIp:f(e.registerIp),virtualIp:f(e.virtualIp),tunnel:v(e.tunnel),preferSameLanIp:v(e.preferSameLanIp),maxRetries:O(e.maxRetries),retryInterval:O(e.retryInterval)}}function j(){const e=m();try{if(!g.existsSync(e))return i.debug(`[AutoRegister] \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728: ${e}`),null;const r=g.readFileSync(e,"utf-8"),t=JSON.parse(r);return i.info(`[AutoRegister] \u4ECE\u914D\u7F6E\u6587\u4EF6\u52A0\u8F7D\u914D\u7F6E: ${e}`),k(t)}catch(r){const t=r;return i.warn(`[AutoRegister] \u8BFB\u53D6\u914D\u7F6E\u6587\u4EF6\u5931\u8D25: ${e}, error: ${t.message}`),null}}function X(){const e=m();try{if(!g.existsSync(e))return[];const r=g.readFileSync(e,"utf-8"),t=JSON.parse(r),n=k(t),o=Array.isArray(t.autoRegisterTargets)?t.autoRegisterTargets:[];return o.length===0?n.userKey?[n]:[]:o.filter(s=>!!(s&&typeof s=="object"&&!Array.isArray(s))).map(s=>{const a=k(s);return{...n,...a,connectionKey:a.connectionKey||n.connectionKey}})}catch(r){const t=r;return i.warn(`[AutoRegister] \u8BFB\u53D6\u81EA\u52A8\u6CE8\u518C\u76EE\u6807\u5931\u8D25: ${e}, error: ${t.message}`),[]}}function F(){const e={};return process.env.AWS_AUTO_REGISTER==="true"&&(e.enabled=!0),process.env.AWS_RUNTIME_SCHEDULER_BASE_URL&&(e.serverUrl=process.env.AWS_RUNTIME_SCHEDULER_BASE_URL),process.env.AWS_TENANT_ID&&(e.tenantId=process.env.AWS_TENANT_ID),process.env.AWS_USER_KEY&&(e.userKey=process.env.AWS_USER_KEY),process.env.AWS_BRIDGE_CONNECTION_KEY&&(e.connectionKey=process.env.AWS_BRIDGE_CONNECTION_KEY),process.env.AWS_INSTANCE_NAME&&(e.instanceName=process.env.AWS_INSTANCE_NAME),process.env.AWS_PROJECT_NAME&&(e.projectId=process.env.AWS_PROJECT_NAME),process.env.AWS_ROLE_NAME&&(e.roleName=process.env.AWS_ROLE_NAME),process.env.AWS_WORKSPACE_PATH&&(e.workspacePath=process.env.AWS_WORKSPACE_PATH),process.env.AWS_REGISTER_ADDR&&(e.registerAddr=process.env.AWS_REGISTER_ADDR),process.env.AWS_REGISTER_IP&&(e.registerIp=process.env.AWS_REGISTER_IP),process.env.AWS_VIRTUAL_IP&&(e.virtualIp=process.env.AWS_VIRTUAL_IP),process.env.AWS_PREFER_SAME_LAN_IP&&(e.preferSameLanIp=v(process.env.AWS_PREFER_SAME_LAN_IP)??!0),process.env.AWS_REGISTER_MAX_RETRIES&&(e.maxRetries=parseInt(process.env.AWS_REGISTER_MAX_RETRIES,10)),process.env.AWS_REGISTER_RETRY_INTERVAL&&(e.retryInterval=parseInt(process.env.AWS_REGISTER_RETRY_INTERVAL,10)),e}function T(){const e=j(),r=F(),t={...P,...e||{},...r},n=t.instanceName||A.hostname();let o=!1;return process.env.AWS_AUTO_REGISTER!==void 0?o=process.env.AWS_AUTO_REGISTER==="true":e&&(o=!0),{enabled:o,serverUrl:t.serverUrl||d,tenantId:t.tenantId||"",userKey:t.userKey||"",connectionKey:t.connectionKey,instanceName:n,instanceId:t.instanceId,projectId:t.projectId,roleName:t.roleName,workspacePath:t.workspacePath,registerAddr:t.registerAddr,registerIp:t.registerIp,virtualIp:t.virtualIp,tunnel:typeof t.tunnel=="boolean"?t.tunnel:void 0,preferSameLanIp:t.preferSameLanIp!==!1,maxRetries:t.maxRetries,retryInterval:t.retryInterval}}function S(){const e=X(),r=F(),n=(e.length>0?e:[j()||{}]).map(o=>{const s={...P,...o,...r};let a=!1;return process.env.AWS_AUTO_REGISTER!==void 0?a=process.env.AWS_AUTO_REGISTER==="true":a=e.length>0||!!s.userKey,{enabled:a,serverUrl:s.serverUrl||d,tenantId:s.tenantId||"",userKey:s.userKey||"",connectionKey:s.connectionKey,instanceName:s.instanceName||A.hostname(),instanceId:s.instanceId,projectId:s.projectId,roleName:s.roleName,workspacePath:s.workspacePath,registerAddr:s.registerAddr,registerIp:s.registerIp,virtualIp:s.virtualIp,tunnel:typeof s.tunnel=="boolean"?s.tunnel:void 0,preferSameLanIp:s.preferSameLanIp!==!1,maxRetries:s.maxRetries,retryInterval:s.retryInterval}});return b=n.map(o=>o.connectionKey).filter(o=>!!(o&&o.trim())),n}function Q(){const e=A.networkInterfaces(),r=[];for(const t of Object.keys(e)){const n=e[t];if(n)for(const o of n)o.family==="IPv4"&&!o.internal&&r.push({address:o.address,netmask:o.netmask,name:t})}return r}function N(e){const r=e.split(".").map(Number);return(r[0]<<24)+(r[1]<<16)+(r[2]<<8)+r[3]}function Z(e,r,t){const n=N(e),o=N(r),s=N(t);return(n&s)===(o&s)}function ee(e){try{const r=new URL(e);return r.hostname==="localhost"||r.hostname==="127.0.0.1"?"127.0.0.1":/^(\d{1,3}\.){3}\d{1,3}$/.test(r.hostname)?r.hostname:null}catch{return null}}function re(e){return e==="127.0.0.1"}function te(e){const r=Q();if(r.length===0)return i.warn("[AutoRegister] \u672A\u627E\u5230\u4EFB\u4F55\u975E\u5185\u90E8 IP \u5730\u5740\uFF0C\u4F7F\u7528 127.0.0.1"),"127.0.0.1";const t=ee(e);if(t){if(re(t))return"127.0.0.1";for(const n of r)if(Z(n.address,t,n.netmask))return i.info(`[AutoRegister] \u627E\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u540C\u5B50\u7F51\u7684 IP: ${n.address} (\u7F51\u5361: ${n.name}, \u5B50\u7F51\u63A9\u7801: ${n.netmask})`),n.address;i.warn(`[AutoRegister] \u672A\u627E\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3 (${t}) \u540C\u5B50\u7F51\u7684\u672C\u673A IP\uFF0C\u4F7F\u7528 127.0.0.1`)}else i.warn("[AutoRegister] \u65E0\u6CD5\u89E3\u6790\u8C03\u5EA6\u4E2D\u5FC3 IP\uFF0C\u4F7F\u7528 127.0.0.1");return"127.0.0.1"}function ne(e=d){return te(e)}function D(e){const r=e||T();return!r.enabled||!r.userKey?!1:r.tunnel===!0?!0:r.tunnel===!1?!1:!r.registerAddr&&!r.registerIp&&!r.virtualIp}function U(e){const r=M();if(D(e)){const s=e.serverUrl||d;try{const a=new URL(s);if(!e.instanceId)i.warn("[AutoRegister] \u96A7\u9053\u6A21\u5F0F\u4F46\u7F3A\u5C11 instanceId\uFF0C\u964D\u7EA7\u4E3A\u76F4\u8FDE\u6A21\u5F0F");else return`${a.protocol}//${a.host}/tunnel/${e.instanceId}`}catch{i.warn("[AutoRegister] serverUrl \u89E3\u6790\u5931\u8D25\uFF0C\u964D\u7EA7\u4E3A\u76F4\u8FDE\u6A21\u5F0F")}}const t=e.preferSameLanIp===!1?"127.0.0.1":ne(e.serverUrl||d),n=e.registerAddr||e.registerIp||e.virtualIp||t;return n?/^https?:\/\//i.test(n)?n:/:[0-9]+$/.test(n)?`http://${n}`:`http://${n}:${r}`:`http://127.0.0.1:${r}`}function y(){return S()[0]||T()}function Re(e){const r=String(e||"").trim();if(!r)return;const t=[];for(const o of S())o?.serverUrl&&t.push(o.serverUrl);const n=h();n.schedulerBaseUrl&&t.push(n.schedulerBaseUrl);for(const o of t){const s=q(o);if(s&&s===r)return p(o)}}function se(e){return e?Object.entries(u.registrations).find(([,t])=>t===e)?.[0]:void 0}function _(e,r){const t=se(r);if(t)return t;const n=f(e.serverUrl);if(n&&(n!==d||process.env.AWS_RUNTIME_SCHEDULER_BASE_URL))return n;const o=h(),s=f(o.schedulerBaseUrl);return o.status==="paired"&&s?s:n||d}async function oe(e){const r=e.instanceName||A.hostname(),t=e.serverUrl||d,n={tenantId:e.tenantId,userKey:e.userKey,instanceId:e.instanceId,instanceName:r,hostname:A.hostname(),virtualIp:e.registerAddr||e.registerIp||e.virtualIp,runtimeBridgeBaseUrl:U(e),connectionKey:e.connectionKey,workspacePath:e.workspacePath,projectId:e.projectId,roleName:e.roleName};return i.info(`[AutoRegister] \u6B63\u5728\u6CE8\u518C\u5B9E\u4F8B: ${r}`),i.info(`[AutoRegister] \u8C03\u5EA6\u4E2D\u5FC3: ${t}`),i.info(`[AutoRegister] \u7528\u6237 Key: ${e.userKey?"****"+e.userKey.slice(-4):"(\u672A\u8BBE\u7F6E)"}`),i.info(`[AutoRegister] \u79DF\u6237 ID: ${e.tenantId||"(\u81EA\u52A8\u63A8\u5BFC)"}`),(await I.post(`${t}/api/instances/register`,n,{headers:{"Content-Type":"application/json"},timeout:1e4})).data}function ie(e,r){const t=m();return z(t,()=>{if(!g.existsSync(t))return;const n=g.readFileSync(t,"utf-8"),o=JSON.parse(n),s=p(e);if(!s)return;let a=!1;const l=c=>{p(String(c.serverUrl||c.schedulerBaseUrl||""))===s&&r&&c.instanceId!==r&&(c.instanceId=r,a=!0)};if(Array.isArray(o.autoRegisterTargets))for(const c of o.autoRegisterTargets)c&&typeof c=="object"&&!Array.isArray(c)&&l(c);else l(o);a&&(g.writeFileSync(t,JSON.stringify(o,null,2),"utf-8"),i.info(`[AutoRegister] \u5DF2\u56DE\u5199 instanceId \u5230 config.json (serverUrl=${e})`))})}async function ae(e){const r=_(y(),e),t=E(r);if(!t)throw new Error("runtimeAccessToken is required to unregister bridge instance");return(await I.post(`${r}/api/instances/unregister`,{instanceId:e},{headers:{"Content-Type":"application/json","X-Runtime-Token":t},timeout:1e4})).data}async function Se(e){const r=e?[{...T(),...e}]:S(),n=(r.length>1?await Promise.all(r.map(s=>$(s))):[await $(r[0]||T())]).every(Boolean),o=r.every(s=>!s.enabled||!s.userKey);if(!e&&(n||o)){const{stopTunnelClientsExcept:s}=await import("./tunnel-client.js");s(r.map(a=>a.serverUrl).filter(a=>!!a))}return n}async function $(e,r){if(!e.enabled)return i.info("[AutoRegister] \u81EA\u52A8\u6CE8\u518C\u672A\u542F\u7528"),i.info(`[AutoRegister] \u8981\u542F\u7528\u81EA\u52A8\u6CE8\u518C\uFF0C\u8BF7\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6 ${m()} \u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF AWS_AUTO_REGISTER=true`),!1;if(!e.userKey)return i.error("[AutoRegister] \u7F3A\u5C11\u7528\u6237 Key\uFF08\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u8BBE\u7F6E userKey \u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF AWS_USER_KEY\uFF09"),!1;const t=D(e);t&&!e.instanceId&&(e={...e,instanceId:`bridge-${G().replace(/-/g,"").slice(0,12)}`},i.info(`[AutoRegister] \u96A7\u9053\u6A21\u5F0F\uFF1A\u5DF2\u9884\u58F0\u660E instanceId=${e.instanceId}`));const n=r?.backgroundRetry?1:e.maxRetries??3,o=e.retryInterval??2e3;for(let s=1;s<=n;s++){try{u.lastAttempt=new Date;const a=await oe(e);if(a.success){if(u.registered=!0,u.instanceId=a.instanceId,a.instanceId&&(u.registrations[e.serverUrl||d]=a.instanceId),u.error=void 0,i.info("[AutoRegister] \u2713 \u6CE8\u518C\u6210\u529F\uFF01"),i.info(`[AutoRegister] \u5B9E\u4F8B ID: ${a.instanceId}`),i.info(`[AutoRegister] \u6D88\u606F: ${a.message}`),i.info(`[AutoRegister] \u66F4\u65B0: ${a.isUpdate?"\u662F":"\u5426"}`),a.runtimeAccessToken)try{const l=e.serverUrl||d;K({accessToken:a.runtimeAccessToken,instanceId:a.instanceId,userId:a.userId,schedulerBaseUrl:l});const c=p(a.serverUrl);c&&c!==p(l)&&(C({serverBaseUrl:c,accessToken:a.runtimeAccessToken}),i.info(`[AutoRegister] \u68C0\u6D4B\u5230 server \u4E0B\u53D1\u5730\u5740(${c})\u4E0E\u8FDE\u63A5\u5730\u5740(${l})\u4E0D\u540C\uFF0C\u5DF2\u6309\u4E24\u4E2A\u5730\u5740\u5206\u522B\u4FDD\u5B58 scoped token`)),i.info("[AutoRegister] \u5DF2\u4FDD\u5B58\u8C03\u5EA6\u4E2D\u5FC3\u4E0B\u53D1\u7684 runtime access token"),a.instanceId&&ie(e.serverUrl||d,a.instanceId).catch(B=>{i.warn(`[AutoRegister] \u56DE\u5199 instanceId \u5230 config.json \u5931\u8D25: ${B.message}`)})}catch(l){const c=l;return i.error(`[AutoRegister] \u4FDD\u5B58 runtime access token \u5931\u8D25: ${c.message}`),u.error=c.message,!1}else i.warn("[AutoRegister] \u6CE8\u518C\u54CD\u5E94\u672A\u5305\u542B runtime access token\uFF0CMCP \u5C06\u65E0\u6CD5\u8BBF\u95EE\u8C03\u5EA6\u4E2D\u5FC3\uFF0C\u8BF7\u68C0\u67E5 server \u7684 bridge \u5B9E\u4F8B token \u9881\u53D1\u903B\u8F91");if(t&&a.instanceId&&a.runtimeAccessToken){const{startTunnelClient:l}=await import("./tunnel-client.js"),c=e.serverUrl||d;l(c,a.instanceId),i.info(`[AutoRegister] \u96A7\u9053\u5BA2\u6237\u7AEF\u5DF2\u542F\u52A8: server=${c}, instanceId=${a.instanceId}`)}return!0}else i.warn(`[AutoRegister] \u6CE8\u518C\u5931\u8D25: ${a.message}`),u.error=a.message}catch(a){const l=a,c=l.response?.data?JSON.stringify(l.response.data):l.message;i.error(`[AutoRegister] \u6CE8\u518C\u8BF7\u6C42\u5931\u8D25 (\u5C1D\u8BD5 ${s}/${n}): ${c}`),u.error=c}s<n&&(i.info(`[AutoRegister] ${o/1e3} \u79D2\u540E\u91CD\u8BD5...`),await new Promise(a=>setTimeout(a,o)))}return r?.backgroundRetry?i.warn(`[AutoRegister] \u540E\u53F0\u91CD\u8BD5\u6CE8\u518C\u4ECD\u672A\u6210\u529F (server=${e.serverUrl||d}): ${u.error||"\u672A\u77E5"}`):(i.error("[AutoRegister] \u2717 \u6CE8\u518C\u5931\u8D25\uFF0C\u5DF2\u8FBE\u6700\u5927\u91CD\u8BD5\u6B21\u6570"),i.error("[AutoRegister] ========================================"),i.error("[AutoRegister] \u81EA\u52A8\u6CE8\u518C\u5DF2\u542F\u7528\u4F46\u6CE8\u518C\u5931\u8D25\uFF0C\u5B9E\u4F8B\u6682\u65F6\u65E0\u6CD5\u6B63\u5E38\u5DE5\u4F5C"),i.error("[AutoRegister] \u8BF7\u68C0\u67E5\u4EE5\u4E0B\u914D\u7F6E\uFF1A"),i.error(`[AutoRegister] - \u7528\u6237 Key (userKey): ${e.userKey?"****"+e.userKey.slice(-4):"(\u672A\u8BBE\u7F6E)"}`),i.error(`[AutoRegister] - \u79DF\u6237 ID (tenantId): ${e.tenantId||"(\u53EF\u9009\uFF0C\u5C06\u81EA\u52A8\u63A8\u5BFC)"}`),i.error(`[AutoRegister] - \u5B9E\u4F8B\u540D (instanceName): ${e.instanceName||"(\u4F7F\u7528\u4E3B\u673A\u540D)"}`),i.error(`[AutoRegister] - \u8C03\u5EA6\u4E2D\u5FC3\u5730\u5740: ${e.serverUrl||d}`),i.error(`[AutoRegister] - \u6700\u540E\u9519\u8BEF: ${u.error||"\u672A\u77E5"}`),i.error("[AutoRegister] ========================================"),i.error(`[AutoRegister] \u914D\u7F6E\u6765\u6E90\uFF1A${m()} \u6216\u73AF\u5883\u53D8\u91CF`),i.warn(`[AutoRegister] \u5C06\u5728\u540E\u53F0\u6301\u7EED\u91CD\u8BD5\u6CE8\u518C\uFF08\u6BCF ${Math.round(W()/1e3)} \u79D2\uFF09\uFF0C\u76F4\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u5EFA\u7ACB\u8FDE\u63A5`)),L(e),!1}async function ye(){const e=y();if(!e.userKey)return{success:!1,error:"userKey is required for runtime token refresh"};const r=w(),t=_(e),n=U(e);try{const o=await I.post(`${t}/api/instances/runtime-tokens/refresh`,{tenantId:e.tenantId,userKey:e.userKey,instanceId:r.instanceId,instanceName:e.instanceName,runtimeBridgeBaseUrl:n},{headers:{"Content-Type":"application/json"},timeout:1e4});if(!o.data.success||!o.data.runtimeAccessToken)return{success:!1,error:o.data.message||"scheduler did not return runtimeAccessToken"};const a=E()!==o.data.runtimeAccessToken;return K({accessToken:o.data.runtimeAccessToken,instanceId:r.instanceId,userId:o.data.userId||e.userKey,schedulerBaseUrl:t}),{success:!0,runtimeAccessToken:o.data.runtimeAccessToken,updated:a}}catch(o){const s=o;return{success:!1,error:s.response?.data?JSON.stringify(s.response.data):s.message}}}async function ve(e){const r=x(e);if(!r)return{success:!1,error:"serverUrl is required for runtime token refresh"};const t=S().find(s=>x(s.serverUrl)===r)||y();if(!t.userKey)return{success:!1,error:"userKey is required for runtime token refresh"};const n=w(),o=U(t);try{const s=await I.post(`${r}/api/instances/runtime-tokens/refresh`,{tenantId:t.tenantId,userKey:t.userKey,instanceId:n.instanceId,instanceName:t.instanceName,runtimeBridgeBaseUrl:o},{headers:{"Content-Type":"application/json"},timeout:1e4});if(!s.data.success||!s.data.runtimeAccessToken)return{success:!1,error:s.data.message||"scheduler did not return runtimeAccessToken"};const l=E(r)!==s.data.runtimeAccessToken;return C({serverBaseUrl:r,accessToken:s.data.runtimeAccessToken}),{success:!0,runtimeAccessToken:s.data.runtimeAccessToken,updated:l}}catch(s){const a=s;return{success:!1,error:a.response?.data?JSON.stringify(a.response.data):a.message}}}async function Te(){if(!u.registered||!u.instanceId)return i.info("[AutoRegister] \u5B9E\u4F8B\u672A\u6CE8\u518C\uFF0C\u65E0\u9700\u6CE8\u9500"),!0;try{const e=await ae(u.instanceId);if(e.success){i.info(`[AutoRegister] \u2713 \u6CE8\u9500\u6210\u529F: ${u.instanceId}`);const r=_(y(),u.instanceId);h().schedulerBaseUrl&&Y(r),J();try{const{stopTunnelClientForServer:n}=await import("./tunnel-client.js");n(r)}catch(n){i.warn(`[AutoRegister] \u6CE8\u9500\u540E\u505C\u6B62\u96A7\u9053\u5931\u8D25: ${n.message}`)}return u.registered=!1,u.instanceId=void 0,!0}else return i.warn(`[AutoRegister] \u6CE8\u9500\u5931\u8D25: ${e.message}`),!1}catch(e){const r=e;return i.error(`[AutoRegister] \u6CE8\u9500\u8BF7\u6C42\u5931\u8D25: ${r.message}`),!1}}function Ue(){return{...u}}function _e(){return u.registered}function Ee(){return u.instanceId}async function he(){const e=y(),r=u.instanceId,t=_(e,r),n={};if(r&&(n.instanceId=r),e.enabled&&(n.runtimeBridgeBaseUrl=U(e)),!n.instanceId&&!n.runtimeBridgeBaseUrl)return i.info("[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\uFF1A\u6CA1\u6709 instanceId \u6216 runtimeBridgeBaseUrl\uFF0C\u8DF3\u8FC7\u6E05\u7406"),{success:!0,agentCount:0};try{i.info("[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\uFF1A\u6B63\u5728\u901A\u77E5\u8C03\u5EA6\u4E2D\u5FC3..."),i.info(`[AutoRegister] instanceId: ${n.instanceId||"(\u65E0)"}`),i.info(`[AutoRegister] runtimeBridgeBaseUrl: ${n.runtimeBridgeBaseUrl||"(\u65E0)"}`);const o=await I.post(`${t}/api/instances/bridge-restart-cleanup`,n,{headers:{"Content-Type":"application/json"},timeout:1e4});return o.data.success?(i.info(`[AutoRegister] \u2713 Bridge \u91CD\u542F\u6E05\u7406\u6210\u529F\uFF1A${o.data.message}`),i.info(`[AutoRegister] \u6E05\u7406\u4E86 ${o.data.agentCount||0} \u4E2A Agent`),{success:!0,agentCount:o.data.agentCount||0}):(i.warn(`[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\u5931\u8D25\uFF1A${o.data.message}`),{success:!1,error:o.data.message})}catch(o){const s=o,a=s.response?.data?JSON.stringify(s.response.data):s.message;return i.warn(`[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\u8BF7\u6C42\u5931\u8D25\uFF1A${a}`),{success:!1,error:a}}}export{Se as autoRegister,he as bridgeRestartCleanup,Ie as cancelBackgroundRegisterRetries,m as getAutoRegisterConfigFilePath,Ae as getConfiguredConnectionKeys,Ee as getInstanceId,Ue as getRegistrationState,_e as isRegistered,D as isTunnelConfig,T as loadConfig,S as loadConfigs,y as loadPrimaryLifecycleConfig,ye as requestRuntimeAccessTokenRefresh,ve as requestRuntimeAccessTokenRefreshForServer,U as resolveRuntimeBridgeBaseUrl,Re as resolveSchedulerBaseUrlFromToken,Te as unregister};
|
|
2
2
|
|
|
@@ -72,9 +72,19 @@ export interface LaunchStartupWaitResult {
|
|
|
72
72
|
logTail: LaunchLogEntry[];
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
export declare class LaunchAlreadyRunningError extends Error {
|
|
76
|
+
|
|
77
|
+
readonly existing: LaunchRun;
|
|
78
|
+
constructor(existing: LaunchRun);
|
|
79
|
+
}
|
|
80
|
+
|
|
75
81
|
export interface LaunchBatchItemResult {
|
|
76
82
|
configId: string;
|
|
77
83
|
ok: boolean;
|
|
84
|
+
|
|
85
|
+
skipped?: boolean;
|
|
86
|
+
|
|
87
|
+
message?: string;
|
|
78
88
|
run?: LaunchRun;
|
|
79
89
|
error?: string;
|
|
80
90
|
wait?: LaunchStartupWaitResult;
|
|
@@ -85,6 +95,8 @@ export interface LaunchBatchResult {
|
|
|
85
95
|
summary: {
|
|
86
96
|
total: number;
|
|
87
97
|
started: number;
|
|
98
|
+
|
|
99
|
+
skipped: number;
|
|
88
100
|
failed: number;
|
|
89
101
|
ready: number;
|
|
90
102
|
exited: number;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import{exec as
|
|
1
|
+
import{exec as j,spawn as z}from"node:child_process";import{promises as F}from"node:fs";import A from"node:os";import M from"node:path";import{promisify as J}from"node:util";import{atomicWriteJsonFile as U,withFileLock as G}from"../utils/file-utils.js";import{createLogger as V}from"../utils/logger.js";import{LaunchMetricsMonitor as X}from"./launch-metrics.js";import{getLaunchStreamHub as x}from"./launch-streams.js";import{getListeningPortsForProcessTrees as k}from"./port-detector.js";import{isProcessRunning as L,terminateProcessTree as E}from"./process-detector.js";import{RingBuffer as O}from"./ring-buffer.js";const C=J(j),g=V("launch-manager"),D=5e3,B=4096,K=1500,Y=20;class H extends Error{constructor(t){super(`\u542F\u52A8\u9879\u5DF2\u5728\u8FD0\u884C: pid=${t.pid}`),this.name="LaunchAlreadyRunningError",this.existing=t}}function N(){return M.join(A.tmpdir(),"agentswork-runtime-bridge","launch-runs.json")}function Z(l,t){return l.replace(/\$\{([^}]+)\}/g,(e,r)=>{const s=r.trim(),n=s.toUpperCase();if(n==="WORKSPACE")return t.workspacePath||"";if(n==="JAVA_HOME")return t.jdkPath||process.env.JAVA_HOME||"";if(n==="HOME")return A.homedir();if(t.env&&t.env[s]!==void 0)return t.env[s];if(t.env){for(const[i,a]of Object.entries(t.env))if(i.toUpperCase()===n)return a}return e})}function Q(l){const t={...process.env};l.env&&Object.assign(t,l.env);for(const e of Object.keys(t))if(e.toUpperCase()==="PATH"&&e!=="PATH"){const r=t[e];delete t[e],t.PATH===void 0&&typeof r=="string"&&(t.PATH=r)}if(l.jdkPath){t.JAVA_HOME=l.jdkPath;const e=M.join(l.jdkPath,"bin"),r=M.delimiter;t.PATH=t.PATH?`${e}${r}${t.PATH}`:e}return t}const q=256,tt=120;class W{constructor(t=()=>{}){this.utf8Probe=new TextDecoder("utf-8",{fatal:!0}),this.utf8=new TextDecoder("utf-8"),this.gbk=new TextDecoder("gbk"),this.mode=null,this.buffered=[],this.bufferedSize=0,this.flushTimer=null,this.onFlush=t}decode(t){return this.mode!==null?(this.mode==="gbk"?this.gbk:this.utf8).decode(t,{stream:!0}):(this.buffered.push(t),this.bufferedSize+=t.length,this.bufferedSize>=q?this.commit():(this.flushTimer===null&&(this.flushTimer=setTimeout(()=>{this.flushTimer=null,this.onFlush(this.commit())},tt)),""))}finalize(){return this.flushTimer!==null&&(clearTimeout(this.flushTimer),this.flushTimer=null),this.mode===null?this.commit():(this.mode==="gbk"?this.gbk:this.utf8).decode()}commit(){if(this.flushTimer!==null&&(clearTimeout(this.flushTimer),this.flushTimer=null),this.mode!==null)return"";const t=Buffer.concat(this.buffered,this.bufferedSize);this.buffered=[],this.bufferedSize=0;try{return this.utf8Probe.decode(t),this.mode="utf8",this.utf8.decode(t)}catch{return this.mode="gbk",this.gbk.decode(t)}}}function et(l){const t=l.length>0&&!l.endsWith(`
|
|
2
2
|
`)?l+`
|
|
3
|
-
`:l;return t.length>B?t.slice(-B):t}async function
|
|
4
|
-
`});
|
|
5
|
-
`);const c=this.runs.get(e);c&&
|
|
3
|
+
`:l;return t.length>B?t.slice(-B):t}async function st(l){const t=A.platform();for(let e=0;e<6;e+=1){try{if(t==="win32"){const r=`Get-CimInstance Win32_Process -Filter "ParentProcessId = ${l} AND Name <> 'conhost.exe'" | Select-Object -First 1 ProcessId | ConvertTo-Json -Compress`,s=Buffer.from(r,"utf16le").toString("base64"),{stdout:n}=await C(`powershell -NoProfile -NonInteractive -EncodedCommand ${s}`,{encoding:"utf8",timeout:5e3,windowsHide:!0}),i=n.replace(/#\s*<\s*CLIXML[\s\S]*?(?=\{|\[|$)/g,"").trim(),a=JSON.parse(i||"null"),h=Number(a?.ProcessId);if(Number.isFinite(h)&&h>0)return h}else{const{stdout:r}=await C(`pgrep -P ${l} | head -n 1`,{encoding:"utf8",timeout:3e3}),s=Number(r.trim());if(Number.isFinite(s)&&s>0)return s}}catch{}await new Promise(r=>setTimeout(r,300))}return null}class S{constructor(){this.runs=new Map,this.logs=new Map,this.startupWaiters=new Map,this.readinessMatchers=new Map,this.logListeners=new Map,this.metricsMonitor=new X(()=>this.runningRefs()),this.restored=!1}static getInstance(){return S.instance===null&&(S.instance=new S),S.instance}runningRefs(){const t=[];for(const e of this.runs.values())e.state==="running"&&e.pid>0&&t.push({configId:e.configId,pid:e.pid});return t}async start(t){const e=t.configId;if(!e||!e.trim())throw new Error("configId is required");if(!t.command||!t.command.trim())throw new Error("command is required");let r=null;if(t.readinessPattern&&t.readinessPattern.trim())try{r=new RegExp(t.readinessPattern.trim())}catch(o){throw new Error(`readinessPattern \u6B63\u5219\u8BED\u6CD5\u65E0\u6548: ${o.message}`)}const s=t.startedBy?.trim()||void 0;await this.ensureRestored();const n=this.runs.get(e);if(n&&n.state==="running"&&L(n.pid))throw new H(n);const i=Z(t.command,{workspacePath:t.workspacePath,jdkPath:t.jdkPath,env:t.env}),a=t.cwd||t.workspacePath||process.cwd(),h=Q(t);g.info(`[start] \u542F\u52A8\u547D\u4EE4: configId=${e}, cwd=${a}, command=${i}`);let m;try{m=z(i,{cwd:a,env:h,shell:!0,windowsHide:!0})}catch(o){const c=`\u8FDB\u7A0B\u542F\u52A8\u5931\u8D25: ${o.message}`;throw g.error(`[start] spawn \u5931\u8D25: configId=${e}, error=${c}`),new Error(c)}const w=m.pid??0,T={configId:e,pid:w,state:"running",startedAt:new Date().toISOString(),command:i,cwd:a,...s?{startedBy:s}:{}};this.runs.set(e,T),this.publishRunStatus(e,!0),this.metricsMonitor.clear(e),this.metricsMonitor.ensureRunning();let p=this.logs.get(e);p||(p=new O(D),this.logs.set(e,p));const I=p.getSinceIndex(-1).nextIndex;r?this.readinessMatchers.set(e,{pattern:r,fromIndex:I+1}):this.readinessMatchers.delete(e);const y=p.append({stream:"stdout",text:`> ${i}
|
|
4
|
+
`});x().publish(e,"logs",y.index,y.data);let R=null;(async()=>{const o=await st(w),c=this.runs.get(e);o&&c?.pid===w&&(R=o,this.runs.set(e,{...c,pid:o}),await this.persist(),this.publishRunStatus(e))})();const P=o=>o!==void 0&&(o.pid===w||o.pid===R),u=new W(o=>{f("stdout",o)}),d=new W(o=>{f("stderr",o)}),f=(o,c)=>{const b=et(c);if(b){const $=p.append({stream:o,text:b});x().publish(e,"logs",$.index,$.data);const v=this.logListeners.get(e);if(v&&v.size>0)for(const _ of v)try{_($)}catch{}}};return m.stdout.on("data",o=>{f("stdout",u.decode(o))}),m.stderr.on("data",o=>{f("stderr",d.decode(o))}),m.on("error",o=>{f("stderr",`[\u542F\u52A8\u5931\u8D25] ${o.message}
|
|
5
|
+
`);const c=this.runs.get(e);c&&P(c)&&c.state==="running"&&(this.runs.set(e,{...c,state:"exited",exitedAt:new Date().toISOString(),exitCode:-1}),x().publishState(e,{configId:e,state:"exited",exitCode:-1}),this.publishRunStatus(e),this.persist(),this.resolveStartupWaiters(e,"exited",-1))}),m.on("exit",(o,c)=>{f("stdout",u.finalize()),f("stderr",d.finalize()),f("stderr",`
|
|
6
6
|
[\u8FDB\u7A0B\u9000\u51FA] code=${o??"-"}${c?` signal=${c}`:""}
|
|
7
|
-
`);const
|
|
7
|
+
`);const b=this.runs.get(e);b&&P(b)&&b.state==="running"&&(this.runs.set(e,{...b,state:"exited",exitedAt:new Date().toISOString(),exitCode:o}),x().publishState(e,{configId:e,state:"exited",exitCode:o}),this.publishRunStatus(e),this.persist(),this.resolveStartupWaiters(e,"exited",o))}),await this.persist(),T}async stop(t,e="manual",r){await this.ensureRestored();const s=this.runs.get(t);if(!s||s.state!=="running")return{success:!1,message:"\u542F\u52A8\u9879\u672A\u5728\u8FD0\u884C",pid:s?.pid};const n=r?.trim()||void 0;g.info(`[stop] \u7EC8\u6B62\u8FDB\u7A0B\u6811: configId=${t}, pid=${s.pid}, reason=${e}${n?`, actor=${n}`:""}`),this.runs.set(t,{...s,state:"stopped",exitedAt:new Date().toISOString(),...n?{stoppedBy:n}:{}});const i=await E(s.pid),a=e==="shutdown"?`
|
|
8
8
|
[bridge \u505C\u6B62\uFF0C\u8FDB\u7A0B\u5DF2\u8054\u52A8\u7EC8\u6B62]
|
|
9
9
|
`:`
|
|
10
10
|
[\u5DF2\u624B\u52A8\u505C\u6B62]
|
|
11
|
-
`,h=this.logs.get(t)?.append({stream:"stderr",text:a});return h&&
|
|
11
|
+
`,h=this.logs.get(t)?.append({stream:"stderr",text:a});return h&&x().publish(t,"logs",h.index,h.data),x().publishState(t,{configId:t,state:"stopped"}),this.publishRunStatus(t),await this.persist(),this.resolveStartupWaiters(t,"stopped",void 0),{success:i.failed===0,message:i.failed===0?"\u8FDB\u7A0B\u5DF2\u505C\u6B62":`\u90E8\u5206\u8FDB\u7A0B\u672A\u80FD\u7EC8\u6B62\uFF08terminated=${i.terminated}, failed=${i.failed}\uFF09`,pid:s.pid}}async restart(t){await this.ensureRestored();const e=this.runs.get(t.configId);return e&&e.state==="running"&&await this.stop(t.configId,"manual",t.startedBy),await this.start(t)}async startBatch(t,e){await this.ensureRestored();const r=await Promise.all(t.map(async n=>{try{const i=await this.start(n);return{configId:n.configId,ok:!0,run:i}}catch(i){return i instanceof H?{configId:n.configId,ok:!0,skipped:!0,message:"\u5F53\u524D\u5DF2\u5904\u4E8E\u542F\u52A8/\u6B63\u5728\u542F\u52A8\u72B6\u6001\uFF0C\u8DF3\u8FC7",run:i.existing}:{configId:n.configId,ok:!1,error:i.message}}}));if(e>0){const n=await Promise.all(r.map(async i=>{if(!i.ok||i.skipped)return i;try{const a=await this.waitStartupResult(i.configId,e);return{...i,wait:a}}catch(a){return{...i,error:a.message}}}));r.splice(0,r.length,...n)}const s={total:r.length,started:0,skipped:0,failed:0,ready:0,exited:0,stopped:0,timeout:0};for(const n of r){if(!n.ok){s.failed+=1;continue}if(n.skipped){s.skipped+=1;continue}s.started+=1,n.wait&&(s[n.wait.outcome]+=1)}return{items:r,summary:s}}async stopAll(){await this.ensureRestored();const t=Array.from(this.runs.values()).filter(r=>r.state==="running");let e=0;for(const r of t)try{const s=await this.stop(r.configId,"shutdown");s.success?e++:g.warn(`[stopAll] \u542F\u52A8\u9879\u672A\u80FD\u5B8C\u5168\u7EC8\u6B62: configId=${r.configId}, message=${s.message}`)}catch(s){g.warn(`[stopAll] \u505C\u6B62\u542F\u52A8\u9879\u5931\u8D25: configId=${r.configId}, error=${s.message}`)}return{running:t.length,stopped:e}}async waitStartupResult(t,e){const r=this.runs.get(t);if(!r)throw new Error("launch run not found");const s=Date.now(),n=()=>(this.logs.get(t)?.getLastN(Y)??[]).map(a=>a.data);if(r.state!=="running")return{outcome:r.state==="stopped"?"stopped":"exited",waitedMs:0,...r.state==="exited"?{exitCode:r.exitCode??null}:{},logTail:n()};const i=this.readinessMatchers.get(t);if(i){const a=this.scanReadinessMatch(t,i);if(a!==null)return{outcome:"ready",waitedMs:0,matchedLine:a,logTail:n()}}return await new Promise(a=>{let h=!1,m=null,w=null,T=!1,p=null;const I=()=>{m!==null&&(clearInterval(m),m=null),w!==null&&(clearTimeout(w),w=null);const u=this.startupWaiters.get(t);if(u&&(u.delete(R),u.size===0&&this.startupWaiters.delete(t)),p!==null){const d=this.logListeners.get(t);d&&(d.delete(p),d.size===0&&this.logListeners.delete(t)),p=null}},y=u=>{h||(h=!0,I(),a(u))},R=(u,d)=>{y({outcome:u==="stopped"?"stopped":"exited",waitedMs:Date.now()-s,...u==="exited"?{exitCode:d??null}:{},logTail:n()})};let P=this.startupWaiters.get(t);if(P||(P=new Set,this.startupWaiters.set(t,P)),P.add(R),i){p=d=>{if(!(h||d.index<i.fromIndex)){for(const f of d.data.text.split(/\r?\n/))if(f&&i.pattern.test(f)){y({outcome:"ready",waitedMs:Date.now()-s,matchedLine:f.trim(),logTail:n()});return}}};let u=this.logListeners.get(t);u||(u=new Set,this.logListeners.set(t,u)),u.add(p)}else{const u=async()=>{if(h||T)return;const d=this.runs.get(t);if(!(!d||d.state!=="running"||d.pid<=0)){T=!0;try{const o=(await k([d.pid])).get(d.pid)??[];if(o.length>0&&!h){const c=this.runs.get(t);c?.state==="running"&&c.pid===d.pid&&y({outcome:"ready",waitedMs:Date.now()-s,ports:o,logTail:n()})}}catch{}finally{T=!1}}};m=setInterval(()=>{u()},K),u()}w=setTimeout(()=>{y({outcome:"timeout",waitedMs:Date.now()-s,logTail:n()})},e)})}scanReadinessMatch(t,e){const r=this.logs.get(t);if(!r)return null;for(const s of r.getSinceIndex(e.fromIndex-1).entries)for(const n of s.data.text.split(/\r?\n/))if(n&&e.pattern.test(n))return n.trim();return null}resolveStartupWaiters(t,e,r){const s=this.startupWaiters.get(t);if(!(!s||s.size===0)){this.startupWaiters.delete(t);for(const n of s)try{n(e,r)}catch{}}}async listRuns(){await this.ensureRestored();const t=Array.from(this.runs.values()).filter(s=>s.state==="running"&&s.pid>0).map(s=>s.pid);let e=new Map;if(t.length>0)try{e=await k(t)}catch(s){g.debug(`[listRuns] \u7AEF\u53E3\u63A2\u6D4B\u5931\u8D25: ${s.message}`)}const r=[];for(const s of this.runs.values()){const n=this.logs.get(s.configId);r.push({...s,logTail:n?n.getLastN(20).map(i=>i.data):[],nextLogIndex:n?n.getSinceIndex(-1).nextIndex:0,ports:s.state==="running"?e.get(s.pid)??[]:[],metrics:this.metricsMonitor.getLatest(s.configId)??void 0})}return r}async getLogs(t,e){await this.ensureRestored();const r=this.runs.get(t);if(!r)return null;const s=this.logs.get(t);if(!s)return{configId:t,state:r.state,entries:[],nextIndex:0,oldestIndex:0};const{entries:n,nextIndex:i,oldestIndex:a}=s.getSinceIndex(e);return{configId:t,state:r.state,entries:n,nextIndex:i,oldestIndex:a}}getRun(t){return this.runs.get(t)}getMetrics(t,e){return this.metricsMonitor.getHistory(t,e)}getMetricsSince(t,e,r){return this.metricsMonitor.getHistoryEntriesSince(t,e,r)}async ensureRestored(){if(!this.restored){this.restored=!0;try{const t=await F.readFile(N(),"utf-8"),e=JSON.parse(t);for(const r of e){const s=r.pid>0&&L(r.pid);if(s){g.warn(`[restore] \u68C0\u6D4B\u5230\u4E0A\u6B21 bridge \u975E\u4F18\u96C5\u9000\u51FA\u540E\u7684\u6B8B\u7559\u8FDB\u7A0B\uFF0C\u8054\u52A8\u7EC8\u6B62: configId=${r.configId}, pid=${r.pid}`);try{await E(r.pid)}catch(n){g.warn(`[restore] \u7EC8\u6B62\u6B8B\u7559\u8FDB\u7A0B\u5931\u8D25: configId=${r.configId}, pid=${r.pid}, error=${n.message}`)}}this.runs.set(r.configId,{...r,state:"exited",...s?{exitedAt:new Date().toISOString()}:{}}),this.logs.set(r.configId,new O(D))}g.info(`[restore] \u5DF2\u6062\u590D ${e.length} \u6761\u542F\u52A8\u9879\u8FD0\u884C\u8BB0\u5F55`)}catch{}}}publishRunStatus(t,e=!1){const r=this.runs.get(t);r&&(x().publishStatusRun({...r}),!(!e||r.state!=="running"||r.pid<=0)&&setTimeout(()=>{const s=this.runs.get(t);!s||s.state!=="running"||s.pid<=0||(async()=>{let n=[];try{n=(await k([s.pid])).get(s.pid)??[]}catch{}const i=this.runs.get(t);i&&i.state==="running"&&i.pid===s.pid&&x().publishStatusRun({...i,ports:n})})()},2e3))}async persist(){const t=N();try{const e=Array.from(this.runs.values());await G(t,async()=>{await U(t,e)})}catch(e){g.warn(`[persist] \u6301\u4E45\u5316\u5931\u8D25: ${e.message}`)}}}S.instance=null;function mt(){return S.getInstance()}export{H as LaunchAlreadyRunningError,S as LaunchManager,W as StreamDecoder,mt as getLaunchManager,Z as resolvePlaceholders};
|
|
12
12
|
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
`,{encoding:"utf8",mode:384})}async function
|
|
1
|
+
import f from"node:fs/promises";import g from"node:path";import E from"axios";import{getRuntimeHomeDir as w}from"../config.js";import{createLogger as A}from"../utils/logger.js";import{checkBridgeUpdate as S}from"../utils/npm-version.js";import{loadConfigs as U,resolveRuntimeBridgeBaseUrl as $}from"./auto-register.js";import{getRuntimeAccessToken as D}from"./runtime-binding.js";import{appendUpdateLog as N}from"./update-log.js";const r=A("update-notifier"),h=6*60*60*1e3,y=3e4,T="\u5F53\u524D\u5BA2\u6237\u7AEFbridge\u53EF\u66F4\u65B0\uFF0C\u8BF7\u53CA\u65F6\u66F4\u65B0~";function v(){return g.join(w(),".aws-bridge","update-notify-state.json")}async function b(){try{const e=await f.readFile(v(),"utf8"),n=JSON.parse(e);return{latestVersion:n.latestVersion,notifiedAt:n.notifiedAt}}catch{return{}}}async function B(e){const n=v();await f.mkdir(g.dirname(n),{recursive:!0}),await f.writeFile(n,`${JSON.stringify(e,null,2)}
|
|
2
|
+
`,{encoding:"utf8",mode:384})}async function I(){const e=await S();if(!e.ok||!e.hasUpdate||!e.latestVersion||(await b()).latestVersion===e.latestVersion)return!1;const a=U().filter(t=>t.enabled&&!!t.serverUrl);if(a.length===0)return r.info(`[update-notifier] \u68C0\u6D4B\u5230\u65B0\u7248\u672C v${e.latestVersion}\uFF08\u5F53\u524D v${e.currentVersion}\uFF09\uFF0C\u4F46\u672A\u914D\u7F6E\u4EFB\u4F55\u8C03\u5EA6\u4E2D\u5FC3\uFF0C\u8DF3\u8FC7\u901A\u77E5`),!1;const i=e.currentVersion,l=e.latestVersion,d=a[0]?.instanceName||"",u={eventType:"update-available",bridgeInstanceId:a[0]?.instanceId||"",bridgeInstanceName:d,currentVersion:i,latestVersion:l,message:T},c=await Promise.allSettled(a.map(async t=>{const o=String(t.serverUrl).replace(/\/+$/,""),p=D(o);if(!p)throw r.warn(`[update-notifier] \u8DF3\u8FC7 ${o}\uFF1A\u7F3A\u5C11 runtime access token\uFF08\u672A\u6CE8\u518C\uFF09`),new Error("\u7F3A\u5C11 runtime access token\uFF08\u672A\u6CE8\u518C\uFF09");const _=$(t);await E.post(`${o}/api/runtime/callback/bridge-update-notify`,{...u,bridgeInstanceId:t.instanceId||u.bridgeInstanceId,bridgeInstanceName:t.instanceName||d,runtimeBridgeBaseUrl:_},{headers:{"X-Runtime-Token":p},timeout:1e4})})),m=c.some(t=>t.status==="fulfilled");if(m)await B({latestVersion:l,notifiedAt:new Date().toISOString()}),r.info(`[update-notifier] \u5DF2\u901A\u77E5 ${c.filter(t=>t.status==="fulfilled").length}/${c.length} \u4E2A\u8C03\u5EA6\u4E2D\u5FC3\uFF1Av${i} -> v${l}`),N(`\u68C0\u6D4B\u5230\u65B0\u7248\u672C v${l}\uFF08\u5F53\u524D v${i}\uFF09\uFF0C\u5DF2\u53D1\u9001\u53EF\u66F4\u65B0\u901A\u77E5`).catch(()=>{});else{r.warn(`[update-notifier] \u5411 ${c.length} \u4E2A\u8C03\u5EA6\u4E2D\u5FC3\u53D1\u9001\u66F4\u65B0\u901A\u77E5\u5747\u5931\u8D25\uFF0C\u5C06\u5728\u4E0B\u4E2A\u5468\u671F\u91CD\u8BD5`);for(const[t,o]of c.entries())o.status==="rejected"&&r.warn(`[update-notifier] \u901A\u77E5\u5931\u8D25: ${a[t]?.serverUrl}, ${o.reason?.message}`)}return m}let s=null;function M(){if(process.env.AWS_BRIDGE_UPDATE_CHECK_DISABLED==="true"){r.info("[update-notifier] \u7248\u672C\u68C0\u67E5\u5DF2\u901A\u8FC7 AWS_BRIDGE_UPDATE_CHECK_DISABLED \u5173\u95ED");return}if(s)return;const e=Number(process.env.AWS_BRIDGE_UPDATE_CHECK_INTERVAL_HOURS),n=Number.isFinite(e)&&e>0?e*60*60*1e3:h;setTimeout(()=>{I().catch(i=>{r.warn(`[update-notifier] \u68C0\u67E5\u5F02\u5E38: ${i?.message}`)})},y).unref?.(),s=setInterval(()=>{I().catch(i=>{r.warn(`[update-notifier] \u68C0\u67E5\u5F02\u5E38: ${i?.message}`)})},n),s.unref?.(),r.info(`[update-notifier] \u7248\u672C\u68C0\u67E5\u5B9A\u65F6\u4EFB\u52A1\u5DF2\u542F\u52A8\uFF0C\u95F4\u9694 ${Math.round(n/36e5)} \u5C0F\u65F6`)}function O(){s&&(clearInterval(s),s=null)}export{I as runUpdateCheck,M as startUpdateNotifier,O as stopUpdateNotifier};
|
|
3
3
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{spawn as E}from"node:child_process";import{promises as A}from"node:fs";import{createInterface as I}from"node:readline";import{randomBytes as S}from"node:crypto";import{prepareShellCommand as O,shellExecutable as R}from"./builtins/shellCommandPreparation.js";import{createShellOutputDecoder as M,decodeShellOutputChunk as w}from"./builtins/shellOutputDecoder.js";import{BackgroundOutputRingBuffer as D}from"./background-output-ringbuffer.js";import{BackgroundCommandStore as F}from"./background-command-store.js";const z=1e3,G=
|
|
1
|
+
import{spawn as E}from"node:child_process";import{promises as A}from"node:fs";import{createInterface as I}from"node:readline";import{randomBytes as S}from"node:crypto";import{prepareShellCommand as O,shellExecutable as R}from"./builtins/shellCommandPreparation.js";import{createShellOutputDecoder as M,decodeShellOutputChunk as w}from"./builtins/shellOutputDecoder.js";import{BackgroundOutputRingBuffer as D}from"./background-output-ringbuffer.js";import{BackgroundCommandStore as F}from"./background-command-store.js";const z=1e3,G=30*60*1e3,N=24*60*60*1e3,B=50*1024*1024,C=16,_=256,W=256*1024,X=100,$=5e3,q=256,b=20,v=5*60*1e3,L=1024*1024;class k{constructor(){this.tasksByAgent=new Map,this.store=new F}globalCount(){let t=0;for(const i of this.tasksByAgent.values())t+=i.size;return t}startCommand(t){const i=t.agentId,e=this.getOrCreateBucket(i);if(e.size>=C)throw new x("too_many_tasks",`Agent ${i} has ${e.size} background tasks (limit ${C}). Kill or wait for completion first.`);if(this.globalCount()>=_)throw new x("global_limit_reached",`Global background task limit ${_} reached.`);const n=this.generateTaskId(e),o=t.timeoutMs===void 0?G:t.timeoutMs>0?Math.min(t.timeoutMs,N):0,s=typeof t.inactivityTimeoutMs=="number"&&Number.isFinite(t.inactivityTimeoutMs)&&t.inactivityTimeoutMs>0?t.inactivityTimeoutMs:0,r=this.store.outputPathFor(i,n),u=t.commandText.length>80?`${t.commandText.slice(0,77)}...`:t.commandText,a={taskId:n,agentId:i,command:t.commandText,commandPreview:u,cwd:t.cwd,status:"running",startedAt:Date.now(),finishedAt:null,exitCode:null,signal:null,killedReason:null,timeoutMs:o,inactivityTimeoutMs:s,child:null,ringBuffer:new D,outputPath:r,outputWriteChain:Promise.resolve(),outputTruncated:!1,outputLineCount:0,outputBytes:0,notified:!1,completionWaiters:[],onCompleted:t.onCompleted,onOutput:t.onOutput,outputSeq:0,outputSubscribers:new Set,timeoutTimer:null,killEscalationTimer:null,retentionTimer:null,inactivityTimer:null,inactivityTimedOut:!1,finalized:!1,stdoutDecoder:M(),stderrDecoder:M(),stdoutText:"",stderrText:"",commandLineCount:0},c=new Promise(d=>{a.completionResolve=d});return e.set(n,a),this.spawnAndAttach(a,t).catch(d=>{a.ringBuffer.push(`[ACode] spawn failed: ${d?.message??String(d)}
|
|
2
2
|
`),this.finalizeTask(a,-1,null,"spawn_error")}),this.persistTask(a),{taskId:n,completion:c}}async spawnAndAttach(t,i){const e=R(),n=await O(i.commandText,i.workspaceRoot,e),o=process.platform==="win32",s=E(e.command,[...e.argsPrefix,n.commandText],{cwd:i.cwd,env:process.env,detached:!o,stdio:["ignore","pipe","pipe"],windowsVerbatimArguments:o,windowsHide:!0});t.child=s,t.commandFilePath=n.commandFilePath,t.commandLineCount=n.commandLineCount,t.inactivityTimeoutMs>0&&this.scheduleInactivity(t),s.stdout?.on("data",r=>{const u=w(t.stdoutDecoder,r);this.onOutput(t,"stdout",u)}),s.stderr?.on("data",r=>{const u=w(t.stderrDecoder,r);this.onOutput(t,"stderr",u)}),s.on("error",r=>{this.onOutput(t,"stderr",`[ACode] child error: ${r.message}
|
|
3
3
|
`),t.finalized||this.finalizeTask(t,-1,null,"child_error")}),s.on("close",(r,u)=>{const a=w(t.stdoutDecoder,void 0,!0),c=w(t.stderrDecoder,void 0,!0);if(a&&this.onOutput(t,"stdout",a),c&&this.onOutput(t,"stderr",c),t.ringBuffer.flush(),!t.finalized){const d=t.killedReason??null;this.finalizeTask(t,r,u,d??void 0)}}),t.timeoutMs>0&&(t.timeoutTimer=setTimeout(()=>{t.finalized||(t.killedReason="timeout",this.killProcessGroup(s))},t.timeoutMs),t.timeoutTimer.unref?.())}disableInactivityTimeout(t,i){const e=this.getTask(t,i);return e?(e.inactivityTimeoutMs=0,e.inactivityTimer&&(clearTimeout(e.inactivityTimer),e.inactivityTimer=null),!0):!1}onOutput(t,i,e){if(!e)return;t.outputSeq++;const n=t.outputSeq;if(t.outputSubscribers.size>0)for(const r of t.outputSubscribers)try{r.onLine({stream:i,text:e,seq:n})}catch{}const o=i==="stdout"?"stdoutText":"stderrText";if(Buffer.byteLength(t[o],"utf-8")<L){const r=L-Buffer.byteLength(t[o],"utf-8");t[o]+=r>0?e.slice(0,r):""}if(t.inactivityTimeoutMs>0&&this.scheduleInactivity(t),t.outputBytes>=B){if(!t.outputTruncated){t.outputTruncated=!0;const r=`
|
|
4
4
|
[ACode] output truncated at 50MB
|
|
5
5
|
`;t.ringBuffer.push(r),this.appendToFile(t,r)}t.ringBuffer.push(e);return}t.ringBuffer.push(e),t.onOutput?.({stream:i,text:e});const s=(e.match(/\n/g)??[]).length;t.outputLineCount+=s,t.outputBytes+=Buffer.byteLength(e,"utf-8"),this.appendToFile(t,e)}scheduleInactivity(t){t.finalized||t.inactivityTimeoutMs<=0||(t.inactivityTimer&&clearTimeout(t.inactivityTimer),t.inactivityTimer=setTimeout(()=>{t.finalized||!t.child||(t.inactivityTimedOut=!0,t.killedReason="inactivity",this.killProcessGroup(t.child))},t.inactivityTimeoutMs),t.inactivityTimer.unref?.())}appendToFile(t,i){return t.outputBytes>B?Promise.resolve():(t.outputWriteChain=t.outputWriteChain.then(()=>A.appendFile(t.outputPath,i,"utf-8")).catch(e=>{t.ringBuffer.push(`[ACode] output write failed: ${e?.message??e}
|
|
6
|
-
`)}),t.outputWriteChain)}finalizeTask(t,i,e,n){if(t.finalized)return;t.finalized=!0,t.timeoutTimer&&(clearTimeout(t.timeoutTimer),t.timeoutTimer=null),t.killEscalationTimer&&(clearTimeout(t.killEscalationTimer),t.killEscalationTimer=null),t.inactivityTimer&&(clearTimeout(t.inactivityTimer),t.inactivityTimer=null),t.child=null,t.finishedAt=Date.now();let o;n?(o="killed",t.killedReason=n):i===0?o="completed":o="failed",t.status=o,t.exitCode=i,t.signal=e;const s=n==="inactivity"||t.inactivityTimedOut,r={taskId:t.taskId,exitCode:i,signal:e,timedOut:n==="timeout"||s,inactivityTimedOut:s,outputFilePath:t.outputPath,outputLineCount:t.outputLineCount,outputSpilled:t.outputTruncated,commandFilePath:t.commandFilePath,commandLineCount:t.commandLineCount,timeoutMs:t.timeoutMs,inactivityTimeoutMs:t.inactivityTimeoutMs,stdout:t.stdoutText,stderr:t.stderrText,durationMs:t.finishedAt-t.startedAt};t.completionResolve?.(r);const u={taskId:t.taskId,status:o,exitCode:i,signal:e,timedOut:n==="timeout"||s,aborted:!1,durationMs:t.finishedAt-t.startedAt},a=t.completionWaiters;t.completionWaiters=[];for(const c of a)c(u);if(this.persistTask(t),t.onCompleted?.({taskId:t.taskId,agentId:t.agentId,status:o,exitCode:i,signal:e,commandPreview:t.commandPreview,outputLineCount:t.outputLineCount,outputBytes:t.outputBytes,outputPath:t.outputPath,finishedAt:t.finishedAt,killedReason:t.killedReason}),t.outputSubscribers.size>0){const c=Array.from(t.outputSubscribers);t.outputSubscribers.clear();for(const d of c)try{d.onDone({status:o,exitCode:i,signal:e})}catch{}}t.retentionTimer=setTimeout(()=>{this.evictTask(t.agentId,t.taskId)},_),t.retentionTimer.unref?.()}evictTask(t,i){const e=this.tasksByAgent.get(t);if(!e)return;const n=e.get(i);n&&(A.unlink(n.outputPath).catch(()=>{}),e.delete(i),e.size===0&&this.tasksByAgent.delete(t))}listTasks(t,i){const e=this.tasksByAgent.get(t);if(!e)return[];const n=[];for(const o of e.values())i&&i!=="all"&&o.status!==i||n.push(this.toSummary(o));return n.sort((o,s)=>s.startedAt-o.startedAt)}toSummary(t){return{taskId:t.taskId,status:t.status,command:t.command,commandPreview:t.commandPreview,cwd:t.cwd,startedAt:t.startedAt,finishedAt:t.finishedAt,exitCode:t.exitCode,signal:t.signal,outputLineCount:t.outputLineCount,outputBytes:t.outputBytes}}getTaskOutputSnapshot(t,i,e=500){const n=this.getTask(t,i);if(!n)return null;const o=n.ringBuffer.tail(e);return{taskId:n.taskId,status:n.status,exitCode:n.exitCode,signal:n.signal,startedAt:n.startedAt,finishedAt:n.finishedAt,command:n.command,lines:o,nextSeq:n.outputSeq+1,totalLines:n.outputLineCount,totalBytes:n.outputBytes,truncated:n.outputTruncated}}subscribeTaskOutput(t,i,e){const n=this.getTask(t,i);if(!n)return null;n.outputSubscribers.add(e);let o=!0;return()=>{o&&(o=!1,n.outputSubscribers.delete(e))}}async readOutput(t,i){const e=String(i.task_id??""),n=this.getTask(t,e),o=i.mode==="lines"||i.mode==="grep"?i.mode:"tail",s=Math.min(Math.max(1,i.line_size??100),W),r=Number.isFinite(i.start_line)&&(i.start_line??0)>0?Math.floor(i.start_line??0):0;if(!n)return{taskId:e,status:"killed",mode:o,lines:[],lineCount:0,metadata:{totalLines:0,totalBytes:0,returnedBytes:0,truncated:!1,outputTruncated:!1,hasMore:!1,nextStartLine:null,outputFile:""}};let u=[],a=!1,c=null;if(o==="tail"){const m=n.ringBuffer.tail(s),f=Math.max(0,n.outputLineCount-m.length);u=m.map((l,g)=>({line:f+g,text:l})),c=null}else if(o==="lines"){const m=n.ringBuffer.firstLineIndex(),f=m+n.ringBuffer.getLineCount();if(r>=m&&r<f)u=n.ringBuffer.offset(r,s).map((g,h)=>({line:r+h,text:g})),a=r+u.length<f,c=a?r+u.length:null;else if(r<f){const l=await this.readFromFile(n,"lines",r,s,0,0,void 0);u=l.rows,a=l.hasMore,c=l.nextStartLine}}else{const m=String(i.pattern??"");if(!m||m.length>$)return this._emptyResult(e,n,o);let f;try{f=new RegExp(m,"i")}catch{return this._emptyResult(e,n,o)}const l=Math.min(Math.max(0,i.context_before??0),v),g=Math.min(Math.max(0,i.context_after??0),v),h=await this.readFromFile(n,"grep",r,s,l,g,f);u=h.rows,a=h.hasMore,c=h.nextStartLine}const d=[];let p=0,T=!1;for(const m of u){const f=Buffer.byteLength(m.text,"utf-8")+1;if(d.length>=s||p+f>N){T=!0,a=!0;break}d.push(m),p+=f}const y=i.include_metadata!==!1;return{taskId:e,status:n.status,mode:o,lines:d,lineCount:d.length,metadata:y?{totalLines:n.outputLineCount,totalBytes:n.outputBytes,returnedBytes:p,truncated:T,outputTruncated:n.outputTruncated,hasMore:a,nextStartLine:a?c:null,outputFile:n.outputPath}:void 0}}_emptyResult(t,i,e){return{taskId:t,status:i.status,mode:e,lines:[],lineCount:0,metadata:{totalLines:i.outputLineCount,totalBytes:i.outputBytes,returnedBytes:0,truncated:!1,outputTruncated:i.outputTruncated,hasMore:!1,nextStartLine:null,outputFile:i.outputPath}}}async readFromFile(t,i,e,n,o,s,r){const u=[],a=new Set;let c=0,d=!1;const p=[];let T=-1/0;try{const y=await A.open(t.outputPath,"r"),m=I({input:y.createReadStream({encoding:"utf-8"}),crlfDelay:1/0});for await(const f of m){const l=c;if(c++,i==="grep"&&l-e>=X&&l>=e){d=!0;break}if(l>=e){if(i==="lines"){if(u.length>=n){d=!0;break}a.has(l)||(a.add(l),u.push({line:l,text:f}))}else if(r.test(f)){for(const h of p)h.line>=e&&!a.has(h.line)&&(a.add(h.line),u.push(h));if(a.has(l)||(a.add(l),u.push({line:l,text:f})),T=l,u.length>=n){d=!0;break}}else if(o>0&&(p.push({line:l,text:f}),p.length>o&&p.shift()),T>=e&&l-T<=s&&!a.has(l)&&(a.add(l),u.push({line:l,text:f}),u.length>=n)){d=!0;break}}}m.close(),await y.close()}catch{return{rows:[],hasMore:!1,nextStartLine:null}}return d?{rows:u,hasMore:d,nextStartLine:c}:{rows:u,hasMore:d,nextStartLine:null}}async awaitCompletion(t,i,e){return Promise.all(i.map(n=>this.awaitOne(t,n,e)))}async awaitOne(t,i,e){const n=this.getTask(t,i);if(n)return n.status!=="running"?this.taskToAwaitResult(n):new Promise(r=>{let u=null;const a=c=>{u&&clearTimeout(u),r(c)};n.completionWaiters.push(a),e&&e>0&&(u=setTimeout(()=>{n.completionWaiters=n.completionWaiters.filter(c=>c!==a),r({taskId:i,status:"running",exitCode:null,signal:null,timedOut:!0,aborted:!1,durationMs:Date.now()-n.startedAt})},e),u.unref?.())});const s=(await this.store.readSession(t))?.tasks.find(r=>r.taskId===i);return s?s.status!=="running"?{taskId:i,status:s.status,exitCode:s.exitCode,signal:s.signal,timedOut:s.killedReason==="timeout",aborted:!1,durationMs:(s.finishedAt??Date.now())-s.startedAt,...s.outputPath?{outputFilePath:s.outputPath}:{}}:{taskId:i,status:"killed",exitCode:null,signal:null,timedOut:!1,aborted:!1,durationMs:(s.finishedAt??Date.now())-s.startedAt}:null}taskToAwaitResult(t){return{taskId:t.taskId,status:t.status,exitCode:t.exitCode,signal:t.signal,timedOut:t.killedReason==="timeout",aborted:!1,durationMs:(t.finishedAt??Date.now())-t.startedAt,...t.status!=="running"&&t.outputPath?{outputFilePath:t.outputPath}:{}}}interruptAwaits(t,i){const e=this.tasksByAgent.get(t);if(e)for(const n of i){const o=e.get(n);if(!o)continue;const s=o.completionWaiters;if(s.length===0)continue;o.completionWaiters=[];const r={taskId:n,status:"running",exitCode:null,signal:null,timedOut:!1,aborted:!0,durationMs:Date.now()-o.startedAt};for(const u of s)u(r)}}async killTask(t,i){const e=this.getTask(t,i);return e?e.status!=="running"?{taskId:i,status:e.status,exitCode:e.exitCode??void 0}:e.child?(e.killedReason="user_kill",this.killProcessGroup(e.child)?(e.killEscalationTimer&&clearTimeout(e.killEscalationTimer),e.killEscalationTimer=setTimeout(()=>{e.child&&!e.finalized&&this.killProcessGroup(e.child,!0)},z),e.killEscalationTimer.unref?.(),{taskId:i,status:"killed",signal:"SIGTERM"}):{taskId:i,status:e.status,error:"kill_failed",reason:"permission_denied"}):{taskId:i,status:e.status,error:"kill_failed",reason:"no_child"}:{taskId:i,status:"killed",error:"task_not_found"}}killProcessGroup(t,i=!1){const e=t.pid;if(!e)return!1;try{if(process.platform==="win32"){const n="/F",{spawnSync:o}=require("node:child_process");return o("taskkill",["/PID",String(e),"/T",n],{windowsHide:!0}),!0}try{process.kill(-e,i?"SIGKILL":"SIGTERM")}catch{process.kill(e,i?"SIGKILL":"SIGTERM")}return!0}catch{return!1}}async disposeAgent(t){const i=this.tasksByAgent.get(t);if(i){for(const e of i.values())e.status==="running"&&e.child&&(e.killedReason="session_disposed",this.killProcessGroup(e.child,!0)),e.timeoutTimer&&clearTimeout(e.timeoutTimer),e.killEscalationTimer&&clearTimeout(e.killEscalationTimer),e.retentionTimer&&clearTimeout(e.retentionTimer);this.tasksByAgent.delete(t)}await this.store.deleteAgent(t)}async disposeAll(){for(const[t,i]of this.tasksByAgent){for(const e of i.values())e.status==="running"&&e.child&&(e.killedReason="process_exit",this.killProcessGroup(e.child,!0)),e.timeoutTimer&&clearTimeout(e.timeoutTimer),e.killEscalationTimer&&clearTimeout(e.killEscalationTimer),e.retentionTimer&&clearTimeout(e.retentionTimer);this.tasksByAgent.delete(t)}}async reconcileOrphans(t){const i=await this.store.readSession(t);if(!i||i.tasks.length===0)return;let e=!1;for(const n of i.tasks)n.status==="running"&&(n.status="killed",n.killedReason="runtime_crashed",n.finishedAt=Date.now(),n.notified=!0,e=!0);e&&await this.store.persistSession(t,i.tasks)}async readSessionState(t){return this.store.readSession(t)}async markNotified(t,i){await this.store.markNotified(t,i)}getOrCreateBucket(t){let i=this.tasksByAgent.get(t);return i||(i=new Map,this.tasksByAgent.set(t,i)),i}getTask(t,i){const e=this.tasksByAgent.get(t);if(e&&/^[A-Za-z0-9]{8}$/.test(i))return e.get(i)}generateTaskId(t){for(let i=0;i<3;i++){const e=S(4).toString("hex").slice(0,8);if(!t.has(e))return e}return S(6).toString("hex").slice(0,8)}async persistTask(t){const i=await this.store.readSession(t.agentId)??{agentId:t.agentId,updatedAt:0,tasks:[]},e={taskId:t.taskId,agentId:t.agentId,command:t.command,commandPreview:t.commandPreview,cwd:t.cwd,status:t.status,startedAt:t.startedAt,finishedAt:t.finishedAt,exitCode:t.exitCode,signal:t.signal,outputPath:t.outputPath,outputLineCount:t.outputLineCount,outputBytes:t.outputBytes,notified:t.notified,killedReason:t.killedReason},n=i.tasks.findIndex(s=>s.taskId===t.taskId);n>=0?i.tasks[n]=e:i.tasks.push(e);const o=Date.now();i.tasks=i.tasks.filter(s=>s.status==="running"||!s.finishedAt||o-s.finishedAt<_),await this.store.persistSession(t.agentId,i.tasks)}}class x extends Error{constructor(t,i){super(i),this.name="BackgroundTaskError",this.code=t}}const J=new q;export{q as BackgroundCommandManager,x as BackgroundTaskError,J as backgroundCommandManager};
|
|
6
|
+
`)}),t.outputWriteChain)}finalizeTask(t,i,e,n){if(t.finalized)return;t.finalized=!0,t.timeoutTimer&&(clearTimeout(t.timeoutTimer),t.timeoutTimer=null),t.killEscalationTimer&&(clearTimeout(t.killEscalationTimer),t.killEscalationTimer=null),t.inactivityTimer&&(clearTimeout(t.inactivityTimer),t.inactivityTimer=null),t.child=null,t.finishedAt=Date.now();let o;n?(o="killed",t.killedReason=n):i===0?o="completed":o="failed",t.status=o,t.exitCode=i,t.signal=e;const s=n==="inactivity"||t.inactivityTimedOut,r={taskId:t.taskId,exitCode:i,signal:e,timedOut:n==="timeout"||s,inactivityTimedOut:s,outputFilePath:t.outputPath,outputLineCount:t.outputLineCount,outputSpilled:t.outputTruncated,commandFilePath:t.commandFilePath,commandLineCount:t.commandLineCount,timeoutMs:t.timeoutMs,inactivityTimeoutMs:t.inactivityTimeoutMs,stdout:t.stdoutText,stderr:t.stderrText,durationMs:t.finishedAt-t.startedAt};t.completionResolve?.(r);const u={taskId:t.taskId,status:o,exitCode:i,signal:e,timedOut:n==="timeout"||s,aborted:!1,durationMs:t.finishedAt-t.startedAt},a=t.completionWaiters;t.completionWaiters=[];for(const c of a)c(u);if(this.persistTask(t),t.onCompleted?.({taskId:t.taskId,agentId:t.agentId,status:o,exitCode:i,signal:e,commandPreview:t.commandPreview,outputLineCount:t.outputLineCount,outputBytes:t.outputBytes,outputPath:t.outputPath,finishedAt:t.finishedAt,killedReason:t.killedReason}),t.outputSubscribers.size>0){const c=Array.from(t.outputSubscribers);t.outputSubscribers.clear();for(const d of c)try{d.onDone({status:o,exitCode:i,signal:e})}catch{}}t.retentionTimer=setTimeout(()=>{this.evictTask(t.agentId,t.taskId)},v),t.retentionTimer.unref?.()}evictTask(t,i){const e=this.tasksByAgent.get(t);if(!e)return;const n=e.get(i);n&&(A.unlink(n.outputPath).catch(()=>{}),e.delete(i),e.size===0&&this.tasksByAgent.delete(t))}listTasks(t,i){const e=this.tasksByAgent.get(t);if(!e)return[];const n=[];for(const o of e.values())i&&i!=="all"&&o.status!==i||n.push(this.toSummary(o));return n.sort((o,s)=>s.startedAt-o.startedAt)}toSummary(t){return{taskId:t.taskId,status:t.status,command:t.command,commandPreview:t.commandPreview,cwd:t.cwd,startedAt:t.startedAt,finishedAt:t.finishedAt,exitCode:t.exitCode,signal:t.signal,outputLineCount:t.outputLineCount,outputBytes:t.outputBytes}}getTaskOutputSnapshot(t,i,e=500){const n=this.getTask(t,i);if(!n)return null;const o=n.ringBuffer.tail(e);return{taskId:n.taskId,status:n.status,exitCode:n.exitCode,signal:n.signal,startedAt:n.startedAt,finishedAt:n.finishedAt,command:n.command,lines:o,nextSeq:n.outputSeq+1,totalLines:n.outputLineCount,totalBytes:n.outputBytes,truncated:n.outputTruncated}}subscribeTaskOutput(t,i,e){const n=this.getTask(t,i);if(!n)return null;n.outputSubscribers.add(e);let o=!0;return()=>{o&&(o=!1,n.outputSubscribers.delete(e))}}async readOutput(t,i){const e=String(i.task_id??""),n=this.getTask(t,e),o=i.mode==="lines"||i.mode==="grep"?i.mode:"tail",s=Math.min(Math.max(1,i.line_size??100),X),r=Number.isFinite(i.start_line)&&(i.start_line??0)>0?Math.floor(i.start_line??0):0;if(!n)return{taskId:e,status:"killed",mode:o,lines:[],lineCount:0,metadata:{totalLines:0,totalBytes:0,returnedBytes:0,truncated:!1,outputTruncated:!1,hasMore:!1,nextStartLine:null,outputFile:""}};let u=[],a=!1,c=null;if(o==="tail"){const m=n.ringBuffer.tail(s),f=Math.max(0,n.outputLineCount-m.length);u=m.map((l,g)=>({line:f+g,text:l})),c=null}else if(o==="lines"){const m=n.ringBuffer.firstLineIndex(),f=m+n.ringBuffer.getLineCount();if(r>=m&&r<f)u=n.ringBuffer.offset(r,s).map((g,h)=>({line:r+h,text:g})),a=r+u.length<f,c=a?r+u.length:null;else if(r<f){const l=await this.readFromFile(n,"lines",r,s,0,0,void 0);u=l.rows,a=l.hasMore,c=l.nextStartLine}}else{const m=String(i.pattern??"");if(!m||m.length>q)return this._emptyResult(e,n,o);let f;try{f=new RegExp(m,"i")}catch{return this._emptyResult(e,n,o)}const l=Math.min(Math.max(0,i.context_before??0),b),g=Math.min(Math.max(0,i.context_after??0),b),h=await this.readFromFile(n,"grep",r,s,l,g,f);u=h.rows,a=h.hasMore,c=h.nextStartLine}const d=[];let p=0,T=!1;for(const m of u){const f=Buffer.byteLength(m.text,"utf-8")+1;if(d.length>=s||p+f>W){T=!0,a=!0;break}d.push(m),p+=f}const y=i.include_metadata!==!1;return{taskId:e,status:n.status,mode:o,lines:d,lineCount:d.length,metadata:y?{totalLines:n.outputLineCount,totalBytes:n.outputBytes,returnedBytes:p,truncated:T,outputTruncated:n.outputTruncated,hasMore:a,nextStartLine:a?c:null,outputFile:n.outputPath}:void 0}}_emptyResult(t,i,e){return{taskId:t,status:i.status,mode:e,lines:[],lineCount:0,metadata:{totalLines:i.outputLineCount,totalBytes:i.outputBytes,returnedBytes:0,truncated:!1,outputTruncated:i.outputTruncated,hasMore:!1,nextStartLine:null,outputFile:i.outputPath}}}async readFromFile(t,i,e,n,o,s,r){const u=[],a=new Set;let c=0,d=!1;const p=[];let T=-1/0;try{const y=await A.open(t.outputPath,"r"),m=I({input:y.createReadStream({encoding:"utf-8"}),crlfDelay:1/0});for await(const f of m){const l=c;if(c++,i==="grep"&&l-e>=$&&l>=e){d=!0;break}if(l>=e){if(i==="lines"){if(u.length>=n){d=!0;break}a.has(l)||(a.add(l),u.push({line:l,text:f}))}else if(r.test(f)){for(const h of p)h.line>=e&&!a.has(h.line)&&(a.add(h.line),u.push(h));if(a.has(l)||(a.add(l),u.push({line:l,text:f})),T=l,u.length>=n){d=!0;break}}else if(o>0&&(p.push({line:l,text:f}),p.length>o&&p.shift()),T>=e&&l-T<=s&&!a.has(l)&&(a.add(l),u.push({line:l,text:f}),u.length>=n)){d=!0;break}}}m.close(),await y.close()}catch{return{rows:[],hasMore:!1,nextStartLine:null}}return d?{rows:u,hasMore:d,nextStartLine:c}:{rows:u,hasMore:d,nextStartLine:null}}async awaitCompletion(t,i,e){return Promise.all(i.map(n=>this.awaitOne(t,n,e)))}async awaitOne(t,i,e){const n=this.getTask(t,i);if(n)return n.status!=="running"?this.taskToAwaitResult(n):new Promise(r=>{let u=null;const a=c=>{u&&clearTimeout(u),r(c)};n.completionWaiters.push(a),e&&e>0&&(u=setTimeout(()=>{n.completionWaiters=n.completionWaiters.filter(c=>c!==a),r({taskId:i,status:"running",exitCode:null,signal:null,timedOut:!0,aborted:!1,durationMs:Date.now()-n.startedAt})},e),u.unref?.())});const s=(await this.store.readSession(t))?.tasks.find(r=>r.taskId===i);return s?s.status!=="running"?{taskId:i,status:s.status,exitCode:s.exitCode,signal:s.signal,timedOut:s.killedReason==="timeout",aborted:!1,durationMs:(s.finishedAt??Date.now())-s.startedAt,...s.outputPath?{outputFilePath:s.outputPath}:{}}:{taskId:i,status:"killed",exitCode:null,signal:null,timedOut:!1,aborted:!1,durationMs:(s.finishedAt??Date.now())-s.startedAt}:null}taskToAwaitResult(t){return{taskId:t.taskId,status:t.status,exitCode:t.exitCode,signal:t.signal,timedOut:t.killedReason==="timeout",aborted:!1,durationMs:(t.finishedAt??Date.now())-t.startedAt,...t.status!=="running"&&t.outputPath?{outputFilePath:t.outputPath}:{}}}interruptAwaits(t,i){const e=this.tasksByAgent.get(t);if(e)for(const n of i){const o=e.get(n);if(!o)continue;const s=o.completionWaiters;if(s.length===0)continue;o.completionWaiters=[];const r={taskId:n,status:"running",exitCode:null,signal:null,timedOut:!1,aborted:!0,durationMs:Date.now()-o.startedAt};for(const u of s)u(r)}}async killTask(t,i){const e=this.getTask(t,i);return e?e.status!=="running"?{taskId:i,status:e.status,exitCode:e.exitCode??void 0}:e.child?(e.killedReason="user_kill",this.killProcessGroup(e.child)?(e.killEscalationTimer&&clearTimeout(e.killEscalationTimer),e.killEscalationTimer=setTimeout(()=>{e.child&&!e.finalized&&this.killProcessGroup(e.child,!0)},z),e.killEscalationTimer.unref?.(),{taskId:i,status:"killed",signal:"SIGTERM"}):{taskId:i,status:e.status,error:"kill_failed",reason:"permission_denied"}):{taskId:i,status:e.status,error:"kill_failed",reason:"no_child"}:{taskId:i,status:"killed",error:"task_not_found"}}killProcessGroup(t,i=!1){const e=t.pid;if(!e)return!1;try{if(process.platform==="win32"){const n="/F",{spawnSync:o}=require("node:child_process");return o("taskkill",["/PID",String(e),"/T",n],{windowsHide:!0}),!0}try{process.kill(-e,i?"SIGKILL":"SIGTERM")}catch{process.kill(e,i?"SIGKILL":"SIGTERM")}return!0}catch{return!1}}async disposeAgent(t){const i=this.tasksByAgent.get(t);if(i){for(const e of i.values())e.status==="running"&&e.child&&(e.killedReason="session_disposed",this.killProcessGroup(e.child,!0)),e.timeoutTimer&&clearTimeout(e.timeoutTimer),e.killEscalationTimer&&clearTimeout(e.killEscalationTimer),e.retentionTimer&&clearTimeout(e.retentionTimer);this.tasksByAgent.delete(t)}await this.store.deleteAgent(t)}async disposeAll(){for(const[t,i]of this.tasksByAgent){for(const e of i.values())e.status==="running"&&e.child&&(e.killedReason="process_exit",this.killProcessGroup(e.child,!0)),e.timeoutTimer&&clearTimeout(e.timeoutTimer),e.killEscalationTimer&&clearTimeout(e.killEscalationTimer),e.retentionTimer&&clearTimeout(e.retentionTimer);this.tasksByAgent.delete(t)}}async reconcileOrphans(t){const i=await this.store.readSession(t);if(!i||i.tasks.length===0)return;let e=!1;for(const n of i.tasks)n.status==="running"&&(n.status="killed",n.killedReason="runtime_crashed",n.finishedAt=Date.now(),n.notified=!0,e=!0);e&&await this.store.persistSession(t,i.tasks)}async readSessionState(t){return this.store.readSession(t)}async markNotified(t,i){await this.store.markNotified(t,i)}getOrCreateBucket(t){let i=this.tasksByAgent.get(t);return i||(i=new Map,this.tasksByAgent.set(t,i)),i}getTask(t,i){const e=this.tasksByAgent.get(t);if(e&&/^[A-Za-z0-9]{8}$/.test(i))return e.get(i)}generateTaskId(t){for(let i=0;i<3;i++){const e=S(4).toString("hex").slice(0,8);if(!t.has(e))return e}return S(6).toString("hex").slice(0,8)}async persistTask(t){const i=await this.store.readSession(t.agentId)??{agentId:t.agentId,updatedAt:0,tasks:[]},e={taskId:t.taskId,agentId:t.agentId,command:t.command,commandPreview:t.commandPreview,cwd:t.cwd,status:t.status,startedAt:t.startedAt,finishedAt:t.finishedAt,exitCode:t.exitCode,signal:t.signal,outputPath:t.outputPath,outputLineCount:t.outputLineCount,outputBytes:t.outputBytes,notified:t.notified,killedReason:t.killedReason},n=i.tasks.findIndex(s=>s.taskId===t.taskId);n>=0?i.tasks[n]=e:i.tasks.push(e);const o=Date.now();i.tasks=i.tasks.filter(s=>s.status==="running"||!s.finishedAt||o-s.finishedAt<v),await this.store.persistSession(t.agentId,i.tasks)}}class x extends Error{constructor(t,i){super(i),this.name="BackgroundTaskError",this.code=t}}const Q=new k;export{k as BackgroundCommandManager,x as BackgroundTaskError,Q as backgroundCommandManager};
|
|
7
7
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{randomUUID as
|
|
1
|
+
import{randomUUID as nt}from"node:crypto";import{promises as w,createReadStream as X}from"node:fs";import it from"node:os";import d from"node:path";import Y from"node:readline";import{runShellCommand as at}from"./builtins/shellCommandRunner.js";import{createOutputEventCollector as rt}from"./builtins/commandOutputEvents.js";import{buildCommandOutputSpilloverContent as st,COMMAND_OUTPUT_SPILLOVER_LINE_LIMIT as ct,countOutputLines as H,formatCommandOutputSpilloverStdout as lt,writeCommandArtifactFile as ut}from"./builtins/commandArtifacts.js";import{symbolsTool as dt}from"./built-in-symbols-tool.js";import{createListBackgroundCommandsTool as mt,createKillBackgroundCommandTool as ht,createReadBackgroundOutputTool as ft}from"./background-command-tools.js";import{detectImageFormatFromBuffer as pt,formatBytes as x,imageMediaType as K,readImageDimensions as wt,tryResizeWithSharp as gt}from"./image-utils.js";const _t=2e3,O=2e3,yt=50*1024,V=4096,bt=.3,kt=new Set([".png",".jpg",".jpeg",".gif",".bmp",".ico",".webp",".tiff",".tif",".zip",".gz",".tar",".rar",".7z",".bz2",".xz",".lz",".exe",".dll",".so",".dylib",".bin",".o",".a",".pdf",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".mp3",".mp4",".avi",".mov",".wav",".flv",".mkv",".ogg",".woff",".woff2",".ttf",".otf",".eot",".class",".jar",".war",".ear",".pyc",".pyo",".node",".sqlite",".db",".mdb",".wasm"]),Tt=new Set(["png","jpg","jpeg","gif","webp"]),Z=20*1024*1024,L=10*1024*1024,D=Math.floor(3.75*1024*1024),C=2e3,Et=15e3,Pt=1e3,vt=1024*1024,xt=256*1024,$t=1e3,Rt=new Set([".git","node_modules","dist","build",".next",".nuxt",".cache",".turbo",".output","coverage",".nyc_output"]),se={fileReadOutside:"allow",commandExecution:"allow",fileModification:"allow"};async function F(n,o,e){if(!n)return;const t=n.getLevel(o);if(t==="deny")throw new Error(`Operation blocked by tool permission policy (${o} = deny). Explain this restriction to the user if needed.`);if(t==="ask"&&!await n.requestPermission(o,e))throw new Error(`Operation denied by the user (${o}). Do not retry the same operation without asking the user.`)}function $(n){return n.replace(/\\/g,"/")}async function J(n){try{return await w.access(n),!0}catch{return!1}}function St(n,o){if(!o)return 0;let e=0,t=n.indexOf(o);for(;t>=0;)e+=1,t=n.indexOf(o,t+o.length);return e}function R(n,o,e){for(const t of o){const i=n[t];if(typeof i=="string")return i}throw new Error(`${e} is required`)}function I(n,o){for(const e of o){const t=n[e];if(typeof t=="string"&&t.trim())return t}}function U(n,o,e){for(const t of o){const i=n[t],a=typeof i=="number"?i:typeof i=="string"?Number(i):NaN;if(Number.isFinite(a)&&a>0)return Math.floor(a)}return e}function It(n,o,e){for(const t of o){const i=n[t],a=typeof i=="number"?i:typeof i=="string"?Number(i):NaN;if(Number.isFinite(a)&&a>0)return Math.floor(a);if(Number.isFinite(a)&&a===0)return 0}return e}async function Q(n){const o=d.extname(n).toLowerCase();if(kt.has(o))return!0;const e=await w.open(n,"r");try{const t=Buffer.alloc(V),{bytesRead:i}=await e.read(t,0,V,0);if(i===0)return!1;const a=t.subarray(0,i);if(a.includes(0))return!0;let r=0;for(let s=0;s<i;s++){const c=a[s];(c<9||c>13&&c<32)&&r++}return r/i>bt}finally{await e.close()}}function M(n,o){const e=d.resolve(o),t=d.relative(n,e);if(t.startsWith("..")||d.isAbsolute(t))throw new Error(`Target path is outside workspace: ${e}`);return e}function W(n){return n==="~"||n.startsWith("~/")?d.join(it.homedir(),n.slice(1)):n}async function Mt(n,o){const e=d.resolve(String(n||"").trim()),t=await w.realpath(e);if(!(await w.stat(t)).isDirectory())throw new Error(`Workspace path is not a directory: ${e}`);if(!o?.trim())return{workspaceRoot:t,cwd:t};const a=W(o.trim()),r=d.isAbsolute(a)?d.resolve(a):d.resolve(e,a),s=d.relative(e,r);if(s.startsWith("..")||d.isAbsolute(s))throw new Error(`Command cwd is outside workspace: ${r}`);const c=M(t,await w.realpath(r));if(!(await w.stat(c)).isDirectory())throw new Error(`Command cwd is not a directory: ${c}`);return{workspaceRoot:t,cwd:c}}async function Ot(n,o){const e=await w.realpath(d.dirname(o));M(n,e);try{if((await w.lstat(o)).isSymbolicLink())throw new Error(`Refusing to write through symbolic link: ${o}`)}catch(t){if((typeof t=="object"&&t!==null?Reflect.get(t,"code"):void 0)!=="ENOENT")throw t}}async function A(n,o){const e=d.resolve(String(n||"").trim()),t=await w.realpath(e);if(!(await w.stat(t)).isDirectory())throw new Error(`Workspace path is not a directory: ${e}`);const a=W(o.trim());if(!a)throw new Error("file_path is required");const r=d.isAbsolute(a)?d.resolve(a):d.resolve(e,a),s=d.relative(e,r);if(s.startsWith("..")||d.isAbsolute(s))throw new Error(`Target path is outside workspace: ${r}`);return{workspaceRoot:t,requestedPath:r,targetPath:M(t,d.join(t,s))}}async function tt(n,o,e){const t=d.resolve(String(n||"").trim()),i=await w.realpath(t);if(!(await w.stat(i)).isDirectory())throw new Error(`Workspace path is not a directory: ${t}`);const r=W(o.trim());if(!r)throw new Error("file_path is required");const s=d.isAbsolute(r)?d.resolve(r):d.resolve(t,r),c=d.relative(t,s),u=await w.realpath(s).catch(()=>s),l=d.relative(i,u);if(c.startsWith("..")||d.isAbsolute(c)||l.startsWith("..")||d.isAbsolute(l)){if(!e)throw new Error(`Target path is outside workspace: ${s}`);return await F(e,"fileReadOutside",{path:s}),{workspaceRoot:i,requestedPath:s,targetPath:u}}return{workspaceRoot:i,requestedPath:s,targetPath:M(i,u)}}async function et(n,o,e){const t=await A(n,o),i=d.dirname(t.targetPath),a=!await J(i);await w.mkdir(i,{recursive:!0}),await Ot(t.workspaceRoot,t.targetPath);const r=d.join(i,`.${d.basename(t.targetPath)}.${process.pid}.${nt()}.tmp`);try{await w.writeFile(r,e,"utf-8"),await w.rename(r,t.targetPath)}catch(s){throw await w.rm(r,{force:!0}),s}return{workspaceRoot:t.workspaceRoot,targetPath:t.targetPath,bytes:Buffer.byteLength(e,"utf-8"),createdParentDirectory:a}}async function Lt(n,o){const e=await A(n,o),t=M(e.workspaceRoot,await w.realpath(e.targetPath));if(!(await w.stat(t)).isFile())throw new Error(`Path is not a file: ${t}`);return{workspaceRoot:e.workspaceRoot,targetPath:t,content:await w.readFile(t,"utf-8")}}async function At(n,o,e,t,i){const a=await tt(n,o,i),r=a.targetPath;if(!(await w.stat(r)).isFile())throw new Error(`Path is not a file: ${r}`);if(await Q(r))return{workspaceRoot:a.workspaceRoot,targetPath:r,content:"[Binary file, content skipped]",isBinary:!0,truncated:!1,totalLines:0,shownFromLine:0,shownToLine:0};const c=X(r,{encoding:"utf-8"}),u=Y.createInterface({input:c,crlfDelay:1/0});try{const l=[];let g=0,h=0,y=0,m=!1,E=!1;const f=e-1;for await(const S of u){if(h++,g<f){g++;continue}if(l.length>=t){m=!0,g++;continue}let P=S;P.length>O&&(P=P.slice(0,O)+`... (line truncated to ${O} chars)`);const v=`${g+1}: ${P}`,T=Buffer.byteLength(v,"utf-8")+1;if(y+T>yt){E=!0;break}l.push(v),y+=T,g++}if(h>0&&l.length===0&&!m&&!E&&f>=h)throw new Error(`offset ${e} exceeds total line count ${h} in file: ${r}`);const k=l.length>0?e:0,b=l.length>0?e+l.length-1:0;let _;E?_=`Output capped at 50 KB. Showing lines ${k}-${b}. Use offset=${b+1} to continue.`:m?_=`Showing lines ${k}-${b} of ${h}. Use offset=${b+1} to continue.`:_=`End of file - total ${h} lines`;const p=l.length>0?l.join(`
|
|
2
2
|
`)+`
|
|
3
|
-
`+k:k;return{workspaceRoot:s.workspaceRoot,targetPath:a,content:P,isBinary:!1,truncated:d||E,totalLines:E?-1:h,shownFromLine:b,shownToLine:y}}finally{u.close(),c.destroy()}}function q(n){return/^https?:\/\//i.test(n)}async function Ft(n){let o;try{o=new URL(n)}catch{throw new Error(`Invalid image URL: ${n}`)}if(o.protocol!=="http:"&&o.protocol!=="https:")throw new Error(`Unsupported image URL protocol: ${o.protocol} (only http/https)`);let e;try{e=await fetch(n,{signal:AbortSignal.timeout(Et)})}catch(u){const l=u instanceof Error?u.message:String(u);throw new Error(`Image URL fetch failed: ${n} (${l})`)}if(!e.ok)throw new Error(`Image URL fetch failed: ${n} (HTTP ${e.status})`);const t=(e.headers.get("content-type")||"").split(";")[0]?.trim().toLowerCase()||"";if(t&&!t.startsWith("image/"))throw new Error(`URL did not return an image (content-type: ${t}): ${n}`);const i=Number(e.headers.get("content-length")||"");if(Number.isFinite(i)&&i>A)throw new Error(`Image too large to fetch: ${n} (${x(i)} > ${x(A)})`);const s=e.body;if(!s){const u=await e.arrayBuffer();if(u.byteLength>A)throw new Error(`Image too large to fetch: ${n} (${x(u.byteLength)} > ${x(A)})`);return Buffer.from(u)}const a=s.getReader(),r=[];let c=0;for(;;){const{done:u,value:l}=await a.read();if(u)break;if(l){if(c+=l.byteLength,c>A)throw a.cancel().catch(()=>{}),new Error(`Image too large to fetch: ${n} (${x(c)} > ${x(A)})`);r.push(Buffer.from(l))}}return Buffer.concat(r,c)}async function Bt(n,o,e){let t,i;if(q(o))t=await Ft(o),i=o;else{const y=(await tt(n,o,e)).targetPath,k=await w.stat(y);if(!k.isFile())throw new Error(`Path is not a file: ${y}`);if(k.size>Z)throw new Error(`Image file too large to read: ${$(y)} (${x(k.size)} > ${x(Z)}). Downscale it first.`);t=await w.readFile(y),i=$(y)}if(t.length===0)throw new Error(`Image file is empty: ${i}`);const s=wt(t);if(!s)throw new Error(`Unsupported or corrupt image (unrecognized format): ${i}`);const a=gt(t);let r=s,c=t,u=a?.width,l=a?.height,g=!1;const h=await _t(t,s,{maxWidth:U,maxHeight:U,maxBytes:D});if(h)c=h.buffer,r=h.mediaType,u=h.width,l=h.height,g=h.changed;else if(t.length>D)throw new Error(`Image too large to inline: ${i} (${x(t.length)} > ${x(D)}). Downscale it first, e.g. via Bash: magick "${o}" -resize ${U}x${U} "${o}". Installing sharp enables automatic downscaling.`);const _=u&&l?`${u}x${l}`:"unknown dimensions",d=g&&a&&a.width!==u?` (resized from ${a.width}x${a.height})`:g?" (resized)":"",E=`[Image: ${i}, ${_}${d}, ${x(c.length)}]`,f=q(o)?m.basename(new URL(o).pathname)||"image":m.basename(i);return{ok:!0,filePath:i,content:E,isBinary:!1,image:{mediaType:K(r),width:u??null,height:l??null,originalWidth:a?.width??null,originalHeight:a?.height??null,resized:g,size:c.length},attachments:[{type:"image",name:f,mediaType:K(r),base64Data:c.toString("base64")}]}}function ot(n){let o="",e=0;for(;e<n.length;){const t=n[e];if(t==="*")o+="[^/]*";else if(t==="?")o+="[^/]";else if(t==="{"){const i=n.indexOf("}",e);if(i>=0){const s=n.slice(e+1,i);o+=`(${s.split(",").join("|")})`,e=i}else o+="\\{"}else if(t==="["){const i=n.indexOf("]",e);i>=0?(o+=n.slice(e,i+1),e=i):o+="\\["}else"+^$.()|\\".includes(t)?o+="\\"+t:o+=t;e++}return new RegExp(`^${o}$`)}async function Ct(n,o,e,t){const i=[];async function s(a){if(i.length>=t)return;const r=await w.readdir(a,{withFileTypes:!0});for(const c of r){if(i.length>=t)return;if(c.name.startsWith(".")&&c.isDirectory())continue;const u=m.join(a,c.name);if(c.isDirectory()){if(St.has(c.name))continue;await s(u)}else if(c.isFile()){if(o&&!o.test(c.name)||e&&e.test(c.name))continue;i.push(u)}}}return await s(n),i}async function Nt(n,o,e){if((await w.stat(n)).size>xt)return{matches:[],count:0};if(await Q(n))return{matches:[],count:0};const i=m.relative(o,n).replace(/\\/g,"/"),s=[];let a=0;const r=X(n,{encoding:"utf-8"}),c=Y.createInterface({input:r,crlfDelay:1/0});try{let u=0;for await(const l of c)if(u++,e.regex.test(l)){if(a++,e.collectContent){let g=l;if(g.length>L&&(g=g.slice(0,L)+`... (line truncated to ${L} chars)`),s.push({file:i,line:u,content:g}),s.length>=e.maxResults)break}if(e.stopOnFirstMatch)break}}finally{c.close(),r.destroy()}return{matches:s,count:a}}const nt=10*6e4,Ut=nt,Dt=6e4,Wt=10*6e4;function qt(n,o,e){return{kind:"builtin",toolName:"write_file",exposedName:"write_file",description:"Create or overwrite a UTF-8 text file inside the current workspace. Parent directories are created automatically.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Workspace-relative file path to write."},content:{type:"string",description:"Complete UTF-8 file content."},reason:{type:"string",description:"Optional reason for this change, e.g. what bug is being fixed. Helps humans understand the change later."}},required:["file_path","content"],additionalProperties:!1},async execute(t){const i=S(t,["file_path","filePath"],"file_path"),s=S(t,["content"],"content"),a=I(t,["reason"]),r=await F(n,i);await B(e,"fileModification",{operation:"write",path:r.targetPath});const c=await J(r.targetPath),u=c?await w.readFile(r.targetPath,"utf-8").catch(()=>null):null,l=await et(n,i,s);if(o){const g=m.relative(l.workspaceRoot,l.targetPath).replace(/\\/g,"/");await o({filePath:g,operation:c?"UPDATE":"CREATE",beforeContent:u,afterContent:s,reason:a})}return{ok:!0,filePath:$(l.targetPath),bytes:l.bytes,createdParentDirectory:l.createdParentDirectory}}}}function jt(n,o,e){return{kind:"builtin",toolName:"edit_file",exposedName:"edit_file",description:"Replace exactly one occurrence of old_string with new_string in a UTF-8 workspace text file.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Workspace-relative file path to edit."},old_string:{type:"string",description:"Existing text to replace. Must occur exactly once."},new_string:{type:"string",description:"Replacement text."},reason:{type:"string",description:"Optional reason for this change, e.g. what bug is being fixed. Helps humans understand the change later."}},required:["file_path","old_string","new_string"],additionalProperties:!1},async execute(t){const i=S(t,["file_path","filePath"],"file_path"),s=S(t,["old_string","oldString"],"old_string"),a=S(t,["new_string","newString"],"new_string"),r=I(t,["reason"]);if(!s)throw new Error("old_string must not be empty");const c=await F(n,i);await B(e,"fileModification",{operation:"edit",path:c.targetPath});const u=await Lt(n,i),l=Mt(u.content,s);if(l===0)throw new Error("old_string was not found in file");if(l>1)throw new Error(`old_string occurs ${l} times; provide a unique match`);const g=u.content.replace(s,a),h=await et(n,i,g);if(o){const _=m.relative(h.workspaceRoot,h.targetPath).replace(/\\/g,"/");await o({filePath:_,operation:"UPDATE",beforeContent:u.content,afterContent:g,reason:r})}return{ok:!0,filePath:$(h.targetPath),bytes:h.bytes}}}}function zt(n,o,e){return{kind:"builtin",toolName:"delete_file",exposedName:"delete_file",description:"Delete a file inside the current workspace. Returns an error if the file does not exist.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Workspace-relative file path to delete."},reason:{type:"string",description:"Optional reason for this change, e.g. what bug is being fixed. Helps humans understand the change later."}},required:["file_path"],additionalProperties:!1},async execute(t){const i=S(t,["file_path","filePath"],"file_path"),s=I(t,["reason"]),a=await F(n,i);await B(e,"fileModification",{operation:"delete",path:a.targetPath});const r=O(a.workspaceRoot,await w.realpath(a.targetPath).catch(()=>a.targetPath)),c=await w.stat(r).catch(()=>null);if(!c)throw new Error(`File does not exist: ${r}`);if(!c.isFile())throw new Error(`Path is not a file: ${r}`);const u=await w.readFile(r,"utf-8").catch(()=>null);if(await w.rm(r,{force:!0}),o){const l=m.relative(a.workspaceRoot,r).replace(/\\/g,"/");await o({filePath:l,operation:"DELETE",beforeContent:u,afterContent:null,reason:s})}return{ok:!0,filePath:$(r),deleted:!0}}}}function Gt(n,o){return{kind:"builtin",toolName:"read_file",exposedName:"read_file",description:"Read a UTF-8 text file inside the current workspace. Returns content with line numbers in the format '<line>: <content>'. Supports offset (1-indexed line number to start from) and limit (max lines to return, default 2000). Output is capped at 2000 lines or 50 KB, whichever is reached first. Individual lines longer than 2000 characters are truncated. Avoid tiny repeated slices (e.g. 30-line chunks); read a larger window if more context is needed. Images (.png/.jpg/.jpeg/.gif/.webp) and http(s) image URLs are also supported: the image is inlined into the conversation so you can see it (requires a model with image input). offset/limit are ignored for images; oversized images are automatically downscaled when sharp is available.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Workspace-relative file path to read. Also accepts an http(s) URL pointing to an image."},offset:{type:"number",description:"Line number to start reading from (1-indexed). Defaults to 1."},limit:{type:"number",description:"Maximum number of lines to return. Defaults to 2000."}},required:["file_path"],additionalProperties:!1},async execute(e){const t=S(e,["file_path","filePath"],"file_path"),i=m.extname(t).toLowerCase().slice(1);if(q(t)||Pt.has(i))return await Bt(n,t,o);const s=C(e,["offset"],1),a=C(e,["limit"],yt),r=await At(n,t,s,a,o);return{ok:!0,filePath:$(r.targetPath),content:r.content,isBinary:r.isBinary,truncated:r.truncated,totalLines:r.totalLines,shownFromLine:r.shownFromLine,shownToLine:r.shownToLine}}}}function Xt(n,o,e,t){return{kind:"builtin",toolName:"Bash",exposedName:"Bash",description:"Execute a shell command in the current workspace. Use for local diagnostics, builds, tests, and OS commands. The command runs with a bounded foreground wait and returns stdout, stderr, exit code, and (if converted to background) a task_id. By default (wait_seconds omitted or -1) the command runs in the FOREGROUND and streams output in real time; if the 5-minute adapter watchdog or the command total timeout (timeout_ms) fires while it is still running, the command is moved to the BACKGROUND and the tool returns a task_id plus an explanation (backgrounded=true, reason=watchdog_timeout|tool_timeout). The background command has no total timeout and can be managed via await_complete / list_background_commands / read_background_output / kill_background_command. For immediate backgrounding use wait_seconds=0, or wait_seconds=n>0 to wait n seconds then background.",inputSchema:{type:"object",properties:{command:{type:"string",description:"Shell command to execute."},cwd:{type:"string",description:"Optional workspace-relative working directory. Defaults to the workspace root."},timeout_ms:{type:"number",description:"Optional timeout in milliseconds. Defaults to 600000 and is capped at 600000."},inactivity_timeout_ms:{type:"number",description:"Optional no-output timeout in milliseconds. Defaults to 60000 and is capped at 600000."},wait_seconds:{type:"number",description:"How to wait for the command to finish. Omitted values (or -1, the default): run in the FOREGROUND until completion; if the 5-minute adapter watchdog or timeout_ms fires first, the command is moved to the background and a task_id is returned (backgrounded=true, reason=watchdog_timeout|tool_timeout). 0: spawn and immediately execute in the background, return task_id. n>0: wait up to n seconds; if still running, move to the background and return task_id. Background commands have NO total timeout (run until finished or killed); inactivity_timeout_ms is ignored once backgrounded.",minimum:-1},description:{type:"string",description:"Optional short reason for running the command."}},required:["command"],additionalProperties:!1},async execute(i,s){const a=S(i,["command"],"command").trim();if(!a)throw new Error("command must not be empty");const r=C(i,["timeout_ms","timeoutMs"],Ut),c=Math.min(r,nt),u=C(i,["inactivity_timeout_ms","inactivityTimeoutMs"],Dt),l=Math.min(u,Wt),g=I(i,["cwd"]),h=await It(n,g);await B(t,"commandExecution",{command:a,cwd:$(h.cwd)});const _=i.wait_seconds,E=typeof _=="number"&&Number.isFinite(_)?_:-1;if(e)return await Yt({deps:e,command:a,agentId:o,workspaceRoot:h.workspaceRoot,cwd:h.cwd,timeoutMs:c,inactivityTimeoutMs:l,waitSeconds:E,onOutput:s?.onOutput,settleSignal:s?.settleSignal});const f=await rt({commandText:a,agentId:o,workspaceRoot:h.workspaceRoot,cwd:h.cwd,timeoutMs:c,inactivityTimeoutMs:l,onOutput:s?.onOutput,watchdogSignal:s?.settleSignal}),b={ok:f.exitCode===0&&!f.timedOut,tool:"Bash",command:a,cwd:$(h.cwd),exitCode:f.exitCode,signal:f.signal,timedOut:f.timedOut,inactivityTimedOut:f.inactivityTimedOut,watchdogInterrupted:f.watchdogInterrupted,timeoutMs:c,inactivityTimeoutMs:l,durationMs:f.durationMs,outputSpilled:f.outputSpilled,outputFilePath:f.outputFilePath,outputLineCount:f.outputLineCount,commandFilePath:f.commandFilePath,commandLineCount:f.commandLineCount,stdout:f.stdout,stderr:f.stderr};return f.watchdogInterrupted?{...b,message:"Command was interrupted by the adapter watchdog after ~5 minutes of synchronous (foreground) execution. Only the partial output produced so far is returned above"+(f.outputFilePath?` (full output spilled to "${f.outputFilePath}"; read it if you need more)`:"")+". For long-running commands, re-run with wait_seconds=0 (or n>0) to execute in the background, then manage via await_complete / list_background_commands / read_background_output / kill_background_command."}:b}}}async function Yt(n){const{deps:o,command:e,agentId:t,workspaceRoot:i,cwd:s,timeoutMs:a,inactivityTimeoutMs:r,waitSeconds:c,onOutput:u,settleSignal:l}=n,g=u?st({cwd:s,commandLineCount:0,onOutput:u}):void 0;let h=!!g;const _=()=>{h&&(h=!1,g?.close())};try{const{taskId:d,completion:E}=o.manager.startCommand({commandText:e,agentId:t,workspaceRoot:i,cwd:s,timeoutMs:0,inactivityTimeoutMs:r,onOutput:h?P=>{h&&g?.push(P.stream,P.text)}:void 0,onCompleted:o.emitCompleted});if(c===0)return o.manager.disableInactivityTimeout(t,d),_(),{ok:!0,tool:"Bash",command:e,backgrounded:!0,taskId:d,status:"backgrounded",reason:"immediate",message:`Command moved to background. Use await_complete(bg_cmd_ids=["${d}"]) to block until it finishes, read_background_output(task_id="${d}", mode="tail") to read output, list_background_commands to view all, or kill_background_command(task_id="${d}") to stop.`};const f=c===-1?0:Math.max(0,Math.floor(c*1e3)),b=[E];let y;c!==-1&&b.push(new Promise(P=>{y=setTimeout(()=>P("__timeout__"),f),y.unref?.()}));let k;c===-1&&a>0&&b.push(new Promise(P=>{k=setTimeout(()=>P("__total_timeout__"),a),k.unref?.()})),l&&b.push(l.then(()=>"__settle__"));try{const P=await Promise.race(b);if(P==="__settle__")return o.manager.disableInactivityTimeout(t,d),{ok:!0,tool:"Bash",command:e,backgrounded:!0,taskId:d,status:"backgrounded",reason:"watchdog_timeout",waitedMs:f,message:`Command still running after watchdog timeout; moved to background. Use await_complete(bg_cmd_ids=["${d}"]) to block until it finishes, read_background_output(task_id="${d}", mode="tail") to read output, or kill_background_command(task_id="${d}") to stop.`};if(P==="__timeout__")return o.manager.disableInactivityTimeout(t,d),{ok:!0,tool:"Bash",command:e,backgrounded:!0,taskId:d,status:"backgrounded",reason:"timeout",waitedMs:f,message:`Command still running after ${c}s; moved to background. Use await_complete(bg_cmd_ids=["${d}"]) to block until it finishes, or read_background_output(task_id="${d}", mode="tail") / kill_background_command(task_id="${d}") to inspect.`};if(P==="__total_timeout__")return o.manager.disableInactivityTimeout(t,d),{ok:!0,tool:"Bash",command:e,backgrounded:!0,taskId:d,status:"backgrounded",reason:"tool_timeout",waitedMs:Math.floor(a/1e3),message:`Command still running after ${Math.floor(a/1e3)}s (total timeout); moved to background. It continues running in the background without a total timeout. Use await_complete(bg_cmd_ids=["${d}"]) to block until it finishes, or read_background_output(task_id="${d}", mode="tail") / kill_background_command(task_id="${d}") to inspect.`};const p=P;let v=p.stdout,R=p.stderr,T=p.outputSpilled,N=p.outputFilePath;if(!T&&H(`${p.stdout}${p.stderr}`)>lt){const M=await dt(t,"cmd","out",ct({commandText:e,commandFilePath:p.commandFilePath,commandLineCount:p.commandLineCount,cwd:s,startedAt:new Date(Date.now()-p.durationMs),endedAt:new Date,exitCode:p.exitCode,signal:p.signal??null,timedOut:p.timedOut,inactivityTimedOut:p.inactivityTimedOut??!1,stdout:v,stderr:R}));v=ut($(M),H(`${p.stdout}${p.stderr}`)),T=!0,N=$(M)}return{ok:p.exitCode===0&&!p.timedOut,tool:"Bash",command:e,backgrounded:!1,taskId:d,exitCode:p.exitCode,signal:p.signal,timedOut:p.timedOut,inactivityTimedOut:p.inactivityTimedOut,timeoutMs:p.timeoutMs||a,inactivityTimeoutMs:p.inactivityTimeoutMs,durationMs:p.durationMs,outputSpilled:T,outputFilePath:N,outputLineCount:p.outputLineCount,commandFilePath:p.commandFilePath,commandLineCount:p.commandLineCount,stdout:v,stderr:R}}finally{y&&clearTimeout(y),k&&clearTimeout(k),_()}}catch(d){if(d?.code==="too_many_tasks"||d?.code==="global_limit_reached")return{ok:!1,tool:"Bash",command:e,backgrounded:!1,status:"not_executed",error:d.code,message:`Command was NOT executed: ${d.message}. Wait for some background tasks to finish/cleanup (per-agent limit 16, global 256), or reduce concurrent background commands, then retry.`};throw d}}function Ht(n){return{kind:"builtin",toolName:"grep",exposedName:"grep",description:"Search file contents using regular expressions within the workspace. Returns matched lines with file paths and line numbers. Supports include/exclude glob patterns, case-insensitive matching, and three output modes (content, files_with_matches, count). Searches recursively through directories, skipping binary files, hidden directories, and common build/dependency directories (node_modules, .git, dist, etc.).",inputSchema:{type:"object",properties:{pattern:{type:"string",description:"Regular expression pattern to search for in file contents."},path:{type:"string",description:"Workspace-relative file or directory path to search in. Defaults to the workspace root."},include:{type:"string",description:"Glob pattern to filter files by name (e.g. '*.ts', '*.{js,ts}'). Only matching files are searched."},exclude:{type:"string",description:"Glob pattern to exclude files by name (e.g. '*.test.ts'). Matching files are skipped."},case_insensitive:{type:"boolean",description:"Case-insensitive matching. Default false."},output_mode:{type:"string",enum:["content","files_with_matches","count"],description:"Output format: 'content' returns matched lines with line numbers (default), 'files_with_matches' returns only file paths with matches, 'count' returns match counts per file."},max_results:{type:"number",description:"Maximum number of matched lines to return (content mode). Default 1000."}},required:["pattern"],additionalProperties:!1},async execute(o){const e=S(o,["pattern"],"pattern"),t=I(o,["path"])||".",i=I(o,["include"]),s=I(o,["exclude"]),a=o.case_insensitive===!0,r=(()=>{const T=o.output_mode;return T==="files_with_matches"||T==="count"?T:"content"})(),c=C(o,["max_results"],Rt),u=a?"i":"";let l;try{l=new RegExp(e,u)}catch(T){throw new Error(`Invalid regex pattern: ${T instanceof Error?T.message:String(T)}`)}const g=i?ot(i):null,h=s?ot(s):null,_=await F(n,t),d=O(_.workspaceRoot,await w.realpath(_.targetPath)),E=await w.stat(d);let f;if(E.isFile())f=[d];else if(E.isDirectory())f=await Ct(d,g,h,vt);else throw new Error(`Path is neither a file nor a directory: ${d}`);const b=[],y=[],k=[];let P=0,p=0,v=!1;for(const T of f){if(r==="content"&&b.length>=c){v=!0;break}const N={regex:l,maxResults:r==="content"?c-b.length:Number.MAX_SAFE_INTEGER,collectContent:r==="content",stopOnFirstMatch:r==="files_with_matches"},M=await Nt(T,_.workspaceRoot,N);if(M.count>0){const j=m.relative(_.workspaceRoot,T).replace(/\\/g,"/");if(k.push(j),P+=M.count,r==="content"){for(const z of M.matches){const G=Buffer.byteLength(z.content,"utf-8")+64;if(p+G>$t){v=!0;break}p+=G,b.push(z)}if(v)break;if(b.length>=c){v=!0;break}}else r==="count"&&y.push({file:j,count:M.count})}}const R={ok:!0,tool:"grep",pattern:e,searchPath:$(_.targetPath),outputMode:r,filesSearched:f.length,filesMatched:k.length,totalMatches:P,truncated:v};return r==="content"?R.matches=b:r==="files_with_matches"?R.matches=k:R.matches=y,R}}}function se(n,o,e,t,i){const s=o||"unknown",a=[Gt(n,i),qt(n,e,i),jt(n,e,i),zt(n,e,i),Ht(n),Xt(n,s,t,i),mt(n)];return t&&a.push(ht(s,t),ft(s,t),pt(s,t)),a}export{re as DEFAULT_TOOL_PERMISSION_POLICY,se as createBuiltInFileTools,O as ensureInsideWorkspace,F as resolveWorkspaceTarget};
|
|
3
|
+
`+_:_;return{workspaceRoot:a.workspaceRoot,targetPath:r,content:p,isBinary:!1,truncated:m||E,totalLines:E?-1:h,shownFromLine:k,shownToLine:b}}finally{u.close(),c.destroy()}}function q(n){return/^https?:\/\//i.test(n)}async function Ft(n){let o;try{o=new URL(n)}catch{throw new Error(`Invalid image URL: ${n}`)}if(o.protocol!=="http:"&&o.protocol!=="https:")throw new Error(`Unsupported image URL protocol: ${o.protocol} (only http/https)`);let e;try{e=await fetch(n,{signal:AbortSignal.timeout(Et)})}catch(u){const l=u instanceof Error?u.message:String(u);throw new Error(`Image URL fetch failed: ${n} (${l})`)}if(!e.ok)throw new Error(`Image URL fetch failed: ${n} (HTTP ${e.status})`);const t=(e.headers.get("content-type")||"").split(";")[0]?.trim().toLowerCase()||"";if(t&&!t.startsWith("image/"))throw new Error(`URL did not return an image (content-type: ${t}): ${n}`);const i=Number(e.headers.get("content-length")||"");if(Number.isFinite(i)&&i>L)throw new Error(`Image too large to fetch: ${n} (${x(i)} > ${x(L)})`);const a=e.body;if(!a){const u=await e.arrayBuffer();if(u.byteLength>L)throw new Error(`Image too large to fetch: ${n} (${x(u.byteLength)} > ${x(L)})`);return Buffer.from(u)}const r=a.getReader(),s=[];let c=0;for(;;){const{done:u,value:l}=await r.read();if(u)break;if(l){if(c+=l.byteLength,c>L)throw r.cancel().catch(()=>{}),new Error(`Image too large to fetch: ${n} (${x(c)} > ${x(L)})`);s.push(Buffer.from(l))}}return Buffer.concat(s,c)}async function Nt(n,o,e){let t,i;if(q(o))t=await Ft(o),i=o;else{const b=(await tt(n,o,e)).targetPath,_=await w.stat(b);if(!_.isFile())throw new Error(`Path is not a file: ${b}`);if(_.size>Z)throw new Error(`Image file too large to read: ${$(b)} (${x(_.size)} > ${x(Z)}). Downscale it first.`);t=await w.readFile(b),i=$(b)}if(t.length===0)throw new Error(`Image file is empty: ${i}`);const a=pt(t);if(!a)throw new Error(`Unsupported or corrupt image (unrecognized format): ${i}`);const r=wt(t);let s=a,c=t,u=r?.width,l=r?.height,g=!1;const h=await gt(t,a,{maxWidth:C,maxHeight:C,maxBytes:D});if(h)c=h.buffer,s=h.mediaType,u=h.width,l=h.height,g=h.changed;else if(t.length>D)throw new Error(`Image too large to inline: ${i} (${x(t.length)} > ${x(D)}). Downscale it first, e.g. via Bash: magick "${o}" -resize ${C}x${C} "${o}". Installing sharp enables automatic downscaling.`);const y=u&&l?`${u}x${l}`:"unknown dimensions",m=g&&r&&r.width!==u?` (resized from ${r.width}x${r.height})`:g?" (resized)":"",E=`[Image: ${i}, ${y}${m}, ${x(c.length)}]`,f=q(o)?d.basename(new URL(o).pathname)||"image":d.basename(i);return{ok:!0,filePath:i,content:E,isBinary:!1,image:{mediaType:K(s),width:u??null,height:l??null,originalWidth:r?.width??null,originalHeight:r?.height??null,resized:g,size:c.length},attachments:[{type:"image",name:f,mediaType:K(s),base64Data:c.toString("base64")}]}}function ot(n){let o="",e=0;for(;e<n.length;){const t=n[e];if(t==="*")o+="[^/]*";else if(t==="?")o+="[^/]";else if(t==="{"){const i=n.indexOf("}",e);if(i>=0){const a=n.slice(e+1,i);o+=`(${a.split(",").join("|")})`,e=i}else o+="\\{"}else if(t==="["){const i=n.indexOf("]",e);i>=0?(o+=n.slice(e,i+1),e=i):o+="\\["}else"+^$.()|\\".includes(t)?o+="\\"+t:o+=t;e++}return new RegExp(`^${o}$`)}async function Bt(n,o,e,t){const i=[];async function a(r){if(i.length>=t)return;const s=await w.readdir(r,{withFileTypes:!0});for(const c of s){if(i.length>=t)return;if(c.name.startsWith(".")&&c.isDirectory())continue;const u=d.join(r,c.name);if(c.isDirectory()){if(Rt.has(c.name))continue;await a(u)}else if(c.isFile()){if(o&&!o.test(c.name)||e&&e.test(c.name))continue;i.push(u)}}}return await a(n),i}async function Ct(n,o,e){if((await w.stat(n)).size>vt)return{matches:[],count:0};if(await Q(n))return{matches:[],count:0};const i=d.relative(o,n).replace(/\\/g,"/"),a=[];let r=0;const s=X(n,{encoding:"utf-8"}),c=Y.createInterface({input:s,crlfDelay:1/0});try{let u=0;for await(const l of c)if(u++,e.regex.test(l)){if(r++,e.collectContent){let g=l;if(g.length>O&&(g=g.slice(0,O)+`... (line truncated to ${O} chars)`),a.push({file:i,line:u,content:g}),a.length>=e.maxResults)break}if(e.stopOnFirstMatch)break}}finally{c.close(),s.destroy()}return{matches:a,count:r}}const Ut=12*60*6e4,Dt=30*6e4,Wt=6e4,qt=10*6e4;function jt(n,o,e){return{kind:"builtin",toolName:"write_file",exposedName:"write_file",description:"Create or overwrite a UTF-8 text file inside the current workspace. Parent directories are created automatically.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Workspace-relative file path to write."},content:{type:"string",description:"Complete UTF-8 file content."},reason:{type:"string",description:"Optional reason for this change, e.g. what bug is being fixed. Helps humans understand the change later."}},required:["file_path","content"],additionalProperties:!1},async execute(t){const i=R(t,["file_path","filePath"],"file_path"),a=R(t,["content"],"content"),r=I(t,["reason"]),s=await A(n,i);await F(e,"fileModification",{operation:"write",path:s.targetPath});const c=await J(s.targetPath),u=c?await w.readFile(s.targetPath,"utf-8").catch(()=>null):null,l=await et(n,i,a);if(o){const g=d.relative(l.workspaceRoot,l.targetPath).replace(/\\/g,"/");await o({filePath:g,operation:c?"UPDATE":"CREATE",beforeContent:u,afterContent:a,reason:r})}return{ok:!0,filePath:$(l.targetPath),bytes:l.bytes,createdParentDirectory:l.createdParentDirectory}}}}function zt(n,o,e){return{kind:"builtin",toolName:"edit_file",exposedName:"edit_file",description:"Replace exactly one occurrence of old_string with new_string in a UTF-8 workspace text file.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Workspace-relative file path to edit."},old_string:{type:"string",description:"Existing text to replace. Must occur exactly once."},new_string:{type:"string",description:"Replacement text."},reason:{type:"string",description:"Optional reason for this change, e.g. what bug is being fixed. Helps humans understand the change later."}},required:["file_path","old_string","new_string"],additionalProperties:!1},async execute(t){const i=R(t,["file_path","filePath"],"file_path"),a=R(t,["old_string","oldString"],"old_string"),r=R(t,["new_string","newString"],"new_string"),s=I(t,["reason"]);if(!a)throw new Error("old_string must not be empty");const c=await A(n,i);await F(e,"fileModification",{operation:"edit",path:c.targetPath});const u=await Lt(n,i),l=St(u.content,a);if(l===0)throw new Error("old_string was not found in file");if(l>1)throw new Error(`old_string occurs ${l} times; provide a unique match`);const g=u.content.replace(a,r),h=await et(n,i,g);if(o){const y=d.relative(h.workspaceRoot,h.targetPath).replace(/\\/g,"/");await o({filePath:y,operation:"UPDATE",beforeContent:u.content,afterContent:g,reason:s})}return{ok:!0,filePath:$(h.targetPath),bytes:h.bytes}}}}function Gt(n,o,e){return{kind:"builtin",toolName:"delete_file",exposedName:"delete_file",description:"Delete a file inside the current workspace. Returns an error if the file does not exist.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Workspace-relative file path to delete."},reason:{type:"string",description:"Optional reason for this change, e.g. what bug is being fixed. Helps humans understand the change later."}},required:["file_path"],additionalProperties:!1},async execute(t){const i=R(t,["file_path","filePath"],"file_path"),a=I(t,["reason"]),r=await A(n,i);await F(e,"fileModification",{operation:"delete",path:r.targetPath});const s=M(r.workspaceRoot,await w.realpath(r.targetPath).catch(()=>r.targetPath)),c=await w.stat(s).catch(()=>null);if(!c)throw new Error(`File does not exist: ${s}`);if(!c.isFile())throw new Error(`Path is not a file: ${s}`);const u=await w.readFile(s,"utf-8").catch(()=>null);if(await w.rm(s,{force:!0}),o){const l=d.relative(r.workspaceRoot,s).replace(/\\/g,"/");await o({filePath:l,operation:"DELETE",beforeContent:u,afterContent:null,reason:a})}return{ok:!0,filePath:$(s),deleted:!0}}}}function Xt(n,o){return{kind:"builtin",toolName:"read_file",exposedName:"read_file",description:"Read a UTF-8 text file inside the current workspace. Returns content with line numbers in the format '<line>: <content>'. Supports offset (1-indexed line number to start from) and limit (max lines to return, default 2000). Output is capped at 2000 lines or 50 KB, whichever is reached first. Individual lines longer than 2000 characters are truncated. Avoid tiny repeated slices (e.g. 30-line chunks); read a larger window if more context is needed. Images (.png/.jpg/.jpeg/.gif/.webp) and http(s) image URLs are also supported: the image is inlined into the conversation so you can see it (requires a model with image input). offset/limit are ignored for images; oversized images are automatically downscaled when sharp is available.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Workspace-relative file path to read. Also accepts an http(s) URL pointing to an image."},offset:{type:"number",description:"Line number to start reading from (1-indexed). Defaults to 1."},limit:{type:"number",description:"Maximum number of lines to return. Defaults to 2000."}},required:["file_path"],additionalProperties:!1},async execute(e){const t=R(e,["file_path","filePath"],"file_path"),i=d.extname(t).toLowerCase().slice(1);if(q(t)||Tt.has(i))return await Nt(n,t,o);const a=U(e,["offset"],1),r=U(e,["limit"],_t),s=await At(n,t,a,r,o);return{ok:!0,filePath:$(s.targetPath),content:s.content,isBinary:s.isBinary,truncated:s.truncated,totalLines:s.totalLines,shownFromLine:s.shownFromLine,shownToLine:s.shownToLine}}}}function Yt(n,o,e,t){return{kind:"builtin",toolName:"Bash",exposedName:"Bash",description:"Execute a shell command in the current workspace. Use for local diagnostics, builds, tests, and OS commands. The command runs with a bounded total timeout (timeout_ms) measured from command start \u2014 by default 30 minutes, after which the process is force-terminated; timeout_ms can raise this (up to 12 hours) or set 0 to disable. The tool returns stdout, stderr, exit code, and (if converted to background) a task_id. By default (wait_seconds omitted or -1) the command runs in the FOREGROUND and streams output in real time; if the 5-minute adapter watchdog fires while it is still running, the command is moved to the BACKGROUND and the tool returns a task_id plus an explanation (backgrounded=true, reason=watchdog_timeout). The background command stays bound by the same total timeout (timeout_ms, default 30 minutes, still measured from command start) and can be managed via await_complete / list_background_commands / read_background_output / kill_background_command. For immediate backgrounding use wait_seconds=0, or wait_seconds=n>0 to wait n seconds then background.",inputSchema:{type:"object",properties:{command:{type:"string",description:"Shell command to execute."},cwd:{type:"string",description:"Optional workspace-relative working directory. Defaults to the workspace root."},timeout_ms:{type:"number",description:"Optional total command timeout in milliseconds, measured from command start. Defaults to 1800000 (30 minutes) and is capped at 43200000 (12 hours). Set 0 to disable the timeout entirely (run until finished or killed)."},inactivity_timeout_ms:{type:"number",description:"Optional no-output timeout in milliseconds. Defaults to 60000 and is capped at 600000."},wait_seconds:{type:"number",description:"How to wait for the command to finish. Omitted values (or -1, the default): run in the FOREGROUND until completion; if the 5-minute adapter watchdog fires first, the command is moved to the background and a task_id is returned (backgrounded=true, reason=watchdog_timeout). 0: spawn and immediately execute in the background, return task_id. n>0: wait up to n seconds; if still running, move to the background and return task_id. The command remains bound by the total timeout (timeout_ms, default 30 minutes, measured from command start) whether foreground or background; inactivity_timeout_ms is ignored once backgrounded.",minimum:-1},description:{type:"string",description:"Optional short reason for running the command."}},required:["command"],additionalProperties:!1},async execute(i,a){const r=R(i,["command"],"command").trim();if(!r)throw new Error("command must not be empty");const s=It(i,["timeout_ms","timeoutMs"],Dt),c=s===0?0:Math.min(s,Ut),u=U(i,["inactivity_timeout_ms","inactivityTimeoutMs"],Wt),l=Math.min(u,qt),g=I(i,["cwd"]),h=await Mt(n,g);await F(t,"commandExecution",{command:r,cwd:$(h.cwd)});const y=i.wait_seconds,E=typeof y=="number"&&Number.isFinite(y)?y:-1;if(e)return await Ht({deps:e,command:r,agentId:o,workspaceRoot:h.workspaceRoot,cwd:h.cwd,timeoutMs:c,inactivityTimeoutMs:l,waitSeconds:E,onOutput:a?.onOutput,settleSignal:a?.settleSignal});const f=await at({commandText:r,agentId:o,workspaceRoot:h.workspaceRoot,cwd:h.cwd,timeoutMs:c,inactivityTimeoutMs:l,onOutput:a?.onOutput,watchdogSignal:a?.settleSignal}),k={ok:f.exitCode===0&&!f.timedOut,tool:"Bash",command:r,cwd:$(h.cwd),exitCode:f.exitCode,signal:f.signal,timedOut:f.timedOut,inactivityTimedOut:f.inactivityTimedOut,watchdogInterrupted:f.watchdogInterrupted,timeoutMs:c,inactivityTimeoutMs:l,durationMs:f.durationMs,outputSpilled:f.outputSpilled,outputFilePath:f.outputFilePath,outputLineCount:f.outputLineCount,commandFilePath:f.commandFilePath,commandLineCount:f.commandLineCount,stdout:f.stdout,stderr:f.stderr};return f.watchdogInterrupted?{...k,message:"Command was interrupted by the adapter watchdog after ~5 minutes of synchronous (foreground) execution. Only the partial output produced so far is returned above"+(f.outputFilePath?` (full output spilled to "${f.outputFilePath}"; read it if you need more)`:"")+". For long-running commands, re-run with wait_seconds=0 (or n>0) to execute in the background, then manage via await_complete / list_background_commands / read_background_output / kill_background_command."}:k}}}async function Ht(n){const{deps:o,command:e,agentId:t,workspaceRoot:i,cwd:a,timeoutMs:r,inactivityTimeoutMs:s,waitSeconds:c,onOutput:u,settleSignal:l}=n,g=u?rt({cwd:a,commandLineCount:0,onOutput:u}):void 0;let h=!!g;const y=()=>{h&&(h=!1,g?.close())};try{const{taskId:m,completion:E}=o.manager.startCommand({commandText:e,agentId:t,workspaceRoot:i,cwd:a,timeoutMs:r,inactivityTimeoutMs:s,onOutput:h?_=>{h&&g?.push(_.stream,_.text)}:void 0,onCompleted:o.emitCompleted});if(c===0)return o.manager.disableInactivityTimeout(t,m),y(),{ok:!0,tool:"Bash",command:e,backgrounded:!0,taskId:m,status:"backgrounded",reason:"immediate",message:`Command moved to background. Use await_complete(bg_cmd_ids=["${m}"]) to block until it finishes, read_background_output(task_id="${m}", mode="tail") to read output, list_background_commands to view all, or kill_background_command(task_id="${m}") to stop.`};const f=c===-1?0:Math.max(0,Math.floor(c*1e3)),k=[E];let b;c!==-1&&k.push(new Promise(_=>{b=setTimeout(()=>_("__timeout__"),f),b.unref?.()})),l&&k.push(l.then(()=>"__settle__"));try{const _=await Promise.race(k);if(_==="__settle__")return o.manager.disableInactivityTimeout(t,m),{ok:!0,tool:"Bash",command:e,backgrounded:!0,taskId:m,status:"backgrounded",reason:"watchdog_timeout",waitedMs:f,message:`Command still running after watchdog timeout; moved to background. Use await_complete(bg_cmd_ids=["${m}"]) to block until it finishes, read_background_output(task_id="${m}", mode="tail") to read output, or kill_background_command(task_id="${m}") to stop.`};if(_==="__timeout__")return o.manager.disableInactivityTimeout(t,m),{ok:!0,tool:"Bash",command:e,backgrounded:!0,taskId:m,status:"backgrounded",reason:"timeout",waitedMs:f,message:`Command still running after ${c}s; moved to background. Use await_complete(bg_cmd_ids=["${m}"]) to block until it finishes, or read_background_output(task_id="${m}", mode="tail") / kill_background_command(task_id="${m}") to inspect.`};const p=_;let S=p.stdout,P=p.stderr,v=p.outputSpilled,T=p.outputFilePath;if(!v&&H(`${p.stdout}${p.stderr}`)>ct){const N=await ut(t,"cmd","out",st({commandText:e,commandFilePath:p.commandFilePath,commandLineCount:p.commandLineCount,cwd:a,startedAt:new Date(Date.now()-p.durationMs),endedAt:new Date,exitCode:p.exitCode,signal:p.signal??null,timedOut:p.timedOut,inactivityTimedOut:p.inactivityTimedOut??!1,stdout:S,stderr:P}));S=lt($(N),H(`${p.stdout}${p.stderr}`)),v=!0,T=$(N)}return{ok:p.exitCode===0&&!p.timedOut,tool:"Bash",command:e,backgrounded:!1,taskId:m,exitCode:p.exitCode,signal:p.signal,timedOut:p.timedOut,inactivityTimedOut:p.inactivityTimedOut,timeoutMs:p.timeoutMs,inactivityTimeoutMs:p.inactivityTimeoutMs,durationMs:p.durationMs,outputSpilled:v,outputFilePath:T,outputLineCount:p.outputLineCount,commandFilePath:p.commandFilePath,commandLineCount:p.commandLineCount,stdout:S,stderr:P}}finally{b&&clearTimeout(b),y()}}catch(m){if(m?.code==="too_many_tasks"||m?.code==="global_limit_reached")return{ok:!1,tool:"Bash",command:e,backgrounded:!1,status:"not_executed",error:m.code,message:`Command was NOT executed: ${m.message}. Wait for some background tasks to finish/cleanup (per-agent limit 16, global 256), or reduce concurrent background commands, then retry.`};throw m}}function Kt(n){return{kind:"builtin",toolName:"grep",exposedName:"grep",description:"Search file contents using regular expressions within the workspace. Returns matched lines with file paths and line numbers. Supports include/exclude glob patterns, case-insensitive matching, and three output modes (content, files_with_matches, count). Searches recursively through directories, skipping binary files, hidden directories, and common build/dependency directories (node_modules, .git, dist, etc.).",inputSchema:{type:"object",properties:{pattern:{type:"string",description:"Regular expression pattern to search for in file contents."},path:{type:"string",description:"Workspace-relative file or directory path to search in. Defaults to the workspace root."},include:{type:"string",description:"Glob pattern to filter files by name (e.g. '*.ts', '*.{js,ts}'). Only matching files are searched."},exclude:{type:"string",description:"Glob pattern to exclude files by name (e.g. '*.test.ts'). Matching files are skipped."},case_insensitive:{type:"boolean",description:"Case-insensitive matching. Default false."},output_mode:{type:"string",enum:["content","files_with_matches","count"],description:"Output format: 'content' returns matched lines with line numbers (default), 'files_with_matches' returns only file paths with matches, 'count' returns match counts per file."},max_results:{type:"number",description:"Maximum number of matched lines to return (content mode). Default 1000."}},required:["pattern"],additionalProperties:!1},async execute(o){const e=R(o,["pattern"],"pattern"),t=I(o,["path"])||".",i=I(o,["include"]),a=I(o,["exclude"]),r=o.case_insensitive===!0,s=(()=>{const T=o.output_mode;return T==="files_with_matches"||T==="count"?T:"content"})(),c=U(o,["max_results"],$t),u=r?"i":"";let l;try{l=new RegExp(e,u)}catch(T){throw new Error(`Invalid regex pattern: ${T instanceof Error?T.message:String(T)}`)}const g=i?ot(i):null,h=a?ot(a):null,y=await A(n,t),m=M(y.workspaceRoot,await w.realpath(y.targetPath)),E=await w.stat(m);let f;if(E.isFile())f=[m];else if(E.isDirectory())f=await Bt(m,g,h,Pt);else throw new Error(`Path is neither a file nor a directory: ${m}`);const k=[],b=[],_=[];let p=0,S=0,P=!1;for(const T of f){if(s==="content"&&k.length>=c){P=!0;break}const N={regex:l,maxResults:s==="content"?c-k.length:Number.MAX_SAFE_INTEGER,collectContent:s==="content",stopOnFirstMatch:s==="files_with_matches"},B=await Ct(T,y.workspaceRoot,N);if(B.count>0){const j=d.relative(y.workspaceRoot,T).replace(/\\/g,"/");if(_.push(j),p+=B.count,s==="content"){for(const z of B.matches){const G=Buffer.byteLength(z.content,"utf-8")+64;if(S+G>xt){P=!0;break}S+=G,k.push(z)}if(P)break;if(k.length>=c){P=!0;break}}else s==="count"&&b.push({file:j,count:B.count})}}const v={ok:!0,tool:"grep",pattern:e,searchPath:$(y.targetPath),outputMode:s,filesSearched:f.length,filesMatched:_.length,totalMatches:p,truncated:P};return s==="content"?v.matches=k:s==="files_with_matches"?v.matches=_:v.matches=b,v}}}function ce(n,o,e,t,i){const a=o||"unknown",r=[Xt(n,i),jt(n,e,i),zt(n,e,i),Gt(n,e,i),Kt(n),Yt(n,a,t,i),dt(n)];return t&&r.push(mt(a,t),ht(a,t),ft(a,t)),r}export{se as DEFAULT_TOOL_PERMISSION_POLICY,ce as createBuiltInFileTools,M as ensureInsideWorkspace,A as resolveWorkspaceTarget};
|
|
4
4
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{spawn as R}from"node:child_process";import{createOutputEventCollector as A}from"./commandOutputEvents.js";import{prepareShellCommand as D,shellExecutable as G}from"./shellCommandPreparation.js";import{resolveClosedShellCommand as P}from"./shellCommandResult.js";import{createShellOutputDecoder as E,decodeShellOutputChunk as
|
|
1
|
+
import{spawn as R}from"node:child_process";import{createOutputEventCollector as A}from"./commandOutputEvents.js";import{prepareShellCommand as D,shellExecutable as G}from"./shellCommandPreparation.js";import{resolveClosedShellCommand as P}from"./shellCommandResult.js";import{createShellOutputDecoder as E,decodeShellOutputChunk as i}from"./shellOutputDecoder.js";const K=1e3;async function B(t){const a=G(),d=await D(t.commandText,t.workspaceRoot,a);return new Promise((L,T)=>{const O=new Date,r=R(a.command,[...a.argsPrefix,d.commandText],{cwd:t.cwd,env:process.env,windowsVerbatimArguments:process.platform==="win32",windowsHide:!0}),u=A({cwd:t.cwd,commandLineCount:d.commandLineCount,commandFilePath:d.commandFilePath,onOutput:t.onOutput});let h="",p="",c=!1,S=!1,I=!1,m=!1,n,o;const g=E(),k=E(),s=()=>{o&&clearTimeout(o),n&&clearTimeout(n),o=void 0,n=void 0},f=()=>{n||(n=setTimeout(()=>{r.killed||r.kill("SIGKILL")},K),n.unref?.())};let l;t.timeoutMs>0&&(l=setTimeout(()=>{c=!0,r.kill("SIGTERM"),f()},t.timeoutMs),l.unref?.());const w=()=>{o&&clearTimeout(o),o=setTimeout(()=>{S=!0,c=!0,r.kill("SIGTERM"),f()},t.inactivityTimeoutMs),o.unref?.()};w();const M=()=>{m||r.killed||(I=!0,c=!0,clearTimeout(l),s(),r.kill("SIGTERM"),f())};t.watchdogSignal&&t.watchdogSignal.then(M,()=>{});const v=e=>{e&&(h+=e,u.push("stdout",e),w())},C=e=>{e&&(p+=e,u.push("stderr",e),w())};r.stdout?.on("data",e=>{v(i(g,e))}),r.stderr?.on("data",e=>{C(i(k,e))}),r.on("error",e=>{m=!0,clearTimeout(l),s(),u.close(),T(e)}),r.on("close",(e,y)=>{m=!0,clearTimeout(l),s(),v(i(g,void 0,!0)),C(i(k,void 0,!0)),u.close(),P({exitCode:e,signal:y,stdout:h,stderr:p,startedAt:O,timedOut:c,inactivityTimedOut:S,watchdogInterrupted:I,prepared:d,agentId:t.agentId,workspaceRoot:t.workspaceRoot,cwd:t.cwd}).then(L,T)})})}export{B as runShellCommand};
|
|
2
2
|
|
|
@@ -38,5 +38,5 @@ MCP \u5DE5\u5177\uFF08poll_message/get_message\uFF09\u4E0D\u518D\u8FD4\u56DE sys
|
|
|
38
38
|
|
|
39
39
|
\u8FD4\u56DE\u5B57\u6BB5\uFF1Aid\u3001projectId\u3001businessLine\u3001module\u3001level\u3001detail\u3001createdAt\u3002`,inputSchema:{type:"object",properties:{projectId:{type:"string",description:"\u9879\u76EE ID\uFF08\u5FC5\u586B\uFF09"},businessLine:{type:"string",description:"\u4E1A\u52A1\u7EBF\u540D\u79F0\uFF08\u5FC5\u586B\uFF09"},module:{type:"string",description:"\u6A21\u5757\u540D\uFF08\u53EF\u9009\uFF09"},level:{type:"string",description:"\u65E5\u5FD7\u7EA7\u522B\uFF1ADEBUG / INFO / WARN / ERROR\uFF08\u53EF\u9009\uFF09",enum:["DEBUG","INFO","WARN","ERROR"]},startTime:{type:"string",description:"\u8D77\u59CB\u65F6\u95F4\uFF0CISO \u683C\u5F0F\u5982 2026-08-01T00:00:00\uFF08\u53EF\u9009\uFF09"},endTime:{type:"string",description:"\u7ED3\u675F\u65F6\u95F4\uFF0CISO \u683C\u5F0F\u5982 2026-08-02T00:00:00\uFF08\u53EF\u9009\uFF09"},offset:{type:"number",description:"\u504F\u79FB\u91CF\uFF0C\u9ED8\u8BA4 0"},limit:{type:"number",description:"\u6BCF\u9875\u6761\u6570\uFF0C\u9ED8\u8BA4 20\uFF0C\u6700\u5927 200"}},required:["projectId","businessLine"]}},f={name:"query_file_changes_history",description:`\u5206\u9875\u67E5\u8BE2\u6587\u4EF6\u53D8\u66F4\u5386\u53F2\uFF08\u6309\u65F6\u95F4\u5012\u5E8F\uFF09\u3002\u7528\u4E8E\u4E86\u89E3\u5176\u5B83 Agent \u5BF9\u6587\u4EF6\u505A\u8FC7\u54EA\u4E9B\u4FEE\u6539\u3001\u4FEE\u6539\u539F\u56E0\u4E0E\u5F53\u524D\u72B6\u6001\uFF0C\u652F\u6301\u6309 \u89D2\u8272/\u5B9E\u4F8B/\u6587\u4EF6\u540D/\u76F8\u5BF9\u8DEF\u5F84/\u64CD\u4F5C/\u72B6\u6001/\u4EFB\u52A1\u5B9E\u4F8B/\u65F6\u95F4\u8303\u56F4 \u8FC7\u6EE4\u3002\u67E5\u8BE2\u8303\u56F4\u81EA\u52A8\u9650\u5B9A\u4E3A\u5F53\u524D Agent \u6240\u5C5E\u9879\u76EE\u3002
|
|
40
40
|
|
|
41
|
-
\u8FD4\u56DE\u5B57\u6BB5\uFF1Aid\u3001projectId\u3001roleName\u3001instanceName\u3001agentId\u3001operation\uFF08CREATE/UPDATE/DELETE\uFF09\u3001targetPath\u3001fullPath\u3001reason\u3001status\uFF08APPLIED/REVERTED/REVERT_FAILED\uFF09\u3001createdAt\u3001revertedAt\u3001revertedBy\u3002`,inputSchema:{type:"object",properties:{roleId:{type:"string",description:"\u89D2\u8272\u5B9A\u4E49 ID\uFF08\u53EF\u9009\uFF09"},agentId:{type:"string",description:"Agent \u5B9E\u4F8B ID\uFF08\u53EF\u9009\uFF1B\u4E0D\u4F20=\u67E5\u8BE2\u5F53\u524D\u9879\u76EE\u4E0B\u6240\u6709 Agent\uFF1B\u4F20\u5176\u5B83 Agent \u65F6\u670D\u52A1\u7AEF\u6821\u9A8C\u5176\u4E0E\u8C03\u7528\u8005\u540C\u9879\u76EE\uFF09"},fileName:{type:"string",description:"\u6587\u4EF6\u540D\uFF08\u53EF\u9009\uFF0C\u6309 basename \u6A21\u7CCA\u5339\u914D\uFF09"},filePath:{type:"string",description:"\u5DE5\u4F5C\u533A\u76F8\u5BF9\u8DEF\u5F84\uFF08\u53EF\u9009\uFF0C\u6309\u8D26\u672C\u8BB0\u5F55\u7684\u76F8\u5BF9\u8DEF\u5F84 targetPath \u5339\u914D\uFF0C\u542B\u76EE\u5F55\u524D\u7F00\u5339\u914D\uFF09\u3002\u652F\u6301 ./xx\u3001xx\u3001@/xx\u3001/xx \u7B49\u4EF7\u5199\u6CD5\uFF08@ \u89C6\u4E3A\u5DE5\u4F5C\u533A\u6839\u8DEF\u5F84\u522B\u540D\uFF09\u3002\u793A\u4F8B\uFF1A@/src/main.ts \u7CBE\u786E\u5339\u914D src/main.ts\uFF1B@/src \u5339\u914D src/ \u76EE\u5F55\u53CA\u5176\u4E0B\u6240\u6709\u6587\u4EF6\u7684\u53D8\u66F4\u3002\u4E0E fileName \u6B63\u4EA4\uFF1AfileName \u6309\u6587\u4EF6\u540D\u6A21\u7CCA\uFF0CfilePath \u6309\u76F8\u5BF9\u8DEF\u5F84\u5339\u914D\u3002"},operation:{type:"string",description:"\u64CD\u4F5C\u7C7B\u578B\uFF1ACREATE / UPDATE / DELETE\uFF08\u53EF\u9009\uFF09",enum:["CREATE","UPDATE","DELETE"]},status:{type:"string",description:"\u8BB0\u5F55\u72B6\u6001\uFF1AAPPLIED\uFF08\u5DF2\u751F\u6548\uFF09/ REVERTED\uFF08\u5DF2\u64A4\u9500\uFF09/ REVERT_FAILED\uFF08\u64A4\u9500\u5931\u8D25\uFF09\uFF08\u53EF\u9009\uFF09",enum:["APPLIED","REVERTED","REVERT_FAILED"]},taskInstanceId:{type:"string",description:"\u4EFB\u52A1\u5B9E\u4F8B ID\uFF08\u53EF\u9009\uFF09"},startTime:{type:"string",description:"\u8D77\u59CB\u65F6\u95F4\uFF0CISO \u683C\u5F0F\u5982 2026-08-01T00:00:00\uFF08\u53EF\u9009\uFF09"},endTime:{type:"string",description:"\u7ED3\u675F\u65F6\u95F4\uFF0CISO \u683C\u5F0F\u5982 2026-08-02T00:00:00\uFF08\u53EF\u9009\uFF09"},page:{type:"number",description:"\u9875\u7801\uFF0C\u9ED8\u8BA4 1"},pageSize:{type:"number",description:"\u6BCF\u9875\u6761\u6570\uFF0C\u9ED8\u8BA4 20"}},required:[]}},V=new Set(["create_memory","read_memory","update_memory","delete_memory","search_memory","list_memories","get_memory_stats","list_memories_by_file","memory_recurrence","memory_recurrence_complete"]),C={name:"launch_config_list",description:"\u67E5\u8BE2\u5F53\u524D Agent \u6240\u5C5E\u9879\u76EE\u4E0B\u7684\u542F\u52A8\u9879\uFF08\u7C7B IDEA Run Configuration\uFF09\u5217\u8868\u3002\u6BCF\u4E2A\u542F\u52A8\u9879\u542B id\u3001name\u3001type\uFF08generic/java/python/node/go/php\uFF09\u3001command\u3001cwd\u3001env\u3001jdkId\u3001groupId\u3001sortOrder\u3002\u67E5\u8BE2\u8303\u56F4\u81EA\u52A8\u9650\u5B9A\u4E3A\u5F53\u524D\u9879\u76EE\uFF0C\u65E0\u9700\u4F20 projectId\u3002",inputSchema:{type:"object",properties:{},required:[]}},P={name:"launch_config_create",description:"\u5728\u5F53\u524D Agent \u6240\u5C5E\u9879\u76EE\u4E0B\u65B0\u5EFA\u542F\u52A8\u9879\uFF08\u7C7B IDEA Run Configuration\uFF09\u3002\u521B\u5EFA\u524D\u5EFA\u8BAE\u5148 launch_config_list \u67E5\u770B\u73B0\u6709\u914D\u7F6E\u4E0E\u547D\u540D\u4E60\u60EF\u3002\u9879\u76EE\u8303\u56F4\u81EA\u52A8\u63A8\u5BFC\uFF0C\u65E0\u9700\u4F20 projectId\u3002\u521B\u5EFA\u6210\u529F\u540E\u8FD4\u56DE\u65B0\u542F\u52A8\u9879\u5B8C\u6574\u4FE1\u606F\uFF08\u542B id\uFF09\u3002",inputSchema:{type:"object",properties:{name:{type:"string",description:"\u542F\u52A8\u9879\u540D\u79F0\uFF08\u5FC5\u586B\uFF0C\u9879\u76EE\u5185\u552F\u4E00\uFF0C\u2264128 \u5B57\u7B26\uFF09"},type:{type:"string",description:"\u542F\u52A8\u9879\u7C7B\u578B\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4 generic\uFF09\uFF1Ageneric / java / python / node / go / php",enum:["generic","java","python","node","go","php"]},command:{type:"string",description:"\u542F\u52A8\u547D\u4EE4\uFF08\u5FC5\u586B\uFF0C\u22648192 \u5B57\u7B26\uFF09\u3002\u652F\u6301\u5360\u4F4D\u7B26 ${WORKSPACE}\uFF08\u9879\u76EE\u5DE5\u4F5C\u533A\uFF09\u3001${JAVA_HOME}\uFF08\u6240\u9009 JDK\uFF09\u3001${VAR}\uFF08env \u4E2D\u5B9A\u4E49\u7684\u53D8\u91CF\uFF09\u3002\u793A\u4F8B\uFF1Anpm run dev\u3001python main.py\u3001mvn spring-boot:run"},cwd:{type:"string",description:"\u5DE5\u4F5C\u76EE\u5F55\uFF08\u5FC5\u586B\uFF0C\u2264512 \u5B57\u7B26\uFF09\u2014\u2014\u9879\u76EE\u5B9E\u9645\u4EE3\u7801/\u6784\u5EFA\u76EE\u5F55\u7684\u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u5982 D:/code/xxx/backend"},env:{type:"object",description:"\u989D\u5916\u73AF\u5883\u53D8\u91CF\uFF08\u53EF\u9009\uFF0C\u226464 \u9879\uFF09\uFF0C\u989D\u5916\u5C5E\u6027\uFF1A\u5B57\u7B26\u4E32\u503C",additionalProperties:{type:"string"}},jdkId:{type:"string",description:"\u9009\u4E2D\u7684 JDK ID\uFF08type=java \u65F6\u6709\u6548\uFF0C\u53EF\u9009\uFF09"},groupId:{type:"string",description:"\u6240\u5C5E\u542F\u52A8\u9879\u5206\u7EC4 ID\uFF08\u53EF\u9009\uFF0Cnull/\u7A7A=\u672A\u5206\u7EC4\uFF09"},sortOrder:{type:"number",description:"\u6392\u5E8F\u6743\u91CD\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4\u8FFD\u52A0\u5230\u6240\u5728\u5BB9\u5668\u672B\u5C3E\uFF09"},readinessPattern:{type:"string",description:'\u5C31\u7EEA\u65E5\u5FD7\u6B63\u5219\uFF08\u53EF\u9009\uFF0C\u2264512 \u5B57\u7B26\uFF0CJS RegExp \u8BED\u6CD5\uFF09\u3002\u8BBE\u7F6E\u540E wait_timeout_ms \u7B49\u5F85\u7684 ready \u4FE1\u53F7\u6539\u4E3A"\u8F93\u51FA\u884C\u547D\u4E2D\u8BE5\u6B63\u5219"\uFF08\u9002\u914D\u4E0D\u76D1\u542C\u7AEF\u53E3\u7684\u5E38\u9A7B\u8FDB\u7A0B\uFF0C\u5982 worker/\u6D88\u8D39\u8005\uFF09\u3002\u793A\u4F8B\uFF1A^Server ready|^Build (SUCCESS|successful)\u3002\u7559\u7A7A=\u7AEF\u53E3\u76D1\u542C\u63A2\u6D4B'}},required:["name","command","cwd"]}},j={name:"launch_config_update",description:"\u66F4\u65B0\u542F\u52A8\u9879\uFF08\u540D\u79F0/\u7C7B\u578B/\u547D\u4EE4/\u5DE5\u4F5C\u76EE\u5F55/\u73AF\u5883\u53D8\u91CF/JDK/\u5206\u7EC4/\u6392\u5E8F\uFF09\u3002\u672A\u4F20\u5B57\u6BB5\u4FDD\u6301\u539F\u503C\uFF1B\u4FEE\u6539\u540D\u79F0\u65F6\u9879\u76EE\u5185\u4E0D\u80FD\u91CD\u540D\u3002\u76EE\u6807\u542F\u52A8\u9879\u5FC5\u987B\u5C5E\u4E8E\u5F53\u524D\u9879\u76EE\uFF08\u670D\u52A1\u7AEF\u6821\u9A8C\uFF09\u3002\u8FD0\u884C\u4E2D\u7684\u542F\u52A8\u9879\uFF1A\u4FEE\u6539\u914D\u7F6E\u4E0D\u4F1A\u5F71\u54CD\u5DF2\u8FD0\u884C\u8FDB\u7A0B\uFF0C\u9700\u91CD\u542F\u540E\u751F\u6548\u3002",inputSchema:{type:"object",properties:{configId:{type:"string",description:"\u542F\u52A8\u9879 ID\uFF08\u5FC5\u586B\uFF09"},name:{type:"string",description:"\u542F\u52A8\u9879\u540D\u79F0\uFF08\u53EF\u9009\uFF0C\u2264128 \u5B57\u7B26\uFF09"},type:{type:"string",description:"\u542F\u52A8\u9879\u7C7B\u578B\uFF08\u53EF\u9009\uFF09\uFF1Ageneric / java / python / node / go / php",enum:["generic","java","python","node","go","php"]},command:{type:"string",description:"\u542F\u52A8\u547D\u4EE4\uFF08\u53EF\u9009\uFF0C\u22648192 \u5B57\u7B26\uFF09"},cwd:{type:"string",description:"\u5DE5\u4F5C\u76EE\u5F55\uFF08\u53EF\u9009\uFF09"},env:{type:"object",description:"\u989D\u5916\u73AF\u5883\u53D8\u91CF\uFF08\u53EF\u9009\uFF0C\u6574\u4F53\u8986\u76D6\u539F env\uFF09",additionalProperties:{type:"string"}},jdkId:{type:"string",description:"\u9009\u4E2D\u7684 JDK ID\uFF08type=java \u65F6\u6709\u6548\uFF0C\u53EF\u9009\uFF09"},groupId:{type:"string",description:"\u6240\u5C5E\u542F\u52A8\u9879\u5206\u7EC4 ID\uFF08\u53EF\u9009\uFF09"},clearGroupId:{type:"boolean",description:"\u663E\u5F0F\u6E05\u9664\u5206\u7EC4\uFF08\u79FB\u56DE\u9ED8\u8BA4\u5206\u7EC4\uFF0C\u53EF\u9009\uFF1B\u4E0D\u80FD\u4E0E groupId \u540C\u65F6\u4F20\uFF09"},sortOrder:{type:"number",description:"\u6392\u5E8F\u6743\u91CD\uFF08\u53EF\u9009\uFF09"},readinessPattern:{type:"string",description:"\u5C31\u7EEA\u65E5\u5FD7\u6B63\u5219\uFF08\u53EF\u9009\uFF0CJS RegExp \u8BED\u6CD5\uFF09\uFF1A\u8BBE\u7F6E\u540E\u542F\u52A8\u7B49\u5F85\u7684 ready \u4FE1\u53F7\u4E3A\u8F93\u51FA\u884C\u547D\u4E2D\u6B63\u5219\uFF08\u9002\u914D\u4E0D\u76D1\u542C\u7AEF\u53E3\u7684\u8FDB\u7A0B\uFF09\u3002\u7559\u7A7A=\u7AEF\u53E3\u76D1\u542C\u63A2\u6D4B"},clearReadinessPattern:{type:"boolean",description:"\u663E\u5F0F\u6E05\u9664\u5C31\u7EEA\u6B63\u5219\uFF0C\u6062\u590D\u7AEF\u53E3\u63A2\u6D4B\uFF08\u53EF\u9009\uFF1B\u4E0D\u80FD\u4E0E readinessPattern \u540C\u65F6\u4F20\uFF09"}},required:["configId"]}},x={name:"launch_config_delete",description:"\u5220\u9664\u542F\u52A8\u9879\u914D\u7F6E\u3002\u76EE\u6807\u542F\u52A8\u9879\u5FC5\u987B\u5C5E\u4E8E\u5F53\u524D\u9879\u76EE\uFF08\u670D\u52A1\u7AEF\u6821\u9A8C\uFF09\u3002\u6CE8\u610F\uFF1A\u82E5\u8BE5\u542F\u52A8\u9879\u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u5148 launch_config_stop \u505C\u6B62\u8FDB\u7A0B\u518D\u5220\u9664\uFF08\u5220\u9664\u914D\u7F6E\u4E0D\u4F1A\u81EA\u52A8\u505C\u6B62\u5DF2\u8FD0\u884C\u8FDB\u7A0B\uFF09\u3002",inputSchema:{type:"object",properties:{configId:{type:"string",description:"\u542F\u52A8\u9879 ID\uFF08\u5FC5\u586B\uFF09"}},required:["configId"]}},k={name:"launch_config_start",description:"\u542F\u52A8\u542F\u52A8\u9879\uFF0C\u5728\u8C03\u7528\u8005\u6240\u5728 runtime-bridge \u673A\u5668\u4E0A\u62C9\u8D77\u8FDB\u7A0B\u3002\u652F\u6301\u5355\u9879\uFF08configId\uFF09\u4E0E\u6279\u91CF\uFF08configIds \u6570\u7EC4\uFF0C\u4E00\u6B21\u5E76\u884C\u62C9\u8D77\u591A\u4E2A\uFF09\uFF1A\u6279\u91CF\u65F6\u9010\u9879\u4EE5\u914D\u7F6E\u4E3A\u51C6\u5E76\u884C\u542F\u52A8\uFF0C\u5355\u9879\u5931\u8D25\u4E0D\u5F71\u54CD\u5176\u4F59\u9879\uFF0C\u8FD4\u56DE\u9010\u9879\u7ED3\u679C\u4E0E\u6C47\u603B\uFF08ready/exited/timeout/failed \u8BA1\u6570\uFF09\uFF1B\u5EFA\u8BAE\u542F\u52A8\u524D\u5148 launch_config_status \u786E\u8BA4\u672A\u5728\u8FD0\u884C\u3002\u9ED8\u8BA4\u4E0D\u7B49\u5F85\u7ACB\u5373\u8FD4\u56DE\uFF1B\u4F20 wait_timeout_ms > 0 \u65F6\u963B\u585E\u7B49\u5F85\u542F\u52A8\u7ED3\u679C\uFF08\u5355\u9879\u8FD4\u56DE wait \u5B57\u6BB5\uFF0C\u6279\u91CF\u5BF9\u5168\u90E8\u6210\u529F\u9879\u5E76\u884C\u7B49\u5F85\u3001\u6574\u4F53\u8FD4\u56DE\u65F6\u95F4\u2248\u6700\u6162\u4E00\u9879\uFF09\u3002",inputSchema:{type:"object",properties:{configId:{type:"string",description:"\u542F\u52A8\u9879 ID\uFF08\u5355\u9879\u542F\u52A8\u65F6\u5FC5\u586B\uFF1B\u4E0E configIds \u4E8C\u9009\u4E00\uFF09"},configIds:{type:"array",items:{type:"string"},description:"\u6279\u91CF\u542F\u52A8\uFF1A\u542F\u52A8\u9879 ID \u6570\u7EC4\uFF081-20 \u4E2A\uFF0C\u81EA\u52A8\u53BB\u91CD\uFF1B\u4E0E configId \u4E8C\u9009\u4E00\uFF0C\u4F20\u4E86\u4F18\u5148\u8D70\u6279\u91CF\uFF09\u3002\u6279\u91CF\u6A21\u5F0F\u4EE5\u5404\u9879\u914D\u7F6E\u4E3A\u51C6\u542F\u52A8\uFF0C\u5FFD\u7565 command/cwd/env/readinessPattern \u8986\u76D6\u53C2\u6570\uFF1BworkspacePath/jdkPath \u4E0E wait_timeout_ms \u5BF9\u5168\u90E8\u9879\u751F\u6548"},command:{type:"string",description:"\u542F\u52A8\u547D\u4EE4\u8986\u76D6\uFF08\u53EF\u9009\uFF0C\u4EC5\u5355\u9879\u6A21\u5F0F\uFF09"},cwd:{type:"string",description:"\u5DE5\u4F5C\u76EE\u5F55\u8986\u76D6\uFF08\u53EF\u9009\uFF0C\u4EC5\u5355\u9879\u6A21\u5F0F\uFF09"},env:{type:"object",description:"\u73AF\u5883\u53D8\u91CF\u8986\u76D6\uFF08\u53EF\u9009\uFF0C\u6574\u4F53\u8986\u76D6\u914D\u7F6E env\uFF1B\u4EC5\u5355\u9879\u6A21\u5F0F\uFF09",additionalProperties:{type:"string"}},jdkPath:{type:"string",description:"JDK \u8DEF\u5F84\uFF08type=java \u65F6\u6709\u6548\uFF0C\u53EF\u9009\uFF1B\u5355\u9879=\u8BE5\u9879\u8986\u76D6\uFF0C\u6279\u91CF=\u5168\u90E8\u9879\u751F\u6548\uFF09"},workspacePath:{type:"string",description:"\u9879\u76EE\u5DE5\u4F5C\u533A\u8DEF\u5F84\uFF08\u53EF\u9009\uFF1B\u5355\u9879=\u8BE5\u9879\u8986\u76D6\uFF0C\u6279\u91CF=\u5168\u90E8\u9879\u751F\u6548\uFF09"},readinessPattern:{type:"string",description:"\u5C31\u7EEA\u65E5\u5FD7\u6B63\u5219\u8986\u76D6\uFF08\u53EF\u9009\uFF0C\u4EC5\u5355\u9879\u6A21\u5F0F\uFF0CJS RegExp \u8BED\u6CD5\uFF09\uFF1A\u8BBE\u7F6E\u540E\u542F\u52A8\u7B49\u5F85\u7684 ready \u4FE1\u53F7\u4E3A\u8F93\u51FA\u884C\u547D\u4E2D\u6B63\u5219\uFF08\u9002\u914D\u4E0D\u76D1\u542C\u7AEF\u53E3\u7684\u8FDB\u7A0B\uFF09\u3002\u7559\u7A7A=\u4EE5\u542F\u52A8\u9879\u914D\u7F6E\u4E3A\u51C6\uFF08\u9ED8\u8BA4\u7AEF\u53E3\u76D1\u542C\u63A2\u6D4B\uFF09"},wait_timeout_ms:{type:"number",description:"\u963B\u585E\u7B49\u5F85\u542F\u52A8\u7ED3\u679C\u7684\u8D85\u65F6\u6BEB\u79D2\u6570\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4 0=\u4E0D\u7B49\u5F85\uFF0Cspawn \u540E\u7ACB\u5373\u8FD4\u56DE\uFF09\u3002>0 \u65F6\u672C\u6B21\u8C03\u7528\u963B\u585E\uFF0C\u76F4\u5230\u4EE5\u4E0B\u4FE1\u53F7\u6700\u5148\u5230\u8FBE\u5E76\u5728 wait \u5B57\u6BB5\u8FD4\u56DE\uFF1Aready=\u8FDB\u7A0B\u6811\u63A2\u6D4B\u5230\u76D1\u542C\u7AEF\u53E3\uFF08\u5E38\u9A7B\u670D\u52A1\u542F\u52A8\u6210\u529F\uFF0C\u9644 ports\uFF09\uFF0C\u6216\u8F93\u51FA\u884C\u547D\u4E2D\u5C31\u7EEA\u6B63\u5219\uFF08readinessPattern\uFF0C\u89C1\u4E0A\uFF09\uFF1Bexited=\u8FDB\u7A0B\u9000\u51FA\uFF08\u4E00\u6B21\u6027\u547D\u4EE4\u5B8C\u6210\u6216\u542F\u52A8\u5FEB\u901F\u5931\u8D25\uFF0CexitCode=0 \u4E3A\u6210\u529F\uFF0C\u975E 0 \u68C0\u67E5 logTail \u5B9A\u4F4D\u539F\u56E0\uFF09\uFF1Bstopped=\u7B49\u5F85\u671F\u95F4\u88AB\u505C\u6B62\uFF1Btimeout=\u8D85\u65F6\uFF0C\u8FDB\u7A0B\u4ECD\u5728\u8FD0\u884C\uFF08\u4E0D\u7B97\u9519\u8BEF\uFF0C\u6309 logTail \u81EA\u884C\u5224\u65AD\u6216\u7A0D\u540E launch_config_logs \u8F6E\u8BE2\uFF09\u3002\u4E0A\u9650 300000\uFF085 \u5206\u949F\uFF09\uFF0C\u6162\u542F\u52A8\u670D\u52A1\uFF08\u5982 Spring Boot\uFF09\u5EFA\u8BAE 60000-120000\u3002\u6279\u91CF\u6A21\u5F0F\u5BF9\u5168\u90E8\u6210\u529F\u9879\u5E76\u884C\u7B49\u5F85\uFF08\u6BCF\u9879\u72EC\u7ACB\u8BA1\u65F6\uFF09\u3002"}},required:[]}},q={name:"launch_config_restart",description:"\u91CD\u542F\u542F\u52A8\u9879\uFF08bridge \u5185\u539F\u5B50\u6267\u884C\u300C\u505C\u6B62\u65E7\u8FDB\u7A0B + \u91CD\u65B0\u62C9\u8D77\u300D\uFF0C\u4EE3\u7406\u5230\u8C03\u7528\u8005\u6240\u5728 runtime-bridge\uFF09\u3002\u76F8\u6BD4\u5148 launch_config_stop \u518D launch_config_start\uFF0C\u4E0D\u5B58\u5728 stop \u8BF7\u6C42\u4E22\u5931\u5BFC\u81F4 start \u649E\u4E0A\u4ECD\u5728\u8FD0\u884C\u65E7\u8FDB\u7A0B\u7684\u7ADE\u6001\u3002\u672A\u8FD0\u884C\u65F6\u7B49\u4EF7\u4E8E\u76F4\u63A5 start\u3002\u8986\u76D6\u53C2\u6570\uFF08command/cwd/env \u7B49\uFF09\u4E0E\u542F\u52A8\u7B49\u5F85\u8BED\u4E49\u540C launch_config_start\u3002",inputSchema:{type:"object",properties:{configId:{type:"string",description:"\u542F\u52A8\u9879 ID\uFF08\u5FC5\u586B\uFF09"},command:{type:"string",description:"\u542F\u52A8\u547D\u4EE4\u8986\u76D6\uFF08\u53EF\u9009\uFF09"},cwd:{type:"string",description:"\u5DE5\u4F5C\u76EE\u5F55\u8986\u76D6\uFF08\u53EF\u9009\uFF09"},env:{type:"object",description:"\u73AF\u5883\u53D8\u91CF\u8986\u76D6\uFF08\u53EF\u9009\uFF0C\u6574\u4F53\u8986\u76D6\u914D\u7F6E env\uFF09",additionalProperties:{type:"string"}},jdkPath:{type:"string",description:"JDK \u8DEF\u5F84\uFF08type=java \u65F6\u6709\u6548\uFF0C\u53EF\u9009\uFF09"},workspacePath:{type:"string",description:"\u9879\u76EE\u5DE5\u4F5C\u533A\u8DEF\u5F84\uFF08\u53EF\u9009\uFF09"},readinessPattern:{type:"string",description:"\u5C31\u7EEA\u65E5\u5FD7\u6B63\u5219\u8986\u76D6\uFF08\u53EF\u9009\uFF0CJS RegExp \u8BED\u6CD5\uFF09\uFF1A\u8BBE\u7F6E\u540E\u65B0\u8FDB\u7A0B\u542F\u52A8\u7B49\u5F85\u7684 ready \u4FE1\u53F7\u4E3A\u8F93\u51FA\u884C\u547D\u4E2D\u6B63\u5219\u3002\u7559\u7A7A=\u4EE5\u542F\u52A8\u9879\u914D\u7F6E\u4E3A\u51C6\uFF08\u9ED8\u8BA4\u7AEF\u53E3\u76D1\u542C\u63A2\u6D4B\uFF09"},wait_timeout_ms:{type:"number",description:"\u963B\u585E\u7B49\u5F85\u65B0\u8FDB\u7A0B\u542F\u52A8\u7ED3\u679C\u7684\u8D85\u65F6\u6BEB\u79D2\u6570\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4 0=\u4E0D\u7B49\u5F85\uFF09\u3002\u8BED\u4E49\u540C launch_config_start\uFF1Aready=\u7AEF\u53E3\u5C31\u7EEA\u6216\u65E5\u5FD7\u547D\u4E2D\u5C31\u7EEA\u6B63\u5219 / exited=\u8FDB\u7A0B\u9000\u51FA / timeout=\u8D85\u65F6\uFF08\u8FDB\u7A0B\u4ECD\u5728\u8FD0\u884C\uFF0C\u975E\u9519\u8BEF\uFF09\u3002"}},required:["configId"]}},U={name:"launch_config_stop",description:"\u505C\u6B62\u542F\u52A8\u9879\u8FDB\u7A0B\uFF08\u542B\u8FDB\u7A0B\u6811\uFF0C\u4EE3\u7406\u5230\u8C03\u7528\u8005\u6240\u5728 runtime-bridge\uFF09\u3002\u76EE\u6807\u542F\u52A8\u9879\u5FC5\u987B\u5C5E\u4E8E\u5F53\u524D\u9879\u76EE\uFF08\u670D\u52A1\u7AEF\u6821\u9A8C\uFF09\u3002\u82E5\u8FDB\u7A0B\u5DF2\u9000\u51FA\uFF0C\u8FD4\u56DE\u5DF2\u505C\u6B62/\u65E0\u8FD0\u884C\u8FDB\u7A0B\u7684\u72B6\u6001\uFF0C\u4E0D\u62A5\u9519\u3002",inputSchema:{type:"object",properties:{configId:{type:"string",description:"\u542F\u52A8\u9879 ID\uFF08\u5FC5\u586B\uFF09"}},required:["configId"]}},G={name:"launch_config_logs",description:"\u589E\u91CF\u62C9\u53D6\u542F\u52A8\u9879\u8FD0\u884C\u65E5\u5FD7\uFF08\u6700\u8FD1 200 \u6761\u73AF\u5F62\u7F13\u51B2\uFF0C\u4EE3\u7406\u5230\u8C03\u7528\u8005\u6240\u5728 runtime-bridge\uFF09\u3002\u9996\u6B21\u8C03\u7528\u4E0D\u4F20 since \u83B7\u53D6\u5168\u90E8\u7F13\u51B2\u65E5\u5FD7\uFF1B\u540E\u7EED\u6BCF\u6B21\u628A\u8FD4\u56DE\u7684 nextSince \u4F5C\u4E3A since \u7EED\u62C9\u589E\u91CF\u3002\u8FD4\u56DE\u5B57\u6BB5\uFF1Alines\uFF08\u65E5\u5FD7\u884C\uFF09\u3001nextSince\uFF08\u4E0B\u6B21\u6E38\u6807\uFF09\u3001running\uFF08\u8FDB\u7A0B\u662F\u5426\u8FD0\u884C\u4E2D\uFF09\u3002\u76EE\u6807\u542F\u52A8\u9879\u5FC5\u987B\u5C5E\u4E8E\u5F53\u524D\u9879\u76EE\uFF08\u670D\u52A1\u7AEF\u6821\u9A8C\uFF09\u3002",inputSchema:{type:"object",properties:{configId:{type:"string",description:"\u542F\u52A8\u9879 ID\uFF08\u5FC5\u586B\uFF09"},since:{type:"number",description:"\u65E5\u5FD7\u6E38\u6807\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4 0 = \u4ECE\u5934\u62C9\u53D6\uFF09"}},required:["configId"]}},w={name:"launch_config_status",description:"\u67E5\u8BE2\u8C03\u7528\u8005\u6240\u5728 bridge \u673A\u5668\u4E0A\u5F53\u524D\u9879\u76EE\u7684\u5168\u90E8\u542F\u52A8\u9879\u8FD0\u884C\u72B6\u6001\u3002\u8FD4\u56DE runs \u6570\u7EC4\uFF1A\u6BCF\u9879\u542B configId\u3001status\uFF08running/exited/stopped\uFF09\u3001pid\u3001startTime\u3001command \u7B49\u3002\u4EC5\u8FD4\u56DE\u5F53\u524D\u9879\u76EE\u914D\u7F6E\u7684\u542F\u52A8\u9879\uFF08\u670D\u52A1\u7AEF\u6309\u9879\u76EE\u8FC7\u6EE4\uFF09\u3002",inputSchema:{type:"object",properties:{},required:[]}},W=new Set(["launch_config_list","launch_config_create","launch_config_update","launch_config_delete","launch_config_start","launch_config_restart","launch_config_stop","launch_config_logs","launch_config_status"]),z=new Set(["hire_colleague"]),v={name:"create_meeting",description:"\u521B\u5EFA\u65B0\u4F1A\u8BAE\u5E76\u9080\u8BF7\u6307\u5B9A\u89D2\u8272\uFF08\u542B Agent \u5B9E\u4F8B\uFF09\u3002\u6210\u5458\u5168\u90E8\u5230\u4F4D\u540E\u4F1A\u8BAE\u5F00\u59CB\uFF0C\u968F\u540E\u4F7F\u7528 meeting_speak \u53D1\u8A00 / poll_message \u7B49\u5F85\u5176\u5B83\u7528\u6237\u53D1\u8A00 / end_meeting \u7ED3\u675F\u4F1A\u8BAE\u3002\u963B\u585E\u578B\u5DE5\u5177\uFF1A\u5168\u5458\u5230\u4F4D\u6216\u7B49\u5F85\u8D85\u65F6\u540E\u624D\u8FD4\u56DE\u3002\u6301\u6709\u8FDB\u884C\u4E2D\u6D41\u7A0B\u4EFB\u52A1\u65F6\u540C\u6837\u53EF\u4EE5\u521B\u5EFA\u4F1A\u8BAE\uFF08\u4F8B\u5982\u4EFB\u52A1\u672C\u8EAB\u8981\u6C42\u5F00\u4F1A\u8BA8\u8BBA/\u534F\u8C03\u7684\u573A\u666F\uFF09\uFF0C\u4E0D\u4F1A\u88AB\u4EFB\u52A1\u62E6\u622A\uFF1B\u8FDB\u5165\u4F1A\u8BAE\u540E\u4EFB\u52A1\u63D0\u9192\u6682\u505C\uFF0C\u4F1A\u8BAE\u7ED3\u675F\u540E\u81EA\u52A8\u6062\u590D\u3002",inputSchema:{type:"object",properties:{topic:{type:"string",description:"\u4F1A\u8BAE\u4E3B\u9898\uFF08\u5FC5\u586B\uFF09"},description:{type:"string",description:"\u4F1A\u8BAE\u63CF\u8FF0\uFF08\u53EF\u9009\uFF09"},members:{type:"array",description:"\u53D7\u9080\u6210\u5458\uFF1A[{roleId, agentId?}, ...]\uFF0CagentId \u672A\u6307\u5B9A\u65F6\u670D\u52A1\u7AEF\u6309\u89D2\u8272\u81EA\u52A8\u9009\u53D6\u5B9E\u4F8B",items:{type:"object",properties:{roleId:{type:"string",description:"\u89D2\u8272 id\uFF08\u5FC5\u586B\uFF09"},agentId:{type:"string",description:"Agent \u5B9E\u4F8B id\uFF08\u53EF\u9009\uFF09"}},required:["roleId"]}},waitTimeoutMs:{type:"number",description:"\u7B49\u5F85\u5168\u5458\u5230\u4F4D\u7684\u8D85\u65F6\u65F6\u957F\uFF08\u6BEB\u79D2\uFF0C\u53EF\u9009\uFF0C\u9ED8\u8BA4/\u4E0A\u9650 270000\uFF09\u3002\u8D85\u65F6\u8FD4\u56DE WAITING \u72B6\u6001\u800C\u975E\u9519\u8BEF\uFF0C\u53EF\u7EE7\u7EED poll_message \u7B49\u5F85\u5168\u5458\u5230\u4F4D"}},required:["topic","members"]}},H={name:"leave_meeting",description:"\u9000\u51FA\u5F53\u524D\u52A0\u5165\u7684\u4F1A\u8BAE\u3002\u5DF2\u52A0\u5165\u6210\u5458\u6B63\u5F0F\u9000\u51FA\uFF1B\u672A\u52A0\u5165\u6210\u5458\u8C03\u7528\u89C6\u4E3A\u5A49\u62D2\u9080\u8BF7\u3002",inputSchema:{type:"object",properties:{meetingId:{type:"string",description:"\u4F1A\u8BAE ID\uFF08\u5FC5\u586B\uFF09"}},required:["meetingId"]}},Y={name:"end_meeting",description:"\u7ED3\u675F\u6307\u5B9A\u4F1A\u8BAE\uFF08\u4EC5\u4F1A\u8BAE\u521B\u5EFA\u8005\u53EF\u8C03\u7528\uFF09\u3002\u7ED3\u675F\u540E\u6210\u5458\u53EF\u4F7F\u7528 get_meeting_info \u67E5\u770B\u5386\u53F2\u53D1\u8A00\u3002",inputSchema:{type:"object",properties:{meetingId:{type:"string",description:"\u4F1A\u8BAE ID\uFF08\u5FC5\u586B\uFF09"}},required:["meetingId"]}},F={name:"meeting_speak",description:"\u5411\u6D3B\u8DC3\u4F1A\u8BAE\u53D1\u8A00\uFF08\u4EC5\u5DF2\u52A0\u5165\u4E14\u4F1A\u8BAE\u5DF2 STARTED \u7684\u6210\u5458\u53EF\u7528\uFF09\u3002\u53D1\u8A00\u5B9E\u65F6\u5E7F\u64AD\u7ED9\u6240\u6709\u53C2\u4F1A\u6210\u5458\u3002",inputSchema:{type:"object",properties:{meetingId:{type:"string",description:"\u4F1A\u8BAE ID\uFF08\u5FC5\u586B\uFF09"},content:{type:"string",description:"\u53D1\u8A00\u5185\u5BB9\uFF08\u5FC5\u586B\uFF09"}},required:["meetingId","content"]}},K={name:"get_meeting_info",description:"\u83B7\u53D6\u4F1A\u8BAE\u4FE1\u606F JSON\uFF1A\u4E3B\u9898/\u63CF\u8FF0/\u72B6\u6001/\u6210\u5458\u5217\u8868\uFF08\u521B\u5EFA\u4EBA\u6807\u6CE8 isCreator\uFF09/\u6700\u8FD1\u53D1\u8A00\u8BB0\u5F55\u3002\u53EF\u7528\u4E8E\u67E5\u770B\u81EA\u5DF1\u521B\u5EFA\u7684\u4F1A\u8BAE\u8FDB\u5EA6\u6216\u5DF2\u52A0\u5165\u4F1A\u8BAE\u7684\u8BE6\u60C5\u3002",inputSchema:{type:"object",properties:{meetingId:{type:"string",description:"\u4F1A\u8BAE ID\uFF08\u5FC5\u586B\uFF09"}},required:["meetingId"]}},J={name:"my_meetings",description:"\u67E5\u770B\u4E0E\u6211\u76F8\u5173\u7684\u4F1A\u8BAE\u5217\u8868\uFF08\u65E0\u9700 meetingId\uFF09\uFF1Aactive=\u5DF2\u52A0\u5165\u7684\u8FDB\u884C\u4E2D\u4F1A\u8BAE\uFF1Binvited=\u53D7\u9080\u5C1A\u672A\u52A0\u5165\u7684\u4F1A\u8BAE\u3002\u6BCF\u4E2A\u4F1A\u8BAE\u542B meetingId/\u4E3B\u9898/\u72B6\u6001/\u6210\u5458\u5230\u4F4D\u60C5\u51B5\uFF0C\u53EF\u5148\u7528\u672C\u5DE5\u5177\u83B7\u53D6 meetingId \u518D\u8C03\u7528 get_meeting_info\u3002\u52A0\u5165\u4F1A\u8BAE\u4E0D\u9700\u8981\u624B\u52A8\u5DE5\u5177\uFF1A\u53D7\u9080\u540E\u5C06\u5728 poll_message \u65F6\u81EA\u52A8\u52A0\u5165\u3002",inputSchema:{type:"object",properties:{},required:[]}},$=new Set(["create_meeting","leave_meeting","end_meeting","meeting_speak","get_meeting_info","my_meetings"]),Q=[g,_,m,y,u,E,O,I,l,T,A,S,h,L,R,b,D,e,r,o,t,p,n,i,s,c,a,d,M,N,f,C,P,j,x,k,q,U,G,w,v,H,Y,F,K,J];export{ce as ABANDON_MEMORY_UPDATE_TOOL,v as CREATE_MEETING_TOOL,ee as CREATE_MEMORY_TOOL,S as CREATE_TASK_INSTANCE_COMMENT_TOOL,te as DELETE_MEMORY_TOOL,Y as END_MEETING_TOOL,R as FINISH_TASK_ROLLBACK_TOOL,g as GET_COLLEAGUE_TOOL,M as GET_DEBUG_LOG_CONFIG_TOOL,l as GET_DM_HISTORY_TOOL,T as GET_GROUP_HISTORY_TOOL,_ as GET_GROUP_ROOMS_TOOL,K as GET_MEETING_INFO_TOOL,ie as GET_MEMORY_STATS_TOOL,I as GET_MESSAGE_TOOL,m as GET_PROFILE_TOOL,y as HIRE_COLLEAGUE_TOOL,z as HIRE_TOOL_NAMES,P as LAUNCH_CONFIG_CREATE_TOOL,x as LAUNCH_CONFIG_DELETE_TOOL,C as LAUNCH_CONFIG_LIST_TOOL,G as LAUNCH_CONFIG_LOGS_TOOL,q as LAUNCH_CONFIG_RESTART_TOOL,k as LAUNCH_CONFIG_START_TOOL,w as LAUNCH_CONFIG_STATUS_TOOL,U as LAUNCH_CONFIG_STOP_TOOL,W as LAUNCH_CONFIG_TOOL_NAMES,j as LAUNCH_CONFIG_UPDATE_TOOL,H as LEAVE_MEETING_TOOL,se as LIST_MEMORIES_BY_FILE_TOOL,ne as LIST_MEMORIES_TOOL,Q as MCP_TOOLS,F as MEETING_SPEAK_TOOL,$ as MEETING_TOOL_NAMES,de as MEMORY_RECURRENCE_COMPLETE_TOOL,ae as MEMORY_RECURRENCE_TOOL,V as MEMORY_TOOL_NAMES,J as MY_MEETINGS_TOOL,A as MY_TASK_TOOL,O as POLL_MESSAGE_TOOL,N as QUERY_DEBUG_LOGS_TOOL,f as QUERY_FILE_CHANGES_HISTORY_TOOL,re as READ_MEMORY_TOOL,b as REJECT_TASK_TOOL,pe as SEARCH_MEMORY_TOOL,u as SEND_GROUP_TOOL,E as SEND_PRIVATE_TOOL,L as START_TASK_ROLLBACK_TOOL,h as SUBMIT_TASK_RESULT_TOOL,D as TERMINATE_TASK_TOOL,oe as UPDATE_MEMORY_TOOL};
|
|
41
|
+
\u8FD4\u56DE\u5B57\u6BB5\uFF1Aid\u3001projectId\u3001roleName\u3001instanceName\u3001agentId\u3001operation\uFF08CREATE/UPDATE/DELETE\uFF09\u3001targetPath\u3001fullPath\u3001reason\u3001status\uFF08APPLIED/REVERTED/REVERT_FAILED\uFF09\u3001createdAt\u3001revertedAt\u3001revertedBy\u3002`,inputSchema:{type:"object",properties:{roleId:{type:"string",description:"\u89D2\u8272\u5B9A\u4E49 ID\uFF08\u53EF\u9009\uFF09"},agentId:{type:"string",description:"Agent \u5B9E\u4F8B ID\uFF08\u53EF\u9009\uFF1B\u4E0D\u4F20=\u67E5\u8BE2\u5F53\u524D\u9879\u76EE\u4E0B\u6240\u6709 Agent\uFF1B\u4F20\u5176\u5B83 Agent \u65F6\u670D\u52A1\u7AEF\u6821\u9A8C\u5176\u4E0E\u8C03\u7528\u8005\u540C\u9879\u76EE\uFF09"},fileName:{type:"string",description:"\u6587\u4EF6\u540D\uFF08\u53EF\u9009\uFF0C\u6309 basename \u6A21\u7CCA\u5339\u914D\uFF09"},filePath:{type:"string",description:"\u5DE5\u4F5C\u533A\u76F8\u5BF9\u8DEF\u5F84\uFF08\u53EF\u9009\uFF0C\u6309\u8D26\u672C\u8BB0\u5F55\u7684\u76F8\u5BF9\u8DEF\u5F84 targetPath \u5339\u914D\uFF0C\u542B\u76EE\u5F55\u524D\u7F00\u5339\u914D\uFF09\u3002\u652F\u6301 ./xx\u3001xx\u3001@/xx\u3001/xx \u7B49\u4EF7\u5199\u6CD5\uFF08@ \u89C6\u4E3A\u5DE5\u4F5C\u533A\u6839\u8DEF\u5F84\u522B\u540D\uFF09\u3002\u793A\u4F8B\uFF1A@/src/main.ts \u7CBE\u786E\u5339\u914D src/main.ts\uFF1B@/src \u5339\u914D src/ \u76EE\u5F55\u53CA\u5176\u4E0B\u6240\u6709\u6587\u4EF6\u7684\u53D8\u66F4\u3002\u4E0E fileName \u6B63\u4EA4\uFF1AfileName \u6309\u6587\u4EF6\u540D\u6A21\u7CCA\uFF0CfilePath \u6309\u76F8\u5BF9\u8DEF\u5F84\u5339\u914D\u3002"},operation:{type:"string",description:"\u64CD\u4F5C\u7C7B\u578B\uFF1ACREATE / UPDATE / DELETE\uFF08\u53EF\u9009\uFF09",enum:["CREATE","UPDATE","DELETE"]},status:{type:"string",description:"\u8BB0\u5F55\u72B6\u6001\uFF1AAPPLIED\uFF08\u5DF2\u751F\u6548\uFF09/ REVERTED\uFF08\u5DF2\u64A4\u9500\uFF09/ REVERT_FAILED\uFF08\u64A4\u9500\u5931\u8D25\uFF09\uFF08\u53EF\u9009\uFF09",enum:["APPLIED","REVERTED","REVERT_FAILED"]},taskInstanceId:{type:"string",description:"\u4EFB\u52A1\u5B9E\u4F8B ID\uFF08\u53EF\u9009\uFF09"},startTime:{type:"string",description:"\u8D77\u59CB\u65F6\u95F4\uFF0CISO \u683C\u5F0F\u5982 2026-08-01T00:00:00\uFF08\u53EF\u9009\uFF09"},endTime:{type:"string",description:"\u7ED3\u675F\u65F6\u95F4\uFF0CISO \u683C\u5F0F\u5982 2026-08-02T00:00:00\uFF08\u53EF\u9009\uFF09"},page:{type:"number",description:"\u9875\u7801\uFF0C\u9ED8\u8BA4 1"},pageSize:{type:"number",description:"\u6BCF\u9875\u6761\u6570\uFF0C\u9ED8\u8BA4 20"}},required:[]}},V=new Set(["create_memory","read_memory","update_memory","delete_memory","search_memory","list_memories","get_memory_stats","list_memories_by_file","memory_recurrence","memory_recurrence_complete"]),C={name:"launch_config_list",description:"\u67E5\u8BE2\u5F53\u524D Agent \u6240\u5C5E\u9879\u76EE\u4E0B\u7684\u542F\u52A8\u9879\uFF08\u7C7B IDEA Run Configuration\uFF09\u5217\u8868\u3002\u6BCF\u4E2A\u542F\u52A8\u9879\u542B id\u3001name\u3001type\uFF08generic/java/python/node/go/php\uFF09\u3001command\u3001cwd\u3001env\u3001jdkId\u3001groupId\u3001sortOrder\u3002\u67E5\u8BE2\u8303\u56F4\u81EA\u52A8\u9650\u5B9A\u4E3A\u5F53\u524D\u9879\u76EE\uFF0C\u65E0\u9700\u4F20 projectId\u3002",inputSchema:{type:"object",properties:{},required:[]}},P={name:"launch_config_create",description:"\u5728\u5F53\u524D Agent \u6240\u5C5E\u9879\u76EE\u4E0B\u65B0\u5EFA\u542F\u52A8\u9879\uFF08\u7C7B IDEA Run Configuration\uFF09\u3002\u521B\u5EFA\u524D\u5EFA\u8BAE\u5148 launch_config_list \u67E5\u770B\u73B0\u6709\u914D\u7F6E\u4E0E\u547D\u540D\u4E60\u60EF\u3002\u9879\u76EE\u8303\u56F4\u81EA\u52A8\u63A8\u5BFC\uFF0C\u65E0\u9700\u4F20 projectId\u3002\u521B\u5EFA\u6210\u529F\u540E\u8FD4\u56DE\u65B0\u542F\u52A8\u9879\u5B8C\u6574\u4FE1\u606F\uFF08\u542B id\uFF09\u3002",inputSchema:{type:"object",properties:{name:{type:"string",description:"\u542F\u52A8\u9879\u540D\u79F0\uFF08\u5FC5\u586B\uFF0C\u9879\u76EE\u5185\u552F\u4E00\uFF0C\u2264128 \u5B57\u7B26\uFF09"},type:{type:"string",description:"\u542F\u52A8\u9879\u7C7B\u578B\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4 generic\uFF09\uFF1Ageneric / java / python / node / go / php",enum:["generic","java","python","node","go","php"]},command:{type:"string",description:"\u542F\u52A8\u547D\u4EE4\uFF08\u5FC5\u586B\uFF0C\u22648192 \u5B57\u7B26\uFF09\u3002\u652F\u6301\u5360\u4F4D\u7B26 ${WORKSPACE}\uFF08\u9879\u76EE\u5DE5\u4F5C\u533A\uFF09\u3001${JAVA_HOME}\uFF08\u6240\u9009 JDK\uFF09\u3001${VAR}\uFF08env \u4E2D\u5B9A\u4E49\u7684\u53D8\u91CF\uFF09\u3002\u793A\u4F8B\uFF1Anpm run dev\u3001python main.py\u3001mvn spring-boot:run"},cwd:{type:"string",description:"\u5DE5\u4F5C\u76EE\u5F55\uFF08\u5FC5\u586B\uFF0C\u2264512 \u5B57\u7B26\uFF09\u2014\u2014\u9879\u76EE\u5B9E\u9645\u4EE3\u7801/\u6784\u5EFA\u76EE\u5F55\u7684\u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u5982 D:/code/xxx/backend"},env:{type:"object",description:"\u989D\u5916\u73AF\u5883\u53D8\u91CF\uFF08\u53EF\u9009\uFF0C\u226464 \u9879\uFF09\uFF0C\u989D\u5916\u5C5E\u6027\uFF1A\u5B57\u7B26\u4E32\u503C",additionalProperties:{type:"string"}},jdkId:{type:"string",description:"\u9009\u4E2D\u7684 JDK ID\uFF08type=java \u65F6\u6709\u6548\uFF0C\u53EF\u9009\uFF09"},groupId:{type:"string",description:"\u6240\u5C5E\u542F\u52A8\u9879\u5206\u7EC4 ID\uFF08\u53EF\u9009\uFF0Cnull/\u7A7A=\u672A\u5206\u7EC4\uFF09"},sortOrder:{type:"number",description:"\u6392\u5E8F\u6743\u91CD\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4\u8FFD\u52A0\u5230\u6240\u5728\u5BB9\u5668\u672B\u5C3E\uFF09"},readinessPattern:{type:"string",description:'\u5C31\u7EEA\u65E5\u5FD7\u6B63\u5219\uFF08\u53EF\u9009\uFF0C\u2264512 \u5B57\u7B26\uFF0CJS RegExp \u8BED\u6CD5\uFF09\u3002\u8BBE\u7F6E\u540E wait_timeout_ms \u7B49\u5F85\u7684 ready \u4FE1\u53F7\u6539\u4E3A"\u8F93\u51FA\u884C\u547D\u4E2D\u8BE5\u6B63\u5219"\uFF08\u9002\u914D\u4E0D\u76D1\u542C\u7AEF\u53E3\u7684\u5E38\u9A7B\u8FDB\u7A0B\uFF0C\u5982 worker/\u6D88\u8D39\u8005\uFF09\u3002\u793A\u4F8B\uFF1A^Server ready|^Build (SUCCESS|successful)\u3002\u7559\u7A7A=\u7AEF\u53E3\u76D1\u542C\u63A2\u6D4B'}},required:["name","command","cwd"]}},j={name:"launch_config_update",description:"\u66F4\u65B0\u542F\u52A8\u9879\uFF08\u540D\u79F0/\u7C7B\u578B/\u547D\u4EE4/\u5DE5\u4F5C\u76EE\u5F55/\u73AF\u5883\u53D8\u91CF/JDK/\u5206\u7EC4/\u6392\u5E8F\uFF09\u3002\u672A\u4F20\u5B57\u6BB5\u4FDD\u6301\u539F\u503C\uFF1B\u4FEE\u6539\u540D\u79F0\u65F6\u9879\u76EE\u5185\u4E0D\u80FD\u91CD\u540D\u3002\u76EE\u6807\u542F\u52A8\u9879\u5FC5\u987B\u5C5E\u4E8E\u5F53\u524D\u9879\u76EE\uFF08\u670D\u52A1\u7AEF\u6821\u9A8C\uFF09\u3002\u8FD0\u884C\u4E2D\u7684\u542F\u52A8\u9879\uFF1A\u4FEE\u6539\u914D\u7F6E\u4E0D\u4F1A\u5F71\u54CD\u5DF2\u8FD0\u884C\u8FDB\u7A0B\uFF0C\u9700\u91CD\u542F\u540E\u751F\u6548\u3002",inputSchema:{type:"object",properties:{configId:{type:"string",description:"\u542F\u52A8\u9879 ID\uFF08\u5FC5\u586B\uFF09"},name:{type:"string",description:"\u542F\u52A8\u9879\u540D\u79F0\uFF08\u53EF\u9009\uFF0C\u2264128 \u5B57\u7B26\uFF09"},type:{type:"string",description:"\u542F\u52A8\u9879\u7C7B\u578B\uFF08\u53EF\u9009\uFF09\uFF1Ageneric / java / python / node / go / php",enum:["generic","java","python","node","go","php"]},command:{type:"string",description:"\u542F\u52A8\u547D\u4EE4\uFF08\u53EF\u9009\uFF0C\u22648192 \u5B57\u7B26\uFF09"},cwd:{type:"string",description:"\u5DE5\u4F5C\u76EE\u5F55\uFF08\u53EF\u9009\uFF09"},env:{type:"object",description:"\u989D\u5916\u73AF\u5883\u53D8\u91CF\uFF08\u53EF\u9009\uFF0C\u6574\u4F53\u8986\u76D6\u539F env\uFF09",additionalProperties:{type:"string"}},jdkId:{type:"string",description:"\u9009\u4E2D\u7684 JDK ID\uFF08type=java \u65F6\u6709\u6548\uFF0C\u53EF\u9009\uFF09"},groupId:{type:"string",description:"\u6240\u5C5E\u542F\u52A8\u9879\u5206\u7EC4 ID\uFF08\u53EF\u9009\uFF09"},clearGroupId:{type:"boolean",description:"\u663E\u5F0F\u6E05\u9664\u5206\u7EC4\uFF08\u79FB\u56DE\u9ED8\u8BA4\u5206\u7EC4\uFF0C\u53EF\u9009\uFF1B\u4E0D\u80FD\u4E0E groupId \u540C\u65F6\u4F20\uFF09"},sortOrder:{type:"number",description:"\u6392\u5E8F\u6743\u91CD\uFF08\u53EF\u9009\uFF09"},readinessPattern:{type:"string",description:"\u5C31\u7EEA\u65E5\u5FD7\u6B63\u5219\uFF08\u53EF\u9009\uFF0CJS RegExp \u8BED\u6CD5\uFF09\uFF1A\u8BBE\u7F6E\u540E\u542F\u52A8\u7B49\u5F85\u7684 ready \u4FE1\u53F7\u4E3A\u8F93\u51FA\u884C\u547D\u4E2D\u6B63\u5219\uFF08\u9002\u914D\u4E0D\u76D1\u542C\u7AEF\u53E3\u7684\u8FDB\u7A0B\uFF09\u3002\u7559\u7A7A=\u7AEF\u53E3\u76D1\u542C\u63A2\u6D4B"},clearReadinessPattern:{type:"boolean",description:"\u663E\u5F0F\u6E05\u9664\u5C31\u7EEA\u6B63\u5219\uFF0C\u6062\u590D\u7AEF\u53E3\u63A2\u6D4B\uFF08\u53EF\u9009\uFF1B\u4E0D\u80FD\u4E0E readinessPattern \u540C\u65F6\u4F20\uFF09"}},required:["configId"]}},x={name:"launch_config_delete",description:"\u5220\u9664\u542F\u52A8\u9879\u914D\u7F6E\u3002\u76EE\u6807\u542F\u52A8\u9879\u5FC5\u987B\u5C5E\u4E8E\u5F53\u524D\u9879\u76EE\uFF08\u670D\u52A1\u7AEF\u6821\u9A8C\uFF09\u3002\u6CE8\u610F\uFF1A\u82E5\u8BE5\u542F\u52A8\u9879\u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u5148 launch_config_stop \u505C\u6B62\u8FDB\u7A0B\u518D\u5220\u9664\uFF08\u5220\u9664\u914D\u7F6E\u4E0D\u4F1A\u81EA\u52A8\u505C\u6B62\u5DF2\u8FD0\u884C\u8FDB\u7A0B\uFF09\u3002",inputSchema:{type:"object",properties:{configId:{type:"string",description:"\u542F\u52A8\u9879 ID\uFF08\u5FC5\u586B\uFF09"}},required:["configId"]}},k={name:"launch_config_start",description:"\u542F\u52A8\u542F\u52A8\u9879\uFF0C\u5728\u8C03\u7528\u8005\u6240\u5728 runtime-bridge \u673A\u5668\u4E0A\u62C9\u8D77\u8FDB\u7A0B\u3002\u652F\u6301\u5355\u9879\uFF08configId\uFF09\u4E0E\u6279\u91CF\uFF08configIds \u6570\u7EC4\uFF0C\u4E00\u6B21\u5E76\u884C\u62C9\u8D77\u591A\u4E2A\uFF09\uFF1A\u6279\u91CF\u65F6\u9010\u9879\u4EE5\u914D\u7F6E\u4E3A\u51C6\u5E76\u884C\u542F\u52A8\uFF0C\u5355\u9879\u5931\u8D25\u4E0D\u5F71\u54CD\u5176\u4F59\u9879\uFF0C\u8FD4\u56DE\u9010\u9879\u7ED3\u679C\u4E0E\u6C47\u603B\uFF08ready/exited/timeout/failed/skipped \u8BA1\u6570\uFF09\u3002\u82E5\u542F\u52A8\u9879\u5DF2\u5904\u4E8E\u8FD0\u884C/\u6B63\u5728\u542F\u52A8\u72B6\u6001\uFF08\u672A\u9000\u51FA/\u505C\u6B62\uFF09\uFF0C\u8C03\u7528\u4F1A\u8FD4\u56DE skipped=true\uFF08\u9644 message\u300C\u5F53\u524D\u5DF2\u5904\u4E8E\u542F\u52A8/\u6B63\u5728\u542F\u52A8\u72B6\u6001\uFF0C\u8DF3\u8FC7\u300D\u4E0E\u5F53\u524D run\uFF09\u800C\u975E\u62A5\u9519\uFF0C\u4E0D\u4F1A\u91CD\u590D\u62C9\u8D77\uFF0C\u4E5F\u65E0\u9700\u5148 launch_config_status \u786E\u8BA4\u3002\u9ED8\u8BA4\u4E0D\u7B49\u5F85\u7ACB\u5373\u8FD4\u56DE\uFF1B\u4F20 wait_timeout_ms > 0 \u65F6\u963B\u585E\u7B49\u5F85\u542F\u52A8\u7ED3\u679C\uFF08\u5355\u9879\u8FD4\u56DE wait \u5B57\u6BB5\uFF0C\u6279\u91CF\u5BF9\u6210\u529F\u62C9\u8D77\u9879\u5E76\u884C\u7B49\u5F85\u3001\u6574\u4F53\u8FD4\u56DE\u65F6\u95F4\u2248\u6700\u6162\u4E00\u9879\uFF1B\u88AB\u8DF3\u8FC7\u7684\u9879\u4E0D\u53C2\u4E0E\u7B49\u5F85\uFF09\u3002",inputSchema:{type:"object",properties:{configId:{type:"string",description:"\u542F\u52A8\u9879 ID\uFF08\u5355\u9879\u542F\u52A8\u65F6\u5FC5\u586B\uFF1B\u4E0E configIds \u4E8C\u9009\u4E00\uFF09"},configIds:{type:"array",items:{type:"string"},description:"\u6279\u91CF\u542F\u52A8\uFF1A\u542F\u52A8\u9879 ID \u6570\u7EC4\uFF081-20 \u4E2A\uFF0C\u81EA\u52A8\u53BB\u91CD\uFF1B\u4E0E configId \u4E8C\u9009\u4E00\uFF0C\u4F20\u4E86\u4F18\u5148\u8D70\u6279\u91CF\uFF09\u3002\u6279\u91CF\u6A21\u5F0F\u4EE5\u5404\u9879\u914D\u7F6E\u4E3A\u51C6\u542F\u52A8\uFF0C\u5FFD\u7565 command/cwd/env/readinessPattern \u8986\u76D6\u53C2\u6570\uFF1BworkspacePath/jdkPath \u4E0E wait_timeout_ms \u5BF9\u5168\u90E8\u9879\u751F\u6548"},command:{type:"string",description:"\u542F\u52A8\u547D\u4EE4\u8986\u76D6\uFF08\u53EF\u9009\uFF0C\u4EC5\u5355\u9879\u6A21\u5F0F\uFF09"},cwd:{type:"string",description:"\u5DE5\u4F5C\u76EE\u5F55\u8986\u76D6\uFF08\u53EF\u9009\uFF0C\u4EC5\u5355\u9879\u6A21\u5F0F\uFF09"},env:{type:"object",description:"\u73AF\u5883\u53D8\u91CF\u8986\u76D6\uFF08\u53EF\u9009\uFF0C\u6574\u4F53\u8986\u76D6\u914D\u7F6E env\uFF1B\u4EC5\u5355\u9879\u6A21\u5F0F\uFF09",additionalProperties:{type:"string"}},jdkPath:{type:"string",description:"JDK \u8DEF\u5F84\uFF08type=java \u65F6\u6709\u6548\uFF0C\u53EF\u9009\uFF1B\u5355\u9879=\u8BE5\u9879\u8986\u76D6\uFF0C\u6279\u91CF=\u5168\u90E8\u9879\u751F\u6548\uFF09"},workspacePath:{type:"string",description:"\u9879\u76EE\u5DE5\u4F5C\u533A\u8DEF\u5F84\uFF08\u53EF\u9009\uFF1B\u5355\u9879=\u8BE5\u9879\u8986\u76D6\uFF0C\u6279\u91CF=\u5168\u90E8\u9879\u751F\u6548\uFF09"},readinessPattern:{type:"string",description:"\u5C31\u7EEA\u65E5\u5FD7\u6B63\u5219\u8986\u76D6\uFF08\u53EF\u9009\uFF0C\u4EC5\u5355\u9879\u6A21\u5F0F\uFF0CJS RegExp \u8BED\u6CD5\uFF09\uFF1A\u8BBE\u7F6E\u540E\u542F\u52A8\u7B49\u5F85\u7684 ready \u4FE1\u53F7\u4E3A\u8F93\u51FA\u884C\u547D\u4E2D\u6B63\u5219\uFF08\u9002\u914D\u4E0D\u76D1\u542C\u7AEF\u53E3\u7684\u8FDB\u7A0B\uFF09\u3002\u7559\u7A7A=\u4EE5\u542F\u52A8\u9879\u914D\u7F6E\u4E3A\u51C6\uFF08\u9ED8\u8BA4\u7AEF\u53E3\u76D1\u542C\u63A2\u6D4B\uFF09"},wait_timeout_ms:{type:"number",description:"\u963B\u585E\u7B49\u5F85\u542F\u52A8\u7ED3\u679C\u7684\u8D85\u65F6\u6BEB\u79D2\u6570\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4 0=\u4E0D\u7B49\u5F85\uFF0Cspawn \u540E\u7ACB\u5373\u8FD4\u56DE\uFF09\u3002>0 \u65F6\u672C\u6B21\u8C03\u7528\u963B\u585E\uFF0C\u76F4\u5230\u4EE5\u4E0B\u4FE1\u53F7\u6700\u5148\u5230\u8FBE\u5E76\u5728 wait \u5B57\u6BB5\u8FD4\u56DE\uFF1Aready=\u8FDB\u7A0B\u6811\u63A2\u6D4B\u5230\u76D1\u542C\u7AEF\u53E3\uFF08\u5E38\u9A7B\u670D\u52A1\u542F\u52A8\u6210\u529F\uFF0C\u9644 ports\uFF09\uFF0C\u6216\u8F93\u51FA\u884C\u547D\u4E2D\u5C31\u7EEA\u6B63\u5219\uFF08readinessPattern\uFF0C\u89C1\u4E0A\uFF09\uFF1Bexited=\u8FDB\u7A0B\u9000\u51FA\uFF08\u4E00\u6B21\u6027\u547D\u4EE4\u5B8C\u6210\u6216\u542F\u52A8\u5FEB\u901F\u5931\u8D25\uFF0CexitCode=0 \u4E3A\u6210\u529F\uFF0C\u975E 0 \u68C0\u67E5 logTail \u5B9A\u4F4D\u539F\u56E0\uFF09\uFF1Bstopped=\u7B49\u5F85\u671F\u95F4\u88AB\u505C\u6B62\uFF1Btimeout=\u8D85\u65F6\uFF0C\u8FDB\u7A0B\u4ECD\u5728\u8FD0\u884C\uFF08\u4E0D\u7B97\u9519\u8BEF\uFF0C\u6309 logTail \u81EA\u884C\u5224\u65AD\u6216\u7A0D\u540E launch_config_logs \u8F6E\u8BE2\uFF09\u3002\u4E0A\u9650 300000\uFF085 \u5206\u949F\uFF09\uFF0C\u6162\u542F\u52A8\u670D\u52A1\uFF08\u5982 Spring Boot\uFF09\u5EFA\u8BAE 60000-120000\u3002\u6279\u91CF\u6A21\u5F0F\u5BF9\u5168\u90E8\u6210\u529F\u9879\u5E76\u884C\u7B49\u5F85\uFF08\u6BCF\u9879\u72EC\u7ACB\u8BA1\u65F6\uFF09\u3002"}},required:[]}},q={name:"launch_config_restart",description:"\u91CD\u542F\u542F\u52A8\u9879\uFF08bridge \u5185\u539F\u5B50\u6267\u884C\u300C\u505C\u6B62\u65E7\u8FDB\u7A0B + \u91CD\u65B0\u62C9\u8D77\u300D\uFF0C\u4EE3\u7406\u5230\u8C03\u7528\u8005\u6240\u5728 runtime-bridge\uFF09\u3002\u76F8\u6BD4\u5148 launch_config_stop \u518D launch_config_start\uFF0C\u4E0D\u5B58\u5728 stop \u8BF7\u6C42\u4E22\u5931\u5BFC\u81F4 start \u649E\u4E0A\u4ECD\u5728\u8FD0\u884C\u65E7\u8FDB\u7A0B\u7684\u7ADE\u6001\u3002\u672A\u8FD0\u884C\u65F6\u7B49\u4EF7\u4E8E\u76F4\u63A5 start\u3002\u8986\u76D6\u53C2\u6570\uFF08command/cwd/env \u7B49\uFF09\u4E0E\u542F\u52A8\u7B49\u5F85\u8BED\u4E49\u540C launch_config_start\u3002",inputSchema:{type:"object",properties:{configId:{type:"string",description:"\u542F\u52A8\u9879 ID\uFF08\u5FC5\u586B\uFF09"},command:{type:"string",description:"\u542F\u52A8\u547D\u4EE4\u8986\u76D6\uFF08\u53EF\u9009\uFF09"},cwd:{type:"string",description:"\u5DE5\u4F5C\u76EE\u5F55\u8986\u76D6\uFF08\u53EF\u9009\uFF09"},env:{type:"object",description:"\u73AF\u5883\u53D8\u91CF\u8986\u76D6\uFF08\u53EF\u9009\uFF0C\u6574\u4F53\u8986\u76D6\u914D\u7F6E env\uFF09",additionalProperties:{type:"string"}},jdkPath:{type:"string",description:"JDK \u8DEF\u5F84\uFF08type=java \u65F6\u6709\u6548\uFF0C\u53EF\u9009\uFF09"},workspacePath:{type:"string",description:"\u9879\u76EE\u5DE5\u4F5C\u533A\u8DEF\u5F84\uFF08\u53EF\u9009\uFF09"},readinessPattern:{type:"string",description:"\u5C31\u7EEA\u65E5\u5FD7\u6B63\u5219\u8986\u76D6\uFF08\u53EF\u9009\uFF0CJS RegExp \u8BED\u6CD5\uFF09\uFF1A\u8BBE\u7F6E\u540E\u65B0\u8FDB\u7A0B\u542F\u52A8\u7B49\u5F85\u7684 ready \u4FE1\u53F7\u4E3A\u8F93\u51FA\u884C\u547D\u4E2D\u6B63\u5219\u3002\u7559\u7A7A=\u4EE5\u542F\u52A8\u9879\u914D\u7F6E\u4E3A\u51C6\uFF08\u9ED8\u8BA4\u7AEF\u53E3\u76D1\u542C\u63A2\u6D4B\uFF09"},wait_timeout_ms:{type:"number",description:"\u963B\u585E\u7B49\u5F85\u65B0\u8FDB\u7A0B\u542F\u52A8\u7ED3\u679C\u7684\u8D85\u65F6\u6BEB\u79D2\u6570\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4 0=\u4E0D\u7B49\u5F85\uFF09\u3002\u8BED\u4E49\u540C launch_config_start\uFF1Aready=\u7AEF\u53E3\u5C31\u7EEA\u6216\u65E5\u5FD7\u547D\u4E2D\u5C31\u7EEA\u6B63\u5219 / exited=\u8FDB\u7A0B\u9000\u51FA / timeout=\u8D85\u65F6\uFF08\u8FDB\u7A0B\u4ECD\u5728\u8FD0\u884C\uFF0C\u975E\u9519\u8BEF\uFF09\u3002"}},required:["configId"]}},U={name:"launch_config_stop",description:"\u505C\u6B62\u542F\u52A8\u9879\u8FDB\u7A0B\uFF08\u542B\u8FDB\u7A0B\u6811\uFF0C\u4EE3\u7406\u5230\u8C03\u7528\u8005\u6240\u5728 runtime-bridge\uFF09\u3002\u76EE\u6807\u542F\u52A8\u9879\u5FC5\u987B\u5C5E\u4E8E\u5F53\u524D\u9879\u76EE\uFF08\u670D\u52A1\u7AEF\u6821\u9A8C\uFF09\u3002\u82E5\u8FDB\u7A0B\u5DF2\u9000\u51FA\uFF0C\u8FD4\u56DE\u5DF2\u505C\u6B62/\u65E0\u8FD0\u884C\u8FDB\u7A0B\u7684\u72B6\u6001\uFF0C\u4E0D\u62A5\u9519\u3002",inputSchema:{type:"object",properties:{configId:{type:"string",description:"\u542F\u52A8\u9879 ID\uFF08\u5FC5\u586B\uFF09"}},required:["configId"]}},G={name:"launch_config_logs",description:"\u589E\u91CF\u62C9\u53D6\u542F\u52A8\u9879\u8FD0\u884C\u65E5\u5FD7\uFF08\u6700\u8FD1 200 \u6761\u73AF\u5F62\u7F13\u51B2\uFF0C\u4EE3\u7406\u5230\u8C03\u7528\u8005\u6240\u5728 runtime-bridge\uFF09\u3002\u9996\u6B21\u8C03\u7528\u4E0D\u4F20 since \u83B7\u53D6\u5168\u90E8\u7F13\u51B2\u65E5\u5FD7\uFF1B\u540E\u7EED\u6BCF\u6B21\u628A\u8FD4\u56DE\u7684 nextSince \u4F5C\u4E3A since \u7EED\u62C9\u589E\u91CF\u3002\u8FD4\u56DE\u5B57\u6BB5\uFF1Alines\uFF08\u65E5\u5FD7\u884C\uFF09\u3001nextSince\uFF08\u4E0B\u6B21\u6E38\u6807\uFF09\u3001running\uFF08\u8FDB\u7A0B\u662F\u5426\u8FD0\u884C\u4E2D\uFF09\u3002\u76EE\u6807\u542F\u52A8\u9879\u5FC5\u987B\u5C5E\u4E8E\u5F53\u524D\u9879\u76EE\uFF08\u670D\u52A1\u7AEF\u6821\u9A8C\uFF09\u3002",inputSchema:{type:"object",properties:{configId:{type:"string",description:"\u542F\u52A8\u9879 ID\uFF08\u5FC5\u586B\uFF09"},since:{type:"number",description:"\u65E5\u5FD7\u6E38\u6807\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4 0 = \u4ECE\u5934\u62C9\u53D6\uFF09"}},required:["configId"]}},w={name:"launch_config_status",description:"\u67E5\u8BE2\u8C03\u7528\u8005\u6240\u5728 bridge \u673A\u5668\u4E0A\u5F53\u524D\u9879\u76EE\u7684\u5168\u90E8\u542F\u52A8\u9879\u8FD0\u884C\u72B6\u6001\u3002\u8FD4\u56DE runs \u6570\u7EC4\uFF1A\u6BCF\u9879\u542B configId\u3001status\uFF08running/exited/stopped\uFF09\u3001pid\u3001startTime\u3001command \u7B49\u3002\u4EC5\u8FD4\u56DE\u5F53\u524D\u9879\u76EE\u914D\u7F6E\u7684\u542F\u52A8\u9879\uFF08\u670D\u52A1\u7AEF\u6309\u9879\u76EE\u8FC7\u6EE4\uFF09\u3002",inputSchema:{type:"object",properties:{},required:[]}},W=new Set(["launch_config_list","launch_config_create","launch_config_update","launch_config_delete","launch_config_start","launch_config_restart","launch_config_stop","launch_config_logs","launch_config_status"]),z=new Set(["hire_colleague"]),v={name:"create_meeting",description:"\u521B\u5EFA\u65B0\u4F1A\u8BAE\u5E76\u9080\u8BF7\u6307\u5B9A\u89D2\u8272\uFF08\u542B Agent \u5B9E\u4F8B\uFF09\u3002\u6210\u5458\u5168\u90E8\u5230\u4F4D\u540E\u4F1A\u8BAE\u5F00\u59CB\uFF0C\u968F\u540E\u4F7F\u7528 meeting_speak \u53D1\u8A00 / poll_message \u7B49\u5F85\u5176\u5B83\u7528\u6237\u53D1\u8A00 / end_meeting \u7ED3\u675F\u4F1A\u8BAE\u3002\u963B\u585E\u578B\u5DE5\u5177\uFF1A\u5168\u5458\u5230\u4F4D\u6216\u7B49\u5F85\u8D85\u65F6\u540E\u624D\u8FD4\u56DE\u3002\u6301\u6709\u8FDB\u884C\u4E2D\u6D41\u7A0B\u4EFB\u52A1\u65F6\u540C\u6837\u53EF\u4EE5\u521B\u5EFA\u4F1A\u8BAE\uFF08\u4F8B\u5982\u4EFB\u52A1\u672C\u8EAB\u8981\u6C42\u5F00\u4F1A\u8BA8\u8BBA/\u534F\u8C03\u7684\u573A\u666F\uFF09\uFF0C\u4E0D\u4F1A\u88AB\u4EFB\u52A1\u62E6\u622A\uFF1B\u8FDB\u5165\u4F1A\u8BAE\u540E\u4EFB\u52A1\u63D0\u9192\u6682\u505C\uFF0C\u4F1A\u8BAE\u7ED3\u675F\u540E\u81EA\u52A8\u6062\u590D\u3002",inputSchema:{type:"object",properties:{topic:{type:"string",description:"\u4F1A\u8BAE\u4E3B\u9898\uFF08\u5FC5\u586B\uFF09"},description:{type:"string",description:"\u4F1A\u8BAE\u63CF\u8FF0\uFF08\u53EF\u9009\uFF09"},members:{type:"array",description:"\u53D7\u9080\u6210\u5458\uFF1A[{roleId, agentId?}, ...]\uFF0CagentId \u672A\u6307\u5B9A\u65F6\u670D\u52A1\u7AEF\u6309\u89D2\u8272\u81EA\u52A8\u9009\u53D6\u5B9E\u4F8B",items:{type:"object",properties:{roleId:{type:"string",description:"\u89D2\u8272 id\uFF08\u5FC5\u586B\uFF09"},agentId:{type:"string",description:"Agent \u5B9E\u4F8B id\uFF08\u53EF\u9009\uFF09"}},required:["roleId"]}},waitTimeoutMs:{type:"number",description:"\u7B49\u5F85\u5168\u5458\u5230\u4F4D\u7684\u8D85\u65F6\u65F6\u957F\uFF08\u6BEB\u79D2\uFF0C\u53EF\u9009\uFF0C\u9ED8\u8BA4/\u4E0A\u9650 270000\uFF09\u3002\u8D85\u65F6\u8FD4\u56DE WAITING \u72B6\u6001\u800C\u975E\u9519\u8BEF\uFF0C\u53EF\u7EE7\u7EED poll_message \u7B49\u5F85\u5168\u5458\u5230\u4F4D"}},required:["topic","members"]}},H={name:"leave_meeting",description:"\u9000\u51FA\u5F53\u524D\u52A0\u5165\u7684\u4F1A\u8BAE\u3002\u5DF2\u52A0\u5165\u6210\u5458\u6B63\u5F0F\u9000\u51FA\uFF1B\u672A\u52A0\u5165\u6210\u5458\u8C03\u7528\u89C6\u4E3A\u5A49\u62D2\u9080\u8BF7\u3002",inputSchema:{type:"object",properties:{meetingId:{type:"string",description:"\u4F1A\u8BAE ID\uFF08\u5FC5\u586B\uFF09"}},required:["meetingId"]}},Y={name:"end_meeting",description:"\u7ED3\u675F\u6307\u5B9A\u4F1A\u8BAE\uFF08\u4EC5\u4F1A\u8BAE\u521B\u5EFA\u8005\u53EF\u8C03\u7528\uFF09\u3002\u7ED3\u675F\u540E\u6210\u5458\u53EF\u4F7F\u7528 get_meeting_info \u67E5\u770B\u5386\u53F2\u53D1\u8A00\u3002",inputSchema:{type:"object",properties:{meetingId:{type:"string",description:"\u4F1A\u8BAE ID\uFF08\u5FC5\u586B\uFF09"}},required:["meetingId"]}},F={name:"meeting_speak",description:"\u5411\u6D3B\u8DC3\u4F1A\u8BAE\u53D1\u8A00\uFF08\u4EC5\u5DF2\u52A0\u5165\u4E14\u4F1A\u8BAE\u5DF2 STARTED \u7684\u6210\u5458\u53EF\u7528\uFF09\u3002\u53D1\u8A00\u5B9E\u65F6\u5E7F\u64AD\u7ED9\u6240\u6709\u53C2\u4F1A\u6210\u5458\u3002",inputSchema:{type:"object",properties:{meetingId:{type:"string",description:"\u4F1A\u8BAE ID\uFF08\u5FC5\u586B\uFF09"},content:{type:"string",description:"\u53D1\u8A00\u5185\u5BB9\uFF08\u5FC5\u586B\uFF09"}},required:["meetingId","content"]}},K={name:"get_meeting_info",description:"\u83B7\u53D6\u4F1A\u8BAE\u4FE1\u606F JSON\uFF1A\u4E3B\u9898/\u63CF\u8FF0/\u72B6\u6001/\u6210\u5458\u5217\u8868\uFF08\u521B\u5EFA\u4EBA\u6807\u6CE8 isCreator\uFF09/\u6700\u8FD1\u53D1\u8A00\u8BB0\u5F55\u3002\u53EF\u7528\u4E8E\u67E5\u770B\u81EA\u5DF1\u521B\u5EFA\u7684\u4F1A\u8BAE\u8FDB\u5EA6\u6216\u5DF2\u52A0\u5165\u4F1A\u8BAE\u7684\u8BE6\u60C5\u3002",inputSchema:{type:"object",properties:{meetingId:{type:"string",description:"\u4F1A\u8BAE ID\uFF08\u5FC5\u586B\uFF09"}},required:["meetingId"]}},J={name:"my_meetings",description:"\u67E5\u770B\u4E0E\u6211\u76F8\u5173\u7684\u4F1A\u8BAE\u5217\u8868\uFF08\u65E0\u9700 meetingId\uFF09\uFF1Aactive=\u5DF2\u52A0\u5165\u7684\u8FDB\u884C\u4E2D\u4F1A\u8BAE\uFF1Binvited=\u53D7\u9080\u5C1A\u672A\u52A0\u5165\u7684\u4F1A\u8BAE\u3002\u6BCF\u4E2A\u4F1A\u8BAE\u542B meetingId/\u4E3B\u9898/\u72B6\u6001/\u6210\u5458\u5230\u4F4D\u60C5\u51B5\uFF0C\u53EF\u5148\u7528\u672C\u5DE5\u5177\u83B7\u53D6 meetingId \u518D\u8C03\u7528 get_meeting_info\u3002\u52A0\u5165\u4F1A\u8BAE\u4E0D\u9700\u8981\u624B\u52A8\u5DE5\u5177\uFF1A\u53D7\u9080\u540E\u5C06\u5728 poll_message \u65F6\u81EA\u52A8\u52A0\u5165\u3002",inputSchema:{type:"object",properties:{},required:[]}},$=new Set(["create_meeting","leave_meeting","end_meeting","meeting_speak","get_meeting_info","my_meetings"]),Q=[g,_,m,y,u,E,O,I,l,T,A,S,h,L,R,b,D,e,r,o,t,p,n,i,s,c,a,d,M,N,f,C,P,j,x,k,q,U,G,w,v,H,Y,F,K,J];export{ce as ABANDON_MEMORY_UPDATE_TOOL,v as CREATE_MEETING_TOOL,ee as CREATE_MEMORY_TOOL,S as CREATE_TASK_INSTANCE_COMMENT_TOOL,te as DELETE_MEMORY_TOOL,Y as END_MEETING_TOOL,R as FINISH_TASK_ROLLBACK_TOOL,g as GET_COLLEAGUE_TOOL,M as GET_DEBUG_LOG_CONFIG_TOOL,l as GET_DM_HISTORY_TOOL,T as GET_GROUP_HISTORY_TOOL,_ as GET_GROUP_ROOMS_TOOL,K as GET_MEETING_INFO_TOOL,ie as GET_MEMORY_STATS_TOOL,I as GET_MESSAGE_TOOL,m as GET_PROFILE_TOOL,y as HIRE_COLLEAGUE_TOOL,z as HIRE_TOOL_NAMES,P as LAUNCH_CONFIG_CREATE_TOOL,x as LAUNCH_CONFIG_DELETE_TOOL,C as LAUNCH_CONFIG_LIST_TOOL,G as LAUNCH_CONFIG_LOGS_TOOL,q as LAUNCH_CONFIG_RESTART_TOOL,k as LAUNCH_CONFIG_START_TOOL,w as LAUNCH_CONFIG_STATUS_TOOL,U as LAUNCH_CONFIG_STOP_TOOL,W as LAUNCH_CONFIG_TOOL_NAMES,j as LAUNCH_CONFIG_UPDATE_TOOL,H as LEAVE_MEETING_TOOL,se as LIST_MEMORIES_BY_FILE_TOOL,ne as LIST_MEMORIES_TOOL,Q as MCP_TOOLS,F as MEETING_SPEAK_TOOL,$ as MEETING_TOOL_NAMES,de as MEMORY_RECURRENCE_COMPLETE_TOOL,ae as MEMORY_RECURRENCE_TOOL,V as MEMORY_TOOL_NAMES,J as MY_MEETINGS_TOOL,A as MY_TASK_TOOL,O as POLL_MESSAGE_TOOL,N as QUERY_DEBUG_LOGS_TOOL,f as QUERY_FILE_CHANGES_HISTORY_TOOL,re as READ_MEMORY_TOOL,b as REJECT_TASK_TOOL,pe as SEARCH_MEMORY_TOOL,u as SEND_GROUP_TOOL,E as SEND_PRIVATE_TOOL,L as START_TASK_ROLLBACK_TOOL,h as SUBMIT_TASK_RESULT_TOOL,D as TERMINATE_TASK_TOOL,oe as UPDATE_MEMORY_TOOL};
|
|
42
42
|
|