@agenthippo-ai/agenthippo 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (480) hide show
  1. package/LICENSE +21 -0
  2. package/bin/agenthippo.js +2 -0
  3. package/out/agentpack/github.js +547 -0
  4. package/out/agentpack/index.js +66 -0
  5. package/out/agentpack/install.js +297 -0
  6. package/out/agentpack/manager.js +441 -0
  7. package/out/agentpack/manifest.js +135 -0
  8. package/out/agentpack/paths.js +475 -0
  9. package/out/agentpack/publish.js +248 -0
  10. package/out/agentpack/stores.js +554 -0
  11. package/out/agentpack/types.js +5 -0
  12. package/out/analytics/dashboard/artifactManager.js +439 -0
  13. package/out/analytics/dashboard/fleetDisplayUtils.js +159 -0
  14. package/out/analytics/dashboard/fleetOrchestrator.js +142 -0
  15. package/out/analytics/dashboard/fleetRegistry.js +79 -0
  16. package/out/analytics/dashboard/fleetRowDefaults.js +87 -0
  17. package/out/analytics/dashboard/fleetScriptAdapter.js +146 -0
  18. package/out/analytics/dashboard/fleetStatusUtils.js +30 -0
  19. package/out/analytics/dashboard/fleetTitleUtils.js +68 -0
  20. package/out/analytics/dashboard/fleetTypes.js +29 -0
  21. package/out/analytics/dashboard/index.js +17 -0
  22. package/out/analytics/dashboard/indexingService.js +422 -0
  23. package/out/analytics/dashboard/localFleetAdapter.js +222 -0
  24. package/out/analytics/dashboard/performanceMonitor.js +76 -0
  25. package/out/analytics/dashboard/processManager.js +209 -0
  26. package/out/analytics/dashboard/provider.js +3885 -0
  27. package/out/analytics/dashboard/queryRunner.js +994 -0
  28. package/out/analytics/dashboard/refreshPolicy.js +16 -0
  29. package/out/analytics/dashboard/scheduledFleetFingerprint.js +22 -0
  30. package/out/analytics/dashboard/scheduledFleetStorage.js +241 -0
  31. package/out/analytics/dashboard/scheduledFleetUtils.js +22 -0
  32. package/out/analytics/dashboard/sessionEventFleetStats.js +118 -0
  33. package/out/analytics/dashboard/sessionJsonlFleet.js +204 -0
  34. package/out/analytics/dashboard/teamViewDiscovery.js +106 -0
  35. package/out/analytics/dashboard/viewsConfigMerge.js +221 -0
  36. package/out/analytics/dashboard/webview/analytics-panel.html +155 -0
  37. package/out/analytics/dashboard/webview/codicon.ttf +0 -0
  38. package/out/analytics/dashboard/webview/index.html +78 -0
  39. package/out/analytics/dashboard/webview/panel.js +2295 -0
  40. package/out/analytics/dashboard/webview/runtime-bridge.js +82 -0
  41. package/out/analytics/dashboard/webview/styles.css +1009 -0
  42. package/out/analytics/lifecycle.js +43 -0
  43. package/out/analytics/service.js +1279 -0
  44. package/out/analytics/sessionEvents.js +231 -0
  45. package/out/auth/bootstrapApply.js +72 -0
  46. package/out/auth/brokerClient.js +126 -0
  47. package/out/auth/callbackUri.js +59 -0
  48. package/out/auth/callbackUriParse.js +59 -0
  49. package/out/auth/githubStoreGate.js +70 -0
  50. package/out/auth/loopbackAuthServer.js +165 -0
  51. package/out/auth/pkce.js +9 -0
  52. package/out/auth/provider.js +239 -0
  53. package/out/auth/sessionStore.js +193 -0
  54. package/out/auth/signInFlow.js +182 -0
  55. package/out/auth/types.js +12 -0
  56. package/out/auth-broker/config.js +62 -0
  57. package/out/auth-broker/jwt.js +105 -0
  58. package/out/auth-broker/pkce.js +57 -0
  59. package/out/auth-broker/server.js +539 -0
  60. package/out/auth-broker/store.js +273 -0
  61. package/out/base-prompts/gateway/openclaw-starter.json5 +144 -0
  62. package/out/base-prompts/gateway/slack-socket-mode-minimal.manifest.json +44 -0
  63. package/out/base-prompts/mcp-servers/.mcp.json +13 -0
  64. package/out/base-prompts/mcp-servers/langfuse-analytics/README.md +142 -0
  65. package/out/base-prompts/mcp-servers/langfuse-analytics/mcp.json +13 -0
  66. package/out/base-prompts/mcp-servers/langfuse-analytics/package-lock.json +1192 -0
  67. package/out/base-prompts/mcp-servers/langfuse-analytics/package.json +23 -0
  68. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/run-with-env.sh +12 -0
  69. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/sdk-test.js +102 -0
  70. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/simple-test.js +137 -0
  71. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/test-client.js +118 -0
  72. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/test-server.js +209 -0
  73. package/out/base-prompts/mcp-servers/langfuse-analytics/src/client.ts +431 -0
  74. package/out/base-prompts/mcp-servers/langfuse-analytics/src/index.ts +270 -0
  75. package/out/base-prompts/mcp-servers/langfuse-analytics/tsconfig.json +18 -0
  76. package/out/base-prompts/rules/AGENTS.md +204 -0
  77. package/out/base-prompts/skills/agent-browser/SKILL.md +102 -0
  78. package/out/base-prompts/skills/agent-builder/SKILL.md +73 -0
  79. package/out/base-prompts/skills/agent-builder/references/agent-pack.md +63 -0
  80. package/out/base-prompts/skills/agent-builder/references/crewai.md +66 -0
  81. package/out/base-prompts/skills/agent-builder/references/langchain.md +60 -0
  82. package/out/base-prompts/skills/agent-builder/references/raw-sdk.md +73 -0
  83. package/out/base-prompts/skills/agent-engine-creator/SKILL.md +586 -0
  84. package/out/base-prompts/skills/agent-engine-installer/SKILL.md +106 -0
  85. package/out/base-prompts/skills/agent-engine-installer/scripts/install-engine.mjs +259 -0
  86. package/out/base-prompts/skills/agent-engine-installer/scripts/install-engine.ps1 +189 -0
  87. package/out/base-prompts/skills/agenthippo-cli/SKILL.md +69 -0
  88. package/out/base-prompts/skills/agenthippo-cli/scripts/install.sh +63 -0
  89. package/out/base-prompts/skills/agentpack-creator/SKILL.md +375 -0
  90. package/out/base-prompts/skills/agentpack-creator/references/agent-templates.md +261 -0
  91. package/out/base-prompts/skills/agentpack-creator/references/agents-md-guide.md +195 -0
  92. package/out/base-prompts/skills/agentpack-creator/scripts/init_pack.py +391 -0
  93. package/out/base-prompts/skills/agentpack-creator/scripts/init_pack_test.py +294 -0
  94. package/out/base-prompts/skills/agentpack-testbench/SKILL.md +135 -0
  95. package/out/base-prompts/skills/algorithmic-art/LICENSE.txt +202 -0
  96. package/out/base-prompts/skills/algorithmic-art/SKILL.md +405 -0
  97. package/out/base-prompts/skills/algorithmic-art/templates/generator_template.js +223 -0
  98. package/out/base-prompts/skills/algorithmic-art/templates/viewer.html +599 -0
  99. package/out/base-prompts/skills/debug-agent/SKILL.md +83 -0
  100. package/out/base-prompts/skills/desktop-automation/SKILL.md +166 -0
  101. package/out/base-prompts/skills/desktop-automation/references/agenthippo-ui-recipes.md +441 -0
  102. package/out/base-prompts/skills/desktop-automation/scripts/windows-desktop-uia.psm1 +280 -0
  103. package/out/base-prompts/skills/docx/LICENSE.txt +30 -0
  104. package/out/base-prompts/skills/docx/SKILL.md +197 -0
  105. package/out/base-prompts/skills/docx/docx-js.md +350 -0
  106. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  107. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  108. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  109. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  110. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  111. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  112. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  113. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  114. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  115. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  116. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  117. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  118. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  119. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  120. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  121. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  122. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  123. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  124. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  125. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  126. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  127. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  128. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  129. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  130. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  131. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  132. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  133. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  134. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  135. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  136. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  137. package/out/base-prompts/skills/docx/ooxml/schemas/mce/mc.xsd +75 -0
  138. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  139. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  140. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  141. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  142. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  143. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  144. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  145. package/out/base-prompts/skills/docx/ooxml/scripts/pack.py +159 -0
  146. package/out/base-prompts/skills/docx/ooxml/scripts/unpack.py +29 -0
  147. package/out/base-prompts/skills/docx/ooxml/scripts/validate.py +69 -0
  148. package/out/base-prompts/skills/docx/ooxml/scripts/validation/__init__.py +15 -0
  149. package/out/base-prompts/skills/docx/ooxml/scripts/validation/base.py +951 -0
  150. package/out/base-prompts/skills/docx/ooxml/scripts/validation/docx.py +274 -0
  151. package/out/base-prompts/skills/docx/ooxml/scripts/validation/pptx.py +315 -0
  152. package/out/base-prompts/skills/docx/ooxml/scripts/validation/redlining.py +279 -0
  153. package/out/base-prompts/skills/docx/ooxml.md +610 -0
  154. package/out/base-prompts/skills/docx/scripts/__init__.py +1 -0
  155. package/out/base-prompts/skills/docx/scripts/document.py +1276 -0
  156. package/out/base-prompts/skills/docx/scripts/templates/comments.xml +3 -0
  157. package/out/base-prompts/skills/docx/scripts/templates/commentsExtended.xml +3 -0
  158. package/out/base-prompts/skills/docx/scripts/templates/commentsExtensible.xml +3 -0
  159. package/out/base-prompts/skills/docx/scripts/templates/commentsIds.xml +3 -0
  160. package/out/base-prompts/skills/docx/scripts/templates/people.xml +3 -0
  161. package/out/base-prompts/skills/docx/scripts/utilities.py +374 -0
  162. package/out/base-prompts/skills/gateway-outbound/SKILL.md +136 -0
  163. package/out/base-prompts/skills/mcp-builder/LICENSE.txt +202 -0
  164. package/out/base-prompts/skills/mcp-builder/SKILL.md +328 -0
  165. package/out/base-prompts/skills/mcp-builder/reference/evaluation.md +602 -0
  166. package/out/base-prompts/skills/mcp-builder/reference/mcp_best_practices.md +249 -0
  167. package/out/base-prompts/skills/mcp-builder/reference/node_mcp_server.md +970 -0
  168. package/out/base-prompts/skills/mcp-builder/reference/python_mcp_server.md +719 -0
  169. package/out/base-prompts/skills/mcp-builder/scripts/connections.py +151 -0
  170. package/out/base-prompts/skills/mcp-builder/scripts/evaluation.py +373 -0
  171. package/out/base-prompts/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
  172. package/out/base-prompts/skills/mcp-builder/scripts/requirements.txt +2 -0
  173. package/out/base-prompts/skills/openclaw/SKILL.md +406 -0
  174. package/out/base-prompts/skills/openclaw/scripts/run-smoke.sh +61 -0
  175. package/out/base-prompts/skills/pdf/LICENSE.txt +30 -0
  176. package/out/base-prompts/skills/pdf/SKILL.md +294 -0
  177. package/out/base-prompts/skills/pdf/forms.md +205 -0
  178. package/out/base-prompts/skills/pdf/reference.md +612 -0
  179. package/out/base-prompts/skills/pdf/scripts/check_bounding_boxes.py +70 -0
  180. package/out/base-prompts/skills/pdf/scripts/check_bounding_boxes_test.py +226 -0
  181. package/out/base-prompts/skills/pdf/scripts/check_fillable_fields.py +12 -0
  182. package/out/base-prompts/skills/pdf/scripts/convert_pdf_to_images.py +35 -0
  183. package/out/base-prompts/skills/pdf/scripts/create_validation_image.py +41 -0
  184. package/out/base-prompts/skills/pdf/scripts/extract_form_field_info.py +152 -0
  185. package/out/base-prompts/skills/pdf/scripts/fill_fillable_fields.py +114 -0
  186. package/out/base-prompts/skills/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
  187. package/out/base-prompts/skills/pptx/LICENSE.txt +30 -0
  188. package/out/base-prompts/skills/pptx/SKILL.md +484 -0
  189. package/out/base-prompts/skills/pptx/html2pptx.md +625 -0
  190. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  191. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  192. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  193. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  194. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  195. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  196. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  197. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  198. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  199. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  200. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  201. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  202. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  203. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  204. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  205. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  206. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  207. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  208. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  209. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  210. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  211. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  212. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  213. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  214. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  215. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  216. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  217. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  218. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  219. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  220. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  221. package/out/base-prompts/skills/pptx/ooxml/schemas/mce/mc.xsd +75 -0
  222. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  223. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  224. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  225. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  226. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  227. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  228. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  229. package/out/base-prompts/skills/pptx/ooxml/scripts/pack.py +159 -0
  230. package/out/base-prompts/skills/pptx/ooxml/scripts/unpack.py +29 -0
  231. package/out/base-prompts/skills/pptx/ooxml/scripts/validate.py +69 -0
  232. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/__init__.py +15 -0
  233. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/base.py +951 -0
  234. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/docx.py +274 -0
  235. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/pptx.py +315 -0
  236. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/redlining.py +279 -0
  237. package/out/base-prompts/skills/pptx/ooxml.md +427 -0
  238. package/out/base-prompts/skills/pptx/scripts/html2pptx.js +984 -0
  239. package/out/base-prompts/skills/pptx/scripts/inventory.py +1020 -0
  240. package/out/base-prompts/skills/pptx/scripts/rearrange.py +231 -0
  241. package/out/base-prompts/skills/pptx/scripts/replace.py +385 -0
  242. package/out/base-prompts/skills/pptx/scripts/thumbnail.py +450 -0
  243. package/out/base-prompts/skills/prompt-lab/SKILL.md +149 -0
  244. package/out/base-prompts/skills/prompt-lab/scripts/query-analytics.sh +2551 -0
  245. package/out/base-prompts/skills/skill-creator/LICENSE.txt +202 -0
  246. package/out/base-prompts/skills/skill-creator/SKILL.md +371 -0
  247. package/out/base-prompts/skills/skill-creator/references/output-patterns.md +82 -0
  248. package/out/base-prompts/skills/skill-creator/references/workflows.md +28 -0
  249. package/out/base-prompts/skills/skill-creator/scripts/init_skill.py +303 -0
  250. package/out/base-prompts/skills/skill-creator/scripts/package_skill.py +110 -0
  251. package/out/base-prompts/skills/skill-creator/scripts/quick_validate.py +95 -0
  252. package/out/base-prompts/skills/skill-installer/SKILL.md +251 -0
  253. package/out/base-prompts/skills/skill-installer/references/store-api.md +219 -0
  254. package/out/base-prompts/skills/spotlight-dashboard/SKILL.md +83 -0
  255. package/out/base-prompts/skills/spotlight-insights/SKILL.md +101 -0
  256. package/out/base-prompts/skills/spotlight-optimize/SKILL.md +93 -0
  257. package/out/base-prompts/skills/spotlight-optimize/scripts/query-analytics.sh +2551 -0
  258. package/out/base-prompts/skills/spotlight-query/SKILL.md +314 -0
  259. package/out/base-prompts/skills/spotlight-query/references/otel-schema.md +163 -0
  260. package/out/base-prompts/skills/spotlight-query/scripts/query-analytics.sh +2551 -0
  261. package/out/base-prompts/skills/spotlight-query/scripts/query-analytics.test.sh +744 -0
  262. package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/sessions/sess-test-1.jsonl +14 -0
  263. package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/traces/.duckdb-index.json +7 -0
  264. package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/traces/sample.jsonl +5 -0
  265. package/out/base-prompts/skills/spotlight-report/SKILL.md +86 -0
  266. package/out/base-prompts/skills/spotlight-visualize/SKILL.md +92 -0
  267. package/out/base-prompts/skills/spotlight-visualize/scripts/query-analytics.sh +2551 -0
  268. package/out/base-prompts/skills/xlsx/LICENSE.txt +30 -0
  269. package/out/base-prompts/skills/xlsx/SKILL.md +289 -0
  270. package/out/base-prompts/skills/xlsx/recalc.py +178 -0
  271. package/out/branding.js +23 -0
  272. package/out/cli/commands/anywhere.js +66 -0
  273. package/out/cli/commands/ask.js +243 -0
  274. package/out/cli/commands/auth-broker.js +24 -0
  275. package/out/cli/commands/auth.js +219 -0
  276. package/out/cli/commands/chat.js +354 -0
  277. package/out/cli/commands/deploy.js +223 -0
  278. package/out/cli/commands/gateway.js +160 -0
  279. package/out/cli/commands/pack.js +220 -0
  280. package/out/cli/commands/probe-custom-engine.js +82 -0
  281. package/out/cli/commands/serve.js +583 -0
  282. package/out/cli/commands/store.js +919 -0
  283. package/out/cli/credential-context.js +113 -0
  284. package/out/cli/deploy-init.js +2087 -0
  285. package/out/cli/deps.js +238 -0
  286. package/out/cli/index.js +390 -0
  287. package/out/cli/pack-loader.js +376 -0
  288. package/out/cli/run-custom-engine-runner.js +318 -0
  289. package/out/cli/runtime.js +409 -0
  290. package/out/cli/serve-hardening.js +325 -0
  291. package/out/cli/state-sync.js +135 -0
  292. package/out/cli/utils.js +220 -0
  293. package/out/cli/vscode-shim.js +86 -0
  294. package/out/engines/base.js +159 -0
  295. package/out/engines/claude.js +1215 -0
  296. package/out/engines/codex.js +759 -0
  297. package/out/engines/custom.js +632 -0
  298. package/out/engines/customEngineIpc.js +95 -0
  299. package/out/engines/customEngineRunnerEmbed.js +107 -0
  300. package/out/engines/customRegistry.js +274 -0
  301. package/out/engines/embeddedCustomEngineRunner.generated.js +9 -0
  302. package/out/engines/engineApiKey.js +138 -0
  303. package/out/engines/factory.js +45 -0
  304. package/out/engines/install.js +372 -0
  305. package/out/engines/persistentEngineWorker.js +320 -0
  306. package/out/engines/publish.js +341 -0
  307. package/out/engines/types.js +17 -0
  308. package/out/examples/run-headless-repl.js +291 -0
  309. package/out/examples/run-headless.js +187 -0
  310. package/out/extension.js +4472 -0
  311. package/out/gateway/bridge.js +805 -0
  312. package/out/gateway/cli-agent-id.js +36 -0
  313. package/out/gateway/client.js +303 -0
  314. package/out/gateway/client.test.js +395 -0
  315. package/out/gateway/gateway-scope-errors.js +14 -0
  316. package/out/gateway/gatewayBackup.js +76 -0
  317. package/out/gateway/gatewayRouteIndex.js +371 -0
  318. package/out/gateway/gatewaySessionStore.js +243 -0
  319. package/out/gateway/index.js +31 -0
  320. package/out/gateway/lifecycle.js +3056 -0
  321. package/out/gateway/openclaw-channel-routing.js +317 -0
  322. package/out/gateway/outboundHandles.js +373 -0
  323. package/out/gateway/outboundPaths.js +72 -0
  324. package/out/gateway/outboundSend.js +254 -0
  325. package/out/gateway/protocol.js +48 -0
  326. package/out/gateway/resetMappings.js +52 -0
  327. package/out/gateway/service.js +1244 -0
  328. package/out/gateway/sessionRouting.js +77 -0
  329. package/out/headless/index.js +505 -0
  330. package/out/headless/sync.js +473 -0
  331. package/out/mcp/publish.js +143 -0
  332. package/out/mcp.js +597 -0
  333. package/out/permissions.js +108 -0
  334. package/out/permissions.mapping.yaml +68 -0
  335. package/out/registry/index.js +332 -0
  336. package/out/remote/handleRemoteChat.js +122 -0
  337. package/out/remote/remotePackStatusBar.js +103 -0
  338. package/out/remote/serveClient.js +216 -0
  339. package/out/remoteSkills.js +191 -0
  340. package/out/runtime/index.js +32 -0
  341. package/out/runtime/interfaces/config-provider.js +32 -0
  342. package/out/runtime/interfaces/edit-tracker.js +22 -0
  343. package/out/runtime/interfaces/index.js +29 -0
  344. package/out/runtime/interfaces/logger.js +40 -0
  345. package/out/runtime/interfaces/permission-handler.js +66 -0
  346. package/out/runtime/interfaces/session-store.js +342 -0
  347. package/out/runtime/vscode/index.js +20 -0
  348. package/out/runtime/vscode/vscode-config-provider.js +77 -0
  349. package/out/runtime/vscode/vscode-edit-tracker.js +120 -0
  350. package/out/runtime/vscode/vscode-logger.js +30 -0
  351. package/out/runtime/vscode/vscode-permission-handler.js +72 -0
  352. package/out/runtime/vscode/vscode-session-store.js +22 -0
  353. package/out/scripts/agentide-litellm.ps1 +501 -0
  354. package/out/scripts/agentide-litellm.sh +700 -0
  355. package/out/scripts/agentide_litellm_hooks_v1.py +604 -0
  356. package/out/scripts/analytics/agent-fleet-widget.js +954 -0
  357. package/out/scripts/analytics/agentide-litellm-otel.config.yaml +160 -0
  358. package/out/scripts/analytics/default-seed-scripts.json +12 -0
  359. package/out/scripts/analytics/duckdbLocator.js +29 -0
  360. package/out/scripts/analytics/fleet-local-adapter.js +246 -0
  361. package/out/scripts/analytics/fleet-workflow.sh +263 -0
  362. package/out/scripts/analytics/generate-default-charts.py +685 -0
  363. package/out/scripts/analytics/hotspot-analysis-widget.js +909 -0
  364. package/out/scripts/analytics/index-traces.py +1394 -0
  365. package/out/scripts/analytics/install-analytics.sh +286 -0
  366. package/out/scripts/analytics/live-fleet-4-collector.cjs +315 -0
  367. package/out/scripts/analytics/live-fleet-4-daemon.mjs +134 -0
  368. package/out/scripts/analytics/live-fleet-4-widget.cjs +433 -0
  369. package/out/scripts/analytics/otel-collector.yaml +55 -0
  370. package/out/scripts/analytics/query-analytics.ps1 +396 -0
  371. package/out/scripts/analytics/query-analytics.sh +2551 -0
  372. package/out/scripts/analytics/session-comparison-widget.js +1468 -0
  373. package/out/scripts/analytics/session-timeline-widget.js +2137 -0
  374. package/out/scripts/analytics/setup-analytics.ps1 +432 -0
  375. package/out/scripts/analytics/setup-analytics.sh +854 -0
  376. package/out/scripts/analytics/start-analytics.ps1 +169 -0
  377. package/out/scripts/analytics/start-analytics.sh +323 -0
  378. package/out/scripts/analytics/token-cost-flamegraph-widget.js +954 -0
  379. package/out/scripts/analytics/token-cost-trend-widget.js +1062 -0
  380. package/out/scripts/analytics/workflows-collector.cjs +315 -0
  381. package/out/scripts/analytics/workflows-daemon.mjs +186 -0
  382. package/out/scripts/analytics/workflows-widget.cjs +433 -0
  383. package/out/scripts/analytics/wow-model-widget.js +191 -0
  384. package/out/scripts/gateway/Dockerfile.serve +45 -0
  385. package/out/scripts/gateway/docker-serve.sh +248 -0
  386. package/out/scripts/gateway/setup-gateway-server.ps1 +953 -0
  387. package/out/scripts/gateway/setup-gateway-server.sh +935 -0
  388. package/out/scripts/gateway/setup-gateway.ps1 +1813 -0
  389. package/out/scripts/gateway/setup-gateway.sh +1541 -0
  390. package/out/scripts/setup-cli.ps1 +86 -0
  391. package/out/scripts/setup-cli.sh +117 -0
  392. package/out/scripts/tools-manifest.json +83 -0
  393. package/out/scripts/vendor-tools.mjs +234 -0
  394. package/out/session.js +272 -0
  395. package/out/shared/agentEngines.js +170 -0
  396. package/out/shared/index.js +109 -0
  397. package/out/shared/models.js +235 -0
  398. package/out/shared/providers.js +202 -0
  399. package/out/skills/publish.js +178 -0
  400. package/out/spotlight/install.js +339 -0
  401. package/out/spotlight/publish.js +544 -0
  402. package/out/spotlight/yaml.js +31 -0
  403. package/out/store/github/setup.js +235 -0
  404. package/out/store/github/templates/build-index.ts +339 -0
  405. package/out/store/github/templates/build-index.yml +97 -0
  406. package/out/store/github/templates/package.json +11 -0
  407. package/out/store/index.js +755 -0
  408. package/out/store/oramaIndex.js +884 -0
  409. package/out/store/shared.js +241 -0
  410. package/out/sync.js +1827 -0
  411. package/out/terminalLogger.js +358 -0
  412. package/out/test/agentEnvFile.test.js +97 -0
  413. package/out/test/agentYaml.test.js +373 -0
  414. package/out/test/agentpack.test.js +639 -0
  415. package/out/test/analytics-lifecycle.test.js +174 -0
  416. package/out/test/analytics.test.js +524 -0
  417. package/out/test/auth-bootstrapApply.test.js +102 -0
  418. package/out/test/auth-broker.test.js +434 -0
  419. package/out/test/auth-callback.test.js +62 -0
  420. package/out/test/branding.test.js +229 -0
  421. package/out/test/cli-agent-id.test.js +55 -0
  422. package/out/test/credential-context.test.js +105 -0
  423. package/out/test/customEngineInstall.test.js +100 -0
  424. package/out/test/customRegistry.test.js +122 -0
  425. package/out/test/deploy-init.test.js +532 -0
  426. package/out/test/deps-auto-install.test.js +81 -0
  427. package/out/test/engine-integration.test.js +297 -0
  428. package/out/test/enginePaths.test.js +195 -0
  429. package/out/test/enginePublish.test.js +82 -0
  430. package/out/test/fleetDisplayUtils.test.js +96 -0
  431. package/out/test/gateway-client.test.js +381 -0
  432. package/out/test/gateway-lifecycle.test.js +608 -0
  433. package/out/test/gateway-outbound.test.js +531 -0
  434. package/out/test/gateway-reset-mappings.test.js +221 -0
  435. package/out/test/gateway-route-index.test.js +235 -0
  436. package/out/test/gateway-session-routing.test.js +47 -0
  437. package/out/test/gateway-session-store.test.js +216 -0
  438. package/out/test/github.test.js +232 -0
  439. package/out/test/headless-sync.test.js +279 -0
  440. package/out/test/helpers/manifest-fixtures.js +27 -0
  441. package/out/test/mcp-obo.test.js +82 -0
  442. package/out/test/mcp.test.js +307 -0
  443. package/out/test/openclaw-channel-routing.test.js +191 -0
  444. package/out/test/pathSafety.test.js +63 -0
  445. package/out/test/permissions.test.js +175 -0
  446. package/out/test/persistent-engine-worker.test.js +220 -0
  447. package/out/test/refreshPolicy.test.js +60 -0
  448. package/out/test/registry.test.js +351 -0
  449. package/out/test/runtime.test.js +349 -0
  450. package/out/test/scheduledFleetStorage.test.js +72 -0
  451. package/out/test/serve-hardening.test.js +192 -0
  452. package/out/test/serveClient.test.js +173 -0
  453. package/out/test/sessionJsonlFleet.test.js +78 -0
  454. package/out/test/shared.test.js +173 -0
  455. package/out/test/skills-mcp.test.js +299 -0
  456. package/out/test/spotlightPublish.test.js +299 -0
  457. package/out/test/spotlightYaml.test.js +58 -0
  458. package/out/test/state-sync-peer.test.js +74 -0
  459. package/out/test/store.test.js +331 -0
  460. package/out/test/stores.test.js +504 -0
  461. package/out/test/sync-switch.test.js +251 -0
  462. package/out/test/teamViewDiscovery.test.js +90 -0
  463. package/out/test/toolPath.test.js +120 -0
  464. package/out/test/utils.test.js +308 -0
  465. package/out/test/viewsConfigMerge.test.js +180 -0
  466. package/out/test/windows-command-line.test.js +75 -0
  467. package/out/utils/agentEnvFile.js +131 -0
  468. package/out/utils/binary.js +175 -0
  469. package/out/utils/index.js +37 -0
  470. package/out/utils/network.js +74 -0
  471. package/out/utils/pathSafety.js +60 -0
  472. package/out/utils/paths.js +116 -0
  473. package/out/utils/pid.js +180 -0
  474. package/out/utils/pythonRunner.js +258 -0
  475. package/out/utils/resolveNodeBinary.js +168 -0
  476. package/out/utils/toolPath.js +83 -0
  477. package/out/utils/windowsCommandLine.js +29 -0
  478. package/out/utils.js +915 -0
  479. package/out/workspaceFolders.js +59 -0
  480. package/package.json +41 -0
