aws-runtime-bridge 1.9.137 → 1.9.139

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.
Files changed (96) hide show
  1. package/dist/adapter/AcodeSdkAdapter.d.ts +2 -0
  2. package/dist/adapter/AcodeSdkAdapter.js +2 -2
  3. package/dist/adapter/ClaudeSdkAdapter.js +3 -3
  4. package/dist/adapter/CodexSdkAdapter.js +3 -3
  5. package/dist/adapter/OpencodeSdkAdapter.js +3 -3
  6. package/dist/browser/browser-pool.js +1 -1
  7. package/dist/browser/built-in-browser-tools.d.ts +1 -2
  8. package/dist/browser/built-in-browser-tools.js +1 -1
  9. package/dist/browser/ws-server.js +1 -1
  10. package/dist/config.js +2 -2
  11. package/dist/index.js +1 -1
  12. package/dist/middleware/auth.js +1 -1
  13. package/dist/remote-desktop/computer-control.d.ts +1 -1
  14. package/dist/remote-desktop/index.d.ts +1 -1
  15. package/dist/remote-desktop/index.js +2 -2
  16. package/dist/remote-desktop/session-manager.d.ts +2 -2
  17. package/dist/remote-desktop/session-manager.js +1 -1
  18. package/dist/remote-desktop/system-backend.js +3 -3
  19. package/dist/routes/ai-sources.js +1 -1
  20. package/dist/routes/background-tasks.js +1 -1
  21. package/dist/routes/browser-listeners.js +1 -1
  22. package/dist/routes/capabilities.js +1 -1
  23. package/dist/routes/dashboard.js +1 -1
  24. package/dist/routes/file-change-diff.js +3 -3
  25. package/dist/routes/file-diff-rollback.js +1 -1
  26. package/dist/routes/file-snapshot.js +1 -1
  27. package/dist/routes/git.js +1 -1
  28. package/dist/routes/instance.js +1 -1
  29. package/dist/routes/launch.js +1 -1
  30. package/dist/routes/mcp.js +1 -1
  31. package/dist/routes/plugins.js +1 -1
  32. package/dist/routes/properties.js +1 -1
  33. package/dist/routes/pty.d.ts +1 -1
  34. package/dist/routes/pty.js +1 -1
  35. package/dist/routes/runtime-binding.js +1 -1
  36. package/dist/routes/skills.js +1 -1
  37. package/dist/routes/sub-agents.js +1 -1
  38. package/dist/routes/task-context.js +1 -1
  39. package/dist/routes/terminal.js +5 -5
  40. package/dist/routes/yml.js +1 -1
  41. package/dist/services/access-control.js +1 -1
  42. package/dist/services/acode-bg-manager.js +1 -1
  43. package/dist/services/agent-capability-sync.js +1 -1
  44. package/dist/services/agent-process-manager.d.ts +1 -1
  45. package/dist/services/agent-process-manager.js +1 -1
  46. package/dist/services/ai-config-service.js +1 -1
  47. package/dist/services/ai-source-apply.d.ts +1 -1
  48. package/dist/services/auto-register.js +1 -1
  49. package/dist/services/bridge-package-publish-hooks.js +1 -1
  50. package/dist/services/browser-session-manager.d.ts +3 -3
  51. package/dist/services/browser-session-manager.js +1 -1
  52. package/dist/services/cli-commands.js +2 -2
  53. package/dist/services/desktop-mcp-manager.js +1 -1
  54. package/dist/services/fileSnapshotStore.js +1 -1
  55. package/dist/services/instance-ai-config-service.js +1 -1
  56. package/dist/services/instance-init-service.js +1 -1
  57. package/dist/services/jdk-scanner.js +1 -1
  58. package/dist/services/launch-manager.js +1 -1
  59. package/dist/services/lifecycle-state.js +2 -2
  60. package/dist/services/mcp-deploy.js +1 -1
  61. package/dist/services/orphan-monitor.js +1 -1
  62. package/dist/services/plugin-manager.d.ts +26 -4
  63. package/dist/services/plugin-manager.js +15 -9
  64. package/dist/services/process-detail.js +2 -2
  65. package/dist/services/process-detector.js +10 -10
  66. package/dist/services/process-registry.js +1 -1
  67. package/dist/services/process-top.js +2 -2
  68. package/dist/services/runtime-binding.js +4 -4
  69. package/dist/services/sdk-tool-file-change-recorder.js +1 -1
  70. package/dist/services/skill-manager.js +2 -2
  71. package/dist/services/startup-config-wizard.js +6 -6
  72. package/dist/services/system-metrics.js +1 -1
  73. package/dist/services/tunnel-client.js +1 -1
  74. package/dist/services/update-notifier.js +2 -2
  75. package/dist/services/windows-service-manager.js +1 -1
  76. package/dist/services/workspace-files.js +1 -1
  77. package/dist/services/workspaceTaskChangeWatcher.js +3 -3
  78. package/dist/utils/file-utils.js +2 -2
  79. package/dist/utils/instance-ai-config-debug-logger.js +1 -1
  80. package/dist/utils/mcp-utils.js +1 -1
  81. package/dist/utils/yaml-utils.js +1 -1
  82. package/package/acode/dist/plugin-tools.js +3 -8
  83. package/package/acode/dist/plugin-types.d.ts +10 -0
  84. package/package/acode/dist/runtime.d.ts +2 -0
  85. package/package/acode/dist/runtime.js +17 -17
  86. package/package/acode/dist/types.d.ts +2 -0
  87. package/package/aws-client-agent-mcp/dist/http-client.js +1 -1
  88. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +0 -1
  89. package/package/aws-client-agent-mcp/dist/mcp-server.js +10 -10
  90. package/package/aws-client-agent-mcp/dist/memory-tools.js +6 -6
  91. package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts +1 -1
  92. package/package/aws-client-agent-mcp/dist/server-memory-store.js +1 -1
  93. package/package/aws-client-agent-mcp/dist/status-reporter.d.ts +2 -0
  94. package/package/aws-client-agent-mcp/dist/status-reporter.js +3 -2
  95. package/package/aws-client-agent-mcp/dist/types.d.ts +1 -0
  96. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
