@agenthippo-ai/agenthippo 1.110.11 → 1.110.20

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 (534) 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 -302
  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 -1283
  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 +618 -564
  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 +127 -459
  61. package/out/scripts/analytics/agent-fleet-widget.js +18 -257
  62. package/out/scripts/analytics/agentide-litellm-otel.config.yaml +0 -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/token-cost-flamegraph-widget.js +4 -461
  70. package/out/scripts/analytics/token-cost-trend-widget.js +4 -534
  71. package/out/scripts/analytics/workflows-collector.cjs +4 -314
  72. package/out/scripts/analytics/workflows-daemon.mjs +9 -185
  73. package/out/scripts/analytics/workflows-widget.cjs +15 -159
  74. package/out/scripts/analytics/wow-model-widget.js +10 -120
  75. package/out/scripts/vendor-tools.mjs +2 -233
  76. package/out/skills/publish.js +3 -178
  77. package/out/store/github/setup.js +7 -212
  78. package/out/store/oramaIndex.js +2 -884
  79. package/out/sync.js +26 -1829
  80. package/out/terminalLogger.js +5 -358
  81. package/out/utils/pathSafety.js +2 -60
  82. package/out/utils/pythonRunner.js +4 -258
  83. package/out/utils/toolPath.js +2 -83
  84. package/out/workspaceFolders.js +2 -59
  85. package/package.json +10 -6
  86. package/out/agentpack/github.js +0 -547
  87. package/out/agentpack/index.js +0 -69
  88. package/out/agentpack/install.js +0 -297
  89. package/out/agentpack/manager.js +0 -441
  90. package/out/agentpack/manifest.js +0 -135
  91. package/out/agentpack/paths.js +0 -521
  92. package/out/agentpack/publish.js +0 -248
  93. package/out/agentpack/stores.js +0 -554
  94. package/out/analytics/dashboard/fleetStatusUtils.js +0 -30
  95. package/out/analytics/dashboard/fleetTitleUtils.js +0 -68
  96. package/out/analytics/dashboard/refreshPolicy.js +0 -16
  97. package/out/analytics/dashboard/scheduledFleetFingerprint.js +0 -22
  98. package/out/analytics/dashboard/scheduledFleetUtils.js +0 -22
  99. package/out/analytics/dashboard/sessionEventFleetStats.js +0 -118
  100. package/out/analytics/dashboard/viewsConfigMerge.js +0 -221
  101. package/out/analytics/dashboard/webview/codicon.ttf +0 -0
  102. package/out/analytics/identity.js +0 -0
  103. package/out/analytics/sessionEvents.js +0 -324
  104. package/out/auth/callbackUriParse.js +0 -59
  105. package/out/auth/types.js +0 -12
  106. package/out/auth-broker/config.js +0 -112
  107. package/out/auth-broker/jwt.js +0 -105
  108. package/out/auth-broker/pkce.js +0 -59
  109. package/out/auth-broker/server.js +0 -681
  110. package/out/auth-broker/store.js +0 -275
  111. package/out/authority/warrant.js +0 -206
  112. package/out/base-prompts/mcp-servers/.mcp.json +0 -13
  113. package/out/base-prompts/mcp-servers/langfuse-analytics/README.md +0 -142
  114. package/out/base-prompts/mcp-servers/langfuse-analytics/mcp.json +0 -13
  115. package/out/base-prompts/mcp-servers/langfuse-analytics/package-lock.json +0 -1192
  116. package/out/base-prompts/mcp-servers/langfuse-analytics/package.json +0 -23
  117. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/run-with-env.sh +0 -12
  118. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/sdk-test.js +0 -102
  119. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/simple-test.js +0 -137
  120. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/test-client.js +0 -118
  121. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/test-server.js +0 -209
  122. package/out/base-prompts/mcp-servers/langfuse-analytics/src/client.ts +0 -431
  123. package/out/base-prompts/mcp-servers/langfuse-analytics/src/index.ts +0 -270
  124. package/out/base-prompts/mcp-servers/langfuse-analytics/tsconfig.json +0 -18
  125. package/out/base-prompts/rules/AGENTS.md +0 -204
  126. package/out/base-prompts/skills/agent-browser/SKILL.md +0 -102
  127. package/out/base-prompts/skills/agent-builder/SKILL.md +0 -73
  128. package/out/base-prompts/skills/agent-builder/references/agent-pack.md +0 -63
  129. package/out/base-prompts/skills/agent-builder/references/crewai.md +0 -66
  130. package/out/base-prompts/skills/agent-builder/references/langchain.md +0 -60
  131. package/out/base-prompts/skills/agent-builder/references/raw-sdk.md +0 -73
  132. package/out/base-prompts/skills/agent-engine-creator/SKILL.md +0 -586
  133. package/out/base-prompts/skills/agent-engine-installer/SKILL.md +0 -106
  134. package/out/base-prompts/skills/agent-engine-installer/scripts/install-engine.mjs +0 -259
  135. package/out/base-prompts/skills/agent-engine-installer/scripts/install-engine.ps1 +0 -189
  136. package/out/base-prompts/skills/agenthippo-cli/SKILL.md +0 -69
  137. package/out/base-prompts/skills/agenthippo-cli/scripts/install.sh +0 -63
  138. package/out/base-prompts/skills/agentpack-creator/SKILL.md +0 -375
  139. package/out/base-prompts/skills/agentpack-creator/references/agent-templates.md +0 -261
  140. package/out/base-prompts/skills/agentpack-creator/references/agents-md-guide.md +0 -195
  141. package/out/base-prompts/skills/agentpack-creator/scripts/init_pack.py +0 -391
  142. package/out/base-prompts/skills/agentpack-creator/scripts/init_pack_test.py +0 -294
  143. package/out/base-prompts/skills/agentpack-testbench/SKILL.md +0 -135
  144. package/out/base-prompts/skills/algorithmic-art/LICENSE.txt +0 -202
  145. package/out/base-prompts/skills/algorithmic-art/SKILL.md +0 -405
  146. package/out/base-prompts/skills/algorithmic-art/templates/generator_template.js +0 -223
  147. package/out/base-prompts/skills/algorithmic-art/templates/viewer.html +0 -599
  148. package/out/base-prompts/skills/debug-agent/SKILL.md +0 -83
  149. package/out/base-prompts/skills/desktop-automation/SKILL.md +0 -166
  150. package/out/base-prompts/skills/desktop-automation/references/agenthippo-ui-recipes.md +0 -441
  151. package/out/base-prompts/skills/desktop-automation/scripts/windows-desktop-uia.psm1 +0 -280
  152. package/out/base-prompts/skills/docx/LICENSE.txt +0 -30
  153. package/out/base-prompts/skills/docx/SKILL.md +0 -197
  154. package/out/base-prompts/skills/docx/docx-js.md +0 -350
  155. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  156. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  157. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  158. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  159. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  160. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  161. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  162. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  163. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  164. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  165. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  166. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  167. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  168. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  169. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  170. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  171. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  172. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  173. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  174. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  175. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  176. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  177. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  178. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  179. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  180. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  181. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  182. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  183. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  184. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  185. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  186. package/out/base-prompts/skills/docx/ooxml/schemas/mce/mc.xsd +0 -75
  187. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  188. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  189. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  190. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  191. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  192. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  193. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  194. package/out/base-prompts/skills/docx/ooxml/scripts/pack.py +0 -159
  195. package/out/base-prompts/skills/docx/ooxml/scripts/unpack.py +0 -29
  196. package/out/base-prompts/skills/docx/ooxml/scripts/validate.py +0 -69
  197. package/out/base-prompts/skills/docx/ooxml/scripts/validation/__init__.py +0 -15
  198. package/out/base-prompts/skills/docx/ooxml/scripts/validation/base.py +0 -951
  199. package/out/base-prompts/skills/docx/ooxml/scripts/validation/docx.py +0 -274
  200. package/out/base-prompts/skills/docx/ooxml/scripts/validation/pptx.py +0 -315
  201. package/out/base-prompts/skills/docx/ooxml/scripts/validation/redlining.py +0 -279
  202. package/out/base-prompts/skills/docx/ooxml.md +0 -610
  203. package/out/base-prompts/skills/docx/scripts/__init__.py +0 -1
  204. package/out/base-prompts/skills/docx/scripts/document.py +0 -1276
  205. package/out/base-prompts/skills/docx/scripts/templates/comments.xml +0 -3
  206. package/out/base-prompts/skills/docx/scripts/templates/commentsExtended.xml +0 -3
  207. package/out/base-prompts/skills/docx/scripts/templates/commentsExtensible.xml +0 -3
  208. package/out/base-prompts/skills/docx/scripts/templates/commentsIds.xml +0 -3
  209. package/out/base-prompts/skills/docx/scripts/templates/people.xml +0 -3
  210. package/out/base-prompts/skills/docx/scripts/utilities.py +0 -374
  211. package/out/base-prompts/skills/gateway-outbound/SKILL.md +0 -136
  212. package/out/base-prompts/skills/mcp-builder/LICENSE.txt +0 -202
  213. package/out/base-prompts/skills/mcp-builder/SKILL.md +0 -328
  214. package/out/base-prompts/skills/mcp-builder/reference/evaluation.md +0 -602
  215. package/out/base-prompts/skills/mcp-builder/reference/mcp_best_practices.md +0 -249
  216. package/out/base-prompts/skills/mcp-builder/reference/node_mcp_server.md +0 -970
  217. package/out/base-prompts/skills/mcp-builder/reference/python_mcp_server.md +0 -719
  218. package/out/base-prompts/skills/mcp-builder/scripts/connections.py +0 -151
  219. package/out/base-prompts/skills/mcp-builder/scripts/evaluation.py +0 -373
  220. package/out/base-prompts/skills/mcp-builder/scripts/example_evaluation.xml +0 -22
  221. package/out/base-prompts/skills/mcp-builder/scripts/requirements.txt +0 -2
  222. package/out/base-prompts/skills/openclaw/SKILL.md +0 -406
  223. package/out/base-prompts/skills/openclaw/scripts/run-smoke.sh +0 -61
  224. package/out/base-prompts/skills/pdf/LICENSE.txt +0 -30
  225. package/out/base-prompts/skills/pdf/SKILL.md +0 -294
  226. package/out/base-prompts/skills/pdf/forms.md +0 -205
  227. package/out/base-prompts/skills/pdf/reference.md +0 -612
  228. package/out/base-prompts/skills/pdf/scripts/check_bounding_boxes.py +0 -70
  229. package/out/base-prompts/skills/pdf/scripts/check_bounding_boxes_test.py +0 -226
  230. package/out/base-prompts/skills/pdf/scripts/check_fillable_fields.py +0 -12
  231. package/out/base-prompts/skills/pdf/scripts/convert_pdf_to_images.py +0 -35
  232. package/out/base-prompts/skills/pdf/scripts/create_validation_image.py +0 -41
  233. package/out/base-prompts/skills/pdf/scripts/extract_form_field_info.py +0 -152
  234. package/out/base-prompts/skills/pdf/scripts/fill_fillable_fields.py +0 -114
  235. package/out/base-prompts/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -108
  236. package/out/base-prompts/skills/pptx/LICENSE.txt +0 -30
  237. package/out/base-prompts/skills/pptx/SKILL.md +0 -484
  238. package/out/base-prompts/skills/pptx/html2pptx.md +0 -625
  239. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  240. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  241. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  242. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  243. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  244. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  245. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  246. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  247. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  248. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  249. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  250. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  251. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  252. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  253. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  254. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  255. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  256. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  257. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  258. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  259. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  260. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  261. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  262. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  263. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  264. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  265. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  266. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  267. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  268. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  269. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  270. package/out/base-prompts/skills/pptx/ooxml/schemas/mce/mc.xsd +0 -75
  271. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  272. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  273. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  274. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  275. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  276. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  277. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  278. package/out/base-prompts/skills/pptx/ooxml/scripts/pack.py +0 -159
  279. package/out/base-prompts/skills/pptx/ooxml/scripts/unpack.py +0 -29
  280. package/out/base-prompts/skills/pptx/ooxml/scripts/validate.py +0 -69
  281. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/__init__.py +0 -15
  282. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/base.py +0 -951
  283. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/docx.py +0 -274
  284. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/pptx.py +0 -315
  285. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/redlining.py +0 -279
  286. package/out/base-prompts/skills/pptx/ooxml.md +0 -427
  287. package/out/base-prompts/skills/pptx/scripts/html2pptx.js +0 -984
  288. package/out/base-prompts/skills/pptx/scripts/inventory.py +0 -1020
  289. package/out/base-prompts/skills/pptx/scripts/rearrange.py +0 -231
  290. package/out/base-prompts/skills/pptx/scripts/replace.py +0 -385
  291. package/out/base-prompts/skills/pptx/scripts/thumbnail.py +0 -450
  292. package/out/base-prompts/skills/prompt-lab/SKILL.md +0 -149
  293. package/out/base-prompts/skills/prompt-lab/scripts/query-analytics.sh +0 -2551
  294. package/out/base-prompts/skills/skill-creator/LICENSE.txt +0 -202
  295. package/out/base-prompts/skills/skill-creator/SKILL.md +0 -371
  296. package/out/base-prompts/skills/skill-creator/references/output-patterns.md +0 -82
  297. package/out/base-prompts/skills/skill-creator/references/workflows.md +0 -28
  298. package/out/base-prompts/skills/skill-creator/scripts/init_skill.py +0 -303
  299. package/out/base-prompts/skills/skill-creator/scripts/package_skill.py +0 -110
  300. package/out/base-prompts/skills/skill-creator/scripts/quick_validate.py +0 -95
  301. package/out/base-prompts/skills/skill-installer/SKILL.md +0 -251
  302. package/out/base-prompts/skills/skill-installer/references/store-api.md +0 -219
  303. package/out/base-prompts/skills/spotlight-dashboard/SKILL.md +0 -83
  304. package/out/base-prompts/skills/spotlight-insights/SKILL.md +0 -101
  305. package/out/base-prompts/skills/spotlight-optimize/SKILL.md +0 -93
  306. package/out/base-prompts/skills/spotlight-optimize/scripts/query-analytics.sh +0 -2551
  307. package/out/base-prompts/skills/spotlight-query/SKILL.md +0 -314
  308. package/out/base-prompts/skills/spotlight-query/references/otel-schema.md +0 -163
  309. package/out/base-prompts/skills/spotlight-query/scripts/query-analytics.sh +0 -2551
  310. package/out/base-prompts/skills/spotlight-query/scripts/query-analytics.test.sh +0 -744
  311. package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/sessions/sess-test-1.jsonl +0 -14
  312. package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/traces/.duckdb-index.json +0 -7
  313. package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/traces/sample.jsonl +0 -5
  314. package/out/base-prompts/skills/spotlight-report/SKILL.md +0 -86
  315. package/out/base-prompts/skills/spotlight-visualize/SKILL.md +0 -92
  316. package/out/base-prompts/skills/spotlight-visualize/scripts/query-analytics.sh +0 -2551
  317. package/out/base-prompts/skills/xlsx/LICENSE.txt +0 -30
  318. package/out/base-prompts/skills/xlsx/SKILL.md +0 -289
  319. package/out/base-prompts/skills/xlsx/recalc.py +0 -178
  320. package/out/branding.js +0 -49
  321. package/out/cli/commands/anywhere.js +0 -66
  322. package/out/cli/commands/ask.js +0 -246
  323. package/out/cli/commands/auth-broker.js +0 -24
  324. package/out/cli/commands/auth.js +0 -219
  325. package/out/cli/commands/chat.js +0 -357
  326. package/out/cli/commands/conformance.js +0 -249
  327. package/out/cli/commands/data-plane.js +0 -151
  328. package/out/cli/commands/deploy.js +0 -263
  329. package/out/cli/commands/gateway.js +0 -218
  330. package/out/cli/commands/idp.js +0 -85
  331. package/out/cli/commands/pack.js +0 -399
  332. package/out/cli/commands/probe-custom-engine.js +0 -82
  333. package/out/cli/commands/sandbox.js +0 -351
  334. package/out/cli/commands/serve.js +0 -1950
  335. package/out/cli/commands/store.js +0 -927
  336. package/out/cli/credential-context.js +0 -108
  337. package/out/cli/data-plane/broker.js +0 -78
  338. package/out/cli/data-plane/connector-host.js +0 -121
  339. package/out/cli/data-plane/egress.js +0 -189
  340. package/out/cli/data-plane/gateway.js +0 -218
  341. package/out/cli/data-plane/index.js +0 -153
  342. package/out/cli/data-plane/registry.js +0 -89
  343. package/out/cli/data-plane/remote.js +0 -106
  344. package/out/cli/data-plane/sidecar.js +0 -225
  345. package/out/cli/deploy/blueprints/registry.js +0 -84
  346. package/out/cli/deploy/layers/identity.js +0 -175
  347. package/out/cli/deploy-init.js +0 -3023
  348. package/out/cli/deps.js +0 -342
  349. package/out/cli/idp-init.js +0 -338
  350. package/out/cli/pack-install-ref.js +0 -15
  351. package/out/cli/pack-loader.js +0 -418
  352. package/out/cli/pack-runtime.js +0 -61
  353. package/out/cli/runtime.js +0 -450
  354. package/out/cli/serve-hardening.js +0 -776
  355. package/out/cli/state-sync.js +0 -424
  356. package/out/cli/utils.js +0 -231
  357. package/out/engines/base.js +0 -188
  358. package/out/engines/claude.js +0 -1254
  359. package/out/engines/codex.js +0 -862
  360. package/out/engines/custom.js +0 -680
  361. package/out/engines/customEngineIpc.js +0 -95
  362. package/out/engines/customEngineRunnerEmbed.js +0 -107
  363. package/out/engines/customRegistry.js +0 -274
  364. package/out/engines/embeddedCustomEngineRunner.generated.js +0 -9
  365. package/out/engines/engineApiKey.js +0 -138
  366. package/out/engines/install.js +0 -372
  367. package/out/engines/persistentEngineWorker.js +0 -320
  368. package/out/engines/publish.js +0 -341
  369. package/out/evidence/sessionShip.js +0 -643
  370. package/out/gateway/bridge.js +0 -843
  371. package/out/gateway/cli-agent-id.js +0 -36
  372. package/out/gateway/client.js +0 -336
  373. package/out/gateway/client.test.js +0 -395
  374. package/out/gateway/gateway-scope-errors.js +0 -14
  375. package/out/gateway/gatewayBackup.js +0 -76
  376. package/out/gateway/installSource.js +0 -68
  377. package/out/gateway/lifecycle.js +0 -3190
  378. package/out/gateway/openclaw-channel-routing.js +0 -317
  379. package/out/gateway/outboundHandles.js +0 -373
  380. package/out/gateway/outboundPaths.js +0 -75
  381. package/out/gateway/outboundSend.js +0 -254
  382. package/out/gateway/protocol.js +0 -48
  383. package/out/gateway/secretsPreflight.js +0 -90
  384. package/out/gateway/sessionRouting.js +0 -77
  385. package/out/headless/index.js +0 -546
  386. package/out/headless/sync.js +0 -473
  387. package/out/live-e2e/mcp-demo/server.mjs +0 -32
  388. package/out/live-probe/connector.mjs +0 -8
  389. package/out/live-probe/env-report.mjs +0 -8
  390. package/out/mcp.js +0 -654
  391. package/out/pack/caps.js +0 -271
  392. package/out/pack/governor.js +0 -326
  393. package/out/pack/lease-schema.js +0 -273
  394. package/out/pack/lease.js +0 -682
  395. package/out/pack/reconcile.js +0 -217
  396. package/out/pack/signature.js +0 -839
  397. package/out/permissions.js +0 -108
  398. package/out/permissions.mapping.yaml +0 -68
  399. package/out/registry/index.js +0 -332
  400. package/out/runner/host.js +0 -141
  401. package/out/runner/protocol.js +0 -128
  402. package/out/runner/remoteEngine.js +0 -166
  403. package/out/runtime/interfaces/config-provider.js +0 -32
  404. package/out/runtime/interfaces/edit-tracker.js +0 -24
  405. package/out/runtime/interfaces/index.js +0 -29
  406. package/out/runtime/interfaces/logger.js +0 -40
  407. package/out/runtime/interfaces/permission-handler.js +0 -66
  408. package/out/runtime/interfaces/session-store.js +0 -342
  409. package/out/runtime/vscode/vscode-session-store.js +0 -22
  410. package/out/sandbox/containerDriver.js +0 -572
  411. package/out/sandbox/processDriver.js +0 -318
  412. package/out/sandbox/sandboxRunner.js +0 -303
  413. package/out/sandbox/support.js +0 -301
  414. package/out/sandbox/types.js +0 -55
  415. package/out/scripts/analytics/fleet-local-adapter.js +0 -246
  416. package/out/scripts/analytics/live-fleet-4-collector.cjs +0 -315
  417. package/out/scripts/analytics/live-fleet-4-daemon.mjs +0 -134
  418. package/out/scripts/analytics/live-fleet-4-widget.cjs +0 -433
  419. package/out/scripts/gateway/Dockerfile.serve +0 -45
  420. package/out/scripts/gateway/docker-serve.sh +0 -248
  421. package/out/scripts/gateway/setup-gateway-server.ps1 +0 -953
  422. package/out/scripts/gateway/setup-gateway-server.sh +0 -935
  423. package/out/session.js +0 -272
  424. package/out/shared/agentEngines.js +0 -170
  425. package/out/shared/index.js +0 -109
  426. package/out/shared/models.js +0 -136
  427. package/out/shared/providers.js +0 -205
  428. package/out/spotlight/install.js +0 -345
  429. package/out/spotlight/publish.js +0 -544
  430. package/out/spotlight/yaml.js +0 -31
  431. package/out/store/index.js +0 -786
  432. package/out/store/shared.js +0 -241
  433. package/out/test/agentEnvFile.test.js +0 -97
  434. package/out/test/agentYaml.test.js +0 -373
  435. package/out/test/agentpack.test.js +0 -639
  436. package/out/test/analytics-lifecycle.test.js +0 -174
  437. package/out/test/analytics.test.js +0 -756
  438. package/out/test/auth-baseurl.test.js +0 -132
  439. package/out/test/auth-bootstrapApply.test.js +0 -123
  440. package/out/test/auth-broker-hardening.test.js +0 -227
  441. package/out/test/auth-broker.test.js +0 -541
  442. package/out/test/auth-callback.test.js +0 -62
  443. package/out/test/blueprint-registry.test.js +0 -105
  444. package/out/test/branding.test.js +0 -242
  445. package/out/test/caps-governor.test.js +0 -460
  446. package/out/test/cli-agent-id.test.js +0 -55
  447. package/out/test/codex-new-file-survival.test.js +0 -119
  448. package/out/test/configuration-scopes.test.js +0 -131
  449. package/out/test/credential-context.test.js +0 -160
  450. package/out/test/custom-env-layering.test.js +0 -151
  451. package/out/test/customEngineInstall.test.js +0 -100
  452. package/out/test/customRegistry.test.js +0 -122
  453. package/out/test/data-plane-engine-wiring.test.js +0 -282
  454. package/out/test/data-plane.test.js +0 -624
  455. package/out/test/deploy-init.test.js +0 -860
  456. package/out/test/deps-auto-install.test.js +0 -81
  457. package/out/test/egress-broker.test.js +0 -172
  458. package/out/test/engine-integration.test.js +0 -297
  459. package/out/test/enginePaths.test.js +0 -195
  460. package/out/test/enginePublish.test.js +0 -82
  461. package/out/test/fleetDisplayUtils.test.js +0 -100
  462. package/out/test/gateway-client.test.js +0 -409
  463. package/out/test/gateway-install-source.test.js +0 -111
  464. package/out/test/gateway-lifecycle.test.js +0 -608
  465. package/out/test/gateway-outbound.test.js +0 -538
  466. package/out/test/gateway-reset-mappings.test.js +0 -221
  467. package/out/test/gateway-route-index.test.js +0 -235
  468. package/out/test/gateway-secrets-preflight.test.js +0 -127
  469. package/out/test/gateway-session-routing.test.js +0 -65
  470. package/out/test/gateway-session-store.test.js +0 -216
  471. package/out/test/github.test.js +0 -232
  472. package/out/test/governor-hardening.test.js +0 -222
  473. package/out/test/headless-sync.test.js +0 -301
  474. package/out/test/helpers/manifest-fixtures.js +0 -27
  475. package/out/test/idp-init.test.js +0 -151
  476. package/out/test/lease-signature.test.js +0 -357
  477. package/out/test/lease-trust-root.test.js +0 -273
  478. package/out/test/lease-validation.test.js +0 -224
  479. package/out/test/lease.test.js +0 -114
  480. package/out/test/localFleetAdapter.test.js +0 -91
  481. package/out/test/mcp-obo.test.js +0 -107
  482. package/out/test/mcp.test.js +0 -389
  483. package/out/test/model-routing.test.js +0 -133
  484. package/out/test/openclaw-channel-routing.test.js +0 -191
  485. package/out/test/pack-admission.test.js +0 -216
  486. package/out/test/pack-digest-parity.test.js +0 -140
  487. package/out/test/pack-reconcile.test.js +0 -183
  488. package/out/test/pack-signature-artifact.test.js +0 -103
  489. package/out/test/pack-signature.test.js +0 -176
  490. package/out/test/pack-trust-root.test.js +0 -202
  491. package/out/test/pathSafety.test.js +0 -63
  492. package/out/test/permissions.test.js +0 -175
  493. package/out/test/persistent-engine-worker.test.js +0 -220
  494. package/out/test/refreshPolicy.test.js +0 -60
  495. package/out/test/registry.test.js +0 -351
  496. package/out/test/remote-trust.test.js +0 -242
  497. package/out/test/runner-protocol.test.js +0 -249
  498. package/out/test/runtime.test.js +0 -349
  499. package/out/test/sandbox-driver.test.js +0 -553
  500. package/out/test/sandbox-hardening.test.js +0 -406
  501. package/out/test/sandbox-runner.test.js +0 -343
  502. package/out/test/sandbox-scope.test.js +0 -449
  503. package/out/test/scheduledFleetStorage.test.js +0 -72
  504. package/out/test/serve-cron-acceptance.test.js +0 -370
  505. package/out/test/serve-gateway-turn.test.js +0 -389
  506. package/out/test/serve-hardening.test.js +0 -591
  507. package/out/test/serveClient.test.js +0 -209
  508. package/out/test/sessionJsonlFleet.test.js +0 -78
  509. package/out/test/sessionShip.test.js +0 -618
  510. package/out/test/shared.test.js +0 -173
  511. package/out/test/skills-mcp.test.js +0 -299
  512. package/out/test/spotlightPublish.test.js +0 -327
  513. package/out/test/spotlightYaml.test.js +0 -58
  514. package/out/test/state-sync-peer.test.js +0 -156
  515. package/out/test/store-install-safe.test.js +0 -69
  516. package/out/test/store.test.js +0 -331
  517. package/out/test/stores.test.js +0 -504
  518. package/out/test/sync-switch.test.js +0 -251
  519. package/out/test/teamViewDiscovery.test.js +0 -90
  520. package/out/test/tls-bypass.test.js +0 -90
  521. package/out/test/toolPath.test.js +0 -120
  522. package/out/test/utils.test.js +0 -308
  523. package/out/test/viewsConfigMerge.test.js +0 -180
  524. package/out/test/warrant.test.js +0 -138
  525. package/out/test/windows-command-line.test.js +0 -75
  526. package/out/utils/agentEnvFile.js +0 -131
  527. package/out/utils/binary.js +0 -175
  528. package/out/utils/index.js +0 -37
  529. package/out/utils/network.js +0 -74
  530. package/out/utils/paths.js +0 -116
  531. package/out/utils/pid.js +0 -180
  532. package/out/utils/resolveNodeBinary.js +0 -168
  533. package/out/utils/windowsCommandLine.js +0 -29
  534. 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;