aws-runtime-bridge 1.9.186 → 1.9.192

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 (108) hide show
  1. package/CHANGELOG.md +1878 -1673
  2. package/README.md +256 -256
  3. package/dist/adapter/AcodeSdkAdapter.d.ts +13 -0
  4. package/dist/adapter/AcodeSdkAdapter.js +3 -3
  5. package/dist/browser/browser-pool.d.ts +2 -0
  6. package/dist/browser/browser-pool.js +1 -1
  7. package/dist/config.d.ts +12 -31
  8. package/dist/config.js +2 -2
  9. package/dist/index.js +1 -1
  10. package/dist/remote-desktop/win32-api.js +1 -1
  11. package/dist/routes/background-tasks.js +4 -4
  12. package/dist/routes/dashboard.js +17 -17
  13. package/dist/routes/media-files.d.ts +19 -0
  14. package/dist/routes/media-files.js +2 -0
  15. package/dist/routes/plugin-ui.d.ts +17 -0
  16. package/dist/routes/plugin-ui.js +2 -0
  17. package/dist/routes/plugins.d.ts +3 -0
  18. package/dist/routes/plugins.js +1 -1
  19. package/dist/routes/terminal.d.ts +83 -0
  20. package/dist/routes/terminal.js +23 -23
  21. package/dist/scripts/migrate-user-scopes.js +1 -1
  22. package/dist/services/acode-bg-manager.js +1 -1
  23. package/dist/services/agent-capability-sync.js +1 -1
  24. package/dist/services/auto-register.js +1 -1
  25. package/dist/services/capability-config.d.ts +0 -1
  26. package/dist/services/capability-config.js +2 -2
  27. package/dist/services/instance-ai-config-service.js +1 -1
  28. package/dist/services/instance-features.d.ts +9 -0
  29. package/dist/services/instance-features.js +1 -1
  30. package/dist/services/panel-auth.d.ts +4 -0
  31. package/dist/services/panel-auth.js +1 -1
  32. package/dist/services/plugin-deployment.d.ts +2 -30
  33. package/dist/services/plugin-deployment.js +2 -2
  34. package/dist/services/plugin-handler-adapter.d.ts +10 -1
  35. package/dist/services/plugin-handler-adapter.js +2 -2
  36. package/dist/services/plugin-listener-runner.js +4 -4
  37. package/dist/services/plugin-loader.d.ts +7 -1
  38. package/dist/services/plugin-loader.js +1 -1
  39. package/dist/services/plugin-manager.d.ts +32 -12
  40. package/dist/services/plugin-manager.js +4 -4
  41. package/dist/services/plugin-manifest.d.ts +53 -3
  42. package/dist/services/plugin-manifest.js +1 -1
  43. package/dist/services/plugin-runtime.d.ts +8 -9
  44. package/dist/services/plugin-ui-status-runtime.d.ts +8 -0
  45. package/dist/services/plugin-ui-status-runtime.js +2 -0
  46. package/dist/services/plugin-ui-status.d.ts +96 -0
  47. package/dist/services/plugin-ui-status.js +2 -0
  48. package/dist/services/plugin-wecom-callback.d.ts +61 -0
  49. package/dist/services/plugin-wecom-callback.js +3 -0
  50. package/dist/services/user-scope.d.ts +1 -9
  51. package/dist/services/user-scope.js +1 -1
  52. package/dist/services/workspace-files.js +1 -1
  53. package/dist/utils/dynamic-import.d.ts +31 -0
  54. package/dist/utils/dynamic-import.js +2 -0
  55. package/dist/utils/sdk-package-loader.js +1 -1
  56. package/node_modules/playwright/cli.js +0 -0
  57. package/node_modules/playwright-core/bin/reinstall_chrome_beta_linux.sh +0 -0
  58. package/node_modules/playwright-core/bin/reinstall_chrome_beta_mac.sh +0 -0
  59. package/node_modules/playwright-core/bin/reinstall_chrome_stable_linux.sh +0 -0
  60. package/node_modules/playwright-core/bin/reinstall_chrome_stable_mac.sh +0 -0
  61. package/node_modules/playwright-core/bin/reinstall_msedge_beta_linux.sh +0 -0
  62. package/node_modules/playwright-core/bin/reinstall_msedge_beta_mac.sh +0 -0
  63. package/node_modules/playwright-core/bin/reinstall_msedge_dev_linux.sh +0 -0
  64. package/node_modules/playwright-core/bin/reinstall_msedge_dev_mac.sh +0 -0
  65. package/node_modules/playwright-core/bin/reinstall_msedge_stable_linux.sh +0 -0
  66. package/node_modules/playwright-core/bin/reinstall_msedge_stable_mac.sh +0 -0
  67. package/node_modules/playwright-core/cli.js +0 -0
  68. package/node_modules/playwright-core/lib/webp_codec.wasm +0 -0
  69. package/node_modules/playwright-core/lib/xdg-open +0 -0
  70. package/package/acode/dist/await-complete-tool.js +3 -3
  71. package/package/acode/dist/plugin-types.d.ts +41 -1
  72. package/package/acode/dist/runtime.d.ts +26 -0
  73. package/package/acode/dist/runtime.js +21 -22
  74. package/package/acode/dist/sub-agent-manager.d.ts +33 -0
  75. package/package/acode/dist/sub-agent-manager.js +9 -1
  76. package/package/acode/dist/sub-agent-tools.d.ts +4 -0
  77. package/package/acode/dist/sub-agent-tools.js +27 -12
  78. package/package/acode/dist/subagent-handback.d.ts +16 -0
  79. package/package/acode/dist/subagent-handback.js +7 -0
  80. package/package/acode/dist/tool-allocation.js +1 -1
  81. package/package/acode/package.json +38 -38
  82. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +10 -5
  83. package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
  84. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +27 -0
  85. package/package/aws-client-agent-mcp/dist/mcp-server.js +16 -16
  86. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +34 -0
  87. package/package/aws-client-agent-mcp/dist/mcp-tools.js +65 -19
  88. package/package/aws-client-agent-mcp/dist/message-buffer.d.ts +10 -0
  89. package/package/aws-client-agent-mcp/dist/message-buffer.js +1 -1
  90. package/package/aws-client-agent-mcp/dist/tool-groups.js +2 -2
  91. package/package/aws-client-agent-mcp/dist/types.d.ts +81 -3
  92. package/package/aws-client-agent-mcp/package.json +53 -53
  93. package/package.json +134 -132
  94. /package/package/acode/dist/grammars/{grammars/tree-sitter-bash.wasm → tree-sitter-bash.wasm} +0 -0
  95. /package/package/acode/dist/grammars/{grammars/tree-sitter-c-sharp.wasm → tree-sitter-c-sharp.wasm} +0 -0
  96. /package/package/acode/dist/grammars/{grammars/tree-sitter-c.wasm → tree-sitter-c.wasm} +0 -0
  97. /package/package/acode/dist/grammars/{grammars/tree-sitter-cpp.wasm → tree-sitter-cpp.wasm} +0 -0
  98. /package/package/acode/dist/grammars/{grammars/tree-sitter-go.wasm → tree-sitter-go.wasm} +0 -0
  99. /package/package/acode/dist/grammars/{grammars/tree-sitter-java.wasm → tree-sitter-java.wasm} +0 -0
  100. /package/package/acode/dist/grammars/{grammars/tree-sitter-javascript.wasm → tree-sitter-javascript.wasm} +0 -0
  101. /package/package/acode/dist/grammars/{grammars/tree-sitter-jsx.wasm → tree-sitter-jsx.wasm} +0 -0
  102. /package/package/acode/dist/grammars/{grammars/tree-sitter-lua.wasm → tree-sitter-lua.wasm} +0 -0
  103. /package/package/acode/dist/grammars/{grammars/tree-sitter-php.wasm → tree-sitter-php.wasm} +0 -0
  104. /package/package/acode/dist/grammars/{grammars/tree-sitter-python.wasm → tree-sitter-python.wasm} +0 -0
  105. /package/package/acode/dist/grammars/{grammars/tree-sitter-ruby.wasm → tree-sitter-ruby.wasm} +0 -0
  106. /package/package/acode/dist/grammars/{grammars/tree-sitter-rust.wasm → tree-sitter-rust.wasm} +0 -0
  107. /package/package/acode/dist/grammars/{grammars/tree-sitter-tsx.wasm → tree-sitter-tsx.wasm} +0 -0
  108. /package/package/acode/dist/grammars/{grammars/tree-sitter-typescript.wasm → tree-sitter-typescript.wasm} +0 -0
