@agenthippo-ai/agenthippo 1.110.9 → 1.110.19

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 (533) hide show
  1. package/out/agentpack/types.js +2 -5
  2. package/out/analytics/dashboard/artifactManager.js +2 -439
  3. package/out/analytics/dashboard/fleetDisplayUtils.js +2 -162
  4. package/out/analytics/dashboard/fleetOrchestrator.js +3 -142
  5. package/out/analytics/dashboard/fleetRegistry.js +2 -79
  6. package/out/analytics/dashboard/fleetRowDefaults.js +2 -87
  7. package/out/analytics/dashboard/fleetScriptAdapter.js +2 -146
  8. package/out/analytics/dashboard/fleetTypes.js +2 -29
  9. package/out/analytics/dashboard/index.js +2 -17
  10. package/out/analytics/dashboard/indexingService.js +2 -422
  11. package/out/analytics/dashboard/localFleetAdapter.js +2 -222
  12. package/out/analytics/dashboard/performanceMonitor.js +5 -76
  13. package/out/analytics/dashboard/processManager.js +2 -209
  14. package/out/analytics/dashboard/provider.js +38 -3817
  15. package/out/analytics/dashboard/queryRunner.js +62 -750
  16. package/out/analytics/dashboard/scheduledFleetStorage.js +2 -241
  17. package/out/analytics/dashboard/sessionJsonlFleet.js +3 -204
  18. package/out/analytics/dashboard/teamViewDiscovery.js +2 -106
  19. package/out/analytics/dashboard/webview/panel.js +34 -2318
  20. package/out/analytics/dashboard/webview/runtime-bridge.js +2 -82
  21. package/out/analytics/lifecycle.js +2 -43
  22. package/out/analytics/service.js +8 -1277
  23. package/out/auth/authBaseUrl.js +2 -59
  24. package/out/auth/bootstrapApply.js +2 -71
  25. package/out/auth/brokerClient.js +2 -160
  26. package/out/auth/callbackUri.js +2 -59
  27. package/out/auth/githubStoreGate.js +2 -70
  28. package/out/auth/loopbackAuthServer.js +4 -159
  29. package/out/auth/onboardingPrompt.js +2 -112
  30. package/out/auth/pkce.js +2 -9
  31. package/out/auth/provider.js +2 -226
  32. package/out/auth/sessionStore.js +2 -156
  33. package/out/auth/signInFlow.js +2 -183
  34. package/out/cli/index.js +619 -551
  35. package/out/cli/run-custom-engine-runner.js +3 -318
  36. package/out/cli/vscode-shim.js +2 -86
  37. package/out/engines/factory.js +2 -45
  38. package/out/engines/types.js +2 -17
  39. package/out/examples/run-headless-repl.js +6 -286
  40. package/out/examples/run-headless.js +2 -187
  41. package/out/extension.js +32 -4473
  42. package/out/gateway/gatewayRouteIndex.js +6 -371
  43. package/out/gateway/gatewaySessionStore.js +3 -243
  44. package/out/gateway/index.js +2 -31
  45. package/out/gateway/resetMappings.js +2 -52
  46. package/out/gateway/service.js +5 -1249
  47. package/out/mcp/publish.js +2 -143
  48. package/out/remote/handleRemoteChat.js +2 -169
  49. package/out/remote/remotePackStatusBar.js +3 -103
  50. package/out/remote/remoteTrust.js +6 -277
  51. package/out/remote/serveClient.js +4 -277
  52. package/out/remoteSkills.js +3 -191
  53. package/out/runtime/index.js +2 -32
  54. package/out/runtime/vscode/index.js +2 -20
  55. package/out/runtime/vscode/vscode-config-provider.js +2 -77
  56. package/out/runtime/vscode/vscode-edit-tracker.js +2 -122
  57. package/out/runtime/vscode/vscode-logger.js +2 -30
  58. package/out/runtime/vscode/vscode-permission-handler.js +2 -72
  59. package/out/scripts/agentide-litellm.sh +0 -1
  60. package/out/scripts/agentide_litellm_hooks_v1.py +170 -418
  61. package/out/scripts/analytics/agent-fleet-widget.js +18 -257
  62. package/out/scripts/analytics/agentide-litellm-otel.config.yaml +4 -4
  63. package/out/scripts/analytics/duckdbLocator.js +2 -28
  64. package/out/scripts/analytics/generate-default-charts.py +43 -323
  65. package/out/scripts/analytics/hotspot-analysis-widget.js +4 -430
  66. package/out/scripts/analytics/index-traces.py +78 -1036
  67. package/out/scripts/analytics/session-comparison-widget.js +26 -472
  68. package/out/scripts/analytics/session-timeline-widget.js +25 -846
  69. package/out/scripts/analytics/setup-analytics.ps1 +8 -1
  70. package/out/scripts/analytics/setup-analytics.sh +13 -2
  71. package/out/scripts/analytics/token-cost-flamegraph-widget.js +4 -461
  72. package/out/scripts/analytics/token-cost-trend-widget.js +4 -534
  73. package/out/scripts/analytics/workflows-collector.cjs +4 -314
  74. package/out/scripts/analytics/workflows-daemon.mjs +9 -185
  75. package/out/scripts/analytics/workflows-widget.cjs +15 -159
  76. package/out/scripts/analytics/wow-model-widget.js +10 -120
  77. package/out/scripts/vendor-tools.mjs +2 -233
  78. package/out/skills/publish.js +3 -178
  79. package/out/store/github/setup.js +7 -212
  80. package/out/store/oramaIndex.js +2 -884
  81. package/out/sync.js +26 -1829
  82. package/out/terminalLogger.js +5 -358
  83. package/out/utils/pathSafety.js +2 -60
  84. package/out/utils/pythonRunner.js +4 -258
  85. package/out/utils/toolPath.js +2 -83
  86. package/out/workspaceFolders.js +2 -59
  87. package/package.json +1 -1
  88. package/out/agentpack/github.js +0 -547
  89. package/out/agentpack/index.js +0 -67
  90. package/out/agentpack/install.js +0 -297
  91. package/out/agentpack/manager.js +0 -441
  92. package/out/agentpack/manifest.js +0 -135
  93. package/out/agentpack/paths.js +0 -498
  94. package/out/agentpack/publish.js +0 -248
  95. package/out/agentpack/stores.js +0 -554
  96. package/out/analytics/dashboard/fleetStatusUtils.js +0 -30
  97. package/out/analytics/dashboard/fleetTitleUtils.js +0 -68
  98. package/out/analytics/dashboard/refreshPolicy.js +0 -16
  99. package/out/analytics/dashboard/scheduledFleetFingerprint.js +0 -22
  100. package/out/analytics/dashboard/scheduledFleetUtils.js +0 -22
  101. package/out/analytics/dashboard/sessionEventFleetStats.js +0 -118
  102. package/out/analytics/dashboard/viewsConfigMerge.js +0 -221
  103. package/out/analytics/dashboard/webview/codicon.ttf +0 -0
  104. package/out/analytics/identity.js +0 -0
  105. package/out/analytics/sessionEvents.js +0 -323
  106. package/out/auth/callbackUriParse.js +0 -59
  107. package/out/auth/types.js +0 -12
  108. package/out/auth-broker/config.js +0 -112
  109. package/out/auth-broker/jwt.js +0 -105
  110. package/out/auth-broker/pkce.js +0 -59
  111. package/out/auth-broker/server.js +0 -677
  112. package/out/auth-broker/store.js +0 -275
  113. package/out/authority/warrant.js +0 -206
  114. package/out/base-prompts/mcp-servers/.mcp.json +0 -13
  115. package/out/base-prompts/mcp-servers/langfuse-analytics/README.md +0 -142
  116. package/out/base-prompts/mcp-servers/langfuse-analytics/mcp.json +0 -13
  117. package/out/base-prompts/mcp-servers/langfuse-analytics/package-lock.json +0 -1192
  118. package/out/base-prompts/mcp-servers/langfuse-analytics/package.json +0 -23
  119. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/run-with-env.sh +0 -12
  120. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/sdk-test.js +0 -102
  121. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/simple-test.js +0 -137
  122. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/test-client.js +0 -118
  123. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/test-server.js +0 -209
  124. package/out/base-prompts/mcp-servers/langfuse-analytics/src/client.ts +0 -431
  125. package/out/base-prompts/mcp-servers/langfuse-analytics/src/index.ts +0 -270
  126. package/out/base-prompts/mcp-servers/langfuse-analytics/tsconfig.json +0 -18
  127. package/out/base-prompts/rules/AGENTS.md +0 -204
  128. package/out/base-prompts/skills/agent-browser/SKILL.md +0 -102
  129. package/out/base-prompts/skills/agent-builder/SKILL.md +0 -73
  130. package/out/base-prompts/skills/agent-builder/references/agent-pack.md +0 -63
  131. package/out/base-prompts/skills/agent-builder/references/crewai.md +0 -66
  132. package/out/base-prompts/skills/agent-builder/references/langchain.md +0 -60
  133. package/out/base-prompts/skills/agent-builder/references/raw-sdk.md +0 -73
  134. package/out/base-prompts/skills/agent-engine-creator/SKILL.md +0 -586
  135. package/out/base-prompts/skills/agent-engine-installer/SKILL.md +0 -106
  136. package/out/base-prompts/skills/agent-engine-installer/scripts/install-engine.mjs +0 -259
  137. package/out/base-prompts/skills/agent-engine-installer/scripts/install-engine.ps1 +0 -189
  138. package/out/base-prompts/skills/agenthippo-cli/SKILL.md +0 -69
  139. package/out/base-prompts/skills/agenthippo-cli/scripts/install.sh +0 -63
  140. package/out/base-prompts/skills/agentpack-creator/SKILL.md +0 -375
  141. package/out/base-prompts/skills/agentpack-creator/references/agent-templates.md +0 -261
  142. package/out/base-prompts/skills/agentpack-creator/references/agents-md-guide.md +0 -195
  143. package/out/base-prompts/skills/agentpack-creator/scripts/init_pack.py +0 -391
  144. package/out/base-prompts/skills/agentpack-creator/scripts/init_pack_test.py +0 -294
  145. package/out/base-prompts/skills/agentpack-testbench/SKILL.md +0 -135
  146. package/out/base-prompts/skills/algorithmic-art/LICENSE.txt +0 -202
  147. package/out/base-prompts/skills/algorithmic-art/SKILL.md +0 -405
  148. package/out/base-prompts/skills/algorithmic-art/templates/generator_template.js +0 -223
  149. package/out/base-prompts/skills/algorithmic-art/templates/viewer.html +0 -599
  150. package/out/base-prompts/skills/debug-agent/SKILL.md +0 -83
  151. package/out/base-prompts/skills/desktop-automation/SKILL.md +0 -166
  152. package/out/base-prompts/skills/desktop-automation/references/agenthippo-ui-recipes.md +0 -441
  153. package/out/base-prompts/skills/desktop-automation/scripts/windows-desktop-uia.psm1 +0 -280
  154. package/out/base-prompts/skills/docx/LICENSE.txt +0 -30
  155. package/out/base-prompts/skills/docx/SKILL.md +0 -197
  156. package/out/base-prompts/skills/docx/docx-js.md +0 -350
  157. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  158. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  159. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  160. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  161. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  162. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  163. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  164. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  165. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  166. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  167. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  168. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  169. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  170. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  171. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  172. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  173. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  174. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  175. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  176. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  177. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  178. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  179. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  180. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  181. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  182. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  183. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  184. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  185. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  186. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  187. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  188. package/out/base-prompts/skills/docx/ooxml/schemas/mce/mc.xsd +0 -75
  189. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  190. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  191. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  192. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  193. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  194. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  195. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  196. package/out/base-prompts/skills/docx/ooxml/scripts/pack.py +0 -159
  197. package/out/base-prompts/skills/docx/ooxml/scripts/unpack.py +0 -29
  198. package/out/base-prompts/skills/docx/ooxml/scripts/validate.py +0 -69
  199. package/out/base-prompts/skills/docx/ooxml/scripts/validation/__init__.py +0 -15
  200. package/out/base-prompts/skills/docx/ooxml/scripts/validation/base.py +0 -951
  201. package/out/base-prompts/skills/docx/ooxml/scripts/validation/docx.py +0 -274
  202. package/out/base-prompts/skills/docx/ooxml/scripts/validation/pptx.py +0 -315
  203. package/out/base-prompts/skills/docx/ooxml/scripts/validation/redlining.py +0 -279
  204. package/out/base-prompts/skills/docx/ooxml.md +0 -610
  205. package/out/base-prompts/skills/docx/scripts/__init__.py +0 -1
  206. package/out/base-prompts/skills/docx/scripts/document.py +0 -1276
  207. package/out/base-prompts/skills/docx/scripts/templates/comments.xml +0 -3
  208. package/out/base-prompts/skills/docx/scripts/templates/commentsExtended.xml +0 -3
  209. package/out/base-prompts/skills/docx/scripts/templates/commentsExtensible.xml +0 -3
  210. package/out/base-prompts/skills/docx/scripts/templates/commentsIds.xml +0 -3
  211. package/out/base-prompts/skills/docx/scripts/templates/people.xml +0 -3
  212. package/out/base-prompts/skills/docx/scripts/utilities.py +0 -374
  213. package/out/base-prompts/skills/gateway-outbound/SKILL.md +0 -136
  214. package/out/base-prompts/skills/mcp-builder/LICENSE.txt +0 -202
  215. package/out/base-prompts/skills/mcp-builder/SKILL.md +0 -328
  216. package/out/base-prompts/skills/mcp-builder/reference/evaluation.md +0 -602
  217. package/out/base-prompts/skills/mcp-builder/reference/mcp_best_practices.md +0 -249
  218. package/out/base-prompts/skills/mcp-builder/reference/node_mcp_server.md +0 -970
  219. package/out/base-prompts/skills/mcp-builder/reference/python_mcp_server.md +0 -719
  220. package/out/base-prompts/skills/mcp-builder/scripts/connections.py +0 -151
  221. package/out/base-prompts/skills/mcp-builder/scripts/evaluation.py +0 -373
  222. package/out/base-prompts/skills/mcp-builder/scripts/example_evaluation.xml +0 -22
  223. package/out/base-prompts/skills/mcp-builder/scripts/requirements.txt +0 -2
  224. package/out/base-prompts/skills/openclaw/SKILL.md +0 -406
  225. package/out/base-prompts/skills/openclaw/scripts/run-smoke.sh +0 -61
  226. package/out/base-prompts/skills/pdf/LICENSE.txt +0 -30
  227. package/out/base-prompts/skills/pdf/SKILL.md +0 -294
  228. package/out/base-prompts/skills/pdf/forms.md +0 -205
  229. package/out/base-prompts/skills/pdf/reference.md +0 -612
  230. package/out/base-prompts/skills/pdf/scripts/check_bounding_boxes.py +0 -70
  231. package/out/base-prompts/skills/pdf/scripts/check_bounding_boxes_test.py +0 -226
  232. package/out/base-prompts/skills/pdf/scripts/check_fillable_fields.py +0 -12
  233. package/out/base-prompts/skills/pdf/scripts/convert_pdf_to_images.py +0 -35
  234. package/out/base-prompts/skills/pdf/scripts/create_validation_image.py +0 -41
  235. package/out/base-prompts/skills/pdf/scripts/extract_form_field_info.py +0 -152
  236. package/out/base-prompts/skills/pdf/scripts/fill_fillable_fields.py +0 -114
  237. package/out/base-prompts/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -108
  238. package/out/base-prompts/skills/pptx/LICENSE.txt +0 -30
  239. package/out/base-prompts/skills/pptx/SKILL.md +0 -484
  240. package/out/base-prompts/skills/pptx/html2pptx.md +0 -625
  241. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  242. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  243. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  244. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  245. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  246. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  247. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  248. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  249. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  250. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  251. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  252. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  253. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  254. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  255. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  256. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  257. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  258. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  259. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  260. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  261. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  262. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  263. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  264. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  265. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  266. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  267. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  268. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  269. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  270. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  271. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  272. package/out/base-prompts/skills/pptx/ooxml/schemas/mce/mc.xsd +0 -75
  273. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  274. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  275. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  276. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  277. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  278. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  279. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  280. package/out/base-prompts/skills/pptx/ooxml/scripts/pack.py +0 -159
  281. package/out/base-prompts/skills/pptx/ooxml/scripts/unpack.py +0 -29
  282. package/out/base-prompts/skills/pptx/ooxml/scripts/validate.py +0 -69
  283. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/__init__.py +0 -15
  284. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/base.py +0 -951
  285. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/docx.py +0 -274
  286. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/pptx.py +0 -315
  287. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/redlining.py +0 -279
  288. package/out/base-prompts/skills/pptx/ooxml.md +0 -427
  289. package/out/base-prompts/skills/pptx/scripts/html2pptx.js +0 -984
  290. package/out/base-prompts/skills/pptx/scripts/inventory.py +0 -1020
  291. package/out/base-prompts/skills/pptx/scripts/rearrange.py +0 -231
  292. package/out/base-prompts/skills/pptx/scripts/replace.py +0 -385
  293. package/out/base-prompts/skills/pptx/scripts/thumbnail.py +0 -450
  294. package/out/base-prompts/skills/prompt-lab/SKILL.md +0 -149
  295. package/out/base-prompts/skills/prompt-lab/scripts/query-analytics.sh +0 -2551
  296. package/out/base-prompts/skills/skill-creator/LICENSE.txt +0 -202
  297. package/out/base-prompts/skills/skill-creator/SKILL.md +0 -371
  298. package/out/base-prompts/skills/skill-creator/references/output-patterns.md +0 -82
  299. package/out/base-prompts/skills/skill-creator/references/workflows.md +0 -28
  300. package/out/base-prompts/skills/skill-creator/scripts/init_skill.py +0 -303
  301. package/out/base-prompts/skills/skill-creator/scripts/package_skill.py +0 -110
  302. package/out/base-prompts/skills/skill-creator/scripts/quick_validate.py +0 -95
  303. package/out/base-prompts/skills/skill-installer/SKILL.md +0 -251
  304. package/out/base-prompts/skills/skill-installer/references/store-api.md +0 -219
  305. package/out/base-prompts/skills/spotlight-dashboard/SKILL.md +0 -83
  306. package/out/base-prompts/skills/spotlight-insights/SKILL.md +0 -101
  307. package/out/base-prompts/skills/spotlight-optimize/SKILL.md +0 -93
  308. package/out/base-prompts/skills/spotlight-optimize/scripts/query-analytics.sh +0 -2551
  309. package/out/base-prompts/skills/spotlight-query/SKILL.md +0 -314
  310. package/out/base-prompts/skills/spotlight-query/references/otel-schema.md +0 -163
  311. package/out/base-prompts/skills/spotlight-query/scripts/query-analytics.sh +0 -2551
  312. package/out/base-prompts/skills/spotlight-query/scripts/query-analytics.test.sh +0 -744
  313. package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/sessions/sess-test-1.jsonl +0 -14
  314. package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/traces/.duckdb-index.json +0 -7
  315. package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/traces/sample.jsonl +0 -5
  316. package/out/base-prompts/skills/spotlight-report/SKILL.md +0 -86
  317. package/out/base-prompts/skills/spotlight-visualize/SKILL.md +0 -92
  318. package/out/base-prompts/skills/spotlight-visualize/scripts/query-analytics.sh +0 -2551
  319. package/out/base-prompts/skills/xlsx/LICENSE.txt +0 -30
  320. package/out/base-prompts/skills/xlsx/SKILL.md +0 -289
  321. package/out/base-prompts/skills/xlsx/recalc.py +0 -178
  322. package/out/branding.js +0 -49
  323. package/out/cli/commands/anywhere.js +0 -66
  324. package/out/cli/commands/ask.js +0 -246
  325. package/out/cli/commands/auth-broker.js +0 -24
  326. package/out/cli/commands/auth.js +0 -219
  327. package/out/cli/commands/chat.js +0 -357
  328. package/out/cli/commands/conformance.js +0 -249
  329. package/out/cli/commands/data-plane.js +0 -67
  330. package/out/cli/commands/deploy.js +0 -263
  331. package/out/cli/commands/gateway.js +0 -218
  332. package/out/cli/commands/idp.js +0 -85
  333. package/out/cli/commands/pack.js +0 -399
  334. package/out/cli/commands/probe-custom-engine.js +0 -82
  335. package/out/cli/commands/sandbox.js +0 -332
  336. package/out/cli/commands/serve.js +0 -1758
  337. package/out/cli/commands/store.js +0 -927
  338. package/out/cli/credential-context.js +0 -91
  339. package/out/cli/data-plane/broker.js +0 -78
  340. package/out/cli/data-plane/connector-host.js +0 -121
  341. package/out/cli/data-plane/egress.js +0 -189
  342. package/out/cli/data-plane/gateway.js +0 -218
  343. package/out/cli/data-plane/index.js +0 -152
  344. package/out/cli/data-plane/registry.js +0 -89
  345. package/out/cli/data-plane/remote.js +0 -106
  346. package/out/cli/data-plane/sidecar.js +0 -161
  347. package/out/cli/deploy/blueprints/registry.js +0 -84
  348. package/out/cli/deploy/layers/identity.js +0 -172
  349. package/out/cli/deploy-init.js +0 -3023
  350. package/out/cli/deps.js +0 -342
  351. package/out/cli/idp-init.js +0 -338
  352. package/out/cli/pack-install-ref.js +0 -15
  353. package/out/cli/pack-loader.js +0 -418
  354. package/out/cli/pack-runtime.js +0 -61
  355. package/out/cli/runtime.js +0 -450
  356. package/out/cli/serve-hardening.js +0 -607
  357. package/out/cli/state-sync.js +0 -424
  358. package/out/cli/utils.js +0 -231
  359. package/out/engines/base.js +0 -188
  360. package/out/engines/claude.js +0 -1254
  361. package/out/engines/codex.js +0 -862
  362. package/out/engines/custom.js +0 -674
  363. package/out/engines/customEngineIpc.js +0 -95
  364. package/out/engines/customEngineRunnerEmbed.js +0 -107
  365. package/out/engines/customRegistry.js +0 -274
  366. package/out/engines/embeddedCustomEngineRunner.generated.js +0 -9
  367. package/out/engines/engineApiKey.js +0 -138
  368. package/out/engines/install.js +0 -372
  369. package/out/engines/persistentEngineWorker.js +0 -320
  370. package/out/engines/publish.js +0 -341
  371. package/out/evidence/sessionShip.js +0 -610
  372. package/out/gateway/bridge.js +0 -843
  373. package/out/gateway/cli-agent-id.js +0 -36
  374. package/out/gateway/client.js +0 -336
  375. package/out/gateway/client.test.js +0 -395
  376. package/out/gateway/gateway-scope-errors.js +0 -14
  377. package/out/gateway/gatewayBackup.js +0 -76
  378. package/out/gateway/installSource.js +0 -68
  379. package/out/gateway/lifecycle.js +0 -3190
  380. package/out/gateway/openclaw-channel-routing.js +0 -317
  381. package/out/gateway/outboundHandles.js +0 -373
  382. package/out/gateway/outboundPaths.js +0 -75
  383. package/out/gateway/outboundSend.js +0 -254
  384. package/out/gateway/protocol.js +0 -48
  385. package/out/gateway/secretsPreflight.js +0 -90
  386. package/out/gateway/sessionRouting.js +0 -77
  387. package/out/headless/index.js +0 -539
  388. package/out/headless/sync.js +0 -473
  389. package/out/live-e2e/mcp-demo/server.mjs +0 -32
  390. package/out/live-probe/connector.mjs +0 -8
  391. package/out/live-probe/env-report.mjs +0 -8
  392. package/out/mcp.js +0 -654
  393. package/out/pack/caps.js +0 -271
  394. package/out/pack/governor.js +0 -309
  395. package/out/pack/lease-schema.js +0 -270
  396. package/out/pack/lease.js +0 -640
  397. package/out/pack/reconcile.js +0 -217
  398. package/out/pack/signature.js +0 -839
  399. package/out/permissions.js +0 -108
  400. package/out/permissions.mapping.yaml +0 -68
  401. package/out/registry/index.js +0 -332
  402. package/out/runner/host.js +0 -131
  403. package/out/runner/protocol.js +0 -108
  404. package/out/runner/remoteEngine.js +0 -130
  405. package/out/runtime/interfaces/config-provider.js +0 -32
  406. package/out/runtime/interfaces/edit-tracker.js +0 -24
  407. package/out/runtime/interfaces/index.js +0 -29
  408. package/out/runtime/interfaces/logger.js +0 -40
  409. package/out/runtime/interfaces/permission-handler.js +0 -66
  410. package/out/runtime/interfaces/session-store.js +0 -342
  411. package/out/runtime/vscode/vscode-session-store.js +0 -22
  412. package/out/sandbox/containerDriver.js +0 -570
  413. package/out/sandbox/processDriver.js +0 -315
  414. package/out/sandbox/sandboxRunner.js +0 -191
  415. package/out/sandbox/support.js +0 -301
  416. package/out/sandbox/types.js +0 -55
  417. package/out/scripts/analytics/fleet-local-adapter.js +0 -246
  418. package/out/scripts/analytics/live-fleet-4-collector.cjs +0 -315
  419. package/out/scripts/analytics/live-fleet-4-daemon.mjs +0 -134
  420. package/out/scripts/analytics/live-fleet-4-widget.cjs +0 -433
  421. package/out/scripts/gateway/Dockerfile.serve +0 -45
  422. package/out/scripts/gateway/docker-serve.sh +0 -248
  423. package/out/scripts/gateway/setup-gateway-server.ps1 +0 -953
  424. package/out/scripts/gateway/setup-gateway-server.sh +0 -935
  425. package/out/session.js +0 -272
  426. package/out/shared/agentEngines.js +0 -170
  427. package/out/shared/index.js +0 -109
  428. package/out/shared/models.js +0 -136
  429. package/out/shared/providers.js +0 -205
  430. package/out/spotlight/install.js +0 -345
  431. package/out/spotlight/publish.js +0 -544
  432. package/out/spotlight/yaml.js +0 -31
  433. package/out/store/index.js +0 -786
  434. package/out/store/shared.js +0 -241
  435. package/out/test/agentEnvFile.test.js +0 -97
  436. package/out/test/agentYaml.test.js +0 -373
  437. package/out/test/agentpack.test.js +0 -639
  438. package/out/test/analytics-lifecycle.test.js +0 -174
  439. package/out/test/analytics.test.js +0 -756
  440. package/out/test/auth-baseurl.test.js +0 -132
  441. package/out/test/auth-bootstrapApply.test.js +0 -123
  442. package/out/test/auth-broker-hardening.test.js +0 -227
  443. package/out/test/auth-broker.test.js +0 -541
  444. package/out/test/auth-callback.test.js +0 -62
  445. package/out/test/blueprint-registry.test.js +0 -105
  446. package/out/test/branding.test.js +0 -242
  447. package/out/test/caps-governor.test.js +0 -455
  448. package/out/test/cli-agent-id.test.js +0 -55
  449. package/out/test/codex-new-file-survival.test.js +0 -119
  450. package/out/test/configuration-scopes.test.js +0 -131
  451. package/out/test/credential-context.test.js +0 -160
  452. package/out/test/custom-env-layering.test.js +0 -151
  453. package/out/test/customEngineInstall.test.js +0 -100
  454. package/out/test/customRegistry.test.js +0 -122
  455. package/out/test/data-plane-engine-wiring.test.js +0 -250
  456. package/out/test/data-plane.test.js +0 -311
  457. package/out/test/deploy-init.test.js +0 -854
  458. package/out/test/deps-auto-install.test.js +0 -81
  459. package/out/test/egress-broker.test.js +0 -172
  460. package/out/test/engine-integration.test.js +0 -297
  461. package/out/test/enginePaths.test.js +0 -195
  462. package/out/test/enginePublish.test.js +0 -82
  463. package/out/test/fleetDisplayUtils.test.js +0 -100
  464. package/out/test/gateway-client.test.js +0 -409
  465. package/out/test/gateway-install-source.test.js +0 -111
  466. package/out/test/gateway-lifecycle.test.js +0 -608
  467. package/out/test/gateway-outbound.test.js +0 -538
  468. package/out/test/gateway-reset-mappings.test.js +0 -221
  469. package/out/test/gateway-route-index.test.js +0 -235
  470. package/out/test/gateway-secrets-preflight.test.js +0 -127
  471. package/out/test/gateway-session-routing.test.js +0 -65
  472. package/out/test/gateway-session-store.test.js +0 -216
  473. package/out/test/github.test.js +0 -232
  474. package/out/test/governor-hardening.test.js +0 -217
  475. package/out/test/headless-sync.test.js +0 -301
  476. package/out/test/helpers/manifest-fixtures.js +0 -27
  477. package/out/test/idp-init.test.js +0 -151
  478. package/out/test/lease-signature.test.js +0 -357
  479. package/out/test/lease-trust-root.test.js +0 -273
  480. package/out/test/lease-validation.test.js +0 -169
  481. package/out/test/lease.test.js +0 -114
  482. package/out/test/mcp-obo.test.js +0 -107
  483. package/out/test/mcp.test.js +0 -389
  484. package/out/test/model-routing.test.js +0 -133
  485. package/out/test/openclaw-channel-routing.test.js +0 -191
  486. package/out/test/pack-admission.test.js +0 -216
  487. package/out/test/pack-digest-parity.test.js +0 -140
  488. package/out/test/pack-reconcile.test.js +0 -183
  489. package/out/test/pack-signature-artifact.test.js +0 -103
  490. package/out/test/pack-signature.test.js +0 -176
  491. package/out/test/pack-trust-root.test.js +0 -202
  492. package/out/test/pathSafety.test.js +0 -63
  493. package/out/test/permissions.test.js +0 -175
  494. package/out/test/persistent-engine-worker.test.js +0 -220
  495. package/out/test/refreshPolicy.test.js +0 -60
  496. package/out/test/registry.test.js +0 -351
  497. package/out/test/remote-trust.test.js +0 -242
  498. package/out/test/runner-protocol.test.js +0 -249
  499. package/out/test/runtime.test.js +0 -349
  500. package/out/test/sandbox-driver.test.js +0 -553
  501. package/out/test/sandbox-hardening.test.js +0 -395
  502. package/out/test/sandbox-runner.test.js +0 -343
  503. package/out/test/scheduledFleetStorage.test.js +0 -72
  504. package/out/test/serve-gateway-turn.test.js +0 -267
  505. package/out/test/serve-hardening.test.js +0 -418
  506. package/out/test/serveClient.test.js +0 -209
  507. package/out/test/sessionJsonlFleet.test.js +0 -78
  508. package/out/test/sessionShip.test.js +0 -560
  509. package/out/test/shared.test.js +0 -173
  510. package/out/test/skills-mcp.test.js +0 -299
  511. package/out/test/spotlightPublish.test.js +0 -327
  512. package/out/test/spotlightYaml.test.js +0 -58
  513. package/out/test/state-sync-peer.test.js +0 -156
  514. package/out/test/store-install-safe.test.js +0 -69
  515. package/out/test/store.test.js +0 -331
  516. package/out/test/stores.test.js +0 -504
  517. package/out/test/sync-switch.test.js +0 -251
  518. package/out/test/teamViewDiscovery.test.js +0 -90
  519. package/out/test/tls-bypass.test.js +0 -90
  520. package/out/test/toolPath.test.js +0 -120
  521. package/out/test/utils.test.js +0 -308
  522. package/out/test/viewsConfigMerge.test.js +0 -180
  523. package/out/test/warrant.test.js +0 -138
  524. package/out/test/windows-command-line.test.js +0 -75
  525. package/out/utils/agentEnvFile.js +0 -131
  526. package/out/utils/binary.js +0 -175
  527. package/out/utils/index.js +0 -37
  528. package/out/utils/network.js +0 -74
  529. package/out/utils/paths.js +0 -116
  530. package/out/utils/pid.js +0 -180
  531. package/out/utils/resolveNodeBinary.js +0 -168
  532. package/out/utils/windowsCommandLine.js +0 -29
  533. package/out/utils.js +0 -968