- import m from"node:crypto";import o from"node:fs";import a from"node:path";import{getRuntimeHomeDir as y}from"../config.js";import{createLogger as B}from"../utils/logger.js";const p=B("runtime-binding"),b="sha256",T=v();function v(){const e=m.randomInt(0,1e6);return String(e).padStart(6,"0").replace(/(\d{3})(\d{3})/,"$1-$2")}function d(){return a.join(y(),".aws-bridge")}function g(){return a.join(d(),"binding.json")}function S(){return a.join(d(),"runtime-tokens.properties")}function x(e){return m.createHash(b).update(e,"utf8").digest("hex")}function $(e,t){const n=Buffer.from(e,"hex"),r=Buffer.from(t,"hex");return n.length!==r.length?!1:m.timingSafeEqual(n,r)}function H(e,t){const n=Buffer.from(e,"utf8"),r=Buffer.from(t,"utf8");return n.length!==r.length?!1:m.timingSafeEqual(n,r)}function f(e){return String(e||"").trim()}function I(e){return e.replace(/^((?:https?|wss?):\/\/(?:\[[^\]]+\]|[^/:?#]+):\d+):\d+(?=\/|$)/i,"$1")}function U(e){const t=e.toLowerCase();return t==="localhost"||t==="::1"||t==="[::1]"?"127.0.0.1":t}function u(e){const t=f(e);if(!t)return;const n=I(t);try{const r=new URL(n);return r.protocol==="ws:"?r.protocol="http:":r.protocol==="wss:"?r.protocol="https:":r.protocol=r.protocol.toLowerCase(),r.hostname=U(r.hostname),r.origin}catch{return n.replace(/\/+$/,"")}}function P(){return T}function q(){return g()}function _(){return S()}function N(e){const t=u(e)||String(e||"").trim();if(!t)return"";try{return new URL(t).hostname.toLowerCase()}catch{return t.replace(/^wss?:\/\//i,"").replace(/^https?:\/\//i,"").split("/")[0].split(":")[0].toLowerCase()}}function F(e){const t=u(e);if(t)return t;const n=String(e||"").trim();return n?n.replace(/\/+$/,"").toLowerCase():""}function w(e){const t=F(e);if(!t)throw new Error("serverBaseUrl is required to build runtime token key");return m.createHash("md5").update(t,"utf8").digest("hex")}function k(){const e=new Map;try{const t=o.readFileSync(S(),"utf8");for(const n of t.split(/\r?\n/)){const r=n.trim();if(!r||r.startsWith("#"))continue;const i=r.indexOf("=");if(i<=0)continue;const s=r.slice(0,i).trim(),c=r.slice(i+1).trim();s&&c&&e.set(s,c)}}catch{}return e}function R(e){o.mkdirSync(d(),{recursive:!0});const t=[...e.entries()].sort(([n],[r])=>n.localeCompare(r)).map(([n,r])=>`${n}=${r}`);o.writeFileSync(S(),`${t.join(`
1
+ import m from"node:crypto";import o from"node:fs";import u from"node:path";import{getRuntimeHomeDir as w}from"../config.js";import{createLogger as R}from"../utils/logger.js";const g=R("runtime-binding"),b="sha256",x=v();function v(){const e=m.randomInt(0,1e6);return String(e).padStart(6,"0").replace(/(\d{3})(\d{3})/,"$1-$2")}function a(){return u.join(w(),".aws-bridge")}function p(){return u.join(a(),"binding.json")}function S(){return u.join(a(),"runtime-tokens.properties")}function T(e){return m.createHash(b).update(e,"utf8").digest("hex")}function $(e,t){const n=Buffer.from(e,"hex"),r=Buffer.from(t,"hex");return n.length!==r.length?!1:m.timingSafeEqual(n,r)}function H(e,t){const n=Buffer.from(e,"utf8"),r=Buffer.from(t,"utf8");return n.length!==r.length?!1:m.timingSafeEqual(n,r)}function d(e){return String(e||"").trim()}function I(e){return e.replace(/^((?:https?|wss?):\/\/(?:\[[^\]]+\]|[^/:?#]+):\d+):\d+(?=\/|$)/i,"$1")}function U(e){const t=e.toLowerCase();return t==="localhost"||t==="::1"||t==="[::1]"?"127.0.0.1":t}function f(e){const t=d(e);if(!t)return;const n=I(t);try{const r=new URL(n);return r.protocol==="ws:"?r.protocol="http:":r.protocol==="wss:"?r.protocol="https:":r.protocol=r.protocol.toLowerCase(),r.hostname=U(r.hostname),r.origin}catch{return n.replace(/\/+$/,"")}}function z(){return x}function L(){return p()}function N(){return S()}function F(e){const t=f(e);if(t)return t;const n=String(e||"").trim();return n?n.replace(/\/+$/,"").toLowerCase():""}function y(e){const t=F(e);if(!t)throw new Error("serverBaseUrl is required to build runtime token key");return m.createHash("md5").update(t,"utf8").digest("hex")}function k(){const e=new Map;try{const t=o.readFileSync(S(),"utf8");for(const n of t.split(/\r?\n/)){const r=n.trim();if(!r||r.startsWith("#"))continue;const i=r.indexOf("=");if(i<=0)continue;const s=r.slice(0,i).trim(),c=r.slice(i+1).trim();s&&c&&e.set(s,c)}}catch{}return e}function B(e){o.mkdirSync(a(),{recursive:!0});const t=[...e.entries()].sort(([n],[r])=>n.localeCompare(r)).map(([n,r])=>`${n}=${r}`);o.writeFileSync(S(),`${t.join(`
2
2
  `)}
3
- `,{encoding:"utf8",mode:384})}function A(e){const t=f(e.accessToken);if(t.length<16)throw new Error("accessToken must be at least 16 characters");const n=w(e.serverBaseUrl),r=k();return r.set(n,t),R(r),n}function C(e){if(e)try{const t=w(e);return k().get(t)}catch{return}}function J(e){if(!e)return!1;try{const t=w(e),n=k(),r=n.delete(t);return r&&R(n),r}catch{return!1}}function O(e){if(!e)return!1;for(const t of k().values())if(H(e,t))return!0;return!1}function l(){try{const e=o.readFileSync(g(),"utf8"),t=JSON.parse(e);if(t?.status==="paired"&&t.tokenHash)return{...t,schedulerBaseUrl:u(t.schedulerBaseUrl)||t.schedulerBaseUrl}}catch{}return{status:"unpaired"}}function K(){const e=l(),{tokenHash:t,accessToken:n,...r}=e;return{...r,paired:e.status==="paired"}}function M(){const e=l();return e.status==="paired"&&!!e.tokenHash}function G(e){const t=f(e);if(!t)return!1;const n=l();return n.status==="paired"&&n.tokenHash&&$(x(t),n.tokenHash)?!0:O(t)}function W(e){const t=C(e);if(t)return t;const n=l();if(n.status==="paired"){if(e){const r=u(e),i=u(n.schedulerBaseUrl);return r&&i&&r===i&&f(n.accessToken)||void 0}return f(n.accessToken)||void 0}}function Q(e){return String(e||"").trim()===T}function V(e){const t=f(e.accessToken);if(t.length<16)throw new Error("accessToken must be at least 16 characters");const n=l(),r=u(e.schedulerBaseUrl)||u(n.schedulerBaseUrl),i=new Date().toISOString(),s={status:"paired",instanceId:e.instanceId?String(e.instanceId):n.instanceId,userId:e.userId?String(e.userId):n.userId,schedulerBaseUrl:r,accessToken:t,tokenHash:x(t),createdAt:n.createdAt||i,updatedAt:i};if(o.mkdirSync(d(),{recursive:!0}),o.writeFileSync(g(),`${JSON.stringify(s,null,2)}
4
- `,{encoding:"utf8",mode:384}),s.schedulerBaseUrl){const c=A({serverBaseUrl:s.schedulerBaseUrl,accessToken:t});p.info(`[runtime-bridge] scoped runtime token saved: key=${c}`)}return p.info(`[runtime-bridge] runtime binding saved: ${g()}`),s}function X(){const t={...l(),status:"unpaired",accessToken:void 0,tokenHash:void 0,revokedAt:new Date().toISOString(),updatedAt:new Date().toISOString()};o.mkdirSync(d(),{recursive:!0}),o.writeFileSync(g(),`${JSON.stringify(t,null,2)}
5
- `,{encoding:"utf8",mode:384}),p.info("[runtime-bridge] runtime binding cleared")}function Y(){const e=y(),t=a.join(e,".agentswork","runtime-bridge"),n=d();if(t===n||!o.existsSync(t))return;const r=["binding.json","runtime-tokens.properties"];let i=0;for(const s of r){const c=a.join(t,s),h=a.join(n,s);if(o.existsSync(c)&&!o.existsSync(h)){o.mkdirSync(n,{recursive:!0}),o.copyFileSync(c,h);try{o.chmodSync(h,384)}catch{}i++,p.info(`[runtime-bridge] \u5DF2\u8FC1\u79FB ${c} \u2192 ${h}`)}}i>0&&p.info(`[runtime-bridge] \u5DF2\u8FC1\u79FB ${i} \u4E2A\u914D\u7F6E\u6587\u4EF6\u4ECE ${t} \u5230 ${n}`)}export{w as buildRuntimeTokenKey,X as clearRuntimeBinding,J as clearScopedRuntimeAccessToken,W as getRuntimeAccessToken,q as getRuntimeBindingFilePath,K as getRuntimeBindingPublicState,P as getRuntimePairingCode,_ as getRuntimeTokenStoreFilePath,C as getScopedRuntimeAccessToken,M as hasRuntimeBinding,l as loadRuntimeBinding,Y as migrateOldBindingDir,u as normalizeSchedulerBaseUrl,V as saveRuntimeBinding,A as saveScopedRuntimeAccessToken,G as validateRuntimeBindingToken,Q as validateRuntimePairingCode};
3
+ `,{encoding:"utf8",mode:384})}function A(e){const t=d(e.accessToken);if(t.length<16)throw new Error("accessToken must be at least 16 characters");const n=y(e.serverBaseUrl),r=k();return r.set(n,t),B(r),n}function O(e){if(e)try{const t=y(e);return k().get(t)}catch{return}}function _(e){if(!e)return!1;try{const t=y(e),n=k(),r=n.delete(t);return r&&B(n),r}catch{return!1}}function j(e){if(!e)return!1;for(const t of k().values())if(H(e,t))return!0;return!1}function l(){try{const e=o.readFileSync(p(),"utf8"),t=JSON.parse(e);if(t?.status==="paired"&&t.tokenHash)return{...t,schedulerBaseUrl:f(t.schedulerBaseUrl)||t.schedulerBaseUrl}}catch{}return{status:"unpaired"}}function J(){const e=l(),t={...e};return delete t.tokenHash,delete t.accessToken,{...t,paired:e.status==="paired"}}function K(){const e=l();return e.status==="paired"&&!!e.tokenHash}function M(e){const t=d(e);if(!t)return!1;const n=l();return n.status==="paired"&&n.tokenHash&&$(T(t),n.tokenHash)?!0:j(t)}function G(e){const t=O(e);if(t)return t;const n=l();if(n.status==="paired"){if(e){const r=f(e),i=f(n.schedulerBaseUrl);return r&&i&&r===i&&d(n.accessToken)||void 0}return d(n.accessToken)||void 0}}function W(e){return String(e||"").trim()===x}function Q(e){const t=d(e.accessToken);if(t.length<16)throw new Error("accessToken must be at least 16 characters");const n=l(),r=f(e.schedulerBaseUrl)||f(n.schedulerBaseUrl),i=new Date().toISOString(),s={status:"paired",instanceId:e.instanceId?String(e.instanceId):n.instanceId,userId:e.userId?String(e.userId):n.userId,schedulerBaseUrl:r,accessToken:t,tokenHash:T(t),createdAt:n.createdAt||i,updatedAt:i};if(o.mkdirSync(a(),{recursive:!0}),o.writeFileSync(p(),`${JSON.stringify(s,null,2)}
4
+ `,{encoding:"utf8",mode:384}),s.schedulerBaseUrl){const c=A({serverBaseUrl:s.schedulerBaseUrl,accessToken:t});g.info(`[runtime-bridge] scoped runtime token saved: key=${c}`)}return g.info(`[runtime-bridge] runtime binding saved: ${p()}`),s}function V(){const t={...l(),status:"unpaired",accessToken:void 0,tokenHash:void 0,revokedAt:new Date().toISOString(),updatedAt:new Date().toISOString()};o.mkdirSync(a(),{recursive:!0}),o.writeFileSync(p(),`${JSON.stringify(t,null,2)}
5
+ `,{encoding:"utf8",mode:384}),g.info("[runtime-bridge] runtime binding cleared")}function X(){const e=w(),t=u.join(e,".agentswork","runtime-bridge"),n=a();if(t===n||!o.existsSync(t))return;const r=["binding.json","runtime-tokens.properties"];let i=0;for(const s of r){const c=u.join(t,s),h=u.join(n,s);if(o.existsSync(c)&&!o.existsSync(h)){o.mkdirSync(n,{recursive:!0}),o.copyFileSync(c,h);try{o.chmodSync(h,384)}catch{}i++,g.info(`[runtime-bridge] \u5DF2\u8FC1\u79FB ${c} \u2192 ${h}`)}}i>0&&g.info(`[runtime-bridge] \u5DF2\u8FC1\u79FB ${i} \u4E2A\u914D\u7F6E\u6587\u4EF6\u4ECE ${t} \u5230 ${n}`)}export{y as buildRuntimeTokenKey,V as clearRuntimeBinding,_ as clearScopedRuntimeAccessToken,G as getRuntimeAccessToken,L as getRuntimeBindingFilePath,J as getRuntimeBindingPublicState,z as getRuntimePairingCode,N as getRuntimeTokenStoreFilePath,O as getScopedRuntimeAccessToken,K as hasRuntimeBinding,l as loadRuntimeBinding,X as migrateOldBindingDir,f as normalizeSchedulerBaseUrl,Q as saveRuntimeBinding,A as saveScopedRuntimeAccessToken,M as validateRuntimeBindingToken,W as validateRuntimePairingCode};
6
6
 
@@ -1,2 +1,2 @@
1
- import{promises as A}from"node:fs";import{existsSync as P,readFileSync as L}from"node:fs";import E from"node:path";import{getToolActionInfo as x}from"../adapter/types.js";import{recordAgentFileChange as F}from"./workspaceTaskChangeWatcher.js";import{logger as u}from"../utils/logger.js";const h=new Map,k=new Set(["write","writefile","fswrite","edit","editfile","strreplace","str_replace","editcode","multiedit","apply_patch","applypatch","file_change","write_file","edit_file","delete_file","notebookedit"]),b=new Set(["delete","deletefile","remove","rm","delete_file"]);function y(e){return String(e??"").toLowerCase().replace(/[_-]/g,"")}function w(e){if(!e||typeof e!="object")return;const r=[e.file_path,e.filePath,e.path,e.target_file,e.targetFile,e.file,e.files];for(const t of r){if(typeof t=="string"&&t.trim())return t.trim().replace(/\\/g,"/");if(Array.isArray(t)){const i=t.filter(n=>typeof n=="string"&&n.trim());i.length>1&&u.warn(`[SdkFileChange] \u591A\u6587\u4EF6\u5DE5\u5177\u4EC5\u8BB0\u5F55\u9996\u4E2A\u6587\u4EF6\u8DEF\u5F84\uFF08\u5171 ${i.length} \u4E2A\uFF09`);const o=i[0];if(o)return o.trim().replace(/\\/g,"/")}}}function T(e,r){const t=y(e);if(!t)return;if(b.has(t))return"DELETE";if(k.has(t))return"UPDATE";const i=x(e,r);if(i.actionType==="write_file"||i.actionType==="edit_file")return"UPDATE"}function C(e,r){const t=E.resolve(e).replace(/\\/g,"/"),i=E.resolve(e,r).replace(/\\/g,"/"),o=t+"/";if(!(process.platform==="win32"?i.toLowerCase().startsWith(o.toLowerCase())||i.toLowerCase()===t.toLowerCase():i.startsWith(o)||i===t))return;const s=i.slice(t.length).replace(/^\/+/,"");return s.length>0?s:void 0}function N(e,r,t,i,o){if(!r||!t||typeof t!="object")return;let n=h.get(e);n||(n=new Map,h.set(e,n)),n.set(r,{toolInput:t,startState:D(i,t,o)})}function D(e,r,t){if(!t||!T(e,r))return null;const i=w(r),o=i?C(t,i):void 0;if(!o)return null;const n=E.join(t,o);if(!P(n))return{beforeContent:null,existedAtStart:!1};try{return{beforeContent:L(n,"utf-8"),existedAtStart:!0}}catch{return{beforeContent:null,existedAtStart:!0}}}function O(e){h.delete(e)}async function j(e,r){if(e.type!=="tool_use_end"||r.providerId==="acode")return;const{toolName:t,isError:i}=e.data,o=e.data.toolUseId||e.data.actionId,n=h.get(r.sessionId),s=o&&n?.get(o)||void 0;o&&n&&(n.delete(o),n.size===0&&h.delete(r.sessionId));const S=s?.toolInput;if(i===!0)return;const m=T(t,S);if(!m)return;let l=w(S);if(!l){const c=String(e.data.toolResult??e.data.actionResult??"").match(/(?:path|file)[=:]\s*["']?([^"'\s,]+)["']?/i);c&&(l=c[1].replace(/\\/g,"/"))}if(!l){u.warn(`[SdkFileChange] \u8DF3\u8FC7\u65E0\u6CD5\u89E3\u6790\u8DEF\u5F84\u7684\u6587\u4EF6\u5DE5\u5177: session=${r.sessionId}, tool=${t}`);return}const f=C(r.workspacePath,l);if(!f){u.warn(`[SdkFileChange] \u6587\u4EF6\u8DEF\u5F84\u5728\u5DE5\u4F5C\u533A\u5916\u6216\u4E3A\u5DE5\u4F5C\u533A\u6839\u76EE\u5F55\uFF0C\u8DF3\u8FC7: ${l} (workspace=${r.workspacePath})`);return}try{const a=E.join(r.workspacePath,f);let c=null,p=!1;try{c=await A.readFile(a,"utf-8"),p=!0}catch{}const g=s?.startState??null,_=g?.beforeContent??null;let d;if(m==="DELETE")d="DELETE";else if(g!=null){if(!g.existedAtStart&&!p){u.warn(`[SdkFileChange] \u6587\u4EF6\u5728\u5DE5\u5177\u6267\u884C\u524D\u540E\u5747\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u8BB0\u5F55: ${f}`);return}d=g.existedAtStart?p?"UPDATE":"DELETE":"CREATE"}else d=p?"UPDATE":"CREATE";await F({filePath:f,operation:d,beforeContent:_,afterContent:d==="DELETE"?null:c,agentId:r.agentId,workspacePath:r.workspacePath})}catch(a){u.warn(`[SdkFileChange] \u8BB0\u5F55\u5931\u8D25: session=${r.sessionId}, tool=${t}, file=${f}, error=${a instanceof Error?a.message:String(a)}`)}}export{O as forgetSession,j as onSdkToolUseEnd,N as onSdkToolUseStart};
1
+ import{promises as A,existsSync as P,readFileSync as L}from"node:fs";import E from"node:path";import{getToolActionInfo as x}from"../adapter/types.js";import{logger as u}from"../utils/logger.js";import{recordAgentFileChange as F}from"./workspaceTaskChangeWatcher.js";const h=new Map,k=new Set(["write","writefile","fswrite","edit","editfile","strreplace","str_replace","editcode","multiedit","apply_patch","applypatch","file_change","write_file","edit_file","delete_file","notebookedit"]),b=new Set(["delete","deletefile","remove","rm","delete_file"]);function y(e){return String(e??"").toLowerCase().replace(/[_-]/g,"")}function w(e){if(!e||typeof e!="object")return;const r=[e.file_path,e.filePath,e.path,e.target_file,e.targetFile,e.file,e.files];for(const t of r){if(typeof t=="string"&&t.trim())return t.trim().replace(/\\/g,"/");if(Array.isArray(t)){const i=t.filter(n=>typeof n=="string"&&n.trim());i.length>1&&u.warn(`[SdkFileChange] \u591A\u6587\u4EF6\u5DE5\u5177\u4EC5\u8BB0\u5F55\u9996\u4E2A\u6587\u4EF6\u8DEF\u5F84\uFF08\u5171 ${i.length} \u4E2A\uFF09`);const o=i[0];if(o)return o.trim().replace(/\\/g,"/")}}}function T(e,r){const t=y(e);if(!t)return;if(b.has(t))return"DELETE";if(k.has(t))return"UPDATE";const i=x(e,r);if(i.actionType==="write_file"||i.actionType==="edit_file")return"UPDATE"}function C(e,r){const t=E.resolve(e).replace(/\\/g,"/"),i=E.resolve(e,r).replace(/\\/g,"/"),o=t+"/";if(!(process.platform==="win32"?i.toLowerCase().startsWith(o.toLowerCase())||i.toLowerCase()===t.toLowerCase():i.startsWith(o)||i===t))return;const s=i.slice(t.length).replace(/^\/+/,"");return s.length>0?s:void 0}function I(e,r,t,i,o){if(!r||!t||typeof t!="object")return;let n=h.get(e);n||(n=new Map,h.set(e,n)),n.set(r,{toolInput:t,startState:D(i,t,o)})}function D(e,r,t){if(!t||!T(e,r))return null;const i=w(r),o=i?C(t,i):void 0;if(!o)return null;const n=E.join(t,o);if(!P(n))return{beforeContent:null,existedAtStart:!1};try{return{beforeContent:L(n,"utf-8"),existedAtStart:!0}}catch{return{beforeContent:null,existedAtStart:!0}}}function N(e){h.delete(e)}async function O(e,r){if(e.type!=="tool_use_end"||r.providerId==="acode")return;const{toolName:t,isError:i}=e.data,o=e.data.toolUseId||e.data.actionId,n=h.get(r.sessionId),s=o&&n?.get(o)||void 0;o&&n&&(n.delete(o),n.size===0&&h.delete(r.sessionId));const S=s?.toolInput;if(i===!0)return;const m=T(t,S);if(!m)return;let l=w(S);if(!l){const c=String(e.data.toolResult??e.data.actionResult??"").match(/(?:path|file)[=:]\s*["']?([^"'\s,]+)["']?/i);c&&(l=c[1].replace(/\\/g,"/"))}if(!l){u.warn(`[SdkFileChange] \u8DF3\u8FC7\u65E0\u6CD5\u89E3\u6790\u8DEF\u5F84\u7684\u6587\u4EF6\u5DE5\u5177: session=${r.sessionId}, tool=${t}`);return}const f=C(r.workspacePath,l);if(!f){u.warn(`[SdkFileChange] \u6587\u4EF6\u8DEF\u5F84\u5728\u5DE5\u4F5C\u533A\u5916\u6216\u4E3A\u5DE5\u4F5C\u533A\u6839\u76EE\u5F55\uFF0C\u8DF3\u8FC7: ${l} (workspace=${r.workspacePath})`);return}try{const a=E.join(r.workspacePath,f);let c=null,p=!1;try{c=await A.readFile(a,"utf-8"),p=!0}catch{}const g=s?.startState??null,_=g?.beforeContent??null;let d;if(m==="DELETE")d="DELETE";else if(g!==null){if(!g.existedAtStart&&!p){u.warn(`[SdkFileChange] \u6587\u4EF6\u5728\u5DE5\u5177\u6267\u884C\u524D\u540E\u5747\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u8BB0\u5F55: ${f}`);return}d=g.existedAtStart?p?"UPDATE":"DELETE":"CREATE"}else d=p?"UPDATE":"CREATE";await F({filePath:f,operation:d,beforeContent:_,afterContent:d==="DELETE"?null:c,agentId:r.agentId,workspacePath:r.workspacePath})}catch(a){u.warn(`[SdkFileChange] \u8BB0\u5F55\u5931\u8D25: session=${r.sessionId}, tool=${t}, file=${f}, error=${a instanceof Error?a.message:String(a)}`)}}export{N as forgetSession,O as onSdkToolUseEnd,I as onSdkToolUseStart};
2
2
 
@@ -1,3 +1,3 @@
1
- import{promises as g}from"node:fs";import{cpSync as S,existsSync as c,mkdirSync as $,readFileSync as j,readdirSync as A,rmSync as d,writeFileSync as E}from"node:fs";import i from"node:path";import{getAcodeSkillDataHome as I}from"../config.js";import{createLogger as b}from"../utils/logger.js";import{extractSkillZip as x,resolveSkillSourceDirFromExtractRoot as L}from"../utils/file-utils.js";import{getSkillFarmRoot as N,syncAgentSkillFarm as _}from"./agent-capability-sync.js";import{getAgentInitRoot as D}from"./instance-state.js";import{setDeployedDefaultsProvider as K,reconcileDefaultsFromDeployed as z}from"./capability-config.js";const h=b("skill-manager");function F(n){return typeof n=="string"&&n.length>0&&n.length<=128&&/^[a-zA-Z0-9_.-]+$/.test(n)}const O=1;class p{static getInstance(){return this._instance||(this._instance=new p(i.join(I(),"skills","deployed"))),this._instance}constructor(r){this.rootDir=r}manifestFile(){return i.join(this.rootDir,"manifest.json")}skillDir(r){const t=i.join(this.rootDir,r),e=i.resolve(this.rootDir);if(i.resolve(t)!==i.join(e,r))throw new Error(`\u6280\u80FD\u76EE\u5F55\u8D8A\u51FA\u90E8\u7F72\u533A: ${r}`);return t}isHealthy(r){return c(i.join(this.skillDir(r),"SKILL.md"))}readManifest(){try{const r=JSON.parse(j(this.manifestFile(),"utf8"));return Array.isArray(r.skills)?r.skills.filter(t=>t&&t.skillName):[]}catch{return[]}}writeManifest(r){$(this.rootDir,{recursive:!0}),E(this.manifestFile(),`${JSON.stringify({version:O,skills:r},null,2)}
2
- `,"utf8")}async saveSharedSkill(r,t,e=!0,m,w){if(!r||r.length===0)return{ok:!1,error:"zip \u5305\u5185\u5BB9\u4E3A\u7A7A"};const y=i.join(D("_tmp"),`skill-deploy-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{await R(r,y);const o=await L(y),l=i.basename(i.resolve(o)),M=String(t||"").replace(/\.zip$/i,"").trim(),s=w&&w.trim()||(l&&!l.startsWith("skill-deploy-")?l:"")||M;if(!F(s))return{ok:!1,error:`\u6280\u80FD\u540D\u975E\u6CD5: ${JSON.stringify(s)}`};if(!c(i.join(o,"SKILL.md")))return{ok:!1,error:`\u6280\u80FD\u5305\u7F3A\u5C11 SKILL.md: ${t}`};const k=this.readManifest().find(u=>u.skillName===s);if(k&&k.sha256===m&&this.isHealthy(s))return{ok:!0,skillName:s};$(this.rootDir,{recursive:!0});const a=this.skillDir(s),f=i.join(this.rootDir,`.old-${s}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);if(c(a))try{S(a,f,{recursive:!0})}catch{d(a,{recursive:!0,force:!0})}try{S(o,a,{recursive:!0})}catch(u){throw c(f)&&(d(a,{recursive:!0,force:!0}),S(f,a,{recursive:!0})),u}c(f)&&d(f,{recursive:!0,force:!0});const v=this.readManifest().filter(u=>u.skillName!==s);return v.push({skillName:s,zipFile:k?.zipFile??`${s}.zip`,fileName:t,defaultEnabled:e,sha256:m}),this.writeManifest(v),h.info("[shared] \u6280\u80FD\u5DF2\u90E8\u7F72\u5230 bridge: %s\uFF08\u6765\u6E90 %s%s\uFF09",s,t,m?`, sha256=${m.slice(0,12)}\u2026`:""),this.applyToKnownAgents(),{ok:!0,skillName:s}}catch(o){const l=o instanceof Error?o.message:String(o);return h.warn("[shared] \u6280\u80FD\u90E8\u7F72\u5931\u8D25\uFF08%s\uFF09: %s",t,l),{ok:!1,error:`\u6280\u80FD\u90E8\u7F72\u5931\u8D25: ${l}`}}finally{try{d(y,{recursive:!0,force:!0})}catch{}}}async removeDeployedSkill(r){if(!F(r))return{ok:!1,error:"skillName \u975E\u6CD5"};const t=this.readManifest().filter(e=>e.skillName!==r);this.writeManifest(t);try{d(this.skillDir(r),{recursive:!0,force:!0})}catch(e){return{ok:!1,error:`\u90E8\u7F72\u76EE\u5F55\u6E05\u7406\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`}}return this.applyToKnownAgents(),h.info("[shared] \u6280\u80FD\u5DF2\u4ECE bridge \u79FB\u9664\u90E8\u7F72: %s",r),{ok:!0}}listDeployed(){return this.readManifest().filter(r=>!/^skill-deploy-/.test(r.skillName)).map(r=>({...r,deployed:this.isHealthy(r.skillName)}))}deployedDefaultEnabled(){const r={};for(const t of this.readManifest())/^skill-deploy-/.test(t.skillName)||(r[t.skillName]=t.defaultEnabled);return r}applyToKnownAgents(){const r=new Set;for(const t of[N(),i.dirname(i.resolve(D("_")))])try{if(c(t))for(const e of A(t))e.startsWith(".")||r.add(e)}catch{}for(const t of r)try{_(t)}catch(e){h.warn("[shared] \u540C\u6B65\u6280\u80FD\u519C\u573A\u5931\u8D25 agent=%s: %s",t,e instanceof Error?e.message:String(e))}}}p._instance=null;async function R(n,r){const t=i.join(D("_tmp"),`skill-${Date.now()}-${Math.random().toString(36).slice(2,8)}.zip`);await g.mkdir(i.dirname(t),{recursive:!0}),await g.writeFile(t,n);try{await x(t,r)}finally{await g.rm(t,{force:!0}).catch(()=>{})}}const H=p.getInstance();K("skills",()=>H.deployedDefaultEnabled());const U=()=>z("skills");export{p as SkillManager,F as isValidSkillName,U as reconcileSkillsDefaultsFromDeployed,H as skillManager};
1
+ import{promises as g,cpSync as S,existsSync as c,mkdirSync as $,readFileSync as j,readdirSync as A,rmSync as d,writeFileSync as E}from"node:fs";import i from"node:path";import{getAcodeSkillDataHome as I}from"../config.js";import{extractSkillZip as b,resolveSkillSourceDirFromExtractRoot as x}from"../utils/file-utils.js";import{createLogger as L}from"../utils/logger.js";import{getSkillFarmRoot as N,syncAgentSkillFarm as _}from"./agent-capability-sync.js";import{setDeployedDefaultsProvider as K,reconcileDefaultsFromDeployed as z}from"./capability-config.js";import{getAgentInitRoot as D}from"./instance-state.js";const h=L("skill-manager");function F(n){return typeof n=="string"&&n.length>0&&n.length<=128&&/^[a-zA-Z0-9_.-]+$/.test(n)}const O=1;class p{static getInstance(){return this._instance||(this._instance=new p(i.join(I(),"skills","deployed"))),this._instance}constructor(r){this.rootDir=r}manifestFile(){return i.join(this.rootDir,"manifest.json")}skillDir(r){const t=i.join(this.rootDir,r),e=i.resolve(this.rootDir);if(i.resolve(t)!==i.join(e,r))throw new Error(`\u6280\u80FD\u76EE\u5F55\u8D8A\u51FA\u90E8\u7F72\u533A: ${r}`);return t}isHealthy(r){return c(i.join(this.skillDir(r),"SKILL.md"))}readManifest(){try{const r=JSON.parse(j(this.manifestFile(),"utf8"));return Array.isArray(r.skills)?r.skills.filter(t=>t&&t.skillName):[]}catch{return[]}}writeManifest(r){$(this.rootDir,{recursive:!0}),E(this.manifestFile(),`${JSON.stringify({version:O,skills:r},null,2)}
2
+ `,"utf8")}async saveSharedSkill(r,t,e=!0,m,w){if(!r||r.length===0)return{ok:!1,error:"zip \u5305\u5185\u5BB9\u4E3A\u7A7A"};const y=i.join(D("_tmp"),`skill-deploy-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{await R(r,y);const o=await x(y),l=i.basename(i.resolve(o)),M=String(t||"").replace(/\.zip$/i,"").trim(),s=w&&w.trim()||(l&&!l.startsWith("skill-deploy-")?l:"")||M;if(!F(s))return{ok:!1,error:`\u6280\u80FD\u540D\u975E\u6CD5: ${JSON.stringify(s)}`};if(!c(i.join(o,"SKILL.md")))return{ok:!1,error:`\u6280\u80FD\u5305\u7F3A\u5C11 SKILL.md: ${t}`};const k=this.readManifest().find(u=>u.skillName===s);if(k&&k.sha256===m&&this.isHealthy(s))return{ok:!0,skillName:s};$(this.rootDir,{recursive:!0});const a=this.skillDir(s),f=i.join(this.rootDir,`.old-${s}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);if(c(a))try{S(a,f,{recursive:!0})}catch{d(a,{recursive:!0,force:!0})}try{S(o,a,{recursive:!0})}catch(u){throw c(f)&&(d(a,{recursive:!0,force:!0}),S(f,a,{recursive:!0})),u}c(f)&&d(f,{recursive:!0,force:!0});const v=this.readManifest().filter(u=>u.skillName!==s);return v.push({skillName:s,zipFile:k?.zipFile??`${s}.zip`,fileName:t,defaultEnabled:e,sha256:m}),this.writeManifest(v),h.info("[shared] \u6280\u80FD\u5DF2\u90E8\u7F72\u5230 bridge: %s\uFF08\u6765\u6E90 %s%s\uFF09",s,t,m?`, sha256=${m.slice(0,12)}\u2026`:""),this.applyToKnownAgents(),{ok:!0,skillName:s}}catch(o){const l=o instanceof Error?o.message:String(o);return h.warn("[shared] \u6280\u80FD\u90E8\u7F72\u5931\u8D25\uFF08%s\uFF09: %s",t,l),{ok:!1,error:`\u6280\u80FD\u90E8\u7F72\u5931\u8D25: ${l}`}}finally{try{d(y,{recursive:!0,force:!0})}catch{}}}async removeDeployedSkill(r){if(!F(r))return{ok:!1,error:"skillName \u975E\u6CD5"};const t=this.readManifest().filter(e=>e.skillName!==r);this.writeManifest(t);try{d(this.skillDir(r),{recursive:!0,force:!0})}catch(e){return{ok:!1,error:`\u90E8\u7F72\u76EE\u5F55\u6E05\u7406\u5931\u8D25: ${e instanceof Error?e.message:String(e)}`}}return this.applyToKnownAgents(),h.info("[shared] \u6280\u80FD\u5DF2\u4ECE bridge \u79FB\u9664\u90E8\u7F72: %s",r),{ok:!0}}listDeployed(){return this.readManifest().filter(r=>!/^skill-deploy-/.test(r.skillName)).map(r=>({...r,deployed:this.isHealthy(r.skillName)}))}deployedDefaultEnabled(){const r={};for(const t of this.readManifest())/^skill-deploy-/.test(t.skillName)||(r[t.skillName]=t.defaultEnabled);return r}applyToKnownAgents(){const r=new Set;for(const t of[N(),i.dirname(i.resolve(D("_")))])try{if(c(t))for(const e of A(t))e.startsWith(".")||r.add(e)}catch{}for(const t of r)try{_(t)}catch(e){h.warn("[shared] \u540C\u6B65\u6280\u80FD\u519C\u573A\u5931\u8D25 agent=%s: %s",t,e instanceof Error?e.message:String(e))}}}p._instance=null;async function R(n,r){const t=i.join(D("_tmp"),`skill-${Date.now()}-${Math.random().toString(36).slice(2,8)}.zip`);await g.mkdir(i.dirname(t),{recursive:!0}),await g.writeFile(t,n);try{await b(t,r)}finally{await g.rm(t,{force:!0}).catch(()=>{})}}const H=p.getInstance();K("skills",()=>H.deployedDefaultEnabled());const Q=()=>z("skills");export{p as SkillManager,F as isValidSkillName,Q as reconcileSkillsDefaultsFromDeployed,H as skillManager};
3
3
 
@@ -1,14 +1,14 @@
1
- import{randomBytes as P}from"node:crypto";import{existsSync as m,readFileSync as T}from"node:fs";import v from"node:os";import{stdin as E,stdout as i}from"node:process";import{createInterface as x}from"node:readline/promises";import{atomicWriteJsonFile as _}from"../utils/file-utils.js";import{logger as o}from"../utils/logger.js";import{getAutoRegisterConfigFilePath as d}from"./auto-register.js";const w={autoRegisterTargets:[{instanceName:"<\u5B9E\u4F8B\u540D\u79F0\uFF0C\u4F8B\u5982 \u6211\u7684\u4E3B\u673A>",serverUrl:"http://<\u8C03\u5EA6\u4E2D\u5FC3IP>:<\u7AEF\u53E3>",userKey:"<\u4F60\u7684 userKey>",instanceId:"<\u5B9E\u4F8BID\uFF0C\u9996\u6B21\u53EF\u7559\u7A7A\u7531\u670D\u52A1\u7AEF\u751F\u6210>"}],connectionKey:"<\u9762\u677F\u8FDE\u63A5 Bridge \u7684\u5BC6\u94A5>",panelUsername:"<\u9762\u677F\u7528\u6237\u540D>",panelPassword:"<\u9762\u677F\u5BC6\u7801>"};function C(t=w){return`[runtime-bridge] \u6700\u5C0F\u914D\u7F6E\u793A\u4F8B\uFF08\u8BF7\u5C06 <\u5360\u4F4D\u7B26> \u66FF\u6362\u4E3A\u771F\u5B9E\u503C\u540E\u4FDD\u5B58\uFF09:
1
+ import{randomBytes as R}from"node:crypto";import{existsSync as m,readFileSync as T}from"node:fs";import v from"node:os";import{stdin as E,stdout as i}from"node:process";import{createInterface as x}from"node:readline/promises";import{atomicWriteJsonFile as _}from"../utils/file-utils.js";import{logger as o}from"../utils/logger.js";import{getAutoRegisterConfigFilePath as d}from"./auto-register.js";const w={autoRegisterTargets:[{instanceName:"<\u5B9E\u4F8B\u540D\u79F0\uFF0C\u4F8B\u5982 \u6211\u7684\u4E3B\u673A>",serverUrl:"http://<\u8C03\u5EA6\u4E2D\u5FC3IP>:<\u7AEF\u53E3>",userKey:"<\u4F60\u7684 userKey>",instanceId:"<\u5B9E\u4F8BID\uFF0C\u9996\u6B21\u53EF\u7559\u7A7A\u7531\u670D\u52A1\u7AEF\u751F\u6210>"}],connectionKey:"<\u9762\u677F\u8FDE\u63A5 Bridge \u7684\u5BC6\u94A5>",panelUsername:"<\u9762\u677F\u7528\u6237\u540D>",panelPassword:"<\u9762\u677F\u5BC6\u7801>"};function $(t=w){return`[runtime-bridge] \u6700\u5C0F\u914D\u7F6E\u793A\u4F8B\uFF08\u8BF7\u5C06 <\u5360\u4F4D\u7B26> \u66FF\u6362\u4E3A\u771F\u5B9E\u503C\u540E\u4FDD\u5B58\uFF09:
2
2
  ${JSON.stringify(t,null,2)}
3
- [runtime-bridge] \u8BF4\u660E\uFF1AautoRegisterTargets \u53EF\u5305\u542B\u591A\u4E2A\u76EE\u6807\uFF1BinstanceId \u9996\u6B21\u53EF\u7701\u7565\uFF0C\u7531\u670D\u52A1\u7AEF\u751F\u6210\uFF1BpanelUsername / panelPassword \u4E3A\u53EF\u9009\u9762\u677F\u8BA4\u8BC1\u3002`}function l(t){return t.trim().toLowerCase()}function U(t){return["","y","yes","\u662F","\u597D","\u914D\u7F6E"].includes(l(t))}function B(t){return["n","no","\u5426","\u4E0D","\u8DF3\u8FC7","skip","s"].includes(l(t))}function N(t){if(!m(t))return{};try{const e=JSON.parse(T(t,"utf-8"));return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}catch(e){const r=e;return o.warn(`[runtime-bridge] \u8BFB\u53D6\u73B0\u6709\u914D\u7F6E\u5931\u8D25\uFF0C\u5C06\u4F7F\u7528\u7A7A\u9ED8\u8BA4\u503C: ${r.message}`),{}}}function k(){return`awsb_${P(24).toString("base64url")}`}async function g(t,e){await _(t,e)}async function p(t,e){const r=e();await g(t,{connectionKey:r});const n=`[runtime-bridge] \u5DF2\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ${t}
3
+ [runtime-bridge] \u8BF4\u660E\uFF1AautoRegisterTargets \u53EF\u5305\u542B\u591A\u4E2A\u76EE\u6807\uFF1BinstanceId \u9996\u6B21\u53EF\u7701\u7565\uFF0C\u7531\u670D\u52A1\u7AEF\u751F\u6210\uFF1BpanelUsername / panelPassword \u4E3A\u53EF\u9009\u9762\u677F\u8BA4\u8BC1\u3002`}function l(t){return t.trim().toLowerCase()}function U(t){return["","y","yes","\u662F","\u597D","\u914D\u7F6E"].includes(l(t))}function B(t){return["n","no","\u5426","\u4E0D","\u8DF3\u8FC7","skip","s"].includes(l(t))}function N(t){if(!m(t))return{};try{const e=JSON.parse(T(t,"utf-8"));return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}catch(e){const r=e;return o.warn(`[runtime-bridge] \u8BFB\u53D6\u73B0\u6709\u914D\u7F6E\u5931\u8D25\uFF0C\u5C06\u4F7F\u7528\u7A7A\u9ED8\u8BA4\u503C: ${r.message}`),{}}}function k(){return`awsb_${R(24).toString("base64url")}`}async function g(t,e){await _(t,e)}async function p(t,e){const r=e();await g(t,{connectionKey:r});const n=`[runtime-bridge] \u5DF2\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ${t}
4
4
  [runtime-bridge] \u81EA\u52A8\u751F\u6210 connectionKey: ${r}
5
5
  [runtime-bridge] \u8BF7\u4FDD\u5B58\u8BE5 connectionKey\uFF1Bserver/\u9762\u677F\u8FDE\u63A5\u6B64 Bridge \u65F6\u9700\u8981\u4F7F\u7528\u5B83\u3002`;o.info(n),i.write(`${n}
6
- `)}async function y(t,e,r){return(await t.question(`${e}\uFF08\u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D\u503C ${r}\uFF0C\u76F4\u63A5\u56DE\u8F66\u4FDD\u7559\uFF09: `)).trim()||r}const $=10;async function h(t,e,r){let n=0;for(;;){const a=(await t.question(r?`${e}\uFF08\u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D\u503C ${r}\uFF0C\u76F4\u63A5\u56DE\u8F66\u4FDD\u7559\uFF09: `:`${e}: `)).trim();if(a)return a;if(r)return r;if(n++,n>=$)throw new Error(`${e} \u8F93\u5165\u8D85\u8FC7\u6700\u5927\u91CD\u8BD5\u6B21\u6570\uFF08${$}\uFF09\uFF0C\u9000\u51FA\u914D\u7F6E\u5F15\u5BFC`);i.write(`${e} \u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165\u3002
6
+ `)}async function y(t,e,r){return(await t.question(`${e}\uFF08\u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D\u503C ${r}\uFF0C\u76F4\u63A5\u56DE\u8F66\u4FDD\u7559\uFF09: `)).trim()||r}const h=10;async function b(t,e,r){let n=0;for(;;){const a=(await t.question(r?`${e}\uFF08\u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D\u503C ${r}\uFF0C\u76F4\u63A5\u56DE\u8F66\u4FDD\u7559\uFF09: `:`${e}: `)).trim();if(a)return a;if(r)return r;if(n++,n>=h)throw new Error(`${e} \u8F93\u5165\u8D85\u8FC7\u6700\u5927\u91CD\u8BD5\u6B21\u6570\uFF08${h}\uFF09\uFF0C\u9000\u51FA\u914D\u7F6E\u5F15\u5BFC`);i.write(`${e} \u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165\u3002
7
7
  `)}}async function Y(t){for(;;){const e=await t.question(`\u672A\u68C0\u6D4B\u5230 ${d()}\uFF0C\u662F\u5426\u73B0\u5728\u8FDB\u5165\u81EA\u52A8\u6CE8\u518C\u914D\u7F6E\u5F15\u5BFC\uFF1F(Y/n): `);if(U(e))return!0;if(B(e))return!1;i.write(`\u8BF7\u8F93\u5165 Y \u7EE7\u7EED\u914D\u7F6E\uFF0C\u6216\u8F93\u5165 n \u8DF3\u8FC7\u3002
8
8
  `)}}async function q(t){for(;;){const e=await t.question("\u672A\u68C0\u6D4B\u5230\u914D\u7F6E\u6587\u4EF6\uFF0C\u8BF7\u9009\u62E9\u914D\u7F6E\u65B9\u5F0F\uFF1A[1] \u5B8C\u6574\u9010\u6B65\u5F15\u5BFC [2] \u6700\u5C0F\u914D\u7F6E\u793A\u4F8B\uFF08\u751F\u6210\u5360\u4F4D\u7B26\u6A21\u677F\uFF0C\u7A0D\u540E\u624B\u52A8\u586B\u5199\uFF09 (\u9ED8\u8BA4 1): "),r=l(e);if(r===""||r==="1"||r==="full"||r==="\u5B8C\u6574"||r==="\u5F15\u5BFC")return"full";if(r==="2"||r==="minimal"||r==="\u6700\u5C0F"||r==="\u793A\u4F8B")return"minimal";i.write(`\u8BF7\u8F93\u5165 1\uFF08\u5B8C\u6574\u5F15\u5BFC\uFF09\u6216 2\uFF08\u6700\u5C0F\u914D\u7F6E\u793A\u4F8B\uFF09\u3002
9
- `)}}async function b(t,e={}){const r=e.autoRegisterTargets?.[0]||{},n="http://127.0.0.1:8080",a=v.hostname()||"AgentsWork Runtime Bridge",c=r.registerAddr||r.registerIp||"127.0.0.1",u=await h(t,"connectionKey\uFF08\u9762\u677F\u8FDE\u63A5 Bridge \u7684\u5BC6\u94A5\uFF09",e.connectionKey),f=await y(t,"serverUrl\uFF08\u8C03\u5EA6\u4E2D\u5FC3\u5730\u5740\uFF09",r.serverUrl||n),K=await y(t,"instanceName\uFF08\u5B9E\u4F8B\u540D\u79F0\uFF09",r.instanceName||a),R=await h(t,"userKey\uFF08\u7528\u6237 API Key\uFF09",r.userKey),S=await y(t,"registerAddr\uFF08Bridge \u5BF9\u5916\u8BBF\u95EE\u5730\u5740\uFF0C\u652F\u6301 host:port / \u7EAF host / \u5B8C\u6574 URL\uFF09",c),{registerIp:D,...A}=r;return{...e,connectionKey:u,autoRegisterTargets:[{...A,serverUrl:f,instanceName:K,userKey:R,registerAddr:S}]}}async function I(t){return{prompt:t.prompt||x({input:E,output:i,terminal:!0}),shouldClosePrompt:!t.prompt}}async function z(t={}){const e=t.configPath||d(),r=t.generateConnectionKey||k;if(m(e))return"exists";if((t.env||process.env).AWS_BRIDGE_SKIP_SETUP==="true")return await p(e,r),o.info("[runtime-bridge] AWS_BRIDGE_SKIP_SETUP=true\uFF0C\u8DF3\u8FC7\u9996\u6B21\u914D\u7F6E\u5F15\u5BFC"),"skipped";if(!(t.interactive??!!(process.stdin.isTTY&&process.stdout.isTTY)))return await p(e,r),o.info(`[runtime-bridge] \u672A\u68C0\u6D4B\u5230\u914D\u7F6E\u6587\u4EF6: ${e}\uFF1B\u5F53\u524D\u4E3A\u975E\u4EA4\u4E92\u73AF\u5883\uFF0C\u8DF3\u8FC7\u9996\u6B21\u914D\u7F6E\u5F15\u5BFC`),"non-interactive";const{prompt:s,shouldClosePrompt:c}=await I(t);try{if(!await Y(s))return await p(e,r),o.info("[runtime-bridge] \u5DF2\u8DF3\u8FC7\u9996\u6B21\u914D\u7F6E\u5F15\u5BFC"),"skipped";const f=await b(s);return await g(e,f),o.info(`[runtime-bridge] \u5DF2\u5199\u5165\u914D\u7F6E\u6587\u4EF6: ${e}`),"created"}catch(u){const f=u;return o.warn(`[runtime-bridge] \u9996\u6B21\u914D\u7F6E\u5F15\u5BFC\u5931\u8D25: ${f.message}`),"failed"}finally{c&&s.close()}}async function Q(t={}){const e=t.configPath||d();if(!(t.interactive??!!(process.stdin.isTTY&&process.stdout.isTTY)))return o.warn("[runtime-bridge] awsb config \u9700\u8981\u4EA4\u4E92\u5F0F\u7EC8\u7AEF"),"failed";const{prompt:n,shouldClosePrompt:a}=await I(t);try{const s=N(e);if(!m(e)&&await q(n)==="minimal")return i.write(C()),await g(e,w),i.write(`[runtime-bridge] \u5DF2\u5C06\u6700\u5C0F\u914D\u7F6E\u793A\u4F8B\u6A21\u677F\u5199\u5165: ${e}
9
+ `)}}async function I(t,e={}){const r=e.autoRegisterTargets?.[0]||{},n="http://127.0.0.1:8080",a=v.hostname()||"AgentsWork Runtime Bridge",c=r.registerAddr||r.registerIp||"127.0.0.1",u=await b(t,"connectionKey\uFF08\u9762\u677F\u8FDE\u63A5 Bridge \u7684\u5BC6\u94A5\uFF09",e.connectionKey),f=await y(t,"serverUrl\uFF08\u8C03\u5EA6\u4E2D\u5FC3\u5730\u5740\uFF09",r.serverUrl||n),S=await y(t,"instanceName\uFF08\u5B9E\u4F8B\u540D\u79F0\uFF09",r.instanceName||a),A=await b(t,"userKey\uFF08\u7528\u6237 API Key\uFF09",r.userKey),P=await y(t,"registerAddr\uFF08Bridge \u5BF9\u5916\u8BBF\u95EE\u5730\u5740\uFF0C\u652F\u6301 host:port / \u7EAF host / \u5B8C\u6574 URL\uFF09",c),C={...r};return delete C.registerIp,{...e,connectionKey:u,autoRegisterTargets:[{...C,serverUrl:f,instanceName:S,userKey:A,registerAddr:P}]}}async function K(t){return{prompt:t.prompt||x({input:E,output:i,terminal:!0}),shouldClosePrompt:!t.prompt}}async function J(t={}){const e=t.configPath||d(),r=t.generateConnectionKey||k;if(m(e))return"exists";if((t.env||process.env).AWS_BRIDGE_SKIP_SETUP==="true")return await p(e,r),o.info("[runtime-bridge] AWS_BRIDGE_SKIP_SETUP=true\uFF0C\u8DF3\u8FC7\u9996\u6B21\u914D\u7F6E\u5F15\u5BFC"),"skipped";if(!(t.interactive??!!(process.stdin.isTTY&&process.stdout.isTTY)))return await p(e,r),o.info(`[runtime-bridge] \u672A\u68C0\u6D4B\u5230\u914D\u7F6E\u6587\u4EF6: ${e}\uFF1B\u5F53\u524D\u4E3A\u975E\u4EA4\u4E92\u73AF\u5883\uFF0C\u8DF3\u8FC7\u9996\u6B21\u914D\u7F6E\u5F15\u5BFC`),"non-interactive";const{prompt:s,shouldClosePrompt:c}=await K(t);try{if(!await Y(s))return await p(e,r),o.info("[runtime-bridge] \u5DF2\u8DF3\u8FC7\u9996\u6B21\u914D\u7F6E\u5F15\u5BFC"),"skipped";const f=await I(s);return await g(e,f),o.info(`[runtime-bridge] \u5DF2\u5199\u5165\u914D\u7F6E\u6587\u4EF6: ${e}`),"created"}catch(u){const f=u;return o.warn(`[runtime-bridge] \u9996\u6B21\u914D\u7F6E\u5F15\u5BFC\u5931\u8D25: ${f.message}`),"failed"}finally{c&&s.close()}}async function z(t={}){const e=t.configPath||d();if(!(t.interactive??!!(process.stdin.isTTY&&process.stdout.isTTY)))return o.warn("[runtime-bridge] awsb config \u9700\u8981\u4EA4\u4E92\u5F0F\u7EC8\u7AEF"),"failed";const{prompt:n,shouldClosePrompt:a}=await K(t);try{const s=N(e);if(!m(e)&&await q(n)==="minimal")return i.write($()),await g(e,w),i.write(`[runtime-bridge] \u5DF2\u5C06\u6700\u5C0F\u914D\u7F6E\u793A\u4F8B\u6A21\u677F\u5199\u5165: ${e}
10
10
  `),i.write(`[runtime-bridge] \u8BF7\u5C06 <\u5360\u4F4D\u7B26> \u66FF\u6362\u4E3A\u771F\u5B9E\u503C\u540E\u4FDD\u5B58\u3002
11
- `),"created";const u=await b(n,s);return await g(e,u),o.info(`[runtime-bridge] \u5DF2\u66F4\u65B0\u914D\u7F6E\u6587\u4EF6: ${e}`),"configured"}catch(s){const c=s;return o.warn(`[runtime-bridge] \u914D\u7F6E\u5F15\u5BFC\u5931\u8D25: ${c.message}`),"failed"}finally{a&&n.close()}}async function X(t={}){const e=t.configPath||d();i.write(C());try{return await g(e,w),i.write(`[runtime-bridge] \u5DF2\u5C06\u6700\u5C0F\u914D\u7F6E\u793A\u4F8B\u6A21\u677F\u5199\u5165: ${e}
11
+ `),"created";const u=await I(n,s);return await g(e,u),o.info(`[runtime-bridge] \u5DF2\u66F4\u65B0\u914D\u7F6E\u6587\u4EF6: ${e}`),"configured"}catch(s){const c=s;return o.warn(`[runtime-bridge] \u914D\u7F6E\u5F15\u5BFC\u5931\u8D25: ${c.message}`),"failed"}finally{a&&n.close()}}async function Q(t={}){const e=t.configPath||d();i.write($());try{return await g(e,w),i.write(`[runtime-bridge] \u5DF2\u5C06\u6700\u5C0F\u914D\u7F6E\u793A\u4F8B\u6A21\u677F\u5199\u5165: ${e}
12
12
  `),i.write(`[runtime-bridge] \u8BF7\u5C06 <\u5360\u4F4D\u7B26> \u66FF\u6362\u4E3A\u771F\u5B9E\u503C\u540E\u4FDD\u5B58\u3002
13
- `),"created"}catch(r){const n=r;return o.warn(`[runtime-bridge] \u5199\u5165\u793A\u4F8B\u6A21\u677F\u5931\u8D25: ${n.message}`),"failed"}}export{w as MINIMAL_CONFIG_TEMPLATE,Q as configureStartupConfig,z as ensureStartupConfig,C as formatConfigExample,X as printConfigExampleCommand};
13
+ `),"created"}catch(r){const n=r;return o.warn(`[runtime-bridge] \u5199\u5165\u793A\u4F8B\u6A21\u677F\u5931\u8D25: ${n.message}`),"failed"}}export{w as MINIMAL_CONFIG_TEMPLATE,z as configureStartupConfig,J as ensureStartupConfig,$ as formatConfigExample,Q as printConfigExampleCommand};
14
14
 
@@ -1,2 +1,2 @@
1
- import{execFile as T,exec as S}from"node:child_process";import{promisify as y}from"node:util";import c from"node:os";const i=y(T),N=y(S);import{createLogger as b}from"../utils/logger.js";const u=b("system-metrics"),g=120,h=1024**3;let p=null;function B(t){return Math.round(t*100)/100}function d(t){return Number.isFinite(t)?B(Math.min(100,Math.max(0,t))):0}function w(t){return B(t/h)}function f(){return c.cpus().reduce((t,e)=>{const o=Object.values(e.times).reduce((n,s)=>n+s,0);return{idle:t.idle+e.times.idle,total:t.total+o}},{idle:0,total:0})}function M(t){return new Promise(e=>{setTimeout(e,t)})}async function P(){const t=f();await M(g);const e=f(),o=e.total-t.total,n=e.idle-t.idle,s=o<=0?0:(o-n)/o*100,r=c.cpus();return{usagePercent:d(s),coreCount:r.length,model:r[0]?.model||c.arch()}}function x(){const t=c.totalmem(),e=c.freemem(),o=Math.max(0,t-e);return{usedBytes:o,freeBytes:e,totalBytes:t,usagePercent:t>0?d(o/t*100):0}}function k(){return process.env.AWS_SYSTEM_METRICS_STORAGE_PATH||process.cwd()}async function C(t){const o=`Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='${(c.platform()==="win32"?t.slice(0,2).toUpperCase():t).replace(/'/g,"''")}'" | Select-Object Size,FreeSpace | ConvertTo-Json -Compress`,{stdout:n}=await i("powershell",["-NoProfile","-NonInteractive","-Command",o],{encoding:"utf8",timeout:5e3,windowsHide:!0}),s=JSON.parse(n.trim());return{freeBytes:Number(s.FreeSpace||0),totalBytes:Number(s.Size||0)}}async function F(t){const{stdout:e}=await i("df",["-kP",t],{encoding:"utf8",timeout:5e3}),n=e.trim().split(/\r?\n/).filter(Boolean)[1]?.trim().split(/\s+/)||[],s=Number(n[1]||0),r=Number(n[2]||0);return{freeBytes:Number(n[3]||Math.max(0,s-r))*1024,totalBytes:s*1024}}async function v(){const t=k();try{const e=c.platform()==="win32"?await C(t):await F(t),o=Math.max(0,e.totalBytes),n=Math.max(0,e.freeBytes),s=Math.max(0,o-n);return{path:t,usedBytes:s,freeBytes:n,totalBytes:o,usagePercent:o>0?d(s/o*100):0,freeGiB:w(n),totalGiB:w(o)}}catch(e){return u.debug("Failed to collect storage metrics:",e),{path:t,usedBytes:0,freeBytes:0,totalBytes:0,usagePercent:0,freeGiB:0,totalGiB:0}}}async function A(){try{const{stdout:t}=await N("cat /proc/net/dev",{encoding:"utf8",timeout:5e3});let e=0,o=0;for(const n of t.split(/\r?\n/)){const[s,r]=n.split(":");if(!s||!r)continue;const a=s.trim();if(!a||a==="lo")continue;const l=r.trim().split(/\s+/).map(Number);o+=Number.isFinite(l[0])?l[0]:0,e+=Number.isFinite(l[8])?l[8]:0}return{uploadTotalBytes:e,downloadTotalBytes:o}}catch(t){return u.debug("Failed to collect Linux network metrics:",t),null}}async function D(){try{const{stdout:t}=await i("netstat",["-ibn"],{encoding:"utf8",timeout:5e3}),e=new Set;let o=0,n=0;for(const s of t.split(/\r?\n/).slice(1)){const r=s.trim().split(/\s+/),a=r[0];if(!a||a==="lo0"||e.has(a))continue;const l=Number(r[6]||0),m=Number(r[9]||0);n+=Number.isFinite(l)?l:0,o+=Number.isFinite(m)?m:0,e.add(a)}return{uploadTotalBytes:o,downloadTotalBytes:n}}catch(t){return u.debug("Failed to collect macOS network metrics:",t),null}}async function _(){try{const t="Get-NetAdapterStatistics | Select-Object ReceivedBytes,SentBytes | ConvertTo-Json -Compress",{stdout:e}=await i("powershell",["-NoProfile","-NonInteractive","-Command",t],{encoding:"utf8",timeout:5e3,windowsHide:!0}),o=e.trim();if(!o)return null;const n=JSON.parse(o);return(Array.isArray(n)?n:[n]).reduce((r,a)=>({downloadTotalBytes:r.downloadTotalBytes+Number(a.ReceivedBytes||0),uploadTotalBytes:r.uploadTotalBytes+Number(a.SentBytes||0)}),{uploadTotalBytes:0,downloadTotalBytes:0})}catch(t){return u.debug("Failed to collect Windows network metrics:",t),null}}async function G(){const t=c.platform(),e=t==="win32"?await _():t==="darwin"?await D():await A();return{uploadTotalBytes:e?.uploadTotalBytes||0,downloadTotalBytes:e?.downloadTotalBytes||0,sampledAt:Date.now()}}async function I(){const t=await G(),e=p;if(p=t,!e)return{uploadBytesPerSecond:0,downloadBytesPerSecond:0,uploadTotalBytes:t.uploadTotalBytes,downloadTotalBytes:t.downloadTotalBytes};const o=Math.max(1,(t.sampledAt-e.sampledAt)/1e3);return{uploadBytesPerSecond:Math.max(0,Math.round((t.uploadTotalBytes-e.uploadTotalBytes)/o)),downloadBytesPerSecond:Math.max(0,Math.round((t.downloadTotalBytes-e.downloadTotalBytes)/o)),uploadTotalBytes:t.uploadTotalBytes,downloadTotalBytes:t.downloadTotalBytes}}async function U(){const[t,e,o,n]=await Promise.all([P(),Promise.resolve(x()),v(),I()]);return{ok:!0,collectedAt:new Date().toISOString(),cpu:t,memory:e,storage:o,network:n}}export{U as collectSystemMetrics};
1
+ import{execFile as T,exec as S}from"node:child_process";import c from"node:os";import{promisify as y}from"node:util";const i=y(T),N=y(S);import{createLogger as b}from"../utils/logger.js";const u=b("system-metrics"),g=120,h=1024**3;let p=null;function B(t){return Math.round(t*100)/100}function d(t){return Number.isFinite(t)?B(Math.min(100,Math.max(0,t))):0}function w(t){return B(t/h)}function f(){return c.cpus().reduce((t,e)=>{const o=Object.values(e.times).reduce((n,s)=>n+s,0);return{idle:t.idle+e.times.idle,total:t.total+o}},{idle:0,total:0})}function M(t){return new Promise(e=>{setTimeout(e,t)})}async function P(){const t=f();await M(g);const e=f(),o=e.total-t.total,n=e.idle-t.idle,s=o<=0?0:(o-n)/o*100,r=c.cpus();return{usagePercent:d(s),coreCount:r.length,model:r[0]?.model||c.arch()}}function x(){const t=c.totalmem(),e=c.freemem(),o=Math.max(0,t-e);return{usedBytes:o,freeBytes:e,totalBytes:t,usagePercent:t>0?d(o/t*100):0}}function k(){return process.env.AWS_SYSTEM_METRICS_STORAGE_PATH||process.cwd()}async function C(t){const o=`Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='${(c.platform()==="win32"?t.slice(0,2).toUpperCase():t).replace(/'/g,"''")}'" | Select-Object Size,FreeSpace | ConvertTo-Json -Compress`,{stdout:n}=await i("powershell",["-NoProfile","-NonInteractive","-Command",o],{encoding:"utf8",timeout:5e3,windowsHide:!0}),s=JSON.parse(n.trim());return{freeBytes:Number(s.FreeSpace||0),totalBytes:Number(s.Size||0)}}async function F(t){const{stdout:e}=await i("df",["-kP",t],{encoding:"utf8",timeout:5e3}),n=e.trim().split(/\r?\n/).filter(Boolean)[1]?.trim().split(/\s+/)||[],s=Number(n[1]||0),r=Number(n[2]||0);return{freeBytes:Number(n[3]||Math.max(0,s-r))*1024,totalBytes:s*1024}}async function v(){const t=k();try{const e=c.platform()==="win32"?await C(t):await F(t),o=Math.max(0,e.totalBytes),n=Math.max(0,e.freeBytes),s=Math.max(0,o-n);return{path:t,usedBytes:s,freeBytes:n,totalBytes:o,usagePercent:o>0?d(s/o*100):0,freeGiB:w(n),totalGiB:w(o)}}catch(e){return u.debug("Failed to collect storage metrics:",e),{path:t,usedBytes:0,freeBytes:0,totalBytes:0,usagePercent:0,freeGiB:0,totalGiB:0}}}async function A(){try{const{stdout:t}=await N("cat /proc/net/dev",{encoding:"utf8",timeout:5e3});let e=0,o=0;for(const n of t.split(/\r?\n/)){const[s,r]=n.split(":");if(!s||!r)continue;const a=s.trim();if(!a||a==="lo")continue;const l=r.trim().split(/\s+/).map(Number);o+=Number.isFinite(l[0])?l[0]:0,e+=Number.isFinite(l[8])?l[8]:0}return{uploadTotalBytes:e,downloadTotalBytes:o}}catch(t){return u.debug("Failed to collect Linux network metrics:",t),null}}async function D(){try{const{stdout:t}=await i("netstat",["-ibn"],{encoding:"utf8",timeout:5e3}),e=new Set;let o=0,n=0;for(const s of t.split(/\r?\n/).slice(1)){const r=s.trim().split(/\s+/),a=r[0];if(!a||a==="lo0"||e.has(a))continue;const l=Number(r[6]||0),m=Number(r[9]||0);n+=Number.isFinite(l)?l:0,o+=Number.isFinite(m)?m:0,e.add(a)}return{uploadTotalBytes:o,downloadTotalBytes:n}}catch(t){return u.debug("Failed to collect macOS network metrics:",t),null}}async function _(){try{const t="Get-NetAdapterStatistics | Select-Object ReceivedBytes,SentBytes | ConvertTo-Json -Compress",{stdout:e}=await i("powershell",["-NoProfile","-NonInteractive","-Command",t],{encoding:"utf8",timeout:5e3,windowsHide:!0}),o=e.trim();if(!o)return null;const n=JSON.parse(o);return(Array.isArray(n)?n:[n]).reduce((r,a)=>({downloadTotalBytes:r.downloadTotalBytes+Number(a.ReceivedBytes||0),uploadTotalBytes:r.uploadTotalBytes+Number(a.SentBytes||0)}),{uploadTotalBytes:0,downloadTotalBytes:0})}catch(t){return u.debug("Failed to collect Windows network metrics:",t),null}}async function G(){const t=c.platform(),e=t==="win32"?await _():t==="darwin"?await D():await A();return{uploadTotalBytes:e?.uploadTotalBytes||0,downloadTotalBytes:e?.downloadTotalBytes||0,sampledAt:Date.now()}}async function I(){const t=await G(),e=p;if(p=t,!e)return{uploadBytesPerSecond:0,downloadBytesPerSecond:0,uploadTotalBytes:t.uploadTotalBytes,downloadTotalBytes:t.downloadTotalBytes};const o=Math.max(1,(t.sampledAt-e.sampledAt)/1e3);return{uploadBytesPerSecond:Math.max(0,Math.round((t.uploadTotalBytes-e.uploadTotalBytes)/o)),downloadBytesPerSecond:Math.max(0,Math.round((t.downloadTotalBytes-e.downloadTotalBytes)/o)),uploadTotalBytes:t.uploadTotalBytes,downloadTotalBytes:t.downloadTotalBytes}}async function U(){const[t,e,o,n]=await Promise.all([P(),Promise.resolve(x()),v(),I()]);return{ok:!0,collectedAt:new Date().toISOString(),cpu:t,memory:e,storage:o,network:n}}export{U as collectSystemMetrics};
2
2
 
@@ -1,2 +1,2 @@
1
- import R,{AxiosError as x}from"axios";import p from"ws";import{getRuntimeAccessToken as M,normalizeSchedulerBaseUrl as S}from"./runtime-binding.js";import{loadConfigs as L,loadPrimaryLifecycleConfig as O}from"./auto-register.js";import{logger as c}from"../utils/logger.js";import{getActiveBridgeHttpPort as k}from"../config.js";const D=15e3,W=5e3,P=200,$=1*1024*1024,q=4001,G=768*1024,H=384*1024,m=new Map;function J(e){const r=e.serverUrl,n=e.instanceId;if(!r||!n)return null;try{const t=new URL(r),o=t.protocol==="https:"?"wss:":"ws:",i=M(r),l=L().find(h=>S(h.serverUrl)===r)||O(),s=i||l.userKey;if(i?c.debug("[TunnelClient] \u4F7F\u7528 runtime access token \u8FDE\u63A5\u96A7\u9053"):l.userKey&&c.warn("[TunnelClient] getRuntimeAccessToken \u8FD4\u56DE\u7A7A\uFF0C\u56DE\u9000\u5230 userKey\uFF08\u975E runtime token\uFF0C\u9274\u6743\u53EF\u80FD\u5931\u8D25\uFF09: targetUrl=",r),!s)return c.warn("[TunnelClient] \u7F3A\u5C11 runtime token\uFF0C\u65E0\u6CD5\u5EFA\u7ACB\u96A7\u9053: targetUrl=",r),null;const a=new URLSearchParams({instanceId:n});return{url:`${o}//${t.host}/ws/bridge-tunnel?${a.toString()}`,token:s}}catch(t){return c.warn("[TunnelClient] \u65E0\u6CD5\u89E3\u6790 serverUrl:",String(t)),null}}function re(e,r){const n=S(e);if(!n){c.warn("[TunnelClient] serverUrl \u65E0\u6548\uFF0C\u65E0\u6CD5\u542F\u52A8\u96A7\u9053:",e);return}const t=m.get(n);t&&(t.shuttingDown=!0,C(t),m.delete(n));const o={serverUrl:n,instanceId:r,streams:new Map,shuttingDown:!1};m.set(n,o),B(o)}function te(){for(const e of m.values())e.shuttingDown=!0,C(e);m.clear()}function oe(e){const r=S(e);if(!r)return;const n=m.get(r);n&&(n.shuttingDown=!0,C(n),m.delete(r),c.info(`[TunnelClient] tunnel stopped: ${r}`))}function se(e){const r=new Set(e.map(n=>S(n)).filter(n=>!!n));for(const[n,t]of m.entries())r.has(n)||(c.info(`[TunnelClient] serverUrl \u5DF2\u4E0D\u5728\u914D\u7F6E\u4E2D\uFF0C\u505C\u6B62\u65E7\u96A7\u9053: ${n}`),t.shuttingDown=!0,C(t),m.delete(n))}function C(e){e.timer&&(clearInterval(e.timer),e.timer=void 0),e.reconnectTimer&&(clearTimeout(e.reconnectTimer),e.reconnectTimer=void 0);for(const[r,n]of e.streams.entries()){try{n.ws.close(1e3,"tunnel client stopped")}catch{}e.streams.delete(r)}if(e.ws){e.ws.removeAllListeners();try{e.ws.close(1e3,"tunnel client stopped")}catch{}e.ws=void 0}}function B(e){if(e.shuttingDown)return;const r=e.instanceId;if(!r)return;const n=J(e);if(!n){b(e);return}c.info("[TunnelClient] \u8FDE\u63A5\u96A7\u9053\u670D\u52A1\u7AEF:",n.url);const t=new p(n.url,{handshakeTimeout:15e3,headers:{"X-Runtime-Token":n.token}});e.ws=t,t.on("open",()=>{c.info("[TunnelClient] \u96A7\u9053\u8FDE\u63A5\u5DF2\u5EFA\u7ACB: server=",e.serverUrl,"instanceId=",r),e.reconnectTimer&&clearTimeout(e.reconnectTimer),e.reconnectTimer=void 0,e.timer=setInterval(()=>{t.readyState===p.OPEN&&t.send(JSON.stringify({t:"ping"}))},D)}),t.on("unexpected-response",(o,i)=>{c.error("[TunnelClient] \u670D\u52A1\u7AEF\u62D2\u7EDD\u8FDE\u63A5\uFF08\u975E 101 \u54CD\u5E94\uFF09: server=",e.serverUrl,"statusCode=",i.statusCode,"statusMessage=",i.statusMessage)}),t.on("upgrade",o=>{c.debug("[TunnelClient] \u6536\u5230\u5347\u7EA7\u54CD\u5E94: statusCode=",o.statusCode)}),t.on("message",o=>{let i;typeof o=="string"?i=o:Buffer.isBuffer(o)?i=o.toString("utf-8"):i=Buffer.from(o).toString("utf-8");try{const l=JSON.parse(i);K(e,l)}catch(l){c.warn("[TunnelClient] \u89E3\u6790\u96A7\u9053\u6D88\u606F\u5931\u8D25:",String(l))}}),t.on("close",(o,i)=>{if(c.warn("[TunnelClient] \u96A7\u9053\u8FDE\u63A5\u5173\u95ED: server=",e.serverUrl,"code=",o,"reason=",String(i)),U(e),o===q){c.warn("[TunnelClient] \u9274\u6743\u5931\u8D25\uFF084001\uFF09\uFF0C\u505C\u6B62\u81EA\u52A8\u91CD\u8FDE\uFF1B\u5F85\u91CD\u65B0\u6CE8\u518C\u540E\u518D\u542F\u52A8\u96A7\u9053: server=",e.serverUrl);return}b(e)}),t.on("error",o=>{c.warn("[TunnelClient] \u96A7\u9053\u8FDE\u63A5\u9519\u8BEF: server=",e.serverUrl,"err=",o.message,"code=",o.code),U(e),b(e)})}function U(e){e.timer&&(clearInterval(e.timer),e.timer=void 0);for(const[r,n]of e.streams.entries()){try{n.ws.close(1011,"tunnel disconnected")}catch{}e.streams.delete(r)}e.ws=void 0}function b(e){e.shuttingDown||e.reconnectTimer||(e.reconnectTimer=setTimeout(()=>{e.reconnectTimer=void 0,B(e)},W))}function K(e,r){switch(r.t){case"req":z(e,r);break;case"wsopen":F(e,r);break;case"wsmsg":X(e,r);break;case"wsclose":Y(e,r);break;case"ping":f(e,{t:"pong"});break;case"pong":break;default:c.debug("[TunnelClient] \u672A\u77E5\u6D88\u606F\u7C7B\u578B: t=",r.t)}}async function z(e,r){const n=r.id,t=r.method||"GET",o=r.path||"/",i=`http://127.0.0.1:${k()}${o}`;try{const l=r.body?Buffer.from(r.body,"base64"):void 0,s={};if(r.headers)for(const[d,u]of Object.entries(r.headers))u&&u.length>0&&(s[d]=u[0]);s["x-bridge-tunnel-source"]=e.serverUrl;const a=await R.request({url:i,method:t,headers:s,data:l,timeout:0,responseType:"stream",validateStatus:()=>!0}),h={};for(const[d,u]of Object.entries(a.headers))u!==void 0&&(h[d]=Array.isArray(u)?u:[String(u)]);const E=a.data,A=String(h["content-type"]?.[0]||"").toLowerCase().includes("text/event-stream"),g=[];let w=0,T=!1,y=!1;try{if(E)for await(const d of E){const u=Buffer.isBuffer(d)?d:Buffer.from(d);if(u.length!==0){if(T){if(!v(e,n,u))return}else if(A){if(T=!0,y=!0,!f(e,{t:"res",id:n,status:a.status,headers:h,body:null,chunked:!0})||!v(e,n,u))return}else if(g.push(u),w+=u.length,w>G){if(T=!0,y=!0,!f(e,{t:"res",id:n,status:a.status,headers:h,body:null,chunked:!0}))return;for(const N of g)if(!v(e,n,N))return;g.length=0,w=0}}}}catch(d){const u=d instanceof Error?d.message:String(d);c.warn("[TunnelClient] \u672C\u5730\u6D41\u8BFB\u53D6\u4E2D\u65AD:",t,o,"->",u),y?f(e,{t:"resend",id:n,error:u}):f(e,{t:"res",id:n,status:502,headers:{"content-type":["text/plain; charset=utf-8"]},body:Buffer.from(u).toString("base64")});return}if(T){f(e,{t:"resend",id:n});return}const I=w>0?Buffer.concat(g).toString("base64"):"";f(e,{t:"res",id:n,status:a.status,headers:h,body:I||null})}catch(l){const s=l instanceof x?l.message:String(l);c.warn("[TunnelClient] \u672C\u5730\u8F6C\u53D1\u5931\u8D25:",t,o,"->",s),f(e,{t:"res",id:n,status:502,headers:{"content-type":["text/plain; charset=utf-8"]},body:Buffer.from(s).toString("base64")})}}function v(e,r,n){let t=0;for(;t<n.length;){const o=n.subarray(t,t+H);if(!f(e,{t:"reschunk",id:r,d:o.toString("base64")}))return!1;t+=o.length}return!0}function F(e,r){const n=r.id,t=r.path||"/",o=`ws://127.0.0.1:${k()}${t}`;let i;try{i=new p(o,{handshakeTimeout:1e4})}catch(s){c.warn("[TunnelClient] \u672C\u5730 WS \u8FDE\u63A5\u5931\u8D25:",String(s)),f(e,{t:"wsclose",id:n,code:1011,reason:"local ws connect failed"});return}const l={ws:i,pending:[]};e.streams.set(n,l),i.on("open",()=>{for(const s of l.pending)_(l,s.data,s.bin);l.pending=[],f(e,{t:"wsopened",id:n})}),i.on("message",(s,a)=>{const h=Buffer.isBuffer(s)?s:Buffer.from(s);a&&e.ws&&e.ws.bufferedAmount>$||f(e,{t:"wsmsg",id:n,bin:a,d:h.toString("base64")})}),i.on("close",(s,a)=>{e.streams.delete(n),f(e,{t:"wsclose",id:n,code:s,reason:String(a)})}),i.on("error",s=>{c.warn("[TunnelClient] \u672C\u5730 WS \u9519\u8BEF: id=",n,"err=",s.message),e.streams.delete(n);try{i.close(1011,s.message)}catch{}f(e,{t:"wsclose",id:n,code:1011,reason:s.message})})}function _(e,r,n){n?e.ws.send(r):e.ws.send(r.toString("utf-8"))}function X(e,r){const n=e.streams.get(r.id);if(!n)return;const t=r.d?Buffer.from(r.d,"base64"):Buffer.alloc(0);if(n.ws.readyState!==p.OPEN){n.pending.length>=P&&(n.pending.shift(),c.warn("[TunnelClient] \u672C\u5730 WS \u672A\u5C31\u7EEA\uFF0C\u6392\u961F\u6D88\u606F\u8D85\u4E0A\u9650\uFF0C\u4E22\u5F03\u6700\u65E7\u4E00\u6761: id=",r.id)),n.pending.push({data:t,bin:!!r.bin});return}_(n,t,!!r.bin)}function Y(e,r){const n=e.streams.get(r.id);if(n){e.streams.delete(r.id);try{n.ws.close(r.code??1e3,r.reason||"")}catch{}}}function f(e,r){if(!e.ws||e.ws.readyState!==p.OPEN)return!1;try{return e.ws.send(JSON.stringify(r)),!0}catch(n){return c.warn("[TunnelClient] sendJson \u5931\u8D25:",String(n)),!1}}export{re as startTunnelClient,te as stopTunnelClient,oe as stopTunnelClientForServer,se as stopTunnelClientsExcept};
1
+ import R,{AxiosError as x}from"axios";import p from"ws";import{getActiveBridgeHttpPort as k}from"../config.js";import{logger as c}from"../utils/logger.js";import{loadConfigs as M,loadPrimaryLifecycleConfig as L}from"./auto-register.js";import{getRuntimeAccessToken as O,normalizeSchedulerBaseUrl as S}from"./runtime-binding.js";const D=15e3,W=5e3,P=200,$=1*1024*1024,q=4001,G=768*1024,H=384*1024,m=new Map;function J(e){const r=e.serverUrl,n=e.instanceId;if(!r||!n)return null;try{const t=new URL(r),o=t.protocol==="https:"?"wss:":"ws:",i=O(r),l=M().find(h=>S(h.serverUrl)===r)||L(),s=i||l.userKey;if(i?c.debug("[TunnelClient] \u4F7F\u7528 runtime access token \u8FDE\u63A5\u96A7\u9053"):l.userKey&&c.warn("[TunnelClient] getRuntimeAccessToken \u8FD4\u56DE\u7A7A\uFF0C\u56DE\u9000\u5230 userKey\uFF08\u975E runtime token\uFF0C\u9274\u6743\u53EF\u80FD\u5931\u8D25\uFF09: targetUrl=",r),!s)return c.warn("[TunnelClient] \u7F3A\u5C11 runtime token\uFF0C\u65E0\u6CD5\u5EFA\u7ACB\u96A7\u9053: targetUrl=",r),null;const a=new URLSearchParams({instanceId:n});return{url:`${o}//${t.host}/ws/bridge-tunnel?${a.toString()}`,token:s}}catch(t){return c.warn("[TunnelClient] \u65E0\u6CD5\u89E3\u6790 serverUrl:",String(t)),null}}function re(e,r){const n=S(e);if(!n){c.warn("[TunnelClient] serverUrl \u65E0\u6548\uFF0C\u65E0\u6CD5\u542F\u52A8\u96A7\u9053:",e);return}const t=m.get(n);t&&(t.shuttingDown=!0,C(t),m.delete(n));const o={serverUrl:n,instanceId:r,streams:new Map,shuttingDown:!1};m.set(n,o),B(o)}function te(){for(const e of m.values())e.shuttingDown=!0,C(e);m.clear()}function oe(e){const r=S(e);if(!r)return;const n=m.get(r);n&&(n.shuttingDown=!0,C(n),m.delete(r),c.info(`[TunnelClient] tunnel stopped: ${r}`))}function se(e){const r=new Set(e.map(n=>S(n)).filter(n=>!!n));for(const[n,t]of m.entries())r.has(n)||(c.info(`[TunnelClient] serverUrl \u5DF2\u4E0D\u5728\u914D\u7F6E\u4E2D\uFF0C\u505C\u6B62\u65E7\u96A7\u9053: ${n}`),t.shuttingDown=!0,C(t),m.delete(n))}function C(e){e.timer&&(clearInterval(e.timer),e.timer=void 0),e.reconnectTimer&&(clearTimeout(e.reconnectTimer),e.reconnectTimer=void 0);for(const[r,n]of e.streams.entries()){try{n.ws.close(1e3,"tunnel client stopped")}catch{}e.streams.delete(r)}if(e.ws){e.ws.removeAllListeners();try{e.ws.close(1e3,"tunnel client stopped")}catch{}e.ws=void 0}}function B(e){if(e.shuttingDown)return;const r=e.instanceId;if(!r)return;const n=J(e);if(!n){b(e);return}c.info("[TunnelClient] \u8FDE\u63A5\u96A7\u9053\u670D\u52A1\u7AEF:",n.url);const t=new p(n.url,{handshakeTimeout:15e3,headers:{"X-Runtime-Token":n.token}});e.ws=t,t.on("open",()=>{c.info("[TunnelClient] \u96A7\u9053\u8FDE\u63A5\u5DF2\u5EFA\u7ACB: server=",e.serverUrl,"instanceId=",r),e.reconnectTimer&&clearTimeout(e.reconnectTimer),e.reconnectTimer=void 0,e.timer=setInterval(()=>{t.readyState===p.OPEN&&t.send(JSON.stringify({t:"ping"}))},D)}),t.on("unexpected-response",(o,i)=>{c.error("[TunnelClient] \u670D\u52A1\u7AEF\u62D2\u7EDD\u8FDE\u63A5\uFF08\u975E 101 \u54CD\u5E94\uFF09: server=",e.serverUrl,"statusCode=",i.statusCode,"statusMessage=",i.statusMessage)}),t.on("upgrade",o=>{c.debug("[TunnelClient] \u6536\u5230\u5347\u7EA7\u54CD\u5E94: statusCode=",o.statusCode)}),t.on("message",o=>{let i;typeof o=="string"?i=o:Buffer.isBuffer(o)?i=o.toString("utf-8"):i=Buffer.from(o).toString("utf-8");try{const l=JSON.parse(i);K(e,l)}catch(l){c.warn("[TunnelClient] \u89E3\u6790\u96A7\u9053\u6D88\u606F\u5931\u8D25:",String(l))}}),t.on("close",(o,i)=>{if(c.warn("[TunnelClient] \u96A7\u9053\u8FDE\u63A5\u5173\u95ED: server=",e.serverUrl,"code=",o,"reason=",String(i)),U(e),o===q){c.warn("[TunnelClient] \u9274\u6743\u5931\u8D25\uFF084001\uFF09\uFF0C\u505C\u6B62\u81EA\u52A8\u91CD\u8FDE\uFF1B\u5F85\u91CD\u65B0\u6CE8\u518C\u540E\u518D\u542F\u52A8\u96A7\u9053: server=",e.serverUrl);return}b(e)}),t.on("error",o=>{c.warn("[TunnelClient] \u96A7\u9053\u8FDE\u63A5\u9519\u8BEF: server=",e.serverUrl,"err=",o.message,"code=",o.code),U(e),b(e)})}function U(e){e.timer&&(clearInterval(e.timer),e.timer=void 0);for(const[r,n]of e.streams.entries()){try{n.ws.close(1011,"tunnel disconnected")}catch{}e.streams.delete(r)}e.ws=void 0}function b(e){e.shuttingDown||e.reconnectTimer||(e.reconnectTimer=setTimeout(()=>{e.reconnectTimer=void 0,B(e)},W))}function K(e,r){switch(r.t){case"req":z(e,r);break;case"wsopen":F(e,r);break;case"wsmsg":X(e,r);break;case"wsclose":Y(e,r);break;case"ping":f(e,{t:"pong"});break;case"pong":break;default:c.debug("[TunnelClient] \u672A\u77E5\u6D88\u606F\u7C7B\u578B: t=",r.t)}}async function z(e,r){const n=r.id,t=r.method||"GET",o=r.path||"/",i=`http://127.0.0.1:${k()}${o}`;try{const l=r.body?Buffer.from(r.body,"base64"):void 0,s={};if(r.headers)for(const[d,u]of Object.entries(r.headers))u&&u.length>0&&(s[d]=u[0]);s["x-bridge-tunnel-source"]=e.serverUrl;const a=await R.request({url:i,method:t,headers:s,data:l,timeout:0,responseType:"stream",validateStatus:()=>!0}),h={};for(const[d,u]of Object.entries(a.headers))u!==void 0&&(h[d]=Array.isArray(u)?u:[String(u)]);const E=a.data,A=String(h["content-type"]?.[0]||"").toLowerCase().includes("text/event-stream"),g=[];let w=0,T=!1,y=!1;try{if(E)for await(const d of E){const u=Buffer.isBuffer(d)?d:Buffer.from(d);if(u.length!==0){if(T){if(!v(e,n,u))return}else if(A){if(T=!0,y=!0,!f(e,{t:"res",id:n,status:a.status,headers:h,body:null,chunked:!0})||!v(e,n,u))return}else if(g.push(u),w+=u.length,w>G){if(T=!0,y=!0,!f(e,{t:"res",id:n,status:a.status,headers:h,body:null,chunked:!0}))return;for(const N of g)if(!v(e,n,N))return;g.length=0,w=0}}}}catch(d){const u=d instanceof Error?d.message:String(d);c.warn("[TunnelClient] \u672C\u5730\u6D41\u8BFB\u53D6\u4E2D\u65AD:",t,o,"->",u),y?f(e,{t:"resend",id:n,error:u}):f(e,{t:"res",id:n,status:502,headers:{"content-type":["text/plain; charset=utf-8"]},body:Buffer.from(u).toString("base64")});return}if(T){f(e,{t:"resend",id:n});return}const I=w>0?Buffer.concat(g).toString("base64"):"";f(e,{t:"res",id:n,status:a.status,headers:h,body:I||null})}catch(l){const s=l instanceof x?l.message:String(l);c.warn("[TunnelClient] \u672C\u5730\u8F6C\u53D1\u5931\u8D25:",t,o,"->",s),f(e,{t:"res",id:n,status:502,headers:{"content-type":["text/plain; charset=utf-8"]},body:Buffer.from(s).toString("base64")})}}function v(e,r,n){let t=0;for(;t<n.length;){const o=n.subarray(t,t+H);if(!f(e,{t:"reschunk",id:r,d:o.toString("base64")}))return!1;t+=o.length}return!0}function F(e,r){const n=r.id,t=r.path||"/",o=`ws://127.0.0.1:${k()}${t}`;let i;try{i=new p(o,{handshakeTimeout:1e4})}catch(s){c.warn("[TunnelClient] \u672C\u5730 WS \u8FDE\u63A5\u5931\u8D25:",String(s)),f(e,{t:"wsclose",id:n,code:1011,reason:"local ws connect failed"});return}const l={ws:i,pending:[]};e.streams.set(n,l),i.on("open",()=>{for(const s of l.pending)_(l,s.data,s.bin);l.pending=[],f(e,{t:"wsopened",id:n})}),i.on("message",(s,a)=>{const h=Buffer.isBuffer(s)?s:Buffer.from(s);a&&e.ws&&e.ws.bufferedAmount>$||f(e,{t:"wsmsg",id:n,bin:a,d:h.toString("base64")})}),i.on("close",(s,a)=>{e.streams.delete(n),f(e,{t:"wsclose",id:n,code:s,reason:String(a)})}),i.on("error",s=>{c.warn("[TunnelClient] \u672C\u5730 WS \u9519\u8BEF: id=",n,"err=",s.message),e.streams.delete(n);try{i.close(1011,s.message)}catch{}f(e,{t:"wsclose",id:n,code:1011,reason:s.message})})}function _(e,r,n){n?e.ws.send(r):e.ws.send(r.toString("utf-8"))}function X(e,r){const n=e.streams.get(r.id);if(!n)return;const t=r.d?Buffer.from(r.d,"base64"):Buffer.alloc(0);if(n.ws.readyState!==p.OPEN){n.pending.length>=P&&(n.pending.shift(),c.warn("[TunnelClient] \u672C\u5730 WS \u672A\u5C31\u7EEA\uFF0C\u6392\u961F\u6D88\u606F\u8D85\u4E0A\u9650\uFF0C\u4E22\u5F03\u6700\u65E7\u4E00\u6761: id=",r.id)),n.pending.push({data:t,bin:!!r.bin});return}_(n,t,!!r.bin)}function Y(e,r){const n=e.streams.get(r.id);if(n){e.streams.delete(r.id);try{n.ws.close(r.code??1e3,r.reason||"")}catch{}}}function f(e,r){if(!e.ws||e.ws.readyState!==p.OPEN)return!1;try{return e.ws.send(JSON.stringify(r)),!0}catch(n){return c.warn("[TunnelClient] sendJson \u5931\u8D25:",String(n)),!1}}export{re as startTunnelClient,te as stopTunnelClient,oe as stopTunnelClientForServer,se as stopTunnelClientsExcept};
2
2
 
@@ -1,3 +1,3 @@
1
- import l from"node:fs/promises";import g from"node:path";import v from"axios";import{getActiveBridgeHttpPort as E,getRuntimeHomeDir as w}from"../config.js";import{loadConfigs as A}from"./auto-register.js";import{getRuntimeAccessToken as S}from"./runtime-binding.js";import{appendUpdateLog as $}from"./update-log.js";import{checkBridgeUpdate as h}from"../utils/npm-version.js";import{createLogger as D}from"../utils/logger.js";const r=D("update-notifier"),N=6*60*60*1e3,U=3e4,y="\u5F53\u524D\u5BA2\u6237\u7AEFbridge\u53EF\u66F4\u65B0\uFF0C\u8BF7\u53CA\u65F6\u66F4\u65B0~";function I(){return g.join(w(),".aws-bridge","update-notify-state.json")}async function T(){try{const e=await l.readFile(I(),"utf8"),n=JSON.parse(e);return{latestVersion:n.latestVersion,notifiedAt:n.notifiedAt}}catch{return{}}}async function b(e){const n=I();await l.mkdir(g.dirname(n),{recursive:!0}),await l.writeFile(n,`${JSON.stringify(e,null,2)}
2
- `,{encoding:"utf8",mode:384})}async function _(){const e=await h();if(!e.ok||!e.hasUpdate||!e.latestVersion||(await T()).latestVersion===e.latestVersion)return!1;const a=A().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,f=e.latestVersion,d=a[0]?.instanceName||"",u={eventType:"update-available",bridgeInstanceId:a[0]?.instanceId||"",bridgeInstanceName:d,currentVersion:i,latestVersion:f,message:y,runtimeBridgeBaseUrl:`http://127.0.0.1:${E()}`},c=await Promise.allSettled(a.map(async t=>{const o=String(t.serverUrl).replace(/\/+$/,""),m=S(o);if(!m)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");await v.post(`${o}/api/runtime/callback/bridge-update-notify`,{...u,bridgeInstanceId:t.instanceId||u.bridgeInstanceId,bridgeInstanceName:t.instanceName||d},{headers:{"X-Runtime-Token":m},timeout:1e4})})),p=c.some(t=>t.status==="fulfilled");if(p)await b({latestVersion:f,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${f}`),$(`\u68C0\u6D4B\u5230\u65B0\u7248\u672C v${f}\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 p}let s=null;function x(){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:N;setTimeout(()=>{_().catch(i=>{r.warn(`[update-notifier] \u68C0\u67E5\u5F02\u5E38: ${i?.message}`)})},U).unref?.(),s=setInterval(()=>{_().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 K(){s&&(clearInterval(s),s=null)}export{_ as runUpdateCheck,x as startUpdateNotifier,K as stopUpdateNotifier};
1
+ import l from"node:fs/promises";import g from"node:path";import v from"axios";import{getActiveBridgeHttpPort as E,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 $}from"./auto-register.js";import{getRuntimeAccessToken as h}from"./runtime-binding.js";import{appendUpdateLog as D}from"./update-log.js";const r=A("update-notifier"),N=6*60*60*1e3,U=3e4,y="\u5F53\u524D\u5BA2\u6237\u7AEFbridge\u53EF\u66F4\u65B0\uFF0C\u8BF7\u53CA\u65F6\u66F4\u65B0~";function I(){return g.join(w(),".aws-bridge","update-notify-state.json")}async function T(){try{const e=await l.readFile(I(),"utf8"),n=JSON.parse(e);return{latestVersion:n.latestVersion,notifiedAt:n.notifiedAt}}catch{return{}}}async function b(e){const n=I();await l.mkdir(g.dirname(n),{recursive:!0}),await l.writeFile(n,`${JSON.stringify(e,null,2)}
2
+ `,{encoding:"utf8",mode:384})}async function _(){const e=await S();if(!e.ok||!e.hasUpdate||!e.latestVersion||(await T()).latestVersion===e.latestVersion)return!1;const a=$().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,f=e.latestVersion,d=a[0]?.instanceName||"",u={eventType:"update-available",bridgeInstanceId:a[0]?.instanceId||"",bridgeInstanceName:d,currentVersion:i,latestVersion:f,message:y,runtimeBridgeBaseUrl:`http://127.0.0.1:${E()}`},c=await Promise.allSettled(a.map(async t=>{const o=String(t.serverUrl).replace(/\/+$/,""),m=h(o);if(!m)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");await v.post(`${o}/api/runtime/callback/bridge-update-notify`,{...u,bridgeInstanceId:t.instanceId||u.bridgeInstanceId,bridgeInstanceName:t.instanceName||d},{headers:{"X-Runtime-Token":m},timeout:1e4})})),p=c.some(t=>t.status==="fulfilled");if(p)await b({latestVersion:f,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${f}`),D(`\u68C0\u6D4B\u5230\u65B0\u7248\u672C v${f}\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 p}let s=null;function x(){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:N;setTimeout(()=>{_().catch(i=>{r.warn(`[update-notifier] \u68C0\u67E5\u5F02\u5E38: ${i?.message}`)})},U).unref?.(),s=setInterval(()=>{_().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 K(){s&&(clearInterval(s),s=null)}export{_ as runUpdateCheck,x as startUpdateNotifier,K as stopUpdateNotifier};
3
3
 
@@ -1,2 +1,2 @@
1
- import{createRequire as s}from"node:module";import{mkdirSync as c}from"node:fs";let e;function o(){if(e!==void 0)return e;try{e=s(import.meta.url)("node-windows").Service}catch{e=null}return e}function w(){return o()!==null}function m(){return{async install(r){const n=o();if(!n)throw new Error("node-windows \u672A\u5B89\u88C5\u3002\u8BF7\u91CD\u65B0\u5B89\u88C5 aws-runtime-bridge\uFF1Anpm install -g aws-runtime-bridge");if(r.logpath)try{c(r.logpath,{recursive:!0})}catch{}const t=new n({name:r.name,description:r.description,script:r.script,workingDirectory:r.workingDirectory,env:r.env,logpath:r.logpath,logmode:"rotate"});await new Promise((i,a)=>{t.on("install",()=>i()),t.on("alreadyinstalled",()=>i()),t.on("error",l=>a(l)),t.install()})}}}export{m as createWindowsServiceManager,w as isNodeWindowsAvailable};
1
+ import{mkdirSync as s}from"node:fs";import{createRequire as c}from"node:module";let e=null;function o(){if(e!==null)return e;try{e=c(import.meta.url)("node-windows").Service}catch{e=null}return e}function w(){return o()!==null}function m(){return{async install(r){const n=o();if(!n)throw new Error("node-windows \u672A\u5B89\u88C5\u3002\u8BF7\u91CD\u65B0\u5B89\u88C5 aws-runtime-bridge\uFF1Anpm install -g aws-runtime-bridge");if(r.logpath)try{s(r.logpath,{recursive:!0})}catch{}const t=new n({name:r.name,description:r.description,script:r.script,workingDirectory:r.workingDirectory,env:r.env,logpath:r.logpath,logmode:"rotate"});await new Promise((i,a)=>{t.on("install",()=>i()),t.on("alreadyinstalled",()=>i()),t.on("error",l=>a(l)),t.install()})}}}export{m as createWindowsServiceManager,w as isNodeWindowsAvailable};
2
2
 
@@ -1,2 +1,2 @@
1
- import{createReadStream as U,createWriteStream as O,promises as s}from"node:fs";import lt from"node:os";import d from"node:path";import{Readable as ht}from"node:stream";import{pipeline as ut}from"node:stream/promises";import{TextDecoder as dt}from"node:util";import{createGunzip as wt}from"node:zlib";import*as ft from"tar";import pt from"unzipper";const{ZipArchive:_}=await import("archiver"),x={maxEntries:1e4,maxFileBytes:512*1024*1024,maxTotalBytes:2*1024*1024*1024,maxPathDepth:64,maxPathLength:4096},mt=new dt("gbk");function u(t){return String(t||"").replace(/\\/g,"/")}function Z(t){const e=d.resolve(String(t||"").trim());if(!e)throw new Error("workspacePath is required");return e}async function yt(t){const e=Z(t),r=await s.realpath(e);if(!(await s.stat(r)).isDirectory())throw new Error(`Workspace path is not a directory: ${e}`);return r}async function v(t){return{requestedRoot:Z(t),workspaceRoot:await yt(t)}}function C(t,e){const r=d.resolve(e),i=d.relative(t,r);if(i.startsWith("..")||d.isAbsolute(i))throw new Error(`Target path is outside workspace: ${r}`);return r}async function F(t){return s.realpath(t)}async function T(t){await s.realpath(d.dirname(t));try{if((await s.lstat(t)).isSymbolicLink())throw new Error(`Refusing to write through symbolic link: ${t}`)}catch(e){if((typeof e=="object"&&e!==null?Reflect.get(e,"code"):void 0)!=="ENOENT")throw e}}function L(t,e,r){const i=d.resolve(r),o=d.relative(t,i);return o.startsWith("..")||d.isAbsolute(o)?i:C(e,d.join(e,o))}async function b({workspacePath:t,targetPath:e=""}){const{requestedRoot:r,workspaceRoot:i}=await v(t),o=String(e||"").trim(),a=o?L(r,i,o):i,c=await F(a);return{workspaceRoot:i,resolvedTargetPath:c}}function $(t){const e=String(t||"").trim();if(!e)throw new Error("entryName is required");if(e==="."||e==="..")throw new Error("entryName is invalid");if(e.includes("/")||e.includes("\\")||d.basename(e)!==e)throw new Error(`entryName must be a plain file or directory name: ${e}`);return e}function G(t){const e=String(t||"");if(!/[\u00c0-\u00ff]/.test(e))return e;const r=Buffer.from(e,"latin1").toString("utf8");return!r||r.includes("\uFFFD")?e:r}function B(t){const e=G(t);return $(d.basename(e.replace(/\\/g,"/")))}function gt(t,e){if(!t)return B(e);const i=G(String(t||e||"")).replace(/\\/g,"/").split("/").filter(Boolean).map(o=>$(o));return i.length===0?B(e):d.join(...i)}function H(t){return(t&4095).toString(8).padStart(4,"0")}function Pt(t){const e=String(t||"").trim();if(!/^[0-7]{3,4}$/.test(e))throw new Error("mode must be a 3 or 4 digit octal string");return Number.parseInt(e,8)}function I(t,e,r,i,o,a,c){const n=t&e?"r":"-",l=t&r?"w":"-",h=(t&i)!==0,f=(t&o)!==0?h?a:c:h?"x":"-";return`${n}${l}${f}`}function kt(t){return[I(t,256,128,64,2048,"s","S"),I(t,32,16,8,1024,"s","S"),I(t,4,2,1,512,"t","T")].join("")}function xt(t){if(!(t.length<24||t.toString("hex",0,8)!=="89504e470d0a1a0a"))return{format:"png",width:t.readUInt32BE(16),height:t.readUInt32BE(20)}}function vt(t){if(!(t.length<10||t.toString("ascii",0,6)!=="GIF87a"&&t.toString("ascii",0,6)!=="GIF89a"))return{format:"gif",width:t.readUInt16LE(6),height:t.readUInt16LE(8)}}function Et(t){if(t.length<4||t[0]!==255||t[1]!==216)return;let e=2;for(;e+9<t.length;){if(t[e]!==255){e+=1;continue}const r=t[e+1],i=t.readUInt16BE(e+2);if(i<2)return;if(r>=192&&r<=207&&![196,200,204].includes(r)&&e+8<t.length)return{format:"jpeg",height:t.readUInt16BE(e+5),width:t.readUInt16BE(e+7)};e+=2+i}}function St(t){if(t.length<30||t.toString("ascii",0,4)!=="RIFF"||t.toString("ascii",8,12)!=="WEBP")return;const e=t.toString("ascii",12,16);if(e==="VP8X"&&t.length>=30)return{format:"webp",width:1+t.readUIntLE(24,3),height:1+t.readUIntLE(27,3)};if(e==="VP8 "&&t.length>=30)return{format:"webp",width:t.readUInt16LE(26)&16383,height:t.readUInt16LE(28)&16383};if(e==="VP8L"&&t.length>=25){const r=t.readUInt32LE(21);return{format:"webp",width:(r&16383)+1,height:(r>>14&16383)+1}}}async function K(t,e){if((await s.lstat(t)).isSymbolicLink())throw new Error(`Refusing to change permissions on symbolic link: ${t}`);const i=await s.stat(t);if(!e||!i.isDirectory())return[t];const o=await s.readdir(t),a=await Promise.all(o.map(c=>{const n=d.join(t,c);return K(n,!0)}));return[t,...a.flat()]}async function Rt(t){if((await s.lstat(t)).isSymbolicLink())throw new Error(`Refusing to change permissions on symbolic link: ${t}`);await F(t)}async function Dt(t){const e=await s.open(t,"r");try{const r=Buffer.alloc(512),{bytesRead:i}=await e.read(r,0,r.length,0),o=r.subarray(0,i);return xt(o)||vt(o)||Et(o)||St(o)}finally{await e.close()}}async function z({workspacePath:t,targetPath:e},r={}){const{requestedRoot:i,workspaceRoot:o}=await v(t),a=String(e||"").trim();if(!a)throw new Error("targetPath is required");const c=L(i,o,a),n=await F(c);if(!r.allowWorkspaceRoot&&n===o)throw new Error("Workspace root cannot be modified");return{workspaceRoot:o,resolvedTargetPath:n}}async function X(t){const{requestedRoot:e,workspaceRoot:r}=await v(t.workspacePath),i=String(t.targetPath||"").trim();if(!i)return{workspaceRoot:r,resolvedTargetPath:r};const o=L(e,r,i);return await et(o)?{workspaceRoot:r,resolvedTargetPath:await s.realpath(o)}:(await s.realpath(d.dirname(o)),{workspaceRoot:r,resolvedTargetPath:o})}function V(t){const e=t.toLowerCase();return e.endsWith(".zip")?"zip":e.endsWith(".tar.gz")||e.endsWith(".tgz")?"tgz":e.endsWith(".tar")?"tar":e.endsWith(".gz")?"gz":null}function Y(t){return t.replace(/\.tar\.gz$/i,"").replace(/\.tgz$/i,"").replace(/\.zip$/i,"").replace(/\.tar$/i,"").replace(/\.gz$/i,"")}function Ft(t,e){const r=$(Y(e)||"extracted");return d.join(t,r)}function M(t,e){const r=String(e||"").replace(/\\/g,"/"),i=r.split("/").filter(Boolean);if(!r||r.startsWith("/")||/^[A-Za-z]:/.test(r))throw new Error(`Archive entry path is invalid: ${e}`);if(r.length>x.maxPathLength||i.length>x.maxPathDepth)throw new Error(`Archive entry path is too deep or too long: ${e}`);return C(t,d.join(t,r))}function Tt(t){const e=t.props?.pathBuffer;if(!e||t.props?.flags?.isUnicode)return t.path;const r=mt.decode(e);return!r||r.includes("\uFFFD")?t.path:r}async function J(t){const e=t.autodrain?.();e&&await new Promise((r,i)=>{e.on("close",r),e.on("end",r),e.on("finish",r),e.on("error",i)})}function N(t){if(t.entries+=1,t.entries>x.maxEntries)throw new Error(`Archive contains too many entries. Limit: ${x.maxEntries}`)}function Q(t,e){if(t.totalBytes+=e,e>x.maxFileBytes)throw new Error(`Archive entry exceeds max size. Limit: ${x.maxFileBytes} bytes`);if(t.totalBytes>x.maxTotalBytes)throw new Error(`Archive extraction exceeds total size. Limit: ${x.maxTotalBytes} bytes`)}async function tt(t,e,r){let i=0;t.on("data",o=>{const a=Buffer.isBuffer(o)?o.length:Buffer.byteLength(o);i+=a,(i>x.maxFileBytes||r.totalBytes+i>x.maxTotalBytes)&&t instanceof ht&&t.destroy(new Error("Archive extraction size limit exceeded"))}),await ut(t,O(e)),Q(r,i)}async function et(t){try{return await s.access(t),!0}catch(e){if((typeof e=="object"&&e!==null?Reflect.get(e,"code"):void 0)==="ENOENT")return!1;throw e}}async function W({workspacePath:t,filePath:e}){const{requestedRoot:r,workspaceRoot:i}=await v(t),o=String(e||"").trim();if(!o)throw new Error("filePath is required");return{workspaceRoot:i,resolvedFilePath:L(r,i,o)}}async function Gt(t){const{workspaceRoot:e}=await v(t.workspacePath),r=String(t.targetPath||"").trim();if(!r){const{resolvedTargetPath:l}=await b(t);return rt(e,l)}const i=d.resolve(r);let o;try{o=await s.realpath(i)}catch{throw new Error(`Path not found: ${i}`)}if(!(await s.stat(o)).isDirectory())throw new Error(`Path is not a directory: ${i}`);const c=d.relative(e,o),n=c===""||!c.startsWith("..")&&!d.isAbsolute(c);return rt(e,n?o:i)}async function rt(t,e){if(!(await s.stat(e)).isDirectory())throw new Error(`Path is not a directory: ${e}`);const i=await s.readdir(e,{withFileTypes:!0}),o=await Promise.all(i.map(async a=>{const c=d.join(e,a.name),n=a.isFile()?(await s.stat(c)).size:void 0;return{name:a.name,path:u(c),isDirectory:a.isDirectory(),size:n}}));return{currentPath:u(e),workspacePath:u(t),items:o}}async function Ht(t){const{workspaceRoot:e,resolvedFilePath:r}=await W(t),i=await F(r),o=await s.stat(i);if(!o.isFile())throw new Error(`Path is not a file: ${i}`);const a=await s.readFile(i,"utf-8");return{workspacePath:u(e),filePath:u(i),content:a,mtimeMs:o.mtimeMs}}const it={maxEntries:1e5,maxDepth:32};async function zt(t){let e=0,r=0;async function i(o,a){if(a>=it.maxDepth)return;let c;try{c=await s.readdir(o,{withFileTypes:!0})}catch{return}for(const n of c){if(r+=1,r>it.maxEntries)return;if(n.isSymbolicLink())continue;const l=d.join(o,n.name);try{if(n.isDirectory())await i(l,a+1);else if(n.isFile()){const h=await s.stat(l);e+=h.size}}catch{}}}return await i(t,0),e}async function Kt(t){const{workspaceRoot:e,resolvedTargetPath:r}=await z(t,{allowWorkspaceRoot:!0}),[i,o]=await Promise.all([s.stat(r),s.lstat(r)]),a=i.isDirectory(),c=i.isFile()?await Dt(r):void 0,n=a?await zt(r):i.size;return{workspacePath:u(e),targetPath:u(r),name:d.basename(r),isDirectory:i.isDirectory(),isFile:i.isFile(),isSymbolicLink:o.isSymbolicLink(),size:n,mode:i.mode,modeOctal:H(i.mode),permissions:kt(i.mode),uid:i.uid,gid:i.gid,atimeMs:i.atimeMs,mtimeMs:i.mtimeMs,ctimeMs:i.ctimeMs,birthtimeMs:i.birthtimeMs,...c?{image:c}:{}}}async function Xt(t){const e=Pt(t.mode),r=!!t.recursive,{workspaceRoot:i,resolvedTargetPath:o}=await z(t),a=await K(o,r);for(const c of a)await Rt(c),await s.chmod(c,e);return{ok:!0,workspacePath:u(i),targetPath:u(o),mode:e,modeOctal:H(e),recursive:r,changedCount:a.length}}async function Vt(t){const{workspaceRoot:e,resolvedFilePath:r}=await W(t),i=await F(r),o=await s.stat(i);if(!o.isFile())throw new Error(`Path is not a file: ${i}`);const a=d.extname(i).toLowerCase();if(a===".doc")return{workspacePath:u(e),filePath:u(i),kind:"unsupported",content:"",message:"\u6682\u4E0D\u652F\u6301\u65E7\u7248 .doc \u683C\u5F0F\u9884\u89C8\uFF0C\u8BF7\u53E6\u5B58\u4E3A .docx \u540E\u518D\u6253\u5F00\u3002",size:o.size,mtimeMs:o.mtimeMs};if(a!==".docx")throw new Error("Document preview only supports .docx files");return{workspacePath:u(e),filePath:u(i),kind:"html",content:"",size:o.size,mtimeMs:o.mtimeMs}}async function Yt(t){const{workspaceRoot:e,resolvedFilePath:r}=await W(t);await s.mkdir(d.dirname(r),{recursive:!0}),await T(r),await s.writeFile(r,String(t.content??""),"utf-8");const i=await s.stat(r);return{ok:!0,workspacePath:u(e),filePath:u(r),mtimeMs:i.mtimeMs}}async function Jt(t){const{workspaceRoot:e,resolvedTargetPath:r}=await b(t),i=$(t.entryName),o=d.join(r,i);if(!(await s.stat(r)).isDirectory())throw new Error(`Path is not a directory: ${r}`);try{throw await s.access(o),new Error(`Path already exists: ${o}`)}catch(c){if((typeof c=="object"&&c!==null?Reflect.get(c,"code"):void 0)!=="ENOENT")throw c}return t.isDirectory?await s.mkdir(o,{recursive:!1}):(await s.mkdir(d.dirname(o),{recursive:!0}),await T(o),await s.writeFile(o,"","utf-8")),{ok:!0,workspacePath:u(e),targetPath:u(o),isDirectory:t.isDirectory}}async function Qt(t){const{workspaceRoot:e,resolvedTargetPath:r}=await z(t),i=$(t.newName),o=d.join(d.dirname(r),i);if(o===r)return{ok:!0,workspacePath:u(e),sourcePath:u(r),targetPath:u(o)};await s.stat(r);try{throw await s.access(o),new Error(`Path already exists: ${o}`)}catch(a){if((typeof a=="object"&&a!==null?Reflect.get(a,"code"):void 0)!=="ENOENT")throw a}return await s.rename(r,o),{ok:!0,workspacePath:u(e),sourcePath:u(r),targetPath:u(o)}}async function te(t){const{workspaceRoot:e,resolvedTargetPath:r}=await z(t),i=await b({workspacePath:t.workspacePath,targetPath:t.destinationPath});if(!(await s.stat(i.resolvedTargetPath)).isDirectory())throw new Error(`Destination is not a directory: ${i.resolvedTargetPath}`);if((await s.stat(r)).isDirectory()){const n=d.relative(r,i.resolvedTargetPath);if(n===""||!n.startsWith("..")&&!d.isAbsolute(n))throw new Error("Cannot move a directory into itself or its descendant")}const c=d.join(i.resolvedTargetPath,d.basename(r));if(c===r)return{ok:!0,workspacePath:u(e),sourcePath:u(r),targetPath:u(c),destinationPath:u(i.resolvedTargetPath)};try{throw await s.access(c),new Error(`Path already exists: ${c}`)}catch(n){if((typeof n=="object"&&n!==null?Reflect.get(n,"code"):void 0)!=="ENOENT")throw n}return await s.rename(r,c),{ok:!0,workspacePath:u(e),sourcePath:u(r),targetPath:u(c),destinationPath:u(i.resolvedTargetPath)}}async function ee(t){const{workspaceRoot:e,resolvedTargetPath:r}=await z(t),i=await s.stat(r),o=d.parse(r).root;if(r===o)throw new Error("Filesystem root cannot be deleted");return i.isDirectory()?await s.rm(r,{recursive:!0,force:!1}):await s.unlink(r),{ok:!0,workspacePath:u(e),targetPath:u(r)}}async function re(t){if(!Array.isArray(t.files)||t.files.length===0)throw new Error("files are required");const{workspaceRoot:e,resolvedTargetPath:r}=await X(t);if(!(await s.stat(r)).isDirectory())throw new Error(`Path is not a directory: ${r}`);const o=[];for(const a of t.files){const c=B(a.originalname),n=gt(a.relativePath,a.originalname),l=d.join(r,n);await s.mkdir(d.dirname(l),{recursive:!0}),await T(l),await s.copyFile(a.path,l);let h;t.extractArchives&&V(l)&&(h=await Wt({workspacePath:e,archivePath:l,outputPath:Ft(r,c)})),o.push({fileName:c,targetPath:u(l),size:a.size,extracted:h})}return{ok:!0,workspacePath:u(e),targetPath:u(r),files:o}}async function ie(t){const{workspaceRoot:e,resolvedTargetPath:r}=await z(t),i=await s.stat(r),o=d.basename(r);return{workspacePath:u(e),targetPath:u(r),resolvedTargetPath:r,fileName:i.isDirectory()?`${o||"workspace"}.zip`:o,contentType:i.isDirectory()?"application/zip":Lt(r),isDirectory:i.isDirectory(),size:i.isDirectory()?void 0:i.size}}function Lt(t){const e=d.extname(t).toLowerCase();return{".svg":"image/svg+xml",".svgz":"image/svg+xml",".ico":"image/x-icon",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".bmp":"image/bmp",".avif":"image/avif",".txt":"text/plain; charset=utf-8",".json":"application/json; charset=utf-8",".xml":"application/xml; charset=utf-8",".html":"text/html; charset=utf-8",".htm":"text/html; charset=utf-8",".css":"text/css; charset=utf-8",".js":"text/javascript; charset=utf-8",".md":"text/markdown; charset=utf-8",".csv":"text/csv; charset=utf-8",".pdf":"application/pdf",".zip":"application/zip",".mp3":"audio/mpeg",".wav":"audio/wav",".mp4":"video/mp4",".webm":"video/webm"}[e]||"application/octet-stream"}async function oe(t,e){const r=new _({zlib:{level:9}}),i=new Promise((o,a)=>{e.on("close",o),e.on("finish",o),r.on("error",a),e.on("error",a)});r.pipe(e),r.directory(t,!1),await r.finalize(),await i}async function ae(t,e,r,i){const o=d.join(lt.tmpdir(),"agentswork-bridge-downloads");await s.mkdir(o,{recursive:!0});const a=(e||"workspace.zip").replace(/[^\w.-]/g,"_").replace(/\.zip$/i,"")||"workspace",c=d.join(o,`${a}-${Date.now()}-${Math.random().toString(36).slice(2,8)}.zip`),n=new _({zlib:{level:9}}),l=()=>n.pointer(),h=()=>n.abort(),w=O(c),f=new Promise((m,g)=>{w.on("close",m),w.on("finish",m),n.on("error",g),w.on("error",g)});f.catch(()=>{}),n.pipe(w);const p=setInterval(()=>{try{if(i?.()){h();return}r?.(l())}catch{}},200);try{return n.on("progress",()=>{i?.()&&h()}),n.directory(t,!1),i?.()&&h(),await n.finalize(),await f,r?.(l()),c}catch(m){throw await s.rm(c,{force:!0}).catch(()=>{}),m}finally{clearInterval(p)}}async function $t(t,e,r){let i=0,o;const a=U(t),c=a.pipe(pt.Parse({forceStream:!0}));try{for await(const n of c){if(o){await J(n);continue}const l=Tt(n);try{const h=M(e,l);if(N(r),n.type==="Directory"){await s.mkdir(h,{recursive:!0});continue}if(n.type!=="File")throw new Error(`Unsupported archive entry type: ${l}`);await s.mkdir(d.dirname(h),{recursive:!0}),await T(h),await tt(n,h,r),i+=1}catch(h){o=h,await J(n)}}}finally{a.destroy(),c.destroy()}if(o)throw o;return i}async function At(t,e,r,i){let o=0,a;const c=(n,l)=>{if(a)return!1;try{M(e,n),N(i);const h=String(l.type||"").toLowerCase();if(h==="symboliclink"||h==="link")throw new Error(`Archive links are not supported: ${n}`);if(h!=="file"&&h!=="oldfile"&&h!=="contiguousfile"&&h!=="directory")throw new Error(`Unsupported archive entry type: ${n}`);return typeof l.size=="number"&&Q(i,l.size),h!=="directory"&&(o+=1),!0}catch(h){return a=h,!1}};if(await ft.x({file:t,cwd:e,gzip:r,strict:!0,filter:(n,l)=>c(n,l)}),a)throw a;return o}async function Ct(t,e,r){const i=Y(d.basename(t)),o=M(e,i||"decompressed");return N(r),await s.mkdir(d.dirname(o),{recursive:!0}),await T(o),await tt(U(t).pipe(wt()),o,r),1}async function Wt(t){const{requestedRoot:e,workspaceRoot:r}=await v(t.workspacePath),{resolvedTargetPath:i}=await X({workspacePath:t.workspacePath,targetPath:t.outputPath||""}),o=L(e,r,String(t.archivePath||"").trim()),a=await F(o);if(!(await s.stat(a)).isFile())throw new Error(`Archive path is not a file: ${a}`);if(await et(i)||await s.mkdir(i,{recursive:!0}),!(await s.stat(i)).isDirectory())throw new Error(`Output path is not a directory: ${i}`);const l=V(a);if(!l)throw new Error("Unsupported archive type. Supported: .zip, .tar, .tar.gz, .tgz, .gz");let h=0;const w={entries:0,totalBytes:0};return l==="zip"?h=await $t(a,i,w):l==="tar"||l==="tgz"?h=await At(a,i,l==="tgz",w):h=await Ct(a,i,w),{ok:!0,workspacePath:u(r),archivePath:u(a),targetPath:u(i),extractedEntries:h}}function ot(t){const e=t.match(/^(.*?)\{([^}]+)\}(.*)$/);if(!e)return[t];const[,r,i,o]=e;return i.split(",").flatMap(a=>ot(r+a.trim()+o))}function at(t,e){const r=String(e||"").trim();if(!r||r==="*"||r==="*.*")return!0;const i=t.toLowerCase();return ot(r.toLowerCase()).some(a=>{if(a==="*")return!0;const c=a.replace(/\./g,"\\.").replace(/\*\*/g,"<<GLOBSTAR>>").replace(/\*/g,"[^/]*").replace(/\?/g,"[^/]").replace(/<<GLOBSTAR>>/g,".*");return new RegExp(`^${c}$`).test(i)})}function j(t){return t===".git"||t==="node_modules"||t===".svn"||t===".hg"}const nt=10*1024*1024,bt=1e3;async function ne(t){const{workspaceRoot:e}=await v(t.workspacePath),r=String(t.keyword||"").trim();if(!r)throw new Error("keyword is required");const i=!!t.ignoreCase,o=String(t.fileMask||"").trim(),a=typeof t.maxResults=="number"&&t.maxResults>0?t.maxResults:bt,c=i?r.toLowerCase():r,l=(t.mode==="filename"?"filename":"content")==="filename",h=[];let w=0,f=!1;async function p(m){if(f)return;let g;try{g=await s.readdir(m,{withFileTypes:!0})}catch{return}for(const y of g){if(f)return;const P=C(e,d.join(m,y.name));if(y.isSymbolicLink())continue;if(y.isDirectory()){if(j(y.name))continue;await p(P);continue}if(!y.isFile()||o&&!at(y.name,o))continue;w+=1;let E;try{E=await s.stat(P)}catch{continue}if(E.size>nt)continue;if(l){const R=(i?y.name.toLowerCase():y.name).indexOf(c);if(R!==-1&&(h.push({filePath:u(P),lineNumber:0,lineContent:y.name,matchStart:R,matchEnd:R+r.length}),h.length>=a)){f=!0;return}continue}let k;try{k=await s.readFile(P,"utf-8")}catch{continue}const D=k.split(/\r?\n/);for(let S=0;S<D.length;S+=1){const R=D[S],ct=i?R.toLowerCase():R;let q=0;for(;;){const A=ct.indexOf(c,q);if(A===-1)break;if(h.push({filePath:u(P),lineNumber:S+1,lineContent:R,matchStart:A,matchEnd:A+r.length}),h.length>=a){f=!0;return}q=A+1}}}}return await p(e),{workspacePath:u(e),keyword:r,totalFiles:w,totalMatches:h.length,matches:h,truncated:f}}const Bt=100,It=120;async function se(t){const{requestedRoot:e,workspaceRoot:r}=await v(t.workspacePath),i=String(t.keyword||"").trim();if(!i)throw new Error("keyword is required");const o=!!t.ignoreCase,a=o?i.toLowerCase():i,c=typeof t.maxResults=="number"&&t.maxResults>0?t.maxResults:Bt,n=typeof t.maxDirectories=="number"&&t.maxDirectories>0?t.maxDirectories:It,l=String(t.rootPath||"").trim(),h=l?d.resolve(/^[A-Za-z]:$/.test(l)?`${l}/`:l):r;let w;try{w=await s.realpath(h)}catch{throw new Error(`Path not found: ${h}`)}if(!(await s.stat(w)).isDirectory())throw new Error(`Path is not a directory: ${h}`);const p=[],m=[w];let g=0,y=!1;for(;m.length>0&&p.length<c&&g<n;){const P=m.shift();g+=1;let E;try{E=await s.readdir(P,{withFileTypes:!0})}catch{continue}for(const k of E){if(p.length>=c){y=!0;break}if(k.isSymbolicLink())continue;const D=d.join(P,k.name);if(k.isDirectory()&&j(k.name))continue;const S=d.relative(w,D).replace(/\\/g,"/");(o?S.toLowerCase():S).includes(a)&&p.push({name:k.name,path:u(D),isDirectory:k.isDirectory()}),k.isDirectory()&&g<n&&m.push(D)}}return(g>=n||p.length>=c)&&(y=!0),p.sort((P,E)=>P.isDirectory===E.isDirectory?P.name.localeCompare(E.name):P.isDirectory?-1:1),{workspacePath:u(r),rootPath:u(w),keyword:i,items:p,truncated:y}}async function st(t,e,r,i){let o;try{o=await s.readFile(t,"utf-8")}catch{return{changed:!1,count:0}}const a=o;let c=0;if(i){const n=e.toLowerCase();let l=0;for(;;){const w=o.toLowerCase().indexOf(n,l);if(w===-1)break;o=o.slice(0,w)+r+o.slice(w+e.length),c+=1;const f=r.length||1;l=w+f}}else{let n=0;for(;;){const l=o.indexOf(e,n);if(l===-1)break;o=o.slice(0,l)+r+o.slice(l+e.length),c+=1;const h=r.length||1;n=l+h}}return o===a?{changed:!1,count:0}:(await T(t),await s.writeFile(t,o,"utf-8"),{changed:!0,count:c})}async function ce(t){const{workspaceRoot:e}=await v(t.workspacePath),r=String(t.keyword||"").trim();if(!r)throw new Error("keyword is required");const i=String(t.replacement??""),o=!!t.ignoreCase,a=String(t.fileMask||"").trim(),c=String(t.filePath||"").trim();let n=0,l=0;if(c){const{resolvedFilePath:w}=await W({workspacePath:t.workspacePath,filePath:c}),f=await st(w,r,i,o);return f.changed&&(n=1,l=f.count),{workspacePath:u(e),keyword:r,replacement:i,changedFiles:n,changedMatches:l}}async function h(w){let f;try{f=await s.readdir(w,{withFileTypes:!0})}catch{return}for(const p of f){const m=C(e,d.join(w,p.name));if(p.isSymbolicLink())continue;if(p.isDirectory()){if(j(p.name))continue;await h(m);continue}if(!p.isFile()||a&&!at(p.name,a))continue;try{if((await s.stat(m)).size>nt)continue}catch{continue}const g=await st(m,r,i,o);g.changed&&(n+=1,l+=g.count)}}return await h(e),{workspacePath:u(e),keyword:r,replacement:i,changedFiles:n,changedMatches:l}}export{Xt as chmodWorkspaceEntry,Jt as createWorkspaceEntry,ee as deleteWorkspaceEntry,Wt as extractWorkspaceArchive,Kt as getWorkspaceEntryProperties,Gt as listWorkspaceDirectory,te as moveWorkspaceEntry,Vt as previewWorkspaceDocument,Ht as readWorkspaceFile,Qt as renameWorkspaceEntry,ce as replaceWorkspaceFiles,ie as resolveWorkspaceDownloadTarget,ne as searchWorkspaceFiles,se as searchWorkspacePaths,oe as streamWorkspaceDirectoryZip,re as uploadWorkspaceFiles,Yt as writeWorkspaceFile,ae as zipWorkspaceDirectoryToTemp};
1
+ import{createReadStream as q,createWriteStream as O,promises as s}from"node:fs";import lt from"node:os";import w from"node:path";import{Readable as ht}from"node:stream";import{pipeline as ut}from"node:stream/promises";import{TextDecoder as wt}from"node:util";import{createGunzip as dt}from"node:zlib";import*as ft from"tar";import pt from"unzipper";const{ZipArchive:_}=await import("archiver"),x={maxEntries:1e4,maxFileBytes:512*1024*1024,maxTotalBytes:2*1024*1024*1024,maxPathDepth:64,maxPathLength:4096},mt=new wt("gbk");function u(t){return String(t||"").replace(/\\/g,"/")}function Z(t){const e=w.resolve(String(t||"").trim());if(!e)throw new Error("workspacePath is required");return e}async function yt(t){const e=Z(t),r=await s.realpath(e);if(!(await s.stat(r)).isDirectory())throw new Error(`Workspace path is not a directory: ${e}`);return r}async function v(t){return{requestedRoot:Z(t),workspaceRoot:await yt(t)}}function C(t,e){const r=w.resolve(e),i=w.relative(t,r);if(i.startsWith("..")||w.isAbsolute(i))throw new Error(`Target path is outside workspace: ${r}`);return r}async function D(t){return s.realpath(t)}async function F(t){await s.realpath(w.dirname(t));try{if((await s.lstat(t)).isSymbolicLink())throw new Error(`Refusing to write through symbolic link: ${t}`)}catch(e){if((typeof e=="object"&&e!==null?Reflect.get(e,"code"):void 0)!=="ENOENT")throw e}}function L(t,e,r){const i=w.resolve(r),o=w.relative(t,i);return o.startsWith("..")||w.isAbsolute(o)?i:C(e,w.join(e,o))}async function b({workspacePath:t,targetPath:e=""}){const{requestedRoot:r,workspaceRoot:i}=await v(t),o=String(e||"").trim(),a=o?L(r,i,o):i,c=await D(a);return{workspaceRoot:i,resolvedTargetPath:c}}function $(t){const e=String(t||"").trim();if(!e)throw new Error("entryName is required");if(e==="."||e==="..")throw new Error("entryName is invalid");if(e.includes("/")||e.includes("\\")||w.basename(e)!==e)throw new Error(`entryName must be a plain file or directory name: ${e}`);return e}function G(t){const e=String(t||"");if(!/[\u00c0-\u00ff]/.test(e))return e;const r=Buffer.from(e,"latin1").toString("utf8");return!r||r.includes("\uFFFD")?e:r}function B(t){const e=G(t);return $(w.basename(e.replace(/\\/g,"/")))}function gt(t,e){if(!t)return B(e);const i=G(String(t||e||"")).replace(/\\/g,"/").split("/").filter(Boolean).map(o=>$(o));return i.length===0?B(e):w.join(...i)}function H(t){return(t&4095).toString(8).padStart(4,"0")}function Pt(t){const e=String(t||"").trim();if(!/^[0-7]{3,4}$/.test(e))throw new Error("mode must be a 3 or 4 digit octal string");return Number.parseInt(e,8)}function I(t,e,r,i,o,a,c){const n=t&e?"r":"-",h=t&r?"w":"-",l=(t&i)!==0,d=(t&o)!==0?l?a:c:l?"x":"-";return`${n}${h}${d}`}function kt(t){return[I(t,256,128,64,2048,"s","S"),I(t,32,16,8,1024,"s","S"),I(t,4,2,1,512,"t","T")].join("")}function xt(t){if(!(t.length<24||t.toString("hex",0,8)!=="89504e470d0a1a0a"))return{format:"png",width:t.readUInt32BE(16),height:t.readUInt32BE(20)}}function vt(t){if(!(t.length<10||t.toString("ascii",0,6)!=="GIF87a"&&t.toString("ascii",0,6)!=="GIF89a"))return{format:"gif",width:t.readUInt16LE(6),height:t.readUInt16LE(8)}}function Et(t){if(t.length<4||t[0]!==255||t[1]!==216)return;let e=2;for(;e+9<t.length;){if(t[e]!==255){e+=1;continue}const r=t[e+1],i=t.readUInt16BE(e+2);if(i<2)return;if(r>=192&&r<=207&&![196,200,204].includes(r)&&e+8<t.length)return{format:"jpeg",height:t.readUInt16BE(e+5),width:t.readUInt16BE(e+7)};e+=2+i}}function St(t){if(t.length<30||t.toString("ascii",0,4)!=="RIFF"||t.toString("ascii",8,12)!=="WEBP")return;const e=t.toString("ascii",12,16);if(e==="VP8X"&&t.length>=30)return{format:"webp",width:1+t.readUIntLE(24,3),height:1+t.readUIntLE(27,3)};if(e==="VP8 "&&t.length>=30)return{format:"webp",width:t.readUInt16LE(26)&16383,height:t.readUInt16LE(28)&16383};if(e==="VP8L"&&t.length>=25){const r=t.readUInt32LE(21);return{format:"webp",width:(r&16383)+1,height:(r>>14&16383)+1}}}async function K(t,e){if((await s.lstat(t)).isSymbolicLink())throw new Error(`Refusing to change permissions on symbolic link: ${t}`);const i=await s.stat(t);if(!e||!i.isDirectory())return[t];const o=await s.readdir(t),a=await Promise.all(o.map(c=>{const n=w.join(t,c);return K(n,!0)}));return[t,...a.flat()]}async function Rt(t){if((await s.lstat(t)).isSymbolicLink())throw new Error(`Refusing to change permissions on symbolic link: ${t}`);await D(t)}async function Dt(t){const e=await s.open(t,"r");try{const r=Buffer.alloc(512),{bytesRead:i}=await e.read(r,0,r.length,0),o=r.subarray(0,i);return xt(o)||vt(o)||Et(o)||St(o)}finally{await e.close()}}async function T({workspacePath:t,targetPath:e},r={}){const{requestedRoot:i,workspaceRoot:o}=await v(t),a=String(e||"").trim();if(!a)throw new Error("targetPath is required");const c=L(i,o,a),n=await D(c);if(!r.allowWorkspaceRoot&&n===o)throw new Error("Workspace root cannot be modified");return{workspaceRoot:o,resolvedTargetPath:n}}async function X(t){const{requestedRoot:e,workspaceRoot:r}=await v(t.workspacePath),i=String(t.targetPath||"").trim();if(!i)return{workspaceRoot:r,resolvedTargetPath:r};const o=L(e,r,i);return await et(o)?{workspaceRoot:r,resolvedTargetPath:await s.realpath(o)}:(await s.realpath(w.dirname(o)),{workspaceRoot:r,resolvedTargetPath:o})}function V(t){const e=t.toLowerCase();return e.endsWith(".zip")?"zip":e.endsWith(".tar.gz")||e.endsWith(".tgz")?"tgz":e.endsWith(".tar")?"tar":e.endsWith(".gz")?"gz":null}function Y(t){return t.replace(/\.tar\.gz$/i,"").replace(/\.tgz$/i,"").replace(/\.zip$/i,"").replace(/\.tar$/i,"").replace(/\.gz$/i,"")}function Ft(t,e){const r=$(Y(e)||"extracted");return w.join(t,r)}function M(t,e){const r=String(e||"").replace(/\\/g,"/"),i=r.split("/").filter(Boolean);if(!r||r.startsWith("/")||/^[A-Za-z]:/.test(r))throw new Error(`Archive entry path is invalid: ${e}`);if(r.length>x.maxPathLength||i.length>x.maxPathDepth)throw new Error(`Archive entry path is too deep or too long: ${e}`);return C(t,w.join(t,r))}function Tt(t){const e=t.props?.pathBuffer;if(!e||t.props?.flags?.isUnicode)return t.path;const r=mt.decode(e);return!r||r.includes("\uFFFD")?t.path:r}async function J(t){const e=t.autodrain?.();e&&await new Promise((r,i)=>{e.on("close",r),e.on("end",r),e.on("finish",r),e.on("error",i)})}function N(t){if(t.entries+=1,t.entries>x.maxEntries)throw new Error(`Archive contains too many entries. Limit: ${x.maxEntries}`)}function Q(t,e){if(t.totalBytes+=e,e>x.maxFileBytes)throw new Error(`Archive entry exceeds max size. Limit: ${x.maxFileBytes} bytes`);if(t.totalBytes>x.maxTotalBytes)throw new Error(`Archive extraction exceeds total size. Limit: ${x.maxTotalBytes} bytes`)}async function tt(t,e,r){let i=0;t.on("data",o=>{const a=Buffer.isBuffer(o)?o.length:Buffer.byteLength(o);i+=a,(i>x.maxFileBytes||r.totalBytes+i>x.maxTotalBytes)&&t instanceof ht&&t.destroy(new Error("Archive extraction size limit exceeded"))}),await ut(t,O(e)),Q(r,i)}async function et(t){try{return await s.access(t),!0}catch(e){if((typeof e=="object"&&e!==null?Reflect.get(e,"code"):void 0)==="ENOENT")return!1;throw e}}async function W({workspacePath:t,filePath:e}){const{requestedRoot:r,workspaceRoot:i}=await v(t),o=String(e||"").trim();if(!o)throw new Error("filePath is required");return{workspaceRoot:i,resolvedFilePath:L(r,i,o)}}async function Gt(t){const{workspaceRoot:e}=await v(t.workspacePath),r=String(t.targetPath||"").trim();if(!r){const{resolvedTargetPath:h}=await b(t);return rt(e,h)}const i=w.resolve(r);let o;try{o=await s.realpath(i)}catch{throw new Error(`Path not found: ${i}`)}if(!(await s.stat(o)).isDirectory())throw new Error(`Path is not a directory: ${i}`);const c=w.relative(e,o),n=c===""||!c.startsWith("..")&&!w.isAbsolute(c);return rt(e,n?o:i)}async function rt(t,e){if(!(await s.stat(e)).isDirectory())throw new Error(`Path is not a directory: ${e}`);const i=await s.readdir(e,{withFileTypes:!0}),o=await Promise.all(i.map(async a=>{const c=w.join(e,a.name),n=a.isFile()?(await s.stat(c)).size:void 0;return{name:a.name,path:u(c),isDirectory:a.isDirectory(),size:n}}));return{currentPath:u(e),workspacePath:u(t),items:o}}async function Ht(t){const{workspaceRoot:e,resolvedFilePath:r}=await W(t),i=await D(r),o=await s.stat(i);if(!o.isFile())throw new Error(`Path is not a file: ${i}`);const a=await s.readFile(i,"utf-8");return{workspacePath:u(e),filePath:u(i),content:a,mtimeMs:o.mtimeMs}}const it={maxEntries:1e5,maxDepth:32};async function zt(t){let e=0,r=0;async function i(o,a){if(a>=it.maxDepth)return;let c;try{c=await s.readdir(o,{withFileTypes:!0})}catch{return}for(const n of c){if(r+=1,r>it.maxEntries)return;if(n.isSymbolicLink())continue;const h=w.join(o,n.name);try{if(n.isDirectory())await i(h,a+1);else if(n.isFile()){const l=await s.stat(h);e+=l.size}}catch{}}}return await i(t,0),e}async function Kt(t){const{workspaceRoot:e,resolvedTargetPath:r}=await T(t,{allowWorkspaceRoot:!0}),[i,o]=await Promise.all([s.stat(r),s.lstat(r)]),a=i.isDirectory(),c=i.isFile()?await Dt(r):void 0,n=a?await zt(r):i.size;return{workspacePath:u(e),targetPath:u(r),name:w.basename(r),isDirectory:i.isDirectory(),isFile:i.isFile(),isSymbolicLink:o.isSymbolicLink(),size:n,mode:i.mode,modeOctal:H(i.mode),permissions:kt(i.mode),uid:i.uid,gid:i.gid,atimeMs:i.atimeMs,mtimeMs:i.mtimeMs,ctimeMs:i.ctimeMs,birthtimeMs:i.birthtimeMs,...c?{image:c}:{}}}async function Xt(t){const e=Pt(t.mode),r=!!t.recursive,{workspaceRoot:i,resolvedTargetPath:o}=await T(t),a=await K(o,r);for(const c of a)await Rt(c),await s.chmod(c,e);return{ok:!0,workspacePath:u(i),targetPath:u(o),mode:e,modeOctal:H(e),recursive:r,changedCount:a.length}}async function Vt(t){const{workspaceRoot:e,resolvedFilePath:r}=await W(t),i=await D(r),o=await s.stat(i);if(!o.isFile())throw new Error(`Path is not a file: ${i}`);const a=w.extname(i).toLowerCase();if(a===".doc")return{workspacePath:u(e),filePath:u(i),kind:"unsupported",content:"",message:"\u6682\u4E0D\u652F\u6301\u65E7\u7248 .doc \u683C\u5F0F\u9884\u89C8\uFF0C\u8BF7\u53E6\u5B58\u4E3A .docx \u540E\u518D\u6253\u5F00\u3002",size:o.size,mtimeMs:o.mtimeMs};if(a!==".docx")throw new Error("Document preview only supports .docx files");return{workspacePath:u(e),filePath:u(i),kind:"html",content:"",size:o.size,mtimeMs:o.mtimeMs}}async function Yt(t){const{workspaceRoot:e,resolvedFilePath:r}=await W(t);await s.mkdir(w.dirname(r),{recursive:!0}),await F(r),await s.writeFile(r,String(t.content??""),"utf-8");const i=await s.stat(r);return{ok:!0,workspacePath:u(e),filePath:u(r),mtimeMs:i.mtimeMs}}async function Jt(t){const{workspaceRoot:e,resolvedTargetPath:r}=await b(t),i=$(t.entryName),o=w.join(r,i);if(!(await s.stat(r)).isDirectory())throw new Error(`Path is not a directory: ${r}`);try{throw await s.access(o),new Error(`Path already exists: ${o}`)}catch(c){if((typeof c=="object"&&c!==null?Reflect.get(c,"code"):void 0)!=="ENOENT")throw c}return t.isDirectory?await s.mkdir(o,{recursive:!1}):(await s.mkdir(w.dirname(o),{recursive:!0}),await F(o),await s.writeFile(o,"","utf-8")),{ok:!0,workspacePath:u(e),targetPath:u(o),isDirectory:t.isDirectory}}async function Qt(t){const{workspaceRoot:e,resolvedTargetPath:r}=await T(t),i=$(t.newName),o=w.join(w.dirname(r),i);if(o===r)return{ok:!0,workspacePath:u(e),sourcePath:u(r),targetPath:u(o)};await s.stat(r);try{throw await s.access(o),new Error(`Path already exists: ${o}`)}catch(a){if((typeof a=="object"&&a!==null?Reflect.get(a,"code"):void 0)!=="ENOENT")throw a}return await s.rename(r,o),{ok:!0,workspacePath:u(e),sourcePath:u(r),targetPath:u(o)}}async function te(t){const{workspaceRoot:e,resolvedTargetPath:r}=await T(t),i=await b({workspacePath:t.workspacePath,targetPath:t.destinationPath});if(!(await s.stat(i.resolvedTargetPath)).isDirectory())throw new Error(`Destination is not a directory: ${i.resolvedTargetPath}`);if((await s.stat(r)).isDirectory()){const n=w.relative(r,i.resolvedTargetPath);if(n===""||!n.startsWith("..")&&!w.isAbsolute(n))throw new Error("Cannot move a directory into itself or its descendant")}const c=w.join(i.resolvedTargetPath,w.basename(r));if(c===r)return{ok:!0,workspacePath:u(e),sourcePath:u(r),targetPath:u(c),destinationPath:u(i.resolvedTargetPath)};try{throw await s.access(c),new Error(`Path already exists: ${c}`)}catch(n){if((typeof n=="object"&&n!==null?Reflect.get(n,"code"):void 0)!=="ENOENT")throw n}return await s.rename(r,c),{ok:!0,workspacePath:u(e),sourcePath:u(r),targetPath:u(c),destinationPath:u(i.resolvedTargetPath)}}async function ee(t){const{workspaceRoot:e,resolvedTargetPath:r}=await T(t),i=await s.stat(r),o=w.parse(r).root;if(r===o)throw new Error("Filesystem root cannot be deleted");return i.isDirectory()?await s.rm(r,{recursive:!0,force:!1}):await s.unlink(r),{ok:!0,workspacePath:u(e),targetPath:u(r)}}async function re(t){if(!Array.isArray(t.files)||t.files.length===0)throw new Error("files are required");const{workspaceRoot:e,resolvedTargetPath:r}=await X(t);if(!(await s.stat(r)).isDirectory())throw new Error(`Path is not a directory: ${r}`);const o=[];for(const a of t.files){const c=B(a.originalname),n=gt(a.relativePath,a.originalname),h=w.join(r,n);await s.mkdir(w.dirname(h),{recursive:!0}),await F(h),await s.copyFile(a.path,h);let l;t.extractArchives&&V(h)&&(l=await Wt({workspacePath:e,archivePath:h,outputPath:Ft(r,c)})),o.push({fileName:c,targetPath:u(h),size:a.size,extracted:l})}return{ok:!0,workspacePath:u(e),targetPath:u(r),files:o}}async function ie(t){const{workspaceRoot:e,resolvedTargetPath:r}=await T(t),i=await s.stat(r),o=w.basename(r);return{workspacePath:u(e),targetPath:u(r),resolvedTargetPath:r,fileName:i.isDirectory()?`${o||"workspace"}.zip`:o,contentType:i.isDirectory()?"application/zip":Lt(r),isDirectory:i.isDirectory(),size:i.isDirectory()?void 0:i.size}}function Lt(t){const e=w.extname(t).toLowerCase();return{".svg":"image/svg+xml",".svgz":"image/svg+xml",".ico":"image/x-icon",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".bmp":"image/bmp",".avif":"image/avif",".txt":"text/plain; charset=utf-8",".json":"application/json; charset=utf-8",".xml":"application/xml; charset=utf-8",".html":"text/html; charset=utf-8",".htm":"text/html; charset=utf-8",".css":"text/css; charset=utf-8",".js":"text/javascript; charset=utf-8",".md":"text/markdown; charset=utf-8",".csv":"text/csv; charset=utf-8",".pdf":"application/pdf",".zip":"application/zip",".mp3":"audio/mpeg",".wav":"audio/wav",".mp4":"video/mp4",".webm":"video/webm"}[e]||"application/octet-stream"}async function oe(t,e){const r=new _({zlib:{level:9}}),i=new Promise((o,a)=>{e.on("close",o),e.on("finish",o),r.on("error",a),e.on("error",a)});r.pipe(e),r.directory(t,!1),await r.finalize(),await i}async function ae(t,e,r,i){const o=w.join(lt.tmpdir(),"agentswork-bridge-downloads");await s.mkdir(o,{recursive:!0});const a=(e||"workspace.zip").replace(/[^\w.-]/g,"_").replace(/\.zip$/i,"")||"workspace",c=w.join(o,`${a}-${Date.now()}-${Math.random().toString(36).slice(2,8)}.zip`),n=new _({zlib:{level:9}}),h=()=>n.pointer(),l=()=>n.abort(),f=O(c),d=new Promise((m,g)=>{f.on("close",m),f.on("finish",m),n.on("error",g),f.on("error",g)});d.catch(()=>{}),n.pipe(f);const y=setInterval(()=>{try{if(i?.()){l();return}r?.(h())}catch{}},200);try{return n.on("progress",()=>{i?.()&&l()}),n.directory(t,!1),i?.()&&l(),await n.finalize(),await d,r?.(h()),c}catch(m){throw await s.rm(c,{force:!0}).catch(()=>{}),m}finally{clearInterval(y)}}async function $t(t,e,r){let i=0,o;const a=q(t),c=a.pipe(pt.Parse({forceStream:!0}));try{for await(const n of c){if(o){await J(n);continue}const h=Tt(n);try{const l=M(e,h);if(N(r),n.type==="Directory"){await s.mkdir(l,{recursive:!0});continue}if(n.type!=="File")throw new Error(`Unsupported archive entry type: ${h}`);await s.mkdir(w.dirname(l),{recursive:!0}),await F(l),await tt(n,l,r),i+=1}catch(l){o=l,await J(n)}}}finally{a.destroy(),c.destroy()}if(o)throw o;return i}async function At(t,e,r,i){let o=0,a;const c=(n,h)=>{if(a)return!1;try{M(e,n),N(i);const l=String(h.type||"").toLowerCase();if(l==="symboliclink"||l==="link")throw new Error(`Archive links are not supported: ${n}`);if(l!=="file"&&l!=="oldfile"&&l!=="contiguousfile"&&l!=="directory")throw new Error(`Unsupported archive entry type: ${n}`);return typeof h.size=="number"&&Q(i,h.size),l!=="directory"&&(o+=1),!0}catch(l){return a=l,!1}};if(await ft.x({file:t,cwd:e,gzip:r,strict:!0,filter:(n,h)=>c(n,h)}),a)throw a;return o}async function Ct(t,e,r){const i=Y(w.basename(t)),o=M(e,i||"decompressed");return N(r),await s.mkdir(w.dirname(o),{recursive:!0}),await F(o),await tt(q(t).pipe(dt()),o,r),1}async function Wt(t){const{requestedRoot:e,workspaceRoot:r}=await v(t.workspacePath),{resolvedTargetPath:i}=await X({workspacePath:t.workspacePath,targetPath:t.outputPath||""}),o=L(e,r,String(t.archivePath||"").trim()),a=await D(o);if(!(await s.stat(a)).isFile())throw new Error(`Archive path is not a file: ${a}`);if(await et(i)||await s.mkdir(i,{recursive:!0}),!(await s.stat(i)).isDirectory())throw new Error(`Output path is not a directory: ${i}`);const h=V(a);if(!h)throw new Error("Unsupported archive type. Supported: .zip, .tar, .tar.gz, .tgz, .gz");let l=0;const f={entries:0,totalBytes:0};return h==="zip"?l=await $t(a,i,f):h==="tar"||h==="tgz"?l=await At(a,i,h==="tgz",f):l=await Ct(a,i,f),{ok:!0,workspacePath:u(r),archivePath:u(a),targetPath:u(i),extractedEntries:l}}function ot(t){const e=t.match(/^(.*?)\{([^}]+)\}(.*)$/);if(!e)return[t];const[,r,i,o]=e;return i.split(",").flatMap(a=>ot(r+a.trim()+o))}function at(t,e){const r=String(e||"").trim();if(!r||r==="*"||r==="*.*")return!0;const i=t.toLowerCase();return ot(r.toLowerCase()).some(a=>{if(a==="*")return!0;const c=a.replace(/\./g,"\\.").replace(/\*\*/g,"<<GLOBSTAR>>").replace(/\*/g,"[^/]*").replace(/\?/g,"[^/]").replace(/<<GLOBSTAR>>/g,".*");return new RegExp(`^${c}$`).test(i)})}function j(t){return t===".git"||t==="node_modules"||t===".svn"||t===".hg"}const nt=10*1024*1024,bt=1e3;async function ne(t){const{workspaceRoot:e}=await v(t.workspacePath),r=String(t.keyword||"").trim();if(!r)throw new Error("keyword is required");const i=!!t.ignoreCase,o=String(t.fileMask||"").trim(),a=typeof t.maxResults=="number"&&t.maxResults>0?t.maxResults:bt,c=i?r.toLowerCase():r,h=(t.mode==="filename"?"filename":"content")==="filename",l=[];let f=0,d=!1;async function y(m){if(d)return;let g;try{g=await s.readdir(m,{withFileTypes:!0})}catch{return}for(const p of g){if(d)return;const P=C(e,w.join(m,p.name));if(p.isSymbolicLink())continue;if(p.isDirectory()){if(j(p.name))continue;await y(P);continue}if(!p.isFile()||o&&!at(p.name,o))continue;f+=1;let k;try{k=await s.stat(P)}catch{continue}if(k.size>nt)continue;if(h){const E=(i?p.name.toLowerCase():p.name).indexOf(c);if(E!==-1&&(l.push({filePath:u(P),lineNumber:0,lineContent:p.name,matchStart:E,matchEnd:E+r.length}),l.length>=a)){d=!0;return}continue}let S;try{S=await s.readFile(P,"utf-8")}catch{continue}const z=S.split(/\r?\n/);for(let R=0;R<z.length;R+=1){const E=z[R],ct=i?E.toLowerCase():E;let U=0;for(;;){const A=ct.indexOf(c,U);if(A===-1)break;if(l.push({filePath:u(P),lineNumber:R+1,lineContent:E,matchStart:A,matchEnd:A+r.length}),l.length>=a){d=!0;return}U=A+1}}}}return await y(e),{workspacePath:u(e),keyword:r,totalFiles:f,totalMatches:l.length,matches:l,truncated:d}}const Bt=100,It=120;async function se(t){const{workspaceRoot:e}=await v(t.workspacePath),r=String(t.keyword||"").trim();if(!r)throw new Error("keyword is required");const i=!!t.ignoreCase,o=i?r.toLowerCase():r,a=typeof t.maxResults=="number"&&t.maxResults>0?t.maxResults:Bt,c=typeof t.maxDirectories=="number"&&t.maxDirectories>0?t.maxDirectories:It,n=String(t.rootPath||"").trim(),h=n?w.resolve(/^[A-Za-z]:$/.test(n)?`${n}/`:n):e;let l;try{l=await s.realpath(h)}catch{throw new Error(`Path not found: ${h}`)}if(!(await s.stat(l)).isDirectory())throw new Error(`Path is not a directory: ${h}`);const d=[],y=[l];let m=0,g=!1;for(;y.length>0&&d.length<a&&m<c;){const p=y.shift();m+=1;let P;try{P=await s.readdir(p,{withFileTypes:!0})}catch{continue}for(const k of P){if(d.length>=a){g=!0;break}if(k.isSymbolicLink())continue;const S=w.join(p,k.name);if(k.isDirectory()&&j(k.name))continue;const z=w.relative(l,S).replace(/\\/g,"/");(i?z.toLowerCase():z).includes(o)&&d.push({name:k.name,path:u(S),isDirectory:k.isDirectory()}),k.isDirectory()&&m<c&&y.push(S)}}return(m>=c||d.length>=a)&&(g=!0),d.sort((p,P)=>p.isDirectory===P.isDirectory?p.name.localeCompare(P.name):p.isDirectory?-1:1),{workspacePath:u(e),rootPath:u(l),keyword:r,items:d,truncated:g}}async function st(t,e,r,i){let o;try{o=await s.readFile(t,"utf-8")}catch{return{changed:!1,count:0}}const a=o;let c=0;if(i){const n=e.toLowerCase();let h=0;for(;;){const f=o.toLowerCase().indexOf(n,h);if(f===-1)break;o=o.slice(0,f)+r+o.slice(f+e.length),c+=1;const d=r.length||1;h=f+d}}else{let n=0;for(;;){const h=o.indexOf(e,n);if(h===-1)break;o=o.slice(0,h)+r+o.slice(h+e.length),c+=1;const l=r.length||1;n=h+l}}return o===a?{changed:!1,count:0}:(await F(t),await s.writeFile(t,o,"utf-8"),{changed:!0,count:c})}async function ce(t){const{workspaceRoot:e}=await v(t.workspacePath),r=String(t.keyword||"").trim();if(!r)throw new Error("keyword is required");const i=String(t.replacement??""),o=!!t.ignoreCase,a=String(t.fileMask||"").trim(),c=String(t.filePath||"").trim();let n=0,h=0;if(c){const{resolvedFilePath:f}=await W({workspacePath:t.workspacePath,filePath:c}),d=await st(f,r,i,o);return d.changed&&(n=1,h=d.count),{workspacePath:u(e),keyword:r,replacement:i,changedFiles:n,changedMatches:h}}async function l(f){let d;try{d=await s.readdir(f,{withFileTypes:!0})}catch{return}for(const y of d){const m=C(e,w.join(f,y.name));if(y.isSymbolicLink())continue;if(y.isDirectory()){if(j(y.name))continue;await l(m);continue}if(!y.isFile()||a&&!at(y.name,a))continue;try{if((await s.stat(m)).size>nt)continue}catch{continue}const g=await st(m,r,i,o);g.changed&&(n+=1,h+=g.count)}}return await l(e),{workspacePath:u(e),keyword:r,replacement:i,changedFiles:n,changedMatches:h}}export{Xt as chmodWorkspaceEntry,Jt as createWorkspaceEntry,ee as deleteWorkspaceEntry,Wt as extractWorkspaceArchive,Kt as getWorkspaceEntryProperties,Gt as listWorkspaceDirectory,te as moveWorkspaceEntry,Vt as previewWorkspaceDocument,Ht as readWorkspaceFile,Qt as renameWorkspaceEntry,ce as replaceWorkspaceFiles,ie as resolveWorkspaceDownloadTarget,ne as searchWorkspaceFiles,se as searchWorkspacePaths,oe as streamWorkspaceDirectoryZip,re as uploadWorkspaceFiles,Yt as writeWorkspaceFile,ae as zipWorkspaceDirectoryToTemp};
2
2
 
@@ -1,4 +1,4 @@
1
- import{promises as f}from"node:fs";import r from"node:path";import{createHash as T}from"node:crypto";import J from"axios";import*as V from"diff";import{createLogger as Z}from"../utils/logger.js";import{resolveSchedulerBaseUrl as q,getRuntimeHomeDir as C}from"../config.js";import{getChangeCacheRetentionDays as I,setChangeCacheRetentionDays as Q}from"./change-cache-retention.js";import{getRuntimeAccessToken as H}from"./runtime-binding.js";const h=Z("workspace-task-change-watcher"),Y=new Set([".git","node_modules","__pycache__",".cache",".next","target","dist",".idea",".vscode",".agentswork-snapshots",".aws-bridge"]),ee=new Set([".lock",".log",".pid",".swp",".swo",".tmp"]),F=500,te=10*1024*1024,ne=".agentswork/change-cache",m="change-cache",ae=60*60*1e3,ie=24*60*60*1e3;let l=null,$=!1,E="",p=null;const g=new Map,u=new Map;let b=!1;function we(e){l&&l.taskNodeId!==e.taskNodeId&&z().catch(()=>{}),l=e,h.info(`Task context set: agent=${e.agentId}, taskInstance=${e.taskInstanceId}, node=${e.taskNodeId}`)}function Ce(){l&&(h.info(`Task context cleared: agent=${l.agentId}`),z().catch(()=>{})),l=null}function me(){return l}function Ee(){return l!==null}async function ke(e){const t=r.resolve(e.trim());try{if(!(await f.stat(t)).isDirectory())throw new Error(`Not a directory: ${t}`)}catch{throw new Error(`Workspace path does not exist or inaccessible: ${t}`)}if(p){try{p.close()}catch{}p=null}E=t,$=!0,h.info(`Workspace path set (fs.watch disabled, using tool interception only): ${E}`)}async function ye(){if($=!1,p){try{p.close()}catch{}p=null}g.clear(),u.clear(),E="",h.info("Workspace watch stopped")}function N(e,t,n){return T("sha256").update(`${e||"no-task"}:${t}:${n}`,"utf-8").digest("hex").slice(0,32)}function W(e){return T("sha256").update(r.resolve(e),"utf-8").digest("hex").slice(0,16)}function k(e){return r.join(C(),".aws-bridge",m,W(e))}function oe(e){return r.join(C(),m,W(e))}function j(e){return r.join(e,ne)}const U=new Set;async function M(e){if(!U.has(e)){U.add(e);try{const t=j(e),n=k(e);await f.access(t),await f.mkdir(r.dirname(n),{recursive:!0}),await f.rename(t,n),h.info(`Migrated legacy change-cache: ${t} -> ${n}`)}catch{}}}async function x(e,t,n){if(n===null)return;await M(e);const a=k(e);await f.mkdir(a,{recursive:!0});const i=r.join(a,`${t}.before`);await f.writeFile(i,n,"utf-8"),X(),h.debug(`Saved beforeContent cache: ${i}`)}async function B(e,t,n,a){const i=V.createPatch("file",n,a);await M(e);const o=k(e);await f.mkdir(o,{recursive:!0});const c=r.join(o,`${t}.diff`);await f.writeFile(c,i,"utf-8"),X(),h.debug(`Saved diff cache: ${c}`)}async function O(e,t){const n=[r.join(k(e),t),r.join(oe(e),t),r.join(j(e),t)];for(const a of n)try{return await f.readFile(a,"utf-8")}catch{}return null}async function De(e,t){return O(e,`${t}.before`)}async function Te(e,t){return O(e,`${t}.diff`)}let v=0,A=null,L=Promise.resolve();function S(){return L=L.then(()=>se()),L}async function se(){const e=I();if(!(e===null||e<=0))try{const t=[r.join(C(),".aws-bridge",m),r.join(C(),m)],n=Date.now()-e*24*60*60*1e3;let a=0;for(const i of t){let o=[];try{o=(await f.readdir(i)).filter(c=>!c.startsWith("."))}catch{continue}for(const c of o){const s=r.join(i,c);try{const d=await f.readdir(s);let w=!0;for(const D of d){if(!D.endsWith(".diff")&&!D.endsWith(".before")){w=!1;continue}const P=r.join(s,D);try{(await f.stat(P)).mtimeMs<n?(await f.unlink(P),a++):w=!1}catch{w=!1}}w&&await f.rmdir(s).catch(()=>{})}catch{}}}a>0&&h.info(`Change-cache TTL sweep: removed ${a} expired file(s), retentionDays=${e}`)}catch(t){h.warn(`Change-cache TTL sweep failed: ${t.message}`)}}function X(){const e=Date.now();e-v>=ae&&(v=e,S().catch(()=>{})),A||(A=setInterval(()=>{S().catch(()=>{})},ie),A.unref?.())}function Ie(e){const t=e.split(/[/\\]/);for(const a of t.slice(0,-1))if(Y.has(a))return!0;const n=r.extname(t[t.length-1]).toLowerCase();return!!ee.has(n)}async function _(e){try{return(await f.stat(e)).size>te?null:await f.readFile(e,"utf-8")}catch{return null}}function y(e){return e===null?null:T("sha256").update(e,"utf-8").digest("hex").slice(0,16)}async function $e(e,t){}function be(e,t,n){const a=g.get(n);if(a)t==="DELETE"||a.operation==="DELETE"?a.operation="DELETE":a.operation==="CREATE"&&t==="UPDATE"||(a.operation=t),a.timer&&clearTimeout(a.timer),a.timer=setTimeout(()=>{R(n).catch(()=>{})},F);else{let i=null;if(t==="UPDATE"||t==="DELETE")if(u.has(n))i=u.get(n)??null;else{_(n).then(c=>{c!==void 0&&u.set(n,c)}).catch(()=>{});return}const o={filePath:n,operation:t,timer:null,beforeContent:i};o.timer=setTimeout(()=>{R(n).catch(()=>{})},F),g.set(n,o)}}async function R(e){const t=g.get(e);if(!t)return;g.delete(e),t.timer&&clearTimeout(t.timer);const n=l;if(!n){if(t.operation==="DELETE")u.delete(e);else{const d=await _(e);d!==null&&u.set(e,d)}return}const a=r.relative(n.workspacePath,e).replace(/\\/g,"/");if(a.startsWith(".."))return;let i=t.beforeContent,o=null;t.operation==="DELETE"?(i=i??u.get(e)??null,o=null):(o=await _(e),t.operation==="UPDATE"&&i===null&&(i=u.get(e)??null)),t.operation==="DELETE"?u.delete(e):u.set(e,o);const c=new Date().toISOString(),s=N(n.taskInstanceId,a,c);t.operation==="UPDATE"&&i!==null&&o!==null?await B(n.workspacePath,s,i,o):t.operation==="DELETE"&&await x(n.workspacePath,s,i),await K(n,{workspacePath:n.workspacePath,filePath:a,operation:t.operation,beforeContent:i,afterContent:o,beforeHash:y(i),afterHash:y(o),timestamp:c,reason:G(t.operation,i,o)},s)}async function K(e,t,n){try{const a=q().url,i=H(a)||H();if(!i){h.warn("Cannot send change record: no auth token");return}const o=JSON.stringify({toolRecorded:!0,cacheKey:n,timestamp:t.timestamp}),s=(await J.post(`${a}/api/runtime/callback/task-file-changed`,{agentId:e.agentId,taskInstanceId:e.taskInstanceId,taskNodeId:e.taskNodeId,tenantId:e.tenantId,operation:t.operation,targetType:"FILE",targetPath:t.filePath,beforeHash:t.beforeHash,afterHash:t.afterHash,metadata:o,reason:t.reason,workspacePath:e.workspacePath},{headers:{"X-Runtime-Token":i},timeout:1e4})).data;if(s?.ignored===!0?h.warn(`Change record ignored by server: ${t.filePath} (${t.operation}), reason: ${String(s.reason??"unknown")}`):h.info(`Change record sent: ${t.filePath} (${t.operation})`),s&&s.changeCacheRetentionDays!==void 0){const d=I();Q(s.changeCacheRetentionDays),d!==I()&&(v=0,S().catch(()=>{}))}}catch(a){h.warn(`Failed to send change record: ${a.message}`)}}async function z(){if(b)return;b=!0;const e=Array.from(g.keys());for(const t of e)try{await R(t)}catch{}b=!1}function xe(){return g.size}function ve(){return $&&p!==null}function Ae(){return E}function G(e,t,n){const a=t?t.split(`
2
- `).length:0,i=n?n.split(`
3
- `).length:0;if(e==="CREATE")return`\u521B\u5EFA\u6587\u4EF6\uFF0C\u5171 ${i} \u884C`;if(e==="DELETE")return`\u5220\u9664\u6587\u4EF6\uFF0C\u539F ${a} \u884C`;if(a===i)return`\u4FEE\u6539\u6587\u4EF6\uFF08\u884C\u6570\u4E0D\u53D8\uFF0C${i} \u884C\uFF09`;const o=i-a;return`\u4FEE\u6539\u6587\u4EF6\uFF1A${a} \u884C -> ${i} \u884C\uFF08${o>0?"+":""}${o} \u884C\uFF09`}async function Le(e){const t=l,n=e.agentId||t?.agentId,a=e.workspacePath||t?.workspacePath;if(!n||!a){h.warn(`Agent file change skipped (no identity): ${e.filePath} (${e.operation})`);return}h.info(`Recording agent file change: ${e.filePath} (${e.operation}), taskNode=${t?.taskNodeId??"(no task)"}`);const i=t??{agentId:n,taskInstanceId:"",taskNodeId:"",tenantId:"",workspacePath:a,projectId:""},o=r.join(i.workspacePath,e.filePath),c=new Date().toISOString(),s=N(i.taskInstanceId,e.filePath,c);e.operation==="UPDATE"&&e.beforeContent!==null&&e.afterContent!==null?(await B(i.workspacePath,s,e.beforeContent,e.afterContent),await x(i.workspacePath,s,e.beforeContent)):e.operation==="DELETE"&&await x(i.workspacePath,s,e.beforeContent);const d=e.reason?.trim()||G(e.operation,e.beforeContent,e.afterContent);await K(i,{workspacePath:i.workspacePath,filePath:e.filePath,operation:e.operation,beforeContent:e.beforeContent,afterContent:e.afterContent,beforeHash:y(e.beforeContent),afterHash:y(e.afterContent),timestamp:c,reason:d},s)}export{Ce as clearTaskContext,xe as getPendingChangeCountForTest,me as getTaskContext,Ae as getWorkspaceRoot,Ee as hasActiveTask,ve as isWatching,De as readBeforeContentFromCache,Te as readDiffFromCache,Le as recordAgentFileChange,we as setTaskContext,ke as startWatching,ye as stopWatching,S as sweepExpiredChangeCache};
1
+ import{createHash as $}from"node:crypto";import{promises as r}from"node:fs";import s from"node:path";import G from"axios";import*as X from"diff";import{resolveSchedulerBaseUrl as J,getRuntimeHomeDir as C}from"../config.js";import{createLogger as V}from"../utils/logger.js";import{getChangeCacheRetentionDays as D,setChangeCacheRetentionDays as Z}from"./change-cache-retention.js";import{getRuntimeAccessToken as H}from"./runtime-binding.js";const h=V("workspace-task-change-watcher"),q=10*1024*1024,Q=".agentswork/change-cache",m="change-cache",Y=60*60*1e3,ee=24*60*60*1e3;let l=null,T=!1,k="",u=null;const g=new Map,d=new Map;let b=!1;function de(e){l&&l.taskNodeId!==e.taskNodeId&&K().catch(()=>{}),l=e,h.info(`Task context set: agent=${e.agentId}, taskInstance=${e.taskInstanceId}, node=${e.taskNodeId}`)}function pe(){l&&(h.info(`Task context cleared: agent=${l.agentId}`),K().catch(()=>{})),l=null}function ge(){return l}function we(){return l!==null}async function Ce(e){const t=s.resolve(e.trim());try{if(!(await r.stat(t)).isDirectory())throw new Error(`Not a directory: ${t}`)}catch{throw new Error(`Workspace path does not exist or inaccessible: ${t}`)}if(u){try{u.close()}catch{}u=null}k=t,T=!0,h.info(`Workspace path set (fs.watch disabled, using tool interception only): ${k}`)}async function me(){if(T=!1,u){try{u.close()}catch{}u=null}g.clear(),d.clear(),k="",h.info("Workspace watch stopped")}function L(e,t,a){return $("sha256").update(`${e||"no-task"}:${t}:${a}`,"utf-8").digest("hex").slice(0,32)}function F(e){return $("sha256").update(s.resolve(e),"utf-8").digest("hex").slice(0,16)}function y(e){return s.join(C(),".aws-bridge",m,F(e))}function te(e){return s.join(C(),m,F(e))}function N(e){return s.join(e,Q)}const W=new Set;async function j(e){if(!W.has(e)){W.add(e);try{const t=N(e),a=y(e);await r.access(t),await r.mkdir(s.dirname(a),{recursive:!0}),await r.rename(t,a),h.info(`Migrated legacy change-cache: ${t} -> ${a}`)}catch{}}}async function v(e,t,a){if(a===null)return;await j(e);const o=y(e);await r.mkdir(o,{recursive:!0});const n=s.join(o,`${t}.before`);await r.writeFile(n,a,"utf-8"),U(),h.debug(`Saved beforeContent cache: ${n}`)}async function _(e,t,a,o){const n=X.createPatch("file",a,o);await j(e);const i=y(e);await r.mkdir(i,{recursive:!0});const c=s.join(i,`${t}.diff`);await r.writeFile(c,n,"utf-8"),U(),h.debug(`Saved diff cache: ${c}`)}async function M(e,t){const a=[s.join(y(e),t),s.join(te(e),t),s.join(N(e),t)];for(const o of a)try{return await r.readFile(o,"utf-8")}catch{}return null}async function ke(e,t){return M(e,`${t}.before`)}async function ye(e,t){return M(e,`${t}.diff`)}let x=0,A=null,P=Promise.resolve();function R(){return P=P.then(()=>ne()),P}async function ne(){const e=D();if(!(e===null||e<=0))try{const t=[s.join(C(),".aws-bridge",m),s.join(C(),m)],a=Date.now()-e*24*60*60*1e3;let o=0;for(const n of t){let i=[];try{i=(await r.readdir(n)).filter(c=>!c.startsWith("."))}catch{continue}for(const c of i){const f=s.join(n,c);try{const p=await r.readdir(f);let w=!0;for(const E of p){if(!E.endsWith(".diff")&&!E.endsWith(".before")){w=!1;continue}const S=s.join(f,E);try{(await r.stat(S)).mtimeMs<a?(await r.unlink(S),o++):w=!1}catch{w=!1}}w&&await r.rmdir(f).catch(()=>{})}catch{}}}o>0&&h.info(`Change-cache TTL sweep: removed ${o} expired file(s), retentionDays=${e}`)}catch(t){h.warn(`Change-cache TTL sweep failed: ${t.message}`)}}function U(){const e=Date.now();e-x>=Y&&(x=e,R().catch(()=>{})),A||(A=setInterval(()=>{R().catch(()=>{})},ee),A.unref?.())}async function B(e){try{return(await r.stat(e)).size>q?null:await r.readFile(e,"utf-8")}catch{return null}}function I(e){return e===null?null:$("sha256").update(e,"utf-8").digest("hex").slice(0,16)}async function ae(e){const t=g.get(e);if(!t)return;g.delete(e),t.timer&&clearTimeout(t.timer);const a=l;if(!a){if(t.operation==="DELETE")d.delete(e);else{const p=await B(e);p!==null&&d.set(e,p)}return}const o=s.relative(a.workspacePath,e).replace(/\\/g,"/");if(o.startsWith(".."))return;let n=t.beforeContent,i=null;t.operation==="DELETE"?(n=n??d.get(e)??null,i=null):(i=await B(e),t.operation==="UPDATE"&&n===null&&(n=d.get(e)??null)),t.operation==="DELETE"?d.delete(e):d.set(e,i);const c=new Date().toISOString(),f=L(a.taskInstanceId,o,c);t.operation==="UPDATE"&&n!==null&&i!==null?await _(a.workspacePath,f,n,i):t.operation==="DELETE"&&await v(a.workspacePath,f,n),await O(a,{workspacePath:a.workspacePath,filePath:o,operation:t.operation,beforeContent:n,afterContent:i,beforeHash:I(n),afterHash:I(i),timestamp:c,reason:z(t.operation,n,i)},f)}async function O(e,t,a){try{const o=J().url,n=H(o)||H();if(!n){h.warn("Cannot send change record: no auth token");return}const i=JSON.stringify({toolRecorded:!0,cacheKey:a,timestamp:t.timestamp}),f=(await G.post(`${o}/api/runtime/callback/task-file-changed`,{agentId:e.agentId,taskInstanceId:e.taskInstanceId,taskNodeId:e.taskNodeId,tenantId:e.tenantId,operation:t.operation,targetType:"FILE",targetPath:t.filePath,beforeHash:t.beforeHash,afterHash:t.afterHash,metadata:i,reason:t.reason,workspacePath:e.workspacePath},{headers:{"X-Runtime-Token":n},timeout:1e4})).data;if(f?.ignored===!0?h.warn(`Change record ignored by server: ${t.filePath} (${t.operation}), reason: ${String(f.reason??"unknown")}`):h.info(`Change record sent: ${t.filePath} (${t.operation})`),f&&f.changeCacheRetentionDays!==void 0){const p=D();Z(f.changeCacheRetentionDays),p!==D()&&(x=0,R().catch(()=>{}))}}catch(o){h.warn(`Failed to send change record: ${o.message}`)}}async function K(){if(b)return;b=!0;const e=Array.from(g.keys());for(const t of e)try{await ae(t)}catch{}b=!1}function Ie(){return g.size}function Ee(){return T&&u!==null}function $e(){return k}function z(e,t,a){const o=t?t.split(`
2
+ `).length:0,n=a?a.split(`
3
+ `).length:0;if(e==="CREATE")return`\u521B\u5EFA\u6587\u4EF6\uFF0C\u5171 ${n} \u884C`;if(e==="DELETE")return`\u5220\u9664\u6587\u4EF6\uFF0C\u539F ${o} \u884C`;if(o===n)return`\u4FEE\u6539\u6587\u4EF6\uFF08\u884C\u6570\u4E0D\u53D8\uFF0C${n} \u884C\uFF09`;const i=n-o;return`\u4FEE\u6539\u6587\u4EF6\uFF1A${o} \u884C -> ${n} \u884C\uFF08${i>0?"+":""}${i} \u884C\uFF09`}async function De(e){const t=l,a=e.agentId||t?.agentId,o=e.workspacePath||t?.workspacePath;if(!a||!o){h.warn(`Agent file change skipped (no identity): ${e.filePath} (${e.operation})`);return}h.info(`Recording agent file change: ${e.filePath} (${e.operation}), taskNode=${t?.taskNodeId??"(no task)"}`);const n=t??{agentId:a,taskInstanceId:"",taskNodeId:"",tenantId:"",workspacePath:o,projectId:""},i=new Date().toISOString(),c=L(n.taskInstanceId,e.filePath,i);e.operation==="UPDATE"&&e.beforeContent!==null&&e.afterContent!==null?(await _(n.workspacePath,c,e.beforeContent,e.afterContent),await v(n.workspacePath,c,e.beforeContent)):e.operation==="DELETE"&&await v(n.workspacePath,c,e.beforeContent);const f=e.reason?.trim()||z(e.operation,e.beforeContent,e.afterContent);await O(n,{workspacePath:n.workspacePath,filePath:e.filePath,operation:e.operation,beforeContent:e.beforeContent,afterContent:e.afterContent,beforeHash:I(e.beforeContent),afterHash:I(e.afterContent),timestamp:i,reason:f},c)}export{pe as clearTaskContext,Ie as getPendingChangeCountForTest,ge as getTaskContext,$e as getWorkspaceRoot,we as hasActiveTask,Ee as isWatching,ke as readBeforeContentFromCache,ye as readDiffFromCache,De as recordAgentFileChange,de as setTaskContext,Ce as startWatching,me as stopWatching,R as sweepExpiredChangeCache};
4
4
 
@@ -1,3 +1,3 @@
1
- import{spawn as E}from"node:child_process";import{createHash as h}from"node:crypto";import{createWriteStream as B,mkdirSync as b,renameSync as z,rmSync as U,writeFileSync as k}from"node:fs";import{promises as c}from"node:fs";import a from"node:path";import{Readable as T,Transform as y}from"node:stream";import{pipeline as v}from"node:stream/promises";import F from"unzipper";import S from"axios";import{DEFAULT_SCHEDULER_BASE_URL as L,schedulerBaseUrl as _}from"../config.js";import{getRuntimeAccessToken as p,loadRuntimeBinding as A}from"../services/runtime-binding.js";const d=new Map;function g(){const e=String(process.env.AWS_RUNTIME_SCHEDULER_BASE_URL||"").trim();if(e)return e;const t=A(),r=String(t.schedulerBaseUrl||"").trim();return t.status==="paired"&&r?r:_||L}async function W(e){return await c.mkdir(e,{recursive:!0}),e}async function Y(e,t){const r=a.resolve(e),n=d.get(r)??Promise.resolve();let i;const o=new Promise(m=>{i=m}),s=n.then(()=>o);d.set(r,s),await n;try{return await t()}finally{i(),d.get(r)===s&&d.delete(r)}}function j(e){if(!e||typeof e!="object")return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function w(e){return Array.isArray(e)?e.map(t=>w(t)):j(e)?Object.keys(e).sort().reduce((t,r)=>(t[r]=w(e[r]),t),{}):e}function N(e){return`${JSON.stringify(w(e),null,2)}
2
- `}function P(e){return String(e??"").replace(/[^a-zA-Z0-9_.-]/g,"_").replace(/^\.+/g,"").slice(0,128)}function x(e,t){const r=String(e??"").trim();if(!r||/[\\/]/.test(r))return t;const n=a.basename(r);return!n||n==="."||n===".."?t:n}async function C(e,t){await W(a.dirname(e));const r=a.dirname(e),n=a.basename(e),i=a.join(r,`.${n}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`);try{await c.writeFile(i,t,"utf-8"),await c.rename(i,e)}catch(o){throw await c.rm(i,{force:!0}).catch(()=>{}),o}}function ee(e,t){b(a.dirname(e),{recursive:!0});const r=a.dirname(e),n=a.basename(e),i=a.join(r,`.${n}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`);try{k(i,t,"utf-8"),z(i,e)}catch(o){try{U(i,{force:!0})}catch{}throw o}}async function re(e,t){await C(e,N(t))}async function te(e,t){if(!e||!e.downloadUrl)return null;const r=String(e.downloadUrl).trim();if(!r)return null;const n=g();let i=r;i.startsWith("/")&&(i=`${n}${i}`);const o=x(e.fileName,"skill-package.zip"),s=a.join(t,o),m=p(n)||p();if(!m)throw new Error("runtime access token is required to download skill package");const l=await S.get(i,{responseType:"arraybuffer",timeout:3e4,headers:{"X-Runtime-Token":m}}),u=Buffer.from(l.data);if(await c.writeFile(s,u),e.sha256&&h("sha256").update(u).digest("hex")!==String(e.sha256).trim().toLowerCase())throw new Error("skill zip checksum mismatch");return{fileName:o,outputPath:s,bytes:u.length}}async function ne(e,t){await new Promise((r,n)=>{const i=E(e,t,{stdio:["ignore","pipe","pipe"]});let o="";i.stderr?.on("data",s=>{o+=String(s||"")}),i.on("error",s=>{n(s)}),i.on("close",s=>{if(s!==0){n(new Error(o||`${e} exited with code ${s}`));return}r()})})}function ie(e){return String(e||"").replace(/'/g,"''")}const f={maxEntries:2e3,maxFileBytes:100*1024*1024,maxTotalBytes:200*1024*1024,maxPathLength:400,maxPathDepth:24};function D(e,t){const r=String(t||"").replace(/\\/g,"/");if(!r||r.startsWith("/")||/^[A-Za-z]:/.test(r)||r.split("/").includes(".."))throw new Error(`skill zip \u6761\u76EE\u8DEF\u5F84\u975E\u6CD5: ${t}`);if(r.length>f.maxPathLength)throw new Error(`skill zip \u6761\u76EE\u8DEF\u5F84\u8FC7\u957F: ${t}`);if(r.split("/").filter(Boolean).length>f.maxPathDepth)throw new Error(`skill zip \u6761\u76EE\u8DEF\u5F84\u8FC7\u6DF1: ${t}`);const n=a.resolve(e,r),i=a.resolve(e)+a.sep;if(n!==a.resolve(e)&&!n.startsWith(i))throw new Error(`skill zip \u6761\u76EE\u8D8A\u754C\uFF08zip-slip\uFF09: ${t}`);return n}function I(e,t){let r=0;return new y({transform(n,i,o){if(r+=n.length,r>e){o(new Error(`${t} \u8D85\u51FA\u4E0A\u9650\uFF08${e} \u5B57\u8282\uFF09`));return}o(null,n)}})}function O(e,t){let r=0;return{transform(){return new y({transform(n,i,o){if(r+=n.length,r>e){o(new Error(`${t} \u8D85\u51FA\u603B\u91CF\u4E0A\u9650\uFF08${e} \u5B57\u8282\uFF09`));return}o(null,n)}})}}}async function oe(e,t){await c.rm(t,{recursive:!0,force:!0}),await c.mkdir(t,{recursive:!0});const r=await c.readFile(e),n=T.from([r]),i=n.pipe(F.Parse({forceStream:!0}));let o=0,s=0;const m=O(f.maxTotalBytes,"skill zip \u89E3\u538B\u603B\u91CF");try{for await(const l of i){const u=D(t,l.path);if(l.type==="Directory"){await c.mkdir(u,{recursive:!0}),l.autodrain?.();continue}if(l.type!=="File"){l.autodrain?.();continue}if(o++,o>f.maxEntries)throw new Error(`skill zip \u6761\u76EE\u6570\u8D85\u51FA\u4E0A\u9650\uFF08${f.maxEntries}\uFF09`);if(s+=Number(l.size??0),s>f.maxTotalBytes)throw new Error(`skill zip \u603B\u91CF\u8D85\u51FA\u4E0A\u9650\uFF08${f.maxTotalBytes} \u5B57\u8282\uFF09`);await c.mkdir(a.dirname(u),{recursive:!0}),await v(l,I(f.maxFileBytes,`skill zip \u6761\u76EE ${l.path}`),m.transform(),B(u))}}catch(l){throw await c.rm(t,{recursive:!0,force:!0}).catch(()=>{}),l}finally{n.destroy(),i.destroy?.()}}async function se(e){const r=(await c.readdir(e,{withFileTypes:!0})).filter(n=>!n.name.startsWith("."));return r.length===1&&r[0].isDirectory()?a.join(e,r[0].name):e}async function ae(e,t){if(!e||!e.downloadUrl)return null;const r=String(e.downloadUrl).trim();if(!r)return null;const n=g();let i=r;i.startsWith("/")&&(i=`${n}${i}`);const o=x(e.fileName,"plugin-package.zip"),s=a.join(t,o),m=p(n)||p();if(!m)throw new Error("runtime access token is required to download plugin package");const l=await S.get(i,{responseType:"arraybuffer",timeout:3e4,headers:{"X-Runtime-Token":m}}),u=Buffer.from(l.data);if(await c.writeFile(s,u),e.sha256&&h("sha256").update(u).digest("hex")!==String(e.sha256).trim().toLowerCase())throw new Error(`plugin package sha256 mismatch: ${o}`);return{fileName:o,outputPath:s,bytes:u.length}}export{C as atomicWriteFile,ee as atomicWriteFileSync,re as atomicWriteJsonFile,ae as downloadPluginZip,te as downloadSkillZip,W as ensureDir,ie as escapePowerShellLiteral,oe as extractSkillZip,se as resolveSkillSourceDirFromExtractRoot,ne as runCommand,P as sanitizeAgentId,x as sanitizeArchiveFileName,N as stringifyStableJson,Y as withFileLock};
1
+ import{spawn as E}from"node:child_process";import{createHash as h}from"node:crypto";import{createWriteStream as B,mkdirSync as b,renameSync as z,rmSync as U,writeFileSync as k,promises as c}from"node:fs";import a from"node:path";import{Readable as T,Transform as y}from"node:stream";import{pipeline as v}from"node:stream/promises";import S from"axios";import F from"unzipper";import{DEFAULT_SCHEDULER_BASE_URL as L,schedulerBaseUrl as _}from"../config.js";import{getRuntimeAccessToken as p,loadRuntimeBinding as A}from"../services/runtime-binding.js";const d=new Map;function g(){const e=String(process.env.AWS_RUNTIME_SCHEDULER_BASE_URL||"").trim();if(e)return e;const t=A(),r=String(t.schedulerBaseUrl||"").trim();return t.status==="paired"&&r?r:_||L}async function W(e){return await c.mkdir(e,{recursive:!0}),e}async function Q(e,t){const r=a.resolve(e),n=d.get(r)??Promise.resolve();let i;const o=new Promise(m=>{i=m}),s=n.then(()=>o);d.set(r,s),await n;try{return await t()}finally{i(),d.get(r)===s&&d.delete(r)}}function j(e){if(!e||typeof e!="object")return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function w(e){return Array.isArray(e)?e.map(t=>w(t)):j(e)?Object.keys(e).sort().reduce((t,r)=>(t[r]=w(e[r]),t),{}):e}function N(e){return`${JSON.stringify(w(e),null,2)}
2
+ `}function Y(e){return String(e??"").replace(/[^a-zA-Z0-9_.-]/g,"_").replace(/^\.+/g,"").slice(0,128)}function x(e,t){const r=String(e??"").trim();if(!r||/[\\/]/.test(r))return t;const n=a.basename(r);return!n||n==="."||n===".."?t:n}async function C(e,t){await W(a.dirname(e));const r=a.dirname(e),n=a.basename(e),i=a.join(r,`.${n}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`);try{await c.writeFile(i,t,"utf-8"),await c.rename(i,e)}catch(o){throw await c.rm(i,{force:!0}).catch(()=>{}),o}}function P(e,t){b(a.dirname(e),{recursive:!0});const r=a.dirname(e),n=a.basename(e),i=a.join(r,`.${n}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`);try{k(i,t,"utf-8"),z(i,e)}catch(o){try{U(i,{force:!0})}catch{}throw o}}async function ee(e,t){await C(e,N(t))}async function re(e,t){if(!e||!e.downloadUrl)return null;const r=String(e.downloadUrl).trim();if(!r)return null;const n=g();let i=r;i.startsWith("/")&&(i=`${n}${i}`);const o=x(e.fileName,"skill-package.zip"),s=a.join(t,o),m=p(n)||p();if(!m)throw new Error("runtime access token is required to download skill package");const l=await S.get(i,{responseType:"arraybuffer",timeout:3e4,headers:{"X-Runtime-Token":m}}),u=Buffer.from(l.data);if(await c.writeFile(s,u),e.sha256&&h("sha256").update(u).digest("hex")!==String(e.sha256).trim().toLowerCase())throw new Error("skill zip checksum mismatch");return{fileName:o,outputPath:s,bytes:u.length}}async function te(e,t){await new Promise((r,n)=>{const i=E(e,t,{stdio:["ignore","pipe","pipe"]});let o="";i.stderr?.on("data",s=>{o+=String(s||"")}),i.on("error",s=>{n(s)}),i.on("close",s=>{if(s!==0){n(new Error(o||`${e} exited with code ${s}`));return}r()})})}function ne(e){return String(e||"").replace(/'/g,"''")}const f={maxEntries:2e3,maxFileBytes:100*1024*1024,maxTotalBytes:200*1024*1024,maxPathLength:400,maxPathDepth:24};function D(e,t){const r=String(t||"").replace(/\\/g,"/");if(!r||r.startsWith("/")||/^[A-Za-z]:/.test(r)||r.split("/").includes(".."))throw new Error(`skill zip \u6761\u76EE\u8DEF\u5F84\u975E\u6CD5: ${t}`);if(r.length>f.maxPathLength)throw new Error(`skill zip \u6761\u76EE\u8DEF\u5F84\u8FC7\u957F: ${t}`);if(r.split("/").filter(Boolean).length>f.maxPathDepth)throw new Error(`skill zip \u6761\u76EE\u8DEF\u5F84\u8FC7\u6DF1: ${t}`);const n=a.resolve(e,r),i=a.resolve(e)+a.sep;if(n!==a.resolve(e)&&!n.startsWith(i))throw new Error(`skill zip \u6761\u76EE\u8D8A\u754C\uFF08zip-slip\uFF09: ${t}`);return n}function I(e,t){let r=0;return new y({transform(n,i,o){if(r+=n.length,r>e){o(new Error(`${t} \u8D85\u51FA\u4E0A\u9650\uFF08${e} \u5B57\u8282\uFF09`));return}o(null,n)}})}function O(e,t){let r=0;return{transform(){return new y({transform(n,i,o){if(r+=n.length,r>e){o(new Error(`${t} \u8D85\u51FA\u603B\u91CF\u4E0A\u9650\uFF08${e} \u5B57\u8282\uFF09`));return}o(null,n)}})}}}async function ie(e,t){await c.rm(t,{recursive:!0,force:!0}),await c.mkdir(t,{recursive:!0});const r=await c.readFile(e),n=T.from([r]),i=n.pipe(F.Parse({forceStream:!0}));let o=0,s=0;const m=O(f.maxTotalBytes,"skill zip \u89E3\u538B\u603B\u91CF");try{for await(const l of i){const u=D(t,l.path);if(l.type==="Directory"){await c.mkdir(u,{recursive:!0}),l.autodrain?.();continue}if(l.type!=="File"){l.autodrain?.();continue}if(o++,o>f.maxEntries)throw new Error(`skill zip \u6761\u76EE\u6570\u8D85\u51FA\u4E0A\u9650\uFF08${f.maxEntries}\uFF09`);if(s+=Number(l.size??0),s>f.maxTotalBytes)throw new Error(`skill zip \u603B\u91CF\u8D85\u51FA\u4E0A\u9650\uFF08${f.maxTotalBytes} \u5B57\u8282\uFF09`);await c.mkdir(a.dirname(u),{recursive:!0}),await v(l,I(f.maxFileBytes,`skill zip \u6761\u76EE ${l.path}`),m.transform(),B(u))}}catch(l){throw await c.rm(t,{recursive:!0,force:!0}).catch(()=>{}),l}finally{n.destroy(),i.destroy?.()}}async function oe(e){const r=(await c.readdir(e,{withFileTypes:!0})).filter(n=>!n.name.startsWith("."));return r.length===1&&r[0].isDirectory()?a.join(e,r[0].name):e}async function se(e,t){if(!e||!e.downloadUrl)return null;const r=String(e.downloadUrl).trim();if(!r)return null;const n=g();let i=r;i.startsWith("/")&&(i=`${n}${i}`);const o=x(e.fileName,"plugin-package.zip"),s=a.join(t,o),m=p(n)||p();if(!m)throw new Error("runtime access token is required to download plugin package");const l=await S.get(i,{responseType:"arraybuffer",timeout:3e4,headers:{"X-Runtime-Token":m}}),u=Buffer.from(l.data);if(await c.writeFile(s,u),e.sha256&&h("sha256").update(u).digest("hex")!==String(e.sha256).trim().toLowerCase())throw new Error(`plugin package sha256 mismatch: ${o}`);return{fileName:o,outputPath:s,bytes:u.length}}export{C as atomicWriteFile,P as atomicWriteFileSync,ee as atomicWriteJsonFile,se as downloadPluginZip,re as downloadSkillZip,W as ensureDir,ne as escapePowerShellLiteral,ie as extractSkillZip,oe as resolveSkillSourceDirFromExtractRoot,te as runCommand,Y as sanitizeAgentId,x as sanitizeArchiveFileName,N as stringifyStableJson,Q as withFileLock};
3
3
 
@@ -1,4 +1,4 @@
1
- import n from"node:fs/promises";import a from"node:path";import g from"node:os";const c=a.join(g.userInfo().homedir,"Instance-ai-configuration-debug.log");class l{constructor(s=c){this.logPath=s}async log(s){try{const o=[`[${new Date().toISOString()}]`,`[${s.level.toUpperCase()}]`,`[${s.source}]`,`[${s.category}]`,s.message];s.sessionId&&o.push(`session=${s.sessionId}`),s.agentId&&o.push(`agent=${s.agentId}`);const i=o.join(" "),e=s.details?` ${JSON.stringify(s.details,null,2)}`:"";await n.appendFile(this.logPath,`${i}
1
+ import n from"node:fs/promises";import a from"node:os";import g from"node:path";const c=g.join(a.userInfo().homedir,"Instance-ai-configuration-debug.log");class l{constructor(s=c){this.logPath=s}async log(s){try{const o=[`[${new Date().toISOString()}]`,`[${s.level.toUpperCase()}]`,`[${s.source}]`,`[${s.category}]`,s.message];s.sessionId&&o.push(`session=${s.sessionId}`),s.agentId&&o.push(`agent=${s.agentId}`);const i=o.join(" "),e=s.details?` ${JSON.stringify(s.details,null,2)}`:"";await n.appendFile(this.logPath,`${i}
2
2
  ${e?`${e}
3
3
  `:""}`,"utf-8")}catch{}}async flush(){}}let t;function d(){return t||(t=new l),t}export{l as InstanceAiConfigDebugLogger,d as getInstanceAiConfigDebugLogger};
4
4
 
@@ -1,2 +1,2 @@
1
- import{randomUUID as o}from"node:crypto";import{parseBoolean as a}from"./validation.js";function m(n){if(!n||typeof n!="object")return null;const r=n,t=String(r.name||"").trim();return t?{id:String(r.id||o()),name:t,transport:String(r.transport||"stdio").trim().toLowerCase(),command:r.command==null?"":String(r.command),url:r.url==null?"":String(r.url),args:Array.isArray(r.args)?r.args.map(e=>String(e)):[],env:r.env&&typeof r.env=="object"?r.env:{},enabled:a(r.enabled,!0),installedAt:r.installedAt||new Date().toISOString()}:null}export{m as normalizeMcpPayload};
1
+ import{randomUUID as o}from"node:crypto";import{parseBoolean as i}from"./validation.js";function m(r){if(!r||typeof r!="object")return null;const n=r,t=String(n.name||"").trim();return t?{id:String(n.id||o()),name:t,transport:String(n.transport||"stdio").trim().toLowerCase(),command:n.command===null||n.command===void 0?"":String(n.command),url:n.url===null||n.url===void 0?"":String(n.url),args:Array.isArray(n.args)?n.args.map(e=>String(e)):[],env:n.env&&typeof n.env=="object"?n.env:{},enabled:i(n.enabled,!0),installedAt:n.installedAt||new Date().toISOString()}:null}export{m as normalizeMcpPayload};
2
2
 
@@ -1,2 +1,2 @@
1
- import f from"node:path";import{promises as m}from"node:fs";import*as g from"js-yaml";import{createLogger as y}from"./logger.js";const d=y("yaml-utils");function P(a,p){try{const n=g.load(a);if(!n||typeof n!="object")return null;const i=n.agent;if(!Array.isArray(i))return null;const r=p.replace(/\\/g,"/");for(const t of i){if(!t||typeof t!="object")continue;const o=t.path;if(typeof o!="string")continue;const u=o.replace(/\\/g,"/");if(u===r||r==="."&&(u==="."||u===""))return o}return null}catch{return null}}function S(a,p){try{const n=g.load(a);if(!n||typeof n!="object")return{content:a,isTemplate:!1,projectFromSibling:null};const i=n.agent;if(!Array.isArray(i))return{content:a,isTemplate:!1,projectFromSibling:null};const r=p.replace(/\\/g,"/");for(const e of i){if(!e||typeof e!="object")continue;const s=e,c=s.path;if(typeof c!="string")continue;const l=c.replace(/\\/g,"/");if(l===r||r==="."&&(l==="."||l==="")){const b={...s,path:l};return{content:g.dump({agent:[b]},{indent:2,lineWidth:-1,quotingType:'"',forceQuotes:!1}),isTemplate:!1,projectFromSibling:null}}}let t=null;for(const e of i){if(!e||typeof e!="object")continue;const s=e;if(typeof s.project=="string"){t=s.project;break}}const o={agent:[{name:"",path:r,project:t||"",describe:"",prompt:""}]};return{content:g.dump(o,{indent:2,lineWidth:-1,quotingType:'"',forceQuotes:!1}),isTemplate:!0,projectFromSibling:t}}catch{return{content:a,isTemplate:!1,projectFromSibling:null}}}function w(a){const n={agent:[{name:"",path:String(a||".").trim().replace(/\\/g,"/")||".",project:"",describe:"",prompt:""}]};return g.dump(n,{indent:2,lineWidth:-1,quotingType:'"',forceQuotes:!1})}function z(a,p){try{const n=g.load(a);if(!n||typeof n!="object")return a;const i=n;if(!i.agent||!Array.isArray(i.agent))return a;let r=!1;for(const t of i.agent)if(t){const o=t.path;(o==null||String(o).trim()==="")&&(t.path=p,r=!0)}return r?g.dump(i,{indent:2,lineWidth:-1,quotingType:'"',forceQuotes:!1}):a}catch{return a}}async function F(a,p){const n=f.resolve(a),i=p.replace(/\//g,f.sep),r=f.resolve(n,i);let t=null;try{const e=await m.readFile(r,"utf-8");d.debug(`\u5DE5\u4F5C\u76EE\u5F55\u4E0B\u627E\u5230\u914D\u7F6E: ${r}`);const c=P(e,".");if(c)return d.debug(`\u5F53\u524D\u76EE\u5F55\u914D\u7F6E\u5339\u914D path: ${c}`),{content:e,resolvedPath:r,foundInParent:!1,matchedAgentPath:c};d.debug("\u5F53\u524D\u76EE\u5F55\u914D\u7F6E\u4E0D\u5339\u914D\uFF0C\u7EE7\u7EED\u5411\u4E0A\u67E5\u627E"),t={content:e,resolvedPath:r}}catch(e){if(e?.code!=="ENOENT")throw e}let o=n;const u=f.parse(o).root;for(;o&&o!==u;){const e=f.dirname(o);if(e===o)break;const s=f.relative(e,n),c=f.join(e,i);try{const l=await m.readFile(c,"utf-8");d.debug(`\u4E0A\u5C42\u627E\u5230\u914D\u7F6E\u6587\u4EF6: ${c}`);const h=P(l,s);if(d.debug(`\u76F8\u5BF9\u8DEF\u5F84: ${s}, \u5339\u914D\u7684agent path: ${h||"\u65E0"}`),h)return{content:l,resolvedPath:c,foundInParent:!0,matchedAgentPath:h};t={content:l,resolvedPath:c}}catch(l){if(l?.code!=="ENOENT")throw l}o=e}return t?(d.debug(`\u6240\u6709\u5C42\u7EA7\u90FD\u4E0D\u5339\u914D\uFF0C\u4F7F\u7528\u6700\u540E\u627E\u5230\u7684\u914D\u7F6E: ${t.resolvedPath}`),{content:t.content,resolvedPath:t.resolvedPath,foundInParent:t.resolvedPath!==r,matchedAgentPath:null}):(d.debug(`\u672A\u627E\u5230\u914D\u7F6E\uFF0C\u5C06\u5728\u5DE5\u4F5C\u76EE\u5F55\u521B\u5EFA: ${r}`),{content:null,resolvedPath:r,foundInParent:!1,matchedAgentPath:null})}export{z as autoFillPathInYml,S as extractAgentConfigOrTemplate,w as generateEmptyTemplate,P as hasMatchingAgentPath,F as loadYmlWithUpwardSearch};
1
+ import{promises as m}from"node:fs";import f from"node:path";import*as g from"js-yaml";import{createLogger as y}from"./logger.js";const d=y("yaml-utils");function P(a,p){try{const n=g.load(a);if(!n||typeof n!="object")return null;const i=n.agent;if(!Array.isArray(i))return null;const r=p.replace(/\\/g,"/");for(const t of i){if(!t||typeof t!="object")continue;const o=t.path;if(typeof o!="string")continue;const u=o.replace(/\\/g,"/");if(u===r||r==="."&&(u==="."||u===""))return o}return null}catch{return null}}function S(a,p){try{const n=g.load(a);if(!n||typeof n!="object")return{content:a,isTemplate:!1,projectFromSibling:null};const i=n.agent;if(!Array.isArray(i))return{content:a,isTemplate:!1,projectFromSibling:null};const r=p.replace(/\\/g,"/");for(const e of i){if(!e||typeof e!="object")continue;const s=e,c=s.path;if(typeof c!="string")continue;const l=c.replace(/\\/g,"/");if(l===r||r==="."&&(l==="."||l==="")){const b={...s,path:l};return{content:g.dump({agent:[b]},{indent:2,lineWidth:-1,quotingType:'"',forceQuotes:!1}),isTemplate:!1,projectFromSibling:null}}}let t=null;for(const e of i){if(!e||typeof e!="object")continue;const s=e;if(typeof s.project=="string"){t=s.project;break}}const o={agent:[{name:"",path:r,project:t||"",describe:"",prompt:""}]};return{content:g.dump(o,{indent:2,lineWidth:-1,quotingType:'"',forceQuotes:!1}),isTemplate:!0,projectFromSibling:t}}catch{return{content:a,isTemplate:!1,projectFromSibling:null}}}function w(a){const n={agent:[{name:"",path:String(a||".").trim().replace(/\\/g,"/")||".",project:"",describe:"",prompt:""}]};return g.dump(n,{indent:2,lineWidth:-1,quotingType:'"',forceQuotes:!1})}function z(a,p){try{const n=g.load(a);if(!n||typeof n!="object")return a;const i=n;if(!i.agent||!Array.isArray(i.agent))return a;let r=!1;for(const t of i.agent)if(t){const o=t.path;(o==null||String(o).trim()==="")&&(t.path=p,r=!0)}return r?g.dump(i,{indent:2,lineWidth:-1,quotingType:'"',forceQuotes:!1}):a}catch{return a}}async function F(a,p){const n=f.resolve(a),i=p.replace(/\//g,f.sep),r=f.resolve(n,i);let t=null;try{const e=await m.readFile(r,"utf-8");d.debug(`\u5DE5\u4F5C\u76EE\u5F55\u4E0B\u627E\u5230\u914D\u7F6E: ${r}`);const c=P(e,".");if(c)return d.debug(`\u5F53\u524D\u76EE\u5F55\u914D\u7F6E\u5339\u914D path: ${c}`),{content:e,resolvedPath:r,foundInParent:!1,matchedAgentPath:c};d.debug("\u5F53\u524D\u76EE\u5F55\u914D\u7F6E\u4E0D\u5339\u914D\uFF0C\u7EE7\u7EED\u5411\u4E0A\u67E5\u627E"),t={content:e,resolvedPath:r}}catch(e){if(e?.code!=="ENOENT")throw e}let o=n;const u=f.parse(o).root;for(;o&&o!==u;){const e=f.dirname(o);if(e===o)break;const s=f.relative(e,n),c=f.join(e,i);try{const l=await m.readFile(c,"utf-8");d.debug(`\u4E0A\u5C42\u627E\u5230\u914D\u7F6E\u6587\u4EF6: ${c}`);const h=P(l,s);if(d.debug(`\u76F8\u5BF9\u8DEF\u5F84: ${s}, \u5339\u914D\u7684agent path: ${h||"\u65E0"}`),h)return{content:l,resolvedPath:c,foundInParent:!0,matchedAgentPath:h};t={content:l,resolvedPath:c}}catch(l){if(l?.code!=="ENOENT")throw l}o=e}return t?(d.debug(`\u6240\u6709\u5C42\u7EA7\u90FD\u4E0D\u5339\u914D\uFF0C\u4F7F\u7528\u6700\u540E\u627E\u5230\u7684\u914D\u7F6E: ${t.resolvedPath}`),{content:t.content,resolvedPath:t.resolvedPath,foundInParent:t.resolvedPath!==r,matchedAgentPath:null}):(d.debug(`\u672A\u627E\u5230\u914D\u7F6E\uFF0C\u5C06\u5728\u5DE5\u4F5C\u76EE\u5F55\u521B\u5EFA: ${r}`),{content:null,resolvedPath:r,foundInParent:!1,matchedAgentPath:null})}export{z as autoFillPathInYml,S as extractAgentConfigOrTemplate,w as generateEmptyTemplate,P as hasMatchingAgentPath,F as loadYmlWithUpwardSearch};
2
2
 
@@ -1,14 +1,9 @@
1
- const d=/^[a-z0-9][a-z0-9-]*$/,y=`\u8C03\u7528\u63D2\u4EF6\u5C42\u6CE8\u5165\u7684\u5DE5\u5177\uFF08\u4E09\u65B9\u5DE5\u5177\u7ECF\u63D2\u4EF6\u63A5\u5165\u540E\u7684\u7EDF\u4E00\u8C03\u7528\u5165\u53E3\uFF09\u3002
1
+ const h=/^[a-z0-9][a-z0-9-]*$/,d=`\u8C03\u7528\u63D2\u4EF6\u5C42\u6CE8\u5165\u7684\u5DE5\u5177\uFF08\u4E09\u65B9\u5DE5\u5177\u7ECF\u63D2\u4EF6\u63A5\u5165\u540E\u7684\u7EDF\u4E00\u8C03\u7528\u5165\u53E3\uFF09\u3002
2
2
  \u63D2\u4EF6\u5DE5\u5177\u4E0D\u5728\u4F60\u7684\u9759\u6001\u5DE5\u5177\u5217\u8868\u4E2D\uFF1A\u53EF\u7528\u5DE5\u5177\u7684\u7D27\u51D1\u76EE\u5F55\u968F poll_message \u7ED3\u679C\u7684 pluginCatalog \u5B57\u6BB5\u8FD4\u56DE\uFF08\u542B\u63D2\u4EF6\u540D\u3001\u5DE5\u5177\u540D\u3001\u4E00\u53E5\u8BDD\u63CF\u8FF0\u3001\u5FC5\u586B\u53C2\u6570\uFF09\uFF0C\u63D2\u4EF6\u4E8B\u4EF6\u6D88\u606F\u5C3E\u90E8\u4F1A\u9644 toolHints \u63D0\u793A\u5EFA\u8BAE\u8C03\u7528\u7684\u5DE5\u5177\u3002
3
3
  \u7528\u6CD5\uFF1A
4
4
  - action=call\uFF08\u9ED8\u8BA4\uFF09\uFF1Atool \u4F20\u9650\u5B9A\u540D "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF08\u5982 "wechat-cli.send_msg"\uFF09\uFF0Cparams \u4F20\u52A8\u6001\u53C2\u6570\u5BF9\u8C61\uFF1B\u53C2\u6570\u6309\u63D2\u4EF6\u58F0\u660E\u7684 JSON Schema \u6821\u9A8C\uFF0C\u6821\u9A8C\u5931\u8D25\u65F6\u8FD4\u56DE\u7ED3\u679C\u4F1A\u9644\u5E26\u5B8C\u6574 inputSchema\uFF0C\u8BF7\u4FEE\u6B63\u540E\u91CD\u8BD5\u3002
5
5
  - action=schema\uFF1Atool \u4F20\u9650\u5B9A\u540D\uFF08\u652F\u6301 "\u63D2\u4EF6\u540D.*"\uFF09\uFF0C\u8FD4\u56DE\u8BE5\u5DE5\u5177\uFF08\u6216\u63D2\u4EF6\u5168\u90E8\u5DE5\u5177\uFF09\u7684\u5B8C\u6574 JSON Schema \u5B9A\u4E49\u3002\u76EE\u5F55\u63CF\u8FF0\u4E0D\u591F\u7528\u3001\u6216\u53C2\u6570\u6821\u9A8C\u53CD\u590D\u5931\u8D25\u65F6\u5148\u53D6 schema\u3002
6
6
  - action=catalog\uFF1A\u8FD4\u56DE\u5F53\u524D\u5168\u90E8\u63D2\u4EF6\u7684\u7D27\u51D1\u76EE\u5F55\uFF08\u5B89\u88C5\u65B0\u63D2\u4EF6\u540E\u53EF\u7528\u5B83\u7ACB\u5373\u611F\u77E5\uFF09\u3002
7
- \u6CE8\u610F\uFF1A\u63D2\u4EF6\u672A\u5B89\u88C5/\u5DF2\u505C\u7528/\u5DE5\u5177\u4E0D\u5B58\u5728\u65F6\u8FD4\u56DE\u660E\u786E\u9519\u8BEF\uFF0C\u4E0D\u8981\u51ED\u7A7A\u7F16\u9020\u5DE5\u5177\u540D\u3002`,h=`\u7BA1\u7406\u63D2\u4EF6\u751F\u547D\u5468\u671F\uFF08\u5B89\u88C5/\u5378\u8F7D/\u91CD\u8F7D/\u542F\u505C/\u5217\u8868\uFF09\u3002\u4EC5\u5F53\u7528\u6237\u660E\u786E\u8981\u6C42\u5B89\u88C5\u3001\u79FB\u9664\u6216\u4FEE\u590D\u63D2\u4EF6\u65F6\u4F7F\u7528\u3002
8
- - action=list\uFF1A\u5217\u51FA\u5DF2\u5B89\u88C5\u63D2\u4EF6\uFF08\u72B6\u6001\u3001\u76D1\u542C\u5668\u5065\u5EB7\u3001\u5DE5\u5177\u6570\uFF09\u3002
9
- - action=install\uFF1Asource \u4E3A\u63D2\u4EF6\u6765\u6E90\uFF0C\u5F53\u524D\u652F\u6301 "local:<\u63D2\u4EF6\u76EE\u5F55\u4E0B\u7684\u8DEF\u5F84>"\uFF08\u63D2\u4EF6\u5FC5\u987B\u4F4D\u4E8E\u63D2\u4EF6\u6839\u76EE\u5F55\u5185\uFF0C\u4E0D\u5141\u8BB8\u4EFB\u610F\u7CFB\u7EDF\u8DEF\u5F84\uFF09\uFF1Bconfig \u4F20\u63D2\u4EF6 manifest \u91CC userConfig \u58F0\u660E\u7684\u914D\u7F6E\u503C\uFF08\u5982 wechat-cli \u7684 WECHAT_TOKEN\uFF09\u3002\u5B89\u88C5\u540E\u7ACB\u5373\u751F\u6548\uFF1A\u4E0B\u4E00\u6B21 poll_message \u7684 pluginCatalog \u5373\u53EF\u89C1\uFF0C\u76D1\u542C\u5668\u5F00\u59CB\u5411 poll_message \u6295\u9012\u4E8B\u4EF6\u3002
10
- - action=reload\uFF1A\u91CD\u8F7D\u6307\u5B9A\u63D2\u4EF6\uFF08\u6539\u8FC7\u63D2\u4EF6\u6587\u4EF6\u540E\u4F7F\u7528\uFF09\uFF0C\u539F\u5B50\u6362\u88C5\uFF0C\u76D1\u542C\u5668\u91CD\u542F\u3002
11
- - action=enable / disable\uFF1A\u505C\u7528/\u542F\u7528\uFF08disable \u4FDD\u7559\u5B89\u88C5\u4E0E\u914D\u7F6E\uFF0C\u4EC5\u505C\u6B62\u76D1\u542C\u4E0E\u5DE5\u5177\u8C03\u7528\uFF09\u3002
12
- - action=uninstall\uFF1A\u5378\u8F7D\u5E76\u5220\u9664\u63D2\u4EF6\u76EE\u5F55\uFF08\u4E0D\u53EF\u9006\uFF0C\u9700\u7528\u6237\u660E\u786E\u8981\u6C42\uFF09\u3002`;function _(e){const t=e.indexOf(".");if(t<=0||t>=e.length-1)return null;const i=e.slice(0,t),n=e.slice(t+1);return!d.test(i)||!n.trim()?null:{plugin:i,tool:n.trim()}}function C(e){const t=e.pluginBridge;return t?[S(t),b(t)]:[]}function S(e){return{kind:"builtin",toolName:"function_call",exposedName:"function_call",category:"plugin",description:y,inputSchema:{type:"object",properties:{action:{type:"string",enum:["call","schema","catalog"],default:"call",description:"call=\u8C03\u7528\u63D2\u4EF6\u5DE5\u5177\uFF1Bschema=\u53D6\u5B8C\u6574\u53C2\u6570\u5B9A\u4E49\uFF1Bcatalog=\u53D6\u63D2\u4EF6\u5DE5\u5177\u76EE\u5F55"},tool:{type:"string",description:'\u9650\u5B9A\u540D "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF08\u5982 "wechat-cli.send_msg"\uFF09\uFF1Baction=schema \u65F6\u652F\u6301 "\u63D2\u4EF6\u540D.*" \u53D6\u6574\u7EC4\u5B9A\u4E49'},params:{type:"object",description:"call \u7684\u52A8\u6001\u53C2\u6570\u5BF9\u8C61\uFF0C\u6309\u63D2\u4EF6\u58F0\u660E\u7684 inputSchema \u6821\u9A8C"}},required:["tool"],additionalProperties:!1},async execute(t,i){const n=typeof t.action=="string"?t.action:"call",o=typeof t.tool=="string"?t.tool.trim():"";try{if(n==="catalog")return await e.getCatalog();if(!o)return{error:'\u7F3A\u5C11 tool \u53C2\u6570\uFF08\u9650\u5B9A\u540D "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF09'};if(n==="schema"){if(o.endsWith(".*")){const r=o.slice(0,-2),m=await e.getCatalog(),g=m.plugins.find(u=>u.plugin===r);if(!g)return{error:`\u63D2\u4EF6 ${r} \u672A\u5B89\u88C5\u6216\u5DF2\u505C\u7528`,catalog:m.plugins};const f=await Promise.all(g.tools.map(u=>e.getToolSchema(`${r}.${u.name}`)));return{plugin:r,schemas:f.filter(Boolean)}}const p=await e.getToolSchema(o);return p||{error:`\u672A\u77E5\u63D2\u4EF6\u5DE5\u5177: ${o}\uFF08\u53EF\u5148 action=catalog \u67E5\u770B\u76EE\u5F55\uFF09`}}if(n!=="call")return{error:`\u672A\u77E5 action: ${n}\uFF08\u5141\u8BB8\uFF1Acall / schema / catalog\uFF09`};const a=_(o);if(!a)return{error:`tool \u9650\u5B9A\u540D\u4E0D\u5408\u6CD5: ${o}\uFF08\u5E94\u4E3A "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF0C\u63D2\u4EF6\u540D\u4E3A kebab-case\uFF09`};const c=t.params&&typeof t.params=="object"&&!Array.isArray(t.params)?t.params:{},l=await e.invokeTool(a.plugin,a.tool,c,{toolCallId:i?.toolCallId});if(l.ok)return l.result??{ok:!0};const s={error:l.error??"\u63D2\u4EF6\u5DE5\u5177\u8C03\u7528\u5931\u8D25"};return l.inputSchema!==void 0&&(s.inputSchema=l.inputSchema),typeof l.durationMs=="number"&&(s.durationMs=l.durationMs),s}catch(a){return{error:`function_call \u5931\u8D25: ${a instanceof Error?a.message:String(a)}`}}}}}function b(e){return{kind:"builtin",toolName:"plugin_manage",exposedName:"plugin_manage",category:"plugin",description:h,inputSchema:{type:"object",properties:{action:{type:"string",enum:["install","uninstall","reload","enable","disable","list"],description:"\u751F\u547D\u5468\u671F\u52A8\u4F5C"},name:{type:"string",description:"\u63D2\u4EF6\u540D\uFF08uninstall/reload/enable/disable \u5FC5\u586B\uFF09"},source:{type:"string",description:'install \u6765\u6E90\uFF0C\u5F53\u524D\u652F\u6301 "local:<\u63D2\u4EF6\u76EE\u5F55\u4E0B\u7684\u8DEF\u5F84>"\uFF08\u63D2\u4EF6\u5FC5\u987B\u4F4D\u4E8E\u63D2\u4EF6\u6839\u76EE\u5F55\u5185\u52A0\u8F7D\uFF09'},config:{type:"object",description:"install \u65F6\u63D2\u4EF6 userConfig \u58F0\u660E\u7684\u914D\u7F6E\u503C\uFF08\u952E\u503C\u5BF9\uFF09",additionalProperties:{type:"string"}}},required:["action"],additionalProperties:!1},async execute(t){const i=t.action;if(typeof i!="string")return{error:"\u7F3A\u5C11 action"};const n={action:i};if(typeof t.name=="string"&&t.name.trim()&&(n.name=t.name.trim()),typeof t.source=="string"&&t.source.trim()&&(n.source=t.source.trim()),t.config&&typeof t.config=="object"&&!Array.isArray(t.config)){const o={};for(const[a,c]of Object.entries(t.config))typeof c=="string"&&(o[a]=c);n.config=o}try{return await e.manage(n)}catch(o){const a=o instanceof Error?o.message:String(o);return{ok:!1,error:`plugin_manage.${i} \u5931\u8D25: ${a}`}}}}}function N(){return["## \u63D2\u4EF6\u7CFB\u7EDF",'- \u4E09\u65B9\u5DE5\u5177\u4EE5\u63D2\u4EF6\u5F62\u5F0F\u63A5\u5165\u3002\u63D2\u4EF6\u5DE5\u5177\u4E0D\u5728\u4F60\u7684\u9759\u6001\u5DE5\u5177\u5217\u8868\u4E2D\uFF1A\u7D27\u51D1\u76EE\u5F55\u968F poll_message \u7ED3\u679C\u7684 pluginCatalog \u5B57\u6BB5\u8FD4\u56DE\uFF1B\u7528 function_call \u8C03\u7528\uFF08tool="\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF0Cparams \u4E3A\u52A8\u6001\u53C2\u6570\uFF09\u3002','- \u53C2\u6570\u4E0D\u7B26\u5408\u63D2\u4EF6 schema \u65F6\uFF0Cfunction_call \u4F1A\u8FD4\u56DE\u9519\u8BEF\u5E76\u9644\u5B8C\u6574 inputSchema\uFF0C\u8BF7\u4FEE\u6B63\u540E\u91CD\u8BD5\uFF1B\u76EE\u5F55\u63CF\u8FF0\u4E0D\u8DB3\u65F6\u7528 function_call {action:"schema"} \u53D6\u5B8C\u6574\u5B9A\u4E49\u3002',"- \u63D2\u4EF6\u4E8B\u4EF6\u4EE5 [plugin-event] \u5F00\u5934\u7684\u6D88\u606F\u51FA\u73B0\u5728 poll_message \u7ED3\u679C\u4E2D\uFF0C\u6D88\u606F\u5C3E\u90E8\u6709 toolHints\uFF08\u5EFA\u8BAE\u8C03\u7528\u7684\u5DE5\u5177\uFF09\u4E0E payload\uFF08\u4E8B\u4EF6\u6570\u636E\uFF09\uFF0C\u6309\u63D0\u793A\u7528 function_call \u5904\u7406\u3002","- \u63D2\u4EF6\u751F\u547D\u5468\u671F\uFF08\u5B89\u88C5/\u5378\u8F7D/\u91CD\u8F7D/\u542F\u505C/\u5217\u8868\uFF09\u7528 plugin_manage \u5DE5\u5177\uFF1B\u672A\u7ECF\u7528\u6237\u660E\u786E\u8981\u6C42\u4E0D\u8981\u5B89\u88C5\u6216\u5378\u8F7D\u63D2\u4EF6\u3002"].join(`
13
- `)}export{N as buildPluginPrompt,C as createPluginTools,_ as splitQualifiedToolName};
7
+ \u6CE8\u610F\uFF1A\u63D2\u4EF6\u672A\u5B89\u88C5/\u5DF2\u505C\u7528/\u5DE5\u5177\u4E0D\u5B58\u5728\u65F6\u8FD4\u56DE\u660E\u786E\u9519\u8BEF\uFF0C\u4E0D\u8981\u51ED\u7A7A\u7F16\u9020\u5DE5\u5177\u540D\u3002`;function _(o){const t=o.indexOf(".");if(t<=0||t>=o.length-1)return null;const c=o.slice(0,t),a=o.slice(t+1);return!h.test(c)||!a.trim()?null:{plugin:c,tool:a.trim()}}function S(o){const t=o.pluginBridge;return t?[y(t)]:[]}function y(o){return{kind:"builtin",toolName:"function_call",exposedName:"function_call",category:"plugin",description:d,inputSchema:{type:"object",properties:{action:{type:"string",enum:["call","schema","catalog"],default:"call",description:"call=\u8C03\u7528\u63D2\u4EF6\u5DE5\u5177\uFF1Bschema=\u53D6\u5B8C\u6574\u53C2\u6570\u5B9A\u4E49\uFF1Bcatalog=\u53D6\u63D2\u4EF6\u5DE5\u5177\u76EE\u5F55"},tool:{type:"string",description:'\u9650\u5B9A\u540D "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF08\u5982 "wechat-cli.send_msg"\uFF09\uFF1Baction=schema \u65F6\u652F\u6301 "\u63D2\u4EF6\u540D.*" \u53D6\u6574\u7EC4\u5B9A\u4E49'},params:{type:"object",description:"call \u7684\u52A8\u6001\u53C2\u6570\u5BF9\u8C61\uFF0C\u6309\u63D2\u4EF6\u58F0\u660E\u7684 inputSchema \u6821\u9A8C"}},required:["tool"],additionalProperties:!1},async execute(t,c){const a=typeof t.action=="string"?t.action:"call",n=typeof t.tool=="string"?t.tool.trim():"";try{if(a==="catalog")return await o.getCatalog();if(!n)return{error:'\u7F3A\u5C11 tool \u53C2\u6570\uFF08\u9650\u5B9A\u540D "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF09'};if(a==="schema"){if(n.endsWith(".*")){const i=n.slice(0,-2),m=await o.getCatalog(),g=m.plugins.find(s=>s.plugin===i);if(!g)return{error:`\u63D2\u4EF6 ${i} \u672A\u5B89\u88C5\u6216\u5DF2\u505C\u7528`,catalog:m.plugins};const f=await Promise.all(g.tools.map(s=>o.getToolSchema(`${i}.${s.name}`)));return{plugin:i,schemas:f.filter(Boolean)}}const p=await o.getToolSchema(n);return p||{error:`\u672A\u77E5\u63D2\u4EF6\u5DE5\u5177: ${n}\uFF08\u53EF\u5148 action=catalog \u67E5\u770B\u76EE\u5F55\uFF09`}}if(a!=="call")return{error:`\u672A\u77E5 action: ${a}\uFF08\u5141\u8BB8\uFF1Acall / schema / catalog\uFF09`};const e=_(n);if(!e)return{error:`tool \u9650\u5B9A\u540D\u4E0D\u5408\u6CD5: ${n}\uFF08\u5E94\u4E3A "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF0C\u63D2\u4EF6\u540D\u4E3A kebab-case\uFF09`};const u=t.params&&typeof t.params=="object"&&!Array.isArray(t.params)?t.params:{},l=await o.invokeTool(e.plugin,e.tool,u,{toolCallId:c?.toolCallId});if(l.ok)return l.result??{ok:!0};const r={error:l.error??"\u63D2\u4EF6\u5DE5\u5177\u8C03\u7528\u5931\u8D25"};return l.inputSchema!==void 0&&(r.inputSchema=l.inputSchema),typeof l.durationMs=="number"&&(r.durationMs=l.durationMs),r}catch(e){return{error:`function_call \u5931\u8D25: ${e instanceof Error?e.message:String(e)}`}}}}}function C(){return["## \u63D2\u4EF6\u7CFB\u7EDF",'- \u4E09\u65B9\u5DE5\u5177\u4EE5\u63D2\u4EF6\u5F62\u5F0F\u63A5\u5165\u3002\u63D2\u4EF6\u5DE5\u5177\u4E0D\u5728\u4F60\u7684\u9759\u6001\u5DE5\u5177\u5217\u8868\u4E2D\uFF1A\u7D27\u51D1\u76EE\u5F55\u968F poll_message \u7ED3\u679C\u7684 pluginCatalog \u5B57\u6BB5\u8FD4\u56DE\uFF1B\u7528 function_call \u8C03\u7528\uFF08tool="\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF0Cparams \u4E3A\u52A8\u6001\u53C2\u6570\uFF09\u3002','- \u53C2\u6570\u4E0D\u7B26\u5408\u63D2\u4EF6 schema \u65F6\uFF0Cfunction_call \u4F1A\u8FD4\u56DE\u9519\u8BEF\u5E76\u9644\u5B8C\u6574 inputSchema\uFF0C\u8BF7\u4FEE\u6B63\u540E\u91CD\u8BD5\uFF1B\u76EE\u5F55\u63CF\u8FF0\u4E0D\u8DB3\u65F6\u7528 function_call {action:"schema"} \u53D6\u5B8C\u6574\u5B9A\u4E49\u3002',"- \u63D2\u4EF6\u4E8B\u4EF6\u4EE5 [plugin-event] \u5F00\u5934\u7684\u6D88\u606F\u51FA\u73B0\u5728 poll_message \u7ED3\u679C\u4E2D\uFF0C\u6D88\u606F\u5C3E\u90E8\u6709 toolHints\uFF08\u5EFA\u8BAE\u8C03\u7528\u7684\u5DE5\u5177\uFF09\u4E0E payload\uFF08\u4E8B\u4EF6\u6570\u636E\uFF09\uFF0C\u6309\u63D0\u793A\u7528 function_call \u5904\u7406\u3002",'- \u63D2\u4EF6\u751F\u547D\u5468\u671F\uFF08\u5B89\u88C5/\u5378\u8F7D/\u91CD\u8F7D/\u542F\u505C/\u5217\u8868\uFF09\u4E5F\u662F\u63D2\u4EF6\u5DE5\u5177\uFF1A\u7ECF function_call \u8C03\u7528\u5185\u7F6E\u63D2\u4EF6 plugin-manager \u7684 manage \u5DE5\u5177\uFF0C\u5373 function_call {tool:"plugin-manager.manage", params:{action:"...", ...}}\uFF08plugin-manager \u5728 pluginCatalog \u4E2D\u53EF\u67E5\uFF09\u3002\u672A\u7ECF\u7528\u6237\u660E\u786E\u8981\u6C42\u4E0D\u8981\u5B89\u88C5\u6216\u5378\u8F7D\u63D2\u4EF6\u3002\u5F00\u53D1\u63D2\u4EF6\u5148\u7528\u5185\u7F6E /create-plugin \u547D\u4EE4\u83B7\u53D6\u5F00\u53D1\u89C4\u8303\uFF0C\u5199\u5B8C\u63D2\u4EF6\u76EE\u5F55\u540E\u518D\u7528 function_call \u8C03 plugin-manager.manage install \u751F\u6548\u3002'].join(`
8
+ `)}export{C as buildPluginPrompt,S as createPluginTools,_ as splitQualifiedToolName};
14
9