@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,1541 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Copyright (c) AgentHippo.ai. All rights reserved.
4
+ #
5
+ # Agent Anywhere — Gateway Setup
6
+ #
7
+ # Installs OpenClaw Gateway and builds the web UI so users can
8
+ # configure messaging channels (Telegram, WhatsApp, Slack, etc.)
9
+ #
10
+ # Usage:
11
+ # ./setup-gateway.sh # Interactive
12
+ # ./setup-gateway.sh --source openclaw/openclaw#branch # Specify source
13
+ # ./setup-gateway.sh --source github:org/repo # npm git protocol
14
+ # ./setup-gateway.sh --source /path/to/local/openclaw # Local source
15
+ # ./setup-gateway.sh --check # Check status only
16
+ # ./setup-gateway.sh --uninstall # stop gateway + npm uninstall -g (config kept)
17
+ # ./setup-gateway.sh --reinstall --source <src> # uninstall, verify (--check), then install
18
+ # ./setup-gateway.sh --no-modify-path # opt out: skip adding wrapper dir to PATH
19
+ #
20
+
21
+ set -euo pipefail
22
+
23
+ # npm/@npmcli: lifecycle hooks use promise-spawn with shell=true → spawns bare `sh` (not /bin/sh).
24
+ # @npmcli/run-script setPATH() rebuilds PATH from node_modules/.bin walk + parent PATH; if PATH was
25
+ # empty/unset, `sh` is not on PATH → spawn sh ENOENT (baileys preinstall, etc.).
26
+ export PATH="/usr/bin:/bin:/usr/sbin:/sbin${PATH:+:$PATH}"
27
+ export npm_config_script_shell=/bin/sh
28
+ # Corepack should never block Agent Anywhere setup waiting for interactive approval.
29
+ export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
30
+
31
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
32
+
33
+ # Colors
34
+ RED='\033[0;31m'
35
+ GREEN='\033[0;32m'
36
+ YELLOW='\033[1;33m'
37
+ BLUE='\033[0;34m'
38
+ CYAN='\033[0;36m'
39
+ BOLD='\033[1m'
40
+ NC='\033[0m'
41
+
42
+ # Defaults
43
+ INSTALL_SOURCE="${INSTALL_SOURCE:-}"
44
+ CHECK_ONLY=false
45
+ UNINSTALL=false
46
+ REINSTALL=false
47
+ GATEWAY_PORT="${GATEWAY_PORT:-18789}"
48
+ CONFIG_TEMPLATE="${CONFIG_TEMPLATE:-}"
49
+ PORT_FROM_CLI=false
50
+ MODIFY_PATH=true
51
+
52
+ if [[ "${AGENT_ANYWHERE_MODIFY_PATH:-0}" == "0" ]]; then
53
+ MODIFY_PATH=false
54
+ fi
55
+
56
+ # Parse arguments
57
+ while [[ $# -gt 0 ]]; do
58
+ case "$1" in
59
+ --source|-s)
60
+ INSTALL_SOURCE="$2"
61
+ shift 2
62
+ ;;
63
+ --uninstall)
64
+ UNINSTALL=true
65
+ shift
66
+ ;;
67
+ --reinstall)
68
+ REINSTALL=true
69
+ shift
70
+ ;;
71
+ --check|-c)
72
+ CHECK_ONLY=true
73
+ shift
74
+ ;;
75
+ --port|-p)
76
+ GATEWAY_PORT="$2"
77
+ PORT_FROM_CLI=true
78
+ shift 2
79
+ ;;
80
+ --config-template)
81
+ CONFIG_TEMPLATE="$2"
82
+ shift 2
83
+ ;;
84
+ --modify-path)
85
+ MODIFY_PATH=true
86
+ shift
87
+ ;;
88
+ --no-modify-path)
89
+ MODIFY_PATH=false
90
+ shift
91
+ ;;
92
+ --help|-h)
93
+ echo "Usage: $0 [options]"
94
+ echo ""
95
+ echo "Options:"
96
+ echo " --source, -s <src> npm install source (git repo or local path)"
97
+ echo " --check, -c Check installation status only"
98
+ echo " --uninstall Stop gateway, remove global openclaw (~/.openclaw unchanged)"
99
+ echo " --reinstall With --source: uninstall, run check, then full install"
100
+ echo " --port, -p <port> Gateway port (default: gateway.port in ~/.openclaw/openclaw.json, else 18789)"
101
+ echo " --config-template <f> Path to starter config template"
102
+ echo " --modify-path Persist only the stable wrapper dir to your shell profile (default: on)"
103
+ echo " --no-modify-path Do not write the wrapper-dir PATH block to shell profiles"
104
+ echo " (set AGENT_ANYWHERE_MODIFY_PATH=0 to disable)"
105
+ echo " --help, -h Show this help"
106
+ exit 0
107
+ ;;
108
+ *)
109
+ echo "Unknown option: $1"
110
+ exit 1
111
+ ;;
112
+ esac
113
+ done
114
+
115
+ # Read gateway.port from ~/.openclaw/openclaw.json (JSON5-ish: strip // comments) for stop/check/start alignment with OpenClaw.
116
+ read_openclaw_config_gateway_port() {
117
+ local f="$HOME/.openclaw/openclaw.json"
118
+ [[ -f "$f" ]] || return 1
119
+ command -v node &>/dev/null || return 1
120
+ node -e '
121
+ const fs = require("fs");
122
+ const path = require("path");
123
+ const os = require("os");
124
+ const fp = path.join(os.homedir(), ".openclaw", "openclaw.json");
125
+ if (!fs.existsSync(fp)) process.exit(1);
126
+ let t = fs.readFileSync(fp, "utf8");
127
+ t = t.replace(/^\s*\/\/.*$/gm, "").replace(/,\s*([\]}])/g, "$1");
128
+ try {
129
+ const j = JSON.parse(t);
130
+ const p = j && j.gateway && j.gateway.port;
131
+ if (typeof p === "number" && p >= 1 && p <= 65535) { process.stdout.write(String(p)); process.exit(0); }
132
+ if (typeof p === "string" && /^[0-9]+$/.test(p)) { process.stdout.write(p); process.exit(0); }
133
+ } catch (e) {}
134
+ process.exit(1);
135
+ ' 2>/dev/null
136
+ }
137
+
138
+ # When --port is omitted, match the running gateway / OpenClaw config (IDE uses the same file).
139
+ if ! $PORT_FROM_CLI; then
140
+ _cfg_port=""
141
+ _cfg_port=$(read_openclaw_config_gateway_port) || true
142
+ if [[ -n "$_cfg_port" ]]; then
143
+ GATEWAY_PORT="$_cfg_port"
144
+ fi
145
+ fi
146
+
147
+ # Logging
148
+ log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
149
+ log_success() { echo -e "${GREEN} ✓${NC} $1"; }
150
+ log_warn() { echo -e "${YELLOW} ✗${NC} $1"; }
151
+ log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
152
+ log_step() { echo -e "\n${BOLD}${CYAN}$1${NC}"; }
153
+
154
+ NODE_REQUIRED_VERSION="${NODE_REQUIRED_VERSION:-22.14.0}"
155
+ NODE_BOOTSTRAP_VERSION="${AGENT_ANYWHERE_NODE_VERSION:-22.22.0}"
156
+ NODE_BOOTSTRAP_ROOT="${HOME}/.agenthippo/tools/node"
157
+ NPM_GLOBAL_PREFIX="${HOME}/.npm-global"
158
+ USING_BOOTSTRAP_NODE=false
159
+ MANAGED_GATEWAY_STATE_DIR="${HOME}/.agenthippo/gateway"
160
+ MANAGED_GATEWAY_MANIFEST_PATH="${MANAGED_GATEWAY_STATE_DIR}/install.json"
161
+ MANAGED_GATEWAY_WRAPPER_DIR="${HOME}/.local/bin"
162
+ AGENT_ANYWHERE_PATH_MARKER_BEGIN="# >>> Agent Anywhere PATH >>>"
163
+ AGENT_ANYWHERE_PATH_MARKER_END="# <<< Agent Anywhere PATH <<<"
164
+ MANAGED_GATEWAY_WRAPPER_MARKER="# Managed by Agent Anywhere"
165
+
166
+ add_path_entry() {
167
+ local entry="$1"
168
+ [[ -n "$entry" ]] || return 0
169
+ local p new_path=""
170
+ IFS=':' read -r -a _path_parts <<<"${PATH:-}"
171
+ for p in "${_path_parts[@]}"; do
172
+ [[ -z "$p" || "$p" == "$entry" ]] && continue
173
+ if [[ -z "$new_path" ]]; then
174
+ new_path="$p"
175
+ else
176
+ new_path="$new_path:$p"
177
+ fi
178
+ done
179
+ export PATH="$entry${new_path:+:$new_path}"
180
+ }
181
+
182
+ path_contains_entry() {
183
+ local entry="$1"
184
+ [[ -n "$entry" ]] || return 1
185
+ local part
186
+ IFS=':' read -r -a _path_parts <<<"${PATH:-}"
187
+ for part in "${_path_parts[@]}"; do
188
+ [[ "$part" == "$entry" ]] && return 0
189
+ done
190
+ return 1
191
+ }
192
+
193
+ is_fish_profile() {
194
+ local file="$1"
195
+ [[ "$file" == "$HOME/.config/fish/config.fish" ]]
196
+ }
197
+
198
+ build_agent_anywhere_shell_path_block() {
199
+ local profile_file="${1:-}"
200
+ if is_fish_profile "$profile_file"; then
201
+ cat <<'EOF'
202
+ # >>> Agent Anywhere PATH >>>
203
+ # Added by Agent Anywhere setup: keep the stable wrapper dir on PATH.
204
+ function _agent_anywhere_prepend_path --argument-names entry
205
+ test -n "$entry"; or return 0
206
+ set -l filtered_path
207
+ for p in $PATH
208
+ if test "$p" != "$entry"
209
+ set -a filtered_path "$p"
210
+ end
211
+ end
212
+ set -gx PATH "$entry" $filtered_path
213
+ end
214
+ EOF
215
+ cat <<'EOF'
216
+ if test -d "$HOME/.local/bin"
217
+ _agent_anywhere_prepend_path "$HOME/.local/bin"
218
+ end
219
+ functions -e _agent_anywhere_prepend_path 2>/dev/null
220
+ # <<< Agent Anywhere PATH <<<
221
+ EOF
222
+ return 0
223
+ fi
224
+
225
+ cat <<'EOF'
226
+ # >>> Agent Anywhere PATH >>>
227
+ # Added by Agent Anywhere setup: keep the stable wrapper dir on PATH.
228
+ _agent_anywhere_prepend_path() {
229
+ [ -n "${1:-}" ] || return 0
230
+ PATH=":${PATH}:"
231
+ PATH="${PATH//:$1:/:}"
232
+ PATH="${PATH#:}"
233
+ PATH="${PATH%:}"
234
+ PATH="$1${PATH:+:$PATH}"
235
+ }
236
+ EOF
237
+ cat <<'EOF'
238
+ if [ -d "$HOME/.local/bin" ]; then
239
+ _agent_anywhere_prepend_path "$HOME/.local/bin"
240
+ fi
241
+ export PATH
242
+ unset -f _agent_anywhere_prepend_path 2>/dev/null || true
243
+ # <<< Agent Anywhere PATH <<<
244
+ EOF
245
+ }
246
+
247
+ upsert_shell_block_in_file() {
248
+ local file="$1"
249
+ local block tmp_file
250
+ block="$(build_agent_anywhere_shell_path_block "$file")"
251
+ if [[ ! -f "$file" ]]; then
252
+ if ! touch "$file" 2>/dev/null; then
253
+ log_warn "Could not update shell profile $file"
254
+ return 1
255
+ fi
256
+ fi
257
+ tmp_file="$(mktemp "${TMPDIR:-/tmp}/agent-anywhere-profile.XXXXXX")"
258
+ awk -v begin="$AGENT_ANYWHERE_PATH_MARKER_BEGIN" -v end="$AGENT_ANYWHERE_PATH_MARKER_END" '
259
+ $0 == begin { skip = 1; next }
260
+ $0 == end { skip = 0; next }
261
+ skip != 1 { print }
262
+ ' "$file" > "$tmp_file"
263
+ printf '\n%s\n' "$block" >> "$tmp_file"
264
+ if cmp -s "$file" "$tmp_file"; then
265
+ rm -f "$tmp_file"
266
+ return 1
267
+ fi
268
+ mv "$tmp_file" "$file"
269
+ return 0
270
+ }
271
+
272
+ resolve_active_shell_profile() {
273
+ local shell_name
274
+ shell_name="$(basename "${SHELL:-}")"
275
+ case "$shell_name" in
276
+ zsh)
277
+ printf '%s\n' "$HOME/.zshrc"
278
+ ;;
279
+ bash)
280
+ if [[ "$(uname -s 2>/dev/null)" == "Darwin" ]]; then
281
+ printf '%s\n' "$HOME/.bash_profile"
282
+ else
283
+ printf '%s\n' "$HOME/.bashrc"
284
+ fi
285
+ ;;
286
+ fish)
287
+ printf '%s\n' "$HOME/.config/fish/config.fish"
288
+ ;;
289
+ *)
290
+ printf '%s\n' "$HOME/.profile"
291
+ ;;
292
+ esac
293
+ }
294
+
295
+ persist_shell_path_setup() {
296
+ $MODIFY_PATH || return 0
297
+
298
+ local file changed=false
299
+ file="$(resolve_active_shell_profile)"
300
+ if upsert_shell_block_in_file "$file"; then
301
+ changed=true
302
+ fi
303
+
304
+ if $changed; then
305
+ log_info "Persisted PATH for future terminals in $file (open a new terminal window after setup)."
306
+ fi
307
+ }
308
+
309
+ remove_agent_anywhere_shell_block_from_file() {
310
+ local file="$1"
311
+ [[ -f "$file" ]] || return 1
312
+
313
+ local tmp_file
314
+ tmp_file="$(mktemp "${TMPDIR:-/tmp}/agent-anywhere-profile-clean.XXXXXX")"
315
+ awk -v begin="$AGENT_ANYWHERE_PATH_MARKER_BEGIN" -v end="$AGENT_ANYWHERE_PATH_MARKER_END" '
316
+ $0 == begin { skip = 1; next }
317
+ $0 == end { skip = 0; next }
318
+ skip != 1 { print }
319
+ ' "$file" > "$tmp_file"
320
+
321
+ if cmp -s "$file" "$tmp_file"; then
322
+ rm -f "$tmp_file"
323
+ return 1
324
+ fi
325
+
326
+ mv "$tmp_file" "$file"
327
+ return 0
328
+ }
329
+
330
+ cleanup_shell_path_setup() {
331
+ local file changed=false
332
+ local -a profile_targets=(
333
+ "$HOME/.zprofile"
334
+ "$HOME/.zshrc"
335
+ "$HOME/.bash_profile"
336
+ "$HOME/.bashrc"
337
+ "$HOME/.profile"
338
+ "$HOME/.config/fish/config.fish"
339
+ )
340
+
341
+ for file in "${profile_targets[@]}"; do
342
+ if remove_agent_anywhere_shell_block_from_file "$file"; then
343
+ changed=true
344
+ fi
345
+ done
346
+
347
+ if $changed; then
348
+ log_info "Removed Agent Anywhere PATH block from shell profiles."
349
+ fi
350
+ }
351
+
352
+ set_npm_user_prefix() {
353
+ mkdir -p "$NPM_GLOBAL_PREFIX/bin" "$NPM_GLOBAL_PREFIX/lib" 2>/dev/null || true
354
+ export npm_config_prefix="$NPM_GLOBAL_PREFIX"
355
+ add_path_entry "$NPM_GLOBAL_PREFIX/bin"
356
+ }
357
+
358
+ npm_global_install_writable() {
359
+ command -v npm &>/dev/null || return 1
360
+ local prefix root root_parent
361
+ prefix="$(npm prefix -g 2>/dev/null || true)"
362
+ [[ -n "$prefix" && -d "$prefix" && -w "$prefix" ]] || return 1
363
+ if [[ -d "$prefix/bin" && ! -w "$prefix/bin" ]]; then
364
+ return 1
365
+ fi
366
+ root="$(npm root -g 2>/dev/null || true)"
367
+ [[ -n "$root" ]] || return 1
368
+ root_parent="$(dirname "$root")"
369
+ [[ -d "$root_parent" && -w "$root_parent" ]]
370
+ }
371
+
372
+ configure_npm_global_context() {
373
+ if [[ "${npm_config_prefix:-}" == "$NPM_GLOBAL_PREFIX" ]]; then
374
+ unset npm_config_prefix
375
+ fi
376
+ if [[ "${NPM_CONFIG_PREFIX:-}" == "$NPM_GLOBAL_PREFIX" ]]; then
377
+ unset NPM_CONFIG_PREFIX
378
+ fi
379
+
380
+ # Default: use npm's normal global prefix (nvm/fnm/homebrew/system).
381
+ # Fallback to ~/.npm-global only when the default prefix is not writable.
382
+ if npm_global_install_writable; then
383
+ return 0
384
+ fi
385
+ set_npm_user_prefix
386
+ }
387
+
388
+ node_version_is_compatible() {
389
+ local version="${1:-}"
390
+ version="${version#v}"
391
+ local required="${NODE_REQUIRED_VERSION#v}"
392
+ local major minor patch_rest patch req_major req_minor req_patch_rest req_patch
393
+ IFS='.' read -r major minor patch_rest <<<"$version"
394
+ IFS='.' read -r req_major req_minor req_patch_rest <<<"$required"
395
+ patch="${patch_rest%%[^0-9]*}"
396
+ req_patch="${req_patch_rest%%[^0-9]*}"
397
+ major="${major:-0}"
398
+ minor="${minor:-0}"
399
+ patch="${patch:-0}"
400
+ req_major="${req_major:-0}"
401
+ req_minor="${req_minor:-0}"
402
+ req_patch="${req_patch:-0}"
403
+ [[ "$major" =~ ^[0-9]+$ && "$minor" =~ ^[0-9]+$ && "$patch" =~ ^[0-9]+$ ]] || return 1
404
+ [[ "$req_major" =~ ^[0-9]+$ && "$req_minor" =~ ^[0-9]+$ && "$req_patch" =~ ^[0-9]+$ ]] || return 1
405
+ if [[ "$major" -gt "$req_major" ]]; then
406
+ return 0
407
+ fi
408
+ if [[ "$major" -lt "$req_major" ]]; then
409
+ return 1
410
+ fi
411
+ if [[ "$minor" -gt "$req_minor" ]]; then
412
+ return 0
413
+ fi
414
+ if [[ "$minor" -lt "$req_minor" ]]; then
415
+ return 1
416
+ fi
417
+ [[ "$patch" -ge "$req_patch" ]]
418
+ }
419
+
420
+ node_is_compatible() {
421
+ if ! command -v node &>/dev/null; then
422
+ return 1
423
+ fi
424
+ local version
425
+ version=$(node -v 2>/dev/null || true)
426
+ node_version_is_compatible "$version"
427
+ }
428
+
429
+ activate_bootstrap_node_if_available() {
430
+ local candidate_dir candidate_node version
431
+ [[ -d "$NODE_BOOTSTRAP_ROOT" ]] || return 1
432
+ while IFS= read -r candidate_node; do
433
+ candidate_dir="${candidate_node%/node}"
434
+ [[ -x "$candidate_node" ]] || continue
435
+ version=$("$candidate_node" -v 2>/dev/null || true)
436
+ if node_version_is_compatible "$version"; then
437
+ add_path_entry "$candidate_dir"
438
+ USING_BOOTSTRAP_NODE=true
439
+ return 0
440
+ fi
441
+ done < <(find "$NODE_BOOTSTRAP_ROOT" -maxdepth 4 -type f -path '*/bin/node' 2>/dev/null | sort -r)
442
+ return 1
443
+ }
444
+
445
+ resolve_gateway_wrapper_path() {
446
+ printf '%s\n' "${MANAGED_GATEWAY_WRAPPER_DIR}/hippoclaw"
447
+ }
448
+
449
+ resolve_openclaw_wrapper_path() {
450
+ printf '%s\n' "${MANAGED_GATEWAY_WRAPPER_DIR}/openclaw"
451
+ }
452
+
453
+ wrapper_is_managed_by_agent_anywhere() {
454
+ local wrapper_path="$1"
455
+ [[ -f "$wrapper_path" ]] || return 1
456
+ grep -Fq "$MANAGED_GATEWAY_WRAPPER_MARKER" "$wrapper_path" 2>/dev/null
457
+ }
458
+
459
+ write_gateway_wrapper() {
460
+ local node_path="$1"
461
+ local entry_script_path="$2"
462
+ local wrapper_path="$3"
463
+ mkdir -p "$(dirname "$wrapper_path")"
464
+ cat > "$wrapper_path" <<EOF
465
+ #!/bin/sh
466
+ $MANAGED_GATEWAY_WRAPPER_MARKER
467
+ exec "$node_path" "$entry_script_path" "\$@"
468
+ EOF
469
+ chmod +x "$wrapper_path"
470
+ }
471
+
472
+ resolve_managed_gateway_install_from_root() {
473
+ local node_path="$1"
474
+ local package_root="$2"
475
+ local bin_dir="$3"
476
+ [[ -x "$node_path" && -d "$package_root" ]] || return 1
477
+ node - "$node_path" "$package_root" "$bin_dir" <<'EOF'
478
+ const fs = require("fs");
479
+ const path = require("path");
480
+ const [nodePath, pkgRoot, binDir] = process.argv.slice(2);
481
+ const pkgJsonPath = path.join(pkgRoot, "package.json");
482
+ if (!fs.existsSync(pkgJsonPath)) {
483
+ process.exit(1);
484
+ }
485
+ const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
486
+ let bins = pkg.bin;
487
+ if (typeof bins === "string") {
488
+ bins = { [pkg.name || "openclaw"]: bins };
489
+ }
490
+ const names = [...new Set(["hippoclaw", "openclaw", ...Object.keys(bins || {})])];
491
+ for (const name of names) {
492
+ const relativeEntry = bins && typeof bins[name] === "string" ? bins[name] : undefined;
493
+ if (!relativeEntry) {
494
+ continue;
495
+ }
496
+ const entryScriptPath = path.resolve(pkgRoot, relativeEntry);
497
+ if (!fs.existsSync(entryScriptPath)) {
498
+ continue;
499
+ }
500
+ const launcherPath = binDir ? path.join(binDir, name) : "";
501
+ if (!launcherPath || fs.existsSync(launcherPath)) {
502
+ process.stdout.write(`${nodePath}\n${launcherPath}\n${entryScriptPath}\n${pkgRoot}\n`);
503
+ process.exit(0);
504
+ }
505
+ }
506
+ process.exit(1);
507
+ EOF
508
+ }
509
+
510
+ resolve_managed_gateway_install() {
511
+ local current_node npm_root prefix package_root
512
+ current_node="$(command -v node 2>/dev/null || true)"
513
+
514
+ if [[ -n "$current_node" ]]; then
515
+ npm_root="$(npm root -g 2>/dev/null || true)"
516
+ prefix="$(npm prefix -g 2>/dev/null || true)"
517
+ package_root="${npm_root}/openclaw"
518
+ if [[ -n "$npm_root" && -n "$prefix" && -d "$package_root" ]]; then
519
+ resolve_managed_gateway_install_from_root "$current_node" "$package_root" "${prefix}/bin" && return 0
520
+ fi
521
+
522
+ package_root="${NPM_GLOBAL_PREFIX}/lib/node_modules/openclaw"
523
+ if [[ -d "$package_root" ]]; then
524
+ resolve_managed_gateway_install_from_root "$current_node" "$package_root" "${NPM_GLOBAL_PREFIX}/bin" && return 0
525
+ fi
526
+ fi
527
+
528
+ local candidate_node candidate_dir install_dir
529
+ [[ -d "$NODE_BOOTSTRAP_ROOT" ]] || return 1
530
+ while IFS= read -r candidate_node; do
531
+ candidate_dir="${candidate_node%/node}"
532
+ install_dir="$(dirname "$candidate_dir")"
533
+ package_root="${install_dir}/lib/node_modules/openclaw"
534
+ if [[ -d "$package_root" ]]; then
535
+ resolve_managed_gateway_install_from_root "$candidate_node" "$package_root" "$candidate_dir" && return 0
536
+ fi
537
+ done < <(find "$NODE_BOOTSTRAP_ROOT" -maxdepth 4 -type f -path '*/bin/node' 2>/dev/null | sort -r)
538
+ return 1
539
+ }
540
+
541
+ write_managed_gateway_manifest() {
542
+ local node_path="$1"
543
+ local cli_path="$2"
544
+ local entry_script_path="$3"
545
+ local package_root="$4"
546
+ local wrapper_path="$5"
547
+ local openclaw_wrapper_path="${6:-}"
548
+ mkdir -p "$MANAGED_GATEWAY_STATE_DIR"
549
+ node - "$MANAGED_GATEWAY_MANIFEST_PATH" "$node_path" "$cli_path" "$entry_script_path" "$package_root" "$wrapper_path" "$MANAGED_GATEWAY_WRAPPER_DIR" "$openclaw_wrapper_path" <<'EOF'
550
+ const fs = require("fs");
551
+ const path = require("path");
552
+ const [manifestPath, nodePath, cliPath, entryScriptPath, packageRoot, wrapperPath, wrapperDir, openclawWrapperPath] = process.argv.slice(2);
553
+ const record = {
554
+ nodePath,
555
+ cliPath,
556
+ entryScriptPath,
557
+ packageRoot,
558
+ wrapperPath,
559
+ wrapperDir,
560
+ updatedAt: new Date().toISOString(),
561
+ };
562
+ if (openclawWrapperPath) {
563
+ record.openclawWrapperPath = openclawWrapperPath;
564
+ }
565
+ fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
566
+ fs.writeFileSync(manifestPath, JSON.stringify(record, null, 2));
567
+ EOF
568
+ }
569
+
570
+ resolve_gateway_cli_bin_from_manifest() {
571
+ [[ -f "$MANAGED_GATEWAY_MANIFEST_PATH" ]] || return 1
572
+ node - "$MANAGED_GATEWAY_MANIFEST_PATH" <<'EOF'
573
+ const fs = require("fs");
574
+ const manifestPath = process.argv[2];
575
+ try {
576
+ const record = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
577
+ for (const candidate of [record.wrapperPath, record.cliPath]) {
578
+ if (candidate && fs.existsSync(candidate)) {
579
+ process.stdout.write(candidate);
580
+ process.exit(0);
581
+ }
582
+ }
583
+ } catch {
584
+ // ignore
585
+ }
586
+ process.exit(1);
587
+ EOF
588
+ }
589
+
590
+ resolve_managed_gateway_package_root_from_manifest() {
591
+ [[ -f "$MANAGED_GATEWAY_MANIFEST_PATH" ]] || return 1
592
+ node - "$MANAGED_GATEWAY_MANIFEST_PATH" <<'EOF'
593
+ const fs = require("fs");
594
+ const manifestPath = process.argv[2];
595
+ try {
596
+ const record = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
597
+ if (record.packageRoot && fs.existsSync(record.packageRoot)) {
598
+ process.stdout.write(record.packageRoot);
599
+ process.exit(0);
600
+ }
601
+ } catch {
602
+ // ignore
603
+ }
604
+ process.exit(1);
605
+ EOF
606
+ }
607
+
608
+ ensure_gateway_wrappers() {
609
+ local resolved_output node_path cli_path entry_script_path package_root wrapper_path openclaw_wrapper_path=""
610
+ resolved_output="$(resolve_managed_gateway_install)" || {
611
+ log_warn "Could not resolve managed gateway install location after setup"
612
+ return 1
613
+ }
614
+ node_path="$(printf '%s\n' "$resolved_output" | sed -n '1p')"
615
+ cli_path="$(printf '%s\n' "$resolved_output" | sed -n '2p')"
616
+ entry_script_path="$(printf '%s\n' "$resolved_output" | sed -n '3p')"
617
+ package_root="$(printf '%s\n' "$resolved_output" | sed -n '4p')"
618
+ [[ -n "$node_path" && -n "$entry_script_path" && -n "$package_root" ]] || {
619
+ log_warn "Managed gateway install metadata was incomplete"
620
+ return 1
621
+ }
622
+
623
+ wrapper_path="$(resolve_gateway_wrapper_path)"
624
+ write_gateway_wrapper "$node_path" "$entry_script_path" "$wrapper_path"
625
+
626
+ local existing_openclaw_wrapper
627
+ existing_openclaw_wrapper="$(resolve_openclaw_wrapper_path)"
628
+ if wrapper_is_managed_by_agent_anywhere "$existing_openclaw_wrapper"; then
629
+ write_gateway_wrapper "$node_path" "$entry_script_path" "$existing_openclaw_wrapper"
630
+ openclaw_wrapper_path="$existing_openclaw_wrapper"
631
+ fi
632
+
633
+ write_managed_gateway_manifest "$node_path" "$cli_path" "$entry_script_path" "$package_root" "$wrapper_path" "$openclaw_wrapper_path"
634
+
635
+ if $MODIFY_PATH; then
636
+ persist_shell_path_setup
637
+ fi
638
+
639
+ log_info "Stable CLI wrapper ready: $wrapper_path"
640
+ if ! path_contains_entry "$MANAGED_GATEWAY_WRAPPER_DIR"; then
641
+ if $MODIFY_PATH; then
642
+ log_info "Open a new terminal after setup so $MANAGED_GATEWAY_WRAPPER_DIR is available on PATH."
643
+ else
644
+ log_info "Add $MANAGED_GATEWAY_WRAPPER_DIR to PATH if you want to run hippoclaw directly from new terminals."
645
+ fi
646
+ fi
647
+ }
648
+
649
+ remove_managed_gateway_wrapper_state() {
650
+ local wrapper_path openclaw_wrapper_path
651
+ wrapper_path="$(resolve_gateway_wrapper_path)"
652
+ openclaw_wrapper_path="$(resolve_openclaw_wrapper_path)"
653
+ if wrapper_is_managed_by_agent_anywhere "$wrapper_path"; then
654
+ rm -f "$wrapper_path"
655
+ fi
656
+ if wrapper_is_managed_by_agent_anywhere "$openclaw_wrapper_path"; then
657
+ rm -f "$openclaw_wrapper_path"
658
+ fi
659
+ rm -f "$MANAGED_GATEWAY_MANIFEST_PATH"
660
+ }
661
+
662
+ install_node_runtime() {
663
+ local uname_s uname_m node_os node_arch archive_ext version dist_name url
664
+ uname_s="$(uname -s)"
665
+ uname_m="$(uname -m)"
666
+
667
+ case "$uname_s" in
668
+ Darwin)
669
+ node_os="darwin"
670
+ archive_ext="tar.gz"
671
+ ;;
672
+ Linux)
673
+ node_os="linux"
674
+ archive_ext="tar.xz"
675
+ ;;
676
+ *)
677
+ log_error "Automatic Node bootstrap unsupported on OS: $uname_s"
678
+ return 1
679
+ ;;
680
+ esac
681
+
682
+ case "$uname_m" in
683
+ x86_64|amd64) node_arch="x64" ;;
684
+ arm64|aarch64) node_arch="arm64" ;;
685
+ *)
686
+ log_error "Automatic Node bootstrap unsupported on architecture: $uname_m"
687
+ return 1
688
+ ;;
689
+ esac
690
+
691
+ version="${NODE_BOOTSTRAP_VERSION#v}"
692
+ dist_name="node-v${version}-${node_os}-${node_arch}"
693
+ url="https://nodejs.org/dist/v${version}/${dist_name}.${archive_ext}"
694
+ local install_dir="${NODE_BOOTSTRAP_ROOT}/${dist_name}"
695
+ local bin_dir="${install_dir}/bin"
696
+
697
+ if [[ -x "${bin_dir}/node" && -x "${bin_dir}/npm" ]]; then
698
+ add_path_entry "$bin_dir"
699
+ USING_BOOTSTRAP_NODE=true
700
+ return 0
701
+ fi
702
+
703
+ log_info "Installing Node.js v${version} (${node_os}-${node_arch}) to ${NODE_BOOTSTRAP_ROOT}"
704
+ mkdir -p "$NODE_BOOTSTRAP_ROOT"
705
+
706
+ local work_dir archive_path
707
+ work_dir="$(mktemp -d "${TMPDIR:-/tmp}/agent-anywhere-node.XXXXXX")"
708
+ archive_path="${work_dir}/${dist_name}.${archive_ext}"
709
+
710
+ if ! curl -fsSL "$url" -o "$archive_path"; then
711
+ rm -rf "$work_dir"
712
+ log_error "Failed to download Node.js runtime from $url"
713
+ return 1
714
+ fi
715
+
716
+ if [[ "$archive_ext" == "tar.xz" ]]; then
717
+ tar -xJf "$archive_path" -C "$work_dir" || {
718
+ rm -rf "$work_dir"
719
+ log_error "Failed to extract Node.js archive (.tar.xz)"
720
+ return 1
721
+ }
722
+ else
723
+ tar -xzf "$archive_path" -C "$work_dir" || {
724
+ rm -rf "$work_dir"
725
+ log_error "Failed to extract Node.js archive (.tar.gz)"
726
+ return 1
727
+ }
728
+ fi
729
+
730
+ if [[ ! -d "${work_dir}/${dist_name}" ]]; then
731
+ rm -rf "$work_dir"
732
+ log_error "Downloaded Node.js archive did not contain ${dist_name}"
733
+ return 1
734
+ fi
735
+
736
+ rm -rf "$install_dir"
737
+ mv "${work_dir}/${dist_name}" "$install_dir"
738
+ rm -rf "$work_dir"
739
+
740
+ add_path_entry "$bin_dir"
741
+ USING_BOOTSTRAP_NODE=true
742
+ return 0
743
+ }
744
+
745
+ ensure_node_npm() {
746
+ if node_is_compatible && command -v npm &>/dev/null; then
747
+ configure_npm_global_context
748
+ return 0
749
+ fi
750
+
751
+ activate_bootstrap_node_if_available || true
752
+ if node_is_compatible && command -v npm &>/dev/null; then
753
+ configure_npm_global_context
754
+ return 0
755
+ fi
756
+
757
+ install_node_runtime || return 1
758
+ if node_is_compatible && command -v npm &>/dev/null; then
759
+ configure_npm_global_context
760
+ return 0
761
+ fi
762
+
763
+ log_error "Node.js bootstrap finished but node/npm are still unavailable"
764
+ return 1
765
+ }
766
+
767
+ # Git / GitHub-style sources need a local UI build (published tarballs ship dist/).
768
+ needs_source_build() {
769
+ if [[ -z "$INSTALL_SOURCE" ]]; then
770
+ return 1
771
+ fi
772
+ local s="$INSTALL_SOURCE"
773
+ if [[ "$s" == /* || "$s" == ./* ]]; then
774
+ return 0
775
+ fi
776
+ if [[ "$s" == github:* || "$s" == git+http:* || "$s" == git+https:* ]]; then
777
+ return 0
778
+ fi
779
+ if [[ "$s" == *"#"* ]]; then
780
+ return 0
781
+ fi
782
+ # npm GitHub shorthand: owner/repo (not @scope/pkg)
783
+ if [[ "$s" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]]; then
784
+ return 0
785
+ fi
786
+ return 1
787
+ }
788
+
789
+ needs_pnpm() {
790
+ needs_source_build
791
+ }
792
+
793
+ # Remote GitHub / git URL: npm install -g github:... can leave a dangling symlink; we clone, npm pack,
794
+ # and npm install -g the .tgz for a real global tree. Git checkouts do not include compiled dist/ (gitignored);
795
+ # we must pnpm build + ui:build in the clone before npm pack so dist/entry.(m)js and dist/control-ui exist.
796
+ install_openclaw_from_remote_git_spec() {
797
+ local spec="$1"
798
+ local s="$spec" ref=""
799
+ if [[ "$s" == *"#"* ]]; then
800
+ ref="${s##*#}"
801
+ s="${s%#*}"
802
+ fi
803
+
804
+ local clone_url=""
805
+ if [[ "$s" == git+https:* || "$s" == git+http:* ]]; then
806
+ clone_url="${s#git+}"
807
+ elif [[ "$s" == github:* ]]; then
808
+ clone_url="https://github.com/${s#github:}.git"
809
+ elif [[ "$s" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]]; then
810
+ clone_url="https://github.com/${s}.git"
811
+ else
812
+ log_error "Unsupported git install source: $spec"
813
+ exit 1
814
+ fi
815
+
816
+ local work
817
+ work="$(mktemp -d "${TMPDIR:-/tmp}/openclaw-gateway-src.XXXXXX")"
818
+
819
+ log_info "Cloning $(basename "$clone_url" .git) (shallow) for npm pack install..."
820
+ if [[ -n "$ref" ]]; then
821
+ git clone --depth 1 -b "$ref" "$clone_url" "$work/src" || {
822
+ log_error "git clone failed (check ref and network)"
823
+ rm -rf "$work"
824
+ exit 1
825
+ }
826
+ else
827
+ git clone --depth 1 "$clone_url" "$work/src" || {
828
+ log_error "git clone failed"
829
+ rm -rf "$work"
830
+ exit 1
831
+ }
832
+ fi
833
+
834
+ build_openclaw_in_dir "$work/src" || {
835
+ log_error "OpenClaw build failed in clone (need pnpm, Node 22.14+, network for deps)"
836
+ rm -rf "$work"
837
+ exit 1
838
+ }
839
+
840
+ log_info "npm pack --ignore-scripts (no publish prepare hooks required)..."
841
+ (cd "$work/src" && npm pack --ignore-scripts) || {
842
+ log_error "npm pack failed"
843
+ rm -rf "$work"
844
+ exit 1
845
+ }
846
+
847
+ local tgz
848
+ tgz="$(ls -t "$work/src"/openclaw-*.tgz 2>/dev/null | head -1)"
849
+ if [[ -z "$tgz" || ! -f "$tgz" ]]; then
850
+ log_error "npm pack did not produce openclaw-*.tgz under clone"
851
+ rm -rf "$work"
852
+ exit 1
853
+ fi
854
+
855
+ log_info "npm install -g $(basename "$tgz") ..."
856
+ npm install -g "$tgz" || {
857
+ log_error "npm install -g tarball failed"
858
+ rm -rf "$work"
859
+ exit 1
860
+ }
861
+
862
+ REMOTE_GATEWAY_CLONE_SRC="$work/src"
863
+ REMOTE_GATEWAY_WORK_DIR="$work"
864
+ }
865
+
866
+ # ============================================================================
867
+ # Check prerequisites
868
+ # ============================================================================
869
+ check_prerequisites() {
870
+ log_step "Checking prerequisites..."
871
+
872
+ local all_good=true
873
+
874
+ if ! ensure_node_npm; then
875
+ log_warn "Could not automatically provision Node.js/npm"
876
+ all_good=false
877
+ fi
878
+
879
+ # Node.js >= 22.14
880
+ if node_is_compatible; then
881
+ log_success "Node.js $(node -v)"
882
+ elif command -v node &>/dev/null; then
883
+ log_warn "Node.js $(node -v) — version 22.14+ required"
884
+ all_good=false
885
+ else
886
+ log_warn "Node.js not found (version 22.14+ required)"
887
+ echo " Automatic bootstrap failed. Install manually: https://nodejs.org/"
888
+ all_good=false
889
+ fi
890
+
891
+ # npm
892
+ if command -v npm &>/dev/null; then
893
+ log_success "npm $(npm -v)"
894
+ else
895
+ log_warn "npm not found"
896
+ all_good=false
897
+ fi
898
+
899
+ # git (clone + npm pack path for remote GitHub/git install sources)
900
+ if needs_pnpm; then
901
+ local src="$INSTALL_SOURCE"
902
+ if [[ "$src" != /* && "$src" != ./* ]]; then
903
+ if command -v git &>/dev/null; then
904
+ log_success "git $(git --version | head -1)"
905
+ else
906
+ log_warn "git not found (required for GitHub / git URL gateway install sources)"
907
+ all_good=false
908
+ fi
909
+ fi
910
+ fi
911
+
912
+ # pnpm (needed for pnpm build + ui:build when installing from git/local source)
913
+ if needs_pnpm; then
914
+ if command -v pnpm &>/dev/null; then
915
+ log_success "pnpm $(pnpm -v)"
916
+ else
917
+ if ensure_pnpm; then
918
+ log_success "pnpm $(pnpm -v)"
919
+ else
920
+ log_warn "pnpm not found (needed to build OpenClaw from source)"
921
+ all_good=false
922
+ fi
923
+ fi
924
+ else
925
+ log_info "pnpm not required for published package install"
926
+ fi
927
+
928
+ $all_good
929
+ }
930
+
931
+ # ============================================================================
932
+ # Ensure pnpm is available when we need to build the UI
933
+ # ============================================================================
934
+ ensure_pnpm() {
935
+ if command -v pnpm &>/dev/null; then
936
+ log_success "pnpm $(pnpm -v)"
937
+ return 0
938
+ fi
939
+
940
+ log_warn "pnpm not found — attempting to install"
941
+
942
+ if command -v corepack &>/dev/null; then
943
+ log_info "Installing pnpm via corepack..."
944
+ export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
945
+ if corepack prepare pnpm@latest --activate &>/dev/null; then
946
+ if command -v pnpm &>/dev/null; then
947
+ log_success "pnpm $(pnpm -v)"
948
+ return 0
949
+ fi
950
+ fi
951
+ fi
952
+
953
+ if command -v npm &>/dev/null; then
954
+ log_info "Installing pnpm via npm..."
955
+ if npm install -g pnpm; then
956
+ log_success "pnpm $(pnpm -v)"
957
+ return 0
958
+ fi
959
+ fi
960
+
961
+ log_warn "pnpm install failed — skipping web UI build"
962
+ return 1
963
+ }
964
+
965
+ # Full compile + control UI in a repo checkout (dist/ is not committed to git).
966
+ build_openclaw_in_dir() {
967
+ local dir="$1"
968
+ if [[ ! -d "$dir" ]]; then
969
+ log_error "build_openclaw_in_dir: not a directory: $dir"
970
+ return 1
971
+ fi
972
+ ensure_pnpm || {
973
+ log_error "pnpm is required to build OpenClaw from a git checkout"
974
+ return 1
975
+ }
976
+ log_info "pnpm install && pnpm build && pnpm ui:build in $(basename "$dir") (may take several minutes)..."
977
+ (
978
+ cd "$dir" || exit 1
979
+ if [[ ! -f pnpm-lock.yaml ]]; then
980
+ log_error "pnpm-lock.yaml missing — expected an OpenClaw repo checkout"
981
+ exit 1
982
+ fi
983
+ pnpm install || {
984
+ log_error "pnpm install failed"
985
+ exit 1
986
+ }
987
+ pnpm build || {
988
+ log_error "pnpm build failed"
989
+ exit 1
990
+ }
991
+ pnpm ui:build || {
992
+ log_error "pnpm ui:build failed"
993
+ exit 1
994
+ }
995
+ )
996
+ }
997
+
998
+ # ============================================================================
999
+ # Check installed components
1000
+ # ============================================================================
1001
+ check_installed() {
1002
+ log_step "Checking installed components..."
1003
+
1004
+ local all_ok=true
1005
+
1006
+ # Gateway CLI binary (prefer hippoclaw from fork, fallback to openclaw)
1007
+ local cli_bin=""
1008
+ cli_bin="$(resolve_gateway_cli_bin || true)"
1009
+ if [[ -n "$cli_bin" ]]; then
1010
+ local oc_version
1011
+ if oc_version="$("$cli_bin" --version 2>/dev/null | head -1)" && [[ -n "$oc_version" ]]; then
1012
+ log_success "Gateway CLI installed ($(basename "$cli_bin")): $oc_version"
1013
+ log_info "Gateway CLI path: $cli_bin"
1014
+ else
1015
+ log_warn "Gateway CLI found ($cli_bin) but command failed (stale/broken shim)"
1016
+ all_ok=false
1017
+ fi
1018
+ else
1019
+ # Check common install locations
1020
+ local found=false
1021
+ local dir name candidate
1022
+ for dir in \
1023
+ "$HOME/Library/pnpm" \
1024
+ "$HOME/.local/share/pnpm" \
1025
+ "$HOME/.npm-global/bin" \
1026
+ "/usr/local/bin" \
1027
+ "/usr/bin"; do
1028
+ for name in hippoclaw openclaw; do
1029
+ candidate="$dir/$name"
1030
+ if [[ -x "$candidate" ]]; then
1031
+ local oc_version
1032
+ oc_version=$("$candidate" --version 2>/dev/null | head -1 || echo "unknown")
1033
+ log_success "Gateway CLI installed at $candidate: $oc_version"
1034
+ found=true
1035
+ break 2
1036
+ fi
1037
+ done
1038
+ done
1039
+ if ! $found; then
1040
+ log_warn "Gateway CLI not installed (hippoclaw/openclaw)"
1041
+ all_ok=false
1042
+ fi
1043
+ fi
1044
+
1045
+ # CLI dist and Web UI under global npm package (npm root first; ~/.npm-global legacy fallback)
1046
+ local npm_root groot ui_dir
1047
+ groot="$(resolve_managed_gateway_package_root_from_manifest || true)"
1048
+ if [[ -z "$groot" || ! -d "$groot" ]]; then
1049
+ npm_root="$(npm root -g 2>/dev/null || true)"
1050
+ groot=""
1051
+ [[ -n "$npm_root" ]] && groot="$npm_root/openclaw"
1052
+ if [[ -z "$groot" || ! -d "$groot" ]]; then
1053
+ groot="$NPM_GLOBAL_PREFIX/lib/node_modules/openclaw"
1054
+ fi
1055
+ fi
1056
+ if [[ -n "$groot" && -d "$groot" ]]; then
1057
+ if [[ -f "$groot/dist/entry.mjs" || -f "$groot/dist/entry.js" ]]; then
1058
+ log_success "CLI dist present ($groot/dist/entry.*)"
1059
+ else
1060
+ log_warn "CLI dist missing (run setup with source build or reinstall from npm)"
1061
+ all_ok=false
1062
+ fi
1063
+
1064
+ ui_dir="$groot/dist/control-ui"
1065
+ if [[ -f "$ui_dir/index.html" ]]; then
1066
+ log_success "Web UI built ($ui_dir)"
1067
+ else
1068
+ log_warn "Web UI not built"
1069
+ all_ok=false
1070
+ fi
1071
+ else
1072
+ if [[ -n "$cli_bin" ]]; then
1073
+ log_warn "Global npm openclaw package not found (CLI appears external/non-npm)"
1074
+ else
1075
+ log_warn "Global npm openclaw package not found"
1076
+ fi
1077
+ all_ok=false
1078
+ fi
1079
+
1080
+ # Gateway running? Informational only; install succeeds even when stopped.
1081
+ if nc -z 127.0.0.1 "$GATEWAY_PORT" 2>/dev/null; then
1082
+ log_success "Gateway running on 127.0.0.1:$GATEWAY_PORT"
1083
+ else
1084
+ log_info "Gateway not running on port $GATEWAY_PORT (this is OK; start it from Agent Anywhere when needed)"
1085
+ fi
1086
+
1087
+ # Config file
1088
+ local config_path="$HOME/.openclaw/openclaw.json"
1089
+ if [[ -f "$config_path" ]]; then
1090
+ log_success "Config file present ($config_path)"
1091
+ else
1092
+ log_warn "Config file not found ($config_path)"
1093
+ all_ok=false
1094
+ fi
1095
+
1096
+ echo ""
1097
+ if $all_ok; then
1098
+ echo -e "${GREEN}${BOLD}Agent Anywhere is fully installed!${NC}"
1099
+ return 0
1100
+ else
1101
+ echo -e "${YELLOW}${BOLD}Agent Anywhere setup is incomplete.${NC}"
1102
+ return 1
1103
+ fi
1104
+ }
1105
+
1106
+ check_uninstalled() {
1107
+ log_step "Checking uninstall state..."
1108
+
1109
+ local all_ok=true
1110
+ local cli_bin=""
1111
+
1112
+ cli_bin="$(resolve_gateway_cli_bin_on_path 2>/dev/null || true)"
1113
+ if [[ -n "$cli_bin" ]]; then
1114
+ log_warn "Gateway CLI still resolves to $cli_bin (likely external/non-npm install)"
1115
+ else
1116
+ log_success "Gateway CLI not installed (hippoclaw/openclaw)"
1117
+ fi
1118
+
1119
+ local groot=""
1120
+ groot="$(resolve_managed_gateway_package_root_from_manifest || true)"
1121
+ if [[ -z "$groot" || ! -d "$groot" ]]; then
1122
+ groot="$NPM_GLOBAL_PREFIX/lib/node_modules/openclaw"
1123
+ fi
1124
+ if [[ -n "$groot" && -d "$groot" ]]; then
1125
+ log_warn "Managed npm openclaw package still present ($groot)"
1126
+ all_ok=false
1127
+ else
1128
+ log_success "Managed npm openclaw package not found"
1129
+ fi
1130
+
1131
+ if nc -z 127.0.0.1 "$GATEWAY_PORT" 2>/dev/null; then
1132
+ log_warn "Gateway still running on 127.0.0.1:$GATEWAY_PORT"
1133
+ all_ok=false
1134
+ else
1135
+ log_success "Gateway not running on port $GATEWAY_PORT"
1136
+ fi
1137
+
1138
+ local config_path="$HOME/.openclaw/openclaw.json"
1139
+ if [[ -f "$config_path" ]]; then
1140
+ log_success "Config file preserved ($config_path)"
1141
+ else
1142
+ log_info "Config file already absent ($config_path)"
1143
+ fi
1144
+
1145
+ echo ""
1146
+ if $all_ok; then
1147
+ echo -e "${GREEN}${BOLD}Agent Anywhere uninstall complete.${NC}"
1148
+ return 0
1149
+ else
1150
+ echo -e "${YELLOW}${BOLD}Agent Anywhere uninstall needs attention.${NC}"
1151
+ return 1
1152
+ fi
1153
+ }
1154
+
1155
+ # ============================================================================
1156
+ # Install gateway
1157
+ # ============================================================================
1158
+ install_gateway() {
1159
+ if [[ -z "$INSTALL_SOURCE" ]]; then
1160
+ log_error "No install source specified. Use --source <source>"
1161
+ exit 1
1162
+ fi
1163
+
1164
+ REMOTE_GATEWAY_CLONE_SRC=""
1165
+ REMOTE_GATEWAY_WORK_DIR=""
1166
+
1167
+ log_step "Installing OpenClaw Gateway..."
1168
+ log_info "Source: $INSTALL_SOURCE"
1169
+
1170
+ local _npm_root
1171
+ _npm_root="$(npm root -g 2>/dev/null || true)"
1172
+ if [[ -n "$_npm_root" && -e "$_npm_root/openclaw" ]]; then
1173
+ log_info "Removing existing global openclaw tree (avoids partial install / tar errors)..."
1174
+ rm -rf "$_npm_root/openclaw"
1175
+ fi
1176
+
1177
+ # Local directory: npm links to that path (stable). Remote github:/git+: use clone+pack+tgz
1178
+ # so global node_modules/openclaw is a real tree (npm git+ignore-scripts leaves a dangling symlink).
1179
+ if needs_source_build; then
1180
+ if [[ "$INSTALL_SOURCE" == /* || "$INSTALL_SOURCE" == ./* ]]; then
1181
+ local abs_src
1182
+ abs_src="$(cd "$INSTALL_SOURCE" && pwd)"
1183
+ build_openclaw_in_dir "$abs_src" || exit 1
1184
+ npm install -g "$abs_src"
1185
+ else
1186
+ install_openclaw_from_remote_git_spec "$INSTALL_SOURCE"
1187
+ fi
1188
+ else
1189
+ npm install -g "$INSTALL_SOURCE"
1190
+ fi
1191
+ log_success "npm install complete"
1192
+ ensure_gateway_wrappers || true
1193
+
1194
+ if needs_source_build; then
1195
+ # dist/ was built before pack (remote) or before npm install -g (local); remove temp clone only.
1196
+ if [[ -n "${REMOTE_GATEWAY_WORK_DIR:-}" ]]; then
1197
+ log_info "Removing temporary clone directory..."
1198
+ rm -rf "$REMOTE_GATEWAY_WORK_DIR"
1199
+ REMOTE_GATEWAY_WORK_DIR=""
1200
+ REMOTE_GATEWAY_CLONE_SRC=""
1201
+ fi
1202
+ else
1203
+ log_info "Published package — web UI should be pre-built"
1204
+ fi
1205
+ }
1206
+
1207
+ # ============================================================================
1208
+ # Stop gateway listeners (graceful CLI stop, then best-effort process/port cleanup)
1209
+ # ============================================================================
1210
+ resolve_gateway_cli_bin_on_path() {
1211
+ if command -v hippoclaw &>/dev/null; then
1212
+ command -v hippoclaw
1213
+ return 0
1214
+ fi
1215
+ if command -v openclaw &>/dev/null; then
1216
+ command -v openclaw
1217
+ return 0
1218
+ fi
1219
+ return 1
1220
+ }
1221
+
1222
+ resolve_gateway_cli_bin() {
1223
+ if resolve_gateway_cli_bin_from_manifest >/dev/null 2>&1; then
1224
+ resolve_gateway_cli_bin_from_manifest
1225
+ return 0
1226
+ fi
1227
+ if resolve_gateway_cli_bin_on_path >/dev/null 2>&1; then
1228
+ resolve_gateway_cli_bin_on_path
1229
+ return 0
1230
+ fi
1231
+ local candidate
1232
+ local dir name
1233
+ local current_prefix
1234
+ current_prefix="$(npm prefix -g 2>/dev/null || true)"
1235
+ for dir in \
1236
+ "$MANAGED_GATEWAY_WRAPPER_DIR" \
1237
+ "${current_prefix}/bin" \
1238
+ "$HOME/Library/pnpm" \
1239
+ "$HOME/.local/share/pnpm" \
1240
+ "$HOME/.npm-global/bin" \
1241
+ "/usr/local/bin" \
1242
+ "/usr/bin"; do
1243
+ for name in hippoclaw openclaw; do
1244
+ candidate="$dir/$name"
1245
+ if [[ -x "$candidate" ]]; then
1246
+ printf '%s\n' "$candidate"
1247
+ return 0
1248
+ fi
1249
+ done
1250
+ done
1251
+ if [[ -d "$NODE_BOOTSTRAP_ROOT" ]]; then
1252
+ while IFS= read -r dir; do
1253
+ for name in hippoclaw openclaw; do
1254
+ candidate="$dir/$name"
1255
+ if [[ -x "$candidate" ]]; then
1256
+ printf '%s\n' "$candidate"
1257
+ return 0
1258
+ fi
1259
+ done
1260
+ done < <(
1261
+ find "$NODE_BOOTSTRAP_ROOT" -maxdepth 4 -type f -path '*/bin/node' -print 2>/dev/null \
1262
+ | xargs -I{} dirname "{}" 2>/dev/null \
1263
+ | sort -u
1264
+ )
1265
+ fi
1266
+ return 1
1267
+ }
1268
+
1269
+ remove_managed_openclaw_artifacts() {
1270
+ local dir install_dir pkg_root
1271
+
1272
+ pkg_root="$NPM_GLOBAL_PREFIX/lib/node_modules/openclaw"
1273
+ if [[ -d "$pkg_root" ]]; then
1274
+ log_info "Removing managed openclaw package from $pkg_root"
1275
+ rm -rf "$pkg_root"
1276
+ fi
1277
+ rm -f "$NPM_GLOBAL_PREFIX/bin/openclaw" "$NPM_GLOBAL_PREFIX/bin/hippoclaw" 2>/dev/null || true
1278
+
1279
+ [[ -d "$NODE_BOOTSTRAP_ROOT" ]] || return 0
1280
+ while IFS= read -r dir; do
1281
+ install_dir="$(dirname "$dir")"
1282
+ pkg_root="$install_dir/lib/node_modules/openclaw"
1283
+ if [[ -d "$pkg_root" ]]; then
1284
+ log_info "Removing managed openclaw package from $pkg_root"
1285
+ rm -rf "$pkg_root"
1286
+ fi
1287
+ rm -f "$dir/openclaw" "$dir/hippoclaw" 2>/dev/null || true
1288
+ done < <(
1289
+ find "$NODE_BOOTSTRAP_ROOT" -maxdepth 4 -type f -path '*/bin/node' -print 2>/dev/null \
1290
+ | xargs -I{} dirname "{}" 2>/dev/null \
1291
+ | sort -u
1292
+ )
1293
+ }
1294
+
1295
+ # Remove the openclaw package wherever the CLI on PATH actually resolves to, including per-version
1296
+ # Node global trees (e.g. nvm) that the managed-prefix cleanup above does not cover. Equivalent to
1297
+ # `npm uninstall -g openclaw` for that prefix (remove the package tree + its bin shims), but
1298
+ # reliable regardless of which Node owns the install. Bounded loop in case several Node versions
1299
+ # each have a copy.
1300
+ remove_resolved_cli_openclaw_install() {
1301
+ local i cli_bin node_bin_dir prefix pkg_root removed_any=false
1302
+ for ((i = 0; i < 8; i++)); do
1303
+ hash -r 2>/dev/null || true
1304
+ cli_bin="$(resolve_gateway_cli_bin_on_path 2>/dev/null || true)"
1305
+ [[ -n "$cli_bin" ]] || break
1306
+ node_bin_dir="$(cd "$(dirname "$cli_bin")" 2>/dev/null && pwd)" || break
1307
+ # npm global layout: <prefix>/bin/<cli> and <prefix>/lib/node_modules/openclaw.
1308
+ prefix="$(dirname "$node_bin_dir")"
1309
+ pkg_root="$prefix/lib/node_modules/openclaw"
1310
+ if [[ -d "$pkg_root" ]]; then
1311
+ log_info "Removing openclaw package tree resolved via CLI on PATH: $pkg_root"
1312
+ rm -rf "$pkg_root" 2>/dev/null || true
1313
+ removed_any=true
1314
+ fi
1315
+ rm -f "$node_bin_dir/openclaw" "$node_bin_dir/hippoclaw" 2>/dev/null || true
1316
+ # Bail if the same path still resolves (could not delete, e.g. permissions) to avoid looping.
1317
+ hash -r 2>/dev/null || true
1318
+ if [[ "$(resolve_gateway_cli_bin_on_path 2>/dev/null || true)" == "$cli_bin" ]]; then
1319
+ break
1320
+ fi
1321
+ done
1322
+ $removed_any && log_success "Removed openclaw install(s) the CLI resolved to outside the managed prefix"
1323
+ return 0
1324
+ }
1325
+
1326
+ # After npm removes the CLI, clear any leftover listener (e.g. detached node). Service teardown is
1327
+ # openclaw uninstall --service; we do not duplicate launchd/systemd/pkill here.
1328
+ free_local_gateway_ports_if_busy() {
1329
+ log_step "Clearing local gateway listener(s) if still bound..."
1330
+ rm -f "$HOME/.openclaw/gateway.pid" 2>/dev/null || true
1331
+ local sweep_ports=("$GATEWAY_PORT")
1332
+ [[ "$GATEWAY_PORT" != "18789" ]] && sweep_ports+=(18789)
1333
+ local sp pids
1334
+ for sp in "${sweep_ports[@]}"; do
1335
+ nc -z 127.0.0.1 "$sp" 2>/dev/null || continue
1336
+ command -v lsof &>/dev/null || {
1337
+ log_warn "Port $sp in use but lsof not available — stop the process manually"
1338
+ continue
1339
+ }
1340
+ log_info "Port $sp in use — stopping listener PID(s)..."
1341
+ pids=$(lsof -nP -iTCP:"$sp" -sTCP:LISTEN -t 2>/dev/null | tr '\n' ' ' || true)
1342
+ if [[ -n "${pids// }" ]]; then
1343
+ # shellcheck disable=SC2086
1344
+ kill $pids 2>/dev/null || true
1345
+ sleep 1
1346
+ pids=$(lsof -nP -iTCP:"$sp" -sTCP:LISTEN -t 2>/dev/null | tr '\n' ' ' || true)
1347
+ if [[ -n "${pids// }" ]]; then
1348
+ # shellcheck disable=SC2086
1349
+ kill -9 $pids 2>/dev/null || true
1350
+ fi
1351
+ fi
1352
+ done
1353
+ local any_up=false
1354
+ for sp in "${sweep_ports[@]}"; do
1355
+ if nc -z 127.0.0.1 "$sp" 2>/dev/null; then
1356
+ any_up=true
1357
+ break
1358
+ fi
1359
+ done
1360
+ if $any_up; then
1361
+ log_warn "A process may still be listening on 127.0.0.1 (${sweep_ports[*]})"
1362
+ else
1363
+ log_success "Gateway port(s) free on 127.0.0.1 (${sweep_ports[*]})"
1364
+ fi
1365
+ }
1366
+
1367
+ # Official teardown: openclaw uninstall --service (launchd/systemd/schtasks) before npm remove.
1368
+ # Docs: https://docs.openclaw.ai/cli/uninstall — does not remove ~/.openclaw unless --state.
1369
+ openclaw_cli_uninstall_service() {
1370
+ local oc_bin=""
1371
+ oc_bin=$(resolve_gateway_cli_bin) || true
1372
+ if [[ -z "$oc_bin" ]]; then
1373
+ return 0
1374
+ fi
1375
+ log_step "OpenClaw CLI: uninstall gateway service..."
1376
+ log_info "Running: $oc_bin uninstall --service --yes --non-interactive"
1377
+ if "$oc_bin" uninstall --service --yes --non-interactive; then
1378
+ log_success "openclaw uninstall --service completed"
1379
+ else
1380
+ log_info "openclaw uninstall --service failed or skipped (continuing)"
1381
+ fi
1382
+ }
1383
+
1384
+ # ============================================================================
1385
+ # Uninstall gateway (OpenClaw service uninstall + npm global remove + port cleanup)
1386
+ # ============================================================================
1387
+ uninstall_gateway() {
1388
+ ensure_node_npm || true
1389
+ openclaw_cli_uninstall_service
1390
+ echo ""
1391
+ log_step "Uninstalling OpenClaw (global npm package)..."
1392
+ if ! command -v npm &>/dev/null; then
1393
+ log_error "npm not found"
1394
+ exit 1
1395
+ fi
1396
+ npm uninstall -g openclaw 2>/dev/null || true
1397
+ remove_managed_gateway_wrapper_state
1398
+ cleanup_shell_path_setup
1399
+ # Also remove the install wherever the CLI actually resolves (nvm/other Node global trees),
1400
+ # not just the active node + managed prefix that `npm uninstall -g` above covers.
1401
+ remove_resolved_cli_openclaw_install
1402
+ log_success "Ran: npm uninstall -g openclaw (global tree removed if present)"
1403
+ log_info "~/.openclaw was not removed (config, sessions, and credentials stay on disk)."
1404
+ local oc_after=""
1405
+ hash -r 2>/dev/null || true
1406
+ oc_after="$(resolve_gateway_cli_bin_on_path 2>/dev/null || true)"
1407
+ if [[ -n "$oc_after" ]]; then
1408
+ log_warn "CLI still resolves to $oc_after (could not be removed automatically; remove it manually)."
1409
+ fi
1410
+ echo ""
1411
+ free_local_gateway_ports_if_busy
1412
+ }
1413
+
1414
+ # ============================================================================
1415
+ # Write starter config
1416
+ # ============================================================================
1417
+ write_config() {
1418
+ local config_path="$HOME/.openclaw/openclaw.json"
1419
+
1420
+ if [[ -f "$config_path" ]]; then
1421
+ log_info "Config already exists at $config_path — skipping"
1422
+ return
1423
+ fi
1424
+
1425
+ log_step "Writing starter config..."
1426
+ mkdir -p "$HOME/.openclaw"
1427
+
1428
+ # Generate a random auth token
1429
+ local random_token="ah-$(openssl rand -hex 24 2>/dev/null || head -c 48 /dev/urandom | od -An -tx1 | tr -d ' \n')"
1430
+
1431
+ if [[ -n "$CONFIG_TEMPLATE" && -f "$CONFIG_TEMPLATE" ]]; then
1432
+ # Copy template and replace placeholder token
1433
+ sed "s/__GENERATED_TOKEN__/${random_token}/" "$CONFIG_TEMPLATE" > "$config_path"
1434
+ log_success "Config written from template: $config_path"
1435
+ else
1436
+ # Minimal inline config with generated token
1437
+ cat > "$config_path" <<CONF
1438
+ // OpenClaw Gateway Configuration (JSON5)
1439
+ // Docs: https://docs.openclaw.ai/configuration
1440
+ {
1441
+ "gateway": { "mode": "local", "auth": { "token": "${random_token}" } },
1442
+ "update": { "checkOnStart": false, "managedMode": true },
1443
+ "bindings": [],
1444
+ "channels": {},
1445
+ "plugins": { "entries": {} },
1446
+ "session": { "dmScope": "per-peer" },
1447
+ "agents": { "defaults": { "maxConcurrent": 4 } }
1448
+ }
1449
+ CONF
1450
+ log_success "Starter config written: $config_path"
1451
+ fi
1452
+
1453
+ # Restrict permissions — config contains auth token
1454
+ chmod 600 "$config_path" 2>/dev/null || true
1455
+
1456
+ echo ""
1457
+ echo -e "${CYAN}Next: Edit $config_path to add your channels (Telegram, WhatsApp, etc.)${NC}"
1458
+ }
1459
+
1460
+ # ============================================================================
1461
+ # Main
1462
+ # ============================================================================
1463
+
1464
+ echo -e "${BOLD}${CYAN}"
1465
+ echo " ╔═══════════════════════════════════════╗"
1466
+ echo " ║ Agent Anywhere Setup ║"
1467
+ echo " ║ Reach your agents from anywhere ║"
1468
+ echo " ╚═══════════════════════════════════════╝"
1469
+ echo -e "${NC}"
1470
+
1471
+ if $CHECK_ONLY; then
1472
+ check_installed
1473
+ exit $?
1474
+ fi
1475
+
1476
+ if $REINSTALL; then
1477
+ if [[ -z "$INSTALL_SOURCE" ]]; then
1478
+ log_error "--reinstall requires --source <src> (or set INSTALL_SOURCE)"
1479
+ exit 1
1480
+ fi
1481
+ log_step "Reinstall: uninstall → verify → install"
1482
+ uninstall_gateway
1483
+ echo ""
1484
+ log_step "Post-uninstall verification (--check)..."
1485
+ check_uninstalled || true
1486
+ echo ""
1487
+ if ! check_prerequisites; then
1488
+ echo ""
1489
+ log_error "Prerequisites not met. Install the missing tools and try again."
1490
+ exit 1
1491
+ fi
1492
+ echo ""
1493
+ install_gateway
1494
+ write_config
1495
+ echo ""
1496
+ check_installed || true
1497
+ echo ""
1498
+ echo -e "${BOLD}Reinstall complete.${NC} Next steps:"
1499
+ echo -e " 1. Edit ${CYAN}~/.openclaw/openclaw.json${NC} to add your channels"
1500
+ echo -e " 2. Click ${CYAN}Agent Anywhere${NC} to start."
1501
+ echo ""
1502
+ exit 0
1503
+ fi
1504
+
1505
+ if $UNINSTALL; then
1506
+ uninstall_gateway
1507
+ echo ""
1508
+ check_uninstalled || true
1509
+ exit 0
1510
+ fi
1511
+
1512
+ # Prerequisites
1513
+ if ! check_prerequisites; then
1514
+ echo ""
1515
+ log_error "Prerequisites not met. Install the missing tools and try again."
1516
+ exit 1
1517
+ fi
1518
+
1519
+ # Install if not present
1520
+ if ! resolve_gateway_cli_bin &>/dev/null; then
1521
+ echo ""
1522
+ install_gateway
1523
+ fi
1524
+
1525
+ # Backfill stable wrappers/manifest for existing managed installs.
1526
+ if ! resolve_gateway_cli_bin_from_manifest >/dev/null 2>&1 && resolve_managed_gateway_install >/dev/null 2>&1; then
1527
+ ensure_gateway_wrappers || true
1528
+ fi
1529
+
1530
+ # Write config if missing
1531
+ write_config
1532
+
1533
+ # Final status
1534
+ echo ""
1535
+ check_installed || true
1536
+
1537
+ echo ""
1538
+ echo -e "${BOLD}Done!${NC} Next steps:"
1539
+ echo -e " 1. Edit ${CYAN}~/.openclaw/openclaw.json${NC} to add your channels"
1540
+ echo -e " 2. Click ${CYAN}Agent Anywhere${NC} to start."
1541
+ echo ""