package/out/sync.js CHANGED
@@ -1,1829 +1,26 @@
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.SyncService = void 0;
40
- const vscode = __importStar(require("vscode"));
41
- const fs_1 = require("fs");
42
- const path = __importStar(require("path"));
43
- const os = __importStar(require("os"));
44
- const utils_1 = require("./utils");
45
- const remoteSkills_1 = require("./remoteSkills");
46
- const branding_1 = require("./branding");
47
- const paths_1 = require("./agentpack/paths");
48
- const manifest_1 = require("./agentpack/manifest");
49
- const mcp_1 = require("./mcp");
50
- const customRegistry_1 = require("./engines/customRegistry");
51
- // -----------------------------------------------------------------------------
52
- // Constants
53
- // -----------------------------------------------------------------------------
54
- const AGENTIDE_DERIVED_DIR_README = 'AGENTIDE_README.md';
55
- const AGENTIDE_CONTEXT_FILE = 'context.md';
56
- const AGENTIDE_MANIFEST_FILE = 'agentide.manifest.json';
57
- const AGENTIDE_INSTALLED_AGENTS_FILE = 'installed-agents.json';
58
- const AGENTIDE_MANIFEST_DEBOUNCE_MS = 2000;
59
- const AGENTIDE_AGENT_YAML = 'agent.yaml';
60
- const AGENTIDE_AGENTS_DIR = 'agents';
61
- const AGENTIDE_DEFAULT_AGENT_ID = 'default';
62
- const AGENTIDE_DIR_NAME = paths_1.AGENT_CONSTANTS.AGENTIDE_DIR_NAME;
63
- // Use unified AGENT_ENGINES from shared
64
- const shared_1 = require("./shared");
65
- function getConfiguredAdditionalEngineDir() {
66
- return vscode.workspace
67
- .getConfiguration('agentide')
68
- .get('additionalEngineDir');
69
- }
70
- function getDerivedEngineSyncTargets(workspaceRoot) {
71
- const builtins = Object.values(shared_1.AGENT_ENGINES).map(engine => ({
72
- id: engine.id,
73
- displayName: engine.displayName,
74
- workspaceDir: engine.workspaceDir,
75
- rulesFile: engine.rulesFile,
76
- managedPaths: engine.managedPaths,
77
- includeSkills: true,
78
- includeRules: true,
79
- }));
80
- const custom = (0, customRegistry_1.discoverCustomEngineManifests)(workspaceRoot, getConfiguredAdditionalEngineDir())
81
- .filter(manifest => manifest.workspaceSync?.enabled)
82
- .map(manifest => ({
83
- id: manifest.id,
84
- displayName: manifest.displayName ?? manifest.id,
85
- workspaceDir: manifest.workspaceSync.dir,
86
- rulesFile: manifest.workspaceSync.rulesFile,
87
- includeSkills: manifest.workspaceSync.includeSkills,
88
- includeRules: manifest.workspaceSync.includeRules,
89
- }));
90
- return [...builtins, ...custom];
91
- }
92
- function getSkillDirNameFromRelPath(relPath) {
93
- const normalized = relPath.replace(/\\/g, '/');
94
- const parts = normalized.split('/').filter(Boolean);
95
- const skillsIndex = parts.indexOf('skills');
96
- if (skillsIndex !== -1 && parts.length > skillsIndex + 1) {
97
- return parts[skillsIndex + 1];
98
- }
99
- // Common case: skills/<dir>/SKILL.md
100
- if (parts.length >= 3 && parts[0] === 'skills') {
101
- return parts[1];
102
- }
103
- return undefined;
104
- }
105
- /**
106
- * Parse YAML front matter from a SKILL.md file.
107
- * Expects format:
108
- * ```
109
- * ---
110
- * name: skill-name
111
- * description: A description of the skill
112
- * ---
113
- * # Content...
114
- * ```
115
- */
116
- function parseSkillYamlHeader(content) {
117
- const result = {};
118
- // Check for YAML front matter (starts with ---)
119
- if (!content.startsWith('---')) {
120
- return result;
121
- }
122
- // Find the closing ---
123
- const lines = content.split('\n');
124
- let endIndex = -1;
125
- for (let i = 1; i < lines.length; i++) {
126
- if (lines[i].trim() === '---') {
127
- endIndex = i;
128
- break;
129
- }
130
- }
131
- if (endIndex === -1) {
132
- return result;
133
- }
134
- // Parse YAML content (simple key: value parsing, no full YAML library needed)
135
- for (let i = 1; i < endIndex; i++) {
136
- const line = lines[i];
137
- const colonIndex = line.indexOf(':');
138
- if (colonIndex === -1) {
139
- continue;
140
- }
141
- const key = line.substring(0, colonIndex).trim().toLowerCase();
142
- let value = line.substring(colonIndex + 1).trim();
143
- // Remove surrounding quotes if present
144
- if ((value.startsWith('"') && value.endsWith('"')) ||
145
- (value.startsWith('\'') && value.endsWith('\''))) {
146
- value = value.slice(1, -1);
147
- }
148
- if (key === 'name' && value) {
149
- result.name = value;
150
- }
151
- else if (key === 'description' && value) {
152
- result.description = value;
153
- }
154
- }
155
- return result;
156
- }
157
- function parseYaml(content) {
158
- const yaml = require('js-yaml');
159
- return yaml.load(content);
160
- }
161
- function dumpYaml(doc) {
162
- const yaml = require('js-yaml');
163
- return yaml.dump(doc, { lineWidth: 120, noRefs: true });
164
- }
165
- async function isDirEmpty(targetDir) {
166
- const entries = await fs_1.promises.readdir(targetDir);
167
- return entries.length === 0;
168
- }
169
- // -----------------------------------------------------------------------------
170
- // Sync Service
171
- // -----------------------------------------------------------------------------
172
- class SyncService {
173
- getBundledBasePromptsDir;
174
- // Cache for tracking .agentide/ directory state to avoid redundant syncs
175
- lastAgentideSyncSignatureByRoot = new Map();
176
- agentideSignatureByRoot = new Map();
177
- agentideSkillsSignatureByRoot = new Map();
178
- agentideRootUpdateState = new Map();
179
- agentideWatchersByRoot = new Map();
180
- // Track active agent turns to avoid syncing while agent is running
181
- activeAgentTurns = 0;
182
- // Track active pack per workspace root (for pack-aware file watching)
183
- activePackIdByRoot = new Map();
184
- // mtime cache for getActiveAgentManifest — handleChatCommand reads this on every turn just
185
- // to check spec.remote.url, so avoid a stat+read+parse per message on the hot chat path.
186
- activeAgentManifestCache = new Map();
187
- constructor(getBundledBasePromptsDir) {
188
- this.getBundledBasePromptsDir = getBundledBasePromptsDir;
189
- }
190
- /**
191
- * Set the active pack ID for a workspace root.
192
- * This is used by the file watcher to determine which pack to sync.
193
- */
194
- setActivePackId(workspaceRoot, packId) {
195
- this.activePackIdByRoot.set(workspaceRoot, packId);
196
- }
197
- /**
198
- * Get the active pack ID for a workspace root.
199
- */
200
- getActivePackId(workspaceRoot) {
201
- return this.activePackIdByRoot.get(workspaceRoot);
202
- }
203
- incrementActiveAgentTurns() {
204
- this.activeAgentTurns++;
205
- }
206
- decrementActiveAgentTurns() {
207
- this.activeAgentTurns = Math.max(0, this.activeAgentTurns - 1);
208
- }
209
- getSkillsSignature(workspaceRoot) {
210
- return this.agentideSkillsSignatureByRoot.get(workspaceRoot);
211
- }
212
- async computeWorkspaceAgentideSignature(workspaceRoot, additionalDirectories) {
213
- const workspaceFolderRoots = vscode.workspace.workspaceFolders?.map(f => f.uri.fsPath) ?? [];
214
- const additionalWorkspaceRoots = (additionalDirectories ?? []).filter(d => workspaceFolderRoots.includes(d));
215
- const roots = Array.from(new Set([workspaceRoot, ...additionalWorkspaceRoots].map(r => r.trim()).filter(Boolean)))
216
- .filter(r => r !== os.homedir());
217
- const pairs = [];
218
- for (const root of roots) {
219
- let sig = this.agentideSignatureByRoot.get(root);
220
- if (!sig) {
221
- sig = (await this.readAgentideManifest(root))?.agentideSignature;
222
- if (sig) {
223
- this.agentideSignatureByRoot.set(root, sig);
224
- }
225
- }
226
- pairs.push([root, sig ?? 'missing']);
227
- }
228
- pairs.sort((a, b) => a[0].localeCompare(b[0]));
229
- return (0, utils_1.shortSig)(JSON.stringify(pairs));
230
- }
231
- // -------------------------------------------------------------------------
232
- // Managed Resources
233
- // -------------------------------------------------------------------------
234
- getManagedResources(codexHome, claudeConfigDir, workspaceRoots) {
235
- const resources = [];
236
- const roots = Array.from(new Set(workspaceRoots.map(r => r.trim()).filter(Boolean)))
237
- .filter(r => r !== os.homedir());
238
- // Build config dir lookup from EngineConfig
239
- const configDirs = {
240
- codexHome,
241
- claudeConfigDir,
242
- };
243
- // Map engine configEnvVar to config key
244
- const envVarToKey = {
245
- 'CODEX_HOME': 'codexHome',
246
- 'CLAUDE_CONFIG_DIR': 'claudeConfigDir',
247
- };
248
- // Add engine-specific managed resources from AGENT_ENGINES
249
- for (const engine of Object.values(shared_1.AGENT_ENGINES)) {
250
- const configKey = engine.configEnvVar ? envVarToKey[engine.configEnvVar] : undefined;
251
- const configDir = configKey ? configDirs[configKey] : undefined;
252
- if (!configDir) {
253
- continue;
254
- }
255
- if (engine.managedPaths?.length) {
256
- // Engine specifies individual managed paths
257
- for (const managedPath of engine.managedPaths) {
258
- const isDir = !managedPath.includes('.');
259
- resources.push({
260
- path: path.join(configDir, managedPath),
261
- type: isDir ? 'directory' : 'generated',
262
- description: `${engine.displayName} ${managedPath} (managed by AgentIDE)`,
263
- safeToDelete: true,
264
- });
265
- }
266
- }
267
- else {
268
- // Engine manages the entire config dir
269
- resources.push({
270
- path: configDir,
271
- type: 'directory',
272
- description: `${engine.displayName} config dir (managed by AgentIDE)`,
273
- safeToDelete: true,
274
- });
275
- }
276
- }
277
- // Add workspace-level resources
278
- for (const root of roots) {
279
- resources.push({
280
- path: path.join(root, AGENTIDE_DIR_NAME),
281
- type: 'directory',
282
- description: 'AgentIDE project rules & skills (source-of-truth)',
283
- safeToDelete: false,
284
- });
285
- // Add derived engine directories from built-in and custom engine manifests.
286
- for (const engine of getDerivedEngineSyncTargets(root)) {
287
- resources.push({
288
- path: path.join(root, engine.workspaceDir),
289
- type: 'directory',
290
- description: `${engine.displayName} project folder (derived/overwritten from ${AGENTIDE_DIR_NAME}/)`,
291
- safeToDelete: true,
292
- });
293
- }
294
- }
295
- return resources;
296
- }
297
- async writeManagedPathsManifest(codexHome, claudeConfigDir, workspaceRoot, additionalDirectories, outputChannel) {
298
- if (!workspaceRoot || workspaceRoot === os.homedir()) {
299
- return;
300
- }
301
- const agentideDir = this.getAgentideProjectDir(workspaceRoot);
302
- const manifestPath = path.join(agentideDir, 'paths.md');
303
- const resources = this.getManagedResources(codexHome, claudeConfigDir, [workspaceRoot, ...(additionalDirectories ?? [])]);
304
- const lines = [
305
- '# AgentIDE Managed Resources',
306
- '',
307
- 'This file lists all files and directories managed by the AgentIDE extension.',
308
- '**Auto-generated** - Do not edit manually.',
309
- '',
310
- `**Workspace:** \`${workspaceRoot}\``,
311
- codexHome ? `**Codex Home:** \`${codexHome}\`` : '',
312
- claudeConfigDir ? `**Claude Config Dir:** \`${claudeConfigDir}\`` : '',
313
- '',
314
- '## Resources',
315
- '',
316
- '| Path | Type | Safe to Delete | Description |',
317
- '|------|------|----------------|-------------|',
318
- ];
319
- for (const r of resources) {
320
- const exists = await (0, utils_1.pathExists)(r.path);
321
- const status = exists ? '[x]' : '[ ]';
322
- lines.push(`| ${status} \`${r.path}\` | ${r.type} | ${r.safeToDelete ? 'Yes' : 'No'} | ${r.description} |`);
323
- }
324
- lines.push('');
325
- lines.push('## How to Reset');
326
- lines.push('');
327
- lines.push('Run the command: **AgentIDE: Clear Managed Resources**');
328
- lines.push('');
329
- lines.push('This will:');
330
- lines.push('- Remove symlinks created by the extension');
331
- lines.push('- Delete generated files (context.md, config.toml, etc.)');
332
- lines.push(`- **NOT** delete user-managed rules/skills inside \`${AGENTIDE_DIR_NAME}/\``);
333
- lines.push('');
334
- await fs_1.promises.mkdir(agentideDir, { recursive: true });
335
- await (0, utils_1.writeFileIfChanged)(manifestPath, lines.filter(Boolean).join('\n'));
336
- outputChannel.appendLine(`[AgentIDE] Wrote manifest: ${manifestPath}`);
337
- }
338
- async clearManagedResources(codexHome, claudeConfigDir, workspaceRoot, additionalDirectories, outputChannel) {
339
- const resources = this.getManagedResources(codexHome, claudeConfigDir, [workspaceRoot ?? '', ...(additionalDirectories ?? [])]);
340
- const cleared = [];
341
- const skipped = [];
342
- const errors = [];
343
- for (const r of resources) {
344
- if (!r.safeToDelete) {
345
- skipped.push(r.path);
346
- continue;
347
- }
348
- try {
349
- const stat = await fs_1.promises.lstat(r.path);
350
- if (r.type === 'symlink') {
351
- if (stat.isSymbolicLink()) {
352
- await fs_1.promises.unlink(r.path);
353
- cleared.push(r.path);
354
- outputChannel.appendLine(`[AgentIDE] Removed symlink: ${r.path}`);
355
- }
356
- else {
357
- skipped.push(r.path);
358
- outputChannel.appendLine(`[AgentIDE] Skipped (not a symlink): ${r.path}`);
359
- }
360
- }
361
- else if (r.type === 'generated') {
362
- if (stat.isFile()) {
363
- await fs_1.promises.unlink(r.path);
364
- cleared.push(r.path);
365
- outputChannel.appendLine(`[AgentIDE] Removed generated file: ${r.path}`);
366
- }
367
- }
368
- else if (r.type === 'directory' && r.safeToDelete) {
369
- if (stat.isDirectory()) {
370
- await fs_1.promises.rm(r.path, { recursive: true, force: true });
371
- cleared.push(r.path);
372
- outputChannel.appendLine(`[AgentIDE] Removed directory: ${r.path}`);
373
- }
374
- }
375
- }
376
- catch (e) {
377
- if ((0, utils_1.getErrorCode)(e) !== 'ENOENT') {
378
- errors.push(`${r.path}: ${e instanceof Error ? e.message : String(e)}`);
379
- }
380
- }
381
- }
382
- // Reset internal state
383
- this.lastAgentideSyncSignatureByRoot.clear();
384
- this.agentideSignatureByRoot.clear();
385
- this.agentideSkillsSignatureByRoot.clear();
386
- return { cleared, skipped, errors };
387
- }
388
- // -------------------------------------------------------------------------
389
- // Manifest Management
390
- // -------------------------------------------------------------------------
391
- getAgentideProjectDir(workspaceRoot) {
392
- return (0, paths_1.getAgentideDir)(workspaceRoot);
393
- }
394
- /**
395
- * Get the agents directory path (.agentide/agents/).
396
- */
397
- getAgentsDir(workspaceRoot) {
398
- return path.join(this.getAgentideProjectDir(workspaceRoot), AGENTIDE_AGENTS_DIR);
399
- }
400
- /**
401
- * Get the root directory for a specific agent.
402
- */
403
- getAgentRoot(workspaceRoot, agentId) {
404
- return path.join(this.getAgentsDir(workspaceRoot), agentId);
405
- }
406
- /**
407
- * Get skills directory for an agent.
408
- */
409
- getAgentSkillsDir(workspaceRoot, agentId) {
410
- return path.join(this.getAgentRoot(workspaceRoot, agentId), 'skills');
411
- }
412
- /**
413
- * Get rules directory for an agent.
414
- */
415
- getAgentRulesDir(workspaceRoot, agentId) {
416
- return path.join(this.getAgentRoot(workspaceRoot, agentId), 'rules');
417
- }
418
- /**
419
- * Get AGENTS.md file path for an agent.
420
- */
421
- getAgentAgentsFile(workspaceRoot, agentId) {
422
- return path.join(this.getAgentRoot(workspaceRoot, agentId), 'AGENTS.md');
423
- }
424
- /**
425
- * Get context.md file path for an agent.
426
- */
427
- getAgentContextFile(workspaceRoot, agentId) {
428
- return path.join(this.getAgentRoot(workspaceRoot, agentId), AGENTIDE_CONTEXT_FILE);
429
- }
430
- /**
431
- * Get the active agent ID, defaulting to 'default'.
432
- */
433
- getActiveAgentId(workspaceRoot) {
434
- return this.getActivePackId(workspaceRoot) ?? AGENTIDE_DEFAULT_AGENT_ID;
435
- }
436
- async resolveManifestSource(workspaceRoot, agentIdOverride) {
437
- // All agents (including default) live in .agentide/agents/<agentId>/
438
- const agentId = agentIdOverride ?? this.getActiveAgentId(workspaceRoot);
439
- const agentRoot = this.getAgentRoot(workspaceRoot, agentId);
440
- return {
441
- agentId,
442
- isPack: agentId !== AGENTIDE_DEFAULT_AGENT_ID,
443
- agentRoot,
444
- agentsFile: this.getAgentAgentsFile(workspaceRoot, agentId),
445
- contextFile: this.getAgentContextFile(workspaceRoot, agentId),
446
- rulesDir: this.getAgentRulesDir(workspaceRoot, agentId),
447
- skillsDir: this.getAgentSkillsDir(workspaceRoot, agentId),
448
- agentYamlPath: path.join(agentRoot, AGENTIDE_AGENT_YAML),
449
- };
450
- }
451
- async getDataPathsForAgent(workspaceRoot, agentId, outputChannel) {
452
- const agentRoot = this.getAgentRoot(workspaceRoot, agentId);
453
- const agentYamlPath = path.join(agentRoot, AGENTIDE_AGENT_YAML);
454
- if (!(await (0, utils_1.pathExists)(agentYamlPath))) {
455
- return undefined;
456
- }
457
- try {
458
- const manifest = await (0, manifest_1.loadAgentManifest)(agentYamlPath);
459
- const data = manifest.spec?.data;
460
- if (!data) {
461
- return undefined;
462
- }
463
- const sourcePath = (data.sourcePath?.trim() || './data');
464
- const workspacePath = (data.workspacePath?.trim() || `.${path.sep}${AGENTIDE_DIR_NAME}${path.sep}data${path.sep}${agentId}`)
465
- .replace(/^(?:\.\/|\.\\)/, '');
466
- const sourceDir = path.resolve(agentRoot, sourcePath);
467
- const targetDir = path.resolve(workspaceRoot, workspacePath);
468
- return { sourceDir, targetDir };
469
- }
470
- catch (e) {
471
- (0, utils_1.logInfo)(outputChannel, `[AgentIDE] Skipping data sync for ${agentId}: failed to parse data config (${e instanceof Error ? e.message : String(e)})`);
472
- return undefined;
473
- }
474
- }
475
- async seedAgentDataIfNeeded(workspaceRoot, agentId, outputChannel) {
476
- const dataPaths = await this.getDataPathsForAgent(workspaceRoot, agentId, outputChannel);
477
- if (!dataPaths) {
478
- return;
479
- }
480
- const { sourceDir, targetDir } = dataPaths;
481
- if (!(await (0, utils_1.pathExists)(sourceDir))) {
482
- return;
483
- }
484
- if (!(await (0, utils_1.pathExists)(targetDir))) {
485
- await (0, utils_1.copyDirRecursive)(sourceDir, targetDir);
486
- (0, utils_1.logInfo)(outputChannel, `[AgentIDE] Seeded pack data for ${agentId}: ${targetDir}`);
487
- return;
488
- }
489
- try {
490
- const st = await fs_1.promises.stat(targetDir);
491
- if (!st.isDirectory()) {
492
- return;
493
- }
494
- }
495
- catch {
496
- return;
497
- }
498
- if (await isDirEmpty(targetDir)) {
499
- await (0, utils_1.copyDirRecursive)(sourceDir, targetDir);
500
- (0, utils_1.logInfo)(outputChannel, `[AgentIDE] Seeded pack data for ${agentId}: ${targetDir}`);
501
- }
502
- }
503
- async syncAgentYamlSkills(workspaceRoot, agentId, manifest, outputChannel) {
504
- const agentYamlPath = path.join(this.getAgentRoot(workspaceRoot, agentId), AGENTIDE_AGENT_YAML);
505
- if (!(await (0, utils_1.pathExists)(agentYamlPath))) {
506
- return;
507
- }
508
- try {
509
- const raw = await fs_1.promises.readFile(agentYamlPath, 'utf8');
510
- const parsed = parseYaml(raw);
511
- if (!parsed || typeof parsed !== 'object') {
512
- return;
513
- }
514
- const doc = parsed;
515
- const skillPaths = manifest.skills.map(skill => ({ path: `./skills/${skill.dirName}` }));
516
- doc.spec = { ...(doc.spec ?? {}), skills: skillPaths };
517
- const next = dumpYaml(doc);
518
- await (0, utils_1.writeFileIfChanged)(agentYamlPath, next);
519
- }
520
- catch (e) {
521
- outputChannel.appendLine(`[AgentIDE] Warning: failed to update agent.yaml skills for ${agentId}: ${e instanceof Error ? e.message : String(e)}`);
522
- }
523
- }
524
- /**
525
- * Get the active agent's manifest (agent.yaml) for permission resolution.
526
- * Returns undefined if the manifest doesn't exist or can't be parsed.
527
- *
528
- * Cached by file mtime/size: handleChatCommand calls this on every turn to check
529
- * spec.remote.url, so we avoid a stat + read + full YAML parse per message. The
530
- * "no agent.yaml" / "invalid" log lines fire only on state transitions, not every
531
- * cached return, to keep the output channel clean.
532
- */
533
- async getActiveAgentManifest(workspaceRoot, outputChannel, agentIdOverride) {
534
- const agentId = agentIdOverride ?? this.getActiveAgentId(workspaceRoot);
535
- const agentYamlPath = path.join(this.getAgentRoot(workspaceRoot, agentId), AGENTIDE_AGENT_YAML);
536
- const stats = await (0, utils_1.getFileStats)(agentYamlPath);
537
- if (!stats) {
538
- const cached = this.activeAgentManifestCache.get(agentYamlPath);
539
- if (!cached?.loggedNoManifest) {
540
- outputChannel.appendLine(`[AgentIDE] No agent.yaml found for agent ${agentId}`);
541
- }
542
- this.activeAgentManifestCache.set(agentYamlPath, {
543
- mtimeMs: -1, size: -1, manifest: undefined,
544
- loggedNoManifest: true, loggedInvalid: cached?.loggedInvalid ?? false,
545
- });
546
- return undefined;
547
- }
548
- const cached = this.activeAgentManifestCache.get(agentYamlPath);
549
- if (cached && cached.mtimeMs === stats.mtimeMs && cached.size === stats.size) {
550
- return cached.manifest;
551
- }
552
- try {
553
- const raw = await fs_1.promises.readFile(agentYamlPath, 'utf8');
554
- const parsed = parseYaml(raw);
555
- // Basic validation
556
- if (!parsed?.metadata?.name || !parsed?.spec?.engine) {
557
- if (!cached?.loggedInvalid) {
558
- outputChannel.appendLine(`[AgentIDE] Invalid agent.yaml for agent ${agentId}: missing required fields`);
559
- }
560
- this.activeAgentManifestCache.set(agentYamlPath, {
561
- mtimeMs: stats.mtimeMs, size: stats.size, manifest: undefined,
562
- loggedNoManifest: false, loggedInvalid: true,
563
- });
564
- return undefined;
565
- }
566
- this.activeAgentManifestCache.set(agentYamlPath, {
567
- mtimeMs: stats.mtimeMs, size: stats.size, manifest: parsed,
568
- loggedNoManifest: false, loggedInvalid: false,
569
- });
570
- return parsed;
571
- }
572
- catch (e) {
573
- if (!cached?.loggedInvalid) {
574
- outputChannel.appendLine(`[AgentIDE] Failed to parse agent.yaml for agent ${agentId}: ${e instanceof Error ? e.message : String(e)}`);
575
- }
576
- this.activeAgentManifestCache.set(agentYamlPath, {
577
- mtimeMs: stats.mtimeMs, size: stats.size, manifest: undefined,
578
- loggedNoManifest: false, loggedInvalid: true,
579
- });
580
- return undefined;
581
- }
582
- }
583
- getAgentideManifestFilePath(workspaceRoot) {
584
- return path.join(this.getAgentideProjectDir(workspaceRoot), AGENTIDE_MANIFEST_FILE);
585
- }
586
- /**
587
- * Check if all derived provider directories exist for the given workspace root.
588
- */
589
- async allDerivedDirsPresent(workspaceRoot) {
590
- const results = await Promise.all(getDerivedEngineSyncTargets(workspaceRoot).map(engine => (0, utils_1.isDirOrSymlink)(path.join(workspaceRoot, engine.workspaceDir))));
591
- return results.every(Boolean);
592
- }
593
- async readAgentideManifest(workspaceRoot) {
594
- const manifestPath = this.getAgentideManifestFilePath(workspaceRoot);
595
- try {
596
- const raw = await fs_1.promises.readFile(manifestPath, 'utf8');
597
- const parsed = JSON.parse(raw);
598
- if (parsed.version !== 1 || typeof parsed.agentideSignature !== 'string') {
599
- return undefined;
600
- }
601
- return parsed;
602
- }
603
- catch (e) {
604
- if ((0, utils_1.getErrorCode)(e) === 'ENOENT') {
605
- return undefined;
606
- }
607
- return undefined;
608
- }
609
- }
610
- async computeAgentideManifest(workspaceRoot, source, cachedManifest) {
611
- const rulesDir = source.rulesDir;
612
- const skillsDir = source.skillsDir;
613
- // Build lookup maps from cached manifest for fast path (mtime caching)
614
- const cachedRulesByPath = new Map();
615
- const cachedSkillsByDirName = new Map();
616
- if (cachedManifest) {
617
- for (const rule of cachedManifest.rules) {
618
- cachedRulesByPath.set(rule.relPath, rule);
619
- }
620
- for (const skill of cachedManifest.skills) {
621
- const dirName = skill.dirName || getSkillDirNameFromRelPath(skill.skillMdRelPath) || skill.name;
622
- cachedSkillsByDirName.set(dirName, skill);
623
- }
624
- }
625
- const rules = [];
626
- const skills = [];
627
- // Helper to get file hash with mtime caching (avoids re-hashing unchanged files)
628
- const getFileHashWithCache = async (filePath, relPath) => {
629
- const stats = await (0, utils_1.getFileStats)(filePath);
630
- if (!stats) {
631
- return undefined;
632
- }
633
- const cached = cachedRulesByPath.get(relPath);
634
- const validCache = (0, utils_1.isCachedHashValid)(cached, stats);
635
- if (validCache) {
636
- return validCache; // Fast path: file unchanged, reuse cached hash
637
- }
638
- // Slow path: file changed, compute new hash
639
- const { sha256, size, mtimeMs } = await (0, utils_1.readFileSha256)(filePath);
640
- return { relPath, sha256, size, mtimeMs };
641
- };
642
- const agentsFile = source.agentsFile;
643
- const agentsEntry = await getFileHashWithCache(agentsFile, 'AGENTS.md');
644
- if (agentsEntry) {
645
- rules.push(agentsEntry);
646
- }
647
- const contextFile = source.contextFile;
648
- const contextEntry = await getFileHashWithCache(contextFile, AGENTIDE_CONTEXT_FILE);
649
- if (contextEntry) {
650
- rules.push(contextEntry);
651
- }
652
- try {
653
- const entries = await fs_1.promises.readdir(rulesDir, { withFileTypes: true });
654
- for (const entry of entries) {
655
- if (!entry.isFile() || !entry.name.toLowerCase().endsWith('.md')) {
656
- continue;
657
- }
658
- const abs = path.join(rulesDir, entry.name);
659
- const relPath = path.join('rules', entry.name).replace(/\\/g, '/');
660
- const ruleEntry = await getFileHashWithCache(abs, relPath);
661
- if (ruleEntry) {
662
- rules.push(ruleEntry);
663
- }
664
- }
665
- }
666
- catch {
667
- // ignore
668
- }
669
- try {
670
- const entries = await fs_1.promises.readdir(skillsDir, { withFileTypes: true });
671
- for (const entry of entries) {
672
- if (!entry.isDirectory()) {
673
- continue;
674
- }
675
- if (entry.name.startsWith('.')) {
676
- continue;
677
- }
678
- const skillMd = path.join(skillsDir, entry.name, 'SKILL.md');
679
- const stats = await (0, utils_1.getFileStats)(skillMd);
680
- if (!stats) {
681
- continue;
682
- }
683
- const cached = cachedSkillsByDirName.get(entry.name);
684
- const validCache = cached && cached.skillMdMtimeMs === stats.mtimeMs && cached.skillMdSize === stats.size;
685
- if (validCache) {
686
- // Fast path: skill unchanged, reuse cached entry entirely (including name/description from manifest)
687
- skills.push({
688
- ...cached,
689
- dirName: entry.name, // Ensure dirName is set (for old manifests that might not have it)
690
- });
691
- }
692
- else {
693
- // Slow path: skill changed, compute new hash and parse YAML header
694
- const { sha256, size, mtimeMs } = await (0, utils_1.readFileSha256)(skillMd);
695
- // Read file content to parse YAML header for name/description
696
- let yamlName;
697
- let yamlDescription;
698
- try {
699
- const content = await fs_1.promises.readFile(skillMd, 'utf-8');
700
- const header = parseSkillYamlHeader(content);
701
- yamlName = header.name;
702
- yamlDescription = header.description;
703
- }
704
- catch {
705
- // Ignore read errors, use directory name as fallback
706
- }
707
- skills.push({
708
- dirName: entry.name,
709
- name: yamlName || entry.name, // Prefer YAML name, fallback to directory name
710
- description: yamlDescription,
711
- skillMdRelPath: path.join('skills', entry.name, 'SKILL.md').replace(/\\/g, '/'),
712
- skillMdSha256: sha256,
713
- skillMdSize: size,
714
- skillMdMtimeMs: mtimeMs,
715
- });
716
- }
717
- }
718
- }
719
- catch {
720
- // ignore
721
- }
722
- rules.sort((a, b) => a.relPath.localeCompare(b.relPath));
723
- skills.sort((a, b) => a.dirName.localeCompare(b.dirName));
724
- const rulesSignature = (0, utils_1.shortSig)(JSON.stringify(rules.map(r => [r.relPath, r.sha256])));
725
- // Use dirName (stable folder identifier) to ensure signature changes when a skill folder is renamed.
726
- const skillsSignature = (0, utils_1.shortSig)(JSON.stringify(skills.map(s => [s.dirName, s.skillMdSha256])));
727
- const agentideSignature = (0, utils_1.shortSig)(`${rulesSignature}:${skillsSignature}`);
728
- return {
729
- version: 1,
730
- workspaceRoot,
731
- generatedAt: new Date().toISOString(),
732
- activeAgentId: source.agentId,
733
- rules,
734
- skills,
735
- rulesSignature,
736
- skillsSignature,
737
- agentideSignature,
738
- };
739
- }
740
- async writeAgentideManifest(workspaceRoot, outputChannel, options) {
741
- const agentideDir = this.getAgentideProjectDir(workspaceRoot);
742
- if (!(await (0, utils_1.pathExists)(agentideDir))) {
743
- await fs_1.promises.mkdir(agentideDir, { recursive: true });
744
- }
745
- const existing = await this.readAgentideManifest(workspaceRoot);
746
- const source = await this.resolveManifestSource(workspaceRoot, options?.packIdOverride);
747
- const useCache = existing?.activeAgentId === source.agentId;
748
- // Pass existing manifest for mtime caching (avoids re-hashing unchanged files)
749
- const manifest = await this.computeAgentideManifest(workspaceRoot, source, useCache ? existing : undefined);
750
- manifest.derivedSkillIngestState = useCache ? (options?.derivedSkillIngestState ?? existing?.derivedSkillIngestState) : options?.derivedSkillIngestState;
751
- // Note: installedAgents is now stored in separate installed-agents.json file
752
- const manifestPath = this.getAgentideManifestFilePath(workspaceRoot);
753
- await (0, utils_1.writeFileIfChanged)(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
754
- this.agentideSignatureByRoot.set(workspaceRoot, manifest.agentideSignature);
755
- this.agentideSkillsSignatureByRoot.set(workspaceRoot, manifest.skillsSignature);
756
- outputChannel.appendLine(`[AgentIDE] Updated manifest: ${manifestPath} (sig=${manifest.agentideSignature})`);
757
- if (!source.isPack) {
758
- await this.syncAgentYamlSkills(workspaceRoot, source.agentId, manifest, outputChannel);
759
- }
760
- return manifest;
761
- }
762
- // -------------------------------------------------------------------------
763
- // File Watchers
764
- // -------------------------------------------------------------------------
765
- ensureAgentideWatchers(outputChannel) {
766
- const roots = vscode.workspace.workspaceFolders?.map(f => f.uri.fsPath) ?? [];
767
- const existingRoots = new Set(this.agentideWatchersByRoot.keys());
768
- for (const root of existingRoots) {
769
- if (!roots.includes(root)) {
770
- this.disposeAgentideWatchersForRoot(root);
771
- this.agentideRootUpdateState.delete(root);
772
- this.lastAgentideSyncSignatureByRoot.delete(root);
773
- this.agentideSignatureByRoot.delete(root);
774
- this.agentideSkillsSignatureByRoot.delete(root);
775
- }
776
- }
777
- for (const root of roots) {
778
- if (this.agentideWatchersByRoot.has(root)) {
779
- continue;
780
- }
781
- // Watch all agents in the agent root
782
- const patterns = [
783
- { pattern: new vscode.RelativePattern(root, `${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/agent.yaml`), reason: 'source' },
784
- { pattern: new vscode.RelativePattern(root, `${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/AGENTS.md`), reason: 'source' },
785
- { pattern: new vscode.RelativePattern(root, `${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/context.md`), reason: 'source' },
786
- { pattern: new vscode.RelativePattern(root, `${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/rules/**/*.md`), reason: 'source' },
787
- { pattern: new vscode.RelativePattern(root, `${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/skills/**/*`), reason: 'source' },
788
- // Also watch agents/ for pack changes (to detect new/updated packs)
789
- { pattern: new vscode.RelativePattern(root, `${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/AGENTS.md`), reason: 'source' },
790
- { pattern: new vscode.RelativePattern(root, `${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/context.md`), reason: 'source' },
791
- { pattern: new vscode.RelativePattern(root, `${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/rules/**/*.md`), reason: 'source' },
792
- { pattern: new vscode.RelativePattern(root, `${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/skills/**/*`), reason: 'source' },
793
- { pattern: new vscode.RelativePattern(root, `${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/agent.yaml`), reason: 'source' },
794
- // Watch derived engine directories for ingest back to .agentide
795
- ...getDerivedEngineSyncTargets(root).flatMap(engine => [
796
- ...(engine.includeSkills
797
- ? [{ pattern: new vscode.RelativePattern(root, `${engine.workspaceDir}/skills/**/SKILL.md`), reason: 'derived' }]
798
- : []),
799
- { pattern: new vscode.RelativePattern(root, `${engine.workspaceDir}/${engine.rulesFile}`), reason: 'derived' },
800
- ...(engine.includeRules
801
- ? [{ pattern: new vscode.RelativePattern(root, `${engine.workspaceDir}/rules/**/*.md`), reason: 'derived' }]
802
- : []),
803
- ]),
804
- ];
805
- const disposables = [];
806
- for (const { pattern, reason } of patterns) {
807
- const watcher = vscode.workspace.createFileSystemWatcher(pattern);
808
- const onAny = () => this.scheduleAgentideRootUpdate(root, outputChannel, reason);
809
- disposables.push(watcher, watcher.onDidChange(onAny), watcher.onDidCreate(onAny), watcher.onDidDelete(onAny));
810
- }
811
- this.agentideWatchersByRoot.set(root, disposables);
812
- this.scheduleAgentideRootUpdate(root, outputChannel, 'source');
813
- }
814
- }
815
- disposeAgentideWatchersForRoot(workspaceRoot) {
816
- const disposables = this.agentideWatchersByRoot.get(workspaceRoot);
817
- if (!disposables) {
818
- return;
819
- }
820
- for (const d of disposables) {
821
- try {
822
- d.dispose();
823
- }
824
- catch { /* ignore */ }
825
- }
826
- this.agentideWatchersByRoot.delete(workspaceRoot);
827
- }
828
- disposeAllWatchers() {
829
- for (const root of this.agentideWatchersByRoot.keys()) {
830
- this.disposeAgentideWatchersForRoot(root);
831
- }
832
- this.agentideRootUpdateState.clear();
833
- }
834
- scheduleAgentideRootUpdate(workspaceRoot, outputChannel, reason) {
835
- const state = this.agentideRootUpdateState.get(workspaceRoot) ?? {
836
- dirty: false,
837
- dirtySource: false,
838
- dirtyDerived: false,
839
- timer: undefined,
840
- deferred: undefined,
841
- };
842
- state.dirty = true;
843
- if (reason === 'source') {
844
- state.dirtySource = true;
845
- }
846
- else {
847
- state.dirtyDerived = true;
848
- }
849
- if (!state.deferred) {
850
- state.deferred = (0, utils_1.createDeferred)();
851
- }
852
- if (state.timer) {
853
- clearTimeout(state.timer);
854
- }
855
- state.timer = setTimeout(() => {
856
- void this.flushAgentideRootUpdate(workspaceRoot, outputChannel, { allowDuringActiveTurn: false, force: false });
857
- }, AGENTIDE_MANIFEST_DEBOUNCE_MS);
858
- this.agentideRootUpdateState.set(workspaceRoot, state);
859
- }
860
- async flushAgentideRootUpdate(workspaceRoot, outputChannel, options) {
861
- const allowDuringActiveTurn = options?.allowDuringActiveTurn ?? false;
862
- const force = options?.force ?? false;
863
- if (!allowDuringActiveTurn && this.activeAgentTurns > 0) {
864
- const existing = this.agentideRootUpdateState.get(workspaceRoot);
865
- const reason = existing?.dirtySource
866
- ? 'source'
867
- : existing?.dirtyDerived
868
- ? 'derived'
869
- : 'source';
870
- this.scheduleAgentideRootUpdate(workspaceRoot, outputChannel, reason);
871
- return;
872
- }
873
- const state = this.agentideRootUpdateState.get(workspaceRoot);
874
- if (!force && (!state || (!state.dirty && !state.deferred))) {
875
- return;
876
- }
877
- const dirtySourceBefore = force || (state?.dirtySource ?? false);
878
- const dirtyDerivedBefore = force || (state?.dirtyDerived ?? false);
879
- if (state?.timer) {
880
- clearTimeout(state.timer);
881
- state.timer = undefined;
882
- }
883
- const deferred = state?.deferred;
884
- if (state) {
885
- state.dirty = false;
886
- state.dirtySource = false;
887
- state.dirtyDerived = false;
888
- state.deferred = undefined;
889
- this.agentideRootUpdateState.set(workspaceRoot, state);
890
- }
891
- try {
892
- let manifest = await this.readAgentideManifest(workspaceRoot);
893
- // Import new skills from derived dirs if they changed
894
- const ingestResult = dirtyDerivedBefore
895
- ? await this.importNewSkillsFromDerivedIntoAgentide(workspaceRoot, outputChannel, manifest?.derivedSkillIngestState)
896
- : {
897
- agentideContentChanged: false,
898
- ingestStateChanged: false,
899
- nextIngestState: manifest?.derivedSkillIngestState ?? {},
900
- };
901
- if (!manifest
902
- || force
903
- || dirtySourceBefore
904
- || ingestResult.agentideContentChanged
905
- || ingestResult.ingestStateChanged) {
906
- manifest = await this.writeAgentideManifest(workspaceRoot, outputChannel, { derivedSkillIngestState: ingestResult.nextIngestState });
907
- // Auto-discover new packs when source files change (e.g., skill creates a new pack)
908
- // Only refresh if the number of agents on disk differs from registered count
909
- if (dirtySourceBefore) {
910
- try {
911
- const agentsDir = path.join(workspaceRoot, AGENTIDE_DIR_NAME, AGENTIDE_AGENTS_DIR);
912
- if (await (0, utils_1.pathExists)(agentsDir)) {
913
- const entries = await fs_1.promises.readdir(agentsDir, { withFileTypes: true });
914
- const diskAgentCount = entries.filter(e => e.isDirectory() && !e.name.startsWith('.')).length;
915
- const registeredAgents = await this.loadInstalledAgents(workspaceRoot);
916
- if (diskAgentCount > registeredAgents.length) {
917
- await vscode.commands.executeCommand('agentide.pack.refresh');
918
- }
919
- }
920
- }
921
- catch {
922
- // Ignore errors - this is a best-effort optimization
923
- }
924
- }
925
- }
926
- else {
927
- this.agentideSignatureByRoot.set(workspaceRoot, manifest.agentideSignature);
928
- this.agentideSkillsSignatureByRoot.set(workspaceRoot, manifest.skillsSignature);
929
- }
930
- if (!manifest) {
931
- return;
932
- }
933
- const lastSynced = this.lastAgentideSyncSignatureByRoot.get(workspaceRoot);
934
- const derivedPresent = await this.allDerivedDirsPresent(workspaceRoot);
935
- if (dirtySourceBefore || ingestResult.agentideContentChanged || lastSynced !== manifest.agentideSignature || !derivedPresent) {
936
- const activePackId = this.getActivePackId(workspaceRoot);
937
- const appliedPackId = await this.switchToPack(workspaceRoot, activePackId, outputChannel);
938
- if (appliedPackId !== activePackId) {
939
- this.setActivePackId(workspaceRoot, appliedPackId);
940
- }
941
- const activeAgentId = appliedPackId ?? AGENTIDE_DEFAULT_AGENT_ID;
942
- await this.seedAgentDataIfNeeded(workspaceRoot, activeAgentId, outputChannel);
943
- this.lastAgentideSyncSignatureByRoot.set(workspaceRoot, manifest.agentideSignature);
944
- outputChannel.appendLine(`[AgentIDE] Derived dirs synced for ${workspaceRoot} (sig=${manifest.agentideSignature}, pack=${appliedPackId ?? 'default'})`);
945
- }
946
- deferred?.resolve();
947
- }
948
- catch (e) {
949
- deferred?.reject(e);
950
- outputChannel.appendLine(`[AgentIDE] Warning: failed agentide update for ${workspaceRoot}: ${e instanceof Error ? e.message : String(e)}`);
951
- }
952
- }
953
- // -------------------------------------------------------------------------
954
- // Project Preparation
955
- // -------------------------------------------------------------------------
956
- async ensureAgentideProjectPrepared(workspaceRoot, additionalDirectories, outputChannel) {
957
- if (!workspaceRoot) {
958
- return;
959
- }
960
- const workspaceFolderRoots = vscode.workspace.workspaceFolders?.map(f => f.uri.fsPath) ?? [];
961
- const additionalWorkspaceRoots = (additionalDirectories ?? []).filter(d => workspaceFolderRoots.includes(d));
962
- const roots = Array.from(new Set([workspaceRoot, ...additionalWorkspaceRoots].map(r => r.trim()).filter(Boolean))).filter(r => r !== os.homedir());
963
- for (const root of roots) {
964
- // Ensure git is initialized and root .gitignore has AgentIDE entries
965
- await (0, utils_1.ensureWorkspaceGitAndGitignore)(root, outputChannel, {
966
- extraSearchPath: getConfiguredAdditionalEngineDir(),
967
- });
968
- const agentideDir = this.getAgentideProjectDir(root);
969
- await fs_1.promises.mkdir(agentideDir, { recursive: true });
970
- await this.ensureAgentideGitignore(root, outputChannel);
971
- await this.ensureAgentideBundledPromptsCopiedToProject(root, outputChannel);
972
- const otherRoots = roots.filter(r => r !== root);
973
- await this.ensureAgentideContextTemplate(root, otherRoots, outputChannel);
974
- await this.ensureGhostTextPrompt(root, outputChannel);
975
- await this.ensureTerminalAssistPrompt(root, outputChannel);
976
- // Best-effort remote skills sync (optional, startup path)
977
- await this.syncRemoteSkillsIfEnabled(root, outputChannel, { force: false });
978
- }
979
- for (const root of roots) {
980
- await this.flushAgentideRootUpdate(root, outputChannel, { force: false, allowDuringActiveTurn: true });
981
- const derivedPresent = await this.allDerivedDirsPresent(root);
982
- let manifest = await this.readAgentideManifest(root);
983
- if (!manifest) {
984
- manifest = await this.writeAgentideManifest(root, outputChannel);
985
- }
986
- else {
987
- this.agentideSignatureByRoot.set(root, manifest.agentideSignature);
988
- this.agentideSkillsSignatureByRoot.set(root, manifest.skillsSignature);
989
- }
990
- const lastSig = this.lastAgentideSyncSignatureByRoot.get(root);
991
- if (lastSig === manifest.agentideSignature && derivedPresent) {
992
- outputChannel.appendLine(`[AgentIDE] .agentide/ unchanged for ${root}, skipping sync`);
993
- continue;
994
- }
995
- // Use pack-aware sync: switchToPack respects active pack ID
996
- // Import derived skills first in case agent created them while extension was stopped
997
- const activePackId = this.getActivePackId(root);
998
- const appliedPackId = await this.switchToPack(root, activePackId, outputChannel, { importDerivedSkills: true });
999
- if (appliedPackId !== activePackId) {
1000
- this.setActivePackId(root, appliedPackId);
1001
- }
1002
- this.lastAgentideSyncSignatureByRoot.set(root, manifest.agentideSignature);
1003
- outputChannel.appendLine(`[AgentIDE] Sync complete for ${root} (sig: ${manifest.agentideSignature}, pack: ${appliedPackId ?? 'default'})`);
1004
- }
1005
- }
1006
- /**
1007
- * Sync remote skills into `.agentide/agents/default/skills` for the given workspace root.
1008
- *
1009
- * - When `force=false`, this respects `agentide.skills.remote.syncOnStartup`.
1010
- * - When `force=true`, it runs as long as remote skills are enabled and a registryUrl is configured.
1011
- */
1012
- async syncRemoteSkillsIfEnabled(workspaceRoot, outputChannel, opts) {
1013
- const cfg = vscode.workspace.getConfiguration('agentide.skills.remote');
1014
- const enabled = cfg.get('enabled', false);
1015
- if (!enabled) {
1016
- return;
1017
- }
1018
- const syncOnStartup = cfg.get('syncOnStartup', true);
1019
- if (!opts.force && !syncOnStartup) {
1020
- return;
1021
- }
1022
- const registryUrl = cfg.get('registryUrl', '').trim();
1023
- if (!registryUrl) {
1024
- outputChannel.appendLine('[AgentIDE] Remote skills: enabled but agentide.skills.remote.registryUrl is empty');
1025
- return;
1026
- }
1027
- const timeoutMs = cfg.get('timeoutMs', 8000);
1028
- const allowOverwriteLocal = cfg.get('allowOverwriteLocal', false);
1029
- try {
1030
- const agentideSkillsDir = this.getAgentSkillsDir(workspaceRoot, AGENTIDE_DEFAULT_AGENT_ID);
1031
- const result = await (0, remoteSkills_1.syncRemoteSkillsToAgentideSkillsDir)(agentideSkillsDir, { registryUrl, timeoutMs, allowOverwriteLocal }, line => outputChannel.appendLine(line));
1032
- if (result.updated > 0) {
1033
- // Mark source dirty so the manifest/signatures are refreshed and derived dirs re-synced.
1034
- this.scheduleAgentideRootUpdate(workspaceRoot, outputChannel, 'source');
1035
- }
1036
- }
1037
- catch (e) {
1038
- outputChannel.appendLine(`[AgentIDE] Remote skills: unexpected error: ${e instanceof Error ? e.message : String(e)}`);
1039
- }
1040
- }
1041
- async ensureAgentideBundledPromptsCopiedToProject(workspaceRoot, outputChannel) {
1042
- const bundledDir = this.getBundledBasePromptsDir();
1043
- if (!bundledDir) {
1044
- return;
1045
- }
1046
- // All agents live in .agentide/agents/<agentId>/
1047
- const defaultAgentRoot = this.getAgentRoot(workspaceRoot, AGENTIDE_DEFAULT_AGENT_ID);
1048
- const agentideAgentsFile = this.getAgentAgentsFile(workspaceRoot, AGENTIDE_DEFAULT_AGENT_ID);
1049
- const agentideRulesDir = this.getAgentRulesDir(workspaceRoot, AGENTIDE_DEFAULT_AGENT_ID);
1050
- const agentideSkillsDir = this.getAgentSkillsDir(workspaceRoot, AGENTIDE_DEFAULT_AGENT_ID);
1051
- await fs_1.promises.mkdir(defaultAgentRoot, { recursive: true });
1052
- await fs_1.promises.mkdir(agentideRulesDir, { recursive: true });
1053
- await fs_1.promises.mkdir(agentideSkillsDir, { recursive: true });
1054
- const bundledAgentsFile = path.join(bundledDir, 'rules', 'AGENTS.md');
1055
- if (!(await (0, utils_1.pathExists)(agentideAgentsFile)) && (await (0, utils_1.pathExists)(bundledAgentsFile))) {
1056
- try {
1057
- const bundledAgentsContent = await fs_1.promises.readFile(bundledAgentsFile, 'utf8');
1058
- await fs_1.promises.writeFile(agentideAgentsFile, (0, branding_1.applyBrandingTokens)(bundledAgentsContent));
1059
- outputChannel.appendLine(`[AgentIDE] Bootstrapped project rules: ${agentideAgentsFile}`);
1060
- }
1061
- catch (e) {
1062
- outputChannel.appendLine(`[AgentIDE] Warning: failed to bootstrap project rules: ${e instanceof Error ? e.message : String(e)}`);
1063
- }
1064
- }
1065
- const bundledSkillsDir = path.join(bundledDir, 'skills');
1066
- if (await (0, utils_1.pathExists)(bundledSkillsDir)) {
1067
- try {
1068
- const entries = await fs_1.promises.readdir(bundledSkillsDir, { withFileTypes: true });
1069
- for (const entry of entries) {
1070
- if (!entry.isDirectory()) {
1071
- continue;
1072
- }
1073
- const srcSkill = path.join(bundledSkillsDir, entry.name);
1074
- const dstSkill = path.join(agentideSkillsDir, entry.name);
1075
- if (await (0, utils_1.pathExists)(dstSkill)) {
1076
- continue;
1077
- }
1078
- // Apply branding tokens to markdown files in bundled skills
1079
- await (0, utils_1.copyDirRecursiveWithTransform)(srcSkill, dstSkill, branding_1.applyBrandingTokens);
1080
- outputChannel.appendLine(`[AgentIDE] Bootstrapped project skill: ${entry.name}`);
1081
- }
1082
- }
1083
- catch (e) {
1084
- outputChannel.appendLine(`[AgentIDE] Warning: failed to bootstrap project skills: ${e instanceof Error ? e.message : String(e)}`);
1085
- }
1086
- }
1087
- // Sync MCP config to default agent's mcp/.mcp.json
1088
- const agentideMcpDir = path.join(defaultAgentRoot, paths_1.AGENT_CONSTANTS.MCP_DIR);
1089
- const mcpConfigPath = path.join(agentideMcpDir, '.mcp.json');
1090
- if (!(await (0, utils_1.pathExists)(mcpConfigPath))) {
1091
- try {
1092
- const mcpConfig = await (0, mcp_1.getDefaultMcpConfig)(bundledDir);
1093
- if (mcpConfig) {
1094
- await fs_1.promises.mkdir(agentideMcpDir, { recursive: true });
1095
- await fs_1.promises.writeFile(mcpConfigPath, mcpConfig);
1096
- outputChannel.appendLine(`[AgentIDE] Bootstrapped MCP config: ${mcpConfigPath}`);
1097
- }
1098
- }
1099
- catch (e) {
1100
- outputChannel.appendLine(`[AgentIDE] Warning: failed to bootstrap MCP config: ${e instanceof Error ? e.message : String(e)}`);
1101
- }
1102
- }
1103
- // Ensure default agent has an agent.yaml
1104
- await this.ensureDefaultAgentYaml(workspaceRoot, outputChannel);
1105
- }
1106
- /**
1107
- * Ensure default agent has an agent.yaml file.
1108
- * All agents have the same structure under .agentide/agents/<agentId>/
1109
- */
1110
- async ensureDefaultAgentYaml(workspaceRoot, outputChannel) {
1111
- const defaultAgentRoot = this.getAgentRoot(workspaceRoot, AGENTIDE_DEFAULT_AGENT_ID);
1112
- const agentYamlPath = path.join(defaultAgentRoot, AGENTIDE_AGENT_YAML);
1113
- if (await (0, utils_1.pathExists)(agentYamlPath)) {
1114
- return; // Already exists
1115
- }
1116
- await fs_1.promises.mkdir(defaultAgentRoot, { recursive: true });
1117
- const defaultAgentYaml = (0, paths_1.generateDefaultAgentYaml)({
1118
- includeModelHintComment: true,
1119
- });
1120
- try {
1121
- await fs_1.promises.writeFile(agentYamlPath, defaultAgentYaml, 'utf8');
1122
- outputChannel.appendLine(`[AgentIDE] Bootstrapped default agent configuration: ${agentYamlPath}`);
1123
- }
1124
- catch (e) {
1125
- outputChannel.appendLine(`[AgentIDE] Warning: failed to create default agent.yaml: ${e instanceof Error ? e.message : String(e)}`);
1126
- }
1127
- }
1128
- async ensureAgentideGitignore(workspaceRoot, outputChannel) {
1129
- const agentideDir = this.getAgentideProjectDir(workspaceRoot);
1130
- const gitignorePath = path.join(agentideDir, '.gitignore');
1131
- const managedBlockLines = [
1132
- '# AgentHippo (managed)',
1133
- '# Keep terminal logs and large per-session terminal attachments out of source control.',
1134
- 'terminals/',
1135
- 'agents/default',
1136
- 'sessions',
1137
- 'paths.md',
1138
- 'sessions/**/terminal.md',
1139
- 'sessions/**/terminal.md.1',
1140
- ];
1141
- let existing = '';
1142
- try {
1143
- existing = await fs_1.promises.readFile(gitignorePath, 'utf8');
1144
- }
1145
- catch (e) {
1146
- if ((0, utils_1.getErrorCode)(e) !== 'ENOENT') {
1147
- outputChannel.appendLine(`[AgentIDE] Warning: failed to read .gitignore: ${e instanceof Error ? e.message : String(e)}`);
1148
- return;
1149
- }
1150
- }
1151
- const hasAll = managedBlockLines.every(line => existing.includes(line));
1152
- if (hasAll) {
1153
- return;
1154
- }
1155
- const next = [
1156
- existing.trimEnd(),
1157
- '',
1158
- managedBlockLines.join('\n'),
1159
- '',
1160
- ].join('\n').replace(/^\n+/, '');
1161
- try {
1162
- const changed = await (0, utils_1.writeFileIfChanged)(gitignorePath, next);
1163
- if (changed) {
1164
- outputChannel.appendLine(`[AgentIDE] Updated ${gitignorePath} to ignore terminal logs`);
1165
- }
1166
- }
1167
- catch (e) {
1168
- outputChannel.appendLine(`[AgentIDE] Warning: failed to write .gitignore: ${e instanceof Error ? e.message : String(e)}`);
1169
- }
1170
- }
1171
- async ensureAgentideContextTemplate(workspaceRoot, additionalDirectories, outputChannel) {
1172
- const agentideDir = this.getAgentideProjectDir(workspaceRoot);
1173
- if (!(await (0, utils_1.pathExists)(agentideDir))) {
1174
- return;
1175
- }
1176
- const activeAgentId = this.getActiveAgentId(workspaceRoot);
1177
- const contextFilePath = this.getAgentContextFile(workspaceRoot, activeAgentId);
1178
- if (await (0, utils_1.pathExists)(contextFilePath)) {
1179
- return;
1180
- }
1181
- const bundledDir = this.getBundledBasePromptsDir();
1182
- const bundledTemplatePath = bundledDir ? path.join(bundledDir, 'templates', 'context.md') : undefined;
1183
- if (!bundledTemplatePath || !(await (0, utils_1.pathExists)(bundledTemplatePath))) {
1184
- outputChannel.appendLine('[AgentIDE] Warning: bundled context.md template not found');
1185
- return;
1186
- }
1187
- try {
1188
- let content = await fs_1.promises.readFile(bundledTemplatePath, 'utf8');
1189
- content = content.replace(/\{\{workspaceRoot\}\}/g, workspaceRoot);
1190
- const stableDirs = additionalDirectories.slice().filter(Boolean).sort();
1191
- const dirBlockRegex = /\{\{#additionalDirectories\}\}([\s\S]*?)\{\{\/additionalDirectories\}\}/;
1192
- const match = content.match(dirBlockRegex);
1193
- if (match) {
1194
- const template = match[1];
1195
- const expanded = stableDirs.length > 0
1196
- ? stableDirs.map(dir => template.replace(/\{\{\.\}\}/g, dir)).join('')
1197
- : '';
1198
- content = content.replace(dirBlockRegex, expanded);
1199
- }
1200
- await fs_1.promises.mkdir(agentideDir, { recursive: true });
1201
- await fs_1.promises.writeFile(contextFilePath, content, 'utf8');
1202
- outputChannel.appendLine(`[AgentIDE] Created context template: ${contextFilePath}`);
1203
- }
1204
- catch (e) {
1205
- outputChannel.appendLine(`[AgentIDE] Warning: failed to copy context template: ${e instanceof Error ? e.message : String(e)}`);
1206
- }
1207
- }
1208
- /**
1209
- * Ensure the active agent has a GHOST_TEXT.md (inline completions prompt).
1210
- * Only copies from bundled templates if the file doesn't already exist.
1211
- */
1212
- async ensureGhostTextPrompt(workspaceRoot, outputChannel) {
1213
- await this.ensureBundledPromptFile(workspaceRoot, paths_1.AGENT_CONSTANTS.GHOST_TEXT_FILE, outputChannel);
1214
- }
1215
- /**
1216
- * Ensure the active agent has a TERMINAL_ASSIST.md (terminal command assist prompt).
1217
- * Only copies from bundled templates if the file doesn't already exist.
1218
- */
1219
- async ensureTerminalAssistPrompt(workspaceRoot, outputChannel) {
1220
- await this.ensureBundledPromptFile(workspaceRoot, paths_1.AGENT_CONSTANTS.TERMINAL_ASSIST_FILE, outputChannel);
1221
- }
1222
- /**
1223
- * Ensure a bundled prompt file exists in the active agent's directory.
1224
- * Copies from base-prompts/ if the file doesn't already exist.
1225
- *
1226
- * IMPORTANT: Uses getActiveAgentId() to respect the active pack.
1227
- * See PLAN/ARCHITECTURE.md "Path Resolution Rules" for why this matters.
1228
- */
1229
- async ensureBundledPromptFile(workspaceRoot, fileName, outputChannel) {
1230
- const agentideDir = this.getAgentideProjectDir(workspaceRoot);
1231
- if (!(await (0, utils_1.pathExists)(agentideDir))) {
1232
- return;
1233
- }
1234
- // Use active agent ID - never hardcode 'default' for pack-specific paths
1235
- const activeAgentId = this.getActiveAgentId(workspaceRoot);
1236
- const agentDir = path.join(agentideDir, 'agents', activeAgentId);
1237
- const targetPath = path.join(agentDir, fileName);
1238
- if (await (0, utils_1.pathExists)(targetPath)) {
1239
- return; // Already exists - don't overwrite user edits
1240
- }
1241
- const bundledDir = this.getBundledBasePromptsDir();
1242
- const bundledPath = bundledDir ? path.join(bundledDir, fileName) : undefined;
1243
- if (!bundledPath || !(await (0, utils_1.pathExists)(bundledPath))) {
1244
- return;
1245
- }
1246
- try {
1247
- await fs_1.promises.mkdir(agentDir, { recursive: true });
1248
- const content = await fs_1.promises.readFile(bundledPath, 'utf8');
1249
- await fs_1.promises.writeFile(targetPath, content, 'utf8');
1250
- outputChannel.appendLine(`[AgentIDE] Created ${fileName}: ${targetPath}`);
1251
- }
1252
- catch (e) {
1253
- outputChannel.appendLine(`[AgentIDE] Warning: failed to copy ${fileName}: ${e instanceof Error ? e.message : String(e)}`);
1254
- }
1255
- }
1256
- // -------------------------------------------------------------------------
1257
- // Derived Directory Sync
1258
- // -------------------------------------------------------------------------
1259
- async importNewSkillsFromDerivedIntoAgentide(workspaceRoot, outputChannel, existingIngestState) {
1260
- // Ingest skills to the active agent's skills dir
1261
- const activeAgentId = this.getActiveAgentId(workspaceRoot);
1262
- const agentideSkillsDir = this.getAgentSkillsDir(workspaceRoot, activeAgentId);
1263
- const derivedSkillDirs = getDerivedEngineSyncTargets(workspaceRoot)
1264
- .filter(engine => engine.includeSkills)
1265
- .map(engine => path.join(workspaceRoot, engine.workspaceDir, 'skills'));
1266
- await fs_1.promises.mkdir(agentideSkillsDir, { recursive: true });
1267
- const ingestState = {
1268
- ...(existingIngestState ?? {}),
1269
- };
1270
- let agentideContentChanged = false;
1271
- let ingestStateChanged = false;
1272
- for (const derivedRoot of derivedSkillDirs) {
1273
- try {
1274
- const entries = await fs_1.promises.readdir(derivedRoot, { withFileTypes: true });
1275
- for (const entry of entries) {
1276
- if (!entry.isDirectory()) {
1277
- continue;
1278
- }
1279
- if (entry.name.startsWith('.')) {
1280
- continue;
1281
- }
1282
- const srcSkillDir = path.join(derivedRoot, entry.name);
1283
- const srcSkillFile = path.join(srcSkillDir, 'SKILL.md');
1284
- if (!(await (0, utils_1.pathExists)(srcSkillFile))) {
1285
- continue;
1286
- }
1287
- const dstSkillDir = path.join(agentideSkillsDir, entry.name);
1288
- const dstSkillFile = path.join(dstSkillDir, 'SKILL.md');
1289
- const { sha256: srcSha } = await (0, utils_1.readFileSha256)(srcSkillFile);
1290
- if (!(await (0, utils_1.pathExists)(dstSkillDir))) {
1291
- await (0, utils_1.copyDirRecursive)(srcSkillDir, dstSkillDir);
1292
- agentideContentChanged = true;
1293
- ingestState[entry.name] = {
1294
- lastIngestedSkillMdSha256: srcSha,
1295
- lastIngestedAt: new Date().toISOString(),
1296
- };
1297
- ingestStateChanged = true;
1298
- outputChannel.appendLine(`[AgentIDE] Imported new skill from derived dir: ${entry.name} → ${activeAgentId}`);
1299
- continue;
1300
- }
1301
- if (!(await (0, utils_1.pathExists)(dstSkillFile))) {
1302
- continue;
1303
- }
1304
- const { sha256: dstSha } = await (0, utils_1.readFileSha256)(dstSkillFile);
1305
- const state = ingestState[entry.name];
1306
- if (!state && srcSha === dstSha) {
1307
- ingestState[entry.name] = {
1308
- lastIngestedSkillMdSha256: dstSha,
1309
- lastIngestedAt: new Date().toISOString(),
1310
- };
1311
- ingestStateChanged = true;
1312
- continue;
1313
- }
1314
- if (!state) {
1315
- continue;
1316
- }
1317
- if (dstSha !== state.lastIngestedSkillMdSha256) {
1318
- outputChannel.appendLine(`[AgentIDE] Skipped ingest for skill '${entry.name}' (conflict: .agentide diverged from last ingested state)`);
1319
- continue;
1320
- }
1321
- if (srcSha !== dstSha) {
1322
- await fs_1.promises.copyFile(srcSkillFile, dstSkillFile);
1323
- agentideContentChanged = true;
1324
- ingestState[entry.name] = {
1325
- lastIngestedSkillMdSha256: srcSha,
1326
- lastIngestedAt: new Date().toISOString(),
1327
- };
1328
- ingestStateChanged = true;
1329
- outputChannel.appendLine(`[AgentIDE] Ingested updated SKILL.md from derived dir: ${entry.name}`);
1330
- }
1331
- }
1332
- }
1333
- catch {
1334
- // ignore
1335
- }
1336
- }
1337
- return { agentideContentChanged, ingestStateChanged, nextIngestState: ingestState };
1338
- }
1339
- async readAgentideContextMd(workspaceRoot) {
1340
- const activeAgentId = this.getActiveAgentId(workspaceRoot);
1341
- const contextFilePath = this.getAgentContextFile(workspaceRoot, activeAgentId);
1342
- try {
1343
- return await fs_1.promises.readFile(contextFilePath, 'utf8');
1344
- }
1345
- catch (e) {
1346
- if ((0, utils_1.getErrorCode)(e) === 'ENOENT') {
1347
- return undefined;
1348
- }
1349
- throw e;
1350
- }
1351
- }
1352
- async writeDerivedDirReadme(targetDir, providerId, outputChannel, sourceOfTruthLines) {
1353
- try {
1354
- const readmePath = path.join(targetDir, AGENTIDE_DERIVED_DIR_README);
1355
- const providerName = providerId.charAt(0).toUpperCase() + providerId.slice(1);
1356
- const sourceLines = (sourceOfTruthLines && sourceOfTruthLines.length > 0)
1357
- ? sourceOfTruthLines
1358
- : [
1359
- '- `.agentide/agents/<agentId>/AGENTS.md` (project rules)',
1360
- '- `.agentide/agents/<agentId>/rules/*.md` (additional rule fragments)',
1361
- '- `.agentide/agents/<agentId>/skills/*/SKILL.md` (project skills)',
1362
- ];
1363
- const contents = [
1364
- `# Managed by ${branding_1.AGENTIDE_BRAND_NAME}`,
1365
- '',
1366
- `This directory is managed by the ${branding_1.AGENTIDE_BRAND_NAME} extension.`,
1367
- '',
1368
- '## How It Works',
1369
- '',
1370
- '- **Skills** created here ARE synced back to `.agentide/agents/<id>/skills/`',
1371
- '- **Rules files** (`CLAUDE.md`, `AGENTS.md`) are generated from the source and **not synced back**',
1372
- ' - Edit rules in `.agentide/agents/<id>/AGENTS.md` instead',
1373
- '- The source-of-truth is in:',
1374
- ...sourceLines,
1375
- '',
1376
- '## Tips',
1377
- '',
1378
- '- Create/edit skills here or in `.agentide/` - both will stay in sync',
1379
- '- To change project rules, edit `.agentide/agents/<id>/AGENTS.md` (not the rules file here)',
1380
- '- This folder exists for ' + providerName + ' auto-discovery compatibility',
1381
- '',
1382
- ].join('\n');
1383
- await (0, utils_1.writeFileIfChanged)(readmePath, contents);
1384
- }
1385
- catch (e) {
1386
- outputChannel.appendLine(`[AgentIDE] Warning: failed to write ${providerId} derived README: ${e instanceof Error ? e.message : String(e)}`);
1387
- }
1388
- }
1389
- async cleanDerivedRulesDir(rulesDir) {
1390
- try {
1391
- const existing = await fs_1.promises.readdir(rulesDir, { withFileTypes: true });
1392
- const rmOps = existing
1393
- .filter(e => e.isFile() && e.name.toLowerCase().endsWith('.md'))
1394
- .map(e => fs_1.promises.rm(path.join(rulesDir, e.name), { force: true }));
1395
- await Promise.all(rmOps);
1396
- }
1397
- catch {
1398
- // ignore
1399
- }
1400
- }
1401
- async syncAgentideProjectToDerivedDirs(workspaceRoots, outputChannel, agentIdOverride) {
1402
- const roots = Array.from(new Set(workspaceRoots.map(r => r.trim()).filter(Boolean)));
1403
- for (const root of roots) {
1404
- if (!root || root === os.homedir()) {
1405
- continue;
1406
- }
1407
- const agentideDir = this.getAgentideProjectDir(root);
1408
- // Use override if provided, otherwise read from manifest
1409
- const activeAgentId = agentIdOverride ?? this.getActiveAgentId(root);
1410
- const agentideSkillsDir = this.getAgentSkillsDir(root, activeAgentId);
1411
- const agentideRulesDir = this.getAgentRulesDir(root, activeAgentId);
1412
- const agentideAgentsFile = this.getAgentAgentsFile(root, activeAgentId);
1413
- if (!(await (0, utils_1.pathExists)(agentideDir))) {
1414
- continue;
1415
- }
1416
- // Build derived directory paths from built-in and custom engine manifests.
1417
- const derivedDirs = getDerivedEngineSyncTargets(root).map(engine => ({
1418
- id: engine.id,
1419
- displayName: engine.displayName,
1420
- workspaceDir: engine.workspaceDir,
1421
- rulesFile: engine.rulesFile,
1422
- managedPaths: engine.managedPaths,
1423
- includeSkills: engine.includeSkills,
1424
- includeRules: engine.includeRules,
1425
- fullPath: path.join(root, engine.workspaceDir),
1426
- rulesPath: path.join(root, engine.workspaceDir, 'rules'),
1427
- skillsPath: path.join(root, engine.workspaceDir, 'skills'),
1428
- }));
1429
- const sourceOfTruthLines = [
1430
- `- \`.agentide/agents/${activeAgentId}/AGENTS.md\` (project rules)`,
1431
- `- \`.agentide/agents/${activeAgentId}/rules/*.md\` (additional rule fragments)`,
1432
- `- \`.agentide/agents/${activeAgentId}/skills/*/SKILL.md\` (project skills)`,
1433
- ];
1434
- // Phase 1: Create base directories
1435
- await Promise.all(derivedDirs.map(d => fs_1.promises.mkdir(d.fullPath, { recursive: true })));
1436
- // Phase 2: Write READMEs and create rules dirs
1437
- await Promise.all(derivedDirs.flatMap(d => [
1438
- this.writeDerivedDirReadme(d.fullPath, d.id, outputChannel, sourceOfTruthLines),
1439
- fs_1.promises.mkdir(d.rulesPath, { recursive: true }),
1440
- ]));
1441
- // Phase 3: Write combined rules files
1442
- const writeAgentsOps = [];
1443
- const agentsFileExists = await (0, utils_1.pathExists)(agentideAgentsFile);
1444
- if (agentsFileExists) {
1445
- const [agentsContent, contextContent] = await Promise.all([
1446
- fs_1.promises.readFile(agentideAgentsFile, 'utf8'),
1447
- this.readAgentideContextMd(root),
1448
- ]);
1449
- let combined = (0, branding_1.applyBrandingTokens)(agentsContent).trimEnd();
1450
- if (contextContent) {
1451
- combined += '\n\n---\n\n' + contextContent.trimEnd() + '\n';
1452
- }
1453
- else {
1454
- combined += '\n';
1455
- }
1456
- // Write rules file to each derived provider directory
1457
- for (const d of derivedDirs) {
1458
- writeAgentsOps.push((0, utils_1.writeFileIfChanged)(path.join(d.fullPath, d.rulesFile), combined));
1459
- }
1460
- }
1461
- await Promise.all([
1462
- ...writeAgentsOps,
1463
- ...derivedDirs.filter(d => d.includeRules).map(d => this.cleanDerivedRulesDir(d.rulesPath)),
1464
- ]);
1465
- // Phase 4: Mirror .agentide/rules/*.md to each derived provider
1466
- if (await (0, utils_1.pathExists)(agentideRulesDir)) {
1467
- const entries = await fs_1.promises.readdir(agentideRulesDir, { withFileTypes: true });
1468
- const ruleOps = entries
1469
- .filter(e => e.isFile() && e.name.toLowerCase().endsWith('.md'))
1470
- .flatMap(entry => {
1471
- const src = path.join(agentideRulesDir, entry.name);
1472
- return derivedDirs.filter(d => d.includeRules).map(d => (0, utils_1.symlinkOrCopyFile)(src, path.join(d.rulesPath, entry.name), outputChannel, `Rule ${entry.name} -> ${d.workspaceDir}`, { force: true }));
1473
- });
1474
- await Promise.all(ruleOps);
1475
- }
1476
- // Phase 5: Ensure skills directories exist
1477
- await Promise.all(derivedDirs.filter(d => d.includeSkills).map(d => (0, utils_1.ensureRealDirectory)(d.skillsPath)));
1478
- // Phase 6: Sync skills via file-level links
1479
- if (await (0, utils_1.pathExists)(agentideSkillsDir)) {
1480
- const entries = await fs_1.promises.readdir(agentideSkillsDir, { withFileTypes: true });
1481
- const expectedSkills = [];
1482
- for (const entry of entries) {
1483
- if (!entry.isDirectory() || entry.name.startsWith('.')) {
1484
- continue;
1485
- }
1486
- const srcSkillMd = path.join(agentideSkillsDir, entry.name, 'SKILL.md');
1487
- if (!(await (0, utils_1.pathExists)(srcSkillMd))) {
1488
- continue;
1489
- }
1490
- expectedSkills.push(entry.name);
1491
- }
1492
- const expectedSet = new Set(expectedSkills);
1493
- const syncOneDerivedSkillsDir = async (dstSkillsRoot, label) => {
1494
- try {
1495
- const existing = await fs_1.promises.readdir(dstSkillsRoot, { withFileTypes: true });
1496
- const rmOps = [];
1497
- for (const e of existing) {
1498
- if (!e.isDirectory() && !e.isSymbolicLink()) {
1499
- continue;
1500
- }
1501
- if (e.name.startsWith('.')) {
1502
- continue;
1503
- }
1504
- if (!expectedSet.has(e.name)) {
1505
- rmOps.push(fs_1.promises.rm(path.join(dstSkillsRoot, e.name), { recursive: true, force: true }));
1506
- }
1507
- }
1508
- await Promise.all(rmOps);
1509
- }
1510
- catch {
1511
- // ignore
1512
- }
1513
- for (const skillName of expectedSkills) {
1514
- const srcSkill = path.join(agentideSkillsDir, skillName);
1515
- const dstSkill = path.join(dstSkillsRoot, skillName);
1516
- await (0, utils_1.syncDirByFileLinks)(srcSkill, dstSkill, outputChannel, `${label}/skills/${skillName}`);
1517
- }
1518
- };
1519
- await Promise.all(derivedDirs.filter(d => d.includeSkills).map(d => syncOneDerivedSkillsDir(d.skillsPath, d.workspaceDir)));
1520
- }
1521
- }
1522
- }
1523
- // -------------------------------------------------------------------------
1524
- // AgentPack Support
1525
- // -------------------------------------------------------------------------
1526
- /**
1527
- * Sync derived directories for an agent pack.
1528
- * Creates .codex/ and .claude/ within the pack folder with synced content.
1529
- */
1530
- async syncPackDerivedDirs(packRoot, outputChannel) {
1531
- if (!packRoot || !(await (0, utils_1.pathExists)(packRoot))) {
1532
- return;
1533
- }
1534
- const agentsFile = path.join(packRoot, 'AGENTS.md');
1535
- const rulesDir = path.join(packRoot, 'rules');
1536
- const skillsDir = path.join(packRoot, 'skills');
1537
- // Build derived directory paths from built-in and custom engine manifests.
1538
- const derivedDirs = getDerivedEngineSyncTargets(packRoot).map(engine => ({
1539
- id: engine.id,
1540
- workspaceDir: engine.workspaceDir,
1541
- rulesFile: engine.rulesFile,
1542
- includeSkills: engine.includeSkills,
1543
- includeRules: engine.includeRules,
1544
- fullPath: path.join(packRoot, engine.workspaceDir),
1545
- rulesPath: path.join(packRoot, engine.workspaceDir, 'rules'),
1546
- skillsPath: path.join(packRoot, engine.workspaceDir, 'skills'),
1547
- }));
1548
- // Phase 1: Create base directories
1549
- await Promise.all(derivedDirs.map(d => fs_1.promises.mkdir(d.fullPath, { recursive: true })));
1550
- // Phase 2: Create rules dirs
1551
- await Promise.all(derivedDirs.map(d => fs_1.promises.mkdir(d.rulesPath, { recursive: true })));
1552
- // Phase 3: Write rules files
1553
- if (await (0, utils_1.pathExists)(agentsFile)) {
1554
- const agentsContent = (0, branding_1.applyBrandingTokens)(await fs_1.promises.readFile(agentsFile, 'utf8'));
1555
- const contextFile = path.join(packRoot, 'context.md');
1556
- let combined = agentsContent.trimEnd();
1557
- if (await (0, utils_1.pathExists)(contextFile)) {
1558
- const contextContent = await fs_1.promises.readFile(contextFile, 'utf8');
1559
- combined += '\n\n---\n\n' + contextContent.trimEnd() + '\n';
1560
- }
1561
- else {
1562
- combined += '\n';
1563
- }
1564
- for (const d of derivedDirs) {
1565
- await (0, utils_1.writeFileIfChanged)(path.join(d.fullPath, d.rulesFile), combined);
1566
- }
1567
- }
1568
- // Phase 4: Symlink rules
1569
- if (await (0, utils_1.pathExists)(rulesDir)) {
1570
- const entries = await fs_1.promises.readdir(rulesDir, { withFileTypes: true });
1571
- for (const entry of entries) {
1572
- if (!entry.isFile() || !entry.name.toLowerCase().endsWith('.md')) {
1573
- continue;
1574
- }
1575
- const src = path.join(rulesDir, entry.name);
1576
- for (const d of derivedDirs.filter(d => d.includeRules)) {
1577
- await (0, utils_1.symlinkOrCopyFile)(src, path.join(d.rulesPath, entry.name), outputChannel, `Pack rule ${entry.name}`, { force: true });
1578
- }
1579
- }
1580
- }
1581
- // Phase 5: Ensure skills directories exist
1582
- await Promise.all(derivedDirs.filter(d => d.includeSkills).map(d => (0, utils_1.ensureRealDirectory)(d.skillsPath)));
1583
- // Phase 6: Sync skills
1584
- if (await (0, utils_1.pathExists)(skillsDir)) {
1585
- const entries = await fs_1.promises.readdir(skillsDir, { withFileTypes: true });
1586
- for (const entry of entries) {
1587
- if (!entry.isDirectory() || entry.name.startsWith('.')) {
1588
- continue;
1589
- }
1590
- const srcSkill = path.join(skillsDir, entry.name);
1591
- for (const d of derivedDirs.filter(d => d.includeSkills)) {
1592
- await (0, utils_1.syncDirByFileLinks)(srcSkill, path.join(d.skillsPath, entry.name), outputChannel, `Pack skill ${entry.name}`);
1593
- }
1594
- }
1595
- }
1596
- outputChannel.appendLine(`[AgentPack] Synced derived dirs for pack at ${packRoot}`);
1597
- }
1598
- /**
1599
- * Switch the workspace's .claude/ and .codex/ to use content from the specified pack.
1600
- * If packId is undefined or 'default', syncs from .agentide/ (default agent).
1601
- * Otherwise, syncs from .agentide/agents/{packId}/.
1602
- *
1603
- * This replaces the content of workspace-root derived directories with the pack's content.
1604
- *
1605
- * @param importDerivedSkills If true, import any new skills from derived dirs to the
1606
- * current pack's source before switching. This preserves agent-created skills.
1607
- */
1608
- async switchToPack(workspaceRoot, packId, outputChannel, options) {
1609
- // Import any new skills from derived dirs before switching
1610
- if (options?.importDerivedSkills) {
1611
- const manifest = await this.readAgentideManifest(workspaceRoot);
1612
- await this.importNewSkillsFromDerivedIntoAgentide(workspaceRoot, outputChannel, manifest?.derivedSkillIngestState);
1613
- }
1614
- if (!packId || packId === 'default') {
1615
- // Default agent: sync from .agentide/agents/default/
1616
- outputChannel.appendLine(`[AgentPack] Switching to default workspace agent`);
1617
- await this.syncAgentideProjectToDerivedDirs([workspaceRoot], outputChannel, 'default');
1618
- await this.seedAgentDataIfNeeded(workspaceRoot, AGENTIDE_DEFAULT_AGENT_ID, outputChannel);
1619
- await this.writeAgentideManifest(workspaceRoot, outputChannel, { packIdOverride: 'default' });
1620
- return undefined;
1621
- }
1622
- // Pack mode: sync from .agentide/agents/{packId}/
1623
- const packRoot = path.join(workspaceRoot, AGENTIDE_DIR_NAME, 'agents', packId);
1624
- if (!(await (0, utils_1.pathExists)(packRoot))) {
1625
- outputChannel.appendLine(`[AgentPack] Warning: Pack not found at ${packRoot}, falling back to default`);
1626
- await this.syncAgentideProjectToDerivedDirs([workspaceRoot], outputChannel, 'default');
1627
- await this.writeAgentideManifest(workspaceRoot, outputChannel, { packIdOverride: 'default' });
1628
- return undefined;
1629
- }
1630
- outputChannel.appendLine(`[AgentPack] Switching to pack: ${packId}`);
1631
- const agentsFile = path.join(packRoot, 'AGENTS.md');
1632
- const rulesDir = path.join(packRoot, 'rules');
1633
- const skillsDir = path.join(packRoot, 'skills');
1634
- // Build derived directory paths at WORKSPACE ROOT (not pack root)
1635
- const derivedDirs = getDerivedEngineSyncTargets(workspaceRoot).map(engine => ({
1636
- id: engine.id,
1637
- workspaceDir: engine.workspaceDir,
1638
- rulesFile: engine.rulesFile,
1639
- includeSkills: engine.includeSkills,
1640
- includeRules: engine.includeRules,
1641
- fullPath: path.join(workspaceRoot, engine.workspaceDir),
1642
- rulesPath: path.join(workspaceRoot, engine.workspaceDir, 'rules'),
1643
- skillsPath: path.join(workspaceRoot, engine.workspaceDir, 'skills'),
1644
- }));
1645
- const sourceOfTruthLines = [
1646
- `- \`.agentide/agents/${packId}/AGENTS.md\` (pack rules)`,
1647
- `- \`.agentide/agents/${packId}/rules/*.md\` (additional rule fragments)`,
1648
- `- \`.agentide/agents/${packId}/skills/*/SKILL.md\` (pack skills)`,
1649
- ];
1650
- // Phase 1: Create base directories
1651
- await Promise.all(derivedDirs.map(d => fs_1.promises.mkdir(d.fullPath, { recursive: true })));
1652
- // Phase 2: Write READMEs and create rules dirs
1653
- await Promise.all(derivedDirs.flatMap(d => [
1654
- this.writeDerivedDirReadme(d.fullPath, d.id, outputChannel, sourceOfTruthLines),
1655
- fs_1.promises.mkdir(d.rulesPath, { recursive: true }),
1656
- ]));
1657
- // Phase 3: Write combined rules files from pack's AGENTS.md
1658
- if (await (0, utils_1.pathExists)(agentsFile)) {
1659
- const agentsContent = (0, branding_1.applyBrandingTokens)(await fs_1.promises.readFile(agentsFile, 'utf8'));
1660
- const contextFile = path.join(packRoot, 'context.md');
1661
- let combined = agentsContent.trimEnd();
1662
- if (await (0, utils_1.pathExists)(contextFile)) {
1663
- const contextContent = await fs_1.promises.readFile(contextFile, 'utf8');
1664
- combined += '\n\n---\n\n' + contextContent.trimEnd() + '\n';
1665
- }
1666
- else {
1667
- combined += '\n';
1668
- }
1669
- for (const d of derivedDirs) {
1670
- await (0, utils_1.writeFileIfChanged)(path.join(d.fullPath, d.rulesFile), combined);
1671
- }
1672
- }
1673
- // Clean rules dirs before syncing
1674
- await Promise.all(derivedDirs.filter(d => d.includeRules).map(d => this.cleanDerivedRulesDir(d.rulesPath)));
1675
- // Phase 4: Symlink rules from pack
1676
- if (await (0, utils_1.pathExists)(rulesDir)) {
1677
- const entries = await fs_1.promises.readdir(rulesDir, { withFileTypes: true });
1678
- for (const entry of entries) {
1679
- if (!entry.isFile() || !entry.name.toLowerCase().endsWith('.md')) {
1680
- continue;
1681
- }
1682
- const src = path.join(rulesDir, entry.name);
1683
- for (const d of derivedDirs.filter(d => d.includeRules)) {
1684
- await (0, utils_1.symlinkOrCopyFile)(src, path.join(d.rulesPath, entry.name), outputChannel, `Pack rule ${entry.name}`, { force: true });
1685
- }
1686
- }
1687
- }
1688
- // Phase 5: Ensure skills directories exist and clean stale skills
1689
- await Promise.all(derivedDirs.filter(d => d.includeSkills).map(d => (0, utils_1.ensureRealDirectory)(d.skillsPath)));
1690
- // Phase 6: Sync skills from pack
1691
- if (await (0, utils_1.pathExists)(skillsDir)) {
1692
- const entries = await fs_1.promises.readdir(skillsDir, { withFileTypes: true });
1693
- const expectedSkills = [];
1694
- for (const entry of entries) {
1695
- if (!entry.isDirectory() || entry.name.startsWith('.')) {
1696
- continue;
1697
- }
1698
- const srcSkillMd = path.join(skillsDir, entry.name, 'SKILL.md');
1699
- if (!(await (0, utils_1.pathExists)(srcSkillMd))) {
1700
- continue;
1701
- }
1702
- expectedSkills.push(entry.name);
1703
- }
1704
- const expectedSet = new Set(expectedSkills);
1705
- // Remove skills not in pack
1706
- for (const d of derivedDirs.filter(d => d.includeSkills)) {
1707
- try {
1708
- const existing = await fs_1.promises.readdir(d.skillsPath, { withFileTypes: true });
1709
- for (const e of existing) {
1710
- if ((e.isDirectory() || e.isSymbolicLink()) && !expectedSet.has(e.name)) {
1711
- await fs_1.promises.rm(path.join(d.skillsPath, e.name), { recursive: true, force: true });
1712
- outputChannel.appendLine(`[AgentPack] Removed stale skill: ${e.name}`);
1713
- }
1714
- }
1715
- }
1716
- catch {
1717
- // Skills dir might not exist yet
1718
- }
1719
- }
1720
- // Sync pack skills
1721
- for (const skillName of expectedSkills) {
1722
- const srcSkill = path.join(skillsDir, skillName);
1723
- for (const d of derivedDirs.filter(d => d.includeSkills)) {
1724
- await (0, utils_1.syncDirByFileLinks)(srcSkill, path.join(d.skillsPath, skillName), outputChannel, `Pack skill ${skillName}`);
1725
- }
1726
- }
1727
- }
1728
- else {
1729
- // Pack has no skills - clear derived skills dirs
1730
- for (const d of derivedDirs.filter(d => d.includeSkills)) {
1731
- try {
1732
- const existing = await fs_1.promises.readdir(d.skillsPath, { withFileTypes: true });
1733
- for (const e of existing) {
1734
- if (e.isDirectory() || e.isSymbolicLink()) {
1735
- await fs_1.promises.rm(path.join(d.skillsPath, e.name), { recursive: true, force: true });
1736
- }
1737
- }
1738
- }
1739
- catch {
1740
- // Ignore
1741
- }
1742
- }
1743
- }
1744
- outputChannel.appendLine(`[AgentPack] Switched workspace to pack: ${packId}`);
1745
- await this.seedAgentDataIfNeeded(workspaceRoot, packId, outputChannel);
1746
- await this.writeAgentideManifest(workspaceRoot, outputChannel, { packIdOverride: packId });
1747
- return packId;
1748
- }
1749
- /**
1750
- * Load the agentide manifest for a workspace.
1751
- */
1752
- async loadAgentideManifest(workspaceRoot) {
1753
- const manifestPath = path.join(workspaceRoot, AGENTIDE_DIR_NAME, AGENTIDE_MANIFEST_FILE);
1754
- try {
1755
- const content = await fs_1.promises.readFile(manifestPath, 'utf8');
1756
- return JSON.parse(content);
1757
- }
1758
- catch {
1759
- return undefined;
1760
- }
1761
- }
1762
- // -------------------------------------------------------------------------
1763
- // Installed Agents (separate file: installed-agents.json)
1764
- // -------------------------------------------------------------------------
1765
- getInstalledAgentsFilePath(workspaceRoot) {
1766
- return path.join(workspaceRoot, AGENTIDE_DIR_NAME, AGENTIDE_INSTALLED_AGENTS_FILE);
1767
- }
1768
- /**
1769
- * Load installed agents from the dedicated file.
1770
- */
1771
- async loadInstalledAgents(workspaceRoot) {
1772
- const filePath = this.getInstalledAgentsFilePath(workspaceRoot);
1773
- try {
1774
- const content = await fs_1.promises.readFile(filePath, 'utf8');
1775
- const data = JSON.parse(content);
1776
- return data.agents ?? [];
1777
- }
1778
- catch {
1779
- return [];
1780
- }
1781
- }
1782
- /**
1783
- * Save installed agents to the dedicated file.
1784
- */
1785
- async saveInstalledAgents(workspaceRoot, agents) {
1786
- const filePath = this.getInstalledAgentsFilePath(workspaceRoot);
1787
- const data = {
1788
- version: 1,
1789
- agents,
1790
- };
1791
- await fs_1.promises.mkdir(path.dirname(filePath), { recursive: true });
1792
- await fs_1.promises.writeFile(filePath, JSON.stringify(data, null, 2));
1793
- }
1794
- /**
1795
- * Update or add an installed agent.
1796
- */
1797
- async updateInstalledAgent(workspaceRoot, agent, outputChannel) {
1798
- const agents = await this.loadInstalledAgents(workspaceRoot);
1799
- // Remove existing entry if present
1800
- const filtered = agents.filter(a => a.id !== agent.id);
1801
- // Add new entry
1802
- const entry = {
1803
- id: agent.id,
1804
- version: agent.version,
1805
- source: agent.source,
1806
- installedAt: new Date().toISOString(),
1807
- featureSetHash: agent.featureSetHash,
1808
- preferredEngine: agent.preferredEngine,
1809
- preferredModel: agent.preferredModel,
1810
- preferredCheapModel: agent.preferredCheapModel,
1811
- status: 'active',
1812
- };
1813
- filtered.push(entry);
1814
- await this.saveInstalledAgents(workspaceRoot, filtered);
1815
- (0, utils_1.logInfo)(outputChannel, `[Agent] Registered agent: ${agent.id}`);
1816
- }
1817
- /**
1818
- * Remove an installed agent.
1819
- */
1820
- async removeInstalledAgent(workspaceRoot, agentId, outputChannel) {
1821
- const agents = await this.loadInstalledAgents(workspaceRoot);
1822
- const filtered = agents.filter(a => a.id !== agentId);
1823
- if (filtered.length !== agents.length) {
1824
- await this.saveInstalledAgents(workspaceRoot, filtered);
1825
- (0, utils_1.logInfo)(outputChannel, `[Agent] Removed agent: ${agentId}`);
1826
- }
1827
- }
1828
- }
1829
- exports.SyncService = SyncService;
1
+ /*! Copyright (c) 2026 AgentHippo.ai. All rights reserved. Proprietary; see LICENSE. */
2
+ "use strict";var __createBinding=this&&this.__createBinding||(Object.create?(function(y,e,t,i){i===void 0&&(i=t);var s=Object.getOwnPropertyDescriptor(e,t);(!s||("get"in s?!e.__esModule:s.writable||s.configurable))&&(s={enumerable:!0,get:function(){return e[t]}}),Object.defineProperty(y,i,s)}):(function(y,e,t,i){i===void 0&&(i=t),y[i]=e[t]})),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?(function(y,e){Object.defineProperty(y,"default",{enumerable:!0,value:e})}):function(y,e){y.default=e}),__importStar=this&&this.__importStar||(function(){var y=function(e){return y=Object.getOwnPropertyNames||function(t){var i=[];for(var s in t)Object.prototype.hasOwnProperty.call(t,s)&&(i[i.length]=s);return i},y(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var i=y(e),s=0;s<i.length;s++)i[s]!=="default"&&__createBinding(t,e,i[s]);return __setModuleDefault(t,e),t}})();Object.defineProperty(exports,"__esModule",{value:!0}),exports.SyncService=void 0;const vscode=__importStar(require("vscode")),fs_1=require("fs"),path=__importStar(require("path")),os=__importStar(require("os")),utils_1=require("./utils"),remoteSkills_1=require("./remoteSkills"),branding_1=require("./branding"),paths_1=require("./agentpack/paths"),manifest_1=require("./agentpack/manifest"),mcp_1=require("./mcp"),customRegistry_1=require("./engines/customRegistry"),AGENTIDE_DERIVED_DIR_README="AGENTIDE_README.md",AGENTIDE_CONTEXT_FILE="context.md",AGENTIDE_MANIFEST_FILE="agentide.manifest.json",AGENTIDE_INSTALLED_AGENTS_FILE="installed-agents.json",AGENTIDE_MANIFEST_DEBOUNCE_MS=2e3,AGENTIDE_AGENT_YAML="agent.yaml",AGENTIDE_AGENTS_DIR="agents",AGENTIDE_DEFAULT_AGENT_ID="default",AGENTIDE_DIR_NAME=paths_1.AGENT_CONSTANTS.AGENTIDE_DIR_NAME,shared_1=require("./shared");function getConfiguredAdditionalEngineDir(){return vscode.workspace.getConfiguration("agentide").get("additionalEngineDir")}function getDerivedEngineSyncTargets(y){const e=Object.values(shared_1.AGENT_ENGINES).map(i=>({id:i.id,displayName:i.displayName,workspaceDir:i.workspaceDir,rulesFile:i.rulesFile,managedPaths:i.managedPaths,includeSkills:!0,includeRules:!0})),t=(0,customRegistry_1.discoverCustomEngineManifests)(y,getConfiguredAdditionalEngineDir()).filter(i=>i.workspaceSync?.enabled).map(i=>({id:i.id,displayName:i.displayName??i.id,workspaceDir:i.workspaceSync.dir,rulesFile:i.workspaceSync.rulesFile,includeSkills:i.workspaceSync.includeSkills,includeRules:i.workspaceSync.includeRules}));return[...e,...t]}function getSkillDirNameFromRelPath(y){const t=y.replace(/\\/g,"/").split("/").filter(Boolean),i=t.indexOf("skills");if(i!==-1&&t.length>i+1)return t[i+1];if(t.length>=3&&t[0]==="skills")return t[1]}function parseSkillYamlHeader(y){const e={};if(!y.startsWith("---"))return e;const t=y.split(`
3
+ `);let i=-1;for(let s=1;s<t.length;s++)if(t[s].trim()==="---"){i=s;break}if(i===-1)return e;for(let s=1;s<i;s++){const l=t[s],o=l.indexOf(":");if(o===-1)continue;const n=l.substring(0,o).trim().toLowerCase();let a=l.substring(o+1).trim();(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),n==="name"&&a?e.name=a:n==="description"&&a&&(e.description=a)}return e}function parseYaml(y){return require("js-yaml").load(y)}function dumpYaml(y){return require("js-yaml").dump(y,{lineWidth:120,noRefs:!0})}async function isDirEmpty(y){return(await fs_1.promises.readdir(y)).length===0}class SyncService{getBundledBasePromptsDir;lastAgentideSyncSignatureByRoot=new Map;agentideSignatureByRoot=new Map;agentideSkillsSignatureByRoot=new Map;agentideRootUpdateState=new Map;agentideWatchersByRoot=new Map;activeAgentTurns=0;activePackIdByRoot=new Map;activeAgentManifestCache=new Map;constructor(e){this.getBundledBasePromptsDir=e}setActivePackId(e,t){this.activePackIdByRoot.set(e,t)}getActivePackId(e){return this.activePackIdByRoot.get(e)}incrementActiveAgentTurns(){this.activeAgentTurns++}decrementActiveAgentTurns(){this.activeAgentTurns=Math.max(0,this.activeAgentTurns-1)}getSkillsSignature(e){return this.agentideSkillsSignatureByRoot.get(e)}async computeWorkspaceAgentideSignature(e,t){const i=vscode.workspace.workspaceFolders?.map(n=>n.uri.fsPath)??[],s=(t??[]).filter(n=>i.includes(n)),l=Array.from(new Set([e,...s].map(n=>n.trim()).filter(Boolean))).filter(n=>n!==os.homedir()),o=[];for(const n of l){let a=this.agentideSignatureByRoot.get(n);a||(a=(await this.readAgentideManifest(n))?.agentideSignature,a&&this.agentideSignatureByRoot.set(n,a)),o.push([n,a??"missing"])}return o.sort((n,a)=>n[0].localeCompare(a[0])),(0,utils_1.shortSig)(JSON.stringify(o))}getManagedResources(e,t,i){const s=[],l=Array.from(new Set(i.map(a=>a.trim()).filter(Boolean))).filter(a=>a!==os.homedir()),o={codexHome:e,claudeConfigDir:t},n={CODEX_HOME:"codexHome",CLAUDE_CONFIG_DIR:"claudeConfigDir"};for(const a of Object.values(shared_1.AGENT_ENGINES)){const r=a.configEnvVar?n[a.configEnvVar]:void 0,d=r?o[r]:void 0;if(d)if(a.managedPaths?.length)for(const c of a.managedPaths){const g=!c.includes(".");s.push({path:path.join(d,c),type:g?"directory":"generated",description:`${a.displayName} ${c} (managed by AgentIDE)`,safeToDelete:!0})}else s.push({path:d,type:"directory",description:`${a.displayName} config dir (managed by AgentIDE)`,safeToDelete:!0})}for(const a of l){s.push({path:path.join(a,AGENTIDE_DIR_NAME),type:"directory",description:"AgentIDE project rules & skills (source-of-truth)",safeToDelete:!1});for(const r of getDerivedEngineSyncTargets(a))s.push({path:path.join(a,r.workspaceDir),type:"directory",description:`${r.displayName} project folder (derived/overwritten from ${AGENTIDE_DIR_NAME}/)`,safeToDelete:!0})}return s}async writeManagedPathsManifest(e,t,i,s,l){if(!i||i===os.homedir())return;const o=this.getAgentideProjectDir(i),n=path.join(o,"paths.md"),a=this.getManagedResources(e,t,[i,...s??[]]),r=["# AgentIDE Managed Resources","","This file lists all files and directories managed by the AgentIDE extension.","**Auto-generated** - Do not edit manually.","",`**Workspace:** \`${i}\``,e?`**Codex Home:** \`${e}\``:"",t?`**Claude Config Dir:** \`${t}\``:"","","## Resources","","| Path | Type | Safe to Delete | Description |","|------|------|----------------|-------------|"];for(const d of a){const g=await(0,utils_1.pathExists)(d.path)?"[x]":"[ ]";r.push(`| ${g} \`${d.path}\` | ${d.type} | ${d.safeToDelete?"Yes":"No"} | ${d.description} |`)}r.push(""),r.push("## How to Reset"),r.push(""),r.push("Run the command: **AgentIDE: Clear Managed Resources**"),r.push(""),r.push("This will:"),r.push("- Remove symlinks created by the extension"),r.push("- Delete generated files (context.md, config.toml, etc.)"),r.push(`- **NOT** delete user-managed rules/skills inside \`${AGENTIDE_DIR_NAME}/\``),r.push(""),await fs_1.promises.mkdir(o,{recursive:!0}),await(0,utils_1.writeFileIfChanged)(n,r.filter(Boolean).join(`
4
+ `)),l.appendLine(`[AgentIDE] Wrote manifest: ${n}`)}async clearManagedResources(e,t,i,s,l){const o=this.getManagedResources(e,t,[i??"",...s??[]]),n=[],a=[],r=[];for(const d of o){if(!d.safeToDelete){a.push(d.path);continue}try{const c=await fs_1.promises.lstat(d.path);d.type==="symlink"?c.isSymbolicLink()?(await fs_1.promises.unlink(d.path),n.push(d.path),l.appendLine(`[AgentIDE] Removed symlink: ${d.path}`)):(a.push(d.path),l.appendLine(`[AgentIDE] Skipped (not a symlink): ${d.path}`)):d.type==="generated"?c.isFile()&&(await fs_1.promises.unlink(d.path),n.push(d.path),l.appendLine(`[AgentIDE] Removed generated file: ${d.path}`)):d.type==="directory"&&d.safeToDelete&&c.isDirectory()&&(await fs_1.promises.rm(d.path,{recursive:!0,force:!0}),n.push(d.path),l.appendLine(`[AgentIDE] Removed directory: ${d.path}`))}catch(c){(0,utils_1.getErrorCode)(c)!=="ENOENT"&&r.push(`${d.path}: ${c instanceof Error?c.message:String(c)}`)}}return this.lastAgentideSyncSignatureByRoot.clear(),this.agentideSignatureByRoot.clear(),this.agentideSkillsSignatureByRoot.clear(),{cleared:n,skipped:a,errors:r}}getAgentideProjectDir(e){return(0,paths_1.getAgentideDir)(e)}getAgentsDir(e){return path.join(this.getAgentideProjectDir(e),AGENTIDE_AGENTS_DIR)}getAgentRoot(e,t){return path.join(this.getAgentsDir(e),t)}getAgentSkillsDir(e,t){return path.join(this.getAgentRoot(e,t),"skills")}getAgentRulesDir(e,t){return path.join(this.getAgentRoot(e,t),"rules")}getAgentAgentsFile(e,t){return path.join(this.getAgentRoot(e,t),"AGENTS.md")}getAgentContextFile(e,t){return path.join(this.getAgentRoot(e,t),AGENTIDE_CONTEXT_FILE)}getActiveAgentId(e){return this.getActivePackId(e)??AGENTIDE_DEFAULT_AGENT_ID}async resolveManifestSource(e,t){const i=t??this.getActiveAgentId(e),s=this.getAgentRoot(e,i);return{agentId:i,isPack:i!==AGENTIDE_DEFAULT_AGENT_ID,agentRoot:s,agentsFile:this.getAgentAgentsFile(e,i),contextFile:this.getAgentContextFile(e,i),rulesDir:this.getAgentRulesDir(e,i),skillsDir:this.getAgentSkillsDir(e,i),agentYamlPath:path.join(s,AGENTIDE_AGENT_YAML)}}async getDataPathsForAgent(e,t,i){const s=this.getAgentRoot(e,t),l=path.join(s,AGENTIDE_AGENT_YAML);if(await(0,utils_1.pathExists)(l))try{const n=(await(0,manifest_1.loadAgentManifest)(l)).spec?.data;if(!n)return;const a=n.sourcePath?.trim()||"./data",r=(n.workspacePath?.trim()||`.${path.sep}${AGENTIDE_DIR_NAME}${path.sep}data${path.sep}${t}`).replace(/^(?:\.\/|\.\\)/,""),d=path.resolve(s,a),c=path.resolve(e,r);return{sourceDir:d,targetDir:c}}catch(o){(0,utils_1.logInfo)(i,`[AgentIDE] Skipping data sync for ${t}: failed to parse data config (${o instanceof Error?o.message:String(o)})`);return}}async seedAgentDataIfNeeded(e,t,i){const s=await this.getDataPathsForAgent(e,t,i);if(!s)return;const{sourceDir:l,targetDir:o}=s;if(await(0,utils_1.pathExists)(l)){if(!await(0,utils_1.pathExists)(o)){await(0,utils_1.copyDirRecursive)(l,o),(0,utils_1.logInfo)(i,`[AgentIDE] Seeded pack data for ${t}: ${o}`);return}try{if(!(await fs_1.promises.stat(o)).isDirectory())return}catch{return}await isDirEmpty(o)&&(await(0,utils_1.copyDirRecursive)(l,o),(0,utils_1.logInfo)(i,`[AgentIDE] Seeded pack data for ${t}: ${o}`))}}async syncAgentYamlSkills(e,t,i,s){const l=path.join(this.getAgentRoot(e,t),AGENTIDE_AGENT_YAML);if(await(0,utils_1.pathExists)(l))try{const o=await fs_1.promises.readFile(l,"utf8"),n=parseYaml(o);if(!n||typeof n!="object")return;const a=n,r=i.skills.map(c=>({path:`./skills/${c.dirName}`}));a.spec={...a.spec??{},skills:r};const d=dumpYaml(a);await(0,utils_1.writeFileIfChanged)(l,d)}catch(o){s.appendLine(`[AgentIDE] Warning: failed to update agent.yaml skills for ${t}: ${o instanceof Error?o.message:String(o)}`)}}async getActiveAgentManifest(e,t,i){const s=i??this.getActiveAgentId(e),l=path.join(this.getAgentRoot(e,s),AGENTIDE_AGENT_YAML),o=await(0,utils_1.getFileStats)(l);if(!o){const a=this.activeAgentManifestCache.get(l);a?.loggedNoManifest||t.appendLine(`[AgentIDE] No agent.yaml found for agent ${s}`),this.activeAgentManifestCache.set(l,{mtimeMs:-1,size:-1,manifest:void 0,loggedNoManifest:!0,loggedInvalid:a?.loggedInvalid??!1});return}const n=this.activeAgentManifestCache.get(l);if(n&&n.mtimeMs===o.mtimeMs&&n.size===o.size)return n.manifest;try{const a=await fs_1.promises.readFile(l,"utf8"),r=parseYaml(a);if(!r?.metadata?.name||!r?.spec?.engine){n?.loggedInvalid||t.appendLine(`[AgentIDE] Invalid agent.yaml for agent ${s}: missing required fields`),this.activeAgentManifestCache.set(l,{mtimeMs:o.mtimeMs,size:o.size,manifest:void 0,loggedNoManifest:!1,loggedInvalid:!0});return}return this.activeAgentManifestCache.set(l,{mtimeMs:o.mtimeMs,size:o.size,manifest:r,loggedNoManifest:!1,loggedInvalid:!1}),r}catch(a){n?.loggedInvalid||t.appendLine(`[AgentIDE] Failed to parse agent.yaml for agent ${s}: ${a instanceof Error?a.message:String(a)}`),this.activeAgentManifestCache.set(l,{mtimeMs:o.mtimeMs,size:o.size,manifest:void 0,loggedNoManifest:!1,loggedInvalid:!0});return}}getAgentideManifestFilePath(e){return path.join(this.getAgentideProjectDir(e),AGENTIDE_MANIFEST_FILE)}async allDerivedDirsPresent(e){return(await Promise.all(getDerivedEngineSyncTargets(e).map(i=>(0,utils_1.isDirOrSymlink)(path.join(e,i.workspaceDir))))).every(Boolean)}async readAgentideManifest(e){const t=this.getAgentideManifestFilePath(e);try{const i=await fs_1.promises.readFile(t,"utf8"),s=JSON.parse(i);return s.version!==1||typeof s.agentideSignature!="string"?void 0:s}catch(i){return(0,utils_1.getErrorCode)(i)==="ENOENT",void 0}}async computeAgentideManifest(e,t,i){const s=t.rulesDir,l=t.skillsDir,o=new Map,n=new Map;if(i){for(const m of i.rules)o.set(m.relPath,m);for(const m of i.skills){const u=m.dirName||getSkillDirNameFromRelPath(m.skillMdRelPath)||m.name;n.set(u,m)}}const a=[],r=[],d=async(m,u)=>{const E=await(0,utils_1.getFileStats)(m);if(!E)return;const w=o.get(u),D=(0,utils_1.isCachedHashValid)(w,E);if(D)return D;const{sha256:k,size:v,mtimeMs:P}=await(0,utils_1.readFileSha256)(m);return{relPath:u,sha256:k,size:v,mtimeMs:P}},c=t.agentsFile,g=await d(c,"AGENTS.md");g&&a.push(g);const p=t.contextFile,h=await d(p,AGENTIDE_CONTEXT_FILE);h&&a.push(h);try{const m=await fs_1.promises.readdir(s,{withFileTypes:!0});for(const u of m){if(!u.isFile()||!u.name.toLowerCase().endsWith(".md"))continue;const E=path.join(s,u.name),w=path.join("rules",u.name).replace(/\\/g,"/"),D=await d(E,w);D&&a.push(D)}}catch{}try{const m=await fs_1.promises.readdir(l,{withFileTypes:!0});for(const u of m){if(!u.isDirectory()||u.name.startsWith("."))continue;const E=path.join(l,u.name,"SKILL.md"),w=await(0,utils_1.getFileStats)(E);if(!w)continue;const D=n.get(u.name);if(D&&D.skillMdMtimeMs===w.mtimeMs&&D.skillMdSize===w.size)r.push({...D,dirName:u.name});else{const{sha256:v,size:P,mtimeMs:T}=await(0,utils_1.readFileSha256)(E);let I,F;try{const $=await fs_1.promises.readFile(E,"utf-8"),j=parseSkillYamlHeader($);I=j.name,F=j.description}catch{}r.push({dirName:u.name,name:I||u.name,description:F,skillMdRelPath:path.join("skills",u.name,"SKILL.md").replace(/\\/g,"/"),skillMdSha256:v,skillMdSize:P,skillMdMtimeMs:T})}}}catch{}a.sort((m,u)=>m.relPath.localeCompare(u.relPath)),r.sort((m,u)=>m.dirName.localeCompare(u.dirName));const f=(0,utils_1.shortSig)(JSON.stringify(a.map(m=>[m.relPath,m.sha256]))),A=(0,utils_1.shortSig)(JSON.stringify(r.map(m=>[m.dirName,m.skillMdSha256]))),S=(0,utils_1.shortSig)(`${f}:${A}`);return{version:1,workspaceRoot:e,generatedAt:new Date().toISOString(),activeAgentId:t.agentId,rules:a,skills:r,rulesSignature:f,skillsSignature:A,agentideSignature:S}}async writeAgentideManifest(e,t,i){const s=this.getAgentideProjectDir(e);await(0,utils_1.pathExists)(s)||await fs_1.promises.mkdir(s,{recursive:!0});const l=await this.readAgentideManifest(e),o=await this.resolveManifestSource(e,i?.packIdOverride),n=l?.activeAgentId===o.agentId,a=await this.computeAgentideManifest(e,o,n?l:void 0);a.derivedSkillIngestState=n?i?.derivedSkillIngestState??l?.derivedSkillIngestState:i?.derivedSkillIngestState;const r=this.getAgentideManifestFilePath(e);return await(0,utils_1.writeFileIfChanged)(r,JSON.stringify(a,null,2)+`
5
+ `),this.agentideSignatureByRoot.set(e,a.agentideSignature),this.agentideSkillsSignatureByRoot.set(e,a.skillsSignature),t.appendLine(`[AgentIDE] Updated manifest: ${r} (sig=${a.agentideSignature})`),o.isPack||await this.syncAgentYamlSkills(e,o.agentId,a,t),a}ensureAgentideWatchers(e){const t=vscode.workspace.workspaceFolders?.map(s=>s.uri.fsPath)??[],i=new Set(this.agentideWatchersByRoot.keys());for(const s of i)t.includes(s)||(this.disposeAgentideWatchersForRoot(s),this.agentideRootUpdateState.delete(s),this.lastAgentideSyncSignatureByRoot.delete(s),this.agentideSignatureByRoot.delete(s),this.agentideSkillsSignatureByRoot.delete(s));for(const s of t){if(this.agentideWatchersByRoot.has(s))continue;const l=[{pattern:new vscode.RelativePattern(s,`${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/agent.yaml`),reason:"source"},{pattern:new vscode.RelativePattern(s,`${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/AGENTS.md`),reason:"source"},{pattern:new vscode.RelativePattern(s,`${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/context.md`),reason:"source"},{pattern:new vscode.RelativePattern(s,`${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/rules/**/*.md`),reason:"source"},{pattern:new vscode.RelativePattern(s,`${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/skills/**/*`),reason:"source"},{pattern:new vscode.RelativePattern(s,`${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/AGENTS.md`),reason:"source"},{pattern:new vscode.RelativePattern(s,`${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/context.md`),reason:"source"},{pattern:new vscode.RelativePattern(s,`${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/rules/**/*.md`),reason:"source"},{pattern:new vscode.RelativePattern(s,`${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/skills/**/*`),reason:"source"},{pattern:new vscode.RelativePattern(s,`${AGENTIDE_DIR_NAME}/${AGENTIDE_AGENTS_DIR}/*/agent.yaml`),reason:"source"},...getDerivedEngineSyncTargets(s).flatMap(n=>[...n.includeSkills?[{pattern:new vscode.RelativePattern(s,`${n.workspaceDir}/skills/**/SKILL.md`),reason:"derived"}]:[],{pattern:new vscode.RelativePattern(s,`${n.workspaceDir}/${n.rulesFile}`),reason:"derived"},...n.includeRules?[{pattern:new vscode.RelativePattern(s,`${n.workspaceDir}/rules/**/*.md`),reason:"derived"}]:[]])],o=[];for(const{pattern:n,reason:a}of l){const r=vscode.workspace.createFileSystemWatcher(n),d=()=>this.scheduleAgentideRootUpdate(s,e,a);o.push(r,r.onDidChange(d),r.onDidCreate(d),r.onDidDelete(d))}this.agentideWatchersByRoot.set(s,o),this.scheduleAgentideRootUpdate(s,e,"source")}}disposeAgentideWatchersForRoot(e){const t=this.agentideWatchersByRoot.get(e);if(t){for(const i of t)try{i.dispose()}catch{}this.agentideWatchersByRoot.delete(e)}}disposeAllWatchers(){for(const e of this.agentideWatchersByRoot.keys())this.disposeAgentideWatchersForRoot(e);this.agentideRootUpdateState.clear()}scheduleAgentideRootUpdate(e,t,i){const s=this.agentideRootUpdateState.get(e)??{dirty:!1,dirtySource:!1,dirtyDerived:!1,timer:void 0,deferred:void 0};s.dirty=!0,i==="source"?s.dirtySource=!0:s.dirtyDerived=!0,s.deferred||(s.deferred=(0,utils_1.createDeferred)()),s.timer&&clearTimeout(s.timer),s.timer=setTimeout(()=>{this.flushAgentideRootUpdate(e,t,{allowDuringActiveTurn:!1,force:!1})},AGENTIDE_MANIFEST_DEBOUNCE_MS),this.agentideRootUpdateState.set(e,s)}async flushAgentideRootUpdate(e,t,i){const s=i?.allowDuringActiveTurn??!1,l=i?.force??!1;if(!s&&this.activeAgentTurns>0){const d=this.agentideRootUpdateState.get(e),c=d?.dirtySource?"source":d?.dirtyDerived?"derived":"source";this.scheduleAgentideRootUpdate(e,t,c);return}const o=this.agentideRootUpdateState.get(e);if(!l&&(!o||!o.dirty&&!o.deferred))return;const n=l||(o?.dirtySource??!1),a=l||(o?.dirtyDerived??!1);o?.timer&&(clearTimeout(o.timer),o.timer=void 0);const r=o?.deferred;o&&(o.dirty=!1,o.dirtySource=!1,o.dirtyDerived=!1,o.deferred=void 0,this.agentideRootUpdateState.set(e,o));try{let d=await this.readAgentideManifest(e);const c=a?await this.importNewSkillsFromDerivedIntoAgentide(e,t,d?.derivedSkillIngestState):{agentideContentChanged:!1,ingestStateChanged:!1,nextIngestState:d?.derivedSkillIngestState??{}};if(!d||l||n||c.agentideContentChanged||c.ingestStateChanged){if(d=await this.writeAgentideManifest(e,t,{derivedSkillIngestState:c.nextIngestState}),n)try{const h=path.join(e,AGENTIDE_DIR_NAME,AGENTIDE_AGENTS_DIR);if(await(0,utils_1.pathExists)(h)){const A=(await fs_1.promises.readdir(h,{withFileTypes:!0})).filter(m=>m.isDirectory()&&!m.name.startsWith(".")).length,S=await this.loadInstalledAgents(e);A>S.length&&await vscode.commands.executeCommand("agentide.pack.refresh")}}catch{}}else this.agentideSignatureByRoot.set(e,d.agentideSignature),this.agentideSkillsSignatureByRoot.set(e,d.skillsSignature);if(!d)return;const g=this.lastAgentideSyncSignatureByRoot.get(e),p=await this.allDerivedDirsPresent(e);if(n||c.agentideContentChanged||g!==d.agentideSignature||!p){const h=this.getActivePackId(e),f=await this.switchToPack(e,h,t);f!==h&&this.setActivePackId(e,f);const A=f??AGENTIDE_DEFAULT_AGENT_ID;await this.seedAgentDataIfNeeded(e,A,t),this.lastAgentideSyncSignatureByRoot.set(e,d.agentideSignature),t.appendLine(`[AgentIDE] Derived dirs synced for ${e} (sig=${d.agentideSignature}, pack=${f??"default"})`)}r?.resolve()}catch(d){r?.reject(d),t.appendLine(`[AgentIDE] Warning: failed agentide update for ${e}: ${d instanceof Error?d.message:String(d)}`)}}async ensureAgentideProjectPrepared(e,t,i){if(!e)return;const s=vscode.workspace.workspaceFolders?.map(n=>n.uri.fsPath)??[],l=(t??[]).filter(n=>s.includes(n)),o=Array.from(new Set([e,...l].map(n=>n.trim()).filter(Boolean))).filter(n=>n!==os.homedir());for(const n of o){await(0,utils_1.ensureWorkspaceGitAndGitignore)(n,i,{extraSearchPath:getConfiguredAdditionalEngineDir()});const a=this.getAgentideProjectDir(n);await fs_1.promises.mkdir(a,{recursive:!0}),await this.ensureAgentideGitignore(n,i),await this.ensureAgentideBundledPromptsCopiedToProject(n,i);const r=o.filter(d=>d!==n);await this.ensureAgentideContextTemplate(n,r,i),await this.ensureGhostTextPrompt(n,i),await this.ensureTerminalAssistPrompt(n,i),await this.syncRemoteSkillsIfEnabled(n,i,{force:!1})}for(const n of o){await this.flushAgentideRootUpdate(n,i,{force:!1,allowDuringActiveTurn:!0});const a=await this.allDerivedDirsPresent(n);let r=await this.readAgentideManifest(n);if(r?(this.agentideSignatureByRoot.set(n,r.agentideSignature),this.agentideSkillsSignatureByRoot.set(n,r.skillsSignature)):r=await this.writeAgentideManifest(n,i),this.lastAgentideSyncSignatureByRoot.get(n)===r.agentideSignature&&a){i.appendLine(`[AgentIDE] .agentide/ unchanged for ${n}, skipping sync`);continue}const c=this.getActivePackId(n),g=await this.switchToPack(n,c,i,{importDerivedSkills:!0});g!==c&&this.setActivePackId(n,g),this.lastAgentideSyncSignatureByRoot.set(n,r.agentideSignature),i.appendLine(`[AgentIDE] Sync complete for ${n} (sig: ${r.agentideSignature}, pack: ${g??"default"})`)}}async syncRemoteSkillsIfEnabled(e,t,i){const s=vscode.workspace.getConfiguration("agentide.skills.remote");if(!s.get("enabled",!1))return;const o=s.get("syncOnStartup",!0);if(!i.force&&!o)return;const n=s.get("registryUrl","").trim();if(!n){t.appendLine("[AgentIDE] Remote skills: enabled but agentide.skills.remote.registryUrl is empty");return}const a=s.get("timeoutMs",8e3),r=s.get("allowOverwriteLocal",!1);try{const d=this.getAgentSkillsDir(e,AGENTIDE_DEFAULT_AGENT_ID);(await(0,remoteSkills_1.syncRemoteSkillsToAgentideSkillsDir)(d,{registryUrl:n,timeoutMs:a,allowOverwriteLocal:r},g=>t.appendLine(g))).updated>0&&this.scheduleAgentideRootUpdate(e,t,"source")}catch(d){t.appendLine(`[AgentIDE] Remote skills: unexpected error: ${d instanceof Error?d.message:String(d)}`)}}async ensureAgentideBundledPromptsCopiedToProject(e,t){const i=this.getBundledBasePromptsDir();if(!i)return;const s=this.getAgentRoot(e,AGENTIDE_DEFAULT_AGENT_ID),l=this.getAgentAgentsFile(e,AGENTIDE_DEFAULT_AGENT_ID),o=this.getAgentRulesDir(e,AGENTIDE_DEFAULT_AGENT_ID),n=this.getAgentSkillsDir(e,AGENTIDE_DEFAULT_AGENT_ID);await fs_1.promises.mkdir(s,{recursive:!0}),await fs_1.promises.mkdir(o,{recursive:!0}),await fs_1.promises.mkdir(n,{recursive:!0});const a=path.join(i,"rules","AGENTS.md");if(!await(0,utils_1.pathExists)(l)&&await(0,utils_1.pathExists)(a))try{const g=await fs_1.promises.readFile(a,"utf8");await fs_1.promises.writeFile(l,(0,branding_1.applyBrandingTokens)(g)),t.appendLine(`[AgentIDE] Bootstrapped project rules: ${l}`)}catch(g){t.appendLine(`[AgentIDE] Warning: failed to bootstrap project rules: ${g instanceof Error?g.message:String(g)}`)}const r=path.join(i,"skills");if(await(0,utils_1.pathExists)(r))try{const g=await fs_1.promises.readdir(r,{withFileTypes:!0});for(const p of g){if(!p.isDirectory())continue;const h=path.join(r,p.name),f=path.join(n,p.name);await(0,utils_1.pathExists)(f)||(await(0,utils_1.copyDirRecursiveWithTransform)(h,f,branding_1.applyBrandingTokens),t.appendLine(`[AgentIDE] Bootstrapped project skill: ${p.name}`))}}catch(g){t.appendLine(`[AgentIDE] Warning: failed to bootstrap project skills: ${g instanceof Error?g.message:String(g)}`)}const d=path.join(s,paths_1.AGENT_CONSTANTS.MCP_DIR),c=path.join(d,".mcp.json");if(!await(0,utils_1.pathExists)(c))try{const g=await(0,mcp_1.getDefaultMcpConfig)(i);g&&(await fs_1.promises.mkdir(d,{recursive:!0}),await fs_1.promises.writeFile(c,g),t.appendLine(`[AgentIDE] Bootstrapped MCP config: ${c}`))}catch(g){t.appendLine(`[AgentIDE] Warning: failed to bootstrap MCP config: ${g instanceof Error?g.message:String(g)}`)}await this.ensureDefaultAgentYaml(e,t)}async ensureDefaultAgentYaml(e,t){const i=this.getAgentRoot(e,AGENTIDE_DEFAULT_AGENT_ID),s=path.join(i,AGENTIDE_AGENT_YAML);if(await(0,utils_1.pathExists)(s))return;await fs_1.promises.mkdir(i,{recursive:!0});const l=(0,paths_1.generateDefaultAgentYaml)({includeModelHintComment:!0});try{await fs_1.promises.writeFile(s,l,"utf8"),t.appendLine(`[AgentIDE] Bootstrapped default agent configuration: ${s}`)}catch(o){t.appendLine(`[AgentIDE] Warning: failed to create default agent.yaml: ${o instanceof Error?o.message:String(o)}`)}}async ensureAgentideGitignore(e,t){const i=this.getAgentideProjectDir(e),s=path.join(i,".gitignore"),l=["# AgentHippo (managed)","# Keep terminal logs and large per-session terminal attachments out of source control.","terminals/","agents/default","sessions","paths.md","sessions/**/terminal.md","sessions/**/terminal.md.1"];let o="";try{o=await fs_1.promises.readFile(s,"utf8")}catch(r){if((0,utils_1.getErrorCode)(r)!=="ENOENT"){t.appendLine(`[AgentIDE] Warning: failed to read .gitignore: ${r instanceof Error?r.message:String(r)}`);return}}if(l.every(r=>o.includes(r)))return;const a=[o.trimEnd(),"",l.join(`
6
+ `),""].join(`
7
+ `).replace(/^\n+/,"");try{await(0,utils_1.writeFileIfChanged)(s,a)&&t.appendLine(`[AgentIDE] Updated ${s} to ignore terminal logs`)}catch(r){t.appendLine(`[AgentIDE] Warning: failed to write .gitignore: ${r instanceof Error?r.message:String(r)}`)}}async ensureAgentideContextTemplate(e,t,i){const s=this.getAgentideProjectDir(e);if(!await(0,utils_1.pathExists)(s))return;const l=this.getActiveAgentId(e),o=this.getAgentContextFile(e,l);if(await(0,utils_1.pathExists)(o))return;const n=this.getBundledBasePromptsDir(),a=n?path.join(n,"templates","context.md"):void 0;if(!a||!await(0,utils_1.pathExists)(a)){i.appendLine("[AgentIDE] Warning: bundled context.md template not found");return}try{let r=await fs_1.promises.readFile(a,"utf8");r=r.replace(/\{\{workspaceRoot\}\}/g,e);const d=t.slice().filter(Boolean).sort(),c=/\{\{#additionalDirectories\}\}([\s\S]*?)\{\{\/additionalDirectories\}\}/,g=r.match(c);if(g){const p=g[1],h=d.length>0?d.map(f=>p.replace(/\{\{\.\}\}/g,f)).join(""):"";r=r.replace(c,h)}await fs_1.promises.mkdir(s,{recursive:!0}),await fs_1.promises.writeFile(o,r,"utf8"),i.appendLine(`[AgentIDE] Created context template: ${o}`)}catch(r){i.appendLine(`[AgentIDE] Warning: failed to copy context template: ${r instanceof Error?r.message:String(r)}`)}}async ensureGhostTextPrompt(e,t){await this.ensureBundledPromptFile(e,paths_1.AGENT_CONSTANTS.GHOST_TEXT_FILE,t)}async ensureTerminalAssistPrompt(e,t){await this.ensureBundledPromptFile(e,paths_1.AGENT_CONSTANTS.TERMINAL_ASSIST_FILE,t)}async ensureBundledPromptFile(e,t,i){const s=this.getAgentideProjectDir(e);if(!await(0,utils_1.pathExists)(s))return;const l=this.getActiveAgentId(e),o=path.join(s,"agents",l),n=path.join(o,t);if(await(0,utils_1.pathExists)(n))return;const a=this.getBundledBasePromptsDir(),r=a?path.join(a,t):void 0;if(!(!r||!await(0,utils_1.pathExists)(r)))try{await fs_1.promises.mkdir(o,{recursive:!0});const d=await fs_1.promises.readFile(r,"utf8");await fs_1.promises.writeFile(n,d,"utf8"),i.appendLine(`[AgentIDE] Created ${t}: ${n}`)}catch(d){i.appendLine(`[AgentIDE] Warning: failed to copy ${t}: ${d instanceof Error?d.message:String(d)}`)}}async importNewSkillsFromDerivedIntoAgentide(e,t,i){const s=this.getActiveAgentId(e),l=this.getAgentSkillsDir(e,s),o=getDerivedEngineSyncTargets(e).filter(d=>d.includeSkills).map(d=>path.join(e,d.workspaceDir,"skills"));await fs_1.promises.mkdir(l,{recursive:!0});const n={...i??{}};let a=!1,r=!1;for(const d of o)try{const c=await fs_1.promises.readdir(d,{withFileTypes:!0});for(const g of c){if(!g.isDirectory()||g.name.startsWith("."))continue;const p=path.join(d,g.name),h=path.join(p,"SKILL.md");if(!await(0,utils_1.pathExists)(h))continue;const f=path.join(l,g.name),A=path.join(f,"SKILL.md"),{sha256:S}=await(0,utils_1.readFileSha256)(h);if(!await(0,utils_1.pathExists)(f)){await(0,utils_1.copyDirRecursive)(p,f),a=!0,n[g.name]={lastIngestedSkillMdSha256:S,lastIngestedAt:new Date().toISOString()},r=!0,t.appendLine(`[AgentIDE] Imported new skill from derived dir: ${g.name} \u2192 ${s}`);continue}if(!await(0,utils_1.pathExists)(A))continue;const{sha256:m}=await(0,utils_1.readFileSha256)(A),u=n[g.name];if(!u&&S===m){n[g.name]={lastIngestedSkillMdSha256:m,lastIngestedAt:new Date().toISOString()},r=!0;continue}if(u){if(m!==u.lastIngestedSkillMdSha256){t.appendLine(`[AgentIDE] Skipped ingest for skill '${g.name}' (conflict: .agentide diverged from last ingested state)`);continue}S!==m&&(await fs_1.promises.copyFile(h,A),a=!0,n[g.name]={lastIngestedSkillMdSha256:S,lastIngestedAt:new Date().toISOString()},r=!0,t.appendLine(`[AgentIDE] Ingested updated SKILL.md from derived dir: ${g.name}`))}}}catch{}return{agentideContentChanged:a,ingestStateChanged:r,nextIngestState:n}}async readAgentideContextMd(e){const t=this.getActiveAgentId(e),i=this.getAgentContextFile(e,t);try{return await fs_1.promises.readFile(i,"utf8")}catch(s){if((0,utils_1.getErrorCode)(s)==="ENOENT")return;throw s}}async writeDerivedDirReadme(e,t,i,s){try{const l=path.join(e,AGENTIDE_DERIVED_DIR_README),o=t.charAt(0).toUpperCase()+t.slice(1),n=s&&s.length>0?s:["- `.agentide/agents/<agentId>/AGENTS.md` (project rules)","- `.agentide/agents/<agentId>/rules/*.md` (additional rule fragments)","- `.agentide/agents/<agentId>/skills/*/SKILL.md` (project skills)"],a=[`# Managed by ${branding_1.AGENTIDE_BRAND_NAME}`,"",`This directory is managed by the ${branding_1.AGENTIDE_BRAND_NAME} extension.`,"","## How It Works","","- **Skills** created here ARE synced back to `.agentide/agents/<id>/skills/`","- **Rules files** (`CLAUDE.md`, `AGENTS.md`) are generated from the source and **not synced back**"," - Edit rules in `.agentide/agents/<id>/AGENTS.md` instead","- The source-of-truth is in:",...n,"","## Tips","","- Create/edit skills here or in `.agentide/` - both will stay in sync","- To change project rules, edit `.agentide/agents/<id>/AGENTS.md` (not the rules file here)","- This folder exists for "+o+" auto-discovery compatibility",""].join(`
8
+ `);await(0,utils_1.writeFileIfChanged)(l,a)}catch(l){i.appendLine(`[AgentIDE] Warning: failed to write ${t} derived README: ${l instanceof Error?l.message:String(l)}`)}}async cleanDerivedRulesDir(e){try{const i=(await fs_1.promises.readdir(e,{withFileTypes:!0})).filter(s=>s.isFile()&&s.name.toLowerCase().endsWith(".md")).map(s=>fs_1.promises.rm(path.join(e,s.name),{force:!0}));await Promise.all(i)}catch{}}async syncAgentideProjectToDerivedDirs(e,t,i){const s=Array.from(new Set(e.map(l=>l.trim()).filter(Boolean)));for(const l of s){if(!l||l===os.homedir())continue;const o=this.getAgentideProjectDir(l),n=i??this.getActiveAgentId(l),a=this.getAgentSkillsDir(l,n),r=this.getAgentRulesDir(l,n),d=this.getAgentAgentsFile(l,n);if(!await(0,utils_1.pathExists)(o))continue;const c=getDerivedEngineSyncTargets(l).map(f=>({id:f.id,displayName:f.displayName,workspaceDir:f.workspaceDir,rulesFile:f.rulesFile,managedPaths:f.managedPaths,includeSkills:f.includeSkills,includeRules:f.includeRules,fullPath:path.join(l,f.workspaceDir),rulesPath:path.join(l,f.workspaceDir,"rules"),skillsPath:path.join(l,f.workspaceDir,"skills")})),g=[`- \`.agentide/agents/${n}/AGENTS.md\` (project rules)`,`- \`.agentide/agents/${n}/rules/*.md\` (additional rule fragments)`,`- \`.agentide/agents/${n}/skills/*/SKILL.md\` (project skills)`];await Promise.all(c.map(f=>fs_1.promises.mkdir(f.fullPath,{recursive:!0}))),await Promise.all(c.flatMap(f=>[this.writeDerivedDirReadme(f.fullPath,f.id,t,g),fs_1.promises.mkdir(f.rulesPath,{recursive:!0})]));const p=[];if(await(0,utils_1.pathExists)(d)){const[f,A]=await Promise.all([fs_1.promises.readFile(d,"utf8"),this.readAgentideContextMd(l)]);let S=(0,branding_1.applyBrandingTokens)(f).trimEnd();A?S+=`
9
+
10
+ ---
11
+
12
+ `+A.trimEnd()+`
13
+ `:S+=`
14
+ `;for(const m of c)p.push((0,utils_1.writeFileIfChanged)(path.join(m.fullPath,m.rulesFile),S))}if(await Promise.all([...p,...c.filter(f=>f.includeRules).map(f=>this.cleanDerivedRulesDir(f.rulesPath))]),await(0,utils_1.pathExists)(r)){const A=(await fs_1.promises.readdir(r,{withFileTypes:!0})).filter(S=>S.isFile()&&S.name.toLowerCase().endsWith(".md")).flatMap(S=>{const m=path.join(r,S.name);return c.filter(u=>u.includeRules).map(u=>(0,utils_1.symlinkOrCopyFile)(m,path.join(u.rulesPath,S.name),t,`Rule ${S.name} -> ${u.workspaceDir}`,{force:!0}))});await Promise.all(A)}if(await Promise.all(c.filter(f=>f.includeSkills).map(f=>(0,utils_1.ensureRealDirectory)(f.skillsPath))),await(0,utils_1.pathExists)(a)){const f=await fs_1.promises.readdir(a,{withFileTypes:!0}),A=[];for(const u of f){if(!u.isDirectory()||u.name.startsWith("."))continue;const E=path.join(a,u.name,"SKILL.md");await(0,utils_1.pathExists)(E)&&A.push(u.name)}const S=new Set(A),m=async(u,E)=>{try{const w=await fs_1.promises.readdir(u,{withFileTypes:!0}),D=[];for(const k of w)!k.isDirectory()&&!k.isSymbolicLink()||k.name.startsWith(".")||S.has(k.name)||D.push(fs_1.promises.rm(path.join(u,k.name),{recursive:!0,force:!0}));await Promise.all(D)}catch{}for(const w of A){const D=path.join(a,w),k=path.join(u,w);await(0,utils_1.syncDirByFileLinks)(D,k,t,`${E}/skills/${w}`)}};await Promise.all(c.filter(u=>u.includeSkills).map(u=>m(u.skillsPath,u.workspaceDir)))}}}async syncPackDerivedDirs(e,t){if(!e||!await(0,utils_1.pathExists)(e))return;const i=path.join(e,"AGENTS.md"),s=path.join(e,"rules"),l=path.join(e,"skills"),o=getDerivedEngineSyncTargets(e).map(n=>({id:n.id,workspaceDir:n.workspaceDir,rulesFile:n.rulesFile,includeSkills:n.includeSkills,includeRules:n.includeRules,fullPath:path.join(e,n.workspaceDir),rulesPath:path.join(e,n.workspaceDir,"rules"),skillsPath:path.join(e,n.workspaceDir,"skills")}));if(await Promise.all(o.map(n=>fs_1.promises.mkdir(n.fullPath,{recursive:!0}))),await Promise.all(o.map(n=>fs_1.promises.mkdir(n.rulesPath,{recursive:!0}))),await(0,utils_1.pathExists)(i)){const n=(0,branding_1.applyBrandingTokens)(await fs_1.promises.readFile(i,"utf8")),a=path.join(e,"context.md");let r=n.trimEnd();if(await(0,utils_1.pathExists)(a)){const d=await fs_1.promises.readFile(a,"utf8");r+=`
15
+
16
+ ---
17
+
18
+ `+d.trimEnd()+`
19
+ `}else r+=`
20
+ `;for(const d of o)await(0,utils_1.writeFileIfChanged)(path.join(d.fullPath,d.rulesFile),r)}if(await(0,utils_1.pathExists)(s)){const n=await fs_1.promises.readdir(s,{withFileTypes:!0});for(const a of n){if(!a.isFile()||!a.name.toLowerCase().endsWith(".md"))continue;const r=path.join(s,a.name);for(const d of o.filter(c=>c.includeRules))await(0,utils_1.symlinkOrCopyFile)(r,path.join(d.rulesPath,a.name),t,`Pack rule ${a.name}`,{force:!0})}}if(await Promise.all(o.filter(n=>n.includeSkills).map(n=>(0,utils_1.ensureRealDirectory)(n.skillsPath))),await(0,utils_1.pathExists)(l)){const n=await fs_1.promises.readdir(l,{withFileTypes:!0});for(const a of n){if(!a.isDirectory()||a.name.startsWith("."))continue;const r=path.join(l,a.name);for(const d of o.filter(c=>c.includeSkills))await(0,utils_1.syncDirByFileLinks)(r,path.join(d.skillsPath,a.name),t,`Pack skill ${a.name}`)}}t.appendLine(`[AgentPack] Synced derived dirs for pack at ${e}`)}async switchToPack(e,t,i,s){if(s?.importDerivedSkills){const c=await this.readAgentideManifest(e);await this.importNewSkillsFromDerivedIntoAgentide(e,i,c?.derivedSkillIngestState)}if(!t||t==="default"){i.appendLine("[AgentPack] Switching to default workspace agent"),await this.syncAgentideProjectToDerivedDirs([e],i,"default"),await this.seedAgentDataIfNeeded(e,AGENTIDE_DEFAULT_AGENT_ID,i),await this.writeAgentideManifest(e,i,{packIdOverride:"default"});return}const l=path.join(e,AGENTIDE_DIR_NAME,"agents",t);if(!await(0,utils_1.pathExists)(l)){i.appendLine(`[AgentPack] Warning: Pack not found at ${l}, falling back to default`),await this.syncAgentideProjectToDerivedDirs([e],i,"default"),await this.writeAgentideManifest(e,i,{packIdOverride:"default"});return}i.appendLine(`[AgentPack] Switching to pack: ${t}`);const o=path.join(l,"AGENTS.md"),n=path.join(l,"rules"),a=path.join(l,"skills"),r=getDerivedEngineSyncTargets(e).map(c=>({id:c.id,workspaceDir:c.workspaceDir,rulesFile:c.rulesFile,includeSkills:c.includeSkills,includeRules:c.includeRules,fullPath:path.join(e,c.workspaceDir),rulesPath:path.join(e,c.workspaceDir,"rules"),skillsPath:path.join(e,c.workspaceDir,"skills")})),d=[`- \`.agentide/agents/${t}/AGENTS.md\` (pack rules)`,`- \`.agentide/agents/${t}/rules/*.md\` (additional rule fragments)`,`- \`.agentide/agents/${t}/skills/*/SKILL.md\` (pack skills)`];if(await Promise.all(r.map(c=>fs_1.promises.mkdir(c.fullPath,{recursive:!0}))),await Promise.all(r.flatMap(c=>[this.writeDerivedDirReadme(c.fullPath,c.id,i,d),fs_1.promises.mkdir(c.rulesPath,{recursive:!0})])),await(0,utils_1.pathExists)(o)){const c=(0,branding_1.applyBrandingTokens)(await fs_1.promises.readFile(o,"utf8")),g=path.join(l,"context.md");let p=c.trimEnd();if(await(0,utils_1.pathExists)(g)){const h=await fs_1.promises.readFile(g,"utf8");p+=`
21
+
22
+ ---
23
+
24
+ `+h.trimEnd()+`
25
+ `}else p+=`
26
+ `;for(const h of r)await(0,utils_1.writeFileIfChanged)(path.join(h.fullPath,h.rulesFile),p)}if(await Promise.all(r.filter(c=>c.includeRules).map(c=>this.cleanDerivedRulesDir(c.rulesPath))),await(0,utils_1.pathExists)(n)){const c=await fs_1.promises.readdir(n,{withFileTypes:!0});for(const g of c){if(!g.isFile()||!g.name.toLowerCase().endsWith(".md"))continue;const p=path.join(n,g.name);for(const h of r.filter(f=>f.includeRules))await(0,utils_1.symlinkOrCopyFile)(p,path.join(h.rulesPath,g.name),i,`Pack rule ${g.name}`,{force:!0})}}if(await Promise.all(r.filter(c=>c.includeSkills).map(c=>(0,utils_1.ensureRealDirectory)(c.skillsPath))),await(0,utils_1.pathExists)(a)){const c=await fs_1.promises.readdir(a,{withFileTypes:!0}),g=[];for(const h of c){if(!h.isDirectory()||h.name.startsWith("."))continue;const f=path.join(a,h.name,"SKILL.md");await(0,utils_1.pathExists)(f)&&g.push(h.name)}const p=new Set(g);for(const h of r.filter(f=>f.includeSkills))try{const f=await fs_1.promises.readdir(h.skillsPath,{withFileTypes:!0});for(const A of f)(A.isDirectory()||A.isSymbolicLink())&&!p.has(A.name)&&(await fs_1.promises.rm(path.join(h.skillsPath,A.name),{recursive:!0,force:!0}),i.appendLine(`[AgentPack] Removed stale skill: ${A.name}`))}catch{}for(const h of g){const f=path.join(a,h);for(const A of r.filter(S=>S.includeSkills))await(0,utils_1.syncDirByFileLinks)(f,path.join(A.skillsPath,h),i,`Pack skill ${h}`)}}else for(const c of r.filter(g=>g.includeSkills))try{const g=await fs_1.promises.readdir(c.skillsPath,{withFileTypes:!0});for(const p of g)(p.isDirectory()||p.isSymbolicLink())&&await fs_1.promises.rm(path.join(c.skillsPath,p.name),{recursive:!0,force:!0})}catch{}return i.appendLine(`[AgentPack] Switched workspace to pack: ${t}`),await this.seedAgentDataIfNeeded(e,t,i),await this.writeAgentideManifest(e,i,{packIdOverride:t}),t}async loadAgentideManifest(e){const t=path.join(e,AGENTIDE_DIR_NAME,AGENTIDE_MANIFEST_FILE);try{const i=await fs_1.promises.readFile(t,"utf8");return JSON.parse(i)}catch{return}}getInstalledAgentsFilePath(e){return path.join(e,AGENTIDE_DIR_NAME,AGENTIDE_INSTALLED_AGENTS_FILE)}async loadInstalledAgents(e){const t=this.getInstalledAgentsFilePath(e);try{const i=await fs_1.promises.readFile(t,"utf8");return JSON.parse(i).agents??[]}catch{return[]}}async saveInstalledAgents(e,t){const i=this.getInstalledAgentsFilePath(e),s={version:1,agents:t};await fs_1.promises.mkdir(path.dirname(i),{recursive:!0}),await fs_1.promises.writeFile(i,JSON.stringify(s,null,2))}async updateInstalledAgent(e,t,i){const l=(await this.loadInstalledAgents(e)).filter(n=>n.id!==t.id),o={id:t.id,version:t.version,source:t.source,installedAt:new Date().toISOString(),featureSetHash:t.featureSetHash,preferredEngine:t.preferredEngine,preferredModel:t.preferredModel,preferredCheapModel:t.preferredCheapModel,status:"active"};l.push(o),await this.saveInstalledAgents(e,l),(0,utils_1.logInfo)(i,`[Agent] Registered agent: ${t.id}`)}async removeInstalledAgent(e,t,i){const s=await this.loadInstalledAgents(e),l=s.filter(o=>o.id!==t);l.length!==s.length&&(await this.saveInstalledAgents(e,l),(0,utils_1.logInfo)(i,`[Agent] Removed agent: ${t}`))}}exports.SyncService=SyncService;