@@ -1,2 +1,2 @@
1
- import{randomBytes as ce}from"node:crypto";import p from"node:fs";import w from"node:os";import $ from"axios";import{v4 as ue}from"uuid";import{getActiveBridgeHttpPort as de,getAutoRegisterConfigFilePath as T,isDesktopAppMode as le,schedulerBaseUrl as m}from"../config.js";import{runExclusiveConfigWrite as D}from"../utils/config-write-queue.js";import{logger as a}from"../utils/logger.js";import{buildTargetKey as x,fingerprintUserKey as fe,serverUrlOfTargetKey as F}from"../utils/target-identity.js";import{clearRuntimeBinding as ge,clearScopedRuntimeAccessToken as me,getRuntimeAccessToken as G,getRuntimeBindingPublicState as pe,getScopedRuntimeAccessToken as Y,listScopedRuntimeAccessTokens as ye,loadRuntimeBinding as M,normalizeSchedulerBaseUrl as S,saveRuntimeBinding as H,saveScopedRuntimeAccessToken as V}from"./runtime-binding.js";const X={enabled:!1,serverUrl:m,preferSameLanIp:!0,maxRetries:3,retryInterval:2e3},d={registered:!1,registrations:{}};let k=[];const Ie=10*60*1e3,B=new Map;function Q(){const e=Date.now();for(const[r,t]of B)t.expiresAt<=e&&B.delete(r)}function Je(){Q();const e=[...k];for(const r of B.values())r.key&&!e.includes(r.key)&&e.push(r.key);return e}function qe(e){const r=String(e||"").trim();if(!r)return[];const t=h(),n=t.filter(i=>String(i.connectionKey||"").trim()===r);if(n.length>0)return n;Q();const o=new Set;for(const[i,s]of B)s.key===r&&o.add(i);return o.size===0?[]:t.filter(i=>o.has(N(i)))}function Ye(){return k[0]??""}const Ae=3e4;function Z(){const e=Number(process.env.AWS_REGISTER_BACKGROUND_RETRY_INTERVAL);return Number.isFinite(e)&&e>0?e:Ae}const C=new Map;function ee(e){const r=e.serverUrl||m,t=N(e)||r;if(C.has(t))return;const n=setTimeout(()=>{C.delete(t),Re(e,t)},Z());n.unref?.(),C.set(t,n)}async function Re(e,r){try{const t=h().find(n=>N(n)===r)||e;await q(t,{backgroundRetry:!0})}catch(t){a.warn(`[AutoRegister] \u540E\u53F0\u91CD\u8BD5\u6CE8\u518C\u5F02\u5E38: ${t.message}`),ee(e)}}function He(){for(const e of C.values())clearTimeout(e);C.clear()}function Te(e){const r=e.trim();if(r.length<8)return r;for(let t=1;t<=r.length/2;t++){if(r.length%t!==0)continue;const n=r.slice(0,t);let o=!0;for(let i=t;i<r.length;i+=t)if(r.slice(i,i+t)!==n){o=!1;break}if(o&&n.length<r.length)return n}return r}function Se(e){const r=g(e);if(!r)return r;const t=Te(r);return t!==r&&a.warn(`[AutoRegister] userKey \u7591\u4F3C\u88AB\u590D\u5236\u4E86\u4E24\u904D\uFF08\u957F\u5EA6 ${r.length} \u2192 ${t.length}\uFF09\uFF0C\u5DF2\u81EA\u52A8\u53BB\u91CD\u3002\u8BF7\u68C0\u67E5\u914D\u7F6E\u6587\u4EF6\u662F\u5426\u91CD\u590D\u7C98\u8D34\u3002`),t}function g(e){return e==null?void 0:String(e).trim()||void 0}function _(e){return S(e)}function re(e){return Array.isArray(e.autoRegisterTargets)?e.autoRegisterTargets.filter(r=>!!(r&&typeof r=="object"&&!Array.isArray(r))):[]}function N(e){const r=e?.serverUrl||m;return x(r,e?.credentialId||e?.userKey)}function y(e){return e?.credentialId||e?.userKey}function P(e){if(typeof e=="boolean")return e;if(typeof e=="string"){const r=e.trim().toLowerCase();if(["true","1","yes","y"].includes(r))return!0;if(["false","0","no","n"].includes(r))return!1}}function te(e){if(e==null||e==="")return;const r=Number(e);return Number.isFinite(r)?r:void 0}function O(e){const r=g(e.serverUrl)||g(e.schedulerBaseUrl),t=g(e.connectionKey)||g(e.password);return{enabled:P(e.enabled),serverUrl:r,tenantId:g(e.tenantId),userId:g(e.userId),userKey:Se(e.userKey),machineToken:g(e.machineToken),connectionKey:t,instanceName:g(e.instanceName),instanceId:g(e.instanceId),credentialId:g(e.credentialId),credentialRef:g(e.credentialRef),credentialType:g(e.credentialType),projectId:g(e.projectId),roleName:g(e.roleName),workspacePath:g(e.workspacePath),registerAddr:g(e.registerAddr),registerIp:g(e.registerIp),virtualIp:g(e.virtualIp),tunnel:P(e.tunnel),preferSameLanIp:P(e.preferSameLanIp),maxRetries:te(e.maxRetries),retryInterval:te(e.retryInterval)}}function ne(){const e=T();try{if(!p.existsSync(e))return a.debug(`[AutoRegister] \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728: ${e}`),null;const r=p.readFileSync(e,"utf-8"),t=JSON.parse(r);return a.info(`[AutoRegister] \u4ECE\u914D\u7F6E\u6587\u4EF6\u52A0\u8F7D\u914D\u7F6E: ${e}`),O(t)}catch(r){const t=r;return a.warn(`[AutoRegister] \u8BFB\u53D6\u914D\u7F6E\u6587\u4EF6\u5931\u8D25: ${e}, error: ${t.message}`),null}}function he(){const e=T();try{if(!p.existsSync(e))return[];const r=p.readFileSync(e,"utf-8"),t=JSON.parse(r),n=O(t),o=Array.isArray(t.autoRegisterTargets)?t.autoRegisterTargets:[];return o.length===0?n.userKey||n.machineToken?[n]:[]:o.filter(i=>!!(i&&typeof i=="object"&&!Array.isArray(i))).map(i=>{const s=O(i);return{...n,...s,machineToken:s.machineToken||(s.userKey?void 0:n.machineToken),connectionKey:s.connectionKey}})}catch(r){const t=r;return a.warn(`[AutoRegister] \u8BFB\u53D6\u81EA\u52A8\u6CE8\u518C\u76EE\u6807\u5931\u8D25: ${e}, error: ${t.message}`),[]}}function Ve(){const e=T();if(!p.existsSync(e))return[];let r;try{r=JSON.parse(p.readFileSync(e,"utf-8"))}catch(s){return a.warn(`[AutoRegister] \u8BFB\u53D6 config.json \u5931\u8D25\uFF08targets \u6458\u8981\uFF09: ${s.message}`),[]}const t=O(r),n=Array.isArray(r.autoRegisterTargets)?r.autoRegisterTargets:[],o=n.length>0?n.filter(s=>!!(s&&typeof s=="object"&&!Array.isArray(s))).map(s=>{const c=O(s);return{...t,...c,machineToken:c.machineToken||(c.userKey?void 0:t.machineToken),connectionKey:c.connectionKey}}):t.userKey||t.machineToken?[t]:[],i=s=>{const c=String(s||"").trim();return c?c.length<=8?"****":`${c.slice(0,8)}****${c.slice(-4)}`:""};return o.map((s,c)=>({index:c,serverUrl:s.serverUrl||"",instanceName:s.instanceName||"",registerAddr:s.registerAddr||s.registerIp||s.virtualIp||"",tunnel:typeof s.tunnel=="boolean"?s.tunnel:null,userKeyMasked:i(s.userKey),machineTokenSet:!!String(s.machineToken||"").trim(),credentialType:s.credentialType||"",credentialId:s.credentialId||"",credentialRef:s.credentialRef||"",connectionKeySet:!!String(s.connectionKey||"").trim()}))}function se(){const e={};return process.env.AWS_AUTO_REGISTER==="true"&&(e.enabled=!0),process.env.AWS_RUNTIME_SCHEDULER_BASE_URL&&(e.serverUrl=process.env.AWS_RUNTIME_SCHEDULER_BASE_URL),process.env.AWS_TENANT_ID&&(e.tenantId=process.env.AWS_TENANT_ID),process.env.AWS_USER_KEY&&(e.userKey=process.env.AWS_USER_KEY),process.env.AWS_BRIDGE_MACHINE_TOKEN&&(e.machineToken=process.env.AWS_BRIDGE_MACHINE_TOKEN),process.env.AWS_BRIDGE_CONNECTION_KEY&&(e.connectionKey=process.env.AWS_BRIDGE_CONNECTION_KEY),process.env.AWS_INSTANCE_NAME&&(e.instanceName=process.env.AWS_INSTANCE_NAME),process.env.AWS_PROJECT_NAME&&(e.projectId=process.env.AWS_PROJECT_NAME),process.env.AWS_ROLE_NAME&&(e.roleName=process.env.AWS_ROLE_NAME),process.env.AWS_WORKSPACE_PATH&&(e.workspacePath=process.env.AWS_WORKSPACE_PATH),process.env.AWS_REGISTER_ADDR&&(e.registerAddr=process.env.AWS_REGISTER_ADDR),process.env.AWS_REGISTER_IP&&(e.registerIp=process.env.AWS_REGISTER_IP),process.env.AWS_VIRTUAL_IP&&(e.virtualIp=process.env.AWS_VIRTUAL_IP),process.env.AWS_PREFER_SAME_LAN_IP&&(e.preferSameLanIp=P(process.env.AWS_PREFER_SAME_LAN_IP)??!0),process.env.AWS_REGISTER_MAX_RETRIES&&(e.maxRetries=parseInt(process.env.AWS_REGISTER_MAX_RETRIES,10)),process.env.AWS_REGISTER_RETRY_INTERVAL&&(e.retryInterval=parseInt(process.env.AWS_REGISTER_RETRY_INTERVAL,10)),e}function W(){const e=ne(),r=se(),t={...X,...e||{},...r},n=t.instanceName||w.hostname();let o=!1;return process.env.AWS_AUTO_REGISTER!==void 0?o=process.env.AWS_AUTO_REGISTER==="true":e&&(o=!0),{enabled:o,serverUrl:t.serverUrl||m,tenantId:t.tenantId||"",userKey:t.userKey||"",machineToken:t.machineToken,connectionKey:t.connectionKey,instanceName:n,instanceId:t.instanceId,credentialId:t.credentialId,credentialRef:t.credentialRef,credentialType:t.credentialType,projectId:t.projectId,roleName:t.roleName,workspacePath:t.workspacePath,registerAddr:t.registerAddr,registerIp:t.registerIp,virtualIp:t.virtualIp,tunnel:typeof t.tunnel=="boolean"?t.tunnel:void 0,preferSameLanIp:t.preferSameLanIp!==!1,maxRetries:t.maxRetries,retryInterval:t.retryInterval}}function h(){const e=he(),r=se(),n=(e.length>0?e:[ne()||{}]).map(o=>{const i={...X,...o,...r};let s=!1;return process.env.AWS_AUTO_REGISTER!==void 0?s=process.env.AWS_AUTO_REGISTER==="true":s=e.length>0||!!(i.userKey||i.machineToken),{enabled:s,serverUrl:i.serverUrl||m,tenantId:i.tenantId||"",userId:i.userId,userKey:i.userKey||"",machineToken:i.machineToken,connectionKey:i.connectionKey,instanceName:i.instanceName||w.hostname(),instanceId:i.instanceId,credentialId:i.credentialId,credentialRef:i.credentialRef,credentialType:i.credentialType,projectId:i.projectId,roleName:i.roleName,workspacePath:i.workspacePath,registerAddr:i.registerAddr,registerIp:i.registerIp,virtualIp:i.virtualIp,tunnel:typeof i.tunnel=="boolean"?i.tunnel:void 0,preferSameLanIp:i.preferSameLanIp!==!1,maxRetries:i.maxRetries,retryInterval:i.retryInterval}});return k=n.map(o=>o.connectionKey).filter(o=>!!(o&&o.trim())),n}function ve(){const e=w.networkInterfaces(),r=[];for(const t of Object.keys(e)){const n=e[t];if(n)for(const o of n)o.family==="IPv4"&&!o.internal&&r.push({address:o.address,netmask:o.netmask,name:t})}return r}function z(e){const r=e.split(".").map(Number);return(r[0]<<24)+(r[1]<<16)+(r[2]<<8)+r[3]}function Ke(e,r,t){const n=z(e),o=z(r),i=z(t);return(n&i)===(o&i)}function Ue(e){try{const r=new URL(e);return r.hostname==="localhost"||r.hostname==="127.0.0.1"?"127.0.0.1":/^(\d{1,3}\.){3}\d{1,3}$/.test(r.hostname)?r.hostname:null}catch{return null}}function ke(e){return e==="127.0.0.1"}function _e(e){const r=ve();if(r.length===0)return a.warn("[AutoRegister] \u672A\u627E\u5230\u4EFB\u4F55\u975E\u5185\u90E8 IP \u5730\u5740\uFF0C\u4F7F\u7528 127.0.0.1"),"127.0.0.1";const t=Ue(e);if(t){if(ke(t))return"127.0.0.1";for(const n of r)if(Ke(n.address,t,n.netmask))return a.info(`[AutoRegister] \u627E\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u540C\u5B50\u7F51\u7684 IP: ${n.address} (\u7F51\u5361: ${n.name}, \u5B50\u7F51\u63A9\u7801: ${n.netmask})`),n.address;a.warn(`[AutoRegister] \u672A\u627E\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3 (${t}) \u540C\u5B50\u7F51\u7684\u672C\u673A IP\uFF0C\u4F7F\u7528 127.0.0.1`)}else a.warn("[AutoRegister] \u65E0\u6CD5\u89E3\u6790\u8C03\u5EA6\u4E2D\u5FC3 IP\uFF0C\u4F7F\u7528 127.0.0.1");return"127.0.0.1"}function Ee(e=m){return _e(e)}function ie(e){const r=e||W();return!r.enabled||!r.userKey&&!r.machineToken?!1:r.tunnel===!0?!0:r.tunnel===!1?!1:!r.registerAddr&&!r.registerIp&&!r.virtualIp}function L(e){const r=de();if(ie(e)){const i=e.serverUrl||m;try{const s=new URL(i);if(!e.instanceId)a.warn("[AutoRegister] \u96A7\u9053\u6A21\u5F0F\u4F46\u7F3A\u5C11 instanceId\uFF0C\u964D\u7EA7\u4E3A\u76F4\u8FDE\u6A21\u5F0F");else return`${s.protocol}//${s.host}/tunnel/${e.instanceId}`}catch{a.warn("[AutoRegister] serverUrl \u89E3\u6790\u5931\u8D25\uFF0C\u964D\u7EA7\u4E3A\u76F4\u8FDE\u6A21\u5F0F")}}const t=le()||e.preferSameLanIp===!1?"127.0.0.1":Ee(e.serverUrl||m),n=e.registerAddr||e.registerIp||e.virtualIp||t;return n?/^https?:\/\//i.test(n)?n:/:[0-9]+$/.test(n)?`http://${n}`:`http://${n}:${r}`:`http://127.0.0.1:${r}`}function b(){return h()[0]||W()}function Xe(e){return Ne(e)?.serverUrl}function Ne(e){const r=String(e||"").trim();if(!r)return;for(const n of h()){if(!n?.serverUrl)continue;const o=Y(n.serverUrl,y(n));if(o&&o===r)return{serverUrl:S(n.serverUrl)||n.serverUrl,userKey:n.userKey,identityKey:y(n),instanceId:n.instanceId};const i=ye(n.serverUrl);for(const s of i){if(s.accessToken!==r)continue;const c=fe(n.userKey)===s.userKeyFingerprint?n.userKey:void 0;return{serverUrl:S(n.serverUrl)||n.serverUrl,userKey:c,identityKey:c}}}const t=M();if(t.schedulerBaseUrl){const n=Y(t.schedulerBaseUrl);if(n&&n===r)return{serverUrl:S(t.schedulerBaseUrl)||t.schedulerBaseUrl}}}function we(e){if(!e)return;const r=Object.entries(d.registrations).find(([,t])=>t===e);return r?F(r[0]):void 0}function $e(e,r){const t=S(e);if(!t)return;if(String(r||"").trim()){const o=d.registrations[x(t,r)];return o||void 0}const n=Object.entries(d.registrations).filter(([o])=>F(o)===t);return n.length===1?n[0][1]:void 0}function j(e,r){const t=we(r);if(t)return t;const n=g(e.serverUrl);if(n&&(n!==m||process.env.AWS_RUNTIME_SCHEDULER_BASE_URL))return n;const o=M(),i=g(o.schedulerBaseUrl);return o.status==="paired"&&i?i:n||m}async function Be(e){const r=e.instanceName||w.hostname(),t=e.serverUrl||m,n={tenantId:e.tenantId,userKey:e.machineToken?void 0:e.userKey,machineToken:e.machineToken,instanceId:e.instanceId,instanceName:r,hostname:w.hostname(),virtualIp:e.registerAddr||e.registerIp||e.virtualIp,runtimeBridgeBaseUrl:L(e),connectionKey:e.connectionKey,workspacePath:e.workspacePath,projectId:e.projectId,roleName:e.roleName};return a.info(`[AutoRegister] \u6B63\u5728\u6CE8\u518C\u5B9E\u4F8B: ${r}`),a.info(`[AutoRegister] \u8C03\u5EA6\u4E2D\u5FC3: ${t}`),a.info(e.machineToken?"[AutoRegister] \u51ED\u636E: \u673A\u5668\u81EA\u6301\u51ED\u636E\uFF08machineToken\uFF09":`[AutoRegister] \u7528\u6237 Key: ${e.userKey?"****"+e.userKey.slice(-4):"(\u672A\u8BBE\u7F6E)"}`),a.info(`[AutoRegister] \u79DF\u6237 ID: ${e.tenantId||"(\u81EA\u52A8\u63A8\u5BFC)"}`),(await $.post(`${t}/api/instances/register`,n,{headers:{"Content-Type":"application/json"},timeout:1e4})).data}function Ce(e,r,t,n,o,i,s,c,u){const l=T();return D(l,()=>{if(!p.existsSync(l))return;const I=p.readFileSync(l,"utf-8"),v=JSON.parse(I),U=S(e);if(!U)return;let A=!1;const R=f=>S(String(f.serverUrl||f.schedulerBaseUrl||""))!==U?!1:String(t||"").trim()?String(f.userKey??"").trim()===String(t).trim():String(s||"").trim()?String(f.machineToken??"").trim()===String(s).trim():!0,K=f=>{R(f)&&(r&&f.instanceId!==r&&(f.instanceId=r,A=!0),n&&f.credentialId!==n&&(f.credentialId=n,A=!0),o&&f.credentialRef!==o&&(f.credentialRef=o,A=!0),i&&f.credentialType!==i&&(f.credentialType=i,A=!0),c&&f.tenantId!==c&&(f.tenantId=c,A=!0),u&&f.userId!==u&&(f.userId=u,A=!0))};if(Array.isArray(v.autoRegisterTargets))for(const f of v.autoRegisterTargets)f&&typeof f=="object"&&!Array.isArray(f)&&K(f);else K(v);A&&(p.writeFileSync(l,JSON.stringify(v,null,2),"utf-8"),a.info(`[AutoRegister] \u5DF2\u56DE\u5199 instanceId \u5230 config.json (serverUrl=${e}${t?`, userKey=****${String(t).slice(-4)}`:""})`))})}async function Oe(e,r){const t=String(r||"").trim();if(!t)return;const n=y(e),o=_(e.serverUrl);if(!n||!o)return;const i=T();try{await D(i,()=>{if(!p.existsSync(i))return;const s=p.readFileSync(i,"utf-8"),c=JSON.parse(s),l=re(c).find(I=>_(I.serverUrl||I.schedulerBaseUrl)===o&&String(I.credentialId||I.userKey||"").trim()===n);if(!l){a.warn(`[AutoRegister] \u65E0\u6CD5\u5B9A\u4F4D connectionKey \u5BF9\u5E94 target\uFF0C\u8DF3\u8FC7\u5199\u76D8: server=${o}`);return}String(l.connectionKey??"").trim()!==t&&(l.connectionKey=t,p.writeFileSync(i,JSON.stringify(c,null,2),"utf-8"),a.info(`[AutoRegister] \u5DF2\u5199\u5165 target connectionKey \u5230 config.json: ${i}`))})}catch(s){a.warn(`[AutoRegister] \u5199\u5165 target connectionKey \u5230 config.json \u5931\u8D25: ${s.message}`)}}async function Qe(e,r){const t=String(e||"").trim();if(!t)throw new Error("connectionKey is required");const n=_(r?.serverUrl);if(!n)throw new Error("serverUrl is required to rotate a target connectionKey");const o=T();let i;const s=await D(o,()=>{if(!p.existsSync(o))return!1;const l=JSON.parse(p.readFileSync(o,"utf-8")),I=re(l),v=String(r?.instanceId||"").trim(),U=String(r?.credentialId||"").trim(),A=I.filter(K=>{if(_(K.serverUrl||K.schedulerBaseUrl)!==n)return!1;if(v&&String(K.instanceId||"").trim()===v)return!0;if(U){const E=String(K.credentialId||"").trim(),ae=String(K.userKey||"").trim();if(E===U||ae===U)return!0}return!v&&!U&&I.filter(E=>_(E.serverUrl||E.schedulerBaseUrl)===n).length===1});if(A.length!==1)throw new Error(`\u65E0\u6CD5\u552F\u4E00\u5B9A\u4F4D connectionKey \u5BF9\u5E94 target\uFF08server=${n}, matches=${A.length}\uFF09`);const R=A[0];return String(R.connectionKey??"").trim()===t?!1:(i={targetKey:x(String(R.serverUrl??R.schedulerBaseUrl??""),R.credentialId||R.userKey),previousConnectionKey:String(R.connectionKey??"").trim()},R.connectionKey=t,String(l.connectionKey??"").trim()&&delete l.connectionKey,p.writeFileSync(o,JSON.stringify(l,null,2),"utf-8"),a.info(`[AutoRegister] \u5DF2\u8F6E\u6362 target connectionKey \u5E76\u5199\u56DE config.json: ${o}`),!0)}),c=!!process.env.AWS_BRIDGE_CONNECTION_KEY;c&&s&&(process.env.AWS_BRIDGE_CONNECTION_KEY=t,a.warn("[AutoRegister] \u68C0\u6D4B\u5230 AWS_BRIDGE_CONNECTION_KEY \u73AF\u5883\u53D8\u91CF\uFF0C\u5DF2\u540C\u6B65\u66F4\u65B0\u5F53\u524D\u8FDB\u7A0B\uFF1B\u91CD\u542F bridge \u540E\u4F1A\u56DE\u5230\u73AF\u5883\u53D8\u91CF\u4E2D\u7684\u65E7\u503C\uFF0C\u8BF7\u4E00\u5E76\u4FEE\u6539\u90E8\u7F72\u914D\u7F6E"));const u=h().map(l=>String(l.connectionKey||"").trim()).filter(l=>l.length>0);return k=s?[...new Set([t,...u])]:[...new Set(u)],s&&i&&i.previousConnectionKey!==t&&B.set(i.targetKey,{key:i.previousConnectionKey,expiresAt:Date.now()+Ie}),{envOverrideWarning:c,rotated:s}}async function oe(e){let r=0;for(const t of e)String(t.connectionKey||"").trim()||(t.connectionKey=`awsb_${ce(24).toString("base64url")}`,r+=1,k.includes(t.connectionKey)||(k=[...k,t.connectionKey]),await Oe(t,t.connectionKey));r!==0&&a.info(`[AutoRegister] ${r} \u4E2A\u76EE\u6807\u7F3A\u5C11 connectionKey\uFF0C\u5DF2\u6309 target \u72EC\u7ACB\u751F\u6210\u5E76\u5199\u5165 config.json`)}function J(e){if(!e)return;const r=Object.entries(d.registrations).find(([,i])=>i===e);if(!r)return;const t=r[0],n=F(t),o=h().find(i=>N(i)===t);return{serverUrl:n,identityKey:o?y(o):void 0,targetKey:t}}async function be(e){const r=J(e),t=r?.serverUrl||j(b(),e),n=G(t,r?.identityKey);if(!n)throw new Error("runtimeAccessToken is required to unregister bridge instance");return(await $.post(`${t}/api/instances/unregister`,{instanceId:e},{headers:{"Content-Type":"application/json","X-Runtime-Token":n},timeout:1e4})).data}async function Ze(e){const r=e?[{...W(),...e}]:h();await oe(r);const n=(r.length>1?await Promise.all(r.map(i=>q(i))):[await q(r[0]||W())]).every(Boolean),o=r.every(i=>!i.enabled||!i.userKey&&!i.machineToken);if(!e&&(n||o)){const{stopTunnelClientsExcept:i}=await import("./tunnel-client.js");i(r.filter(s=>!!s.serverUrl).map(s=>x(s.serverUrl,y(s))))}return n}async function q(e,r){if(!e.enabled)return a.info("[AutoRegister] \u81EA\u52A8\u6CE8\u518C\u672A\u542F\u7528"),a.info(`[AutoRegister] \u8981\u542F\u7528\u81EA\u52A8\u6CE8\u518C\uFF0C\u8BF7\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6 ${T()} \u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF AWS_AUTO_REGISTER=true`),!1;if(!e.userKey&&!e.machineToken)return a.error("[AutoRegister] \u7F3A\u5C11\u6CE8\u518C\u51ED\u636E\uFF08\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u8BBE\u7F6E userKey \u6216 machineToken\uFF0C\u4E5F\u53EF\u7528 `awsb pair --ticket ...` \u914D\u5BF9\uFF09"),!1;String(e.connectionKey||"").trim()||await oe([e]);const t=ie(e);t&&!e.instanceId&&(e.instanceId=`bridge-${ue().replace(/-/g,"").slice(0,12)}`,a.info(`[AutoRegister] \u96A7\u9053\u6A21\u5F0F\uFF1A\u5DF2\u9884\u58F0\u660E instanceId=${e.instanceId}`));const n=r?.backgroundRetry?1:e.maxRetries??3,o=e.retryInterval??2e3;for(let i=1;i<=n;i++){try{d.lastAttempt=new Date;const s=await Be(e);if(s.success){if(d.registered=!0,d.instanceId=s.instanceId,s.credentialId&&(e.credentialId=s.credentialId,e.credentialType=s.credentialType),e.credentialRef=s.credentialRef,s.tenantId&&(e.tenantId=s.tenantId),s.userId&&(e.userId=s.userId),s.instanceId&&(d.registrations[N(e)]=s.instanceId,e.instanceId=s.instanceId),d.error=void 0,a.info("[AutoRegister] \u2713 \u6CE8\u518C\u6210\u529F\uFF01"),a.info(`[AutoRegister] \u5B9E\u4F8B ID: ${s.instanceId}`),a.info(`[AutoRegister] \u6D88\u606F: ${s.message}`),a.info(`[AutoRegister] \u66F4\u65B0: ${s.isUpdate?"\u662F":"\u5426"}`),s.runtimeAccessToken)try{const c=e.serverUrl||m;H({accessToken:s.runtimeAccessToken,instanceId:s.instanceId,userId:s.userId,schedulerBaseUrl:c,userKey:y(e)});const u=S(s.serverUrl);u&&u!==S(c)&&(V({serverBaseUrl:u,accessToken:s.runtimeAccessToken,userKey:y(e)}),a.info(`[AutoRegister] \u68C0\u6D4B\u5230 server \u4E0B\u53D1\u5730\u5740(${u})\u4E0E\u8FDE\u63A5\u5730\u5740(${c})\u4E0D\u540C\uFF0C\u5DF2\u6309\u4E24\u4E2A\u5730\u5740\u5206\u522B\u4FDD\u5B58 scoped token`)),a.info("[AutoRegister] \u5DF2\u4FDD\u5B58\u8C03\u5EA6\u4E2D\u5FC3\u4E0B\u53D1\u7684 runtime access token"),s.instanceId&&Ce(e.serverUrl||m,s.instanceId,e.userKey,s.credentialId,s.credentialRef,s.credentialType,e.machineToken,s.tenantId,s.userId).catch(l=>{a.warn(`[AutoRegister] \u56DE\u5199 instanceId \u5230 config.json \u5931\u8D25: ${l.message}`)})}catch(c){const u=c;return a.error(`[AutoRegister] \u4FDD\u5B58 runtime access token \u5931\u8D25: ${u.message}`),d.error=u.message,!1}else a.warn("[AutoRegister] \u6CE8\u518C\u54CD\u5E94\u672A\u5305\u542B runtime access token\uFF0CMCP \u5C06\u65E0\u6CD5\u8BBF\u95EE\u8C03\u5EA6\u4E2D\u5FC3\uFF0C\u8BF7\u68C0\u67E5 server \u7684 bridge \u5B9E\u4F8B token \u9881\u53D1\u903B\u8F91");if(t&&s.instanceId&&s.runtimeAccessToken){const{startTunnelClient:c}=await import("./tunnel-client.js"),u=e.serverUrl||m;c(u,s.instanceId,y(e)),a.info(`[AutoRegister] \u96A7\u9053\u5BA2\u6237\u7AEF\u5DF2\u542F\u52A8: server=${u}, instanceId=${s.instanceId}${e.userKey?`, userKey=****${e.userKey.slice(-4)}`:""}`)}return!0}else a.warn(`[AutoRegister] \u6CE8\u518C\u5931\u8D25: ${s.message}`),d.error=s.message}catch(s){const c=s,u=c.response?.data?JSON.stringify(c.response.data):c.message;a.error(`[AutoRegister] \u6CE8\u518C\u8BF7\u6C42\u5931\u8D25 (\u5C1D\u8BD5 ${i}/${n}): ${u}`),d.error=u}i<n&&(a.info(`[AutoRegister] ${o/1e3} \u79D2\u540E\u91CD\u8BD5...`),await new Promise(s=>setTimeout(s,o)))}return r?.backgroundRetry?a.warn(`[AutoRegister] \u540E\u53F0\u91CD\u8BD5\u6CE8\u518C\u4ECD\u672A\u6210\u529F (server=${e.serverUrl||m}): ${d.error||"\u672A\u77E5"}`):(a.error("[AutoRegister] \u2717 \u6CE8\u518C\u5931\u8D25\uFF0C\u5DF2\u8FBE\u6700\u5927\u91CD\u8BD5\u6B21\u6570"),a.error("[AutoRegister] ========================================"),a.error("[AutoRegister] \u81EA\u52A8\u6CE8\u518C\u5DF2\u542F\u7528\u4F46\u6CE8\u518C\u5931\u8D25\uFF0C\u5B9E\u4F8B\u6682\u65F6\u65E0\u6CD5\u6B63\u5E38\u5DE5\u4F5C"),a.error("[AutoRegister] \u8BF7\u68C0\u67E5\u4EE5\u4E0B\u914D\u7F6E\uFF1A"),a.error(`[AutoRegister] - \u7528\u6237 Key (userKey): ${e.userKey?"****"+e.userKey.slice(-4):"(\u672A\u8BBE\u7F6E)"}`),a.error(`[AutoRegister] - \u79DF\u6237 ID (tenantId): ${e.tenantId||"(\u53EF\u9009\uFF0C\u5C06\u81EA\u52A8\u63A8\u5BFC)"}`),a.error(`[AutoRegister] - \u5B9E\u4F8B\u540D (instanceName): ${e.instanceName||"(\u4F7F\u7528\u4E3B\u673A\u540D)"}`),a.error(`[AutoRegister] - \u8C03\u5EA6\u4E2D\u5FC3\u5730\u5740: ${e.serverUrl||m}`),a.error(`[AutoRegister] - \u6700\u540E\u9519\u8BEF: ${d.error||"\u672A\u77E5"}`),a.error("[AutoRegister] ========================================"),a.error(`[AutoRegister] \u914D\u7F6E\u6765\u6E90\uFF1A${T()} \u6216\u73AF\u5883\u53D8\u91CF`),a.warn(`[AutoRegister] \u5C06\u5728\u540E\u53F0\u6301\u7EED\u91CD\u8BD5\u6CE8\u518C\uFF08\u6BCF ${Math.round(Z()/1e3)} \u79D2\uFF09\uFF0C\u76F4\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u5EFA\u7ACB\u8FDE\u63A5`)),ee(e),!1}async function er(){const e=b();if(!e.userKey&&!e.machineToken)return{success:!1,error:"userKey or machineToken is required for runtime token refresh"};const r=pe(),t=j(e),n=L(e);try{const o=await $.post(`${t}/api/instances/runtime-tokens/refresh`,{tenantId:e.tenantId,userKey:e.machineToken?void 0:e.userKey,machineToken:e.machineToken,instanceId:r.instanceId,instanceName:e.instanceName,runtimeBridgeBaseUrl:n},{headers:{"Content-Type":"application/json"},timeout:1e4});if(!o.data.success||!o.data.runtimeAccessToken)return{success:!1,error:o.data.message||"scheduler did not return runtimeAccessToken"};const s=G(t,y(e))!==o.data.runtimeAccessToken;return H({accessToken:o.data.runtimeAccessToken,instanceId:r.instanceId,userId:o.data.userId||e.userKey||e.credentialId||"",schedulerBaseUrl:t,userKey:y(e)}),{success:!0,runtimeAccessToken:o.data.runtimeAccessToken,updated:s}}catch(o){const i=o;return{success:!1,error:i.response?.data?JSON.stringify(i.response.data):i.message}}}async function rr(e,r){const t=_(e);if(!t)return{success:!1,error:"serverUrl is required for runtime token refresh"};const n=h().filter(u=>_(u.serverUrl)===t),o=String(r||"").trim(),i=o?n.find(u=>String(u.userKey||"").trim()===o||String(u.credentialId||"").trim()===o):n.length===1?n[0]:void 0;if(!i)return{success:!1,error:o?"no auto-register target matches this identity":"multiple auto-register targets share this serverUrl; specify the target identity"};if(!i.userKey&&!i.machineToken)return{success:!1,error:"userKey or machineToken is required for runtime token refresh"};const s={instanceId:$e(t,y(i))},c=L(i);try{const u=await $.post(`${t}/api/instances/runtime-tokens/refresh`,{tenantId:i.tenantId,userKey:i.machineToken?void 0:i.userKey,machineToken:i.machineToken,instanceId:s.instanceId,instanceName:i.instanceName,runtimeBridgeBaseUrl:c},{headers:{"Content-Type":"application/json"},timeout:1e4});if(!u.data.success||!u.data.runtimeAccessToken)return{success:!1,error:u.data.message||"scheduler did not return runtimeAccessToken"};const I=G(t,y(i))!==u.data.runtimeAccessToken;return V({serverBaseUrl:t,accessToken:u.data.runtimeAccessToken,userKey:y(i)}),{success:!0,runtimeAccessToken:u.data.runtimeAccessToken,updated:I}}catch(u){const l=u;return{success:!1,error:l.response?.data?JSON.stringify(l.response.data):l.message}}}async function tr(){if(!d.registered||!d.instanceId)return a.info("[AutoRegister] \u5B9E\u4F8B\u672A\u6CE8\u518C\uFF0C\u65E0\u9700\u6CE8\u9500"),!0;const e=J(d.instanceId),r=e?h().find(t=>N(t)===e.targetKey):void 0;if(r&&(String(r.machineToken||"").trim()||r.credentialType==="MACHINE_TOKEN"))return a.info(`[AutoRegister] \u673A\u5668\u51ED\u636E\u76EE\u6807\uFF08instanceId=${d.instanceId}\uFF09\u8DF3\u8FC7\u6CE8\u9500\uFF1A\u914D\u5BF9\u8EAB\u4EFD\u5FC5\u987B\u8DE8\u91CD\u542F\u5B58\u6D3B\uFF0C\u4E0D\u5220\u9664\u8C03\u5EA6\u4E2D\u5FC3\u767B\u8BB0\u884C`),!0;try{const t=await be(d.instanceId);if(t.success){a.info(`[AutoRegister] \u2713 \u6CE8\u9500\u6210\u529F: ${d.instanceId}`);const n=J(d.instanceId),o=n?.serverUrl||j(b(),d.instanceId);M().schedulerBaseUrl&&me(o,n?.identityKey),ge();try{const{stopTunnelClientForTarget:s}=await import("./tunnel-client.js");s(o,n?.identityKey??y(b()))}catch(s){a.warn(`[AutoRegister] \u6CE8\u9500\u540E\u505C\u6B62\u96A7\u9053\u5931\u8D25: ${s.message}`)}if(!n)d.registered=!1,d.instanceId=void 0;else{delete d.registrations[n.targetKey];const s=Object.entries(d.registrations);d.registered=s.length>0,d.instanceId=s[s.length-1]?.[1]}return!0}else return a.warn(`[AutoRegister] \u6CE8\u9500\u5931\u8D25: ${t.message}`),!1}catch(t){const n=t;return a.error(`[AutoRegister] \u6CE8\u9500\u8BF7\u6C42\u5931\u8D25: ${n.message}`),!1}}function nr(){return{...d}}function sr(){return d.registered}function ir(){return d.instanceId}async function or(){const e=b(),r=d.instanceId,t=j(e,r),n={};if(r&&(n.instanceId=r),e.enabled&&(n.runtimeBridgeBaseUrl=L(e)),!n.instanceId&&!n.runtimeBridgeBaseUrl)return a.info("[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\uFF1A\u6CA1\u6709 instanceId \u6216 runtimeBridgeBaseUrl\uFF0C\u8DF3\u8FC7\u6E05\u7406"),{success:!0,agentCount:0};try{a.info("[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\uFF1A\u6B63\u5728\u901A\u77E5\u8C03\u5EA6\u4E2D\u5FC3..."),a.info(`[AutoRegister] instanceId: ${n.instanceId||"(\u65E0)"}`),a.info(`[AutoRegister] runtimeBridgeBaseUrl: ${n.runtimeBridgeBaseUrl||"(\u65E0)"}`);const o=await $.post(`${t}/api/instances/bridge-restart-cleanup`,n,{headers:{"Content-Type":"application/json"},timeout:1e4});return o.data.success?(a.info(`[AutoRegister] \u2713 Bridge \u91CD\u542F\u6E05\u7406\u6210\u529F\uFF1A${o.data.message}`),a.info(`[AutoRegister] \u6E05\u7406\u4E86 ${o.data.agentCount||0} \u4E2A Agent`),{success:!0,agentCount:o.data.agentCount||0}):(a.warn(`[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\u5931\u8D25\uFF1A${o.data.message}`),{success:!1,error:o.data.message})}catch(o){const i=o,s=i.response?.data?JSON.stringify(i.response.data):i.message;return a.warn(`[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\u8BF7\u6C42\u5931\u8D25\uFF1A${s}`),{success:!1,error:s}}}export{Ze as autoRegister,or as bridgeRestartCleanup,He as cancelBackgroundRegisterRetries,Te as collapseDuplicatedSecret,qe as findConfigsByConnectionKey,T as getAutoRegisterConfigFilePath,Je as getConfiguredConnectionKeys,Ye as getCurrentConfiguredConnectionKey,ir as getInstanceId,nr as getRegistrationState,sr as isRegistered,ie as isTunnelConfig,Ve as listConfiguredTargetSummaries,W as loadConfig,h as loadConfigs,b as loadPrimaryLifecycleConfig,Qe as replaceConfiguredConnectionKey,er as requestRuntimeAccessTokenRefresh,rr as requestRuntimeAccessTokenRefreshForServer,$e as resolveInstanceIdForTarget,L as resolveRuntimeBridgeBaseUrl,Xe as resolveSchedulerBaseUrlFromToken,Ne as resolveTargetIdentityFromToken,tr as unregister};
1
+ import{createHash as ue,randomBytes as de}from"node:crypto";import m from"node:fs";import w from"node:os";import x from"node:path";import{fileURLToPath as le}from"node:url";import B from"axios";import{v4 as fe}from"uuid";import{getActiveBridgeHttpPort as ge,getAutoRegisterConfigFilePath as S,getBridgeVersion as me,isDesktopAppMode as pe,schedulerBaseUrl as p}from"../config.js";import{runExclusiveConfigWrite as D}from"../utils/config-write-queue.js";import{logger as a}from"../utils/logger.js";import{buildTargetKey as P,fingerprintUserKey as ye,serverUrlOfTargetKey as G}from"../utils/target-identity.js";import{clearRuntimeBinding as Ie,clearScopedRuntimeAccessToken as Ae,getRuntimeAccessToken as M,getRuntimeBindingPublicState as Re,getScopedRuntimeAccessToken as H,listScopedRuntimeAccessTokens as Se,loadRuntimeBinding as z,normalizeSchedulerBaseUrl as T,saveRuntimeBinding as V,saveScopedRuntimeAccessToken as X}from"./runtime-binding.js";const Q={enabled:!1,serverUrl:p,preferSameLanIp:!0,maxRetries:3,retryInterval:2e3},d={registered:!1,registrations:{}};let k=[];const Te=10*60*1e3,$=new Map;function Z(){const e=Date.now();for(const[r,t]of $)t.expiresAt<=e&&$.delete(r)}function Ze(){Z();const e=[...k];for(const r of $.values())r.key&&!e.includes(r.key)&&e.push(r.key);return e}function er(e){const r=String(e||"").trim();if(!r)return[];const t=h(),n=t.filter(i=>String(i.connectionKey||"").trim()===r);if(n.length>0)return n;Z();const o=new Set;for(const[i,s]of $)s.key===r&&o.add(i);return o.size===0?[]:t.filter(i=>o.has(N(i)))}function rr(){return k[0]??""}const he=3e4;function ee(){const e=Number(process.env.AWS_REGISTER_BACKGROUND_RETRY_INTERVAL);return Number.isFinite(e)&&e>0?e:he}const C=new Map;function re(e){const r=e.serverUrl||p,t=N(e)||r;if(C.has(t))return;const n=setTimeout(()=>{C.delete(t),ve(e,t)},ee());n.unref?.(),C.set(t,n)}async function ve(e,r){try{const t=h().find(n=>N(n)===r)||e;await Y(t,{backgroundRetry:!0})}catch(t){a.warn(`[AutoRegister] \u540E\u53F0\u91CD\u8BD5\u6CE8\u518C\u5F02\u5E38: ${t.message}`),re(e)}}function tr(){for(const e of C.values())clearTimeout(e);C.clear()}function Ke(e){const r=e.trim();if(r.length<8)return r;for(let t=1;t<=r.length/2;t++){if(r.length%t!==0)continue;const n=r.slice(0,t);let o=!0;for(let i=t;i<r.length;i+=t)if(r.slice(i,i+t)!==n){o=!1;break}if(o&&n.length<r.length)return n}return r}function Ue(e){const r=g(e);if(!r)return r;const t=Ke(r);return t!==r&&a.warn(`[AutoRegister] userKey \u7591\u4F3C\u88AB\u590D\u5236\u4E86\u4E24\u904D\uFF08\u957F\u5EA6 ${r.length} \u2192 ${t.length}\uFF09\uFF0C\u5DF2\u81EA\u52A8\u53BB\u91CD\u3002\u8BF7\u68C0\u67E5\u914D\u7F6E\u6587\u4EF6\u662F\u5426\u91CD\u590D\u7C98\u8D34\u3002`),t}function g(e){return e==null?void 0:String(e).trim()||void 0}function _(e){return T(e)}function te(e){return Array.isArray(e.autoRegisterTargets)?e.autoRegisterTargets.filter(r=>!!(r&&typeof r=="object"&&!Array.isArray(r))):[]}function N(e){const r=e?.serverUrl||p;return P(r,e?.credentialId||e?.userKey)}function y(e){return e?.credentialId||e?.userKey}function W(e){if(typeof e=="boolean")return e;if(typeof e=="string"){const r=e.trim().toLowerCase();if(["true","1","yes","y"].includes(r))return!0;if(["false","0","no","n"].includes(r))return!1}}function ne(e){if(e==null||e==="")return;const r=Number(e);return Number.isFinite(r)?r:void 0}function O(e){const r=g(e.serverUrl)||g(e.schedulerBaseUrl),t=g(e.connectionKey)||g(e.password);return{enabled:W(e.enabled),serverUrl:r,tenantId:g(e.tenantId),userId:g(e.userId),userKey:Ue(e.userKey),machineToken:g(e.machineToken),connectionKey:t,instanceName:g(e.instanceName),instanceId:g(e.instanceId),credentialId:g(e.credentialId),credentialRef:g(e.credentialRef),credentialType:g(e.credentialType),projectId:g(e.projectId),roleName:g(e.roleName),workspacePath:g(e.workspacePath),registerAddr:g(e.registerAddr),registerIp:g(e.registerIp),virtualIp:g(e.virtualIp),tunnel:W(e.tunnel),preferSameLanIp:W(e.preferSameLanIp),maxRetries:ne(e.maxRetries),retryInterval:ne(e.retryInterval)}}function se(){const e=S();try{if(!m.existsSync(e))return a.debug(`[AutoRegister] \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728: ${e}`),null;const r=m.readFileSync(e,"utf-8"),t=JSON.parse(r);return a.info(`[AutoRegister] \u4ECE\u914D\u7F6E\u6587\u4EF6\u52A0\u8F7D\u914D\u7F6E: ${e}`),O(t)}catch(r){const t=r;return a.warn(`[AutoRegister] \u8BFB\u53D6\u914D\u7F6E\u6587\u4EF6\u5931\u8D25: ${e}, error: ${t.message}`),null}}function ke(){const e=S();try{if(!m.existsSync(e))return[];const r=m.readFileSync(e,"utf-8"),t=JSON.parse(r),n=O(t),o=Array.isArray(t.autoRegisterTargets)?t.autoRegisterTargets:[];return o.length===0?n.userKey||n.machineToken?[n]:[]:o.filter(i=>!!(i&&typeof i=="object"&&!Array.isArray(i))).map(i=>{const s=O(i);return{...n,...s,machineToken:s.machineToken||(s.userKey?void 0:n.machineToken),connectionKey:s.connectionKey}})}catch(r){const t=r;return a.warn(`[AutoRegister] \u8BFB\u53D6\u81EA\u52A8\u6CE8\u518C\u76EE\u6807\u5931\u8D25: ${e}, error: ${t.message}`),[]}}function nr(){const e=S();if(!m.existsSync(e))return[];let r;try{r=JSON.parse(m.readFileSync(e,"utf-8"))}catch(s){return a.warn(`[AutoRegister] \u8BFB\u53D6 config.json \u5931\u8D25\uFF08targets \u6458\u8981\uFF09: ${s.message}`),[]}const t=O(r),n=Array.isArray(r.autoRegisterTargets)?r.autoRegisterTargets:[],o=n.length>0?n.filter(s=>!!(s&&typeof s=="object"&&!Array.isArray(s))).map(s=>{const c=O(s);return{...t,...c,machineToken:c.machineToken||(c.userKey?void 0:t.machineToken),connectionKey:c.connectionKey}}):t.userKey||t.machineToken?[t]:[],i=s=>{const c=String(s||"").trim();return c?c.length<=8?"****":`${c.slice(0,8)}****${c.slice(-4)}`:""};return o.map((s,c)=>({index:c,serverUrl:s.serverUrl||"",instanceName:s.instanceName||"",registerAddr:s.registerAddr||s.registerIp||s.virtualIp||"",tunnel:typeof s.tunnel=="boolean"?s.tunnel:null,userKeyMasked:i(s.userKey),machineTokenSet:!!String(s.machineToken||"").trim(),credentialType:s.credentialType||"",credentialId:s.credentialId||"",credentialRef:s.credentialRef||"",connectionKeySet:!!String(s.connectionKey||"").trim()}))}function ie(){const e={};return process.env.AWS_AUTO_REGISTER==="true"&&(e.enabled=!0),process.env.AWS_RUNTIME_SCHEDULER_BASE_URL&&(e.serverUrl=process.env.AWS_RUNTIME_SCHEDULER_BASE_URL),process.env.AWS_TENANT_ID&&(e.tenantId=process.env.AWS_TENANT_ID),process.env.AWS_USER_KEY&&(e.userKey=process.env.AWS_USER_KEY),process.env.AWS_BRIDGE_MACHINE_TOKEN&&(e.machineToken=process.env.AWS_BRIDGE_MACHINE_TOKEN),process.env.AWS_BRIDGE_CONNECTION_KEY&&(e.connectionKey=process.env.AWS_BRIDGE_CONNECTION_KEY),process.env.AWS_INSTANCE_NAME&&(e.instanceName=process.env.AWS_INSTANCE_NAME),process.env.AWS_PROJECT_NAME&&(e.projectId=process.env.AWS_PROJECT_NAME),process.env.AWS_ROLE_NAME&&(e.roleName=process.env.AWS_ROLE_NAME),process.env.AWS_WORKSPACE_PATH&&(e.workspacePath=process.env.AWS_WORKSPACE_PATH),process.env.AWS_REGISTER_ADDR&&(e.registerAddr=process.env.AWS_REGISTER_ADDR),process.env.AWS_REGISTER_IP&&(e.registerIp=process.env.AWS_REGISTER_IP),process.env.AWS_VIRTUAL_IP&&(e.virtualIp=process.env.AWS_VIRTUAL_IP),process.env.AWS_PREFER_SAME_LAN_IP&&(e.preferSameLanIp=W(process.env.AWS_PREFER_SAME_LAN_IP)??!0),process.env.AWS_REGISTER_MAX_RETRIES&&(e.maxRetries=parseInt(process.env.AWS_REGISTER_MAX_RETRIES,10)),process.env.AWS_REGISTER_RETRY_INTERVAL&&(e.retryInterval=parseInt(process.env.AWS_REGISTER_RETRY_INTERVAL,10)),e}function L(){const e=se(),r=ie(),t={...Q,...e||{},...r},n=t.instanceName||w.hostname();let o=!1;return process.env.AWS_AUTO_REGISTER!==void 0?o=process.env.AWS_AUTO_REGISTER==="true":e&&(o=!0),{enabled:o,serverUrl:t.serverUrl||p,tenantId:t.tenantId||"",userKey:t.userKey||"",machineToken:t.machineToken,connectionKey:t.connectionKey,instanceName:n,instanceId:t.instanceId,credentialId:t.credentialId,credentialRef:t.credentialRef,credentialType:t.credentialType,projectId:t.projectId,roleName:t.roleName,workspacePath:t.workspacePath,registerAddr:t.registerAddr,registerIp:t.registerIp,virtualIp:t.virtualIp,tunnel:typeof t.tunnel=="boolean"?t.tunnel:void 0,preferSameLanIp:t.preferSameLanIp!==!1,maxRetries:t.maxRetries,retryInterval:t.retryInterval}}function h(){const e=ke(),r=ie(),n=(e.length>0?e:[se()||{}]).map(o=>{const i={...Q,...o,...r};let s=!1;return process.env.AWS_AUTO_REGISTER!==void 0?s=process.env.AWS_AUTO_REGISTER==="true":s=e.length>0||!!(i.userKey||i.machineToken),{enabled:s,serverUrl:i.serverUrl||p,tenantId:i.tenantId||"",userId:i.userId,userKey:i.userKey||"",machineToken:i.machineToken,connectionKey:i.connectionKey,instanceName:i.instanceName||w.hostname(),instanceId:i.instanceId,credentialId:i.credentialId,credentialRef:i.credentialRef,credentialType:i.credentialType,projectId:i.projectId,roleName:i.roleName,workspacePath:i.workspacePath,registerAddr:i.registerAddr,registerIp:i.registerIp,virtualIp:i.virtualIp,tunnel:typeof i.tunnel=="boolean"?i.tunnel:void 0,preferSameLanIp:i.preferSameLanIp!==!1,maxRetries:i.maxRetries,retryInterval:i.retryInterval}});return k=n.map(o=>o.connectionKey).filter(o=>!!(o&&o.trim())),n}function _e(){const e=w.networkInterfaces(),r=[];for(const t of Object.keys(e)){const n=e[t];if(n)for(const o of n)o.family==="IPv4"&&!o.internal&&r.push({address:o.address,netmask:o.netmask,name:t})}return r}function J(e){const r=e.split(".").map(Number);return(r[0]<<24)+(r[1]<<16)+(r[2]<<8)+r[3]}function Ee(e,r,t){const n=J(e),o=J(r),i=J(t);return(n&i)===(o&i)}function Ne(e){try{const r=new URL(e);return r.hostname==="localhost"||r.hostname==="127.0.0.1"?"127.0.0.1":/^(\d{1,3}\.){3}\d{1,3}$/.test(r.hostname)?r.hostname:null}catch{return null}}function we(e){return e==="127.0.0.1"}function Be(e){const r=_e();if(r.length===0)return a.warn("[AutoRegister] \u672A\u627E\u5230\u4EFB\u4F55\u975E\u5185\u90E8 IP \u5730\u5740\uFF0C\u4F7F\u7528 127.0.0.1"),"127.0.0.1";const t=Ne(e);if(t){if(we(t))return"127.0.0.1";for(const n of r)if(Ee(n.address,t,n.netmask))return a.info(`[AutoRegister] \u627E\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u540C\u5B50\u7F51\u7684 IP: ${n.address} (\u7F51\u5361: ${n.name}, \u5B50\u7F51\u63A9\u7801: ${n.netmask})`),n.address;a.warn(`[AutoRegister] \u672A\u627E\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3 (${t}) \u540C\u5B50\u7F51\u7684\u672C\u673A IP\uFF0C\u4F7F\u7528 127.0.0.1`)}else a.warn("[AutoRegister] \u65E0\u6CD5\u89E3\u6790\u8C03\u5EA6\u4E2D\u5FC3 IP\uFF0C\u4F7F\u7528 127.0.0.1");return"127.0.0.1"}function $e(e=p){return Be(e)}function oe(e){const r=e||L();return!r.enabled||!r.userKey&&!r.machineToken?!1:r.tunnel===!0?!0:r.tunnel===!1?!1:!r.registerAddr&&!r.registerIp&&!r.virtualIp}function j(e){const r=ge();if(oe(e)){const i=e.serverUrl||p;try{const s=new URL(i);if(!e.instanceId)a.warn("[AutoRegister] \u96A7\u9053\u6A21\u5F0F\u4F46\u7F3A\u5C11 instanceId\uFF0C\u964D\u7EA7\u4E3A\u76F4\u8FDE\u6A21\u5F0F");else return`${s.protocol}//${s.host}/tunnel/${e.instanceId}`}catch{a.warn("[AutoRegister] serverUrl \u89E3\u6790\u5931\u8D25\uFF0C\u964D\u7EA7\u4E3A\u76F4\u8FDE\u6A21\u5F0F")}}const t=pe()||e.preferSameLanIp===!1?"127.0.0.1":$e(e.serverUrl||p),n=e.registerAddr||e.registerIp||e.virtualIp||t;return n?/^https?:\/\//i.test(n)?n:/:[0-9]+$/.test(n)?`http://${n}`:`http://${n}:${r}`:`http://127.0.0.1:${r}`}function b(){return h()[0]||L()}function sr(e){return Ce(e)?.serverUrl}function Ce(e){const r=String(e||"").trim();if(!r)return;for(const n of h()){if(!n?.serverUrl)continue;const o=H(n.serverUrl,y(n));if(o&&o===r)return{serverUrl:T(n.serverUrl)||n.serverUrl,userKey:n.userKey,identityKey:y(n),instanceId:n.instanceId};const i=Se(n.serverUrl);for(const s of i){if(s.accessToken!==r)continue;const c=ye(n.userKey)===s.userKeyFingerprint?n.userKey:void 0;return{serverUrl:T(n.serverUrl)||n.serverUrl,userKey:c,identityKey:c}}}const t=z();if(t.schedulerBaseUrl){const n=H(t.schedulerBaseUrl);if(n&&n===r)return{serverUrl:T(t.schedulerBaseUrl)||t.schedulerBaseUrl}}}function Oe(e){if(!e)return;const r=Object.entries(d.registrations).find(([,t])=>t===e);return r?G(r[0]):void 0}function be(e,r){const t=T(e);if(!t)return;if(String(r||"").trim()){const o=d.registrations[P(t,r)];return o||void 0}const n=Object.entries(d.registrations).filter(([o])=>G(o)===t);return n.length===1?n[0][1]:void 0}function F(e,r){const t=Oe(r);if(t)return t;const n=g(e.serverUrl);if(n&&(n!==p||process.env.AWS_RUNTIME_SCHEDULER_BASE_URL))return n;const o=z(),i=g(o.schedulerBaseUrl);return o.status==="paired"&&i?i:n||p}function xe(){const e={clientVersion:me()};try{const r=x.join(x.dirname(le(import.meta.url)),".."),t=x.join(r,"index.jsc"),n=m.existsSync(t)?t:x.join(r,"index.js"),o=ue("sha256").update(m.readFileSync(n)).digest("hex");e.entrySha256=o.slice(0,16)}catch{}return e}async function Pe(e){const r=e.instanceName||w.hostname(),t=e.serverUrl||p,n={tenantId:e.tenantId,userKey:e.machineToken?void 0:e.userKey,machineToken:e.machineToken,instanceId:e.instanceId,instanceName:r,hostname:w.hostname(),virtualIp:e.registerAddr||e.registerIp||e.virtualIp,runtimeBridgeBaseUrl:j(e),connectionKey:e.connectionKey,workspacePath:e.workspacePath,projectId:e.projectId,roleName:e.roleName,...xe()};return a.info(`[AutoRegister] \u6B63\u5728\u6CE8\u518C\u5B9E\u4F8B: ${r}`),a.info(`[AutoRegister] \u8C03\u5EA6\u4E2D\u5FC3: ${t}`),a.info(e.machineToken?"[AutoRegister] \u51ED\u636E: \u673A\u5668\u81EA\u6301\u51ED\u636E\uFF08machineToken\uFF09":`[AutoRegister] \u7528\u6237 Key: ${e.userKey?"****"+e.userKey.slice(-4):"(\u672A\u8BBE\u7F6E)"}`),a.info(`[AutoRegister] \u79DF\u6237 ID: ${e.tenantId||"(\u81EA\u52A8\u63A8\u5BFC)"}`),(await B.post(`${t}/api/instances/register`,n,{headers:{"Content-Type":"application/json"},timeout:1e4})).data}function We(e,r,t,n,o,i,s,c,u){const l=S();return D(l,()=>{if(!m.existsSync(l))return;const I=m.readFileSync(l,"utf-8"),v=JSON.parse(I),U=T(e);if(!U)return;let A=!1;const R=f=>T(String(f.serverUrl||f.schedulerBaseUrl||""))!==U?!1:String(t||"").trim()?String(f.userKey??"").trim()===String(t).trim():String(s||"").trim()?String(f.machineToken??"").trim()===String(s).trim():!0,K=f=>{R(f)&&(r&&f.instanceId!==r&&(f.instanceId=r,A=!0),n&&f.credentialId!==n&&(f.credentialId=n,A=!0),o&&f.credentialRef!==o&&(f.credentialRef=o,A=!0),i&&f.credentialType!==i&&(f.credentialType=i,A=!0),c&&f.tenantId!==c&&(f.tenantId=c,A=!0),u&&f.userId!==u&&(f.userId=u,A=!0))};if(Array.isArray(v.autoRegisterTargets))for(const f of v.autoRegisterTargets)f&&typeof f=="object"&&!Array.isArray(f)&&K(f);else K(v);A&&(m.writeFileSync(l,JSON.stringify(v,null,2),"utf-8"),a.info(`[AutoRegister] \u5DF2\u56DE\u5199 instanceId \u5230 config.json (serverUrl=${e}${t?`, userKey=****${String(t).slice(-4)}`:""})`))})}async function Le(e,r){const t=String(r||"").trim();if(!t)return;const n=y(e),o=_(e.serverUrl);if(!n||!o)return;const i=S();try{await D(i,()=>{if(!m.existsSync(i))return;const s=m.readFileSync(i,"utf-8"),c=JSON.parse(s),l=te(c).find(I=>_(I.serverUrl||I.schedulerBaseUrl)===o&&String(I.credentialId||I.userKey||"").trim()===n);if(!l){a.warn(`[AutoRegister] \u65E0\u6CD5\u5B9A\u4F4D connectionKey \u5BF9\u5E94 target\uFF0C\u8DF3\u8FC7\u5199\u76D8: server=${o}`);return}String(l.connectionKey??"").trim()!==t&&(l.connectionKey=t,m.writeFileSync(i,JSON.stringify(c,null,2),"utf-8"),a.info(`[AutoRegister] \u5DF2\u5199\u5165 target connectionKey \u5230 config.json: ${i}`))})}catch(s){a.warn(`[AutoRegister] \u5199\u5165 target connectionKey \u5230 config.json \u5931\u8D25: ${s.message}`)}}async function ir(e,r){const t=String(e||"").trim();if(!t)throw new Error("connectionKey is required");const n=_(r?.serverUrl);if(!n)throw new Error("serverUrl is required to rotate a target connectionKey");const o=S();let i;const s=await D(o,()=>{if(!m.existsSync(o))return!1;const l=JSON.parse(m.readFileSync(o,"utf-8")),I=te(l),v=String(r?.instanceId||"").trim(),U=String(r?.credentialId||"").trim(),A=I.filter(K=>{if(_(K.serverUrl||K.schedulerBaseUrl)!==n)return!1;if(v&&String(K.instanceId||"").trim()===v)return!0;if(U){const E=String(K.credentialId||"").trim(),ce=String(K.userKey||"").trim();if(E===U||ce===U)return!0}return!v&&!U&&I.filter(E=>_(E.serverUrl||E.schedulerBaseUrl)===n).length===1});if(A.length!==1)throw new Error(`\u65E0\u6CD5\u552F\u4E00\u5B9A\u4F4D connectionKey \u5BF9\u5E94 target\uFF08server=${n}, matches=${A.length}\uFF09`);const R=A[0];return String(R.connectionKey??"").trim()===t?!1:(i={targetKey:P(String(R.serverUrl??R.schedulerBaseUrl??""),R.credentialId||R.userKey),previousConnectionKey:String(R.connectionKey??"").trim()},R.connectionKey=t,String(l.connectionKey??"").trim()&&delete l.connectionKey,m.writeFileSync(o,JSON.stringify(l,null,2),"utf-8"),a.info(`[AutoRegister] \u5DF2\u8F6E\u6362 target connectionKey \u5E76\u5199\u56DE config.json: ${o}`),!0)}),c=!!process.env.AWS_BRIDGE_CONNECTION_KEY;c&&s&&(process.env.AWS_BRIDGE_CONNECTION_KEY=t,a.warn("[AutoRegister] \u68C0\u6D4B\u5230 AWS_BRIDGE_CONNECTION_KEY \u73AF\u5883\u53D8\u91CF\uFF0C\u5DF2\u540C\u6B65\u66F4\u65B0\u5F53\u524D\u8FDB\u7A0B\uFF1B\u91CD\u542F bridge \u540E\u4F1A\u56DE\u5230\u73AF\u5883\u53D8\u91CF\u4E2D\u7684\u65E7\u503C\uFF0C\u8BF7\u4E00\u5E76\u4FEE\u6539\u90E8\u7F72\u914D\u7F6E"));const u=h().map(l=>String(l.connectionKey||"").trim()).filter(l=>l.length>0);return k=s?[...new Set([t,...u])]:[...new Set(u)],s&&i&&i.previousConnectionKey!==t&&$.set(i.targetKey,{key:i.previousConnectionKey,expiresAt:Date.now()+Te}),{envOverrideWarning:c,rotated:s}}async function ae(e){let r=0;for(const t of e)String(t.connectionKey||"").trim()||(t.connectionKey=`awsb_${de(24).toString("base64url")}`,r+=1,k.includes(t.connectionKey)||(k=[...k,t.connectionKey]),await Le(t,t.connectionKey));r!==0&&a.info(`[AutoRegister] ${r} \u4E2A\u76EE\u6807\u7F3A\u5C11 connectionKey\uFF0C\u5DF2\u6309 target \u72EC\u7ACB\u751F\u6210\u5E76\u5199\u5165 config.json`)}function q(e){if(!e)return;const r=Object.entries(d.registrations).find(([,i])=>i===e);if(!r)return;const t=r[0],n=G(t),o=h().find(i=>N(i)===t);return{serverUrl:n,identityKey:o?y(o):void 0,targetKey:t}}async function je(e){const r=q(e),t=r?.serverUrl||F(b(),e),n=M(t,r?.identityKey);if(!n)throw new Error("runtimeAccessToken is required to unregister bridge instance");return(await B.post(`${t}/api/instances/unregister`,{instanceId:e},{headers:{"Content-Type":"application/json","X-Runtime-Token":n},timeout:1e4})).data}async function or(e){const r=e?[{...L(),...e}]:h();await ae(r);const n=(r.length>1?await Promise.all(r.map(i=>Y(i))):[await Y(r[0]||L())]).every(Boolean),o=r.every(i=>!i.enabled||!i.userKey&&!i.machineToken);if(!e&&(n||o)){const{stopTunnelClientsExcept:i}=await import("./tunnel-client.js");i(r.filter(s=>!!s.serverUrl).map(s=>P(s.serverUrl,y(s))))}return n}async function Y(e,r){if(!e.enabled)return a.info("[AutoRegister] \u81EA\u52A8\u6CE8\u518C\u672A\u542F\u7528"),a.info(`[AutoRegister] \u8981\u542F\u7528\u81EA\u52A8\u6CE8\u518C\uFF0C\u8BF7\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6 ${S()} \u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF AWS_AUTO_REGISTER=true`),!1;if(!e.userKey&&!e.machineToken)return a.error("[AutoRegister] \u7F3A\u5C11\u6CE8\u518C\u51ED\u636E\uFF08\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u8BBE\u7F6E userKey \u6216 machineToken\uFF0C\u4E5F\u53EF\u7528 `awsb pair --ticket ...` \u914D\u5BF9\uFF09"),!1;String(e.connectionKey||"").trim()||await ae([e]);const t=oe(e);t&&!e.instanceId&&(e.instanceId=`bridge-${fe().replace(/-/g,"").slice(0,12)}`,a.info(`[AutoRegister] \u96A7\u9053\u6A21\u5F0F\uFF1A\u5DF2\u9884\u58F0\u660E instanceId=${e.instanceId}`));const n=r?.backgroundRetry?1:e.maxRetries??3,o=e.retryInterval??2e3;for(let i=1;i<=n;i++){try{d.lastAttempt=new Date;const s=await Pe(e);if(s.success){if(d.registered=!0,d.instanceId=s.instanceId,s.credentialId&&(e.credentialId=s.credentialId,e.credentialType=s.credentialType),e.credentialRef=s.credentialRef,s.tenantId&&(e.tenantId=s.tenantId),s.userId&&(e.userId=s.userId),s.instanceId&&(d.registrations[N(e)]=s.instanceId,e.instanceId=s.instanceId),d.error=void 0,a.info("[AutoRegister] \u2713 \u6CE8\u518C\u6210\u529F\uFF01"),a.info(`[AutoRegister] \u5B9E\u4F8B ID: ${s.instanceId}`),a.info(`[AutoRegister] \u6D88\u606F: ${s.message}`),a.info(`[AutoRegister] \u66F4\u65B0: ${s.isUpdate?"\u662F":"\u5426"}`),s.runtimeAccessToken)try{const c=e.serverUrl||p;V({accessToken:s.runtimeAccessToken,instanceId:s.instanceId,userId:s.userId,schedulerBaseUrl:c,userKey:y(e)});const u=T(s.serverUrl);u&&u!==T(c)&&(X({serverBaseUrl:u,accessToken:s.runtimeAccessToken,userKey:y(e)}),a.info(`[AutoRegister] \u68C0\u6D4B\u5230 server \u4E0B\u53D1\u5730\u5740(${u})\u4E0E\u8FDE\u63A5\u5730\u5740(${c})\u4E0D\u540C\uFF0C\u5DF2\u6309\u4E24\u4E2A\u5730\u5740\u5206\u522B\u4FDD\u5B58 scoped token`)),a.info("[AutoRegister] \u5DF2\u4FDD\u5B58\u8C03\u5EA6\u4E2D\u5FC3\u4E0B\u53D1\u7684 runtime access token"),s.instanceId&&We(e.serverUrl||p,s.instanceId,e.userKey,s.credentialId,s.credentialRef,s.credentialType,e.machineToken,s.tenantId,s.userId).catch(l=>{a.warn(`[AutoRegister] \u56DE\u5199 instanceId \u5230 config.json \u5931\u8D25: ${l.message}`)})}catch(c){const u=c;return a.error(`[AutoRegister] \u4FDD\u5B58 runtime access token \u5931\u8D25: ${u.message}`),d.error=u.message,!1}else a.warn("[AutoRegister] \u6CE8\u518C\u54CD\u5E94\u672A\u5305\u542B runtime access token\uFF0CMCP \u5C06\u65E0\u6CD5\u8BBF\u95EE\u8C03\u5EA6\u4E2D\u5FC3\uFF0C\u8BF7\u68C0\u67E5 server \u7684 bridge \u5B9E\u4F8B token \u9881\u53D1\u903B\u8F91");if(t&&s.instanceId&&s.runtimeAccessToken){const{startTunnelClient:c}=await import("./tunnel-client.js"),u=e.serverUrl||p;c(u,s.instanceId,y(e)),a.info(`[AutoRegister] \u96A7\u9053\u5BA2\u6237\u7AEF\u5DF2\u542F\u52A8: server=${u}, instanceId=${s.instanceId}${e.userKey?`, userKey=****${e.userKey.slice(-4)}`:""}`)}return!0}else a.warn(`[AutoRegister] \u6CE8\u518C\u5931\u8D25: ${s.message}`),d.error=s.message}catch(s){const c=s,u=c.response?.data?JSON.stringify(c.response.data):c.message;a.error(`[AutoRegister] \u6CE8\u518C\u8BF7\u6C42\u5931\u8D25 (\u5C1D\u8BD5 ${i}/${n}): ${u}`),d.error=u}i<n&&(a.info(`[AutoRegister] ${o/1e3} \u79D2\u540E\u91CD\u8BD5...`),await new Promise(s=>setTimeout(s,o)))}return r?.backgroundRetry?a.warn(`[AutoRegister] \u540E\u53F0\u91CD\u8BD5\u6CE8\u518C\u4ECD\u672A\u6210\u529F (server=${e.serverUrl||p}): ${d.error||"\u672A\u77E5"}`):(a.error("[AutoRegister] \u2717 \u6CE8\u518C\u5931\u8D25\uFF0C\u5DF2\u8FBE\u6700\u5927\u91CD\u8BD5\u6B21\u6570"),a.error("[AutoRegister] ========================================"),a.error("[AutoRegister] \u81EA\u52A8\u6CE8\u518C\u5DF2\u542F\u7528\u4F46\u6CE8\u518C\u5931\u8D25\uFF0C\u5B9E\u4F8B\u6682\u65F6\u65E0\u6CD5\u6B63\u5E38\u5DE5\u4F5C"),a.error("[AutoRegister] \u8BF7\u68C0\u67E5\u4EE5\u4E0B\u914D\u7F6E\uFF1A"),a.error(`[AutoRegister] - \u7528\u6237 Key (userKey): ${e.userKey?"****"+e.userKey.slice(-4):"(\u672A\u8BBE\u7F6E)"}`),a.error(`[AutoRegister] - \u79DF\u6237 ID (tenantId): ${e.tenantId||"(\u53EF\u9009\uFF0C\u5C06\u81EA\u52A8\u63A8\u5BFC)"}`),a.error(`[AutoRegister] - \u5B9E\u4F8B\u540D (instanceName): ${e.instanceName||"(\u4F7F\u7528\u4E3B\u673A\u540D)"}`),a.error(`[AutoRegister] - \u8C03\u5EA6\u4E2D\u5FC3\u5730\u5740: ${e.serverUrl||p}`),a.error(`[AutoRegister] - \u6700\u540E\u9519\u8BEF: ${d.error||"\u672A\u77E5"}`),a.error("[AutoRegister] ========================================"),a.error(`[AutoRegister] \u914D\u7F6E\u6765\u6E90\uFF1A${S()} \u6216\u73AF\u5883\u53D8\u91CF`),a.warn(`[AutoRegister] \u5C06\u5728\u540E\u53F0\u6301\u7EED\u91CD\u8BD5\u6CE8\u518C\uFF08\u6BCF ${Math.round(ee()/1e3)} \u79D2\uFF09\uFF0C\u76F4\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u5EFA\u7ACB\u8FDE\u63A5`)),re(e),!1}async function ar(){const e=b();if(!e.userKey&&!e.machineToken)return{success:!1,error:"userKey or machineToken is required for runtime token refresh"};const r=Re(),t=F(e),n=j(e);try{const o=await B.post(`${t}/api/instances/runtime-tokens/refresh`,{tenantId:e.tenantId,userKey:e.machineToken?void 0:e.userKey,machineToken:e.machineToken,instanceId:r.instanceId,instanceName:e.instanceName,runtimeBridgeBaseUrl:n},{headers:{"Content-Type":"application/json"},timeout:1e4});if(!o.data.success||!o.data.runtimeAccessToken)return{success:!1,error:o.data.message||"scheduler did not return runtimeAccessToken"};const s=M(t,y(e))!==o.data.runtimeAccessToken;return V({accessToken:o.data.runtimeAccessToken,instanceId:r.instanceId,userId:o.data.userId||e.userKey||e.credentialId||"",schedulerBaseUrl:t,userKey:y(e)}),{success:!0,runtimeAccessToken:o.data.runtimeAccessToken,updated:s}}catch(o){const i=o;return{success:!1,error:i.response?.data?JSON.stringify(i.response.data):i.message}}}async function cr(e,r){const t=_(e);if(!t)return{success:!1,error:"serverUrl is required for runtime token refresh"};const n=h().filter(u=>_(u.serverUrl)===t),o=String(r||"").trim(),i=o?n.find(u=>String(u.userKey||"").trim()===o||String(u.credentialId||"").trim()===o):n.length===1?n[0]:void 0;if(!i)return{success:!1,error:o?"no auto-register target matches this identity":"multiple auto-register targets share this serverUrl; specify the target identity"};if(!i.userKey&&!i.machineToken)return{success:!1,error:"userKey or machineToken is required for runtime token refresh"};const s={instanceId:be(t,y(i))},c=j(i);try{const u=await B.post(`${t}/api/instances/runtime-tokens/refresh`,{tenantId:i.tenantId,userKey:i.machineToken?void 0:i.userKey,machineToken:i.machineToken,instanceId:s.instanceId,instanceName:i.instanceName,runtimeBridgeBaseUrl:c},{headers:{"Content-Type":"application/json"},timeout:1e4});if(!u.data.success||!u.data.runtimeAccessToken)return{success:!1,error:u.data.message||"scheduler did not return runtimeAccessToken"};const I=M(t,y(i))!==u.data.runtimeAccessToken;return X({serverBaseUrl:t,accessToken:u.data.runtimeAccessToken,userKey:y(i)}),{success:!0,runtimeAccessToken:u.data.runtimeAccessToken,updated:I}}catch(u){const l=u;return{success:!1,error:l.response?.data?JSON.stringify(l.response.data):l.message}}}async function ur(){if(!d.registered||!d.instanceId)return a.info("[AutoRegister] \u5B9E\u4F8B\u672A\u6CE8\u518C\uFF0C\u65E0\u9700\u6CE8\u9500"),!0;const e=q(d.instanceId),r=e?h().find(t=>N(t)===e.targetKey):void 0;if(r&&(String(r.machineToken||"").trim()||r.credentialType==="MACHINE_TOKEN"))return a.info(`[AutoRegister] \u673A\u5668\u51ED\u636E\u76EE\u6807\uFF08instanceId=${d.instanceId}\uFF09\u8DF3\u8FC7\u6CE8\u9500\uFF1A\u914D\u5BF9\u8EAB\u4EFD\u5FC5\u987B\u8DE8\u91CD\u542F\u5B58\u6D3B\uFF0C\u4E0D\u5220\u9664\u8C03\u5EA6\u4E2D\u5FC3\u767B\u8BB0\u884C`),!0;try{const t=await je(d.instanceId);if(t.success){a.info(`[AutoRegister] \u2713 \u6CE8\u9500\u6210\u529F: ${d.instanceId}`);const n=q(d.instanceId),o=n?.serverUrl||F(b(),d.instanceId);z().schedulerBaseUrl&&Ae(o,n?.identityKey),Ie();try{const{stopTunnelClientForTarget:s}=await import("./tunnel-client.js");s(o,n?.identityKey??y(b()))}catch(s){a.warn(`[AutoRegister] \u6CE8\u9500\u540E\u505C\u6B62\u96A7\u9053\u5931\u8D25: ${s.message}`)}if(!n)d.registered=!1,d.instanceId=void 0;else{delete d.registrations[n.targetKey];const s=Object.entries(d.registrations);d.registered=s.length>0,d.instanceId=s[s.length-1]?.[1]}return!0}else return a.warn(`[AutoRegister] \u6CE8\u9500\u5931\u8D25: ${t.message}`),!1}catch(t){const n=t;return a.error(`[AutoRegister] \u6CE8\u9500\u8BF7\u6C42\u5931\u8D25: ${n.message}`),!1}}function dr(){return{...d}}function lr(){return d.registered}function fr(){return d.instanceId}async function gr(){const e=b(),r=d.instanceId,t=F(e,r),n={};if(r&&(n.instanceId=r),e.enabled&&(n.runtimeBridgeBaseUrl=j(e)),!n.instanceId&&!n.runtimeBridgeBaseUrl)return a.info("[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\uFF1A\u6CA1\u6709 instanceId \u6216 runtimeBridgeBaseUrl\uFF0C\u8DF3\u8FC7\u6E05\u7406"),{success:!0,agentCount:0};try{a.info("[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\uFF1A\u6B63\u5728\u901A\u77E5\u8C03\u5EA6\u4E2D\u5FC3..."),a.info(`[AutoRegister] instanceId: ${n.instanceId||"(\u65E0)"}`),a.info(`[AutoRegister] runtimeBridgeBaseUrl: ${n.runtimeBridgeBaseUrl||"(\u65E0)"}`);const o=await B.post(`${t}/api/instances/bridge-restart-cleanup`,n,{headers:{"Content-Type":"application/json"},timeout:1e4});return o.data.success?(a.info(`[AutoRegister] \u2713 Bridge \u91CD\u542F\u6E05\u7406\u6210\u529F\uFF1A${o.data.message}`),a.info(`[AutoRegister] \u6E05\u7406\u4E86 ${o.data.agentCount||0} \u4E2A Agent`),{success:!0,agentCount:o.data.agentCount||0}):(a.warn(`[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\u5931\u8D25\uFF1A${o.data.message}`),{success:!1,error:o.data.message})}catch(o){const i=o,s=i.response?.data?JSON.stringify(i.response.data):i.message;return a.warn(`[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\u8BF7\u6C42\u5931\u8D25\uFF1A${s}`),{success:!1,error:s}}}export{or as autoRegister,gr as bridgeRestartCleanup,tr as cancelBackgroundRegisterRetries,Ke as collapseDuplicatedSecret,er as findConfigsByConnectionKey,S as getAutoRegisterConfigFilePath,Ze as getConfiguredConnectionKeys,rr as getCurrentConfiguredConnectionKey,fr as getInstanceId,dr as getRegistrationState,lr as isRegistered,oe as isTunnelConfig,nr as listConfiguredTargetSummaries,L as loadConfig,h as loadConfigs,b as loadPrimaryLifecycleConfig,ir as replaceConfiguredConnectionKey,ar as requestRuntimeAccessTokenRefresh,cr as requestRuntimeAccessTokenRefreshForServer,be as resolveInstanceIdForTarget,j as resolveRuntimeBridgeBaseUrl,sr as resolveSchedulerBaseUrlFromToken,Ce as resolveTargetIdentityFromToken,ur as unregister};
2
2
 
@@ -24,7 +24,6 @@ export declare function getInherited(scope: UserScope | null, agentId: string, t
24
24
 
25
25
 
26
26
 
27
-
28
27
  export declare function getEffective(scope: UserScope | null, agentId: string, type: CapabilityType, name: string, fallback?: boolean): boolean;
29
28
 
30
29
  export declare function getEffectiveSource(scope: UserScope | null, agentId: string, type: CapabilityType, name: string): "agent" | "inherited" | "bridge" | "deployed" | "default";
@@ -1,3 +1,3 @@
1
- import{existsSync as A,readFileSync as x,readdirSync as B}from"node:fs";import h from"node:path";import{getBridgeTemplateMcpDir as P,getBridgeTemplatePluginsDir as W,getBridgeTemplateSkillsDir as C}from"../config.js";import{atomicWriteFileSync as $,sanitizeAgentId as z}from"../utils/file-utils.js";import{getAgentOwner as F}from"./agent-ownership.js";import{getUserCapabilityAgentFile as R,getUserCapabilityDefaultsFile as U,isLegacyFallbackDisabled as v,scopeEquals as Y}from"./user-scope.js";const J=["skills","mcp","plugins"];function a(r,e){if(e){const t=F(e);if(t)return t}return r}function N(r,e){if(!e)return;const t=F(e);if(t&&!Y(t,r))throw new Error("agent-ownership-mismatch")}function j(r){switch(r){case"skills":return C();case"mcp":return P();case"plugins":return W();default:throw new Error(`\u672A\u77E5\u80FD\u529B\u7C7B\u578B: ${String(r)}`)}}function k(r){return h.join(j(r),"config.json")}function O(r,e){return h.join(j(r),"agents",`${z(e)}.json`)}function E(r,e){return U(r,e)}function g(r,e,t){return R(r,e,t)}const y=new Map;function ie(r,e){e?y.set(r,e):y.delete(r)}function S(r,e,t){const n=y.get(r);if(n)try{return n(t)[e]}catch{return}}function b(r){try{if(!A(r))return{};const e=JSON.parse(x(r,"utf8"));return!e||typeof e!="object"||Array.isArray(e)?{}:e}catch{return{}}}function M(r,e){$(r,`${JSON.stringify(e,null,2)}
2
- `)}function l(r,e){const t=e[r];if(!t||typeof t!="object"||Array.isArray(t))return{};const n={};for(const[i,o]of Object.entries(t))i.trim()&&typeof o=="boolean"&&(n[i.trim()]=o);return n}function _(r,e,t,n){const i={...l(e,r)};n==null?delete i[t]:i[t]=n,r[e]=i}function q(r){try{if(!A(r))return{};const e=JSON.parse(x(r,"utf8"));return!e||typeof e!="object"||Array.isArray(e)?{}:e}catch{return{}}}function c(r,e,t){const n=q(r),i=n[t];return i&&typeof i=="object"&&!Array.isArray(i)?l(e,i):t==="overrides"?l(e,n):{}}function T(r,e,t,n){const i={};for(const o of["overrides","inherited"]){const s=o===t?n:c(r,e,o),f={};for(const u of J){const d=u===e?s:c(r,u,o);f[u]=d}i[o]=f}M(r,i)}function p(r,e){const t={};return r?(Object.assign(t,l(e,b(E(r,e)))),t):(v()||Object.assign(t,l(e,b(k(e)))),t)}function L(r,e,t){if(!e)return{};const n=a(r,e);return n?c(g(n,t,e),t,"overrides"):v()?{}:c(O(t,e),t,"overrides")}function V(r,e,t){if(!e)return{};const n=a(r,e);return n?c(g(n,t,e),t,"inherited"):v()?{}:c(O(t,e),t,"inherited")}function G(r,e,t,n,i){const o=a(r,e),f=L(o,e,t)[n];if(f!==void 0)return f;const d=V(o,e,t)[n];if(d!==void 0)return d;const D=p(o,t)[n];if(D!==void 0)return D;if(i!==void 0)return i;const m=S(t,n,o);if(m!==void 0)return m;if(o&&!v()){const w=H(e,t,n);if(w!==void 0)return w}return!1}function H(r,e,t){if(r){const i=c(O(e,r),e,"overrides")[t];if(i!==void 0)return i;const o=c(O(e,r),e,"inherited")[t];if(o!==void 0)return o}const n=l(e,b(k(e)))[t];return n!==void 0?n:S(e,t,null)}function oe(r,e,t,n){const i=a(r,e);return L(i,e,t)[n]!==void 0?"agent":V(i,e,t)[n]!==void 0?"inherited":p(i,t)[n]!==void 0?"bridge":S(t,n,i)!==void 0?"deployed":"default"}function K(r,e,t,n){const i=E(r,e),o=b(i),s=l(e,o);_(o,e,t,n);const f=l(e,o);return JSON.stringify(s)===JSON.stringify(f)?!1:(M(i,o),!0)}function fe(r,e,t,n,i){if(!e)return!1;N(r,e);const o=a(r,e)??r,s=g(o,t,e),f=c(s,t,"overrides"),u={...f};return i==null?delete u[n]:u[n]=i,JSON.stringify(f)===JSON.stringify(u)?!1:(T(s,t,"overrides",u),!0)}function Q(r,e,t,n){if(!e)return!1;N(r,e);const i=a(r,e)??r,o=g(i,t,e),s=c(o,t,"inherited"),f={};if(n&&typeof n=="object"&&!Array.isArray(n))for(const[u,d]of Object.entries(n))u.trim()&&typeof d=="boolean"&&(f[u.trim()]=d);return JSON.stringify(s)===JSON.stringify(f)?!1:(T(o,t,"inherited",f),!0)}function se(r,e){const t=r?h.dirname(g(r,e,"_probe")):h.join(j(e),"agents");try{return A(t)?B(t).filter(n=>n.endsWith(".json")&&!n.startsWith(".")).map(n=>n.slice(0,-5)):[]}catch{return[]}}function ue(r,e){const t=y.get(e);if(!t)return 0;let n=0;const i=p(r,e),o=t(r)??{};for(const s of Object.keys(o))s in i||o[s]===!0&&(K(r,e,s,!1),n++);return n}function ce(r,e){return Object.keys(p(r,e)).length>0}function le(r,e,t,n){const i={};for(const o of n)i[o]=G(r,e,t,o);return i}function de(r,e,t){const n=[];if(!e)return n;for(const i of J){const o=t&&typeof t=="object"?t[i]??{}:{};Q(r,e,i,o)&&n.push(i)}return n}export{J as CAPABILITY_TYPES,p as getDefaults,G as getEffective,le as getEffectiveMap,oe as getEffectiveSource,V as getInherited,L as getOverrides,ce as hasAnyDefault,se as listOverrideAgents,ue as reconcileDefaultsFromDeployed,K as setDefault,ie as setDeployedDefaultsProvider,Q as setInherited,de as setInheritedMap,fe as setOverride};
1
+ import{existsSync as v,readFileSync as x,readdirSync as E}from"node:fs";import M from"node:path";import{atomicWriteFileSync as k}from"../utils/file-utils.js";import{getAgentOwner as S}from"./agent-ownership.js";import{getUserCapabilityAgentFile as L,getUserCapabilityDefaultsFile as W,scopeEquals as C}from"./user-scope.js";const b=["skills","mcp","plugins"];function d(r,e){if(e){const t=S(e);if(t)return t}return r}function m(r,e){if(!e)return;const t=S(e);if(t&&!C(t,r))throw new Error("agent-ownership-mismatch")}function w(r,e){return W(r,e)}function p(r,e,t){return L(r,e,t)}const h=new Map;function G(r,e){e?h.set(r,e):h.delete(r)}function g(r,e,t){const n=h.get(r);if(n)try{return n(t)[e]}catch{return}}function j(r){try{if(!v(r))return{};const e=JSON.parse(x(r,"utf8"));return!e||typeof e!="object"||Array.isArray(e)?{}:e}catch{return{}}}function D(r,e){k(r,`${JSON.stringify(e,null,2)}
2
+ `)}function l(r,e){const t=e[r];if(!t||typeof t!="object"||Array.isArray(t))return{};const n={};for(const[i,o]of Object.entries(t))i.trim()&&typeof o=="boolean"&&(n[i.trim()]=o);return n}function P(r,e,t,n){const i={...l(e,r)};n==null?delete i[t]:i[t]=n,r[e]=i}function V(r){try{if(!v(r))return{};const e=JSON.parse(x(r,"utf8"));return!e||typeof e!="object"||Array.isArray(e)?{}:e}catch{return{}}}function a(r,e,t){const n=V(r),i=n[t];return i&&typeof i=="object"&&!Array.isArray(i)?l(e,i):t==="overrides"?l(e,n):{}}function J(r,e,t,n){const i={};for(const o of["overrides","inherited"]){const s=o===t?n:a(r,e,o),f={};for(const u of b){const c=u===e?s:a(r,u,o);f[u]=c}i[o]=f}D(r,i)}function y(r,e){return r?l(e,j(w(r,e))):{}}function F(r,e,t){if(!e)return{};const n=d(r,e);return n?a(p(n,t,e),t,"overrides"):{}}function N(r,e,t){if(!e)return{};const n=d(r,e);return n?a(p(n,t,e),t,"inherited"):{}}function T(r,e,t,n,i){const o=d(r,e),f=F(o,e,t)[n];if(f!==void 0)return f;const c=N(o,e,t)[n];if(c!==void 0)return c;const A=y(o,t)[n];if(A!==void 0)return A;if(i!==void 0)return i;const O=g(t,n,o);return O!==void 0?O:!1}function H(r,e,t,n){const i=d(r,e);return F(i,e,t)[n]!==void 0?"agent":N(i,e,t)[n]!==void 0?"inherited":y(i,t)[n]!==void 0?"bridge":g(t,n,i)!==void 0?"deployed":"default"}function U(r,e,t,n){const i=w(r,e),o=j(i),s=l(e,o);P(o,e,t,n);const f=l(e,o);return JSON.stringify(s)===JSON.stringify(f)?!1:(D(i,o),!0)}function K(r,e,t,n,i){if(!e)return!1;m(r,e);const o=d(r,e)??r,s=p(o,t,e),f=a(s,t,"overrides"),u={...f};return i==null?delete u[n]:u[n]=i,JSON.stringify(f)===JSON.stringify(u)?!1:(J(s,t,"overrides",u),!0)}function Y(r,e,t,n){if(!e)return!1;m(r,e);const i=d(r,e)??r,o=p(i,t,e),s=a(o,t,"inherited"),f={};if(n&&typeof n=="object"&&!Array.isArray(n))for(const[u,c]of Object.entries(n))u.trim()&&typeof c=="boolean"&&(f[u.trim()]=c);return JSON.stringify(s)===JSON.stringify(f)?!1:(J(o,t,"inherited",f),!0)}function Q(r,e){if(!r)return[];const t=M.dirname(p(r,e,"_probe"));try{return v(t)?E(t).filter(n=>n.endsWith(".json")&&!n.startsWith(".")).map(n=>n.slice(0,-5)):[]}catch{return[]}}function X(r,e){const t=h.get(e);if(!t)return 0;let n=0;const i=y(r,e),o=t(r)??{};for(const s of Object.keys(o))s in i||o[s]===!0&&(U(r,e,s,!1),n++);return n}function Z(r,e){return Object.keys(y(r,e)).length>0}function I(r,e,t,n){const i={};for(const o of n)i[o]=T(r,e,t,o);return i}function ee(r,e,t){const n=[];if(!e)return n;for(const i of b){const o=t&&typeof t=="object"?t[i]??{}:{};Y(r,e,i,o)&&n.push(i)}return n}export{b as CAPABILITY_TYPES,y as getDefaults,T as getEffective,I as getEffectiveMap,H as getEffectiveSource,N as getInherited,F as getOverrides,Z as hasAnyDefault,Q as listOverrideAgents,X as reconcileDefaultsFromDeployed,U as setDefault,G as setDeployedDefaultsProvider,Y as setInherited,ee as setInheritedMap,K as setOverride};
3
3
 
@@ -1,2 +1,2 @@
1
- import l from"node:fs/promises";import M from"node:path";import{getBridgeInstanceConfigFile as D,getBridgeInstanceMcpExtraFile as _,getBridgeTemplateConfigFile as U}from"../config.js";import{getInstanceAiConfigDebugLogger as k}from"../utils/instance-ai-config-debug-logger.js";import{getAgentOwner as K}from"./agent-ownership.js";import{McpDeployManager as P}from"./mcp-deploy.js";import{injectEffectiveEnvIntoMcpServers as x,isBuiltinMcpName as N}from"./mcp-env-injector.js";import{getPanelEnvVars as j,getAgentMeta as B}from"./panel-env.js";import{getUserAiConfigFile as J,isLegacyFallbackDisabled as T}from"./user-scope.js";const $=new Set(["apiKey","api_key","apikey","key","secret","token","password"]);function Y(e){const r={...e};for(const t of Object.keys(r))if($.has(t)){const a=r[t];typeof a=="string"&&a.length>0&&(r[t]=a.length>8?`${a.slice(0,4)}...${a.slice(-4)}`:"***")}else typeof r[t]=="object"&&r[t]!==null&&(r[t]=Y(r[t]));return r}function V(){return{...process.env.ACODE_MODEL?{model:process.env.ACODE_MODEL}:{},...process.env.ACODE_BASE_URL?{baseURL:process.env.ACODE_BASE_URL}:{},...process.env.ACODE_API_KEY?{apiKey:process.env.ACODE_API_KEY}:{},...process.env.ACODE_EFFORT?{effort:process.env.ACODE_EFFORT}:{}}}async function H(e){try{const r=await l.readFile(e,"utf-8"),o=JSON.parse(r).provider?.default,n=o?.options;return{...o?.model?{model:o.model}:{},...n?.baseURL||n?.baseUrl?{baseURL:n.baseURL||n.baseUrl}:{},...n?.apiKey?{apiKey:n.apiKey}:{}}}catch{return{}}}function L(e,r,t,a){return r!==void 0?"api":t!==void 0?"env":a!==void 0?"file":"default"}function w(e){return _(e)}async function q(e){try{const r=await l.readFile(w(e),"utf-8"),t=JSON.parse(r);return t.servers&&typeof t.servers=="object"?t.servers:{}}catch{return{}}}function ae(e){return w(e)}async function ne(e){const r=K(e.agentId);let a=r?J(r):"";if(!a)a=U();else try{await l.access(a)}catch{T()||(a=U())}const o=D(e.agentId),n=e.apiOverrides??{},s=V(),f=await H(a),m=n.model??s.model??f.model,v=n.baseURL??s.baseURL??f.baseURL,b=n.apiKey??s.apiKey??f.apiKey,E=n.effort??s.effort,g={};m&&(g.model=m),v&&(g.baseURL=v),b&&(g.apiKey=b),E&&(g.effort=E);const S={model:L("model",n.model,s.model,f.model),baseURL:L("baseURL",n.baseURL,s.baseURL,f.baseURL),apiKey:L("apiKey",n.apiKey,s.apiKey,f.apiKey),effort:L("effort",n.effort,s.effort,void 0)},I=k();try{await l.mkdir(M.dirname(o),{recursive:!0});let d={};try{const i=await l.readFile(a,"utf-8");d=JSON.parse(i)}catch{}const c=JSON.parse(JSON.stringify(d)),A=c.provider??{},C=A.default??{},p=C.options??{};m&&(p.model=m),v&&(p.baseURL=v),b&&(p.apiKey=b),E&&(p.effort=E),C.options=p,A.default=C,c.provider=A;try{const i=c.mcpServers??{},R=K(e.agentId),u=R?P.forScope(R):null,O=u?u.resolveEnabledMcp(e.agentId,i):i,F=await q(e.agentId);for(const[y,h]of Object.entries(F))N(y)||(O[y]=h);x(O,j(e.agentId),{resolvePackageDir:y=>u&&u.isPackageHealthy(y)?u.packageDir(y):void 0,agentMeta:B(e.agentId)}),c.mcpServers=O}catch(i){I.log({level:"error",category:"apply",message:`MCP \u80FD\u529B\u8FC7\u6EE4/\u79C1\u6709\u5408\u5E76\u5931\u8D25\uFF08fail-open\uFF0C\u4FDD\u6301\u539F\u914D\u7F6E\uFF09: ${i instanceof Error?i.message:String(i)}`,source:"bridge",agentId:e.agentId,sessionId:e.sessionId})}await l.writeFile(o,JSON.stringify(c,null,2),"utf-8"),I.log({level:"info",category:"apply",message:"per-instance acode.json \u5DF2\u5199\u5165",source:"bridge",agentId:e.agentId,sessionId:e.sessionId,details:{perInstanceConfigPath:o,source:S}})}catch(d){const c=d instanceof Error?d.message:String(d);I.log({level:"error",category:"apply",message:`per-instance acode.json \u5199\u5165\u5931\u8D25: ${c}`,source:"bridge",agentId:e.agentId})}return{instanceConfig:{config:g,source:S},perInstanceConfigPath:o}}export{ae as getAgentMcpExtraFilePath,ne as prepareAcodeInstanceConfig,Y as redactForLog};
1
+ import u from"node:fs/promises";import M from"node:path";import{getBridgeInstanceConfigFile as F,getBridgeInstanceMcpExtraFile as _}from"../config.js";import{getInstanceAiConfigDebugLogger as D}from"../utils/instance-ai-config-debug-logger.js";import{getAgentOwner as U}from"./agent-ownership.js";import{McpDeployManager as h}from"./mcp-deploy.js";import{injectEffectiveEnvIntoMcpServers as k,isBuiltinMcpName as P}from"./mcp-env-injector.js";import{getPanelEnvVars as x,getAgentMeta as N}from"./panel-env.js";import{getUserAiConfigFile as j}from"./user-scope.js";const J=new Set(["apiKey","api_key","apikey","key","secret","token","password"]);function B(e){const r={...e};for(const t of Object.keys(r))if(J.has(t)){const o=r[t];typeof o=="string"&&o.length>0&&(r[t]=o.length>8?`${o.slice(0,4)}...${o.slice(-4)}`:"***")}else typeof r[t]=="object"&&r[t]!==null&&(r[t]=B(r[t]));return r}function $(){return{...process.env.ACODE_MODEL?{model:process.env.ACODE_MODEL}:{},...process.env.ACODE_BASE_URL?{baseURL:process.env.ACODE_BASE_URL}:{},...process.env.ACODE_API_KEY?{apiKey:process.env.ACODE_API_KEY}:{},...process.env.ACODE_EFFORT?{effort:process.env.ACODE_EFFORT}:{}}}async function T(e){try{const r=await u.readFile(e,"utf-8"),a=JSON.parse(r).provider?.default,n=a?.options;return{...a?.model?{model:a.model}:{},...n?.baseURL||n?.baseUrl?{baseURL:n.baseURL||n.baseUrl}:{},...n?.apiKey?{apiKey:n.apiKey}:{}}}catch{return{}}}function E(e,r,t,o){return r!==void 0?"api":t!==void 0?"env":o!==void 0?"file":"default"}function C(e){return _(e)}async function Y(e){try{const r=await u.readFile(C(e),"utf-8"),t=JSON.parse(r);return t.servers&&typeof t.servers=="object"?t.servers:{}}catch{return{}}}function ee(e){return C(e)}async function re(e){const r=U(e.agentId),t=r?j(r):"",o=F(e.agentId),a=e.apiOverrides??{},n=$(),c=await T(t),y=a.model??n.model??c.model,m=a.baseURL??n.baseURL??c.baseURL,v=a.apiKey??n.apiKey??c.apiKey,b=a.effort??n.effort,d={};y&&(d.model=y),m&&(d.baseURL=m),v&&(d.apiKey=v),b&&(d.effort=b);const A={model:E("model",a.model,n.model,c.model),baseURL:E("baseURL",a.baseURL,n.baseURL,c.baseURL),apiKey:E("apiKey",a.apiKey,n.apiKey,c.apiKey),effort:E("effort",a.effort,n.effort,void 0)},I=D();try{await u.mkdir(M.dirname(o),{recursive:!0});let f={};try{const s=await u.readFile(t,"utf-8");f=JSON.parse(s)}catch{}const i=JSON.parse(JSON.stringify(f)),L=i.provider??{},O=L.default??{},p=O.options??{};y&&(p.model=y),m&&(p.baseURL=m),v&&(p.apiKey=v),b&&(p.effort=b),O.options=p,L.default=O,i.provider=L;try{const s=i.mcpServers??{},R=U(e.agentId),l=R?h.forScope(R):null,S=l?l.resolveEnabledMcp(e.agentId,s):s,K=await Y(e.agentId);for(const[g,w]of Object.entries(K))P(g)||(S[g]=w);k(S,x(e.agentId),{resolvePackageDir:g=>l&&l.isPackageHealthy(g)?l.packageDir(g):void 0,agentMeta:N(e.agentId)}),i.mcpServers=S}catch(s){I.log({level:"error",category:"apply",message:`MCP \u80FD\u529B\u8FC7\u6EE4/\u79C1\u6709\u5408\u5E76\u5931\u8D25\uFF08fail-open\uFF0C\u4FDD\u6301\u539F\u914D\u7F6E\uFF09: ${s instanceof Error?s.message:String(s)}`,source:"bridge",agentId:e.agentId,sessionId:e.sessionId})}await u.writeFile(o,JSON.stringify(i,null,2),"utf-8"),I.log({level:"info",category:"apply",message:"per-instance acode.json \u5DF2\u5199\u5165",source:"bridge",agentId:e.agentId,sessionId:e.sessionId,details:{perInstanceConfigPath:o,source:A}})}catch(f){const i=f instanceof Error?f.message:String(f);I.log({level:"error",category:"apply",message:`per-instance acode.json \u5199\u5165\u5931\u8D25: ${i}`,source:"bridge",agentId:e.agentId})}return{instanceConfig:{config:d,source:A},perInstanceConfigPath:o}}export{ee as getAgentMcpExtraFilePath,re as prepareAcodeInstanceConfig,B as redactForLog};
2
2
 
@@ -114,6 +114,15 @@ export declare const EMAIL_FEATURE_KEY = "email";
114
114
 
115
115
 
116
116
 
117
+ export declare const COLLABORATION_VOICE_FEATURE_KEY = "collaboration.voice";
118
+
119
+
120
+
121
+
122
+
123
+
124
+
125
+
117
126
 
118
127
  export declare const GROUP_KEY_TO_FEATURE: ReadonlyMap<string, string>;
119
128
 
@@ -1,2 +1,2 @@
1
- import{getAgentOwner as P}from"./agent-ownership.js";import{getEffective as N,hasAnyDefault as D}from"./capability-config.js";const j=new Set(["disabled","collapsed","expanded"]);function v(e){if(e===!0)return"expanded";if(e===!1)return"disabled";if(typeof e=="string"&&j.has(e))return e}const b={},se="desktop",I="browser",S="agentSys.launchItem",x="agentSys.hire",O="agentSys.skillInstall",R="agentSys.abilityDev",z="pencil",G="draw",H="office",k="collaboration",h="collaboration.task",m="collaboration.meeting",L="collaboration.debug",U="collaboration.fileHistory",J="email",V=new Set,W=new Set([I,z,G,H,S,x,O,R,h,m,L,U,J]),X=[["agentSys","agentSys."],[k,"collaboration."]],q=new Map([["task",h],["meeting",m],["debug",L],["fileHistory",U],["launch",S],["hire",x],["abilityMarket",O],["abilityDev",R]]);function le(e){return q.get(e)??e}function w(e){for(const[t,n]of X)if(e.startsWith(n))return t}const Q=new Set,y=new Map,_=new Map,a=new Map,Z=["fileReadOutside","commandExecution","fileModification","fileModificationOutside"],$=new Set(["allow","ask","deny"]);function ee(e){if(typeof e!="object"||e===null||Array.isArray(e))return null;const t=e,n={};let o=!1;for(const r of Z){const i=t[r];typeof i=="string"&&$.has(i)?(n[r]=i,o=!0):n[r]="allow"}return o?n:null}function K(e){if(e==null)return{...b};let t=e;if(typeof e=="string")try{t=JSON.parse(e)}catch{t=null}if(typeof t!="object"||t===null||Array.isArray(t))return{...b};const n={};for(const[o,r]of Object.entries(t)){if(Q.has(o))continue;const i=v(r);i!==void 0&&(n[o]=i)}return n}function ue(e,t){if(!e)return;y.set(e,K(t));let n=t;if(typeof t=="string")try{n=JSON.parse(t)}catch{n=null}if(typeof n=="object"&&n!==null&&!Array.isArray(n)){const o=ee(n.toolPermissions);o?a.set(e,o):a.delete(e)}else a.delete(e)}function te(e){return y.get(e)??{...b}}function ce(e,t){if(!e)return;if(t==null){_.delete(e);return}const n=K(t);if(Object.keys(n).length===0){_.delete(e);return}_.set(e,n)}function ne(e){return _.get(e)??{}}function oe(e,t){const n=te(e),o=ne(e),r=w(t);if(r&&(n[r]??o[r])==="disabled")return"disabled";const i=n[t]??o[t];return i!==void 0?i:V.has(t)?"expanded":W.has(t)?"collapsed":"disabled"}function fe(e,t){return oe(e,t)!=="disabled"}function ae(e){y.delete(e),a.delete(e),f.delete(e),T.delete(e)}function pe(e){return a.get(e)??null}function Ee(e){return a.get(e)??{fileReadOutside:"allow",commandExecution:"allow",fileModification:"allow",fileModificationOutside:"allow"}}const M=["skills","mcp","plugins"],f=new Map,T=new Map;function Y(e){if(typeof e!="object"||e===null||Array.isArray(e))return;const t={};for(const[n,o]of Object.entries(e))n.trim()&&typeof o=="boolean"&&(t[n.trim()]=o);return t}function Ae(e,t){if(!e)return;if(t==null){f.delete(e);return}let n=t;if(typeof t=="string")try{n=JSON.parse(t)}catch{n=null}if(typeof n!="object"||n===null||Array.isArray(n)){f.delete(e);return}const o=n,r={};let i=!1;for(const A of M){const l=Y(o[A]);l&&(r[A]=l,i=!0)}i?f.set(e,r):f.delete(e);const s=o.plugins,u={};let E=!1;if(typeof s=="object"&&s!==null&&!Array.isArray(s))for(const[A,l]of Object.entries(s)){const d=A.trim();if(d){if(typeof l=="boolean"){const c=r.plugins??{};c[d]=l,r.plugins=c,i=!0;continue}if(l!==null&&typeof l=="object"&&!Array.isArray(l)){const c=l,B=c.enabled!==!1,g=typeof c.url=="string"?c.url:void 0,C=typeof c.sha256=="string"?c.sha256:void 0,F=r.plugins??{};F[d]=B,r.plugins=F,i=!0,g&&(u[d]={url:g,sha256:C},E=!0)}}}E?T.set(e,u):T.delete(e)}function de(e){return f.get(e)??null}const p=new Map;function ye(e,t){if(!e)return;if(t==null){p.delete(e);return}let n=t;if(typeof t=="string")try{n=JSON.parse(t)}catch{n=null}if(typeof n!="object"||n===null||Array.isArray(n)){p.delete(e);return}const o=n,r={};let i=!1;for(const s of M){const u=Y(o[s]);u&&(r[s]=u,i=!0)}i?p.set(e,r):p.delete(e)}function _e(e){return p.get(e)??null}function Te(e){return T.get(e)??null}function be(e,t,n){const o=P(e);if(D(o,t))return N(o,e,t,n);const i=p.get(e)?.[t]?.[n];if(i!==void 0)return i;const s=f.get(e);if(!s)return!0;const u=s[t];if(!u)return!0;const E=u[n];return E===void 0?!0:E}function ge(){return y.size}export{R as ABILITY_DEV_FEATURE_KEY,I as BROWSER_FEATURE_KEY,M as CAPABILITY_TYPES,L as COLLABORATION_DEBUG_FEATURE_KEY,k as COLLABORATION_FEATURE_KEY,U as COLLABORATION_FILE_HISTORY_FEATURE_KEY,m as COLLABORATION_MEETING_FEATURE_KEY,h as COLLABORATION_TASK_FEATURE_KEY,se as DESKTOP_FEATURE_KEY,G as DRAW_FEATURE_KEY,J as EMAIL_FEATURE_KEY,q as GROUP_KEY_TO_FEATURE,x as HIRE_FEATURE_KEY,S as LAUNCH_ITEM_FEATURE_KEY,H as OFFICE_FEATURE_KEY,z as PENCIL_FEATURE_KEY,O as SKILL_INSTALL_FEATURE_KEY,ae as clearAgentFeatures,de as getAgentCapabilities,_e as getAgentCapabilitiesInherited,te as getAgentFeatures,ne as getAgentInheritedFeatures,Te as getAgentPluginSources,pe as getAgentToolPermissions,oe as getFeatureState,ge as instanceFeaturesCacheSize,be as isCapabilityEnabled,fe as isFeatureEnabled,v as normalizeFeatureState,Ee as resolveAgentToolPermissions,le as resolveGroupFeatureKey,Ae as setAgentCapabilities,ye as setAgentCapabilitiesInherited,ue as setAgentFeatures,ce as setAgentInheritedFeatures};
1
+ import{getAgentOwner as P}from"./agent-ownership.js";import{getEffective as D,hasAnyDefault as v}from"./capability-config.js";const j=new Set(["disabled","collapsed","expanded"]);function I(e){if(e===!0)return"expanded";if(e===!1)return"disabled";if(typeof e=="string"&&j.has(e))return e}const b={},le="desktop",z="browser",F="agentSys.launchItem",x="agentSys.hire",S="agentSys.skillInstall",R="agentSys.abilityDev",G="pencil",H="draw",k="office",V="collaboration",L="collaboration.task",h="collaboration.meeting",m="collaboration.debug",U="collaboration.fileHistory",J="email",K="collaboration.voice",W=new Set,X=new Set([z,G,H,k,F,x,S,R,L,h,m,U,J,K]),q=[["agentSys","agentSys."],[V,"collaboration."]],w=new Map([["task",L],["meeting",h],["debug",m],["fileHistory",U],["voice",K],["launch",F],["hire",x],["abilityMarket",S],["abilityDev",R]]);function ue(e){return w.get(e)??e}function Q(e){for(const[t,n]of q)if(e.startsWith(n))return t}const Z=new Set,y=new Map,_=new Map,a=new Map,$=["fileReadOutside","commandExecution","fileModification","fileModificationOutside"],ee=new Set(["allow","ask","deny"]);function te(e){if(typeof e!="object"||e===null||Array.isArray(e))return null;const t=e,n={};let o=!1;for(const r of $){const i=t[r];typeof i=="string"&&ee.has(i)?(n[r]=i,o=!0):n[r]="allow"}return o?n:null}function Y(e){if(e==null)return{...b};let t=e;if(typeof e=="string")try{t=JSON.parse(e)}catch{t=null}if(typeof t!="object"||t===null||Array.isArray(t))return{...b};const n={};for(const[o,r]of Object.entries(t)){if(Z.has(o))continue;const i=I(r);i!==void 0&&(n[o]=i)}return n}function ce(e,t){if(!e)return;y.set(e,Y(t));let n=t;if(typeof t=="string")try{n=JSON.parse(t)}catch{n=null}if(typeof n=="object"&&n!==null&&!Array.isArray(n)){const o=te(n.toolPermissions);o?a.set(e,o):a.delete(e)}else a.delete(e)}function ne(e){return y.get(e)??{...b}}function fe(e,t){if(!e)return;if(t==null){_.delete(e);return}const n=Y(t);if(Object.keys(n).length===0){_.delete(e);return}_.set(e,n)}function oe(e){return _.get(e)??{}}function re(e,t){const n=ne(e),o=oe(e),r=Q(t);if(r&&(n[r]??o[r])==="disabled")return"disabled";const i=n[t]??o[t];return i!==void 0?i:W.has(t)?"expanded":X.has(t)?"collapsed":"disabled"}function ae(e,t){return re(e,t)!=="disabled"}function pe(e){y.delete(e),a.delete(e),f.delete(e),T.delete(e)}function Ee(e){return a.get(e)??null}function Ae(e){return a.get(e)??{fileReadOutside:"allow",commandExecution:"allow",fileModification:"allow",fileModificationOutside:"allow"}}const C=["skills","mcp","plugins"],f=new Map,T=new Map;function M(e){if(typeof e!="object"||e===null||Array.isArray(e))return;const t={};for(const[n,o]of Object.entries(e))n.trim()&&typeof o=="boolean"&&(t[n.trim()]=o);return t}function de(e,t){if(!e)return;if(t==null){f.delete(e);return}let n=t;if(typeof t=="string")try{n=JSON.parse(t)}catch{n=null}if(typeof n!="object"||n===null||Array.isArray(n)){f.delete(e);return}const o=n,r={};let i=!1;for(const A of C){const l=M(o[A]);l&&(r[A]=l,i=!0)}i?f.set(e,r):f.delete(e);const s=o.plugins,u={};let E=!1;if(typeof s=="object"&&s!==null&&!Array.isArray(s))for(const[A,l]of Object.entries(s)){const d=A.trim();if(d){if(typeof l=="boolean"){const c=r.plugins??{};c[d]=l,r.plugins=c,i=!0;continue}if(l!==null&&typeof l=="object"&&!Array.isArray(l)){const c=l,B=c.enabled!==!1,O=typeof c.url=="string"?c.url:void 0,N=typeof c.sha256=="string"?c.sha256:void 0,g=r.plugins??{};g[d]=B,r.plugins=g,i=!0,O&&(u[d]={url:O,sha256:N},E=!0)}}}E?T.set(e,u):T.delete(e)}function ye(e){return f.get(e)??null}const p=new Map;function _e(e,t){if(!e)return;if(t==null){p.delete(e);return}let n=t;if(typeof t=="string")try{n=JSON.parse(t)}catch{n=null}if(typeof n!="object"||n===null||Array.isArray(n)){p.delete(e);return}const o=n,r={};let i=!1;for(const s of C){const u=M(o[s]);u&&(r[s]=u,i=!0)}i?p.set(e,r):p.delete(e)}function Te(e){return p.get(e)??null}function be(e){return T.get(e)??null}function Oe(e,t,n){const o=P(e);if(v(o,t))return D(o,e,t,n);const i=p.get(e)?.[t]?.[n];if(i!==void 0)return i;const s=f.get(e);if(!s)return!0;const u=s[t];if(!u)return!0;const E=u[n];return E===void 0?!0:E}function ge(){return y.size}export{R as ABILITY_DEV_FEATURE_KEY,z as BROWSER_FEATURE_KEY,C as CAPABILITY_TYPES,m as COLLABORATION_DEBUG_FEATURE_KEY,V as COLLABORATION_FEATURE_KEY,U as COLLABORATION_FILE_HISTORY_FEATURE_KEY,h as COLLABORATION_MEETING_FEATURE_KEY,L as COLLABORATION_TASK_FEATURE_KEY,K as COLLABORATION_VOICE_FEATURE_KEY,le as DESKTOP_FEATURE_KEY,H as DRAW_FEATURE_KEY,J as EMAIL_FEATURE_KEY,w as GROUP_KEY_TO_FEATURE,x as HIRE_FEATURE_KEY,F as LAUNCH_ITEM_FEATURE_KEY,k as OFFICE_FEATURE_KEY,G as PENCIL_FEATURE_KEY,S as SKILL_INSTALL_FEATURE_KEY,pe as clearAgentFeatures,ye as getAgentCapabilities,Te as getAgentCapabilitiesInherited,ne as getAgentFeatures,oe as getAgentInheritedFeatures,be as getAgentPluginSources,Ee as getAgentToolPermissions,re as getFeatureState,ge as instanceFeaturesCacheSize,Oe as isCapabilityEnabled,ae as isFeatureEnabled,I as normalizeFeatureState,Ae as resolveAgentToolPermissions,ue as resolveGroupFeatureKey,de as setAgentCapabilities,_e as setAgentCapabilitiesInherited,ce as setAgentFeatures,fe as setAgentInheritedFeatures};
2
2
 
@@ -7,6 +7,10 @@
7
7
 
8
8
 
9
9
 
10
+
11
+
12
+ export declare const SESSION_COOKIE_MAX_AGE_SEC: number;
13
+
10
14
  export declare function createSession(): string;
11
15
 
12
16
  export declare function validateSession(token: string | undefined | null): boolean;
@@ -1,2 +1,2 @@
1
- import{randomUUID as _,randomBytes as $,scryptSync as S,timingSafeEqual as I}from"node:crypto";import{existsSync as f,mkdirSync as w,readFileSync as u,writeFileSync as y}from"node:fs";import{homedir as v}from"node:os";import g from"node:path";import{getAutoRegisterConfigFilePath as D}from"../config.js";import{runExclusiveConfigWrite as x}from"../utils/config-write-queue.js";import{logger as i}from"../utils/logger.js";const C=24*60*60*1e3,M=60*60*1e3,a=new Map;let p=null;function F(){p||(p=setInterval(()=>{const e=Date.now();let t=0;for(const[n,o]of a)e-o.lastUsedAt>C&&(a.delete(n),t++);t>0&&i.info(`[panel-auth] \u5DF2\u6E05\u7406 ${t} \u4E2A\u8FC7\u671F\u9762\u677F\u4F1A\u8BDD`)},M),p.unref())}function K(){F();const e=_(),t=Date.now();return a.set(e,{token:e,createdAt:t,lastUsedAt:t}),e}function ee(e){if(!e)return!1;const t=a.get(e);if(!t)return!1;const n=Date.now();return n-t.lastUsedAt>C?(a.delete(e),!1):(t.lastUsedAt=n,!0)}function te(e){a.delete(e)}function ne(){return Array.from(a.values())}function re(){return a.size}const P="scrypt$",A=64;function m(e){return e.startsWith(P)}function k(e){const t=$(16),n=S(e,t,A);return`${P}${t.toString("hex")}$${n.toString("hex")}`}function J(e,t){if(e.length!==t.length)return!1;try{return I(Buffer.from(e,"hex"),Buffer.from(t,"hex"))}catch{return!1}}function U(e,t){if(m(t)){const n=t.split("$");if(n.length!==3)return!1;const o=Buffer.from(n[1],"hex");if(o.length===0)return!1;const s=S(e,o,A).toString("hex");return J(s,n[2])}return e===t}const T=5,h=15*60*1e3,L=10*60*1e3,c=new Map;function R(){const e=Date.now();for(const[t,n]of c)n.lockedUntil<=e&&e-n.windowStart>h&&c.delete(t)}function oe(e){const t=Date.now(),n=c.get(e);return n?n.lockedUntil>t?{allowed:!1,retryAfterSec:Math.ceil((n.lockedUntil-t)/1e3)}:(t-n.windowStart>h&&c.delete(e),{allowed:!0,retryAfterSec:0}):{allowed:!0,retryAfterSec:0}}function se(e){const t=Date.now();R();const n=c.get(e);if(!n||t-n.windowStart>h){c.set(e,{failures:1,windowStart:t,lockedUntil:0});return}n.failures+=1,n.failures>=T&&(n.lockedUntil=t+L,i.warn(`[panel-auth] \u767B\u5F55\u5931\u8D25\u6B21\u6570\u8FC7\u591A\uFF0C\u5DF2\u4E34\u65F6\u9501\u5B9A\u6765\u6E90 ${e}\uFF08${L/6e4} \u5206\u949F\uFF09`))}function ae(e){c.delete(e)}let l=null;function d(){return D()}function B(){const e=d();if(!f(e))return null;try{const t=u(e,"utf-8"),n=JSON.parse(t),o=String(n.panelUsername||"").trim(),s=String(n.panelPassword||"").trim();if(o&&s)return{username:o,password:s}}catch{}return null}function N(){if(l)return l;const e=B();return e?(l=e,e):(q(),l={username:"root",password:"root"},l)}function ie(e,t){const n=N();return e!==n.username||!U(t,n.password)?!1:(!m(n.password)&&H()&&W(n.username,t).then(()=>{i.info("[panel-auth] \u5DF2\u5C06\u660E\u6587\u9762\u677F\u5BC6\u7801\u81EA\u52A8\u8FC1\u79FB\u4E3A scrypt \u54C8\u5E0C\u5B58\u50A8")}).catch(()=>{}),!0)}function O(){l=null}function H(){const e=d();if(!f(e))return!1;try{const t=u(e,"utf-8"),n=JSON.parse(t);return!!(n.panelUsername&&n.panelPassword)}catch{return!1}}function ce(){const e=N();return e.username==="root"&&U("root",e.password)}async function W(e,t){const n=d();O(),await x(n,()=>{const o=g.dirname(n);let s={};if(f(n))try{s=JSON.parse(u(n,"utf-8"))}catch{}s.panelUsername=e,s.panelPassword=m(t)?t:k(t);try{w(o,{recursive:!0})}catch{}y(n,JSON.stringify(s,null,2),"utf-8"),i.info("[panel-auth] \u9762\u677F\u51ED\u636E\u5DF2\u66F4\u65B0")})}let E=!1;function G(){return g.join(v(),".aws-bridge","config.json")}async function j(){const e=d(),t=G();if(t===e||!f(t))return!1;let n="",o="";try{const r=JSON.parse(u(t,"utf-8"));n=String(r.panelUsername??"").trim(),o=String(r.panelPassword??"").trim()}catch(r){return i.warn(`[panel-auth] \u65E7\u914D\u7F6E\u4E0D\u53EF\u89E3\u6790\uFF0C\u8DF3\u8FC7\u9762\u677F\u51ED\u636E\u8FC1\u79FB: ${r instanceof Error?r.message:String(r)}`),!1}if(!n||!o)return!1;let s=!1;return await x(e,()=>{let r={};if(f(e))try{r=JSON.parse(u(e,"utf-8"))}catch{r={}}if(!(String(r.panelUsername??"").trim()&&String(r.panelPassword??"").trim())){r.panelUsername=n,r.panelPassword=o;try{w(g.dirname(e),{recursive:!0})}catch{}y(e,JSON.stringify(r,null,2),"utf-8"),s=!0,i.info(`[panel-auth] \u5DF2\u4ECE ${t} \u8FC1\u79FB\u9762\u677F\u51ED\u636E`)}}),s}function q(){E||(E=!0,j().then(e=>{e&&O()}).catch(e=>{i.warn(`[panel-auth] \u65E7\u9762\u677F\u51ED\u636E\u8FC1\u79FB\u5931\u8D25\uFF08\u5FFD\u7565\uFF09: ${e instanceof Error?e.message:String(e)}`)}))}export{oe as checkLoginAllowed,O as clearCredentialsCache,K as createSession,te as destroySession,re as getActiveSessionCount,ne as getAllSessions,N as getPanelCredentials,H as hasConfiguredCredentials,ce as isDefaultCredentials,j as migrateLegacyPanelCredentials,se as recordLoginFailure,ae as recordLoginSuccess,W as setPanelCredentials,ie as validateCredentials,ee as validateSession};
1
+ import{randomUUID as T,randomBytes as b,scryptSync as E,timingSafeEqual as j}from"node:crypto";import{existsSync as f,mkdirSync as h,readFileSync as l,writeFileSync as w}from"node:fs";import{homedir as H}from"node:os";import u from"node:path";import{getAutoRegisterConfigFilePath as O}from"../config.js";import{runExclusiveConfigWrite as L}from"../utils/config-write-queue.js";import{logger as a}from"../utils/logger.js";const y=30*24*60*60*1e3,fe=30*24*60*60,R=60*60*1e3,B=500,i=new Map;let A=null,p=null;function _(){return u.join(u.dirname(O()),"panel-sessions.json")}function G(){const e=_();if(f(e))try{const t=JSON.parse(l(e,"utf-8")),n=Date.now();let r=0;if(t.sessions&&typeof t.sessions=="object")for(const[o,s]of Object.entries(t.sessions)){const N=Number(s?.createdAt),m=Number(s?.lastUsedAt);typeof o!="string"||!Number.isFinite(N)||!Number.isFinite(m)||n-m>y||(i.set(o,{token:o,createdAt:N,lastUsedAt:m}),r++)}r>0&&a.info(`[panel-auth] \u5DF2\u4ECE\u78C1\u76D8\u6062\u590D ${r} \u4E2A\u9762\u677F\u4F1A\u8BDD`)}catch(t){a.warn(`[panel-auth] \u9762\u677F\u4F1A\u8BDD\u6587\u4EF6\u4E0D\u53EF\u8BFB\uFF08\u5FFD\u7565\uFF09: ${t instanceof Error?t.message:String(t)}`)}}let x=!1;function C(){x||(x=!0,G())}function F(){const e=_();try{h(u.dirname(e),{recursive:!0});const t={version:1,sessions:Object.fromEntries(Array.from(i.values()).map(n=>[n.token,{createdAt:n.createdAt,lastUsedAt:n.lastUsedAt}]))};w(e,JSON.stringify(t,null,2),{encoding:"utf-8",mode:384})}catch(t){a.warn(`[panel-auth] \u9762\u677F\u4F1A\u8BDD\u843D\u76D8\u5931\u8D25\uFF08\u5FFD\u7565\uFF09: ${t instanceof Error?t.message:String(t)}`)}}function g(){p||(p=setTimeout(()=>{p=null,F()},B),p.unref())}function W(){A||(A=setInterval(()=>{const e=Date.now();let t=0;for(const[n,r]of i)e-r.lastUsedAt>y&&(i.delete(n),t++);t>0&&(a.info(`[panel-auth] \u5DF2\u6E05\u7406 ${t} \u4E2A\u8FC7\u671F\u9762\u677F\u4F1A\u8BDD`),g())},R),A.unref())}process.on("exit",()=>{x&&i.size>0&&F()});function le(){C(),W();const e=T(),t=Date.now();return i.set(e,{token:e,createdAt:t,lastUsedAt:t}),g(),e}function ue(e){if(!e)return!1;C();const t=i.get(e);if(!t)return!1;const n=Date.now();return n-t.lastUsedAt>y?(i.delete(e),g(),!1):(t.lastUsedAt=n,!0)}function de(e){C(),i.delete(e)&&g()}function pe(){return Array.from(i.values())}function ge(){return i.size}const $="scrypt$",I=64;function P(e){return e.startsWith($)}function X(e){const t=b(16),n=E(e,t,I);return`${$}${t.toString("hex")}$${n.toString("hex")}`}function Y(e,t){if(e.length!==t.length)return!1;try{return j(Buffer.from(e,"hex"),Buffer.from(t,"hex"))}catch{return!1}}function v(e,t){if(P(t)){const n=t.split("$");if(n.length!==3)return!1;const r=Buffer.from(n[1],"hex");if(r.length===0)return!1;const o=E(e,r,I).toString("hex");return Y(o,n[2])}return e===t}const q=5,U=15*60*1e3,D=10*60*1e3,c=new Map;function z(){const e=Date.now();for(const[t,n]of c)n.lockedUntil<=e&&e-n.windowStart>U&&c.delete(t)}function Se(e){const t=Date.now(),n=c.get(e);return n?n.lockedUntil>t?{allowed:!1,retryAfterSec:Math.ceil((n.lockedUntil-t)/1e3)}:(t-n.windowStart>U&&c.delete(e),{allowed:!0,retryAfterSec:0}):{allowed:!0,retryAfterSec:0}}function me(e){const t=Date.now();z();const n=c.get(e);if(!n||t-n.windowStart>U){c.set(e,{failures:1,windowStart:t,lockedUntil:0});return}n.failures+=1,n.failures>=q&&(n.lockedUntil=t+D,a.warn(`[panel-auth] \u767B\u5F55\u5931\u8D25\u6B21\u6570\u8FC7\u591A\uFF0C\u5DF2\u4E34\u65F6\u9501\u5B9A\u6765\u6E90 ${e}\uFF08${D/6e4} \u5206\u949F\uFF09`))}function he(e){c.delete(e)}let d=null;function S(){return O()}function V(){const e=S();if(!f(e))return null;try{const t=l(e,"utf-8"),n=JSON.parse(t),r=String(n.panelUsername||"").trim(),o=String(n.panelPassword||"").trim();if(r&&o)return{username:r,password:o}}catch{}return null}function M(){if(d)return d;const e=V();return e?(d=e,e):(te(),d={username:"root",password:"root"},d)}function we(e,t){const n=M();return e!==n.username||!v(t,n.password)?!1:(!P(n.password)&&K()&&Q(n.username,t).then(()=>{a.info("[panel-auth] \u5DF2\u5C06\u660E\u6587\u9762\u677F\u5BC6\u7801\u81EA\u52A8\u8FC1\u79FB\u4E3A scrypt \u54C8\u5E0C\u5B58\u50A8")}).catch(()=>{}),!0)}function k(){d=null}function K(){const e=S();if(!f(e))return!1;try{const t=l(e,"utf-8"),n=JSON.parse(t);return!!(n.panelUsername&&n.panelPassword)}catch{return!1}}function ye(){const e=M();return e.username==="root"&&v("root",e.password)}async function Q(e,t){const n=S();k(),await L(n,()=>{const r=u.dirname(n);let o={};if(f(n))try{o=JSON.parse(l(n,"utf-8"))}catch{}o.panelUsername=e,o.panelPassword=P(t)?t:X(t);try{h(r,{recursive:!0})}catch{}w(n,JSON.stringify(o,null,2),"utf-8"),a.info("[panel-auth] \u9762\u677F\u51ED\u636E\u5DF2\u66F4\u65B0")})}let J=!1;function Z(){return u.join(H(),".aws-bridge","config.json")}async function ee(){const e=S(),t=Z();if(t===e||!f(t))return!1;let n="",r="";try{const s=JSON.parse(l(t,"utf-8"));n=String(s.panelUsername??"").trim(),r=String(s.panelPassword??"").trim()}catch(s){return a.warn(`[panel-auth] \u65E7\u914D\u7F6E\u4E0D\u53EF\u89E3\u6790\uFF0C\u8DF3\u8FC7\u9762\u677F\u51ED\u636E\u8FC1\u79FB: ${s instanceof Error?s.message:String(s)}`),!1}if(!n||!r)return!1;let o=!1;return await L(e,()=>{let s={};if(f(e))try{s=JSON.parse(l(e,"utf-8"))}catch{s={}}if(!(String(s.panelUsername??"").trim()&&String(s.panelPassword??"").trim())){s.panelUsername=n,s.panelPassword=r;try{h(u.dirname(e),{recursive:!0})}catch{}w(e,JSON.stringify(s,null,2),"utf-8"),o=!0,a.info(`[panel-auth] \u5DF2\u4ECE ${t} \u8FC1\u79FB\u9762\u677F\u51ED\u636E`)}}),o}function te(){J||(J=!0,ee().then(e=>{e&&k()}).catch(e=>{a.warn(`[panel-auth] \u65E7\u9762\u677F\u51ED\u636E\u8FC1\u79FB\u5931\u8D25\uFF08\u5FFD\u7565\uFF09: ${e instanceof Error?e.message:String(e)}`)}))}export{fe as SESSION_COOKIE_MAX_AGE_SEC,Se as checkLoginAllowed,k as clearCredentialsCache,le as createSession,de as destroySession,ge as getActiveSessionCount,pe as getAllSessions,M as getPanelCredentials,K as hasConfiguredCredentials,ye as isDefaultCredentials,ee as migrateLegacyPanelCredentials,me as recordLoginFailure,he as recordLoginSuccess,Q as setPanelCredentials,we as validateCredentials,ue as validateSession};
2
2
 
@@ -8,36 +8,22 @@
8
8
 
9
9
 
10
10
 
11
- import type { PluginLoader } from "./plugin-loader.js";
12
11
  import type { SharedPluginEntry } from "./plugin-runtime.js";
13
12
  export declare class PluginDeploymentStore {
14
13
  private readonly rootDir;
15
14
  private readonly runtimeRootDir;
16
- private readonly loader;
17
-
18
- private readonly legacyRootDir?;
19
- constructor(rootDir: string, runtimeRootDir: string | undefined, loader: PluginLoader,
20
-
21
- legacyRootDir?: string | undefined);
15
+ constructor(rootDir: string, runtimeRootDir: string | undefined);
22
16
  deployedDir(): string;
23
17
  deployedManifestFile(): string;
24
18
 
25
- private legacyDeployedDir;
26
- private legacyDeployedManifestFile;
27
-
28
19
 
29
20
 
30
21
 
31
22
 
32
23
  deployedPluginDir(name: string): string;
33
24
 
34
- private legacySharedDir;
35
-
36
25
  deployedPluginHealthy(name: string): boolean;
37
26
 
38
- private legacyPluginHealthy;
39
-
40
-
41
27
 
42
28
 
43
29
  resolveDeployedSourceDir(name: string): string | null;
@@ -45,22 +31,10 @@ export declare class PluginDeploymentStore {
45
31
 
46
32
 
47
33
 
48
-
49
- private readMergedManifest;
50
-
51
- hasLegacyManifestEntry(pluginName: string): boolean;
52
-
53
- activeSharedManifest(): SharedPluginEntry[];
54
-
55
-
56
-
57
-
58
34
  readSharedManifest(): SharedPluginEntry[];
59
35
  writeSharedManifest(entries: SharedPluginEntry[]): void;
60
36
 
61
- migrateLegacySharedIfNeeded(): Promise<void>;
62
-
63
- deployPluginZipToPersistentDir(zipBuffer: Buffer, expectedName?: string): Promise<SharedPluginEntry | null>;
37
+ updateSharedManifest(mutator: (entries: SharedPluginEntry[]) => SharedPluginEntry[]): Promise<void>;
64
38
 
65
39
 
66
40
 
@@ -69,8 +43,6 @@ export declare class PluginDeploymentStore {
69
43
 
70
44
  removeDeployedDir(pluginName: string): void;
71
45
 
72
- updateSharedManifest(mutator: (entries: SharedPluginEntry[]) => SharedPluginEntry[]): Promise<void>;
73
-
74
46
 
75
47
 
76
48
 
@@ -1,3 +1,3 @@
1
- import{cpSync as S,existsSync as a,lstatSync as M,mkdirSync as f,readFileSync as d,readdirSync as P,renameSync as D,rmSync as u,symlinkSync as w,writeFileSync as N}from"node:fs";import{join as n,resolve as m}from"node:path";import{getBridgeInstancePluginsDir as v}from"../config.js";import{sanitizeAgentId as F,sanitizeArchiveFileName as k,withFileLock as L}from"../utils/file-utils.js";import{createLogger as $}from"../utils/logger.js";import{isValidPluginName as h,PLUGIN_NAME_PATTERN as A}from"./plugin-manifest.js";import{extractPluginZip as R}from"./plugin-package.js";const l=$("plugin-manager"),E=process.platform==="win32"?"junction":"dir";class x{constructor(e,i,r,t){this.rootDir=e,this.runtimeRootDir=i,this.loader=r,this.legacyRootDir=t}deployedDir(){return n(this.rootDir,"deployed")}deployedManifestFile(){return n(this.deployedDir(),"manifest.json")}legacyDeployedDir(){return this.legacyRootDir?n(this.legacyRootDir,"deployed"):""}legacyDeployedManifestFile(){return this.legacyDeployedDir()?n(this.legacyDeployedDir(),"manifest.json"):""}deployedPluginDir(e){if(!h(e))throw new Error(`\u975E\u6CD5\u63D2\u4EF6\u540D\uFF08\u4EC5\u5141\u8BB8 ${A}\uFF09: ${JSON.stringify(e)}`);const i=n(this.deployedDir(),e),r=m(this.deployedDir());if(m(i)!==n(r,e))throw new Error(`\u63D2\u4EF6\u76EE\u5F55\u8D8A\u51FA\u90E8\u7F72\u533A: ${e}`);return i}legacySharedDir(){return n(this.rootDir,"shared")}deployedPluginHealthy(e){return a(n(this.deployedPluginDir(e),"plugin.json"))||this.legacyPluginHealthy(e)}legacyPluginHealthy(e){if(!this.legacyDeployedDir())return!1;try{const i=n(this.legacyDeployedDir(),e);return a(n(i,"plugin.json"))}catch{return!1}}resolveDeployedSourceDir(e){return a(n(this.deployedPluginDir(e),"plugin.json"))?this.deployedPluginDir(e):this.legacyPluginHealthy(e)?n(this.legacyDeployedDir(),e):null}readMergedManifest(){const e=new Map;if(this.legacyDeployedManifestFile())try{const i=JSON.parse(d(this.legacyDeployedManifestFile(),"utf8"));for(const r of Array.isArray(i.plugins)?i.plugins:[])r&&h(r.pluginName)&&e.set(r.pluginName,r)}catch{}try{const i=JSON.parse(d(this.deployedManifestFile(),"utf8"));for(const r of Array.isArray(i.plugins)?i.plugins:[])r&&h(r.pluginName)&&e.set(r.pluginName,r)}catch{}return[...e.values()]}hasLegacyManifestEntry(e){if(!this.legacyDeployedManifestFile())return!1;try{const i=JSON.parse(d(this.legacyDeployedManifestFile(),"utf8"));return(Array.isArray(i.plugins)?i.plugins:[]).some(r=>r&&h(r.pluginName)&&r.pluginName===e)}catch{return!1}}activeSharedManifest(){return this.readMergedManifest().filter(e=>!e.removed)}readSharedManifest(){return this.activeSharedManifest()}writeSharedManifest(e){f(this.deployedDir(),{recursive:!0}),N(this.deployedManifestFile(),`${JSON.stringify({version:2,plugins:e},null,2)}
2
- `,"utf8")}async migrateLegacySharedIfNeeded(){try{if(a(this.deployedManifestFile()))return;const e=n(this.legacySharedDir(),"manifest.json");if(!a(e))return;const i=JSON.parse(d(e,"utf8")),r=Array.isArray(i.plugins)?i.plugins:[];if(r.length===0)return;const t=[];let s=0,o=0;for(const y of r){const g=k(y.zipFile??"","");if(!y.pluginName||!g)continue;const p=n(this.legacySharedDir(),g);if(a(p)){s+=1;try{const c=await this.deployPluginZipToPersistentDir(d(p),y.pluginName);if(!c){o+=1;continue}t.push(c),l.info("[shared] \u65E7\u5171\u4EAB\u63D2\u4EF6\u8FC1\u79FB\u5230\u90E8\u7F72\u533A: %s",y.pluginName)}catch(c){o+=1,l.warn("[shared] \u65E7\u5171\u4EAB\u63D2\u4EF6 %s \u8FC1\u79FB\u5931\u8D25: %s",y.pluginName,c instanceof Error?c.message:String(c))}}}t.length>0&&this.writeSharedManifest(t),o===0?u(this.legacySharedDir(),{recursive:!0,force:!0}):l.warn("[shared] \u65E7\u5171\u4EAB\u63D2\u4EF6\u8FC1\u79FB\u90E8\u5206\u5931\u8D25\uFF08%d/%d\uFF09\uFF0C\u4FDD\u7559 shared/ \u76EE\u5F55\u4EE5\u514D\u6570\u636E\u4E22\u5931",o,s)}catch(e){l.warn("[shared] \u65E7\u5171\u4EAB\u63D2\u4EF6\u8FC1\u79FB\u672A\u6267\u884C\uFF08\u4E0B\u6B21\u91CD\u8BD5\uFF09: %s",e instanceof Error?e.message:String(e))}}async deployPluginZipToPersistentDir(e,i){if(!e||e.length===0)return null;const r=n(this.rootDir,"tmp",`migrate-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{const t=await R(e,r),s=this.loader.loadManifestOnly(t.pluginDir);if(!s.ok)return null;const o=s.manifest.name;return i&&o!==i?null:(this.replaceDeployedDir(o,t.pluginDir),{pluginName:o,zipFile:`${o}.zip`,fileName:`${o}.zip`,defaultEnabled:!0})}finally{u(r,{recursive:!0,force:!0})}}replaceDeployedDir(e,i){f(this.deployedDir(),{recursive:!0});const r=this.deployedPluginDir(e),t=n(this.deployedDir(),`.old-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);a(r)&&D(r,t);try{S(i,r,{recursive:!0,filter:s=>!/[\\/]\.git([\\/]|$)/.test(s)&&!/[\\/]node_modules([\\/]|$)/.test(s)})}catch(s){throw a(t)&&(u(r,{recursive:!0,force:!0}),D(t,r)),s}a(t)&&u(t,{recursive:!0,force:!0})}removeDeployedDir(e){u(this.deployedPluginDir(e),{recursive:!0,force:!0})}async updateSharedManifest(e){await L(this.deployedManifestFile(),async()=>{this.writeSharedManifest(e(this.readMergedManifest()))})}runtimeDirFor(e){return this.runtimeRootDir?n(this.runtimeRootDir,F(e)):v(e)}runtimeLinkPath(e,i){return n(this.runtimeDirFor(e),i)}ensureRuntimeLink(e,i){const r=this.runtimeLinkPath(e,i),t=this.resolveDeployedSourceDir(i);if(!t)return!1;f(this.runtimeDirFor(e),{recursive:!0});try{if(a(r)){let s=!1;try{s=M(r).isSymbolicLink()}catch{s=!1}if(s)try{return P(r),!0}catch{}u(r,{recursive:!0,force:!0})}return w(t,r,E),l.info("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5DF2\u5EFA\u7ACB: %s \u2192 %s",e,r,t),!0}catch(s){return l.warn("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5931\u8D25\uFF08%s \u2192 %s\uFF09: %s",e,i,t,s instanceof Error?s.message:String(s)),!1}}removeRuntimeLink(e,i){const r=this.runtimeLinkPath(e,i);try{a(r)&&(u(r,{recursive:!0,force:!0}),l.info("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5DF2\u79FB\u9664: %s",e,i))}catch(t){l.warn("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u79FB\u9664\u5931\u8D25\uFF08%s\uFF09: %s",e,i,t instanceof Error?t.message:String(t))}}}export{x as PluginDeploymentStore};
1
+ import{cpSync as y,existsSync as o,lstatSync as p,mkdirSync as c,readFileSync as D,readdirSync as g,renameSync as d,rmSync as u,symlinkSync as m,writeFileSync as S}from"node:fs";import{join as n,resolve as f}from"node:path";import{getBridgeInstancePluginsDir as P}from"../config.js";import{sanitizeAgentId as v,withFileLock as w}from"../utils/file-utils.js";import{createLogger as M}from"../utils/logger.js";import{isValidPluginName as h,PLUGIN_NAME_PATTERN as k}from"./plugin-manifest.js";const l=M("plugin-manager"),F=process.platform==="win32"?"junction":"dir",a=3;class O{constructor(r,i){this.rootDir=r,this.runtimeRootDir=i}deployedDir(){return n(this.rootDir,"deployed")}deployedManifestFile(){return n(this.deployedDir(),"manifest.json")}deployedPluginDir(r){if(!h(r))throw new Error(`\u975E\u6CD5\u63D2\u4EF6\u540D\uFF08\u4EC5\u5141\u8BB8 ${k}\uFF09: ${JSON.stringify(r)}`);const i=n(this.deployedDir(),r),e=f(this.deployedDir());if(f(i)!==n(e,r))throw new Error(`\u63D2\u4EF6\u76EE\u5F55\u8D8A\u51FA\u90E8\u7F72\u533A: ${r}`);return i}deployedPluginHealthy(r){return o(n(this.deployedPluginDir(r),"plugin.json"))}resolveDeployedSourceDir(r){return this.deployedPluginHealthy(r)?this.deployedPluginDir(r):null}readSharedManifest(){try{if(!o(this.deployedManifestFile()))return[];const r=JSON.parse(D(this.deployedManifestFile(),"utf8"));if(r.version!==a)return l.warn("[shared] \u90E8\u7F72\u6E05\u5355\u7248\u672C %s \u975E %d\uFF08\u65E7\u683C\u5F0F\u4E0D\u518D\u517C\u5BB9\uFF09\uFF0C\u6309\u7A7A\u90E8\u7F72\u96C6\u5904\u7406\u2014\u2014\u8BF7\u91CD\u65B0\u90E8\u7F72\u63D2\u4EF6",String(r.version??"(\u7F3A\u5931)"),a),[];const i=[];for(const e of Array.isArray(r.plugins)?r.plugins:[])e&&h(e.pluginName)&&i.push(e);return i}catch{return[]}}writeSharedManifest(r){c(this.deployedDir(),{recursive:!0}),S(this.deployedManifestFile(),`${JSON.stringify({version:a,plugins:r},null,2)}
2
+ `,"utf8")}async updateSharedManifest(r){await w(this.deployedManifestFile(),async()=>{this.writeSharedManifest(r(this.readSharedManifest()))})}replaceDeployedDir(r,i){c(this.deployedDir(),{recursive:!0});const e=this.deployedPluginDir(r),t=n(this.deployedDir(),`.old-${r}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);o(e)&&d(e,t);try{y(i,e,{recursive:!0,filter:s=>!/[\\/]\.git([\\/]|$)/.test(s)&&!/[\\/]node_modules([\\/]|$)/.test(s)})}catch(s){throw o(t)&&(u(e,{recursive:!0,force:!0}),d(t,e)),s}o(t)&&u(t,{recursive:!0,force:!0})}removeDeployedDir(r){u(this.deployedPluginDir(r),{recursive:!0,force:!0})}runtimeDirFor(r){return this.runtimeRootDir?n(this.runtimeRootDir,v(r)):P(r)}runtimeLinkPath(r,i){return n(this.runtimeDirFor(r),i)}ensureRuntimeLink(r,i){const e=this.runtimeLinkPath(r,i),t=this.resolveDeployedSourceDir(i);if(!t)return!1;c(this.runtimeDirFor(r),{recursive:!0});try{if(o(e)){let s=!1;try{s=p(e).isSymbolicLink()}catch{s=!1}if(s)try{return g(e),!0}catch{}u(e,{recursive:!0,force:!0})}return m(t,e,F),l.info("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5DF2\u5EFA\u7ACB: %s \u2192 %s",r,e,t),!0}catch(s){return l.warn("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5931\u8D25\uFF08%s \u2192 %s\uFF09: %s",r,i,t,s instanceof Error?s.message:String(s)),!1}}removeRuntimeLink(r,i){const e=this.runtimeLinkPath(r,i);try{o(e)&&(u(e,{recursive:!0,force:!0}),l.info("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5DF2\u79FB\u9664: %s",r,i))}catch(t){l.warn("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u79FB\u9664\u5931\u8D25\uFF08%s\uFF09: %s",r,i,t instanceof Error?t.message:String(t))}}}export{O as PluginDeploymentStore};
3
3
 
@@ -8,7 +8,6 @@
8
8
 
9
9
 
10
10
 
11
-
12
11
  import type { PluginInvokeContext, PluginToolInvocationResult, JsonObject } from "@agentswork/acode";
13
12
  import type { PluginToolDef } from "./plugin-manifest.js";
14
13
  import type { LoadedPlugin } from "./plugin-runtime.js";
@@ -17,4 +16,14 @@ export declare function executeHandler(agentId: string, plugin: LoadedPlugin, to
17
16
 
18
17
 
19
18
 
19
+
20
+
21
+
22
+
23
+
24
+ export declare function resolveEffectiveConfigValues(plugin: LoadedPlugin, agentId?: string): Record<string, string>;
25
+
26
+
27
+
28
+
20
29
  export declare function buildPluginEnv(plugin: LoadedPlugin, agentId: string): NodeJS.ProcessEnv;
@@ -1,3 +1,3 @@
1
- import{spawn as T}from"node:child_process";import{join as _}from"node:path";import{pathToFileURL as O}from"node:url";import{BLOCKED_ENV_KEYS as P}from"../utils/env-safety.js";import{createLogger as A}from"../utils/logger.js";import{renderCommandArgv as v,truncate as C}from"./plugin-manifest.js";const N=A("plugin-manager"),g=256*1024,h=6e4,S=/^[A-Za-z_][A-Za-z0-9_]*$/;async function G(t,e,s,a,o){const n=Date.now(),r=s.handler??{type:"process"};try{return r.type==="mcp"?{ok:!1,error:"handler.type=mcp \u5C06\u5728\u540E\u7EED\u7248\u672C\u652F\u6301\uFF0C\u8BF7\u6539\u7528 process/module handler"}:r.type==="module"?{ok:!0,result:await b(e,r,a,t,o),durationMs:Date.now()-n}:!r.command||!r.command.trim()?{ok:!1,error:`\u5DE5\u5177 ${s.name} \u7684 process handler \u7F3A\u5C11 command`}:{ok:!0,result:await $(e,r,a,t,o),durationMs:Date.now()-n}}catch(i){return{ok:!1,error:i instanceof Error?i.message:String(i),durationMs:Date.now()-n}}}async function $(t,e,s,a,o){const n=e.command??"";if(e.shell===!0&&/\{\{.+?\}\}/.test(n))throw new Error('shell:true \u7684 handler \u4E0D\u652F\u6301 {{params.*}} \u63D2\u503C\uFF08\u547D\u4EE4\u6CE8\u5165\u98CE\u9669\uFF09\uFF1B\u8BF7\u6539\u7528 shell:false \u7684 argv \u6A21\u5F0F\u6216 stdin:"params"');const r=v(n,{params:s});if(r.length===0)throw new Error("process handler command \u4E3A\u7A7A");const i=typeof e.timeoutMs=="number"&&e.timeoutMs>0?e.timeoutMs:h,u=new AbortController,d=()=>u.abort();o?.signal?.addEventListener("abort",d,{once:!0});const E=setTimeout(()=>u.abort(),i);try{return await new Promise((l,w)=>{N.info("[plugin:%s] spawn: %s",t.name,r.join(" "));const c=T(r[0],r.slice(1),{cwd:t.dir,env:k(t,a),shell:e.shell===!0,windowsHide:!0,signal:u.signal});let f="",y="";c.stdin?.on("error",()=>{}),c.stdout?.on("data",m=>{f.length<g&&(f+=m.toString("utf8"))}),c.stderr?.on("data",m=>{y.length<g&&(y+=m.toString("utf8"))}),c.on("error",m=>{w(new Error(`\u63D2\u4EF6\u8FDB\u7A0B\u542F\u52A8\u5931\u8D25: ${m.message}`))}),c.on("close",m=>{const p=f.trim();if(m!==0){const M=C(y.trim()||p||"(\u65E0\u8F93\u51FA)",600);w(new Error(u.signal.aborted?`\u63D2\u4EF6\u8FDB\u7A0B\u8D85\u65F6(${i}ms)\u6216\u88AB\u4E2D\u6B62`:`\u63D2\u4EF6\u8FDB\u7A0B\u9000\u51FA\u7801 ${m}: ${M}`));return}if(!p){l({ok:!0});return}try{l(JSON.parse(p))}catch{l(p)}});try{e.stdin==="params"?c.stdin?.end(`${JSON.stringify(s)}
2
- `):c.stdin?.end()}catch{}})}finally{clearTimeout(E),o?.signal?.removeEventListener("abort",d)}}async function b(t,e,s,a,o){if(!e.module)throw new Error("module handler \u7F3A\u5C11 module \u8DEF\u5F84");const n=_(t.dir,e.module);let r=t.moduleCache.get(n);r||(r=await import(`${O(n).href}?acode_nonce=${t.importNonce}`),t.moduleCache.set(n,r));const i=e.export||"default",d=r[i];if(typeof d!="function")throw new Error(`\u6A21\u5757 ${e.module} \u672A\u5BFC\u51FA\u51FD\u6570 ${i}`);const E=typeof e.timeoutMs=="number"&&e.timeoutMs>0?e.timeoutMs:h;let l;const w=Promise.resolve().then(()=>d(s,{agentId:a,signal:o?.signal,pluginRoot:t.dir}));try{return await Promise.race([w,new Promise((c,f)=>{l=setTimeout(()=>f(new Error(`\u63D2\u4EF6\u6A21\u5757\u6267\u884C\u8D85\u65F6(${E}ms)`)),E)})])}finally{clearTimeout(l)}}function k(t,e){const s={};for(const o of["PATH","HOME","USERPROFILE","SystemRoot","COMSPEC","TEMP","TMP","LANG","TZ"]){const n=process.env[o];n!==void 0&&(s[o]=n)}s.ACODE_PLUGIN_ROOT=t.dir,s.ACODE_AGENT_ID=e,s.ACODE_PLUGIN_NAME=t.name;const a=new Set((t.userConfig??[]).map(o=>o.key));for(const[o,n]of Object.entries(t.configValues))a.has(o)&&(!S.test(o)||P.has(o.toUpperCase())||(s[o]=n));return s}export{k as buildPluginEnv,G as executeHandler};
1
+ import{spawn as T}from"node:child_process";import{join as _}from"node:path";import{pathToFileURL as O}from"node:url";import{loadDynamicModule as P}from"../utils/dynamic-import.js";import{BLOCKED_ENV_KEYS as k}from"../utils/env-safety.js";import{getPanelEnvVars as A}from"./panel-env.js";import{createLogger as C}from"../utils/logger.js";import{renderCommandArgv as b,truncate as N}from"./plugin-manifest.js";const S=C("plugin-manager"),g=256*1024,h=6e4,D=/^[A-Za-z_][A-Za-z0-9_]*$/;async function Y(o,e,n,s,i){const t=Date.now(),r=n.handler??{type:"process"};try{return r.type==="module"?{ok:!0,result:await $(e,r,s,o,i),durationMs:Date.now()-t}:!r.command||!r.command.trim()?{ok:!1,error:`\u5DE5\u5177 ${n.name} \u7684 process handler \u7F3A\u5C11 command`}:{ok:!0,result:await L(e,r,s,o,i),durationMs:Date.now()-t}}catch(a){return{ok:!1,error:a instanceof Error?a.message:String(a),durationMs:Date.now()-t}}}async function L(o,e,n,s,i){const t=e.command??"";if(e.shell===!0&&/\{\{.+?\}\}/.test(t))throw new Error('shell:true \u7684 handler \u4E0D\u652F\u6301 {{params.*}} \u63D2\u503C\uFF08\u547D\u4EE4\u6CE8\u5165\u98CE\u9669\uFF09\uFF1B\u8BF7\u6539\u7528 shell:false \u7684 argv \u6A21\u5F0F\u6216 stdin:"params"');const r=b(t,{params:n});if(r.length===0)throw new Error("process handler command \u4E3A\u7A7A");const a=typeof e.timeoutMs=="number"&&e.timeoutMs>0?e.timeoutMs:h,f=new AbortController,l=()=>f.abort();i?.signal?.addEventListener("abort",l,{once:!0});const E=setTimeout(()=>f.abort(),a);try{return await new Promise((u,y)=>{S.info("[plugin:%s] spawn: %s",o.name,r.join(" "));const c=T(r[0],r.slice(1),{cwd:o.dir,env:U(o,s),shell:e.shell===!0,windowsHide:!0,signal:f.signal});let d="",p="";c.stdin?.on("error",()=>{}),c.stdout?.on("data",m=>{d.length<g&&(d+=m.toString("utf8"))}),c.stderr?.on("data",m=>{p.length<g&&(p+=m.toString("utf8"))}),c.on("error",m=>{y(new Error(`\u63D2\u4EF6\u8FDB\u7A0B\u542F\u52A8\u5931\u8D25: ${m.message}`))}),c.on("close",m=>{const w=d.trim();if(m!==0){const M=N(p.trim()||w||"(\u65E0\u8F93\u51FA)",600);y(new Error(f.signal.aborted?`\u63D2\u4EF6\u8FDB\u7A0B\u8D85\u65F6(${a}ms)\u6216\u88AB\u4E2D\u6B62`:`\u63D2\u4EF6\u8FDB\u7A0B\u9000\u51FA\u7801 ${m}: ${M}`));return}if(!w){u({ok:!0});return}try{u(JSON.parse(w))}catch{u(w)}});try{e.stdin==="params"?c.stdin?.end(`${JSON.stringify(n)}
2
+ `):c.stdin?.end()}catch{}})}finally{clearTimeout(E),i?.signal?.removeEventListener("abort",l)}}async function $(o,e,n,s,i){if(!e.module)throw new Error("module handler \u7F3A\u5C11 module \u8DEF\u5F84");const t=_(o.dir,e.module);let r=o.moduleCache.get(t);r||(r=await P(O(t).href,{freshInstanceQuery:`acode_nonce=${o.importNonce}`}),o.moduleCache.set(t,r));const a=e.export||"default",l=r[a];if(typeof l!="function")throw new Error(`\u6A21\u5757 ${e.module} \u672A\u5BFC\u51FA\u51FD\u6570 ${a}`);const E=typeof e.timeoutMs=="number"&&e.timeoutMs>0?e.timeoutMs:h;let u;const y=Promise.resolve().then(()=>l(n,{agentId:s,signal:i?.signal,pluginRoot:o.dir,config:v(o,s)}));try{return await Promise.race([y,new Promise((c,d)=>{u=setTimeout(()=>d(new Error(`\u63D2\u4EF6\u6A21\u5757\u6267\u884C\u8D85\u65F6(${E}ms)`)),E)})])}finally{clearTimeout(u)}}function v(o,e){const n={};for(const s of o.userConfig??[]){if(!s||typeof s.key!="string")continue;const i=e?A(e)[s.key]:void 0,t=i!==void 0&&i.length>0?i:process.env[s.key];typeof t=="string"&&t.length>0&&(n[s.key]=t)}for(const[s,i]of Object.entries(o.configValues))typeof i=="string"&&i.length>0&&(n[s]=i);return n}function U(o,e){const n={};for(const t of["PATH","HOME","USERPROFILE","SystemRoot","COMSPEC","TEMP","TMP","LANG","TZ"]){const r=process.env[t];r!==void 0&&(n[t]=r)}n.ACODE_PLUGIN_ROOT=o.dir,n.ACODE_AGENT_ID=e,n.ACODE_PLUGIN_NAME=o.name;const s=new Set((o.userConfig??[]).map(t=>t.key)),i=v(o,e);for(const[t,r]of Object.entries(i))s.has(t)&&(!D.test(t)||k.has(t.toUpperCase())||(n[t]=r));return n}export{U as buildPluginEnv,Y as executeHandler,v as resolveEffectiveConfigValues};
3
3
 
@@ -1,8 +1,8 @@
1
- import{spawn as $}from"node:child_process";import{createLogger as R}from"../utils/logger.js";import{buildPluginEnv as S}from"./plugin-handler-adapter.js";import{getPath as E,isRecord as _,renderCommandArgv as w,renderTemplate as A,safeStableStringify as b,truncate as h}from"./plugin-manifest.js";const I=R("plugin-manager"),L=200,T=256*1024,M=4*1024,y=6e4,x=6e4;function p(g,n){g.logs.push(`${new Date().toISOString()} ${n}`),g.logs.length>L&&g.logs.shift()}class J{ensureRunning(n){for(const t of n.plugins.values())if(t.enabled)for(const e of t.runtimes)!e.child&&!e.timer&&!e.backoffTimer&&!e.stopping&&this.start(n,t,e)}startAll(n,t){for(const e of t.runtimes)this.stop(e),t.enabled&&this.start(n,t,e)}stopAll(n){for(const t of n.runtimes)this.stop(t)}start(n,t,e){const r=e.def.transport??{type:"command-stream"};if(r.type==="http-callback"){e.stopping=!1;return}if(r.type==="poll-command"){const s=Math.max(5e3,r.intervalMs??3e4);e.stopping=!1,e.timer=setInterval(()=>{this.pollOnce(n,t,e)},s),this.pollOnce(n,t,e);return}if(!r.command){e.lastError="command-stream \u7F3A\u5C11 command",p(e,`ERROR ${e.lastError}`);return}e.stopping=!1,this.spawnChild(n,t,e)}spawnChild(n,t,e){const s=e.def.transport?.command??"",d=w(s,{});try{p(e,`spawn: ${d.join(" ")}`);const i=$(d[0],d.slice(1),{cwd:t.dir,env:S(t,n.agentId),shell:!1,windowsHide:!0,stdio:["ignore","pipe","pipe"]});e.child=i,e.lastError=void 0;let o="";i.stdout?.on("data",a=>{o+=a.toString("utf8");let l=o.indexOf(`
1
+ import{spawn as y}from"node:child_process";import{createLogger as R}from"../utils/logger.js";import{buildPluginEnv as S}from"./plugin-handler-adapter.js";import{getPath as E,isRecord as _,renderCommandArgv as w,renderTemplate as A,safeStableStringify as b,truncate as h}from"./plugin-manifest.js";const P=R("plugin-manager"),I=200,T=256*1024,L=4*1024,v=6e4,M=6e4;function p(g,n){g.logs.push(`${new Date().toISOString()} ${n}`),g.logs.length>I&&g.logs.shift()}class J{ensureRunning(n){for(const t of n.plugins.values())if(t.enabled)for(const e of t.runtimes)!e.child&&!e.timer&&!e.backoffTimer&&!e.stopping&&this.start(n,t,e)}startAll(n,t){for(const e of t.runtimes)this.stop(e),t.enabled&&this.start(n,t,e)}stopAll(n){for(const t of n.runtimes)this.stop(t)}start(n,t,e){const i=e.def.transport??{type:"command-stream"};if(i.type==="http-callback"){e.stopping=!1;return}if(i.type==="poll-command"){const s=Math.max(5e3,i.intervalMs??3e4);e.stopping=!1,e.timer=setInterval(()=>{this.pollOnce(n,t,e)},s),this.pollOnce(n,t,e);return}if(!i.command){e.lastError="command-stream \u7F3A\u5C11 command",p(e,`ERROR ${e.lastError}`);return}e.stopping=!1,this.spawnChild(n,t,e)}spawnChild(n,t,e){const s=e.def.transport?.command??"",d=w(s,{});try{p(e,`spawn: ${d.join(" ")}`);const r=y(d[0],d.slice(1),{cwd:t.dir,env:S(t,n.agentId),shell:!1,windowsHide:!0,stdio:["ignore","pipe","pipe"]});e.child=r,e.lastError=void 0;let o="";r.stdout?.on("data",a=>{o+=a.toString("utf8");let l=o.indexOf(`
2
2
  `);for(;l>=0;){const f=o.slice(0,l).trim();o=o.slice(l+1),f&&this.handleLine(n,t,e,f),l=o.indexOf(`
3
- `)}o.length>1024*1024&&(o=o.slice(-4096))}),i.stderr?.on("data",a=>{p(e,`stderr: ${h(a.toString("utf8").trimEnd(),400)}`)}),i.on("error",a=>{e.lastError=`\u8FDB\u7A0B\u542F\u52A8\u5931\u8D25: ${a.message}`,p(e,`ERROR ${e.lastError}`)}),i.on("close",a=>{e.child=void 0,!e.stopping&&(e.lastError=`\u76D1\u542C\u8FDB\u7A0B\u9000\u51FA\uFF08code=${a??"signal"}\uFF09`,p(e,`exit code=${a??"signal"}\uFF0C\u51C6\u5907\u91CD\u542F`),this.scheduleRestart(n,t,e))})}catch(i){const o=i instanceof Error?i.message:String(i);e.lastError=o,p(e,`ERROR spawn: ${o}`),this.scheduleRestart(n,t,e)}}scheduleRestart(n,t,e){if(e.stopping)return;const r=Math.max(500,e.def.transport?.restartBackoffMs??2e3),s=Math.min(x,r*2**Math.min(e.restarts,6));e.restarts++,p(e,`restart #${e.restarts} in ${s}ms`),e.backoffTimer=setTimeout(()=>{e.backoffTimer=void 0,e.stopping||this.spawnChild(n,t,e)},s)}async pollOnce(n,t,e){if(e.polling)return;const r=e.def.transport?.command??"",s=w(r,{});if(s.length===0)return;e.polling=!0;const d=new AbortController,i=setTimeout(()=>d.abort(),y);try{const o=await new Promise((a,l)=>{const f=$(s[0],s.slice(1),{cwd:t.dir,env:S(t,n.agentId),shell:!1,windowsHide:!0,stdio:["ignore","pipe","pipe"],signal:d.signal});let c="",u="";f.stdout?.on("data",m=>{c.length<T&&(c+=m.toString("utf8"))}),f.stderr?.on("data",m=>{u.length<T&&(u+=m.toString("utf8"))});const v=()=>d.signal.aborted;f.on("error",m=>{l(v()?new Error(`poll \u8D85\u65F6(${y}ms)`):m)}),f.on("close",m=>{v()?l(new Error(`poll \u8D85\u65F6(${y}ms)`)):m===0?a(c):l(new Error(`exit ${m}: ${h(u||c,300)}`))})});e.lastError=void 0;for(const a of o.split(`
4
- `)){const l=a.trim();l&&this.handleLine(n,t,e,l)}}catch(o){const a=o instanceof Error?o.message:String(o);e.lastError=a,p(e,`poll \u5931\u8D25: ${a}`)}finally{clearTimeout(i),e.polling=!1}}stop(n){if(n.stopping=!0,n.restarts=0,n.child){try{n.child.kill()}catch{}n.child=void 0}n.timer&&(clearInterval(n.timer),n.timer=void 0),n.backoffTimer&&(clearTimeout(n.backoffTimer),n.backoffTimer=void 0)}handleLine(n,t,e,r){p(e,`event: ${h(r,300)}`);let s;try{s=JSON.parse(r)}catch{e.lastError="\u4E8B\u4EF6\u884C\u4E0D\u662F\u5408\u6CD5 JSON\uFF08\u8981\u6C42 JSONL\uFF09";return}if(!_(s))return;const d=typeof s.event=="string"?s.event:e.def.event,i=d===e.def.event?e.def:t.listeners.find(o=>o.event===d);i&&(i.delivery&&i.delivery!=="poll"&&I.debug("[plugin:%s] delivery=%s \u6682\u6309 poll \u4EA4\u4ED8",t.name,i.delivery),this.enqueue(n,t,i,s))}enqueue(n,t,e,r){for(const[c,u]of Object.entries(e.matcher??{})){const v=E(r,c);if(!(Array.isArray(u)?u:[u]).some(O=>JSON.stringify(O)===JSON.stringify(v)))return}let s;if(e.dedupKey){const c=E(r,e.dedupKey);c!=null&&(s=h(String(c),256))}n.eventSeq++;const d=h(b(r.data??r),M),i=e.summary?A(e.summary,r):e.description??"",o=(e.toolHints??[]).join(","),a=`[plugin:${t.name}] ${e.event}`+(i?`
5
- ${i}`:"")+(o?`
3
+ `)}o.length>1024*1024&&(o=o.slice(-4096))}),r.stderr?.on("data",a=>{p(e,`stderr: ${h(a.toString("utf8").trimEnd(),400)}`)}),r.on("error",a=>{e.lastError=`\u8FDB\u7A0B\u542F\u52A8\u5931\u8D25: ${a.message}`,p(e,`ERROR ${e.lastError}`)}),r.on("close",a=>{e.child=void 0,!e.stopping&&(e.lastError=`\u76D1\u542C\u8FDB\u7A0B\u9000\u51FA\uFF08code=${a??"signal"}\uFF09`,p(e,`exit code=${a??"signal"}\uFF0C\u51C6\u5907\u91CD\u542F`),this.scheduleRestart(n,t,e))})}catch(r){const o=r instanceof Error?r.message:String(r);e.lastError=o,p(e,`ERROR spawn: ${o}`),this.scheduleRestart(n,t,e)}}scheduleRestart(n,t,e){if(e.stopping)return;const i=Math.max(500,e.def.transport?.restartBackoffMs??2e3),s=Math.min(M,i*2**Math.min(e.restarts,6));e.restarts++,p(e,`restart #${e.restarts} in ${s}ms`),e.backoffTimer=setTimeout(()=>{e.backoffTimer=void 0,e.stopping||this.spawnChild(n,t,e)},s)}async pollOnce(n,t,e){if(e.polling)return;const i=e.def.transport?.command??"",s=w(i,{});if(s.length===0)return;e.polling=!0;const d=new AbortController,r=setTimeout(()=>d.abort(),v);try{const o=await new Promise((a,l)=>{const f=y(s[0],s.slice(1),{cwd:t.dir,env:S(t,n.agentId),shell:!1,windowsHide:!0,stdio:["ignore","pipe","pipe"],signal:d.signal});let c="",u="";f.stdout?.on("data",m=>{c.length<T&&(c+=m.toString("utf8"))}),f.stderr?.on("data",m=>{u.length<T&&(u+=m.toString("utf8"))});const $=()=>d.signal.aborted;f.on("error",m=>{l($()?new Error(`poll \u8D85\u65F6(${v}ms)`):m)}),f.on("close",m=>{$()?l(new Error(`poll \u8D85\u65F6(${v}ms)`)):m===0?a(c):l(new Error(`exit ${m}: ${h(u||c,300)}`))})});e.lastError=void 0;for(const a of o.split(`
4
+ `)){const l=a.trim();l&&this.handleLine(n,t,e,l)}}catch(o){const a=o instanceof Error?o.message:String(o);e.lastError=a,p(e,`poll \u5931\u8D25: ${a}`)}finally{clearTimeout(r),e.polling=!1}}stop(n){if(n.stopping=!0,n.restarts=0,n.child){try{n.child.kill()}catch{}n.child=void 0}n.timer&&(clearInterval(n.timer),n.timer=void 0),n.backoffTimer&&(clearTimeout(n.backoffTimer),n.backoffTimer=void 0)}handleLine(n,t,e,i){p(e,`event: ${h(i,300)}`);let s;try{s=JSON.parse(i)}catch{e.lastError="\u4E8B\u4EF6\u884C\u4E0D\u662F\u5408\u6CD5 JSON\uFF08\u8981\u6C42 JSONL\uFF09";return}if(!_(s))return;const d=typeof s.event=="string"?s.event:e.def.event,r=d===e.def.event?e.def:t.listeners.find(o=>o.event===d);r&&this.enqueue(n,t,r,s)}enqueue(n,t,e,i){for(const[c,u]of Object.entries(e.matcher??{})){const $=E(i,c);if(!(Array.isArray(u)?u:[u]).some(O=>JSON.stringify(O)===JSON.stringify($)))return}let s;if(e.dedupKey){const c=E(i,e.dedupKey);c!=null&&(s=h(String(c),256))}n.eventSeq++;const d=h(b(i.data??i),L),r=e.summary?A(e.summary,i):e.description??"",o=(e.toolHints??[]).join(","),a=`[plugin:${t.name}] ${e.event}`+(r?`
5
+ ${r}`:"")+(o?`
6
6
  toolHints=${o}`:"")+`
7
7
  payload=${d}`,l={msgId:h(s?`plugin-event-${t.name}-${s}`:`plugin-event-${t.name}-${e.event}-${n.eventSeq}`,512),channel:"plugin-event",senderId:`plugin:${t.name}`,senderName:`\u63D2\u4EF6[${t.name}]`,receiverId:n.agentId||void 0,content:a,requireReply:!1,role:"system",timestamp:new Date().toISOString()},f=e.priority??"normal";n.buffer.push({plugin:t.name,event:e.event,priority:f,dedupKey:s,receivedAt:Date.now(),message:l})}}export{J as ListenerRunner};
8
8
 
@@ -13,6 +13,7 @@
13
13
 
14
14
  import type { PluginSummary } from "@agentswork/acode";
15
15
  import { type PluginManifest, type PluginToolDef } from "./plugin-manifest.js";
16
+ import type { PluginUiSummary } from "@agentswork/acode";
16
17
  import type { LoadedPlugin } from "./plugin-runtime.js";
17
18
  export type ManifestReadResult = {
18
19
  ok: true;
@@ -44,4 +45,9 @@ export declare class PluginLoader {
44
45
 
45
46
  export declare function requiredParamsOf(tool: PluginToolDef): string[] | undefined;
46
47
 
47
- export declare function toSummary(plugin: LoadedPlugin): PluginSummary;
48
+
49
+
50
+
51
+ export declare function toFrontendSummary(plugin: LoadedPlugin): PluginUiSummary | undefined;
52
+
53
+ export declare function toSummary(plugin: LoadedPlugin, agentId?: string): PluginSummary;
@@ -1,2 +1,2 @@
1
- import{existsSync as A,readFileSync as S}from"node:fs";import{join as p}from"node:path";import{isRecord as b,validateListenerDef as j,validateManifest as J,validateToolDef as R}from"./plugin-manifest.js";class O{constructor(){this.importNonce=0}readJsonFile(t){if(!A(t))return{ok:!0,data:{}};try{const n=JSON.parse(S(t,"utf8"));return b(n)?{ok:!0,data:n}:{ok:!1,error:`${t}: \u6839\u8282\u70B9\u987B\u4E3A\u5BF9\u8C61`}}catch(n){const i=n instanceof Error?n.message:String(n);return{ok:!1,error:`${t}: JSON \u89E3\u6790\u5931\u8D25: ${i}`}}}loadManifestOnly(t){const n=this.readJsonFile(p(t,"plugin.json"));if(!n.ok)return n;const i=n.data,a=J(i);return a?{ok:!1,error:a}:{ok:!0,manifest:i}}validateUserConfigValues(t,n){const i=Array.isArray(t.userConfig)?t.userConfig:[],a={...n};for(const e of i){if(!e||typeof e.key!="string"||!/^[A-Za-z_][A-Za-z0-9_]*$/.test(e.key))return"plugin.json: userConfig.key \u975E\u6CD5\uFF08\u987B\u4E3A\u73AF\u5883\u53D8\u91CF\u540D\uFF09";if(!(typeof a[e.key]=="string"&&a[e.key].length>0)&&e.required){const f=e.default!==void 0&&typeof e.default=="string"?e.default:"";if(!f)return`\u7F3A\u5C11\u5FC5\u9700\u914D\u7F6E ${e.key}${e.description?`\uFF08${e.description}\uFF09`:""}\uFF0C\u5B89\u88C5\u65F6\u8BF7\u5728 config \u4E2D\u63D0\u4F9B`;a[e.key]=f}}return null}loadPluginFromDir(t,n,i,a){const e=this.loadManifestOnly(t);if(!e.ok)return e;const s=e.manifest,f=p(t,s.tools??"tools/tools.json"),u=this.readJsonFile(f);if(!u.ok)return u;const g=[],C=Array.isArray(u.data.tools)?u.data.tools:[];for(const r of C){const l=R(r);if(l)return{ok:!1,error:`${s.tools??"tools/tools.json"}: ${l}`};g.push(r)}const $=p(t,s.listeners??"listeners/listeners.json"),c=this.readJsonFile($);if(!c.ok)return c;const m=[],F=Array.isArray(c.data.listeners)?c.data.listeners:[];for(const r of F){const l=j(r);if(l)return{ok:!1,error:`${s.listeners??"listeners/listeners.json"}: ${l}`};m.push(r)}const k=Array.isArray(s.userConfig)?s.userConfig:[],h=this.validateUserConfigValues(s,a);if(h)return{ok:!1,error:h};const d={...a};for(const r of k){if(!r||typeof r.key!="string")continue;!(typeof d[r.key]=="string"&&d[r.key].length>0)&&r.required&&r.default!==void 0&&typeof r.default=="string"&&(d[r.key]=r.default)}const y=s.commands;let v;if(typeof y=="string"&&y.trim()){const r=p(t,y.trim());A(r)&&(v=r)}return{ok:!0,plugin:{name:s.name,version:typeof s.version=="string"?s.version:void 0,description:typeof s.description=="string"?s.description:void 0,source:n,installedAt:i,dir:t,enabled:!0,tools:g,listeners:m,commandDir:v,userConfig:k,configValues:d,status:"enabled",runtimes:m.map(r=>({def:r,stopping:!1,restarts:0,logs:[]})),moduleCache:new Map,importNonce:++this.importNonce}}}}function w(o){const t=o.inputSchema;if(!(!t||!Array.isArray(t.required)))return t.required.filter(n=>typeof n=="string")}function x(o){const t=e=>!!(e.child||e.timer)||e.def.transport?.type==="http-callback",n=e=>o.enabled?t(e)?"running":e.stopping?"stopped":"pending":"stopped",i=o.runtimes.map(e=>{const s=n(e);return{event:e.def.event,delivery:e.def.delivery??"poll",running:s==="running",state:s,error:e.lastError}}),a=i.some(e=>e.state==="running")?"running":i.some(e=>e.state==="pending")?"pending":"stopped";return{name:o.name,version:o.version,description:o.description,status:o.status,enabled:o.enabled,source:o.source,installedAt:o.installedAt,toolCount:o.tools.length,tools:o.tools.map(e=>({name:e.name,title:e.title,description:e.description})),listeners:i,running:a==="running",listenerState:a,error:o.error}}export{O as PluginLoader,w as requiredParamsOf,x as toSummary};
1
+ import{existsSync as C,readFileSync as F}from"node:fs";import{join as k}from"node:path";import{isRecord as V,validateListenerDef as b,validateManifest as I,validateToolDef as M,PLUGIN_UI_BUILTIN_ICONS as N}from"./plugin-manifest.js";import{getPanelEnvVars as R}from"./panel-env.js";class L{constructor(){this.importNonce=0}readJsonFile(e){if(!C(e))return{ok:!0,data:{}};try{const r=JSON.parse(F(e,"utf8"));return V(r)?{ok:!0,data:r}:{ok:!1,error:`${e}: \u6839\u8282\u70B9\u987B\u4E3A\u5BF9\u8C61`}}catch(r){const u=r instanceof Error?r.message:String(r);return{ok:!1,error:`${e}: JSON \u89E3\u6790\u5931\u8D25: ${u}`}}}loadManifestOnly(e){const r=this.readJsonFile(k(e,"plugin.json"));if(!r.ok)return r;const u=I(r.data);return u?{ok:!1,error:u}:{ok:!0,manifest:r.data}}validateUserConfigValues(e,r){const u=Array.isArray(e.userConfig)?e.userConfig:[],a={...r};for(const o of u){if(!o||typeof o.key!="string"||!/^[A-Za-z_][A-Za-z0-9_]*$/.test(o.key))return"plugin.json: userConfig.key \u975E\u6CD5\uFF08\u987B\u4E3A\u73AF\u5883\u53D8\u91CF\u540D\uFF09";if(!(typeof a[o.key]=="string"&&a[o.key].length>0)&&o.required){const y=o.default!==void 0&&typeof o.default=="string"?o.default:"";if(!y)return`\u7F3A\u5C11\u5FC5\u9700\u914D\u7F6E ${o.key}${o.description?`\uFF08${o.description}\uFF09`:""}\uFF0C\u5B89\u88C5\u65F6\u8BF7\u5728 config \u4E2D\u63D0\u4F9B`;a[o.key]=y}}return null}loadPluginFromDir(e,r,u,a){const o=this.loadManifestOnly(e);if(!o.ok)return o;const i=o.manifest,y=k(e,i.tools??"tools/tools.json"),c=this.readJsonFile(y);if(!c.ok)return c;const p=[],t=Array.isArray(c.data.tools)?c.data.tools:[];for(const n of t){const l=M(n);if(l)return{ok:!1,error:`${i.tools??"tools/tools.json"}: ${l}`};p.push(n)}const d=k(e,i.listeners??"listeners/listeners.json"),m=this.readJsonFile(d);if(!m.ok)return m;const g=[],S=Array.isArray(m.data.listeners)?m.data.listeners:[];for(const n of S){const l=b(n);if(l)return{ok:!1,error:`${i.listeners??"listeners/listeners.json"}: ${l}`};g.push(n)}const h=Array.isArray(i.userConfig)?i.userConfig:[],$=this.validateUserConfigValues(i,a);if($)return{ok:!1,error:$};const v={...a};for(const n of h){if(!n||typeof n.key!="string")continue;!(typeof v[n.key]=="string"&&v[n.key].length>0)&&n.required&&n.default!==void 0&&typeof n.default=="string"&&(v[n.key]=n.default)}const j=new Set(h.filter(n=>n&&typeof n.key=="string"&&typeof a[n.key]=="string"&&a[n.key].length>0).map(n=>n.key)),w=i.commands;let A;if(typeof w=="string"&&w.trim()){const n=k(e,w.trim());C(n)&&(A=n)}const f=i.ui;if(f){const n=new Set(p.map(l=>l.name));if(f.status&&!n.has(f.status.tool))return{ok:!1,error:`plugin.json: ui.status.tool "${f.status.tool}" \u4E0D\u5728\u672C\u63D2\u4EF6 tools \u5B9A\u4E49\u4E2D`};for(const l of f.view?.invoke??[])if(!n.has(l))return{ok:!1,error:`plugin.json: ui.view.invoke \u5F15\u7528\u7684\u5DE5\u5177 "${l}" \u4E0D\u5728\u672C\u63D2\u4EF6 tools \u5B9A\u4E49\u4E2D`};if(f.view&&!C(k(e,f.view.entry)))return{ok:!1,error:`plugin.json: ui.view.entry \u6587\u4EF6\u4E0D\u5B58\u5728: ${f.view.entry}`}}return{ok:!0,plugin:{name:i.name,version:typeof i.version=="string"?i.version:void 0,description:typeof i.description=="string"?i.description:void 0,source:r,installedAt:u,dir:e,enabled:!0,tools:p,listeners:g,commandDir:A,ui:f,userConfig:h,configValues:v,configuredKeys:j,status:"enabled",runtimes:g.map(n=>({def:n,stopping:!1,restarts:0,logs:[]})),moduleCache:new Map,importNonce:++this.importNonce}}}}function P(s){const e=s.inputSchema;if(!(!e||!Array.isArray(e.required)))return e.required.filter(r=>typeof r=="string")}function q(s){const e=s.ui;if(!e)return;const r=e.icon?N.includes(e.icon)?`builtin:${e.icon}`:e.icon:void 0,u=e.status?{tool:e.status.tool,persistent:e.status.persistent===!0,...e.status.hideWhenZero===!0?{hideWhenZero:!0}:{},pollIntervalMs:typeof e.status.pollIntervalMs=="number"&&e.status.pollIntervalMs>=5e3&&e.status.pollIntervalMs<=3e5?e.status.pollIntervalMs:3e4,...e.status.title?{title:e.status.title}:{}}:void 0,a=e.view?{entry:e.view.entry,title:e.view.title,invoke:[...e.view.invoke??[]],...e.view.defaultRoute?{defaultRoute:e.view.defaultRoute}:{}}:void 0;if(!(!u&&!a))return{...r?{icon:r}:{},...u?{status:u}:{},...a?{view:a}:{}}}function U(s,e){const r=t=>!!(t.child||t.timer)||t.def.transport?.type==="http-callback",u=t=>s.enabled?r(t)?"running":t.stopping?"stopped":"pending":"stopped",a=s.runtimes.map(t=>{const d=u(t);return{event:t.def.event,delivery:t.def.delivery??"poll",running:d==="running",state:d,error:t.lastError}}),o=a.some(t=>t.state==="running")?"running":a.some(t=>t.state==="pending")?"pending":"stopped",i=q(s),y=s.configuredKeys??new Set,c=e?R(e):{},p=(s.userConfig??[]).map(t=>{const d=typeof c[t.key]=="string"&&c[t.key].length>0?c[t.key]:typeof process.env[t.key]=="string"&&(process.env[t.key]??"").length>0?process.env[t.key]:void 0,m=y.has(t.key)?"json":d!==void 0?"env":"default",g=typeof s.configValues[t.key]=="string"&&s.configValues[t.key].length>0?s.configValues[t.key]:d!==void 0?d:typeof t.default=="string"?t.default:"";return{key:t.key,...t.description?{description:t.description}:{},...t.required?{required:!0}:{},...t.sensitive?{sensitive:!0}:{},source:m,...g.length>0?{value:g}:{}}});return{name:s.name,version:s.version,description:s.description,status:s.status,enabled:s.enabled,source:s.source,installedAt:s.installedAt,toolCount:s.tools.length,tools:s.tools.map(t=>({name:t.name,title:t.title,description:t.description})),listeners:a,running:o==="running",listenerState:o,error:s.error,...i?{frontend:i}:{},...p.length>0?{userConfig:p}:{}}}export{L as PluginLoader,P as requiredParamsOf,q as toFrontendSummary,U as toSummary};
2
2