@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,1279 @@
1
+ "use strict";
2
+ /*---------------------------------------------------------------------------------------------
3
+ * Copyright (c) AgentHippo.ai. All rights reserved.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.AnalyticsService = void 0;
40
+ const vscode = __importStar(require("vscode"));
41
+ const path = __importStar(require("path"));
42
+ const fsSync = __importStar(require("fs"));
43
+ const fs_1 = require("fs");
44
+ const child_process_1 = require("child_process");
45
+ const branding_1 = require("../branding");
46
+ const indexingService_1 = require("./dashboard/indexingService");
47
+ const performanceMonitor_1 = require("./dashboard/performanceMonitor");
48
+ const lifecycle_1 = require("./lifecycle");
49
+ const index_1 = require("../utils/index");
50
+ const windowsCommandLine_1 = require("../utils/windowsCommandLine");
51
+ /**
52
+ * Resolve the preferred PowerShell host on Windows. PowerShell 7 (`pwsh.exe`)
53
+ * fixed native-command argument quoting bugs that affect inline `bash -c`
54
+ * scripts containing embedded double quotes. We prefer it when present and
55
+ * fall back to the always-present Windows PowerShell 5.1 (`powershell.exe`).
56
+ *
57
+ * Cached for the lifetime of the extension host — pwsh install state is not
58
+ * expected to change mid-session, and the lookup hits the filesystem.
59
+ */
60
+ let cachedWindowsPwshPath;
61
+ function getWindowsPwshOrPowerShell() {
62
+ if (process.platform !== 'win32') {
63
+ return 'powershell.exe';
64
+ }
65
+ if (cachedWindowsPwshPath === undefined) {
66
+ cachedWindowsPwshPath = resolvePwshExecutable();
67
+ }
68
+ return cachedWindowsPwshPath ?? 'powershell.exe';
69
+ }
70
+ function resolvePwshExecutable() {
71
+ const candidates = [];
72
+ const pathDirs = (process.env.PATH ?? '').split(path.delimiter).filter(Boolean);
73
+ for (const dir of pathDirs) {
74
+ candidates.push(path.join(dir, 'pwsh.exe'));
75
+ }
76
+ const programFiles = process.env.ProgramFiles ?? 'C:\\Program Files';
77
+ const programFilesX86 = process.env['ProgramFiles(x86)'] ?? 'C:\\Program Files (x86)';
78
+ const localAppData = process.env.LOCALAPPDATA;
79
+ for (const major of ['7', '8']) {
80
+ candidates.push(path.join(programFiles, 'PowerShell', major, 'pwsh.exe'));
81
+ candidates.push(path.join(programFilesX86, 'PowerShell', major, 'pwsh.exe'));
82
+ }
83
+ if (localAppData) {
84
+ candidates.push(path.join(localAppData, 'Microsoft', 'PowerShell', 'pwsh.exe'));
85
+ }
86
+ for (const candidate of candidates) {
87
+ try {
88
+ if (fsSync.statSync(candidate).isFile()) {
89
+ return candidate;
90
+ }
91
+ }
92
+ catch {
93
+ // not present; continue
94
+ }
95
+ }
96
+ return null;
97
+ }
98
+ /**
99
+ * Manages LiteLLM Spotlight (OTEL Collector + DuckDB analytics).
100
+ * Provides status bar indicator and commands for managing the analytics stack.
101
+ */
102
+ class AnalyticsService {
103
+ statusBarItem;
104
+ outputChannel;
105
+ extensionContext;
106
+ _status = 'stopped';
107
+ _lastStackStatus = { otelRunning: false, litellmRunning: false, litellmWithOtel: false };
108
+ indexProgress = { status: 'idle', percent: 0 };
109
+ indexingService;
110
+ performanceMonitor;
111
+ disposables = [];
112
+ lifecycleInProgress = false;
113
+ /**
114
+ * Get the current status of the analytics stack.
115
+ */
116
+ get status() {
117
+ return this._status;
118
+ }
119
+ healthCheckTimer = null;
120
+ static HEALTH_CHECK_INTERVAL = 30000; // 30 seconds
121
+ constructor(extensionContext, outputChannel) {
122
+ this.extensionContext = extensionContext;
123
+ this.outputChannel = outputChannel;
124
+ this.performanceMonitor = new performanceMonitor_1.PerformanceMonitor(outputChannel);
125
+ // Create status bar item
126
+ this.statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 99);
127
+ this.statusBarItem.command = 'agentide.analytics.toggle';
128
+ // Register commands
129
+ this.registerCommands();
130
+ // Check if analytics has ever been configured before starting heartbeat
131
+ void this.initializeWithLazyHeartbeat();
132
+ }
133
+ /**
134
+ * Initialize with lazy heartbeat - only start periodic checks if analytics is configured.
135
+ * This avoids unnecessary process spawning (pgrep) when user hasn't set up analytics.
136
+ */
137
+ async initializeWithLazyHeartbeat() {
138
+ const isConfigured = await this.isAnalyticsConfigured();
139
+ if (isConfigured) {
140
+ // Analytics was set up - do full check and start heartbeat
141
+ this.updateStatusBar('checking');
142
+ await this.checkStatus();
143
+ this.startHeartbeat();
144
+ }
145
+ else {
146
+ // Not configured - show stopped, no heartbeat needed
147
+ this.updateStatusBar('stopped');
148
+ this.statusBarItem.show();
149
+ // Still check for standalone LiteLLM (not tied to analytics)
150
+ // This allows Language Models table to populate even without analytics setup
151
+ await this.detectStandaloneLiteLLM();
152
+ }
153
+ // Initialize background indexing service for dashboard
154
+ await this.initializeIndexingService();
155
+ }
156
+ /**
157
+ * Initialize background indexing service.
158
+ */
159
+ async initializeIndexingService() {
160
+ try {
161
+ const analyticsDir = this.getAnalyticsDir();
162
+ const tracesDir = path.join(analyticsDir, 'traces');
163
+ this.indexingService = new indexingService_1.IndexingService(tracesDir, this.outputChannel, this.performanceMonitor);
164
+ // Subscribe to indexing progress updates
165
+ this.disposables.push(this.indexingService.onProgressChange((progress) => {
166
+ this.indexProgress = progress;
167
+ this.updateStatusBar(this._status); // Refresh status bar with new progress
168
+ }));
169
+ // Initialize indexing service (starts file watcher, checks if re-indexing needed)
170
+ await this.indexingService.initialize();
171
+ }
172
+ catch (error) {
173
+ this.outputChannel.appendLine(`[Analytics] Failed to initialize indexing service: ${error}`);
174
+ }
175
+ }
176
+ /**
177
+ * Get IndexingService instance (for provider integration).
178
+ */
179
+ getIndexingService() {
180
+ return this.indexingService;
181
+ }
182
+ /**
183
+ * Detect standalone LiteLLM (running without analytics) and update base URL setting.
184
+ * This is a one-time check on startup to enable model discovery even when analytics
185
+ * is not configured.
186
+ */
187
+ async detectStandaloneLiteLLM() {
188
+ try {
189
+ const status = await this.getLiteLLMStatus();
190
+ if (status.running) {
191
+ this.outputChannel.appendLine('[Analytics] Detected standalone LiteLLM running');
192
+ }
193
+ }
194
+ catch {
195
+ // Best-effort only - don't block startup
196
+ }
197
+ }
198
+ /**
199
+ * Check if analytics has been configured (config files exist).
200
+ * This is a fast check that doesn't spawn any processes.
201
+ */
202
+ async isAnalyticsConfigured() {
203
+ const analyticsDir = this.getAnalyticsDir();
204
+ const configPath = path.join(analyticsDir, 'config', 'otel-collector.yaml');
205
+ try {
206
+ await fs_1.promises.access(configPath);
207
+ return true;
208
+ }
209
+ catch {
210
+ return false;
211
+ }
212
+ }
213
+ /**
214
+ * Start the periodic heartbeat timer.
215
+ */
216
+ startHeartbeat() {
217
+ if (this.healthCheckTimer) {
218
+ return; // Already running
219
+ }
220
+ this.healthCheckTimer = setInterval(() => {
221
+ void this.checkStatus();
222
+ }, AnalyticsService.HEALTH_CHECK_INTERVAL);
223
+ }
224
+ registerCommands() {
225
+ this.disposables.push(vscode.commands.registerCommand('agentide.analytics.toggle', () => this.toggle()), vscode.commands.registerCommand('agentide.analytics.restart', () => this.restart()), vscode.commands.registerCommand('agentide.analytics.start', () => this.start()), vscode.commands.registerCommand('agentide.analytics.stop', () => this.stop()), vscode.commands.registerCommand('agentide.analytics.status', () => this.showStatus()), vscode.commands.registerCommand('agentide.analytics.query', () => this.openQueryTerminal()), vscode.commands.registerCommand('agentide.analytics.openLiteLLMConfig', () => this.openLiteLLMConfig()),
226
+ // Returns true if the full analytics stack is running (used by core to skip redundant setup prompts)
227
+ vscode.commands.registerCommand('agentide.analytics.isRunning', () => this.checkStatus()));
228
+ }
229
+ /**
230
+ * Get the analytics home directory.
231
+ * Uses shared path utility for consistency.
232
+ */
233
+ getAnalyticsDir() {
234
+ return index_1.DIRS.analytics();
235
+ }
236
+ /**
237
+ * Get the PID file path for OTEL Collector.
238
+ * Uses shared PID_FILES constant for consistency.
239
+ */
240
+ getOtelPidFile() {
241
+ return index_1.PID_FILES.otelcol();
242
+ }
243
+ /**
244
+ * Get the PID file path for LiteLLM.
245
+ * Uses shared PID_FILES constant for consistency.
246
+ */
247
+ getLiteLLMPidFile() {
248
+ return index_1.PID_FILES.litellm();
249
+ }
250
+ /**
251
+ * Check full analytics stack status (OTEL Collector + LiteLLM).
252
+ * Returns true only if both services are properly configured.
253
+ */
254
+ async checkStatus() {
255
+ try {
256
+ const stackStatus = await this.getStackStatus();
257
+ this._lastStackStatus = stackStatus;
258
+ if (stackStatus.otelRunning && stackStatus.litellmWithOtel) {
259
+ // Full stack running properly
260
+ this.updateStatusBar('running');
261
+ return true;
262
+ }
263
+ else if (this.lifecycleInProgress) {
264
+ // During an explicit start/setup/restart, OTEL commonly becomes visible
265
+ // before LiteLLM has written its PID metadata. Keep the UI in a
266
+ // starting state until readiness monitoring completes.
267
+ this.updateStatusBar('checking');
268
+ return false;
269
+ }
270
+ else if (stackStatus.otelRunning || stackStatus.litellmRunning) {
271
+ // Partial - something is running but not fully configured
272
+ this.updateStatusBar('partial');
273
+ return false;
274
+ }
275
+ else {
276
+ // Nothing running
277
+ this.updateStatusBar('stopped');
278
+ return false;
279
+ }
280
+ }
281
+ catch {
282
+ this.updateStatusBar('error');
283
+ return false;
284
+ }
285
+ }
286
+ /**
287
+ * Get detailed status of each analytics component.
288
+ */
289
+ async getStackStatus() {
290
+ const otelRunning = await this.isOtelRunning();
291
+ const litellmStatus = await this.getLiteLLMStatus();
292
+ return {
293
+ otelRunning,
294
+ litellmRunning: litellmStatus.running,
295
+ litellmWithOtel: litellmStatus.withOtel,
296
+ };
297
+ }
298
+ /**
299
+ * Check if OTEL Collector is running via PID file.
300
+ * Cost: ~1-2ms (file read + signal check, no process spawn)
301
+ * Also cleans up stale PID files per ARCHITECTURE.md pattern.
302
+ */
303
+ async isOtelRunning() {
304
+ const result = await (0, index_1.checkPidFileWithCleanup)(this.getOtelPidFile());
305
+ return result !== null;
306
+ }
307
+ /**
308
+ * Check LiteLLM status via the canonical PID file written by agentide-litellm.{sh,ps1}.
309
+ * Cost: ~1-2ms (file read + signal check, no process spawn).
310
+ *
311
+ * PID file format: "PID\n[otel]\n[url=...]". Process detection / killing across
312
+ * platforms (incl. winpid) is handled inside the launcher script — this code only
313
+ * trusts what the launcher wrote.
314
+ */
315
+ async getLiteLLMStatus() {
316
+ const pidData = await (0, index_1.checkPidFileWithCleanup)(this.getLiteLLMPidFile());
317
+ if (!pidData) {
318
+ return { running: false, withOtel: false };
319
+ }
320
+ const metadata = pidData.metadata ?? [];
321
+ const withOtel = metadata.some(line => line.trim().toLowerCase() === 'otel');
322
+ const urlLine = metadata.find(line => line.startsWith('url='));
323
+ if (urlLine) {
324
+ await this.maybeUpdateLiteLLMBaseUrlValue(urlLine.slice('url='.length).trim());
325
+ }
326
+ return { running: true, withOtel };
327
+ }
328
+ async maybeUpdateLiteLLMBaseUrlValue(baseUrl) {
329
+ const config = vscode.workspace.getConfiguration('agentide.providers.litellm');
330
+ if (config.get('baseUrl')?.trim()) {
331
+ return;
332
+ }
333
+ const trimmed = baseUrl.trim();
334
+ if (!trimmed) {
335
+ return;
336
+ }
337
+ await config.update('baseUrl', trimmed, vscode.ConfigurationTarget.Global);
338
+ this.outputChannel.appendLine(`[Analytics] Auto-detected LiteLLM base URL: ${trimmed}`);
339
+ }
340
+ async waitForStackReady(timeoutMs = 30_000, intervalMs = 1_000) {
341
+ const deadline = Date.now() + timeoutMs;
342
+ let lastStatus = await this.getStackStatus();
343
+ while (Date.now() < deadline) {
344
+ lastStatus = await this.getStackStatus();
345
+ this._lastStackStatus = lastStatus;
346
+ if (lastStatus.otelRunning && lastStatus.litellmWithOtel) {
347
+ return lastStatus;
348
+ }
349
+ await new Promise(resolve => setTimeout(resolve, intervalMs));
350
+ }
351
+ return lastStatus;
352
+ }
353
+ async waitForStackStopped(timeoutMs = 15_000, intervalMs = 500) {
354
+ const deadline = Date.now() + timeoutMs;
355
+ let lastStatus = await this.getStackStatus();
356
+ while (Date.now() < deadline) {
357
+ lastStatus = await this.getStackStatus();
358
+ this._lastStackStatus = lastStatus;
359
+ if (!lastStatus.otelRunning && !lastStatus.litellmRunning) {
360
+ return lastStatus;
361
+ }
362
+ await new Promise(resolve => setTimeout(resolve, intervalMs));
363
+ }
364
+ return lastStatus;
365
+ }
366
+ async monitorStartupReadiness(reason) {
367
+ const stackStatus = await this.waitForStackReady();
368
+ this._lastStackStatus = stackStatus;
369
+ const status = this.deriveStatusFrom(stackStatus);
370
+ this.lifecycleInProgress = false;
371
+ this.updateStatusBar(status);
372
+ if (status === 'running') {
373
+ this.log(`Analytics stack ready after ${reason}.`);
374
+ vscode.window.showInformationMessage(`${branding_1.AGENTIDE_BRAND_NAME}: Spotlight ${reason === 'restart' ? 'restarted' : 'started'}.`);
375
+ return;
376
+ }
377
+ this.log(`Analytics stack not fully ready after ${reason} ` +
378
+ `(otel=${stackStatus.otelRunning}, litellm=${stackStatus.litellmRunning}, litellmWithOtel=${stackStatus.litellmWithOtel})`);
379
+ const choice = await vscode.window.showWarningMessage(`${branding_1.AGENTIDE_BRAND_NAME}: Spotlight ${reason === 'restart' ? 'restart' : 'start'} is not fully ready yet.`, 'Show Status');
380
+ if (choice === 'Show Status') {
381
+ await this.showStatus();
382
+ }
383
+ }
384
+ async monitorStopReadiness() {
385
+ const stackStatus = await this.waitForStackStopped();
386
+ this._lastStackStatus = stackStatus;
387
+ const status = this.deriveStatusFrom(stackStatus);
388
+ this.lifecycleInProgress = false;
389
+ this.updateStatusBar(status);
390
+ if (status === 'stopped') {
391
+ this.log('Analytics stack stopped.');
392
+ vscode.window.showInformationMessage(`${branding_1.AGENTIDE_BRAND_NAME}: Spotlight stopped.`);
393
+ return;
394
+ }
395
+ this.log(`Analytics stack not fully stopped ` +
396
+ `(otel=${stackStatus.otelRunning}, litellm=${stackStatus.litellmRunning}, litellmWithOtel=${stackStatus.litellmWithOtel})`);
397
+ const choice = await vscode.window.showWarningMessage(`${branding_1.AGENTIDE_BRAND_NAME}: Spotlight stop is not fully complete yet.`, 'Show Status');
398
+ if (choice === 'Show Status') {
399
+ await this.showStatus();
400
+ }
401
+ }
402
+ /**
403
+ * Handle status bar click.
404
+ * Always open a menu instantly from cached state.
405
+ * Heavy checks/actions run only after explicit user choice.
406
+ */
407
+ async toggle() {
408
+ // Don't block the click on a foreground check; act on the cached snapshot.
409
+ const status = this._status === 'checking'
410
+ ? this.deriveStatusFrom(this._lastStackStatus)
411
+ : this._status;
412
+ if (status === 'running') {
413
+ await this.showStatusWithRestartOption();
414
+ }
415
+ else if (status === 'partial') {
416
+ await this.showPartialStatusOption();
417
+ }
418
+ else {
419
+ await this.showStoppedStatusOption(status);
420
+ }
421
+ }
422
+ queueBackgroundStatusRefresh(reason) {
423
+ if (this.lifecycleInProgress) {
424
+ return;
425
+ }
426
+ setTimeout(() => {
427
+ if (this.lifecycleInProgress) {
428
+ return;
429
+ }
430
+ void this.checkStatus().catch((err) => {
431
+ this.log(`Background status refresh failed after ${reason}: ${err instanceof Error ? err.message : String(err)}`);
432
+ });
433
+ }, 100);
434
+ }
435
+ deriveStatusFrom(s) {
436
+ return (0, lifecycle_1.deriveAnalyticsStatus)(s);
437
+ }
438
+ /**
439
+ * Show options when in partial state (something running but not fully configured).
440
+ */
441
+ async showPartialStatusOption() {
442
+ const stackStatus = this._lastStackStatus;
443
+ const message = (0, lifecycle_1.getPartialSpotlightMessage)(stackStatus);
444
+ const choicePromise = vscode.window.showWarningMessage(`${branding_1.AGENTIDE_BRAND_NAME}: ${message}`, 'Install', 'Restart All', 'Show Status');
445
+ this.queueBackgroundStatusRefresh('opening partial menu');
446
+ const choice = await choicePromise;
447
+ switch (choice) {
448
+ case 'Install':
449
+ await vscode.commands.executeCommand('agentide.setupAnalytics');
450
+ break;
451
+ case 'Restart All':
452
+ await this.restart();
453
+ break;
454
+ case 'Show Status':
455
+ await this.showStatus();
456
+ break;
457
+ }
458
+ }
459
+ /**
460
+ * Show status summary and offer to restart.
461
+ */
462
+ async showStatusWithRestartOption() {
463
+ const choicePromise = vscode.window.showInformationMessage(`${branding_1.AGENTIDE_BRAND_NAME} Spotlight is running.`, 'See Spotlight', 'Restart All', 'Stop', 'Indexing', 'Show Status');
464
+ this.queueBackgroundStatusRefresh('opening running menu');
465
+ const choice = await choicePromise;
466
+ switch (choice) {
467
+ case 'See Spotlight':
468
+ await vscode.commands.executeCommand('agentide.analytics.openDashboard');
469
+ break;
470
+ case 'Restart All':
471
+ await this.restart();
472
+ break;
473
+ case 'Stop':
474
+ await this.stop();
475
+ break;
476
+ case 'Indexing':
477
+ await this.triggerIndexing();
478
+ break;
479
+ case 'Show Status':
480
+ await this.showStatus();
481
+ break;
482
+ }
483
+ }
484
+ /**
485
+ * Restart the analytics stack: stop LiteLLM, restart OTEL via terminal, start LiteLLM detached.
486
+ */
487
+ async restart() {
488
+ this.log('Restarting analytics stack...');
489
+ this.lifecycleInProgress = true;
490
+ this.updateStatusBar('checking');
491
+ if (!(await this.isAnalyticsConfigured())) {
492
+ await this.start();
493
+ return;
494
+ }
495
+ const isWindows = process.platform === 'win32';
496
+ const startScript = await this.findScript(isWindows ? 'start-analytics.ps1' : 'start-analytics.sh');
497
+ if (!startScript) {
498
+ this.lifecycleInProgress = false;
499
+ this.updateStatusBar('error');
500
+ vscode.window.showErrorMessage(`${branding_1.AGENTIDE_BRAND_NAME}: Spotlight scripts not found. Run Install first.`);
501
+ return;
502
+ }
503
+ const terminal = await this.createSpotlightLifecycleTerminal('Spotlight Restart', 'restart', startScript);
504
+ terminal.show();
505
+ this.updateStatusBar('checking');
506
+ this.startHeartbeat();
507
+ void this.monitorStartupReadiness('restart');
508
+ }
509
+ /**
510
+ * Run Windows setup end-to-end from the extension, then start LiteLLM via
511
+ * the existing launcher path. Unix setup remains script-owned for now.
512
+ */
513
+ async setupWindowsSpotlight(options = {}) {
514
+ if (process.platform !== 'win32') {
515
+ return { success: false, error: 'Windows-only setup flow invoked on a non-Windows platform.' };
516
+ }
517
+ const setupScript = await this.findScript('setup-analytics.ps1');
518
+ if (!setupScript) {
519
+ const message = `${branding_1.AGENTIDE_BRAND_NAME}: Spotlight install script not found.`;
520
+ vscode.window.showErrorMessage(message);
521
+ return { success: false, error: message };
522
+ }
523
+ this.lifecycleInProgress = true;
524
+ this.updateStatusBar('checking');
525
+ this.outputChannel.show(true);
526
+ this.log(`${options.reinstall ? 'Reinstalling' : 'Installing/repairing'} Spotlight on Windows...`);
527
+ vscode.window.showInformationMessage(`${branding_1.AGENTIDE_BRAND_NAME}: ${options.reinstall ? 'Reinstalling' : 'Installing'} Spotlight...`);
528
+ try {
529
+ if (options.reinstall) {
530
+ this.log('Stopping LiteLLM before reinstall...');
531
+ await this.stopLiteLLMDirectly();
532
+ }
533
+ const setupOk = await this.runWindowsSetupScript(setupScript);
534
+ if (!setupOk) {
535
+ throw new Error('setup-analytics.ps1 failed');
536
+ }
537
+ const litellmStatus = await this.getLiteLLMStatus();
538
+ if (litellmStatus.running) {
539
+ this.log('Restarting LiteLLM to apply Spotlight config...');
540
+ await this.stopLiteLLMDirectly();
541
+ }
542
+ this.log('Starting LiteLLM proxy via IDE-managed launcher...');
543
+ const litellmStarted = await this.startLiteLLMDirectly();
544
+ if (!litellmStarted) {
545
+ throw new Error('LiteLLM launcher did not start');
546
+ }
547
+ const analyticsDir = this.getAnalyticsDir();
548
+ this.log(`LiteLLM logs: ${path.join(analyticsDir, 'litellm.log')}`);
549
+ this.log(`LiteLLM errors: ${path.join(analyticsDir, 'litellm.error.log')}`);
550
+ this.startHeartbeat();
551
+ void this.monitorStartupReadiness(options.reinstall ? 'restart' : 'start');
552
+ return { success: true };
553
+ }
554
+ catch (error) {
555
+ this.lifecycleInProgress = false;
556
+ this.updateStatusBar('error');
557
+ const message = error instanceof Error ? error.message : String(error);
558
+ this.log(`Windows Spotlight install failed: ${message}`);
559
+ vscode.window.showErrorMessage(`${branding_1.AGENTIDE_BRAND_NAME}: Spotlight install failed. ${message}`);
560
+ return { success: false, error: message };
561
+ }
562
+ }
563
+ /**
564
+ * Show options when Spotlight is stopped/unknown.
565
+ */
566
+ async showStoppedStatusOption(status) {
567
+ const message = status === 'error'
568
+ ? `${branding_1.AGENTIDE_BRAND_NAME}: Spotlight status is unavailable.`
569
+ : `${branding_1.AGENTIDE_BRAND_NAME}: Spotlight is stopped.`;
570
+ const choicePromise = vscode.window.showInformationMessage(message, 'Start', 'Install', 'See Spotlight', 'Show Status');
571
+ this.queueBackgroundStatusRefresh('opening stopped menu');
572
+ const choice = await choicePromise;
573
+ switch (choice) {
574
+ case 'Start':
575
+ await this.start();
576
+ break;
577
+ case 'Install':
578
+ await vscode.commands.executeCommand('agentide.setupAnalytics');
579
+ break;
580
+ case 'See Spotlight':
581
+ await vscode.commands.executeCommand('agentide.analytics.openDashboard');
582
+ break;
583
+ case 'Show Status':
584
+ await this.showStatus();
585
+ break;
586
+ }
587
+ }
588
+ async runWindowsSetupScript(scriptPath) {
589
+ const agentHomeDir = (0, index_1.getAgentideHome)();
590
+ const args = [
591
+ '-NoProfile',
592
+ '-NonInteractive',
593
+ '-ExecutionPolicy',
594
+ 'Bypass',
595
+ '-File',
596
+ scriptPath,
597
+ '-Yes',
598
+ ];
599
+ this.log(`Running ${path.basename(scriptPath)} -Yes...`);
600
+ return new Promise((resolve) => {
601
+ let settled = false;
602
+ const finish = (ok) => {
603
+ if (settled) {
604
+ return;
605
+ }
606
+ settled = true;
607
+ resolve(ok);
608
+ };
609
+ const child = (0, child_process_1.spawn)(getWindowsPwshOrPowerShell(), args, {
610
+ cwd: path.dirname(scriptPath),
611
+ env: { ...process.env, AGENT_HOME_DIR: agentHomeDir },
612
+ windowsHide: true,
613
+ });
614
+ child.stdout?.on('data', data => {
615
+ this.outputChannel.append(data.toString());
616
+ });
617
+ child.stderr?.on('data', data => {
618
+ this.outputChannel.append(data.toString());
619
+ });
620
+ child.once('error', err => {
621
+ this.log(`Windows setup script failed to spawn: ${err.message}`);
622
+ finish(false);
623
+ });
624
+ child.once('exit', code => {
625
+ if (code === 0) {
626
+ this.log('Windows Spotlight install script completed.');
627
+ finish(true);
628
+ }
629
+ else {
630
+ this.log(`Windows Spotlight install script exited with code ${code ?? 'unknown'}.`);
631
+ finish(false);
632
+ }
633
+ });
634
+ });
635
+ }
636
+ /**
637
+ * Start the OTEL Collector.
638
+ */
639
+ async start() {
640
+ const isRunning = await this.checkStatus();
641
+ if (isRunning) {
642
+ vscode.window.showInformationMessage(`${branding_1.AGENTIDE_BRAND_NAME}: Spotlight is already running.`);
643
+ return;
644
+ }
645
+ // Find the start script (platform-specific)
646
+ const isWindows = process.platform === 'win32';
647
+ const scriptPath = await this.findScript(isWindows ? 'start-analytics.ps1' : 'start-analytics.sh');
648
+ if (!scriptPath) {
649
+ this.lifecycleInProgress = false;
650
+ vscode.window.showErrorMessage(`${branding_1.AGENTIDE_BRAND_NAME}: Spotlight scripts not found. Run Install first.`);
651
+ return;
652
+ }
653
+ this.lifecycleInProgress = true;
654
+ this.updateStatusBar('checking');
655
+ const terminal = await this.createSpotlightLifecycleTerminal('Spotlight Start', 'start', scriptPath);
656
+ terminal.show();
657
+ this.log('Starting Spotlight (OTEL Collector + LiteLLM)...');
658
+ vscode.window.showInformationMessage(`${branding_1.AGENTIDE_BRAND_NAME}: Starting Spotlight...`);
659
+ this.updateStatusBar('checking');
660
+ // Start heartbeat if not already running (user just set up analytics)
661
+ this.startHeartbeat();
662
+ void this.monitorStartupReadiness('start');
663
+ }
664
+ /**
665
+ * Stop the OTEL Collector.
666
+ */
667
+ async stop() {
668
+ this.lifecycleInProgress = true;
669
+ this.updateStatusBar('checking');
670
+ // Find the start script (which also handles stopping)
671
+ const isWindows = process.platform === 'win32';
672
+ const scriptPath = await this.findScript(isWindows ? 'start-analytics.ps1' : 'start-analytics.sh');
673
+ if (!scriptPath) {
674
+ // Try to stop directly via PID
675
+ await this.stopDirectly();
676
+ this.lifecycleInProgress = false;
677
+ return;
678
+ }
679
+ // Run the stop command with visible output
680
+ const terminal = await this.createSpotlightLifecycleTerminal('Spotlight Stop', 'stop', scriptPath);
681
+ terminal.show();
682
+ this.log('Stopping Spotlight (OTEL Collector + LiteLLM)...');
683
+ this.updateStatusBar('checking');
684
+ void this.monitorStopReadiness();
685
+ }
686
+ /**
687
+ * Stop OTEL Collector directly via PID file.
688
+ */
689
+ async stopDirectly() {
690
+ try {
691
+ const pidFile = this.getOtelPidFile();
692
+ const pidContent = await fs_1.promises.readFile(pidFile, 'utf8');
693
+ const pid = parseInt(pidContent.trim(), 10);
694
+ if (!isNaN(pid)) {
695
+ process.kill(pid, 'SIGTERM');
696
+ await fs_1.promises.unlink(pidFile).catch(() => { });
697
+ this.log(`Stopped OTEL Collector (PID: ${pid})`);
698
+ }
699
+ await this.stopLiteLLMDirectly();
700
+ this.updateStatusBar('stopped');
701
+ }
702
+ catch (error) {
703
+ this.log(`Failed to stop directly: ${error}`);
704
+ this.updateStatusBar('error');
705
+ }
706
+ }
707
+ async createSpotlightLifecycleTerminal(name, action, startScript) {
708
+ const agentHomeDir = (0, index_1.getAgentideHome)();
709
+ const analyticsDir = path.join(agentHomeDir, 'analytics');
710
+ fsSync.mkdirSync(analyticsDir, { recursive: true });
711
+ const litellmScript = await this.findLiteLLMScript();
712
+ const configPath = path.join(agentHomeDir, 'litellm-otel.yaml');
713
+ const stdoutPath = path.join(analyticsDir, 'litellm.log');
714
+ const stderrPath = path.join(analyticsDir, 'litellm.error.log');
715
+ if (process.platform === 'win32') {
716
+ return vscode.window.createTerminal({
717
+ name,
718
+ cwd: path.dirname(startScript),
719
+ env: { AGENT_HOME_DIR: agentHomeDir },
720
+ shellPath: getWindowsPwshOrPowerShell(),
721
+ shellArgs: [
722
+ '-NoProfile',
723
+ '-NoExit',
724
+ '-ExecutionPolicy',
725
+ 'Bypass',
726
+ '-Command',
727
+ this.buildWindowsSpotlightLifecycleCommand({
728
+ action,
729
+ startScript,
730
+ litellmScript,
731
+ agentHomeDir,
732
+ configPath,
733
+ stdoutPath,
734
+ stderrPath,
735
+ }),
736
+ ],
737
+ });
738
+ }
739
+ return vscode.window.createTerminal({
740
+ name,
741
+ cwd: path.dirname(startScript),
742
+ env: { AGENT_HOME_DIR: agentHomeDir },
743
+ shellPath: '/bin/bash',
744
+ shellArgs: [
745
+ '-c',
746
+ this.buildUnixSpotlightLifecycleCommand({
747
+ action,
748
+ startScript,
749
+ litellmScript,
750
+ agentHomeDir,
751
+ configPath,
752
+ stdoutPath,
753
+ stderrPath,
754
+ }),
755
+ ],
756
+ });
757
+ }
758
+ buildWindowsSpotlightLifecycleCommand(options) {
759
+ const q = (value) => `'${this.escapePowerShellSingleQuotedString(value)}'`;
760
+ const lines = [
761
+ '$ErrorActionPreference = \'Continue\'',
762
+ `$env:AGENT_HOME_DIR = ${q(options.agentHomeDir)}`,
763
+ `Write-Host ${q(this.getLifecycleTerminalIntro(options.action))}`,
764
+ ];
765
+ if (options.action === 'stop' || options.action === 'restart') {
766
+ lines.push('Write-Host ""', 'Write-Host "Stopping LiteLLM proxy..."', ...this.buildWindowsLiteLLMStopCommands(options.litellmScript, q));
767
+ }
768
+ if (options.action === 'stop') {
769
+ lines.push('Write-Host ""', 'Write-Host "Stopping OTEL Collector..."', `& ${q(options.startScript)} -Stop`);
770
+ }
771
+ else if (options.action === 'restart') {
772
+ lines.push('Write-Host ""', 'Write-Host "Restarting OTEL Collector..."', `& ${q(options.startScript)} -Stop`, 'Start-Sleep 1', `& ${q(options.startScript)} -ForceDaemon`);
773
+ }
774
+ else {
775
+ lines.push('Write-Host ""', 'Write-Host "Starting OTEL Collector..."', `& ${q(options.startScript)} -ForceDaemon`);
776
+ }
777
+ if (options.action === 'start' || options.action === 'restart') {
778
+ lines.push('Write-Host ""', ...this.buildWindowsLiteLLMStartCommands(options, q));
779
+ }
780
+ lines.push('Write-Host ""', 'Write-Host "You can close this window."');
781
+ return lines.join('\r\n');
782
+ }
783
+ buildWindowsLiteLLMStopCommands(litellmScript, q) {
784
+ if (!litellmScript) {
785
+ return ['Write-Host "[WARN] LiteLLM launcher script not found. Skipping LiteLLM stop." -ForegroundColor Yellow'];
786
+ }
787
+ return [`& ${q(litellmScript)} -Stop`];
788
+ }
789
+ buildWindowsLiteLLMStartCommands(options, q) {
790
+ if (!options.litellmScript) {
791
+ return ['Write-Host "[WARN] LiteLLM launcher script not found. Skipping LiteLLM start." -ForegroundColor Yellow'];
792
+ }
793
+ const launcherArgumentLine = (0, windowsCommandLine_1.buildWindowsArgumentLine)([
794
+ '-NoProfile',
795
+ '-NoLogo',
796
+ '-ExecutionPolicy',
797
+ 'Bypass',
798
+ '-File',
799
+ options.litellmScript,
800
+ '-ConfigPath',
801
+ options.configPath,
802
+ ]);
803
+ return [
804
+ 'Write-Host "Starting LiteLLM proxy..."',
805
+ `if (-not (Test-Path ${q(options.configPath)})) {`,
806
+ ` Write-Host ${q(`[WARN] LiteLLM config not found: ${options.configPath}`)} -ForegroundColor Yellow`,
807
+ '} else {',
808
+ ` $env:LITELLM_CONFIG_PATH = ${q(options.configPath)}`,
809
+ ' try {',
810
+ ` $proc = Start-Process -FilePath ${q(getWindowsPwshOrPowerShell())} -WindowStyle Hidden -WorkingDirectory ${q(path.dirname(options.litellmScript))} -ArgumentList ${q(launcherArgumentLine)} -RedirectStandardOutput ${q(options.stdoutPath)} -RedirectStandardError ${q(options.stderrPath)} -PassThru -ErrorAction Stop`,
811
+ ' Write-Host "[OK] LiteLLM launcher started (PID: $($proc.Id))"',
812
+ ` Write-Host ${q(` Logs: ${options.stdoutPath}`)}`,
813
+ ` Write-Host ${q(` Errors: ${options.stderrPath}`)}`,
814
+ ' } catch {',
815
+ ' Write-Host "[ERROR] Failed to start LiteLLM launcher." -ForegroundColor Red',
816
+ ' Write-Host $_.Exception.Message -ForegroundColor Red',
817
+ ' }',
818
+ '}',
819
+ ];
820
+ }
821
+ buildUnixSpotlightLifecycleCommand(options) {
822
+ const q = (value) => this.quoteBash(value);
823
+ const lines = [
824
+ 'set +e',
825
+ `export AGENT_HOME_DIR=${q(options.agentHomeDir)}`,
826
+ `mkdir -p ${q(path.dirname(options.stdoutPath))}`,
827
+ `echo ${q(this.getLifecycleTerminalIntro(options.action))}`,
828
+ ];
829
+ if (options.action === 'stop' || options.action === 'restart') {
830
+ lines.push('echo ""', 'echo "Stopping LiteLLM proxy..."', ...this.buildUnixLiteLLMStopCommands(options.litellmScript, q));
831
+ }
832
+ if (options.action === 'stop') {
833
+ lines.push('echo ""', 'echo "Stopping OTEL Collector..."', `${q(options.startScript)} --stop`);
834
+ }
835
+ else if (options.action === 'restart') {
836
+ lines.push('echo ""', 'echo "Restarting OTEL Collector..."', `${q(options.startScript)} --stop`, 'sleep 1', `${q(options.startScript)} --force-daemon`);
837
+ }
838
+ else {
839
+ lines.push('echo ""', 'echo "Starting OTEL Collector..."', `${q(options.startScript)} --force-daemon`);
840
+ }
841
+ if (options.action === 'start' || options.action === 'restart') {
842
+ lines.push('echo ""', ...this.buildUnixLiteLLMStartCommands(options, q));
843
+ }
844
+ lines.push('echo ""', 'echo "Press any key to close..."', 'read -n 1');
845
+ return lines.join('\n');
846
+ }
847
+ buildUnixLiteLLMStopCommands(litellmScript, q) {
848
+ if (!litellmScript) {
849
+ return ['echo "[WARN] LiteLLM launcher script not found. Skipping LiteLLM stop." >&2'];
850
+ }
851
+ return [`${q(litellmScript)} --stop`];
852
+ }
853
+ buildUnixLiteLLMStartCommands(options, q) {
854
+ if (!options.litellmScript) {
855
+ return ['echo "[WARN] LiteLLM launcher script not found. Skipping LiteLLM start." >&2'];
856
+ }
857
+ return [
858
+ 'echo "Starting LiteLLM proxy..."',
859
+ `if [ ! -f ${q(options.configPath)} ]; then`,
860
+ ` echo ${q(`[WARN] LiteLLM config not found: ${options.configPath}`)} >&2`,
861
+ 'else',
862
+ ` export LITELLM_CONFIG_PATH=${q(options.configPath)}`,
863
+ ` nohup ${q(options.litellmScript)} --config ${q(options.configPath)} >> ${q(options.stdoutPath)} 2>> ${q(options.stderrPath)} &`,
864
+ ' echo "[OK] LiteLLM launcher started (PID: $!)"',
865
+ ` echo ${q(` Logs: ${options.stdoutPath}`)}`,
866
+ ` echo ${q(` Errors: ${options.stderrPath}`)}`,
867
+ 'fi',
868
+ ];
869
+ }
870
+ getLifecycleTerminalIntro(action) {
871
+ switch (action) {
872
+ case 'start':
873
+ return 'Starting Spotlight (OTEL Collector + LiteLLM)...';
874
+ case 'stop':
875
+ return 'Stopping Spotlight (LiteLLM + OTEL Collector)...';
876
+ case 'restart':
877
+ return 'Restarting Spotlight (LiteLLM + OTEL Collector)...';
878
+ }
879
+ }
880
+ quoteBash(value) {
881
+ return `'${value.replace(/'/g, '\'\\\'\'')}'`;
882
+ }
883
+ /**
884
+ * Stop LiteLLM by invoking the launcher script with --stop / -Stop.
885
+ * The script reads the canonical PID file and handles winpid/taskkill on Windows.
886
+ */
887
+ async stopLiteLLMDirectly() {
888
+ const isWindows = process.platform === 'win32';
889
+ const args = isWindows ? ['-Stop'] : ['--stop'];
890
+ return this.runLauncher(args, { detached: false });
891
+ }
892
+ /**
893
+ * Start LiteLLM in a detached background process. Logs go to .agent-hippo/analytics/litellm.{log,error.log}.
894
+ */
895
+ async startLiteLLMDirectly() {
896
+ const configPath = path.join((0, index_1.getAgentideHome)(), 'litellm-otel.yaml');
897
+ try {
898
+ await fs_1.promises.access(configPath);
899
+ }
900
+ catch {
901
+ return false;
902
+ }
903
+ const isWindows = process.platform === 'win32';
904
+ const args = isWindows
905
+ ? ['-ConfigPath', configPath]
906
+ : ['--config', configPath];
907
+ return this.runLauncher(args, { detached: true, configPath });
908
+ }
909
+ /**
910
+ * Spawn the agentide-litellm launcher with the given args.
911
+ * `detached: true` returns immediately and pipes child stdout/stderr to log files.
912
+ * `detached: false` resolves when the process exits (used for --stop).
913
+ */
914
+ async runLauncher(args, opts) {
915
+ const scriptPath = await this.findLiteLLMScript();
916
+ if (!scriptPath) {
917
+ return false;
918
+ }
919
+ const isWindows = process.platform === 'win32';
920
+ const shellPath = isWindows ? getWindowsPwshOrPowerShell() : '/bin/bash';
921
+ const shellArgs = isWindows
922
+ ? ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', scriptPath, ...args]
923
+ : [scriptPath, ...args];
924
+ const env = { ...process.env, AGENT_HOME_DIR: (0, index_1.getAgentideHome)() };
925
+ if (opts.configPath) {
926
+ env.LITELLM_CONFIG_PATH = opts.configPath;
927
+ }
928
+ if (isWindows && opts.detached) {
929
+ return this.startLiteLLMViaHiddenWindowsProcess(scriptPath, args, env);
930
+ }
931
+ if (opts.detached) {
932
+ // Open log files synchronously so spawn can dup the fds before we close them.
933
+ const analyticsDir = path.join((0, index_1.getAgentideHome)(), 'analytics');
934
+ fsSync.mkdirSync(analyticsDir, { recursive: true });
935
+ const stdoutFd = fsSync.openSync(path.join(analyticsDir, 'litellm.log'), 'a');
936
+ const stderrFd = fsSync.openSync(path.join(analyticsDir, 'litellm.error.log'), 'a');
937
+ try {
938
+ const child = (0, child_process_1.spawn)(shellPath, shellArgs, {
939
+ detached: true,
940
+ stdio: ['ignore', stdoutFd, stderrFd],
941
+ windowsHide: true,
942
+ env,
943
+ cwd: path.dirname(scriptPath),
944
+ });
945
+ child.unref();
946
+ this.log(`LiteLLM launcher started (PID: ${child.pid})`);
947
+ return true;
948
+ }
949
+ catch (error) {
950
+ this.log(`Failed to start LiteLLM: ${error}`);
951
+ return false;
952
+ }
953
+ finally {
954
+ fsSync.closeSync(stdoutFd);
955
+ fsSync.closeSync(stderrFd);
956
+ }
957
+ }
958
+ return new Promise((resolve) => {
959
+ const child = (0, child_process_1.spawn)(shellPath, shellArgs, {
960
+ windowsHide: true,
961
+ env,
962
+ cwd: path.dirname(scriptPath),
963
+ });
964
+ child.once('error', (err) => {
965
+ this.log(`LiteLLM launcher failed to spawn: ${err}`);
966
+ resolve(false);
967
+ });
968
+ child.once('exit', (code) => resolve(code === 0));
969
+ });
970
+ }
971
+ async startLiteLLMViaHiddenWindowsProcess(scriptPath, args, env) {
972
+ const analyticsDir = path.join((0, index_1.getAgentideHome)(), 'analytics');
973
+ fsSync.mkdirSync(analyticsDir, { recursive: true });
974
+ const stdoutPath = path.join(analyticsDir, 'litellm.log');
975
+ const stderrPath = path.join(analyticsDir, 'litellm.error.log');
976
+ const launcherArgumentLine = (0, windowsCommandLine_1.buildWindowsArgumentLine)([
977
+ '-NoProfile',
978
+ '-NoLogo',
979
+ '-ExecutionPolicy',
980
+ 'Bypass',
981
+ '-File',
982
+ scriptPath,
983
+ ...args,
984
+ ]);
985
+ const psCommand = [
986
+ `$env:AGENT_HOME_DIR = '${this.escapePowerShellSingleQuotedString(env.AGENT_HOME_DIR ?? (0, index_1.getAgentideHome)())}'`,
987
+ env.LITELLM_CONFIG_PATH
988
+ ? `$env:LITELLM_CONFIG_PATH = '${this.escapePowerShellSingleQuotedString(env.LITELLM_CONFIG_PATH)}'`
989
+ : '',
990
+ `$proc = Start-Process -FilePath '${this.escapePowerShellSingleQuotedString(getWindowsPwshOrPowerShell())}' -WindowStyle Hidden -WorkingDirectory '${this.escapePowerShellSingleQuotedString(path.dirname(scriptPath))}' -ArgumentList '${this.escapePowerShellSingleQuotedString(launcherArgumentLine)}' -RedirectStandardOutput '${this.escapePowerShellSingleQuotedString(stdoutPath)}' -RedirectStandardError '${this.escapePowerShellSingleQuotedString(stderrPath)}' -PassThru`,
991
+ 'Write-Output $proc.Id',
992
+ ].filter(Boolean).join('; ');
993
+ return new Promise((resolve) => {
994
+ let stdout = '';
995
+ let stderr = '';
996
+ const child = (0, child_process_1.spawn)(getWindowsPwshOrPowerShell(), [
997
+ '-NoProfile',
998
+ '-ExecutionPolicy',
999
+ 'Bypass',
1000
+ '-Command',
1001
+ psCommand,
1002
+ ], {
1003
+ windowsHide: true,
1004
+ env,
1005
+ cwd: path.dirname(scriptPath),
1006
+ });
1007
+ child.stdout.on('data', data => {
1008
+ stdout += data.toString();
1009
+ });
1010
+ child.stderr.on('data', data => {
1011
+ stderr += data.toString();
1012
+ });
1013
+ child.once('error', (err) => {
1014
+ this.log(`LiteLLM launcher failed to spawn hidden Windows process: ${err}`);
1015
+ resolve(false);
1016
+ });
1017
+ child.once('exit', (code) => {
1018
+ if (code !== 0) {
1019
+ const detail = stderr.trim() || stdout.trim();
1020
+ this.log(`LiteLLM hidden Windows launcher exited with code ${code}${detail ? `: ${detail}` : ''}`);
1021
+ resolve(false);
1022
+ return;
1023
+ }
1024
+ const startedPid = parseInt(stdout.trim(), 10);
1025
+ if (!Number.isNaN(startedPid)) {
1026
+ this.log(`LiteLLM hidden Windows process started (PID: ${startedPid})`);
1027
+ }
1028
+ resolve(true);
1029
+ });
1030
+ });
1031
+ }
1032
+ escapePowerShellSingleQuotedString(value) {
1033
+ return value.replace(/'/g, '\'\'');
1034
+ }
1035
+ async findLiteLLMScript() {
1036
+ const extensionPath = this.extensionContext.extensionPath;
1037
+ const isWindows = process.platform === 'win32';
1038
+ const scriptName = isWindows ? 'agentide-litellm.ps1' : 'agentide-litellm.sh';
1039
+ const candidates = [
1040
+ path.join(extensionPath, 'out', 'scripts', scriptName),
1041
+ path.join(extensionPath, 'scripts', scriptName),
1042
+ path.join(extensionPath, '..', '..', 'scripts', scriptName),
1043
+ ];
1044
+ for (const candidate of candidates) {
1045
+ try {
1046
+ await fs_1.promises.access(candidate);
1047
+ return candidate;
1048
+ }
1049
+ catch {
1050
+ // ignore
1051
+ }
1052
+ }
1053
+ return null;
1054
+ }
1055
+ /**
1056
+ * Run DuckDB re-indexing from trace JSONL (dashboard).
1057
+ */
1058
+ async triggerIndexing() {
1059
+ if (!this.indexingService) {
1060
+ vscode.window.showWarningMessage(`${branding_1.AGENTIDE_BRAND_NAME}: Indexing service is not available.`);
1061
+ return;
1062
+ }
1063
+ if (this.indexingService.isIndexing()) {
1064
+ vscode.window.showInformationMessage(`${branding_1.AGENTIDE_BRAND_NAME}: Indexing is already in progress.`);
1065
+ return;
1066
+ }
1067
+ this.indexingService.scheduleIndexing(true);
1068
+ vscode.window.showInformationMessage(`${branding_1.AGENTIDE_BRAND_NAME}: Triggered indexing.`);
1069
+ }
1070
+ /**
1071
+ * Show analytics status in a notification.
1072
+ */
1073
+ async showStatus() {
1074
+ const stackStatus = await this.getStackStatus();
1075
+ const litellmBaseUrl = vscode.workspace
1076
+ .getConfiguration('agentide.providers.litellm')
1077
+ .get('baseUrl')
1078
+ ?.trim();
1079
+ // Build status lines
1080
+ // allow-any-unicode-next-line
1081
+ const otelStatus = stackStatus.otelRunning ? '🟢 127.0.0.1:4318' : '⚫ Not running';
1082
+ let litellmStatus;
1083
+ if (stackStatus.litellmRunning && litellmBaseUrl) {
1084
+ // allow-any-unicode-next-line
1085
+ litellmStatus = `🟢 ${litellmBaseUrl}`;
1086
+ }
1087
+ else if (stackStatus.litellmRunning) {
1088
+ // allow-any-unicode-next-line
1089
+ litellmStatus = '🟢 Set URL in Settings or Stop External LiteLLM';
1090
+ }
1091
+ else {
1092
+ // allow-any-unicode-next-line
1093
+ litellmStatus = '⚫ Not running';
1094
+ }
1095
+ const message = [
1096
+ `LiteLLM: ${litellmStatus}`,
1097
+ `OTEL: ${otelStatus}`,
1098
+ ].join('\n\n');
1099
+ const lifecycleAction = (0, lifecycle_1.getSpotlightLifecycleAction)(stackStatus);
1100
+ const installAction = (0, lifecycle_1.getSpotlightInstallAction)(await this.isAnalyticsConfigured());
1101
+ const action = await vscode.window.showInformationMessage(`${message}`, 'Config', installAction, lifecycleAction);
1102
+ switch (action) {
1103
+ case 'Start':
1104
+ await this.start();
1105
+ break;
1106
+ case 'Stop':
1107
+ await this.stop();
1108
+ break;
1109
+ case 'Config':
1110
+ await this.openLiteLLMConfig();
1111
+ break;
1112
+ case 'Restart All':
1113
+ await this.restart();
1114
+ break;
1115
+ case 'Install':
1116
+ if (process.platform === 'win32') {
1117
+ await this.setupWindowsSpotlight({ reinstall: false });
1118
+ }
1119
+ else {
1120
+ await vscode.commands.executeCommand('agentide.setupAnalytics');
1121
+ }
1122
+ break;
1123
+ case 'Reinstall':
1124
+ if (process.platform === 'win32') {
1125
+ await this.setupWindowsSpotlight({ reinstall: true });
1126
+ }
1127
+ else {
1128
+ await vscode.commands.executeCommand('agentide.setupAnalytics');
1129
+ }
1130
+ break;
1131
+ }
1132
+ }
1133
+ async openLiteLLMConfig() {
1134
+ const configPath = path.join((0, index_1.getAgentideHome)(), 'litellm-otel.yaml');
1135
+ try {
1136
+ await fs_1.promises.access(configPath);
1137
+ }
1138
+ catch {
1139
+ const choice = await vscode.window.showWarningMessage(`${branding_1.AGENTIDE_BRAND_NAME}: LiteLLM OTEL config not found.`, 'Install');
1140
+ if (choice === 'Install') {
1141
+ await vscode.commands.executeCommand('agentide.setupAnalytics');
1142
+ }
1143
+ return;
1144
+ }
1145
+ const doc = await vscode.workspace.openTextDocument(configPath);
1146
+ await vscode.window.showTextDocument(doc);
1147
+ }
1148
+ /**
1149
+ * Open a terminal with analytics query commands.
1150
+ * Shows the latest session info by default.
1151
+ */
1152
+ async openQueryTerminal() {
1153
+ const scriptPath = await this.findScript('query-analytics.sh');
1154
+ if (!scriptPath) {
1155
+ vscode.window.showErrorMessage(`${branding_1.AGENTIDE_BRAND_NAME}: Query script not found. Run 'Setup Analytics' first.`);
1156
+ return;
1157
+ }
1158
+ // Show latest session info by default - includes chat history and costs
1159
+ // Keep terminal open so user can see the output
1160
+ const terminal = this.createScriptTerminal('Spotlight Query', scriptPath, '--latest-session', true);
1161
+ terminal.show();
1162
+ }
1163
+ /**
1164
+ * Find a script in the extension bundle or source directory.
1165
+ */
1166
+ async findScript(scriptName) {
1167
+ const extensionPath = this.extensionContext.extensionPath;
1168
+ // Try bundled location first
1169
+ const bundledPath = path.join(extensionPath, 'out', 'scripts', 'analytics', scriptName);
1170
+ try {
1171
+ await fs_1.promises.access(bundledPath);
1172
+ return bundledPath;
1173
+ }
1174
+ catch {
1175
+ // Not in bundled location
1176
+ }
1177
+ // Try development location
1178
+ const devPath = path.join(extensionPath, 'scripts', 'analytics', scriptName);
1179
+ try {
1180
+ await fs_1.promises.access(devPath);
1181
+ return devPath;
1182
+ }
1183
+ catch {
1184
+ // Not in dev location
1185
+ }
1186
+ return null;
1187
+ }
1188
+ /**
1189
+ * Update the status bar item.
1190
+ */
1191
+ updateStatusBar(status) {
1192
+ this._status = status;
1193
+ let tooltip;
1194
+ // Use different icons and colors based on status
1195
+ switch (status) {
1196
+ case 'running':
1197
+ this.statusBarItem.text = '$(pulse) Spotlight';
1198
+ tooltip = 'Spotlight: Running (OTEL + LiteLLM configured)';
1199
+ this.statusBarItem.color = new vscode.ThemeColor('testing.iconPassed'); // Green
1200
+ this.statusBarItem.backgroundColor = undefined;
1201
+ break;
1202
+ case 'partial':
1203
+ this.statusBarItem.text = '$(pulse) Spotlight';
1204
+ tooltip = 'Spotlight: Partial (click to configure)';
1205
+ this.statusBarItem.color = new vscode.ThemeColor('editorWarning.foreground'); // Yellow
1206
+ this.statusBarItem.backgroundColor = undefined;
1207
+ break;
1208
+ case 'stopped':
1209
+ this.statusBarItem.text = '$(pulse) Spotlight';
1210
+ tooltip = 'Spotlight: Stopped (click to start)';
1211
+ this.statusBarItem.color = undefined;
1212
+ this.statusBarItem.backgroundColor = undefined;
1213
+ break;
1214
+ case 'checking':
1215
+ this.statusBarItem.text = '$(sync~spin) Spotlight';
1216
+ tooltip = 'Spotlight: Checking...';
1217
+ this.statusBarItem.color = undefined;
1218
+ this.statusBarItem.backgroundColor = undefined;
1219
+ break;
1220
+ case 'error':
1221
+ this.statusBarItem.text = '$(warning) Spotlight';
1222
+ tooltip = 'Spotlight: Error (click to retry)';
1223
+ this.statusBarItem.color = new vscode.ThemeColor('errorForeground');
1224
+ this.statusBarItem.backgroundColor = undefined;
1225
+ break;
1226
+ }
1227
+ if (this.indexProgress.status === 'indexing') {
1228
+ tooltip += `\n\nBackground analytics indexing is running (${this.indexProgress.percent}% complete). Charts may use JSONL fallback until indexing finishes.`;
1229
+ }
1230
+ this.statusBarItem.tooltip = tooltip;
1231
+ this.statusBarItem.show();
1232
+ }
1233
+ log(message) {
1234
+ this.outputChannel.appendLine(`[Analytics] ${message}`);
1235
+ }
1236
+ /**
1237
+ * Create a terminal that runs a command directly via shellArgs.
1238
+ * This avoids the sendText character-dropping issue.
1239
+ */
1240
+ createScriptTerminal(name, scriptPath, args, keepOpen = false) {
1241
+ const agentHomeDir = (0, index_1.getAgentideHome)();
1242
+ if (keepOpen) {
1243
+ // Run the script, then drop into an interactive shell
1244
+ // Uses the same shellPath/shellArgs approach as Setup Analytics to avoid sendText issues
1245
+ // Echo the command first so user can see what's running
1246
+ const cmd = `"${scriptPath}" ${args}`;
1247
+ return vscode.window.createTerminal({
1248
+ name,
1249
+ cwd: path.dirname(scriptPath),
1250
+ env: {
1251
+ AGENT_HOME_DIR: agentHomeDir,
1252
+ },
1253
+ shellPath: '/bin/bash',
1254
+ shellArgs: ['-c', `echo '$ ${cmd}'; echo ''; ${cmd}; echo ''; exec bash -l`],
1255
+ });
1256
+ }
1257
+ // For non-keepOpen, use bash -c for a one-shot command
1258
+ return vscode.window.createTerminal({
1259
+ name,
1260
+ cwd: path.dirname(scriptPath),
1261
+ env: {
1262
+ AGENT_HOME_DIR: agentHomeDir,
1263
+ },
1264
+ shellPath: '/bin/bash',
1265
+ shellArgs: ['-c', `"${scriptPath}" ${args}`],
1266
+ });
1267
+ }
1268
+ dispose() {
1269
+ if (this.healthCheckTimer) {
1270
+ clearInterval(this.healthCheckTimer);
1271
+ this.healthCheckTimer = null;
1272
+ }
1273
+ this.statusBarItem.dispose();
1274
+ for (const d of this.disposables) {
1275
+ d.dispose();
1276
+ }
1277
+ }
1278
+ }
1279
+ exports.AnalyticsService = AnalyticsService;