@@ -0,0 +1,1813 @@
1
+ #
2
+ # Agent Anywhere -- Gateway Setup (Windows)
3
+ #
4
+ # Installs OpenClaw Gateway and builds the web UI so users can
5
+ # configure messaging channels (Telegram, WhatsApp, Slack, etc.)
6
+ #
7
+ # Usage:
8
+ # .\setup-gateway.ps1 # Interactive
9
+ # .\setup-gateway.ps1 -Source "openclaw/openclaw#branch" # Specify source
10
+ # .\setup-gateway.ps1 -Source "github:org/repo" # npm git protocol
11
+ # .\setup-gateway.ps1 -Source "C:\dev\openclaw" # Local source
12
+ # .\setup-gateway.ps1 -Check # Check status only
13
+ # .\setup-gateway.ps1 -Uninstall # stop gateway + npm uninstall -g openclaw
14
+ # .\setup-gateway.ps1 -Reinstall -Source <src> # uninstall, verify, then install
15
+ # .\setup-gateway.ps1 -NoModifyPath # opt out: skip adding wrapper dir to PATH
16
+ #
17
+
18
+ param(
19
+ [string]$Source = "",
20
+ [switch]$Check,
21
+ [switch]$Uninstall,
22
+ [switch]$Reinstall,
23
+ [switch]$ModifyPath,
24
+ [switch]$NoModifyPath,
25
+ [int]$Port = 18789,
26
+ [string]$ConfigTemplate = ""
27
+ )
28
+
29
+ $ErrorActionPreference = "Stop"
30
+
31
+ function Read-OpenclawConfigGatewayPort {
32
+ $cfg = Join-Path $env:USERPROFILE ".openclaw\openclaw.json"
33
+ if (-not (Test-Path -LiteralPath $cfg)) { return $null }
34
+ if (-not (Get-Command node -ErrorAction SilentlyContinue)) { return $null }
35
+ $expr = 'const fs=require("fs");const p=require("path");const o=require("os");const f=p.join(o.homedir(),".openclaw","openclaw.json");if(!fs.existsSync(f))process.exit(1);let t=fs.readFileSync(f,"utf8");t=t.replace(/^\s*\/\/.*$/gm,"").replace(/,\s*([\]}])/g,"$1");try{const j=JSON.parse(t);const x=j&&j.gateway&&j.gateway.port;if(typeof x==="number"&&x>=1&&x<=65535){process.stdout.write(String(x));process.exit(0)}if(typeof x==="string"&&/^[0-9]+$/.test(x)){process.stdout.write(x);process.exit(0)}}catch(z){}process.exit(1);'
36
+ try {
37
+ $raw = & node -e $expr 2>$null
38
+ if ($null -ne $raw -and "$raw" -match '^[0-9]+$') { return [int]"$raw" }
39
+ } catch { }
40
+ return $null
41
+ }
42
+
43
+ if (-not $PSBoundParameters.ContainsKey('Port')) {
44
+ $cfgPort = Read-OpenclawConfigGatewayPort
45
+ if ($null -ne $cfgPort) { $Port = $cfgPort }
46
+ }
47
+
48
+ # ============================================================================
49
+ # Logging helpers
50
+ # ============================================================================
51
+ function Log-Info { param([string]$msg) Write-Host "[INFO] $msg" -ForegroundColor Blue }
52
+ function Log-Success { param([string]$msg) Write-Host " [OK] $msg" -ForegroundColor Green }
53
+ function Log-Warn { param([string]$msg) Write-Host " [WARN] $msg" -ForegroundColor Yellow }
54
+ function Log-Error { param([string]$msg) Write-Host "[ERROR] $msg" -ForegroundColor Red }
55
+ function Log-Step { param([string]$msg) Write-Host "`n$msg" -ForegroundColor Cyan }
56
+
57
+ $script:NodeRequiredVersion = "22.14.0"
58
+ $script:NodeBootstrapVersion = if ($env:AGENT_ANYWHERE_NODE_VERSION) { $env:AGENT_ANYWHERE_NODE_VERSION.TrimStart('v') } else { "22.22.0" }
59
+ $script:NodeBootstrapRoot = Join-Path $env:USERPROFILE ".agenthippo\tools\node"
60
+ $script:NpmGlobalPrefix = Join-Path $env:USERPROFILE ".npm-global"
61
+ $script:ManagedGatewayStateDir = Join-Path $env:USERPROFILE ".agenthippo\gateway"
62
+ $script:ManagedGatewayManifestPath = Join-Path $script:ManagedGatewayStateDir "install.json"
63
+ $script:GatewayInstallStatusPath = Join-Path $script:ManagedGatewayStateDir "install-status.json"
64
+ $script:ManagedGatewayWrapperDir = if ($env:LOCALAPPDATA) { Join-Path $env:LOCALAPPDATA "AgentHippo\bin" } else { Join-Path (Join-Path $env:USERPROFILE "AppData\Local") "AgentHippo\bin" }
65
+ $script:ManagedGatewayWrapperMarker = "REM Managed by Agent Anywhere"
66
+ $script:GatewayInstallStatus = $null
67
+ $script:ModifyPath = $true
68
+ if ($NoModifyPath -or $env:AGENT_ANYWHERE_MODIFY_PATH -eq "0") {
69
+ $script:ModifyPath = $false
70
+ }
71
+
72
+ function Reset-GatewayInstallStatus {
73
+ $script:GatewayInstallStatus = @{
74
+ phase = "starting"
75
+ message = "Starting Agent Anywhere setup..."
76
+ lastError = $null
77
+ updatedAt = $null
78
+ steps = @{
79
+ cliVersionWorks = $false
80
+ npmInstallComplete = $false
81
+ wrapperExists = $false
82
+ configExists = $false
83
+ distExists = $false
84
+ webUiExists = $false
85
+ finalCheckPassed = $false
86
+ }
87
+ }
88
+ }
89
+
90
+ function Write-GatewayInstallStatus {
91
+ if ($null -eq $script:GatewayInstallStatus) {
92
+ return
93
+ }
94
+
95
+ New-Item -ItemType Directory -Path $script:ManagedGatewayStateDir -Force | Out-Null
96
+ $script:GatewayInstallStatus.updatedAt = [DateTimeOffset]::UtcNow.ToString("o")
97
+ $json = $script:GatewayInstallStatus | ConvertTo-Json -Depth 6
98
+ $utf8NoBom = [System.Text.UTF8Encoding]::new($false)
99
+ [System.IO.File]::WriteAllText($script:GatewayInstallStatusPath, $json, $utf8NoBom)
100
+ }
101
+
102
+ function Initialize-GatewayInstallStatus {
103
+ param(
104
+ [string]$Phase,
105
+ [string]$Message
106
+ )
107
+
108
+ Reset-GatewayInstallStatus
109
+ if ($Phase) {
110
+ $script:GatewayInstallStatus.phase = $Phase
111
+ }
112
+ if ($Message) {
113
+ $script:GatewayInstallStatus.message = $Message
114
+ }
115
+ Write-GatewayInstallStatus
116
+ }
117
+
118
+ function Update-GatewayInstallStatus {
119
+ param(
120
+ [string]$Phase,
121
+ [string]$Message,
122
+ [hashtable]$StepUpdates,
123
+ [string]$LastError
124
+ )
125
+
126
+ if ($null -eq $script:GatewayInstallStatus) {
127
+ Reset-GatewayInstallStatus
128
+ }
129
+
130
+ if ($Phase) {
131
+ $script:GatewayInstallStatus.phase = $Phase
132
+ }
133
+ if ($Message) {
134
+ $script:GatewayInstallStatus.message = $Message
135
+ }
136
+ if ($PSBoundParameters.ContainsKey('LastError')) {
137
+ $script:GatewayInstallStatus.lastError = $LastError
138
+ }
139
+ if ($StepUpdates) {
140
+ foreach ($key in $StepUpdates.Keys) {
141
+ $script:GatewayInstallStatus.steps[$key] = [bool]$StepUpdates[$key]
142
+ }
143
+ }
144
+
145
+ Write-GatewayInstallStatus
146
+ }
147
+
148
+ function Complete-GatewayInstallStatus {
149
+ param(
150
+ [hashtable]$StepUpdates,
151
+ [string]$Message = "Agent Anywhere is fully installed!"
152
+ )
153
+
154
+ Update-GatewayInstallStatus -Phase "complete" -Message $Message -StepUpdates $StepUpdates -LastError $null
155
+ }
156
+
157
+ function Fail-GatewayInstallStatus {
158
+ param(
159
+ [string]$Message,
160
+ [hashtable]$StepUpdates
161
+ )
162
+
163
+ Update-GatewayInstallStatus -Phase "failed" -Message $Message -StepUpdates $StepUpdates -LastError $Message
164
+ }
165
+
166
+ function Add-PathEntry {
167
+ param([string]$Entry)
168
+ if (-not $Entry) { return }
169
+ if (-not (Test-Path -LiteralPath $Entry)) { return }
170
+ $parts = @($env:PATH -split ';' | Where-Object { $_ -ne "" })
171
+ if ($parts -contains $Entry) { return }
172
+ $env:PATH = "$Entry;$($env:PATH)"
173
+ }
174
+
175
+ function Test-PathContainsEntry {
176
+ param([string]$Entry)
177
+ if (-not $Entry) { return $false }
178
+ $parts = @($env:PATH -split ';' | Where-Object { $_ -and $_.Trim() -ne "" })
179
+ $needle = Normalize-PathForCompare -PathValue $Entry
180
+ foreach ($part in $parts) {
181
+ if ((Normalize-PathForCompare -PathValue $part) -eq $needle) {
182
+ return $true
183
+ }
184
+ }
185
+ return $false
186
+ }
187
+
188
+ function Normalize-PathForCompare {
189
+ param([string]$PathValue)
190
+ if (-not $PathValue) { return "" }
191
+ return $PathValue.Trim().TrimEnd('\').ToLowerInvariant()
192
+ }
193
+
194
+ function Get-PreferredGitBashPath {
195
+ $candidates = @()
196
+ if ($env:ProgramFiles) {
197
+ $candidates += (Join-Path $env:ProgramFiles "Git\usr\bin\bash.exe")
198
+ $candidates += (Join-Path $env:ProgramFiles "Git\bin\bash.exe")
199
+ }
200
+ $programFilesX86 = [Environment]::GetEnvironmentVariable("ProgramFiles(x86)")
201
+ if ($programFilesX86) {
202
+ $candidates += (Join-Path $programFilesX86 "Git\usr\bin\bash.exe")
203
+ $candidates += (Join-Path $programFilesX86 "Git\bin\bash.exe")
204
+ }
205
+
206
+ foreach ($candidate in $candidates) {
207
+ if ($candidate -and (Test-Path -LiteralPath $candidate)) {
208
+ return $candidate
209
+ }
210
+ }
211
+
212
+ try {
213
+ $commands = @(Get-Command bash -All -ErrorAction SilentlyContinue)
214
+ foreach ($command in $commands) {
215
+ if ($command.Source -and $command.Source -match '[\\/]Git[\\/]usr[\\/]bin[\\/]bash\.exe$') {
216
+ return $command.Source
217
+ }
218
+ }
219
+ foreach ($command in $commands) {
220
+ if ($command.Source -and $command.Source -match '[\\/]Git[\\/].*bash\.exe$') {
221
+ return $command.Source
222
+ }
223
+ }
224
+ } catch { }
225
+
226
+ return $null
227
+ }
228
+
229
+ function Invoke-WithPreferredWindowsBash {
230
+ param([scriptblock]$ScriptBlock)
231
+
232
+ $originalPath = $env:PATH
233
+ $originalScriptShell = $env:npm_config_script_shell
234
+ $shimDir = $null
235
+ try {
236
+ $gitBashPath = Get-PreferredGitBashPath
237
+ if ($gitBashPath) {
238
+ $gitBashDir = Split-Path -Parent $gitBashPath
239
+ $shimDir = Join-Path ([System.IO.Path]::GetTempPath()) ("agent-anywhere-bash-" + [guid]::NewGuid().ToString("n"))
240
+ New-Item -ItemType Directory -Path $shimDir -Force | Out-Null
241
+ $shimPath = Join-Path $shimDir "bash.cmd"
242
+ $shimContent = @(
243
+ "@echo off",
244
+ ('"{0}" %*' -f $gitBashPath)
245
+ ) -join "`r`n"
246
+ Set-Content -Path $shimPath -Value $shimContent -Encoding Ascii
247
+ $env:PATH = "$shimDir;$gitBashDir;$env:PATH"
248
+ $env:npm_config_script_shell = $gitBashPath
249
+ Log-Info "Using Git Bash for source build scripts: $gitBashPath"
250
+ }
251
+ & $ScriptBlock
252
+ } finally {
253
+ $env:PATH = $originalPath
254
+ if ($null -eq $originalScriptShell) {
255
+ Remove-Item Env:npm_config_script_shell -ErrorAction SilentlyContinue
256
+ } else {
257
+ $env:npm_config_script_shell = $originalScriptShell
258
+ }
259
+ if ($shimDir -and (Test-Path -LiteralPath $shimDir)) {
260
+ Remove-Item -LiteralPath $shimDir -Recurse -Force -ErrorAction SilentlyContinue
261
+ }
262
+ }
263
+ }
264
+
265
+ # Write the user-scope PATH via direct HKCU registry update plus a bounded,
266
+ # best-effort WM_SETTINGCHANGE broadcast.
267
+ #
268
+ # Background: [Environment]::SetEnvironmentVariable("Path", $v, "User") writes
269
+ # the registry AND synchronously broadcasts WM_SETTINGCHANGE to every top-level
270
+ # window. On Windows desktops with a wedged message pump (Explorer, an
271
+ # unresponsive Electron/Chrome window, an old Slack/Teams instance, etc.) this
272
+ # can stall the calling process for many minutes — observed during Agent
273
+ # Anywhere uninstall as a hang with the script alive but using <1s CPU and no
274
+ # child processes. We split the two steps so the registry update always
275
+ # completes, then fire-and-forget a bounded broadcast that explicitly skips
276
+ # hung windows.
277
+ function Set-UserPathRegistry {
278
+ param([AllowEmptyString()][string]$Value)
279
+ try {
280
+ $key = 'HKCU:\Environment'
281
+ if ([string]::IsNullOrEmpty($Value)) {
282
+ Remove-ItemProperty -Path $key -Name 'Path' -Force -ErrorAction SilentlyContinue
283
+ } else {
284
+ $kind = [Microsoft.Win32.RegistryValueKind]::ExpandString
285
+ try {
286
+ $existing = Get-Item -Path $key -ErrorAction Stop
287
+ $existingKind = $existing.GetValueKind('Path')
288
+ if ($existingKind -eq [Microsoft.Win32.RegistryValueKind]::String -or
289
+ $existingKind -eq [Microsoft.Win32.RegistryValueKind]::ExpandString) {
290
+ $kind = $existingKind
291
+ }
292
+ } catch { }
293
+ New-ItemProperty -Path $key -Name 'Path' -PropertyType $kind -Value $Value -Force | Out-Null
294
+ }
295
+ } catch {
296
+ return $false
297
+ }
298
+
299
+ Send-EnvironmentChangeBroadcast
300
+ return $true
301
+ }
302
+
303
+ # Bounded WM_SETTINGCHANGE broadcast. Uses SMTO_ABORTIFHUNG with a short
304
+ # per-window timeout so wedged windows do not block the script. Never throws.
305
+ $script:EnvBroadcastTypeLoaded = $false
306
+ function Send-EnvironmentChangeBroadcast {
307
+ if (-not $script:EnvBroadcastTypeLoaded) {
308
+ try {
309
+ Add-Type -Namespace AgentAnywhereWin32 -Name NativeMethods -MemberDefinition @'
310
+ [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
311
+ public static extern System.IntPtr SendMessageTimeout(
312
+ System.IntPtr hWnd,
313
+ uint Msg,
314
+ System.IntPtr wParam,
315
+ string lParam,
316
+ uint fuFlags,
317
+ uint uTimeout,
318
+ out System.UIntPtr lpdwResult);
319
+ '@ -ErrorAction Stop
320
+ $script:EnvBroadcastTypeLoaded = $true
321
+ } catch {
322
+ return
323
+ }
324
+ }
325
+ try {
326
+ $HWND_BROADCAST = [IntPtr]0xFFFF
327
+ $WM_SETTINGCHANGE = [uint32]0x001A
328
+ $SMTO_ABORTIFHUNG = [uint32]0x0002
329
+ $perWindowTimeoutMs = [uint32]500
330
+ $result = [UIntPtr]::Zero
331
+ [AgentAnywhereWin32.NativeMethods]::SendMessageTimeout(
332
+ $HWND_BROADCAST,
333
+ $WM_SETTINGCHANGE,
334
+ [IntPtr]::Zero,
335
+ 'Environment',
336
+ $SMTO_ABORTIFHUNG,
337
+ $perWindowTimeoutMs,
338
+ [ref]$result) | Out-Null
339
+ } catch { }
340
+ }
341
+
342
+ function Ensure-UserPathEntry {
343
+ param([string]$Entry)
344
+ if (-not $Entry) { return $false }
345
+ try {
346
+ New-Item -ItemType Directory -Path $Entry -Force | Out-Null
347
+ } catch { }
348
+
349
+ $current = [Environment]::GetEnvironmentVariable("Path", "User")
350
+ $parts = @()
351
+ if ($current) {
352
+ $parts = @($current -split ';' | Where-Object { $_ -and $_.Trim() -ne "" })
353
+ }
354
+ $needle = Normalize-PathForCompare -PathValue $Entry
355
+ foreach ($part in $parts) {
356
+ if ((Normalize-PathForCompare -PathValue $part) -eq $needle) {
357
+ return $false
358
+ }
359
+ }
360
+ $nextPath = if ([string]::IsNullOrWhiteSpace($current)) { $Entry } else { "$Entry;$current" }
361
+ if (Set-UserPathRegistry -Value $nextPath) {
362
+ return $true
363
+ }
364
+ Log-Warn "Could not persist PATH entry: $Entry"
365
+ return $false
366
+ }
367
+
368
+ function Remove-UserPathEntry {
369
+ param([string]$Entry)
370
+ if (-not $Entry) { return $false }
371
+ $current = [Environment]::GetEnvironmentVariable("Path", "User")
372
+ if (-not $current) { return $false }
373
+
374
+ $needle = Normalize-PathForCompare -PathValue $Entry
375
+ $parts = @($current -split ';' | Where-Object { $_ -and $_.Trim() -ne "" })
376
+ $nextParts = @()
377
+ $removed = $false
378
+ foreach ($part in $parts) {
379
+ if ((Normalize-PathForCompare -PathValue $part) -eq $needle) {
380
+ $removed = $true
381
+ continue
382
+ }
383
+ $nextParts += $part
384
+ }
385
+
386
+ if (-not $removed) { return $false }
387
+ $nextPath = if ($nextParts.Count -gt 0) { ($nextParts -join ';') } else { '' }
388
+ if (Set-UserPathRegistry -Value $nextPath) {
389
+ return $true
390
+ }
391
+ Log-Warn "Could not remove PATH entry: $Entry"
392
+ return $false
393
+ }
394
+
395
+ function Persist-UserGatewayEnvironment {
396
+ $changed = $false
397
+
398
+ if ($script:ModifyPath -and (Ensure-UserPathEntry -Entry $script:ManagedGatewayWrapperDir)) {
399
+ $changed = $true
400
+ }
401
+
402
+ if ($changed) {
403
+ Log-Info "Persisted PATH for future terminals (open a new terminal window after setup)."
404
+ }
405
+ }
406
+
407
+ function Set-NpmUserPrefix {
408
+ New-Item -ItemType Directory -Path $script:NpmGlobalPrefix -Force | Out-Null
409
+ $env:npm_config_prefix = $script:NpmGlobalPrefix
410
+ Add-PathEntry -Entry $script:NpmGlobalPrefix
411
+ }
412
+
413
+ function Test-DirectoryWritable {
414
+ param([string]$PathValue)
415
+ if (-not $PathValue) { return $false }
416
+ if (-not (Test-Path -LiteralPath $PathValue)) { return $false }
417
+ $probe = Join-Path $PathValue (".agent-anywhere-write-test-" + [guid]::NewGuid().ToString("n") + ".tmp")
418
+ try {
419
+ Set-Content -LiteralPath $probe -Value "" -NoNewline
420
+ Remove-Item -LiteralPath $probe -Force -ErrorAction SilentlyContinue
421
+ return $true
422
+ } catch {
423
+ Remove-Item -LiteralPath $probe -Force -ErrorAction SilentlyContinue
424
+ return $false
425
+ }
426
+ }
427
+
428
+ function Test-NpmGlobalInstallWritable {
429
+ if (-not (Get-Command npm -ErrorAction SilentlyContinue)) { return $false }
430
+ try {
431
+ $prefix = (& npm prefix -g 2>$null)
432
+ if (-not $prefix) { return $false }
433
+ $prefix = "$prefix".Trim()
434
+ if (-not (Test-DirectoryWritable -PathValue $prefix)) { return $false }
435
+
436
+ $root = (& npm root -g 2>$null)
437
+ if (-not $root) { return $false }
438
+ $root = "$root".Trim()
439
+ $rootParent = Split-Path -Parent $root
440
+ if (-not (Test-DirectoryWritable -PathValue $rootParent)) { return $false }
441
+ return $true
442
+ } catch {
443
+ return $false
444
+ }
445
+ }
446
+
447
+ function Clear-ManagedNpmPrefixOverride {
448
+ if ((Normalize-PathForCompare -PathValue $env:npm_config_prefix) -eq (Normalize-PathForCompare -PathValue $script:NpmGlobalPrefix)) {
449
+ Remove-Item Env:npm_config_prefix -ErrorAction SilentlyContinue
450
+ }
451
+ }
452
+
453
+ function Configure-NpmGlobalContext {
454
+ Clear-ManagedNpmPrefixOverride
455
+ if (Test-NpmGlobalInstallWritable) {
456
+ return
457
+ }
458
+ Set-NpmUserPrefix
459
+ }
460
+
461
+ function Cleanup-UserGatewayEnvironment {
462
+ $changed = $false
463
+
464
+ if (Remove-UserPathEntry -Entry $script:ManagedGatewayWrapperDir) {
465
+ $changed = $true
466
+ }
467
+
468
+ if ($changed) {
469
+ Log-Info "Removed Agent Anywhere PATH setting from user environment."
470
+ }
471
+ }
472
+
473
+ function Test-NodeVersionCompatible {
474
+ param([string]$VersionText)
475
+ if (-not $VersionText) { return $false }
476
+ $trimmed = $VersionText.TrimStart('v')
477
+ $version = $null
478
+ if (-not [version]::TryParse($trimmed, [ref]$version)) {
479
+ return $false
480
+ }
481
+ $requiredVersion = $null
482
+ if (-not [version]::TryParse($script:NodeRequiredVersion, [ref]$requiredVersion)) {
483
+ return $false
484
+ }
485
+ return ($version -ge $requiredVersion)
486
+ }
487
+
488
+ function Test-NodeCompatible {
489
+ try {
490
+ $version = (& node -v 2>$null)
491
+ if (-not $version) { return $false }
492
+ return (Test-NodeVersionCompatible -VersionText $version)
493
+ } catch {
494
+ return $false
495
+ }
496
+ }
497
+
498
+ function Use-BootstrappedNodeIfAvailable {
499
+ if (-not (Test-Path -LiteralPath $script:NodeBootstrapRoot)) { return $false }
500
+ $dirs = Get-ChildItem -LiteralPath $script:NodeBootstrapRoot -Directory -ErrorAction SilentlyContinue |
501
+ Sort-Object Name -Descending
502
+ foreach ($dir in $dirs) {
503
+ $nodeExe = Join-Path $dir.FullName "node.exe"
504
+ $npmCli = Join-Path $dir.FullName "npm.cmd"
505
+ if (-not (Test-Path -LiteralPath $nodeExe) -or -not (Test-Path -LiteralPath $npmCli)) {
506
+ continue
507
+ }
508
+ $version = & $nodeExe -v 2>$null
509
+ if (Test-NodeVersionCompatible -VersionText $version) {
510
+ Add-PathEntry -Entry $dir.FullName
511
+ return $true
512
+ }
513
+ }
514
+ return $false
515
+ }
516
+
517
+ function Get-ManagedGatewayWrapperPath {
518
+ return Join-Path $script:ManagedGatewayWrapperDir "hippoclaw.cmd"
519
+ }
520
+
521
+ function Get-ManagedOpenclawWrapperPath {
522
+ return Join-Path $script:ManagedGatewayWrapperDir "openclaw.cmd"
523
+ }
524
+
525
+ function Test-AgentAnywhereManagedWrapper {
526
+ param([string]$PathValue)
527
+ if (-not $PathValue -or -not (Test-Path -LiteralPath $PathValue)) { return $false }
528
+ try {
529
+ return (Get-Content -LiteralPath $PathValue -TotalCount 2 | Select-String -SimpleMatch $script:ManagedGatewayWrapperMarker -Quiet)
530
+ } catch {
531
+ return $false
532
+ }
533
+ }
534
+
535
+ function Write-ManagedGatewayCmdWrapper {
536
+ param(
537
+ [string]$NodePath,
538
+ [string]$EntryScriptPath,
539
+ [string]$WrapperPath
540
+ )
541
+ New-Item -ItemType Directory -Path (Split-Path -Parent $WrapperPath) -Force | Out-Null
542
+ $content = @"
543
+ @echo off
544
+ $($script:ManagedGatewayWrapperMarker)
545
+ "$NodePath" "$EntryScriptPath" %*
546
+ "@
547
+ Set-Content -LiteralPath $WrapperPath -Value $content -Encoding ASCII
548
+ }
549
+
550
+ function Resolve-ManagedGatewayInstallFromRoot {
551
+ param(
552
+ [string]$NodePath,
553
+ [string]$PackageRoot,
554
+ [string]$BinDir
555
+ )
556
+ if (-not $NodePath -or -not (Test-Path -LiteralPath $NodePath)) { return $null }
557
+ if (-not $PackageRoot -or -not (Test-Path -LiteralPath $PackageRoot)) { return $null }
558
+ try {
559
+ $pkgJsonPath = Join-Path $PackageRoot "package.json"
560
+ if (-not (Test-Path -LiteralPath $pkgJsonPath)) { return $null }
561
+ $pkg = Get-Content -LiteralPath $pkgJsonPath -Raw | ConvertFrom-Json
562
+ $binMap = @{}
563
+ if ($pkg.bin) {
564
+ if ($pkg.bin -is [string]) {
565
+ $binName = if ($pkg.name) { [string]$pkg.name } else { "openclaw" }
566
+ $binMap[$binName] = [string]$pkg.bin
567
+ } elseif ($pkg.bin.PSObject.Properties) {
568
+ foreach ($prop in $pkg.bin.PSObject.Properties) {
569
+ $binMap[$prop.Name] = [string]$prop.Value
570
+ }
571
+ }
572
+ }
573
+
574
+ $names = [System.Collections.Generic.List[string]]::new()
575
+ foreach ($name in @("hippoclaw", "openclaw")) {
576
+ if (-not $names.Contains($name)) { [void]$names.Add($name) }
577
+ }
578
+ foreach ($name in $binMap.Keys) {
579
+ if (-not $names.Contains($name)) { [void]$names.Add($name) }
580
+ }
581
+
582
+ foreach ($name in $names) {
583
+ $relativeEntry = if ($binMap.ContainsKey($name)) { $binMap[$name] } else { $null }
584
+ if (-not $relativeEntry) { continue }
585
+ $entryScriptPath = [System.IO.Path]::GetFullPath((Join-Path $PackageRoot $relativeEntry))
586
+ if (-not (Test-Path -LiteralPath $entryScriptPath)) { continue }
587
+
588
+ $cliPath = $null
589
+ foreach ($candidate in @(
590
+ (Join-Path $BinDir "$name.cmd"),
591
+ (Join-Path $BinDir "$name.ps1"),
592
+ (Join-Path $BinDir $name)
593
+ )) {
594
+ if (Test-Path -LiteralPath $candidate) {
595
+ $cliPath = $candidate
596
+ break
597
+ }
598
+ }
599
+
600
+ return [pscustomobject]@{
601
+ NodePath = $NodePath
602
+ CliPath = $cliPath
603
+ EntryScriptPath = $entryScriptPath
604
+ PackageRoot = $PackageRoot
605
+ }
606
+ }
607
+ } catch { }
608
+ return $null
609
+ }
610
+
611
+ function Resolve-ManagedGatewayInstall {
612
+ $currentNode = (Get-Command node -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Source -ErrorAction SilentlyContinue)
613
+
614
+ if ($currentNode) {
615
+ try {
616
+ $npmRoot = (npm root -g 2>$null).Trim()
617
+ $prefix = (& npm prefix -g 2>$null).Trim()
618
+ if ($npmRoot -and $prefix) {
619
+ $resolved = Resolve-ManagedGatewayInstallFromRoot -NodePath $currentNode -PackageRoot (Join-Path $npmRoot "openclaw") -BinDir $prefix
620
+ if ($resolved) { return $resolved }
621
+ }
622
+ } catch { }
623
+
624
+ # Windows npm uses node_modules/ directly (no lib/ prefix); Unix uses lib/node_modules/
625
+ $resolved = Resolve-ManagedGatewayInstallFromRoot -NodePath $currentNode -PackageRoot (Join-Path $script:NpmGlobalPrefix "node_modules\openclaw") -BinDir $script:NpmGlobalPrefix
626
+ if ($resolved) { return $resolved }
627
+ }
628
+
629
+ if (Test-Path -LiteralPath $script:NodeBootstrapRoot) {
630
+ $dirs = Get-ChildItem -LiteralPath $script:NodeBootstrapRoot -Directory -ErrorAction SilentlyContinue |
631
+ Sort-Object Name -Descending
632
+ foreach ($dir in $dirs) {
633
+ # Windows portable Node layout: node_modules/ at the dist root (no lib/ prefix)
634
+ $resolved = Resolve-ManagedGatewayInstallFromRoot -NodePath (Join-Path $dir.FullName "node.exe") -PackageRoot (Join-Path $dir.FullName "node_modules\openclaw") -BinDir $dir.FullName
635
+ if ($resolved) { return $resolved }
636
+ }
637
+ }
638
+
639
+ return $null
640
+ }
641
+
642
+ function Write-ManagedGatewayManifest {
643
+ param(
644
+ [string]$NodePath,
645
+ [string]$CliPath,
646
+ [string]$EntryScriptPath,
647
+ [string]$PackageRoot,
648
+ [string]$WrapperPath,
649
+ [string]$OpenclawWrapperPath = ""
650
+ )
651
+ New-Item -ItemType Directory -Path $script:ManagedGatewayStateDir -Force | Out-Null
652
+ $record = [ordered]@{
653
+ nodePath = $NodePath
654
+ cliPath = $CliPath
655
+ entryScriptPath = $EntryScriptPath
656
+ packageRoot = $PackageRoot
657
+ wrapperPath = $WrapperPath
658
+ wrapperDir = $script:ManagedGatewayWrapperDir
659
+ updatedAt = [DateTime]::UtcNow.ToString("o")
660
+ }
661
+ if ($OpenclawWrapperPath) {
662
+ $record.openclawWrapperPath = $OpenclawWrapperPath
663
+ }
664
+ # Write without BOM - PowerShell 5.1's -Encoding UTF8 emits BOM, which breaks JSON.parse in Node.js
665
+ $json = $record | ConvertTo-Json
666
+ [System.IO.File]::WriteAllBytes($script:ManagedGatewayManifestPath, [System.Text.Encoding]::UTF8.GetBytes($json))
667
+ }
668
+
669
+ function Resolve-ManagedGatewayCliPath {
670
+ if (-not (Test-Path -LiteralPath $script:ManagedGatewayManifestPath)) { return $null }
671
+ try {
672
+ $record = Get-Content -LiteralPath $script:ManagedGatewayManifestPath -Raw | ConvertFrom-Json
673
+ foreach ($candidate in @($record.wrapperPath, $record.cliPath)) {
674
+ if ($candidate -and (Test-Path -LiteralPath $candidate)) {
675
+ return $candidate
676
+ }
677
+ }
678
+ } catch { }
679
+ return $null
680
+ }
681
+
682
+ function Resolve-ManagedGatewayPackageRoot {
683
+ if (-not (Test-Path -LiteralPath $script:ManagedGatewayManifestPath)) { return $null }
684
+ try {
685
+ $record = Get-Content -LiteralPath $script:ManagedGatewayManifestPath -Raw | ConvertFrom-Json
686
+ if ($record.packageRoot -and (Test-Path -LiteralPath $record.packageRoot)) {
687
+ return $record.packageRoot
688
+ }
689
+ } catch { }
690
+ return $null
691
+ }
692
+
693
+ function Ensure-ManagedGatewayWrappers {
694
+ $resolved = Resolve-ManagedGatewayInstall
695
+ if (-not $resolved) {
696
+ Log-Warn "Could not resolve managed gateway install location after setup"
697
+ return $false
698
+ }
699
+
700
+ $wrapperPath = Get-ManagedGatewayWrapperPath
701
+ Write-ManagedGatewayCmdWrapper -NodePath $resolved.NodePath -EntryScriptPath $resolved.EntryScriptPath -WrapperPath $wrapperPath
702
+
703
+ $openclawWrapperPath = ""
704
+ $existingOpenclawWrapper = Get-ManagedOpenclawWrapperPath
705
+ if (Test-AgentAnywhereManagedWrapper -PathValue $existingOpenclawWrapper) {
706
+ Write-ManagedGatewayCmdWrapper -NodePath $resolved.NodePath -EntryScriptPath $resolved.EntryScriptPath -WrapperPath $existingOpenclawWrapper
707
+ $openclawWrapperPath = $existingOpenclawWrapper
708
+ }
709
+
710
+ Write-ManagedGatewayManifest -NodePath $resolved.NodePath -CliPath $resolved.CliPath -EntryScriptPath $resolved.EntryScriptPath -PackageRoot $resolved.PackageRoot -WrapperPath $wrapperPath -OpenclawWrapperPath $openclawWrapperPath
711
+
712
+ if ($script:ModifyPath) {
713
+ Persist-UserGatewayEnvironment
714
+ }
715
+
716
+ Log-Info "Stable CLI wrapper ready: $wrapperPath"
717
+ if (-not (Test-PathContainsEntry -Entry $script:ManagedGatewayWrapperDir)) {
718
+ if ($script:ModifyPath) {
719
+ Log-Info "Open a new terminal after setup so $($script:ManagedGatewayWrapperDir) is available on PATH."
720
+ } else {
721
+ Log-Info "Add $($script:ManagedGatewayWrapperDir) to PATH if you want to run hippoclaw directly from new terminals."
722
+ }
723
+ }
724
+
725
+ return $true
726
+ }
727
+
728
+ function Remove-ManagedGatewayWrapperState {
729
+ foreach ($wrapperPath in @((Get-ManagedGatewayWrapperPath), (Get-ManagedOpenclawWrapperPath))) {
730
+ if (Test-AgentAnywhereManagedWrapper -PathValue $wrapperPath) {
731
+ Remove-Item -LiteralPath $wrapperPath -Force -ErrorAction SilentlyContinue
732
+ }
733
+ }
734
+ Remove-Item -LiteralPath $script:ManagedGatewayManifestPath -Force -ErrorAction SilentlyContinue
735
+ }
736
+
737
+ function Install-NodeRuntime {
738
+ $archRaw = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString().ToLowerInvariant()
739
+ $nodeArch = switch ($archRaw) {
740
+ "arm64" { "arm64" }
741
+ "x64" { "x64" }
742
+ "x86" { "x86" }
743
+ default { $null }
744
+ }
745
+ if (-not $nodeArch) {
746
+ Log-Error "Automatic Node bootstrap unsupported on architecture: $archRaw"
747
+ return $false
748
+ }
749
+
750
+ $version = $script:NodeBootstrapVersion
751
+ $distName = "node-v$version-win-$nodeArch"
752
+ $destDir = Join-Path $script:NodeBootstrapRoot $distName
753
+ $nodeExe = Join-Path $destDir "node.exe"
754
+ $npmCmd = Join-Path $destDir "npm.cmd"
755
+ if ((Test-Path -LiteralPath $nodeExe) -and (Test-Path -LiteralPath $npmCmd)) {
756
+ Add-PathEntry -Entry $destDir
757
+ return $true
758
+ }
759
+
760
+ $url = "https://nodejs.org/dist/v$version/$distName.zip"
761
+ Log-Info "Installing Node.js v$version (win-$nodeArch) to $script:NodeBootstrapRoot"
762
+ New-Item -ItemType Directory -Path $script:NodeBootstrapRoot -Force | Out-Null
763
+
764
+ $work = Join-Path ([System.IO.Path]::GetTempPath()) ("agent-anywhere-node-" + [guid]::NewGuid().ToString("n"))
765
+ New-Item -ItemType Directory -Path $work -Force | Out-Null
766
+ $zipPath = Join-Path $work "node.zip"
767
+
768
+ try {
769
+ Invoke-WebRequest -Uri $url -OutFile $zipPath
770
+ Expand-Archive -LiteralPath $zipPath -DestinationPath $work -Force
771
+ $extracted = Join-Path $work $distName
772
+ if (-not (Test-Path -LiteralPath $extracted)) {
773
+ Log-Error "Downloaded Node.js archive did not contain $distName"
774
+ return $false
775
+ }
776
+ if (Test-Path -LiteralPath $destDir) {
777
+ Remove-Item -Recurse -Force $destDir -ErrorAction SilentlyContinue
778
+ }
779
+ Move-Item -LiteralPath $extracted -Destination $destDir -Force
780
+ Add-PathEntry -Entry $destDir
781
+ return $true
782
+ } catch {
783
+ Log-Error "Failed to download/install Node.js runtime from $url"
784
+ return $false
785
+ } finally {
786
+ Remove-Item -Recurse -Force $work -ErrorAction SilentlyContinue
787
+ }
788
+ }
789
+
790
+ function Ensure-NodeNpm {
791
+ if (Test-NodeCompatible) {
792
+ try {
793
+ $npmVersion = (npm -v 2>$null)
794
+ if ($npmVersion) {
795
+ Configure-NpmGlobalContext
796
+ return $true
797
+ }
798
+ } catch { }
799
+ }
800
+
801
+ $null = Use-BootstrappedNodeIfAvailable
802
+ if (Test-NodeCompatible) {
803
+ try {
804
+ $npmVersion = (npm -v 2>$null)
805
+ if ($npmVersion) {
806
+ Configure-NpmGlobalContext
807
+ return $true
808
+ }
809
+ } catch { }
810
+ }
811
+
812
+ if (-not (Install-NodeRuntime)) {
813
+ return $false
814
+ }
815
+ if (-not (Test-NodeCompatible)) { return $false }
816
+ try {
817
+ $npmVersion = (npm -v 2>$null)
818
+ if (-not $npmVersion) { return $false }
819
+ } catch {
820
+ return $false
821
+ }
822
+
823
+ Configure-NpmGlobalContext
824
+ return $true
825
+ }
826
+
827
+ # ============================================================================
828
+ # Git / GitHub-style sources need a local UI build
829
+ # ============================================================================
830
+ function Test-SourceNeedsBuild {
831
+ param([string]$S)
832
+ if (-not $S) { return $false }
833
+ if ($S.StartsWith("\\") -or $S.StartsWith("/") -or $S.StartsWith(".")) { return $true }
834
+ if ($S -match '^[A-Za-z]:') { return $true }
835
+ if ($S.StartsWith("github:")) { return $true }
836
+ if ($S.StartsWith("git+http:") -or $S.StartsWith("git+https:")) { return $true }
837
+ if ($S.Contains("#")) { return $true }
838
+ if ($S -match '^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$') { return $true }
839
+ return $false
840
+ }
841
+
842
+ function Needs-Pnpm {
843
+ return Test-SourceNeedsBuild -S $Source
844
+ }
845
+
846
+ function Test-InstallSourceLocal {
847
+ param([string]$S)
848
+ if (-not $S) { return $false }
849
+ return $S.StartsWith("\\") -or $S.StartsWith("/") -or $S.StartsWith(".") -or ($S -match '^[A-Za-z]:')
850
+ }
851
+
852
+ # Remote github:/git+: npm global git install can leave a broken symlink; clone -> npm pack -> install .tgz.
853
+ # Git checkouts omit dist/; run pnpm build + ui:build in clone before npm pack (dist/entry + control-ui).
854
+ function Install-OpenclawFromRemoteGitSpec {
855
+ param([string]$Spec)
856
+
857
+ $s = $Spec
858
+ $ref = $null
859
+ if ($s.Contains("#")) {
860
+ $ref = $s.Substring($s.LastIndexOf("#") + 1)
861
+ $s = $s.Substring(0, $s.LastIndexOf("#"))
862
+ }
863
+
864
+ $cloneUrl = $null
865
+ if ($s.StartsWith("git+https:") -or $s.StartsWith("git+http:")) {
866
+ $cloneUrl = $s.Substring(4)
867
+ } elseif ($s.StartsWith("github:")) {
868
+ $rest = $s.Substring("github:".Length)
869
+ $cloneUrl = "https://github.com/$rest.git"
870
+ } elseif ($s -match '^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$') {
871
+ $cloneUrl = "https://github.com/$s.git"
872
+ } else {
873
+ Log-Error "Unsupported git install source: $Spec"
874
+ throw "Unsupported git install source"
875
+ }
876
+
877
+ $work = Join-Path ([System.IO.Path]::GetTempPath()) ("openclaw-gateway-src-" + [guid]::NewGuid().ToString("n"))
878
+ New-Item -ItemType Directory -Path $work -Force | Out-Null
879
+ $srcDir = Join-Path $work "src"
880
+
881
+ try {
882
+ Log-Info "Cloning $(Split-Path -Leaf $cloneUrl) (shallow) for npm pack install..."
883
+ if ($ref) {
884
+ git clone --depth 1 -b $ref $cloneUrl $srcDir
885
+ } else {
886
+ git clone --depth 1 $cloneUrl $srcDir
887
+ }
888
+ if ($LASTEXITCODE -ne 0) {
889
+ if (Test-Path $work) { Remove-Item -Recurse -Force $work -ErrorAction SilentlyContinue }
890
+ Log-Error "git clone failed (check ref and network)"
891
+ throw "git clone failed"
892
+ }
893
+
894
+ Log-Info "Building OpenClaw in clone before npm pack (may take several minutes)..."
895
+ try {
896
+ Invoke-OpenclawRepoBuild -RepoDir $srcDir
897
+ } catch {
898
+ if (Test-Path $work) { Remove-Item -Recurse -Force $work -ErrorAction SilentlyContinue }
899
+ Log-Error "OpenClaw source build failed: $_"
900
+ throw
901
+ }
902
+
903
+ Log-Info "npm pack --ignore-scripts ..."
904
+ Push-Location $srcDir
905
+ try {
906
+ npm pack --ignore-scripts
907
+ if ($LASTEXITCODE -ne 0) {
908
+ if (Test-Path $work) { Remove-Item -Recurse -Force $work -ErrorAction SilentlyContinue }
909
+ Log-Error "npm pack failed"
910
+ throw "npm pack failed"
911
+ }
912
+ } finally {
913
+ Pop-Location
914
+ }
915
+
916
+ $tgz = Get-ChildItem -Path $srcDir -Filter "openclaw-*.tgz" | Sort-Object LastWriteTime -Descending | Select-Object -First 1
917
+ if (-not $tgz) {
918
+ if (Test-Path $work) { Remove-Item -Recurse -Force $work -ErrorAction SilentlyContinue }
919
+ Log-Error "npm pack did not produce openclaw-*.tgz under clone"
920
+ throw "npm pack produced no tarball"
921
+ }
922
+
923
+ Log-Info "npm install -g $($tgz.Name) ..."
924
+ npm install -g $tgz.FullName
925
+ if ($LASTEXITCODE -ne 0) {
926
+ if (Test-Path $work) { Remove-Item -Recurse -Force $work -ErrorAction SilentlyContinue }
927
+ Log-Error "npm install -g tarball failed"
928
+ throw "npm install tarball failed"
929
+ }
930
+
931
+ $script:RemoteGatewayCloneSrc = $srcDir
932
+ $script:RemoteGatewayWorkDir = $work
933
+ } catch {
934
+ if (Test-Path $work) {
935
+ Remove-Item -Recurse -Force $work -ErrorAction SilentlyContinue
936
+ }
937
+ throw
938
+ }
939
+ }
940
+
941
+ # ============================================================================
942
+ # Check prerequisites
943
+ # ============================================================================
944
+ function Check-Prerequisites {
945
+ Log-Step "Checking prerequisites..."
946
+
947
+ $allGood = $true
948
+
949
+ if (-not (Ensure-NodeNpm)) {
950
+ Log-Warn "Could not automatically provision Node.js/npm"
951
+ $allGood = $false
952
+ }
953
+
954
+ # Node.js >= 22.14
955
+ try {
956
+ $nodeVersion = (node -v 2>$null)
957
+ if ($nodeVersion) {
958
+ if (Test-NodeVersionCompatible -VersionText $nodeVersion) {
959
+ Log-Success "Node.js $nodeVersion"
960
+ } else {
961
+ Log-Warn "Node.js $nodeVersion -- version 22.14+ required"
962
+ $allGood = $false
963
+ }
964
+ } else {
965
+ throw "not found"
966
+ }
967
+ } catch {
968
+ Log-Warn "Node.js not found (version 22.14+ required)"
969
+ Write-Host " Install: https://nodejs.org/" -ForegroundColor Gray
970
+ $allGood = $false
971
+ }
972
+
973
+ # npm
974
+ try {
975
+ $npmVersion = (npm -v 2>$null)
976
+ if ($npmVersion) {
977
+ Log-Success "npm $npmVersion"
978
+ } else {
979
+ throw "not found"
980
+ }
981
+ } catch {
982
+ Log-Warn "npm not found"
983
+ $allGood = $false
984
+ }
985
+
986
+ if (Test-SourceNeedsBuild -S $Source) {
987
+ $localSrc = Test-InstallSourceLocal -S $Source
988
+ if (-not $localSrc) {
989
+ try {
990
+ $gitVersion = (git --version 2>$null)
991
+ if ($gitVersion) {
992
+ Log-Success "git $gitVersion"
993
+ } else {
994
+ throw "not found"
995
+ }
996
+ } catch {
997
+ Log-Warn "git not found (required for GitHub / git URL gateway install sources)"
998
+ $allGood = $false
999
+ }
1000
+ }
1001
+ }
1002
+
1003
+ # pnpm
1004
+ if (Needs-Pnpm) {
1005
+ try {
1006
+ $pnpmVersion = (pnpm -v 2>$null)
1007
+ if ($pnpmVersion) {
1008
+ Log-Success "pnpm $pnpmVersion"
1009
+ } else {
1010
+ throw "not found"
1011
+ }
1012
+ } catch {
1013
+ if (Ensure-Pnpm) {
1014
+ $pnpmVersion = (pnpm -v 2>$null)
1015
+ Log-Success "pnpm $pnpmVersion"
1016
+ } else {
1017
+ Log-Warn "pnpm not found (needed to build OpenClaw from source)"
1018
+ $allGood = $false
1019
+ }
1020
+ }
1021
+ } else {
1022
+ Log-Info "pnpm not required for published package install"
1023
+ }
1024
+
1025
+ return $allGood
1026
+ }
1027
+
1028
+ # ============================================================================
1029
+ # Ensure pnpm is available when we need to build the UI
1030
+ # ============================================================================
1031
+ function Ensure-Pnpm {
1032
+ try {
1033
+ $pnpmVersion = (pnpm -v 2>$null)
1034
+ if ($pnpmVersion) {
1035
+ Log-Success "pnpm $pnpmVersion"
1036
+ return $true
1037
+ }
1038
+ } catch { }
1039
+
1040
+ Log-Warn "pnpm not found - attempting to install"
1041
+
1042
+ try {
1043
+ Log-Info "Installing pnpm via npm..."
1044
+ npm install -g pnpm | Out-Null
1045
+ $pnpmVersion = (pnpm -v 2>$null)
1046
+ if ($pnpmVersion) {
1047
+ Log-Success "pnpm $pnpmVersion"
1048
+ return $true
1049
+ }
1050
+ } catch { }
1051
+
1052
+ try {
1053
+ $corepackVersion = (corepack -v 2>$null)
1054
+ if ($corepackVersion) {
1055
+ Log-Info "Installing pnpm via corepack..."
1056
+ $previousPromptValue = $env:COREPACK_ENABLE_DOWNLOAD_PROMPT
1057
+ try {
1058
+ $env:COREPACK_ENABLE_DOWNLOAD_PROMPT = "0"
1059
+ corepack prepare pnpm@latest --activate | Out-Null
1060
+ } finally {
1061
+ if ($null -eq $previousPromptValue) {
1062
+ Remove-Item Env:COREPACK_ENABLE_DOWNLOAD_PROMPT -ErrorAction SilentlyContinue
1063
+ } else {
1064
+ $env:COREPACK_ENABLE_DOWNLOAD_PROMPT = $previousPromptValue
1065
+ }
1066
+ }
1067
+ $pnpmVersion = (pnpm -v 2>$null)
1068
+ if ($pnpmVersion) {
1069
+ Log-Success "pnpm $pnpmVersion"
1070
+ return $true
1071
+ }
1072
+ }
1073
+ } catch { }
1074
+
1075
+ Log-Warn "pnpm install failed - cannot build OpenClaw from source"
1076
+ return $false
1077
+ }
1078
+
1079
+ function Invoke-OpenclawRepoBuild {
1080
+ param([string]$RepoDir)
1081
+ if (-not (Test-Path -LiteralPath $RepoDir)) {
1082
+ Log-Error "Repo directory missing: $RepoDir"
1083
+ throw "missing repo dir"
1084
+ }
1085
+ if (-not (Ensure-Pnpm)) {
1086
+ Log-Error "pnpm is required to build OpenClaw from a git checkout"
1087
+ throw "pnpm missing"
1088
+ }
1089
+ $lock = Join-Path $RepoDir "pnpm-lock.yaml"
1090
+ if (-not (Test-Path $lock)) {
1091
+ Log-Error "pnpm-lock.yaml missing in $RepoDir"
1092
+ throw "missing pnpm-lock.yaml"
1093
+ }
1094
+ Push-Location $RepoDir
1095
+ try {
1096
+ $previousCi = $env:CI
1097
+ try {
1098
+ $env:CI = "true"
1099
+ Invoke-WithPreferredWindowsBash {
1100
+ Log-Info "pnpm install..."
1101
+ pnpm install
1102
+ if ($LASTEXITCODE -ne 0) { throw "pnpm install failed (exit $LASTEXITCODE)" }
1103
+ Log-Info "pnpm build..."
1104
+ pnpm build
1105
+ if ($LASTEXITCODE -ne 0) { throw "pnpm build failed (exit $LASTEXITCODE)" }
1106
+ Log-Info "pnpm ui:build..."
1107
+ pnpm ui:build
1108
+ if ($LASTEXITCODE -ne 0) { throw "pnpm ui:build failed (exit $LASTEXITCODE)" }
1109
+ }
1110
+ } finally {
1111
+ if ($null -eq $previousCi) {
1112
+ Remove-Item Env:CI -ErrorAction SilentlyContinue
1113
+ } else {
1114
+ $env:CI = $previousCi
1115
+ }
1116
+ }
1117
+ } finally {
1118
+ Pop-Location
1119
+ }
1120
+ }
1121
+
1122
+ # ============================================================================
1123
+ # Check installed components
1124
+ # ============================================================================
1125
+ function Get-GatewayCliCommand {
1126
+ $managed = Resolve-ManagedGatewayCliPath
1127
+ if ($managed) {
1128
+ return [pscustomobject]@{
1129
+ Source = $managed
1130
+ Name = [System.IO.Path]::GetFileNameWithoutExtension($managed)
1131
+ }
1132
+ }
1133
+ $hc = Get-Command hippoclaw -ErrorAction SilentlyContinue
1134
+ if ($hc) { return $hc }
1135
+ $oc = Get-Command openclaw -ErrorAction SilentlyContinue
1136
+ if ($oc) { return $oc }
1137
+
1138
+ try {
1139
+ $prefix = (& npm prefix -g 2>$null).Trim()
1140
+ if ($prefix) {
1141
+ foreach ($name in @("hippoclaw.cmd", "hippoclaw.ps1", "hippoclaw", "openclaw.cmd", "openclaw.ps1", "openclaw")) {
1142
+ $candidate = Join-Path $prefix $name
1143
+ if (Test-Path -LiteralPath $candidate) {
1144
+ return [pscustomobject]@{
1145
+ Source = $candidate
1146
+ Name = [System.IO.Path]::GetFileNameWithoutExtension($candidate)
1147
+ }
1148
+ }
1149
+ }
1150
+ }
1151
+ } catch { }
1152
+
1153
+ if (Test-Path -LiteralPath $script:NodeBootstrapRoot) {
1154
+ $dirs = Get-ChildItem -LiteralPath $script:NodeBootstrapRoot -Directory -ErrorAction SilentlyContinue |
1155
+ Sort-Object Name -Descending
1156
+ foreach ($dir in $dirs) {
1157
+ foreach ($name in @("hippoclaw.cmd", "hippoclaw.ps1", "hippoclaw", "openclaw.cmd", "openclaw.ps1", "openclaw")) {
1158
+ $candidate = Join-Path $dir.FullName $name
1159
+ if (Test-Path -LiteralPath $candidate) {
1160
+ return [pscustomobject]@{
1161
+ Source = $candidate
1162
+ Name = [System.IO.Path]::GetFileNameWithoutExtension($candidate)
1163
+ }
1164
+ }
1165
+ }
1166
+ }
1167
+ }
1168
+
1169
+ return $null
1170
+ }
1171
+
1172
+ # A CLI shim can exist while the underlying package is broken (e.g. a half-finished
1173
+ # npm install that left dist/ missing). Treat the CLI as functional only when it both
1174
+ # reports a version AND has its dist entry on disk -- otherwise a plain (non-reinstall)
1175
+ # run must still repair it instead of skipping the install and "finishing" broken.
1176
+ function Test-GatewayCliFunctional {
1177
+ $cli = Get-GatewayCliCommand
1178
+ if (-not $cli) { return $false }
1179
+
1180
+ # --version inside a job with a hard timeout, so a broken/hanging shim can never wedge setup.
1181
+ $ver = $null
1182
+ try {
1183
+ $job = Start-Job -ScriptBlock { param($exe) (& $exe --version 2>$null | Select-Object -First 1) } -ArgumentList $cli.Source
1184
+ if (Wait-Job $job -Timeout 20) { $ver = Receive-Job $job } else { Stop-Job $job -ErrorAction SilentlyContinue }
1185
+ Remove-Job $job -Force -ErrorAction SilentlyContinue
1186
+ } catch { $ver = $null }
1187
+ if (-not $ver) { return $false }
1188
+
1189
+ # Verify the package dist entry exists where the CLI resolves (mirrors Check-Installed).
1190
+ $groot = Resolve-ManagedGatewayPackageRoot
1191
+ if (-not $groot -or -not (Test-Path -LiteralPath $groot)) {
1192
+ $groot = Join-Path $script:NpmGlobalPrefix "node_modules\openclaw"
1193
+ }
1194
+ if (-not (Test-Path -LiteralPath $groot)) {
1195
+ $npmRoot = $null
1196
+ try { $npmRoot = (npm root -g 2>$null).Trim() } catch { }
1197
+ if ($npmRoot) { $groot = Join-Path $npmRoot "openclaw" }
1198
+ }
1199
+ if ($groot -and (Test-Path -LiteralPath $groot)) {
1200
+ if ((Test-Path -LiteralPath (Join-Path $groot "dist\entry.mjs")) -or
1201
+ (Test-Path -LiteralPath (Join-Path $groot "dist\entry.js"))) {
1202
+ return $true
1203
+ }
1204
+ }
1205
+ return $false
1206
+ }
1207
+
1208
+ function Remove-ManagedGatewayShims {
1209
+ param([string]$PrefixDir)
1210
+ if (-not $PrefixDir) { return }
1211
+ foreach ($name in @("openclaw", "openclaw.cmd", "openclaw.ps1", "hippoclaw", "hippoclaw.cmd", "hippoclaw.ps1")) {
1212
+ Remove-Item -Force (Join-Path $PrefixDir $name) -ErrorAction SilentlyContinue
1213
+ }
1214
+ }
1215
+
1216
+ function Remove-ManagedOpenclawArtifacts {
1217
+ $legacyManagedOpenclaw = Join-Path $script:NpmGlobalPrefix "lib\node_modules\openclaw"
1218
+ if (Test-Path $legacyManagedOpenclaw) {
1219
+ Log-Info "Removing managed openclaw package from $legacyManagedOpenclaw"
1220
+ Remove-Item -Recurse -Force $legacyManagedOpenclaw -ErrorAction SilentlyContinue
1221
+ }
1222
+ Remove-ManagedGatewayShims -PrefixDir $script:NpmGlobalPrefix
1223
+
1224
+ if (-not (Test-Path -LiteralPath $script:NodeBootstrapRoot)) { return }
1225
+ $dirs = Get-ChildItem -LiteralPath $script:NodeBootstrapRoot -Directory -ErrorAction SilentlyContinue
1226
+ foreach ($dir in $dirs) {
1227
+ $pkgRoot = Join-Path $dir.FullName "lib\node_modules\openclaw"
1228
+ if (Test-Path $pkgRoot) {
1229
+ Log-Info "Removing managed openclaw package from $pkgRoot"
1230
+ Remove-Item -Recurse -Force $pkgRoot -ErrorAction SilentlyContinue
1231
+ }
1232
+ Remove-ManagedGatewayShims -PrefixDir $dir.FullName
1233
+ }
1234
+ }
1235
+
1236
+ function Check-Installed {
1237
+ param([switch]$UpdateInstallStatus)
1238
+
1239
+ if ($UpdateInstallStatus) {
1240
+ Update-GatewayInstallStatus -Phase "verifying" -Message "Checking installed components..."
1241
+ }
1242
+
1243
+ Log-Step "Checking installed components..."
1244
+
1245
+ $allOk = $true
1246
+ $cliVersionWorks = $false
1247
+ $wrapperExists = $false
1248
+ $configExists = $false
1249
+ $distExists = $false
1250
+ $webUiExists = $false
1251
+
1252
+ $managedWrapper = Resolve-ManagedGatewayCliPath
1253
+ if ($managedWrapper -and (Test-Path -LiteralPath $managedWrapper)) {
1254
+ $wrapperExists = $true
1255
+ }
1256
+
1257
+ # Gateway CLI binary (prefer hippoclaw from fork, fallback to openclaw)
1258
+ $cliPath = Get-GatewayCliCommand
1259
+ if ($cliPath) {
1260
+ try {
1261
+ $ocVersion = (& $cliPath.Source --version 2>$null | Select-Object -First 1)
1262
+ if ($ocVersion) {
1263
+ Log-Success "Gateway CLI installed ($($cliPath.Name)): $ocVersion"
1264
+ Log-Info "Gateway CLI path: $($cliPath.Source)"
1265
+ $cliVersionWorks = $true
1266
+ } else {
1267
+ throw "version unavailable"
1268
+ }
1269
+ } catch {
1270
+ Log-Warn "Gateway CLI found ($($cliPath.Source)) but command failed (stale/broken shim)"
1271
+ $allOk = $false
1272
+ }
1273
+ } else {
1274
+ Log-Warn "Gateway CLI not installed (hippoclaw/openclaw)"
1275
+ $allOk = $false
1276
+ }
1277
+
1278
+ try {
1279
+ $groot = Resolve-ManagedGatewayPackageRoot
1280
+ if (-not $groot -or -not (Test-Path $groot)) {
1281
+ $groot = Join-Path $script:NpmGlobalPrefix "node_modules\openclaw"
1282
+ }
1283
+ if (-not (Test-Path $groot)) {
1284
+ $npmRoot = (npm root -g 2>$null).Trim()
1285
+ $groot = if ($npmRoot) { Join-Path $npmRoot "openclaw" } else { $null }
1286
+ }
1287
+ if ($groot -and (Test-Path $groot)) {
1288
+ $entryMjs = Join-Path $groot "dist\entry.mjs"
1289
+ $entryJs = Join-Path $groot "dist\entry.js"
1290
+ if ((Test-Path $entryMjs) -or (Test-Path $entryJs)) {
1291
+ Log-Success "CLI dist present ($groot\dist\entry.*)"
1292
+ $distExists = $true
1293
+ } else {
1294
+ Log-Warn "CLI dist missing (reinstall from npm or rerun setup with source build)"
1295
+ $allOk = $false
1296
+ }
1297
+ $uiDir = Join-Path $groot "dist\control-ui"
1298
+ if (Test-Path (Join-Path $uiDir "index.html")) {
1299
+ Log-Success "Web UI built ($uiDir)"
1300
+ $webUiExists = $true
1301
+ } else {
1302
+ Log-Warn "Web UI not built"
1303
+ $allOk = $false
1304
+ }
1305
+ } else {
1306
+ if ($cliPath) {
1307
+ Log-Warn "Global npm openclaw package not found (CLI appears external/non-npm)"
1308
+ } else {
1309
+ Log-Warn "Global npm openclaw package not found"
1310
+ }
1311
+ $allOk = $false
1312
+ }
1313
+ } catch {
1314
+ Log-Warn "Could not verify global openclaw dist (npm root?)"
1315
+ $allOk = $false
1316
+ }
1317
+
1318
+ # Gateway running? Informational only; install succeeds even when stopped.
1319
+ try {
1320
+ $tcp = New-Object System.Net.Sockets.TcpClient
1321
+ $tcp.Connect("127.0.0.1", $Port)
1322
+ $tcp.Close()
1323
+ Log-Success "Gateway running on 127.0.0.1:$Port"
1324
+ } catch {
1325
+ Log-Info "Gateway not running on port $Port (this is OK; start it from Agent Anywhere when needed)"
1326
+ }
1327
+
1328
+ # Config file
1329
+ $configPath = Join-Path $env:USERPROFILE ".openclaw\openclaw.json"
1330
+ if (Test-Path $configPath) {
1331
+ Log-Success "Config file present ($configPath)"
1332
+ $configExists = $true
1333
+ } else {
1334
+ Log-Warn "Config file not found ($configPath)"
1335
+ $allOk = $false
1336
+ }
1337
+
1338
+ if ($UpdateInstallStatus) {
1339
+ $stepUpdates = @{
1340
+ cliVersionWorks = $cliVersionWorks
1341
+ wrapperExists = $wrapperExists
1342
+ configExists = $configExists
1343
+ distExists = $distExists
1344
+ webUiExists = $webUiExists
1345
+ finalCheckPassed = $allOk
1346
+ }
1347
+ if ($allOk) {
1348
+ Complete-GatewayInstallStatus -StepUpdates $stepUpdates -Message "Agent Anywhere is fully installed!"
1349
+ } else {
1350
+ Update-GatewayInstallStatus -Phase "verifying" -Message "Install verification incomplete." -StepUpdates $stepUpdates
1351
+ }
1352
+ }
1353
+
1354
+ Write-Host ""
1355
+ if ($allOk) {
1356
+ Write-Host "Agent Anywhere is fully installed!" -ForegroundColor Green
1357
+ } else {
1358
+ Write-Host "Agent Anywhere setup is incomplete." -ForegroundColor Yellow
1359
+ }
1360
+
1361
+ return $allOk
1362
+ }
1363
+
1364
+ function Check-Uninstalled {
1365
+ Log-Step "Checking uninstall state..."
1366
+
1367
+ $allOk = $true
1368
+
1369
+ $cliPath = Get-GatewayCliCommand
1370
+ if ($cliPath) {
1371
+ Log-Warn "Gateway CLI still resolves to $($cliPath.Source) (likely external/non-npm install)"
1372
+ } else {
1373
+ Log-Success "Gateway CLI not installed (hippoclaw/openclaw)"
1374
+ }
1375
+
1376
+ try {
1377
+ $groot = Resolve-ManagedGatewayPackageRoot
1378
+ if (-not $groot -or -not (Test-Path $groot)) {
1379
+ $groot = Join-Path $script:NpmGlobalPrefix "node_modules\openclaw"
1380
+ }
1381
+ if ($groot -and (Test-Path $groot)) {
1382
+ Log-Warn "Managed npm openclaw package still present ($groot)"
1383
+ $allOk = $false
1384
+ } else {
1385
+ Log-Success "Managed npm openclaw package not found"
1386
+ }
1387
+ } catch {
1388
+ Log-Warn "Could not verify managed openclaw package path"
1389
+ $allOk = $false
1390
+ }
1391
+
1392
+ try {
1393
+ $tcp = New-Object System.Net.Sockets.TcpClient
1394
+ $tcp.Connect("127.0.0.1", $Port)
1395
+ $tcp.Close()
1396
+ Log-Warn "Gateway still running on 127.0.0.1:$Port"
1397
+ $allOk = $false
1398
+ } catch {
1399
+ Log-Success "Gateway not running on port $Port"
1400
+ }
1401
+
1402
+ $configPath = Join-Path $env:USERPROFILE ".openclaw\openclaw.json"
1403
+ if (Test-Path $configPath) {
1404
+ Log-Success "Config file preserved ($configPath)"
1405
+ } else {
1406
+ Log-Info "Config file already absent ($configPath)"
1407
+ }
1408
+
1409
+ Write-Host ""
1410
+ if ($allOk) {
1411
+ Write-Host "Agent Anywhere uninstall complete." -ForegroundColor Green
1412
+ } else {
1413
+ Write-Host "Agent Anywhere uninstall needs attention." -ForegroundColor Yellow
1414
+ }
1415
+
1416
+ return $allOk
1417
+ }
1418
+
1419
+ # ============================================================================
1420
+ # Install gateway
1421
+ # ============================================================================
1422
+
1423
+ # Windows holds file handles on running executables/DLLs, so a live gateway node
1424
+ # process keeps the global openclaw tree locked. Stop those processes so the tree
1425
+ # (and its nested deps like @slack/@smithy) can actually be removed before reinstall.
1426
+ function Stop-GatewayProcessesLockingTree {
1427
+ param([string]$PkgRoot)
1428
+
1429
+ # 1) pid recorded by a running gateway
1430
+ $pidPath = Join-Path $env:USERPROFILE ".openclaw\gateway.pid"
1431
+ if (Test-Path $pidPath) {
1432
+ try {
1433
+ $gpid = (Get-Content -LiteralPath $pidPath -ErrorAction SilentlyContinue | Select-Object -First 1)
1434
+ if ($gpid) { Stop-Process -Id ([int]$gpid) -Force -ErrorAction SilentlyContinue }
1435
+ } catch { }
1436
+ }
1437
+
1438
+ # 2) listeners bound to the gateway port(s)
1439
+ $sweepPorts = @($Port)
1440
+ if ($Port -ne 18789) { $sweepPorts += 18789 }
1441
+ foreach ($sp in ($sweepPorts | Select-Object -Unique)) {
1442
+ Stop-ListenersOnGatewayPort $sp
1443
+ }
1444
+
1445
+ # 3) any node process running from inside the global openclaw tree
1446
+ if ($PkgRoot) {
1447
+ try {
1448
+ $procs = Get-CimInstance Win32_Process -Filter "Name='node.exe'" -ErrorAction SilentlyContinue
1449
+ foreach ($p in $procs) {
1450
+ if ($p.CommandLine -and $p.CommandLine -like "*$PkgRoot*") {
1451
+ Stop-Process -Id $p.ProcessId -Force -ErrorAction SilentlyContinue
1452
+ }
1453
+ }
1454
+ } catch { }
1455
+ }
1456
+
1457
+ Start-Sleep -Milliseconds 500
1458
+ }
1459
+
1460
+ # Robustly remove the global openclaw package tree: stop lockers, then retry with
1461
+ # backoff so npm's own rmdir doesn't fail later with EPERM/ENOTEMPTY on Windows.
1462
+ function Remove-OpenclawGlobalTreeRobust {
1463
+ param([string]$PkgRoot)
1464
+ if (-not $PkgRoot -or -not (Test-Path -LiteralPath $PkgRoot)) { return $true }
1465
+ Stop-GatewayProcessesLockingTree -PkgRoot $PkgRoot
1466
+ for ($i = 0; $i -lt 5; $i++) {
1467
+ Remove-Item -Recurse -Force -LiteralPath $PkgRoot -ErrorAction SilentlyContinue
1468
+ if (-not (Test-Path -LiteralPath $PkgRoot)) { return $true }
1469
+ Start-Sleep -Milliseconds (400 * ($i + 1))
1470
+ }
1471
+ return (-not (Test-Path -LiteralPath $PkgRoot))
1472
+ }
1473
+
1474
+ function Install-Gateway {
1475
+ if (-not $Source) {
1476
+ Log-Error "No install source specified. Use -Source <source>"
1477
+ Fail-GatewayInstallStatus -Message "No install source specified."
1478
+ exit 1
1479
+ }
1480
+
1481
+ $script:RemoteGatewayCloneSrc = $null
1482
+ $script:RemoteGatewayWorkDir = $null
1483
+
1484
+ Log-Step "Installing OpenClaw Gateway..."
1485
+ Log-Info "Source: $Source"
1486
+ Update-GatewayInstallStatus -Phase "installing" -Message "Installing Gateway CLI..."
1487
+
1488
+ $npmRoot = $null
1489
+ try {
1490
+ $npmRoot = (npm root -g 2>$null).Trim()
1491
+ } catch { }
1492
+
1493
+ if ($npmRoot -and (Test-Path (Join-Path $npmRoot "openclaw"))) {
1494
+ $existingPkg = Join-Path $npmRoot "openclaw"
1495
+ Log-Info "Removing existing global openclaw tree (avoids partial install)..."
1496
+ if (-not (Remove-OpenclawGlobalTreeRobust -PkgRoot $existingPkg)) {
1497
+ Log-Warn "Could not fully remove $existingPkg (files may be locked by a running gateway)."
1498
+ Log-Warn "Close any running gateway/openclaw process and retry, or run with -Uninstall first."
1499
+ }
1500
+ }
1501
+
1502
+ $isLocal = Test-InstallSourceLocal -S $Source
1503
+
1504
+ try {
1505
+ if (Test-SourceNeedsBuild -S $Source) {
1506
+ if ($isLocal) {
1507
+ $absSrc = (Resolve-Path -LiteralPath $Source).Path
1508
+ try {
1509
+ Invoke-OpenclawRepoBuild -RepoDir $absSrc
1510
+ } catch {
1511
+ Log-Error "OpenClaw source build failed: $_"
1512
+ Fail-GatewayInstallStatus -Message "OpenClaw source build failed."
1513
+ exit 1
1514
+ }
1515
+ npm install -g $absSrc
1516
+ if ($LASTEXITCODE -ne 0) {
1517
+ Log-Error "npm install failed"
1518
+ Fail-GatewayInstallStatus -Message "npm install failed."
1519
+ exit 1
1520
+ }
1521
+ } else {
1522
+ Install-OpenclawFromRemoteGitSpec -Spec $Source
1523
+ }
1524
+ } else {
1525
+ npm install -g $Source
1526
+ if ($LASTEXITCODE -ne 0) {
1527
+ Log-Error "npm install failed"
1528
+ Fail-GatewayInstallStatus -Message "npm install failed."
1529
+ exit 1
1530
+ }
1531
+ }
1532
+ Log-Success "npm install complete"
1533
+ Update-GatewayInstallStatus -Phase "installing" -Message "CLI install complete; preparing managed wrapper..." -StepUpdates @{ npmInstallComplete = $true }
1534
+ Ensure-ManagedGatewayWrappers | Out-Null
1535
+ $wrapperPath = Resolve-ManagedGatewayCliPath
1536
+ if ($wrapperPath -and (Test-Path -LiteralPath $wrapperPath)) {
1537
+ Update-GatewayInstallStatus -Phase "installing" -Message "Managed wrapper ready; preparing config..." -StepUpdates @{ wrapperExists = $true }
1538
+ }
1539
+
1540
+ if (Test-SourceNeedsBuild -S $Source) {
1541
+ Log-Info "OpenClaw built from source; global install includes dist/."
1542
+ } else {
1543
+ Log-Info "Published package -- web UI should be pre-built"
1544
+ }
1545
+ } finally {
1546
+ if ($script:RemoteGatewayWorkDir -and (Test-Path $script:RemoteGatewayWorkDir)) {
1547
+ Remove-Item -Recurse -Force $script:RemoteGatewayWorkDir -ErrorAction SilentlyContinue
1548
+ }
1549
+ $script:RemoteGatewayWorkDir = $null
1550
+ $script:RemoteGatewayCloneSrc = $null
1551
+ }
1552
+ }
1553
+
1554
+ function Test-GatewayPortOpen([int]$ListenPort) {
1555
+ try {
1556
+ $tcp = New-Object System.Net.Sockets.TcpClient
1557
+ $tcp.Connect("127.0.0.1", $ListenPort)
1558
+ $tcp.Close()
1559
+ return $true
1560
+ } catch { return $false }
1561
+ }
1562
+
1563
+ function Stop-ListenersOnGatewayPort([int]$ListenPort) {
1564
+ if (-not (Test-GatewayPortOpen $ListenPort)) { return }
1565
+ Log-Info "Port $ListenPort still in use - stopping listener process(es)..."
1566
+ try {
1567
+ $conns = Get-NetTCPConnection -LocalPort $ListenPort -State Listen -ErrorAction SilentlyContinue
1568
+ foreach ($c in $conns) {
1569
+ Stop-Process -Id $c.OwningProcess -Force -ErrorAction SilentlyContinue
1570
+ }
1571
+ } catch { }
1572
+ }
1573
+
1574
+ # After npm removes the CLI: free loopback listener(s). Service teardown is openclaw uninstall --service.
1575
+ function Stop-OrphanGatewayListenersOnPorts {
1576
+ Log-Step "Clearing local gateway listener(s) if still bound..."
1577
+ $pidPath = Join-Path $env:USERPROFILE ".openclaw\gateway.pid"
1578
+ Remove-Item -Path $pidPath -ErrorAction SilentlyContinue
1579
+ $sweepPorts = @($Port)
1580
+ if ($Port -ne 18789) { $sweepPorts += 18789 }
1581
+ foreach ($sp in ($sweepPorts | Select-Object -Unique)) {
1582
+ Stop-ListenersOnGatewayPort $sp
1583
+ }
1584
+ Start-Sleep -Seconds 1
1585
+ $anyUp = $false
1586
+ foreach ($sp in ($sweepPorts | Select-Object -Unique)) {
1587
+ if (Test-GatewayPortOpen $sp) { $anyUp = $true; break }
1588
+ }
1589
+ if ($anyUp) {
1590
+ Log-Warn "A process may still be listening on 127.0.0.1 (ports: $($sweepPorts -join ', '))"
1591
+ } else {
1592
+ Log-Success "Gateway port(s) free on 127.0.0.1 ($($sweepPorts -join ', '))"
1593
+ }
1594
+ }
1595
+
1596
+ function Invoke-OpenclawUninstallService {
1597
+ $oc = Get-GatewayCliCommand
1598
+ if (-not $oc) { return }
1599
+ Log-Step "OpenClaw CLI: uninstall gateway service..."
1600
+ Log-Info "Running: $($oc.Source) uninstall --service --yes --non-interactive"
1601
+ $prevEap = $ErrorActionPreference
1602
+ $ErrorActionPreference = "Continue"
1603
+ try {
1604
+ & $oc.Source uninstall --service --yes --non-interactive
1605
+ } catch { }
1606
+ $ErrorActionPreference = $prevEap
1607
+ if ($LASTEXITCODE -eq 0) {
1608
+ Log-Success "openclaw uninstall --service completed"
1609
+ } else {
1610
+ Log-Info "openclaw uninstall --service failed or skipped (continuing)"
1611
+ }
1612
+ }
1613
+
1614
+ function Remove-ResolvedCliOpenclawInstall {
1615
+ # Remove the openclaw package wherever the CLI on PATH actually resolves to (the npm global
1616
+ # prefix that owns the shim), not just the active/managed prefix `npm uninstall -g` covers.
1617
+ # Bounded loop in case more than one install is present on PATH.
1618
+ for ($i = 0; $i -lt 8; $i++) {
1619
+ $cli = $null
1620
+ $hc = Get-Command hippoclaw -ErrorAction SilentlyContinue
1621
+ if ($hc) { $cli = $hc.Source }
1622
+ else {
1623
+ $oc = Get-Command openclaw -ErrorAction SilentlyContinue
1624
+ if ($oc) { $cli = $oc.Source }
1625
+ }
1626
+ if (-not $cli) { break }
1627
+ $prefix = Split-Path -Parent $cli
1628
+ if (-not $prefix) { break }
1629
+ # Windows npm global layout: <prefix>\node_modules\openclaw plus shims in <prefix>.
1630
+ $pkgRoot = Join-Path $prefix "node_modules\openclaw"
1631
+ if (Test-Path -LiteralPath $pkgRoot) {
1632
+ Log-Info "Removing openclaw package tree resolved via CLI on PATH: $pkgRoot"
1633
+ Remove-Item -Recurse -Force -LiteralPath $pkgRoot -ErrorAction SilentlyContinue
1634
+ }
1635
+ Remove-ManagedGatewayShims -PrefixDir $prefix
1636
+ $still = Get-Command hippoclaw -ErrorAction SilentlyContinue
1637
+ if (-not $still) { $still = Get-Command openclaw -ErrorAction SilentlyContinue }
1638
+ if (-not $still) { break }
1639
+ if ($still.Source -eq $cli) { break }
1640
+ }
1641
+ }
1642
+
1643
+ function Uninstall-Gateway {
1644
+ $null = Ensure-NodeNpm
1645
+ Invoke-OpenclawUninstallService
1646
+ Write-Host ""
1647
+ Log-Step "Uninstalling OpenClaw (global npm package)..."
1648
+ if (-not (Get-Command npm -ErrorAction SilentlyContinue)) {
1649
+ Log-Error "npm not found"
1650
+ exit 1
1651
+ }
1652
+ npm uninstall -g openclaw 2>$null
1653
+ if ($LASTEXITCODE -ne 0) {
1654
+ Log-Warn "npm uninstall returned exit code $LASTEXITCODE (package may not have been installed)"
1655
+ }
1656
+ Remove-ManagedGatewayWrapperState
1657
+ Cleanup-UserGatewayEnvironment
1658
+ # Also remove the install wherever the CLI actually resolves (other Node global prefixes),
1659
+ # not just the active node + managed prefix that `npm uninstall -g` above covers.
1660
+ Remove-ResolvedCliOpenclawInstall
1661
+ Log-Success "Ran: npm uninstall -g openclaw (global tree removed if present)"
1662
+ Log-Info "~/.openclaw was not removed (config, sessions, and credentials stay on disk)."
1663
+ $ocAfter = Get-Command hippoclaw -ErrorAction SilentlyContinue
1664
+ if (-not $ocAfter) { $ocAfter = Get-Command openclaw -ErrorAction SilentlyContinue }
1665
+ if ($ocAfter) {
1666
+ Log-Warn "CLI still resolves to $($ocAfter.Source) (could not be removed automatically; remove it manually)."
1667
+ }
1668
+ Write-Host ""
1669
+ Stop-OrphanGatewayListenersOnPorts
1670
+ }
1671
+
1672
+ # ============================================================================
1673
+ # Write starter config
1674
+ # ============================================================================
1675
+ function Write-Config {
1676
+ $configPath = Join-Path $env:USERPROFILE ".openclaw\openclaw.json"
1677
+
1678
+ if (Test-Path $configPath) {
1679
+ Log-Info "Config already exists at $configPath -- skipping"
1680
+ Update-GatewayInstallStatus -Phase "installing" -Message "Config already exists; verifying install..." -StepUpdates @{ configExists = $true }
1681
+ return
1682
+ }
1683
+
1684
+ Log-Step "Writing starter config..."
1685
+ Update-GatewayInstallStatus -Phase "installing" -Message "Writing starter config..."
1686
+ $configDir = Split-Path $configPath -Parent
1687
+ New-Item -ItemType Directory -Path $configDir -Force | Out-Null
1688
+
1689
+ # Generate a random auth token
1690
+ $bytes = New-Object byte[] 24
1691
+ [System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)
1692
+ $randomToken = "ah-" + ([System.BitConverter]::ToString($bytes) -replace '-','').ToLower()
1693
+
1694
+ if ($ConfigTemplate -and (Test-Path $ConfigTemplate)) {
1695
+ # Copy template and replace placeholder token
1696
+ $content = Get-Content $ConfigTemplate -Raw
1697
+ $content = $content -replace '__GENERATED_TOKEN__', $randomToken
1698
+ [System.IO.File]::WriteAllBytes($configPath, [System.Text.Encoding]::UTF8.GetBytes($content))
1699
+ Log-Success "Config written from template: $configPath"
1700
+ Update-GatewayInstallStatus -Phase "installing" -Message "Config written; verifying install..." -StepUpdates @{ configExists = $true }
1701
+ } else {
1702
+ $minimalConfig = @"
1703
+ // OpenClaw Gateway Configuration (JSON5)
1704
+ // Docs: https://docs.openclaw.ai/configuration
1705
+ {
1706
+ "gateway": { "mode": "local", "auth": { "token": "$randomToken" } },
1707
+ "update": { "checkOnStart": false, "managedMode": true },
1708
+ "bindings": [],
1709
+ "channels": {},
1710
+ "plugins": { "entries": {} },
1711
+ "session": { "dmScope": "per-peer" },
1712
+ "agents": { "defaults": { "maxConcurrent": 4 } }
1713
+ }
1714
+ "@
1715
+ [System.IO.File]::WriteAllBytes($configPath, [System.Text.Encoding]::UTF8.GetBytes($minimalConfig))
1716
+ Log-Success "Starter config written: $configPath"
1717
+ Update-GatewayInstallStatus -Phase "installing" -Message "Config written; verifying install..." -StepUpdates @{ configExists = $true }
1718
+ }
1719
+
1720
+ Write-Host ""
1721
+ Write-Host "Next: Edit $configPath to add your channels (Telegram, WhatsApp, etc.)" -ForegroundColor Cyan
1722
+ }
1723
+
1724
+ # ============================================================================
1725
+ # Main
1726
+ # ============================================================================
1727
+
1728
+ Write-Host ""
1729
+ Write-Host " +---------------------------------------+" -ForegroundColor Cyan
1730
+ Write-Host " | Agent Anywhere Setup |" -ForegroundColor Cyan
1731
+ Write-Host " | Reach your agents from anywhere |" -ForegroundColor Cyan
1732
+ Write-Host " +---------------------------------------+" -ForegroundColor Cyan
1733
+ Write-Host ""
1734
+
1735
+ if ($Check) {
1736
+ $result = Check-Installed
1737
+ if ($result) { exit 0 } else { exit 1 }
1738
+ }
1739
+
1740
+ if ($Reinstall) {
1741
+ if (-not $Source) {
1742
+ Log-Error "-Reinstall requires -Source <src>"
1743
+ Fail-GatewayInstallStatus -Message "Reinstall requires an install source."
1744
+ exit 1
1745
+ }
1746
+ Initialize-GatewayInstallStatus -Phase "checking-prerequisites" -Message "Starting reinstall..."
1747
+ Log-Step "Reinstall: uninstall -> verify -> install"
1748
+ Uninstall-Gateway
1749
+ Write-Host ""
1750
+ Log-Step "Post-uninstall verification (-Check)..."
1751
+ Check-Uninstalled | Out-Null
1752
+ Write-Host ""
1753
+ if (-not (Check-Prerequisites)) {
1754
+ Write-Host ""
1755
+ Log-Error "Prerequisites not met. Install the missing tools and try again."
1756
+ Fail-GatewayInstallStatus -Message "Prerequisites not met."
1757
+ exit 1
1758
+ }
1759
+ Write-Host ""
1760
+ Install-Gateway
1761
+ Write-Config
1762
+ Write-Host ""
1763
+ Check-Installed -UpdateInstallStatus | Out-Null
1764
+ Write-Host ""
1765
+ Write-Host "Reinstall complete. Next steps:" -ForegroundColor White
1766
+ Write-Host " 1. Edit " -NoNewline; Write-Host "~\.openclaw\openclaw.json" -ForegroundColor Cyan -NoNewline; Write-Host " to add your channels"
1767
+ Write-Host " 2. Click " -NoNewline; Write-Host "Agent Anywhere" -ForegroundColor Cyan -NoNewline; Write-Host " to start."
1768
+ Write-Host ""
1769
+ exit 0
1770
+ }
1771
+
1772
+ if ($Uninstall) {
1773
+ Remove-Item -Path $script:GatewayInstallStatusPath -Force -ErrorAction SilentlyContinue
1774
+ Uninstall-Gateway
1775
+ Write-Host ""
1776
+ Check-Uninstalled | Out-Null
1777
+ exit 0
1778
+ }
1779
+
1780
+ Initialize-GatewayInstallStatus -Phase "checking-prerequisites" -Message "Checking prerequisites..."
1781
+
1782
+ # Prerequisites
1783
+ if (-not (Check-Prerequisites)) {
1784
+ Write-Host ""
1785
+ Log-Error "Prerequisites not met. Install the missing tools and try again."
1786
+ Fail-GatewayInstallStatus -Message "Prerequisites not met."
1787
+ exit 1
1788
+ }
1789
+
1790
+ # Install if not present OR if the resolved CLI is broken (shim exists but dist/ missing,
1791
+ # e.g. left behind by an earlier failed npm install). A bare presence check would skip the
1792
+ # install and "finish" in a broken state.
1793
+ if (-not (Test-GatewayCliFunctional)) {
1794
+ Write-Host ""
1795
+ Install-Gateway
1796
+ }
1797
+
1798
+ if (-not (Resolve-ManagedGatewayCliPath) -and (Resolve-ManagedGatewayInstall)) {
1799
+ Ensure-ManagedGatewayWrappers | Out-Null
1800
+ }
1801
+
1802
+ # Write config if missing
1803
+ Write-Config
1804
+
1805
+ # Final status
1806
+ Write-Host ""
1807
+ Check-Installed -UpdateInstallStatus | Out-Null
1808
+
1809
+ Write-Host ""
1810
+ Write-Host "Done! Next steps:" -ForegroundColor White
1811
+ Write-Host " 1. Edit " -NoNewline; Write-Host "~\.openclaw\openclaw.json" -ForegroundColor Cyan -NoNewline; Write-Host " to add your channels"
1812
+ Write-Host " 2. Click " -NoNewline; Write-Host "Agent Anywhere" -ForegroundColor Cyan -NoNewline; Write-Host " to start."
1813
+ Write-Host ""