@mikode13/harness 4.0.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/README.md +278 -16
  2. package/dist/agent/domain/agent.d.ts +12 -0
  3. package/dist/agent/domain/agent.js.map +1 -1
  4. package/dist/agent/domain/approval.d.ts +9 -0
  5. package/dist/agent/domain/approval.js.map +1 -1
  6. package/dist/agent/domain/runContext.d.ts +31 -0
  7. package/dist/agent/domain/runContext.js +47 -0
  8. package/dist/agent/domain/runContext.js.map +1 -0
  9. package/dist/diff/domain/unifiedDiff.d.ts +19 -0
  10. package/dist/diff/domain/unifiedDiff.js +166 -0
  11. package/dist/diff/domain/unifiedDiff.js.map +1 -0
  12. package/dist/engines/domain/model/historyFollower.d.ts +41 -0
  13. package/dist/engines/domain/model/historyFollower.js +158 -0
  14. package/dist/engines/domain/model/historyFollower.js.map +1 -0
  15. package/dist/engines/domain/model/llmAgent.d.ts +42 -4
  16. package/dist/engines/domain/model/llmAgent.js +223 -23
  17. package/dist/engines/domain/model/llmAgent.js.map +1 -1
  18. package/dist/factory/infrastructure/agentFactory.d.ts +14 -0
  19. package/dist/factory/infrastructure/agentFactory.js +20 -2
  20. package/dist/factory/infrastructure/agentFactory.js.map +1 -1
  21. package/dist/factory/infrastructure/agentLLMFactory.d.ts +119 -14
  22. package/dist/factory/infrastructure/agentLLMFactory.js +284 -57
  23. package/dist/factory/infrastructure/agentLLMFactory.js.map +1 -1
  24. package/dist/index.d.ts +11 -3
  25. package/dist/index.js +5 -2
  26. package/dist/index.js.map +1 -1
  27. package/dist/llm/domain/conversation.d.ts +44 -4
  28. package/dist/llm/domain/conversation.js +56 -7
  29. package/dist/llm/domain/conversation.js.map +1 -1
  30. package/dist/llm/domain/llm.d.ts +3 -1
  31. package/dist/llm/domain/llm.js.map +1 -1
  32. package/dist/llm/domain/tool.d.ts +13 -0
  33. package/dist/llm/domain/tool.js +12 -1
  34. package/dist/llm/domain/tool.js.map +1 -1
  35. package/dist/llm/infrastructure/claudeLLMClient.d.ts +3 -2
  36. package/dist/llm/infrastructure/claudeLLMClient.js +38 -10
  37. package/dist/llm/infrastructure/claudeLLMClient.js.map +1 -1
  38. package/dist/llm/infrastructure/openAILLMClient.d.ts +2 -1
  39. package/dist/llm/infrastructure/openAILLMClient.js +66 -16
  40. package/dist/llm/infrastructure/openAILLMClient.js.map +1 -1
  41. package/dist/orchestration/domain/model/orchestratorAgent.d.ts +11 -2
  42. package/dist/orchestration/domain/model/orchestratorAgent.js +43 -4
  43. package/dist/orchestration/domain/model/orchestratorAgent.js.map +1 -1
  44. package/dist/recovery/domain/fileChanges.d.ts +31 -0
  45. package/dist/recovery/domain/fileChanges.js +48 -0
  46. package/dist/recovery/domain/fileChanges.js.map +1 -0
  47. package/dist/recovery/domain/history.d.ts +114 -0
  48. package/dist/recovery/domain/history.js +62 -0
  49. package/dist/recovery/domain/history.js.map +1 -0
  50. package/dist/recovery/domain/recoveryStore.d.ts +233 -0
  51. package/dist/recovery/domain/recoveryStore.js +32 -0
  52. package/dist/recovery/domain/recoveryStore.js.map +1 -0
  53. package/dist/recovery/domain/retention.d.ts +33 -0
  54. package/dist/recovery/domain/retention.js +90 -0
  55. package/dist/recovery/domain/retention.js.map +1 -0
  56. package/dist/recovery/domain/runChanges.d.ts +37 -0
  57. package/dist/recovery/domain/runChanges.js +109 -0
  58. package/dist/recovery/domain/runChanges.js.map +1 -0
  59. package/dist/recovery/domain/runTree.d.ts +32 -0
  60. package/dist/recovery/domain/runTree.js +90 -0
  61. package/dist/recovery/domain/runTree.js.map +1 -0
  62. package/dist/recovery/infrastructure/createHistory.d.ts +11 -0
  63. package/dist/recovery/infrastructure/createHistory.js +17 -0
  64. package/dist/recovery/infrastructure/createHistory.js.map +1 -0
  65. package/dist/recovery/infrastructure/fileRecoveryStore.d.ts +133 -0
  66. package/dist/recovery/infrastructure/fileRecoveryStore.js +1043 -0
  67. package/dist/recovery/infrastructure/fileRecoveryStore.js.map +1 -0
  68. package/dist/recovery/infrastructure/workspaceFiles.d.ts +30 -0
  69. package/dist/recovery/infrastructure/workspaceFiles.js +125 -0
  70. package/dist/recovery/infrastructure/workspaceFiles.js.map +1 -0
  71. package/dist/tools/domain/accessPolicy.d.ts +30 -0
  72. package/dist/tools/domain/accessPolicy.js +11 -0
  73. package/dist/tools/domain/accessPolicy.js.map +1 -0
  74. package/dist/tools/domain/commands.d.ts +93 -0
  75. package/dist/tools/domain/commands.js +191 -0
  76. package/dist/tools/domain/commands.js.map +1 -0
  77. package/dist/tools/domain/editResponse.d.ts +14 -0
  78. package/dist/tools/domain/editResponse.js +79 -0
  79. package/dist/tools/domain/editResponse.js.map +1 -0
  80. package/dist/tools/domain/fileEdits.d.ts +64 -0
  81. package/dist/tools/domain/fileEdits.js +21 -0
  82. package/dist/tools/domain/fileEdits.js.map +1 -0
  83. package/dist/tools/domain/lineLength.d.ts +7 -0
  84. package/dist/tools/domain/lineLength.js +26 -0
  85. package/dist/tools/domain/lineLength.js.map +1 -0
  86. package/dist/tools/domain/preparedCall.d.ts +31 -0
  87. package/dist/tools/domain/preparedCall.js +14 -0
  88. package/dist/tools/domain/preparedCall.js.map +1 -0
  89. package/dist/tools/domain/readRegistry.d.ts +46 -0
  90. package/dist/tools/domain/readRegistry.js +62 -0
  91. package/dist/tools/domain/readRegistry.js.map +1 -0
  92. package/dist/tools/domain/textLines.d.ts +26 -0
  93. package/dist/tools/domain/textLines.js +44 -0
  94. package/dist/tools/domain/textLines.js.map +1 -0
  95. package/dist/tools/domain/v4aPatch.d.ts +17 -0
  96. package/dist/tools/domain/v4aPatch.js +236 -0
  97. package/dist/tools/domain/v4aPatch.js.map +1 -0
  98. package/dist/tools/infrastructure/boundedWorkspace.d.ts +11 -2
  99. package/dist/tools/infrastructure/boundedWorkspace.js +9 -1
  100. package/dist/tools/infrastructure/boundedWorkspace.js.map +1 -1
  101. package/dist/tools/infrastructure/commandCheckpoint.d.ts +55 -0
  102. package/dist/tools/infrastructure/commandCheckpoint.js +178 -0
  103. package/dist/tools/infrastructure/commandCheckpoint.js.map +1 -0
  104. package/dist/tools/infrastructure/commandProcess.d.ts +47 -0
  105. package/dist/tools/infrastructure/commandProcess.js +217 -0
  106. package/dist/tools/infrastructure/commandProcess.js.map +1 -0
  107. package/dist/tools/infrastructure/commandTool.d.ts +36 -0
  108. package/dist/tools/infrastructure/commandTool.js +254 -0
  109. package/dist/tools/infrastructure/commandTool.js.map +1 -0
  110. package/dist/tools/infrastructure/createWorkspace.d.ts +10 -0
  111. package/dist/tools/infrastructure/createWorkspace.js +11 -3
  112. package/dist/tools/infrastructure/createWorkspace.js.map +1 -1
  113. package/dist/tools/infrastructure/defineTool.d.ts +14 -0
  114. package/dist/tools/infrastructure/defineTool.js +28 -5
  115. package/dist/tools/infrastructure/defineTool.js.map +1 -1
  116. package/dist/tools/infrastructure/editFormats.d.ts +22 -0
  117. package/dist/tools/infrastructure/editFormats.js +211 -0
  118. package/dist/tools/infrastructure/editFormats.js.map +1 -0
  119. package/dist/tools/infrastructure/fileEditor.d.ts +64 -0
  120. package/dist/tools/infrastructure/fileEditor.js +306 -0
  121. package/dist/tools/infrastructure/fileEditor.js.map +1 -0
  122. package/dist/tools/infrastructure/fileTools.d.ts +81 -0
  123. package/dist/tools/infrastructure/fileTools.js +152 -0
  124. package/dist/tools/infrastructure/fileTools.js.map +1 -0
  125. package/dist/tools/infrastructure/gitIgnoreRules.d.ts +15 -0
  126. package/dist/tools/infrastructure/gitIgnoreRules.js +74 -0
  127. package/dist/tools/infrastructure/gitIgnoreRules.js.map +1 -0
  128. package/dist/tools/infrastructure/gitWorkspace.d.ts +1 -1
  129. package/dist/tools/infrastructure/gitWorkspace.js +1 -1
  130. package/dist/tools/infrastructure/gitWorkspace.js.map +1 -1
  131. package/dist/tools/infrastructure/ignoreFileChanges.d.ts +14 -0
  132. package/dist/tools/infrastructure/ignoreFileChanges.js +62 -0
  133. package/dist/tools/infrastructure/ignoreFileChanges.js.map +1 -0
  134. package/dist/tools/infrastructure/policyWorkspace.d.ts +52 -0
  135. package/dist/tools/infrastructure/policyWorkspace.js +32 -0
  136. package/dist/tools/infrastructure/policyWorkspace.js.map +1 -0
  137. package/dist/tools/infrastructure/ripgrepWorkspace.d.ts +2 -1
  138. package/dist/tools/infrastructure/ripgrepWorkspace.js +1 -1
  139. package/dist/tools/infrastructure/ripgrepWorkspace.js.map +1 -1
  140. package/dist/tools/infrastructure/rootsAccessPolicy.d.ts +100 -0
  141. package/dist/tools/infrastructure/rootsAccessPolicy.js +301 -0
  142. package/dist/tools/infrastructure/rootsAccessPolicy.js.map +1 -0
  143. package/dist/tools/infrastructure/runProcess.d.ts +4 -1
  144. package/dist/tools/infrastructure/runProcess.js +4 -2
  145. package/dist/tools/infrastructure/runProcess.js.map +1 -1
  146. package/dist/tools/infrastructure/secretPaths.d.ts +8 -0
  147. package/dist/tools/infrastructure/secretPaths.js +76 -0
  148. package/dist/tools/infrastructure/secretPaths.js.map +1 -0
  149. package/dist/tools/infrastructure/showChangesTool.d.ts +12 -0
  150. package/dist/tools/infrastructure/showChangesTool.js +43 -0
  151. package/dist/tools/infrastructure/showChangesTool.js.map +1 -0
  152. package/dist/tools/infrastructure/trackedEdits.d.ts +33 -0
  153. package/dist/tools/infrastructure/trackedEdits.js +70 -0
  154. package/dist/tools/infrastructure/trackedEdits.js.map +1 -0
  155. package/dist/tools/infrastructure/trackedReadFile.d.ts +21 -0
  156. package/dist/tools/infrastructure/trackedReadFile.js +78 -0
  157. package/dist/tools/infrastructure/trackedReadFile.js.map +1 -0
  158. package/dist/tools/infrastructure/workspaceTools.d.ts +28 -0
  159. package/dist/tools/infrastructure/workspaceTools.js +53 -40
  160. package/dist/tools/infrastructure/workspaceTools.js.map +1 -1
  161. package/dist/tools/infrastructure/workspaceWrites.d.ts +23 -0
  162. package/dist/tools/infrastructure/workspaceWrites.js +42 -0
  163. package/dist/tools/infrastructure/workspaceWrites.js.map +1 -0
  164. package/dist/tools/infrastructure/writeSession.d.ts +35 -0
  165. package/dist/tools/infrastructure/writeSession.js +81 -0
  166. package/dist/tools/infrastructure/writeSession.js.map +1 -0
  167. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileRecoveryStore.js","sourceRoot":"","sources":["../../../src/recovery/infrastructure/fileRecoveryStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EACN,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,EAAE,EACF,IAAI,EACJ,QAAQ,EACR,MAAM,GACN,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAmB,WAAW,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACnF,OAAO,EACN,YAAY,EAOZ,kBAAkB,EAMlB,kBAAkB,EAClB,mBAAmB,GACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC/F,OAAO,EACN,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,eAAe,EACf,aAAa,EACb,cAAc,GACd,MAAM,qBAAqB,CAAC;AAE7B,MAAM,OAAO,GAAG,gBAAgB,CAAC;AACjC,6EAA6E;AAC7E,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAC/B,MAAM,WAAW,GAAG,KAAK,CAAC;AAE1B,MAAM,YAAY,GAAG,eAAe,CAAC;AAErC,kGAAkG;AAClG,MAAM,eAAe,GAAG,EAAE,CAAC;AAE3B,MAAM,YAAY,GAAG,4BAA4B,CAAC;AAClD,MAAM,WAAW,GAAG,gBAAgB,CAAC;AAErC,8FAA8F;AAC9F,MAAM,UAAU,qBAAqB,CACpC,MAAyB,OAAO,CAAC,GAAG,EACpC,WAA4B,OAAO,CAAC,QAAQ,EAC5C,OAAe,OAAO,EAAE;IAExB,4FAA4F;IAC5F,MAAM,GAAG,GAAG,GAAG,CAAC,cAAc,CAAC;IAC/B,IAAI,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACtD,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,qBAAqB,EAAE,OAAO,CAAC,CAAC;IACxF,OAAO,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAC/C,CAAC;AAED,6EAA6E;AAC7E,SAAS,QAAQ;IAChB,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;AAC9F,CAAC;AAED,SAAS,MAAM,CAAC,OAAe;IAC9B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IACjC,OAAQ,KAA+B,CAAC,IAAI,KAAK,QAAQ,CAAC;AAC3D,CAAC;AAED;;;;GAIG;AACH,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;AAEnC,qDAAqD;AACrD,SAAS,YAAY,CAAC,MAAuC;IAC5D,4DAA4D;IAC5D,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC1C,IAAI,MAAM,CAAC,GAAG,KAAK,OAAO,CAAC,GAAG;QAAE,OAAO,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAClE,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,wEAAwE;AACxE,SAAS,OAAO,CAAC,GAAW;IAC3B,IAAI,CAAC;QACJ,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAQ,KAA+B,CAAC,IAAI,KAAK,OAAO,CAAC;IAC1D,CAAC;AACF,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACxC,IAAI,CAAC;QACJ,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC;YAAS,CAAC;QACV,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;IACzB,CAAC;AACF,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAC7E,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO;IAChC,KAAK,IAAI,OAAO,GAAG,IAAI,GAAI,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACvD,MAAM,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;QACtC,IAAI,OAAO,KAAK,KAAK;YAAE,OAAO;IAC/B,CAAC;AACF,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,YAAY,CAC1B,IAAY,EACZ,OAAwB,EACxB,EAAE,SAAS,GAAG,KAAK,KAA8B,EAAE;IAEnD,MAAM,SAAS,GAAG,GAAG,IAAI,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;IAClE,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;QACxD,IAAI,CAAC;YACJ,MAAM,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YAChC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACrB,CAAC;gBAAS,CAAC;YACV,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC;QACD,gEAAgE;QAChE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;YAAS,CAAC;QACV,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;IACD,MAAM,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AACpC,CAAC;AAqCD;;;GAGG;AACH,KAAK,UAAU,YAAY,CAC1B,gBAAwB,EACxB,OAAe;IAEf,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,WAAW,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CACnC,GAAG,EAAE,CAAC,IAAI,EACV,CAAC,KAAc,EAAE,EAAE;QAClB,IAAI,UAAU,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACpC,MAAM,KAAK,CAAC;IACb,CAAC,CACD,CAAC;IACF,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,MAAM,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACnC,MAAM,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC;AACnC,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAO,iBAAiB;IACZ,IAAI,CAAS;IACb,SAAS,CAAS;IAClB,QAAQ,CAAS;IAElC,YAAoB,IAAY,EAAE,SAAiB,EAAE,QAAgB;QACpE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EACjB,IAAI,EACJ,SAAS,GAAG,qBAAqB,EAAE,EACnC,QAAQ,GAAG,eAAe,GAW1B;QACA,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,UAAU,CAAC,kDAAkD,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC5F,CAAC;QACD,4EAA4E;QAC5E,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,SAAS,GAAG,IAAI,CACrB,SAAS,EACT,YAAY,EACZ,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAChE,CAAC;QACF,MAAM,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7C,MAAM,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;QAChD,MAAM,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;QAE1F,OAAO,IAAI,iBAAiB,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC7D,CAAC;IAED,KAAK,CAAC,QAAQ;QACb,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC;YACJ,yFAAyF;YACzF,6CAA6C;YAC7C,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvB,MAAM,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACpC,uDAAuD;YACvD,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC/B,yFAAyF;YACzF,YAAY;YACZ,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;YACnB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC;YAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACzD,MAAM,aAAa,CAAC,YAAY,CAAC,CAAC;YAClC,MAAM,MAAM,GAAc;gBACzB,KAAK;gBACL,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,MAAM,EAAE,SAAS;gBACjB,GAAG,EAAE,OAAO,CAAC,GAAG;aAChB,CAAC;YACF,MAAM,YAAY,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;YAC3E,uEAAuE;YACvE,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YACzD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;YAC/E,MAAM,aAAa,CAAC,YAAY,CAAC,CAAC;YAElC,OAAO,IAAI,cAAc,CAAC;gBACzB,MAAM;gBACN,YAAY;gBACZ,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC;gBACjD,OAAO;gBACP,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;gBACtC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;aACjC,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzB,MAAM,KAAK,CAAC;QACb,CAAC;IACF,CAAC;IAED,KAAK,CAAC,QAAQ;QACb,MAAM,GAAG,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9F,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAgB,EAAE,CAAC;QAC7B,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;YAChC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBACpE,mFAAmF;gBACnF,0CAA0C;gBAC1C,IAAI,UAAU,CAAC,KAAK,CAAC;oBAAE,OAAO,SAAS,CAAC;gBACxC,MAAM,KAAK,CAAC;YACb,CAAC,CAAC,CAAC;YACH,IAAI,MAAM;gBAAE,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QACvD,CAAC;QACD,4FAA4F;QAC5F,sBAAsB;QACtB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC;YACpB,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC;YAC1C,GAAG,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;SAC5B,CAAC,CAAC;QACH,2FAA2F;QAC3F,8EAA8E;QAC9E,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACxB,IAAI,GAAG,CAAC,MAAM,KAAK,aAAa;gBAAE,SAAS;YAC3C,0FAA0F;YAC1F,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YACtF,IAAI,OAAO,IAAI,cAAc,CAAC,OAAO,CAAC;gBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC7D,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACvE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5C,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAEtE,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;IACtF,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAAa;QAC1B,0DAA0D;QAC1D,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC;QAChE,2FAA2F;QAC3F,mCAAmC;QACnC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;QAC5D,mFAAmF;QACnF,MAAM,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,KAAc,EAAE,EAAE;YAC1E,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;gBAAE,MAAM,KAAK,CAAC;YACpC,qDAAqD;YACrD,MAAM,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACpC,MAAM,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QACH,OAAO;YACN,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC;YACtC,OAAO,EAAE,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC;SACtD,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,KAAa;QACrC,OAAO,IAAI,CAAC,KAAK,CAChB,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,CACrD,CAAC;IAChB,CAAC;IAEO,YAAY,CAAC,KAAa;QACjC,gEAAgE;QAChE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,KAAK,EAAE,CAAC,CAAC;QACzE,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;IAEO,KAAK,CAAC,QAAQ;QACrB,IAAI,CAAC;YACJ,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CACtB,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CACxC,CAAC;YACnB,OAAO,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,CAAC,EAAE,CAAC;QAClD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,UAAU,CAAC,KAAK,CAAC;gBAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;YAC9C,MAAM,KAAK,CAAC;QACb,CAAC;IACF,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,IAAU;QACjC,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,IAAI,CAAC,MAAc,EAAE,UAAuB,EAAE;QAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;IACjF,CAAC;IAED,IAAI,CAAC,UAAuB,EAAE;QAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE;YACnC,IAAI,IAAI,KAAK,SAAS;gBAAE,MAAM,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAC7D,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,KAAK,IAAI,CAAC,EAAE,WAAW,CAAC;QAC1D,CAAC,EAAE,OAAO,CAAC,CAAC;IACb,CAAC;IAED,IAAI,CAAC,UAAuB,EAAE;QAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE;YAC9C,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;YACjD,IAAI,MAAM,KAAK,SAAS;gBAAE,MAAM,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAC/D,OAAO,MAAM,CAAC;QACf,CAAC,EAAE,OAAO,CAAC,CAAC;IACb,CAAC;IAED,KAAK,CAAC,aAAa;QAClB,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACJ,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAC;QACxE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,UAAU,CAAC,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YACjC,MAAM,KAAK,CAAC;QACb,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YACpC,IAAI,IAAI,KAAK,EAAE;gBAAE,OAAO,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACJ,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAa,CAAC,CAAC;YACvC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,kFAAkF;gBAClF,4DAA4D;gBAC5D,IAAI,KAAK,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC;oBAAE,OAAO,EAAE,CAAC;gBAC1C,MAAM,IAAI,KAAK,CAAC,oDAAoD,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,EAAE;oBACxF,KAAK,EAAE,KAAK;iBACZ,CAAC,CAAC;YACJ,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,qFAAqF;IAC7E,KAAK,CAAC,IAAI,CACjB,OAIwB,EACxB,EAAE,MAAM,EAAE,IAAI,EAAe;QAE7B,MAAM,MAAM,GAAG,QAAQ,QAAQ,EAAE,EAAE,CAAC;QACpC,IAAI,CAAC;YACJ,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACxB,MAAM,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;YACrC,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,uFAAuF;YACvF,yBAAyB;YACzB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,IAAI,YAAY,CAAC;YACtC,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE;gBAAE,MAAM,IAAI,mBAAmB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC/E,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YACvC,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;YACtF,IAAI,EAAE,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,KAAK,EAAE,CAAC,EAAE,CAAC;gBAC7D,MAAM,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;YAClC,CAAC;YAED,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE;gBACvC,QAAQ,EAAE,IAAI,CAAC,QAAQ,GAAG,CAAC;gBAC3B,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3C,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrB,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;gBAC3C,SAAS,EAAE,EAAE;aACb,CAAC,CAAC;QACJ,CAAC;gBAAS,CAAC;YACV,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC;IACF,CAAC;IAED,yFAAyF;IACjF,KAAK,CAAC,iBAAiB;QAC9B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnC,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,mEAAmE;QACnE,IAAI,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3F,MAAM,IAAI,CAAC,SAAS,CAAC;gBACpB,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5C,QAAQ,EAAE,OAAO,CAAC,QAAQ;aAC1B,CAAC,CAAC;YACH,OAAO;QACR,CAAC;QACD,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACnE,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,SAAS,CAAC,IAAU,EAAE,IAAiB,EAAE,OAAoB;QAC1E,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QAC3D,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACvE,IAAI,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,MAAM,IAAI,GAAG,GAAG,EAAE,CACjB,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QAE9F,2DAA2D;QAC3D,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACvB,MAAM,eAAe,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YACzC,OAAO,OAAO,CAAC,SAAS,CAAC;QAC1B,CAAC;QACD,MAAM,IAAI,EAAE,CAAC;QACb,MAAM,QAAQ,GAAG,KAAK,EAAE,SAA6B,EAAE,EAAE;YACxD,IAAI,SAAS,KAAK,SAAS;gBAAE,OAAO,OAAO,CAAC,SAAS,CAAC;;gBACjD,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;YACnC,MAAM,IAAI,EAAE,CAAC;QACd,CAAC,CAAC;QACF,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;YAC1B,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;YACtE,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC7B,MAAM,IAAI,EAAE,CAAC;QACd,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;YAC1B,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;YACtE,OAAO,GAAG,KAAK,CAAC;YAChB,MAAM,IAAI,EAAE,CAAC;QACd,CAAC;QAED,0EAA0E;QAC1E,OAAO,OAAO,CAAC,SAAS,CAAC;QACzB,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;QACvC,MAAM,QAAQ,GAAa;YAC1B,GAAG,IAAI;YACP,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC5B,QAAQ,EAAE,SAAS,CAAC,MAAM,KAAK,CAAC;YAChC,SAAS;SACT,CAAC;QACF,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QACpC,MAAM,IAAI,CAAC,SAAS,CAAC;YACpB,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5C,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC1B,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED,kFAAkF;IAC1E,KAAK,CAAC,IAAI,CACjB,KAAa,EACb,SAA0B,EAC1B,QAA0D;QAE1D,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAmB,EAAE,CAAC;QACrC,uFAAuF;QACvF,KAAK,MAAM,MAAM,IAAI,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;YACzE,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;gBACzD,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC9C,CAAC;QACF,CAAC;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,QAAQ,CACrB,MAAkB,EAClB,SAA0B,EAC1B,QAA0D;QAE1D,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAC1B,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QACtF,sFAAsF;QACtF,0DAA0D;QAC1D,IAAI,CAAC,CAAC,MAAM,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QACvD,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAEhD,IAAI,OAAO,IAAI,SAAS,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC;YAChD,IAAI,SAAS,KAAK,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;gBACjD,MAAM,kBAAkB,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YACjD,CAAC;YACD,OAAO,IAAI,CAAC;QACb,CAAC;QACD,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;YAAE,OAAO,KAAK,CAAC;QAC1D,uFAAuF;QACvF,gCAAgC;QAChC,IAAI,SAAS,KAAK,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,OAAO,KAAK,CAAC;QAE7D,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;YACxB,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC7C,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC;YAC1B,MAAM,cAAc,CACnB,MAAM,CAAC,IAAI,EACX,MAAM,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,EACxC,WAAW,CAAC,IAAI,EAChB,SAAS,CACT,CAAC;YACF,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC3B,CAAC;aAAM,CAAC;YACP,MAAM,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,SAAS,KAAK,MAAM;gBAAE,MAAM,kBAAkB,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,IAAI,CAAC;IACb,CAAC;IAED,gGAAgG;IACxF,KAAK,CAAC,iBAAiB,CAAC,KAAa;QAC5C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/D,IAAI,MAAM;YAAE,MAAM,IAAI,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACrF,CAAC;IAEO,KAAK,CAAC,UAAU;QACvB,IAAI,CAAC;YACJ,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;YAC1E,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;gBACtC,IAAI,CAAC;oBACJ,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAW,CAAC,CAAC;gBACrC,CAAC;gBAAC,MAAM,CAAC;oBACR,0DAA0D;oBAC1D,OAAO,EAAE,CAAC;gBACX,CAAC;YACF,CAAC,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,UAAU,CAAC,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YACjC,MAAM,KAAK,CAAC;QACb,CAAC;IACF,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,KAAK;QAClB,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC1B,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC7C,SAAS,CAAC;YACT,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC7C,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;YACrE,IAAI,CAAC,IAAI;gBAAE,MAAM;YACjB,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;;gBACxD,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,CAAC;QACD,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;IAC7B,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,KAAK,CAAC,KAAa,EAAE,KAAa;QAC/C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,YAAY,CAC3B,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,EAClD,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,CAClD,CAAC;QACF,MAAM,OAAO,GAAG,WAAW,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC;QAClE,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,EAAE,EAAiB,EAAE,CAAC;YACjF,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,MAAM,EAAE;YACzC,GAAG,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAW,CAAC,CAAC;SACvE,CAAC,CAAC;QACH,MAAM,YAAY,CACjB,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,EACvC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CACvD,CAAC;QAEF,MAAM,MAAM,GAAc;YACzB,GAAG,WAAW;YACd,QAAQ,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,WAAW,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;YACnF,OAAO;SACP,CAAC;QACF,sEAAsE;QACtE,IAAI,WAAW,CAAC,WAAW;YAAE,MAAM,CAAC,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC;;YACrE,OAAO,MAAM,CAAC,WAAW,CAAC;QAC/B,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QACvF,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;IAC3B,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,YAAY;QACzB,KAAK,MAAM,KAAK,IAAI,MAAM,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;YAC7C,MAAM,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACtE,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACvC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACxB,KAAK,MAAM,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;gBAC3C,MAAM,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACzE,CAAC;YACD,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,YAAY,CAAC;YAC5C,KAAK,MAAM,IAAI,IAAI,MAAM,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBAChE,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;oBAC/E,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBACrE,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,SAAS,CAAC,KAAa;QACpC,MAAM,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;QACjE,sFAAsF;QACtF,MAAM,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACpC,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACtE,MAAM,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9C,MAAM,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtE,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,UAAU,CAAC,MAAiB;QACzC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5D,IAAI,SAAS,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC;YAChC,MAAM,IAAI,CAAC,SAAS,CAAC;gBACpB,GAAG,IAAI;gBACP,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC5D,CAAC,CAAC;QACJ,CAAC;QACD,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7E,MAAM,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACrD,MAAM,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,yDAAyD;IACjD,KAAK,CAAC,cAAc;QAC3B,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;QACrC,KAAK,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAChD,KAAK,MAAM,KAAK,IAAI,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpE,KAAK,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;oBACjD,IAAI,KAAK,CAAC,MAAM;wBAAE,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC9C,CAAC;YACF,CAAC;QACF,CAAC;QACD,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACzD,KAAK,MAAM,MAAM,IAAI,MAAM,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACtD,KAAK,MAAM,IAAI,IAAI,MAAM,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;gBAClE,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBACrD,MAAM,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBACjE,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,QAAkB;QAC9C,MAAM,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;QACvE,MAAM,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,iBAAiB,CAAC,QAAgB;QAC/C,MAAM,GAAG,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAC/D,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,QAAQ,CAC9C,CAAC;QACF,KAAK,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBACpE,IAAI,UAAU,CAAC,KAAK,CAAC;oBAAE,OAAO,SAAS,CAAC;gBACxC,MAAM,KAAK,CAAC;YACb,CAAC,CAAC,CAAC;YACH,IAAI,MAAM,EAAE,MAAM,KAAK,SAAS;gBAAE,SAAS;YAE3C,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;YAC9D,MAAM,OAAO,GAAkB,EAAE,CAAC;YAClC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACrC,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;oBAAE,SAAS;gBACrE,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC7C,IAAI,KAAK,IAAI,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC5C,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAC7D,CAAC;qBAAM,IAAI,KAAK,IAAI,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;oBACpD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAC/D,CAAC;YACF,CAAC;YACD,IAAI,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;YACpC,KAAK,MAAM,WAAW,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;gBAChD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;gBACnF,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC;gBACzB,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;YACxB,CAAC;YACD,MAAM,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,IAAI,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;YAC3F,IAAI,cAAc,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;gBACnE,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;gBAC9B,SAAS;YACV,CAAC;YACD,6FAA6F;YAC7F,MAAM,YAAY,CACjB,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,EAC1C,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,aAAa,EAAsB,CAAC,CACxE,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,iBAAiB,CAC9B,WAA4B,EAC5B,OAAuB,EACvB,YAAoB;QAEpB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YACpF,IAAI,UAAU,CAAC,KAAK,CAAC;gBAAE,OAAO,SAAS,CAAC;YACxC,MAAM,KAAK,CAAC;QACb,CAAC,CAAC,CAAC;QACH,mFAAmF;QACnF,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC3E,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAa,CAAC;QACjE,MAAM,QAAQ,GAAG,IAAI,GAAG,CACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CACvF,CAAC;QACF,MAAM,KAAK,GAAkB,EAAE,CAAC;QAChC,IAAI,QAAQ,GAAG,YAAY,CAAC;QAC5B,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7D,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YACtD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YACzC,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC;gBAAE,SAAS;YACjD,QAAQ,EAAE,CAAC;YACX,KAAK,CAAC,IAAI,CACT,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE,EAC/E,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAC7B,CAAC;QACH,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjE,OAAO,KAAK,CAAC;IACd,CAAC;IAED,gGAAgG;IACxF,KAAK,CAAC,SAAS,CAAC,IAAY;QACnC,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK,EAAE,MAAM;YAAE,OAAO,KAAK,CAAC;QACjC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YAC7D,IAAI,UAAU,CAAC,KAAK,CAAC;gBAAE,OAAO,SAAS,CAAC;YACxC,MAAM,KAAK,CAAC;QACb,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QACvC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;QAC9E,2EAA2E;QAC3E,OAAO,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,KAAa,EAAE,OAAO,GAAG,YAAY;QAC9D,OAAO,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IACzD,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,WAAW,CACxB,KAAa,EACb,OAAO,GAAG,YAAY;QAEtB,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACJ,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC;QACxE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,wEAAwE;YACxE,IAAI,UAAU,CAAC,KAAK,CAAC;gBAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;YACjF,MAAM,KAAK,CAAC;QACb,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE/B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;QAChD,MAAM,YAAY,GAAG,IAAI,GAAG,EAA2B,CAAC;QACxD,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YAC7B,IAAI,IAAI,KAAK,EAAE;gBAAE,OAAO;YACxB,IAAI,IAAiB,CAAC;YACtB,IAAI,CAAC;gBACJ,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAgB,CAAC;YACxC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,kFAAkF;gBAClF,uDAAuD;gBACvD,IAAI,KAAK,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC;oBAAE,OAAO;gBACvC,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,uBAAuB,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,EAAE;oBACtF,KAAK,EAAE,KAAK;iBACZ,CAAC,CAAC;YACJ,CAAC;YACD,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YACrD,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC9B,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;gBAC3E,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE;oBACrB,QAAQ;oBACR,IAAI;oBACJ,MAAM;oBACN,KAAK;oBACL,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC7C,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;oBACnD,MAAM,EAAE,UAAU;iBAClB,CAAC,CAAC;gBACH,OAAO;YACR,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBAC/B,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC;gBACxC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;gBACvD,OAAO;YACR,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC9B,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACnC,OAAO;YACR,CAAC;YACD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACzC,IAAI,KAAK;gBAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,OAAO;YACN,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YAC9B,YAAY,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC;YACxC,YAAY;SACZ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,IAAY;QAC7B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;QAC5E,OAAO,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACrE,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,KAAa;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC1C,gFAAgF;QAChF,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC;YAC9C,IAAI,CAAC;gBACJ,kFAAkF;gBAClF,MAAM,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC3F,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBACpB,OAAO;YACR,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;oBAAE,MAAM,KAAK,CAAC;YACrE,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;YACpC,iCAAiC;YACjC,IAAI,CAAC,MAAM;gBAAE,SAAS;YACtB,IAAI,YAAY,CAAC,MAAM,CAAC;gBAAE,MAAM,IAAI,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACrE,mFAAmF;YACnF,gEAAgE;YAChE,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;YACnC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,KAAK,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC;gBACrF,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;oBAC3C,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;wBAAE,MAAM,KAAK,CAAC;gBACrC,CAAC,CAAC,CAAC;YACJ,CAAC;QACF,CAAC;QAED,MAAM,IAAI,kBAAkB,CAAC,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI,SAAS,CAAC,CAAC;IAC1E,CAAC;IAEO,KAAK,CAAC,MAAM,CAAC,KAAa;QACjC,mFAAmF;QACnF,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC1C,sFAAsF;QACtF,IAAI,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,KAAK,KAAK;YAAE,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;IACjE,CAAC;CACD;AAED,8FAA8F;AAC9F,SAAS,cAAc,CAAC,OAAuB;IAC9C,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;AAC7D,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CACtB,MAAiB,EACjB,MAAmD;IAEnD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IAC/C,MAAM,IAAI,GAAG,MAAM,EAAE,KAAK,KAAK,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;IAChG,OAAO,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;AAC7D,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,KAAgB;IACxD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC/B,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,CAAC;QACJ,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,MAAM,KAAK,CAAC;IACrC,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACpD,IAAI,SAAS,GAAG,EAAE,CAAC;IACnB,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;QACjB,IAAI,WAAW,CAAC,IAAI,CAAC;YAAE,SAAS,GAAG,IAAI,CAAC;;YACnC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9E,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;IACnD,IAAI,CAAC;QACJ,MAAM,OAAO,CAAC,UAAU,CAAC,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9F,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;YAAS,CAAC;QACV,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACF,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAChC,IAAI,CAAC;QACJ,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjB,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;AACF,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,QAAQ,CAAC,IAAY;IACnC,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACJ,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,UAAU,CAAC,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QACxC,MAAM,KAAK,CAAC;IACb,CAAC;IACD,IAAI,CAAC;QACJ,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAuC,CAAC;QAC9E,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAa,EAAE,CAAC;IAC9F,CAAC;IAAC,MAAM,CAAC;QACR,oCAAoC;IACrC,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AAC7B,CAAC;AAED,SAAS,WAAW,CAAC,gBAAwB,EAAE,IAAY;IAC1D,qEAAqE;IACrE,OAAO,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,cAAc;IACV,KAAK,CAAS;IACN,MAAM,CAAY;IAClB,YAAY,CAAS;IACrB,gBAAgB,CAAS;IACzB,OAAO,CAAa;IACpB,OAAO,CAAsB;IAC7B,OAAO,CAAsB;IACtC,QAAQ,GAAG,CAAC,CAAC;IACb,MAAM,GAAG,CAAC,CAAC;IACnB,8FAA8F;IAC9F,0FAA0F;IACzE,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAC7C,gEAAgE;IACxD,OAAO,GAAqB,OAAO,CAAC,OAAO,EAAE,CAAC;IAC9C,QAAQ,GAAG,KAAK,CAAC;IACzB,4FAA4F;IAC5F,sCAAsC;IAC9B,MAAM,CAAU;IAExB,YAAY,EACX,MAAM,EACN,YAAY,EACZ,gBAAgB,EAChB,OAAO,EACP,OAAO,EACP,OAAO,GAQP;QACA,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QACzC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAe;QAChC,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QAC7E,IAAI,OAAO;YAAE,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;QAC3C,OAAO,IAAI,CAAC;IACb,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,MAAiD;QAC9D,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,MAAM,QAAQ,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC;QACjC,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC3B,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED,OAAO,CAAC,QAAgB;QACvB,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,QAAgB;QAC/B,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC;QACnD,kFAAkF;QAClF,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAgB,EAAE,EAAU;QACzC,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,MAAM,QAAQ,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC;QACjC,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QACjE,8DAA8D;QAC9D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC3B,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAgB,EAAE,OAA4B;QAC5D,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACnF,qDAAqD;QACrD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,WAAW;QACd,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;IAED,IAAI,OAAO;QACV,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAqD;QACjE,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC;YACJ,MAAM,IAAI,CAAC,OAAO,CAAC;YACnB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAC3B,uFAAuF;YACvF,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACnB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;gBACrB,OAAO;YACR,CAAC;YACD,MAAM,MAAM,GAAc,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;YAC3F,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QACjF,CAAC;gBAAS,CAAC;YACV,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACtB,CAAC;IACF,CAAC;IAEO,MAAM,CAAC,IAAiB;QAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;YAC1C,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,CAAC,KAAK,+BAA+B,EAAE;oBAChF,KAAK,EAAE,IAAI,CAAC,MAAM;iBAClB,CAAC,CAAC;YACJ,CAAC;YACD,IAAI,CAAC;gBACJ,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC3D,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAC3B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,IAAI,CAAC,MAAM,GAAG,KAAK,IAAI,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;gBAC1D,MAAM,KAAK,CAAC;YACb,CAAC;QACF,CAAC,CAAC,CAAC;QACH,wFAAwF;QACxF,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC5C,OAAO,KAAK,CAAC;IACd,CAAC;IAEO,UAAU;QACjB,IAAI,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,uBAAuB,CAAC,CAAC;IAC9E,CAAC;CACD","sourcesContent":["import { createHash, randomBytes } from 'node:crypto';\nimport {\n\tlink,\n\tmkdir,\n\topen,\n\treaddir,\n\treadFile,\n\trealpath,\n\trename,\n\trm,\n\tstat,\n\ttruncate,\n\tunlink,\n} from 'node:fs/promises';\nimport type { FileHandle } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { dirname, isAbsolute, join } from 'node:path';\nimport { type FileChange, fileChanges, sameState } from '../domain/fileChanges.ts';\nimport {\n\thistoryStart,\n\ttype FileState,\n\ttype JournalEntry,\n\ttype Manifest,\n\ttype ObservationMeasure,\n\ttype MoveConflict,\n\ttype MoveOptions,\n\tNothingToMoveError,\n\ttype Revision,\n\ttype RecoveryStore,\n\ttype RunJournal,\n\ttype RunRecord,\n\ttype RunStatus,\n\tWorkspaceBusyError,\n\tWorkspaceMovedError,\n} from '../domain/recoveryStore.ts';\nimport { chainEntries, nextPruneStep } from '../domain/retention.ts';\nimport { HistoryExpiredError, redoTarget, route, UnknownRunError } from '../domain/runTree.ts';\nimport {\n\tcurrentState,\n\thasRealParents,\n\tremoveEmptyFolders,\n\tremoveFile,\n\tremoveTemporary,\n\ttemporaryPath,\n\twriteFileState,\n} from './workspaceFiles.ts';\n\nconst appName = 'mikode-harness';\n// The store holds source code the agent touched: only its owner may read it.\nconst privateDirectory = 0o700;\nconst privateFile = 0o600;\n\nconst firstJournal = 'journal.jsonl';\n\n// A run is roughly one prompt: enough to go back through a working session, not a project's life.\nconst defaultKeepRuns = 25;\n\nconst runIdPattern = /^\\d{8}T\\d{9}Z-[0-9a-f]{6}$/;\nconst hashPattern = /^[0-9a-f]{64}$/;\n\n/** Where an application keeps state that is neither configuration nor cache, per platform. */\nexport function defaultStateDirectory(\n\tenv: NodeJS.ProcessEnv = process.env,\n\tplatform: NodeJS.Platform = process.platform,\n\thome: string = homedir(),\n): string {\n\t// The XDG spec says to ignore a relative path, which here could land inside the repository.\n\tconst xdg = env.XDG_STATE_HOME;\n\tif (xdg && isAbsolute(xdg)) return join(xdg, appName);\n\tif (platform === 'darwin') return join(home, 'Library', 'Application Support', appName);\n\treturn join(home, '.local', 'state', appName);\n}\n\n/** Sorts by start time as text, so the latest run is the last one listed. */\nfunction newRunId(): string {\n\treturn `${new Date().toISOString().replace(/[-:.]/g, '')}-${randomBytes(3).toString('hex')}`;\n}\n\nfunction hashOf(content: Buffer): string {\n\treturn createHash('sha256').update(content).digest('hex');\n}\n\nfunction isNotFound(error: unknown): boolean {\n\treturn (error as NodeJS.ErrnoException).code === 'ENOENT';\n}\n\n/**\n * The runs and moves this process holds a workspace lock for and has not ended. A lock naming\n * this process and none of these was left by one whose release failed: it is as stale as a dead\n * process's, which a process that lives on would otherwise keep until it exits.\n */\nconst heldHere = new Set<string>();\n\n/** Whether the holder of a lock is still at work. */\nfunction isLiveHolder(holder: { runId: string; pid?: number }): boolean {\n\t// A holder that cannot be named cannot be shown to be gone.\n\tif (holder.pid === undefined) return true;\n\tif (holder.pid === process.pid) return heldHere.has(holder.runId);\n\treturn isAlive(holder.pid);\n}\n\n/** Whether a process still exists. One we may not signal exists too. */\nfunction isAlive(pid: number): boolean {\n\ttry {\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch (error) {\n\t\treturn (error as NodeJS.ErrnoException).code === 'EPERM';\n\t}\n}\n\nasync function syncDirectory(path: string): Promise<void> {\n\tconst directory = await open(path, 'r');\n\ttry {\n\t\tawait directory.sync();\n\t} finally {\n\t\tawait directory.close();\n\t}\n}\n\n/**\n * Creates a private folder and any missing parents. A new folder only survives a crash once\n * its parent's entry for it is synced too, so each parent that gained one is.\n */\nasync function makeDirectory(path: string): Promise<void> {\n\tconst first = await mkdir(path, { recursive: true, mode: privateDirectory });\n\tif (first === undefined) return;\n\tfor (let created = path; ; created = dirname(created)) {\n\t\tawait syncDirectory(dirname(created));\n\t\tif (created === first) return;\n\t}\n}\n\n/**\n * Puts `content` at `path` all at once: a crash leaves either the old file or the new one, never\n * half of the new one. It returns only once the new file is on disk. With `exclusive`, it fails\n * with `EEXIST` instead of replacing a file already there.\n */\nasync function writeDurably(\n\tpath: string,\n\tcontent: string | Buffer,\n\t{ exclusive = false }: { exclusive?: boolean } = {},\n): Promise<void> {\n\tconst temporary = `${path}.${randomBytes(6).toString('hex')}.tmp`;\n\ttry {\n\t\tconst handle = await open(temporary, 'wx', privateFile);\n\t\ttry {\n\t\t\tawait handle.writeFile(content);\n\t\t\tawait handle.sync();\n\t\t} finally {\n\t\t\tawait handle.close();\n\t\t}\n\t\t// A link fails if the path is taken; a rename would replace it.\n\t\tawait (exclusive ? link : rename)(temporary, path);\n\t} finally {\n\t\tawait rm(temporary, { force: true });\n\t}\n\tawait syncDirectory(dirname(path));\n}\n\n/** A move not finished yet: the next move or run finishes it before anything else. */\ninterface PendingMove {\n\trevision: number;\n\tfrom?: string;\n\tto?: string;\n\treason?: string;\n\t/** Found by the steps already taken. */\n\tconflicts: MoveConflict[];\n\t/**\n\t * The temporary a file is being restored through, named before it is created, so finishing\n\t * the move removes this one and no file of the user's.\n\t */\n\ttemporary?: string;\n}\n\n/** `head.json`: the run the workspace is at, the moves made so far, and one in progress. */\ninterface Head {\n\trunId?: string;\n\trevision: number;\n\tpending?: PendingMove;\n}\n\ntype JournalLine =\n\t| ({ type: 'prepared'; sequence: number } & Omit<JournalEntry, 'sequence' | 'status'>)\n\t| { type: 'applied' | 'abandoned'; sequence: number }\n\t| { type: 'observing'; sequence: number; manifest: string; by: string }\n\t| { type: 'observed'; sequence: number; measure?: ObservationMeasure };\n\n/** An observation a run began and never finished: what its command changed is not recorded yet. */\ninterface OpenObservation {\n\tsequence: number;\n\tmanifest: string;\n\tby: string;\n}\n\n/**\n * Stores `content` under its hash, unless it is stored already, and returns the hash and whether\n * it was new. It returns only once the content is on disk.\n */\nasync function storeContent(\n\tcontentDirectory: string,\n\tcontent: Buffer,\n): Promise<{ hash: string; written: boolean }> {\n\tconst hash = hashOf(content);\n\tconst path = contentPath(contentDirectory, hash);\n\tconst stored = await stat(path).then(\n\t\t() => true,\n\t\t(error: unknown) => {\n\t\t\tif (isNotFound(error)) return false;\n\t\t\tthrow error;\n\t\t},\n\t);\n\tif (!stored) {\n\t\tawait makeDirectory(dirname(path));\n\t\tawait writeDurably(path, content);\n\t}\n\treturn { hash, written: !stored };\n}\n\n/**\n * The recovery store on disk, in a private directory per workspace under the platform's state\n * directory:\n *\n * ```text\n * <directory>/workspaces/<hash of the root>/\n * workspace.json the root it belongs to\n * lock the run writing now, if any\n * head.json the run the workspace is at, and a move in progress\n * revisions.jsonl every move of the workspace through its history\n * content/<ab>/<hash> file contents, named by their SHA-256\n * runs/<runId>/run.json the run's record\n * runs/<runId>/journal.jsonl its changes, one line per step, appended and synced\n * ```\n *\n * The lock only keeps a second run of this harness from writing at the same time. It does not\n * stop an editor or another program, and two processes taking over a dead run's lock in the\n * same instant could both believe they hold it.\n */\nexport class FileRecoveryStore implements RecoveryStore {\n\tprivate readonly root: string;\n\tprivate readonly directory: string;\n\tprivate readonly keepRuns: number;\n\n\tprivate constructor(root: string, directory: string, keepRuns: number) {\n\t\tthis.root = root;\n\t\tthis.directory = directory;\n\t\tthis.keepRuns = keepRuns;\n\t}\n\n\tstatic async open({\n\t\troot,\n\t\tdirectory = defaultStateDirectory(),\n\t\tkeepRuns = defaultKeepRuns,\n\t}: {\n\t\troot: string;\n\t\t/** Defaults to the platform's state directory. */\n\t\tdirectory?: string;\n\t\t/**\n\t\t * The most runs kept per workspace, the one being recorded included. Defaults to 25. At\n\t\t * least 3: the run the workspace is at is never removed, and the last run of its line has\n\t\t * no next run to be chained into, so pruning can leave two runs besides the new one.\n\t\t */\n\t\tkeepRuns?: number;\n\t}): Promise<FileRecoveryStore> {\n\t\tif (!Number.isInteger(keepRuns) || keepRuns < 3) {\n\t\t\tthrow new RangeError(`keepRuns must be an integer of at least 3; got ${String(keepRuns)}`);\n\t\t}\n\t\t// Two spellings of one folder, such as a symlinked path, are one workspace.\n\t\tconst realRoot = await realpath(root);\n\t\tconst workspace = join(\n\t\t\tdirectory,\n\t\t\t'workspaces',\n\t\t\tcreateHash('sha256').update(realRoot).digest('hex').slice(0, 16),\n\t\t);\n\t\tawait makeDirectory(join(workspace, 'runs'));\n\t\tawait makeDirectory(join(workspace, 'content'));\n\t\tawait writeDurably(join(workspace, 'workspace.json'), JSON.stringify({ root: realRoot }));\n\n\t\treturn new FileRecoveryStore(realRoot, workspace, keepRuns);\n\t}\n\n\tasync startRun(): Promise<RunJournal> {\n\t\tconst runId = newRunId();\n\t\ttry {\n\t\t\t// Inside, because taking the lock can fail after publishing it. Unlocking removes only a\n\t\t\t// lock naming this run, never another run's.\n\t\t\tawait this.lock(runId);\n\t\t\tawait this.settleInterrupted(runId);\n\t\t\t// A run starts where the user last sent the workspace.\n\t\t\tawait this.finishPendingMove();\n\t\t\t// Before the new run exists, so it is never pruned, and after the move, so no run on its\n\t\t\t// route is.\n\t\t\tawait this.prune();\n\t\t\tconst head = await this.readHead();\n\t\t\tconst parentRunId = head.runId;\n\t\t\tconst runDirectory = join(this.directory, 'runs', runId);\n\t\t\tawait makeDirectory(runDirectory);\n\t\t\tconst record: RunRecord = {\n\t\t\t\trunId,\n\t\t\t\troot: this.root,\n\t\t\t\t...(parentRunId ? { parentRunId } : {}),\n\t\t\t\tstartedAt: new Date().toISOString(),\n\t\t\t\tstatus: 'running',\n\t\t\t\tpid: process.pid,\n\t\t\t};\n\t\t\tawait writeDurably(join(runDirectory, 'run.json'), JSON.stringify(record));\n\t\t\t// After the record, so the head never names a run that does not exist.\n\t\t\tawait this.writeHead({ runId, revision: head.revision });\n\t\t\tconst journal = await open(join(runDirectory, firstJournal), 'a', privateFile);\n\t\t\tawait syncDirectory(runDirectory);\n\n\t\t\treturn new FileRunJournal({\n\t\t\t\trecord,\n\t\t\t\trunDirectory,\n\t\t\t\tcontentDirectory: join(this.directory, 'content'),\n\t\t\t\tjournal,\n\t\t\t\tdiscard: () => this.discardRun(record),\n\t\t\t\trelease: () => this.unlock(runId),\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tawait this.unlock(runId);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync listRuns(): Promise<{ head?: string; runs: RunRecord[] }> {\n\t\tconst ids = (await readdir(join(this.directory, 'runs'))).filter(id => runIdPattern.test(id));\n\t\tconst holder = await readLock(join(this.directory, 'lock'));\n\t\tconst runs: RunRecord[] = [];\n\t\tfor (const runId of ids.sort()) {\n\t\t\tconst record = await this.readRecord(runId).catch((error: unknown) => {\n\t\t\t\t// A crash between creating a run's folder and writing its record leaves the folder\n\t\t\t\t// empty: that run never changed anything.\n\t\t\t\tif (isNotFound(error)) return undefined;\n\t\t\t\tthrow error;\n\t\t\t});\n\t\t\tif (record) runs.push(withLiveStatus(record, holder));\n\t\t}\n\t\t// A run retention removed or chained into a later one, whose folder a crash left behind, is\n\t\t// not in the history.\n\t\tconst gone = new Set([\n\t\t\t...runs.flatMap(run => run.absorbed ?? []),\n\t\t\t...(await this.listPruned()),\n\t\t]);\n\t\t// A dead run that changed nothing is not in the history either, though its removal did not\n\t\t// finish. No run follows it: the next run or move removes it before starting.\n\t\tfor (const run of runs) {\n\t\t\tif (run.status !== 'interrupted') continue;\n\t\t\t// A journal it cannot read leaves the run listed: whether it changed anything is unknown.\n\t\t\tconst entries = await this.readEntries(run.runId, run.journal).catch(() => undefined);\n\t\t\tif (entries && changedNothing(entries)) gone.add(run.runId);\n\t\t}\n\t\tconst parents = new Map(runs.map(run => [run.runId, run.parentRunId]));\n\t\tlet { runId: head } = await this.readHead();\n\t\twhile (head !== undefined && gone.has(head)) head = parents.get(head);\n\n\t\treturn { ...(head ? { head } : {}), runs: runs.filter(run => !gone.has(run.runId)) };\n\t}\n\n\tasync readRun(runId: string): Promise<{ record: RunRecord; entries: JournalEntry[] }> {\n\t\t// An id from outside is checked before it names a folder.\n\t\tif (!runIdPattern.test(runId)) throw new UnknownRunError(runId);\n\t\t// The lock first: a run that finishes between the two reads then shows as finished, not as\n\t\t// a `running` record nobody holds.\n\t\tconst holder = await readLock(join(this.directory, 'lock'));\n\t\t// Before the record: a crash can leave the folder of a run retention already took.\n\t\tawait this.assertNotAbsorbed(runId);\n\t\tconst record = await this.readRecord(runId).catch(async (error: unknown) => {\n\t\t\tif (!isNotFound(error)) throw error;\n\t\t\t// Retention may have taken it since the check above.\n\t\t\tawait this.assertNotAbsorbed(runId);\n\t\t\tthrow new UnknownRunError(runId);\n\t\t});\n\t\treturn {\n\t\t\trecord: withLiveStatus(record, holder),\n\t\t\tentries: await this.readEntries(runId, record.journal),\n\t\t};\n\t}\n\n\tprivate async readRecord(runId: string): Promise<RunRecord> {\n\t\treturn JSON.parse(\n\t\t\tawait readFile(join(this.runDirectory(runId), 'run.json'), 'utf8'),\n\t\t) as RunRecord;\n\t}\n\n\tprivate runDirectory(runId: string): string {\n\t\t// The id names a folder, so it must never be a path of its own.\n\t\tif (!runIdPattern.test(runId)) throw new Error(`Not a run id: ${runId}`);\n\t\treturn join(this.directory, 'runs', runId);\n\t}\n\n\tprivate async readHead(): Promise<Head> {\n\t\ttry {\n\t\t\tconst head = JSON.parse(\n\t\t\t\tawait readFile(join(this.directory, 'head.json'), 'utf8'),\n\t\t\t) as Partial<Head>;\n\t\t\treturn { ...head, revision: head.revision ?? 0 };\n\t\t} catch (error) {\n\t\t\tif (isNotFound(error)) return { revision: 0 };\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async writeHead(head: Head): Promise<void> {\n\t\tawait writeDurably(join(this.directory, 'head.json'), JSON.stringify(head));\n\t}\n\n\tgoTo(target: string, options: MoveOptions = {}): Promise<Revision> {\n\t\treturn this.move(() => (target === historyStart ? undefined : target), options);\n\t}\n\n\tundo(options: MoveOptions = {}): Promise<Revision> {\n\t\treturn this.move(({ runs, head }) => {\n\t\t\tif (head === undefined) throw new NothingToMoveError('undo');\n\t\t\treturn runs.find(run => run.runId === head)?.parentRunId;\n\t\t}, options);\n\t}\n\n\tredo(options: MoveOptions = {}): Promise<Revision> {\n\t\treturn this.move(({ runs, head, revisions }) => {\n\t\t\tconst target = redoTarget(runs, revisions, head);\n\t\t\tif (target === undefined) throw new NothingToMoveError('redo');\n\t\t\treturn target;\n\t\t}, options);\n\t}\n\n\tasync listRevisions(): Promise<Revision[]> {\n\t\tlet text: string;\n\t\ttry {\n\t\t\ttext = await readFile(join(this.directory, 'revisions.jsonl'), 'utf8');\n\t\t} catch (error) {\n\t\t\tif (isNotFound(error)) return [];\n\t\t\tthrow error;\n\t\t}\n\t\tconst lines = text.split('\\n');\n\t\treturn lines.flatMap((line, index) => {\n\t\t\tif (line === '') return [];\n\t\t\ttry {\n\t\t\t\treturn [JSON.parse(line) as Revision];\n\t\t\t} catch (error) {\n\t\t\t\t// A crash in the middle of an append leaves half a line, always the last one. Its\n\t\t\t\t// move is still pending, and finishing it records it again.\n\t\t\t\tif (index === lines.length - 1) return [];\n\t\t\t\tthrow new Error(`The history of this workspace is corrupt at line ${String(index + 1)}`, {\n\t\t\t\t\tcause: error,\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\t/** Holds the workspace like a run does, then moves it to the run `resolve` picks. */\n\tprivate async move(\n\t\tresolve: (history: {\n\t\t\truns: RunRecord[];\n\t\t\thead: string | undefined;\n\t\t\trevisions: Revision[];\n\t\t}) => string | undefined,\n\t\t{ reason, from }: MoveOptions,\n\t): Promise<Revision> {\n\t\tconst moveId = `move-${newRunId()}`;\n\t\ttry {\n\t\t\tawait this.lock(moveId);\n\t\t\tawait this.settleInterrupted(moveId);\n\t\t\tawait this.finishPendingMove();\n\t\t\tconst head = await this.readHead();\n\t\t\t// Only now, under the lock and once nothing is left unsettled, is the head the one the\n\t\t\t// move would start from.\n\t\t\tconst at = head.runId ?? historyStart;\n\t\t\tif (from !== undefined && from !== at) throw new WorkspaceMovedError(from, at);\n\t\t\tconst { runs } = await this.listRuns();\n\t\t\tconst to = resolve({ runs, head: head.runId, revisions: await this.listRevisions() });\n\t\t\tif (to !== undefined && !runs.some(run => run.runId === to)) {\n\t\t\t\tawait this.assertNotAbsorbed(to);\n\t\t\t}\n\n\t\t\treturn await this.takeSteps(head, runs, {\n\t\t\t\trevision: head.revision + 1,\n\t\t\t\t...(head.runId ? { from: head.runId } : {}),\n\t\t\t\t...(to ? { to } : {}),\n\t\t\t\t...(reason === undefined ? {} : { reason }),\n\t\t\t\tconflicts: [],\n\t\t\t});\n\t\t} finally {\n\t\t\tawait this.unlock(moveId);\n\t\t}\n\t}\n\n\t/** Finishes a move whose process stopped halfway, from the run its last step reached. */\n\tprivate async finishPendingMove(): Promise<void> {\n\t\tconst head = await this.readHead();\n\t\tconst { pending } = head;\n\t\tif (!pending) return;\n\t\t// It was recorded, and only clearing it from the head was missing.\n\t\tif ((await this.listRevisions()).some(revision => revision.revision === pending.revision)) {\n\t\t\tawait this.writeHead({\n\t\t\t\t...(pending.to ? { runId: pending.to } : {}),\n\t\t\t\trevision: pending.revision,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tawait this.takeSteps(head, (await this.listRuns()).runs, pending);\n\t}\n\n\t/**\n\t * Undoes, then redoes, one run at a time from where the head is to `pending.to`. After each\n\t * step the head names the run reached, with the move still pending, so a crash loses at\n\t * most the step in progress, and that step is safe to take again.\n\t */\n\tprivate async takeSteps(head: Head, runs: RunRecord[], pending: PendingMove): Promise<Revision> {\n\t\tconst { undo, redo } = route(runs, head.runId, pending.to);\n\t\tconst parents = new Map(runs.map(run => [run.runId, run.parentRunId]));\n\t\tlet reached = head.runId;\n\t\tconst save = () =>\n\t\t\tthis.writeHead({ ...(reached ? { runId: reached } : {}), revision: head.revision, pending });\n\n\t\t// What a write the crash interrupted left beside its file.\n\t\tif (pending.temporary) {\n\t\t\tawait removeTemporary(pending.temporary);\n\t\t\tdelete pending.temporary;\n\t\t}\n\t\tawait save();\n\t\tconst announce = async (temporary: string | undefined) => {\n\t\t\tif (temporary === undefined) delete pending.temporary;\n\t\t\telse pending.temporary = temporary;\n\t\t\tawait save();\n\t\t};\n\t\tfor (const runId of undo) {\n\t\t\tpending.conflicts.push(...(await this.step(runId, 'undo', announce)));\n\t\t\treached = parents.get(runId);\n\t\t\tawait save();\n\t\t}\n\t\tfor (const runId of redo) {\n\t\t\tpending.conflicts.push(...(await this.step(runId, 'redo', announce)));\n\t\t\treached = runId;\n\t\t\tawait save();\n\t\t}\n\n\t\t// Every write that started has finished, so no temporary is left to name.\n\t\tdelete pending.temporary;\n\t\tconst { conflicts, ...rest } = pending;\n\t\tconst revision: Revision = {\n\t\t\t...rest,\n\t\t\tat: new Date().toISOString(),\n\t\t\tcomplete: conflicts.length === 0,\n\t\t\tconflicts,\n\t\t};\n\t\tawait this.appendRevision(revision);\n\t\tawait this.writeHead({\n\t\t\t...(pending.to ? { runId: pending.to } : {}),\n\t\t\trevision: pending.revision,\n\t\t});\n\t\treturn revision;\n\t}\n\n\t/** Takes one run's changes back to its parent, or forward again, file by file. */\n\tprivate async step(\n\t\trunId: string,\n\t\tdirection: 'undo' | 'redo',\n\t\tannounce: (temporary: string | undefined) => Promise<void>,\n\t): Promise<MoveConflict[]> {\n\t\tconst { entries } = await this.readRun(runId);\n\t\tconst changes = fileChanges(entries, true);\n\t\tconst conflicts: MoveConflict[] = [];\n\t\t// Undone newest first, so a folder the run created is empty by the time its file goes.\n\t\tfor (const change of direction === 'undo' ? changes.reverse() : changes) {\n\t\t\tif (!(await this.moveFile(change, direction, announce))) {\n\t\t\t\tconflicts.push({ path: change.path, runId });\n\t\t\t}\n\t\t}\n\t\treturn conflicts;\n\t}\n\n\t/**\n\t * Writes the state the step leads to, only if the file holds the state it leaves. A file\n\t * already there is left alone, so taking a step again is safe. Returns whether the file\n\t * ends where the step leads.\n\t */\n\tprivate async moveFile(\n\t\tchange: FileChange,\n\t\tdirection: 'undo' | 'redo',\n\t\tannounce: (temporary: string | undefined) => Promise<void>,\n\t): Promise<boolean> {\n\t\tconst [source, destination] =\n\t\t\tdirection === 'undo' ? [change.after, change.before] : [change.before, change.after];\n\t\t// First, so a file reached through a folder that became a link is never taken for the\n\t\t// destination, and nothing is read or removed through it.\n\t\tif (!(await hasRealParents(change.path))) return false;\n\t\tconst current = await currentState(change.path);\n\n\t\tif (current && sameState(current, destination)) {\n\t\t\tif (direction === 'undo' && !destination.exists) {\n\t\t\t\tawait removeEmptyFolders(change.createdFolders);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\tif (!current || !sameState(current, source)) return false;\n\t\t// Someone wrote to the file between two of the run's changes, and going back to before\n\t\t// the first would discard that.\n\t\tif (direction === 'undo' && !change.continuous) return false;\n\n\t\tif (destination.exists) {\n\t\t\tconst temporary = temporaryPath(change.path);\n\t\t\tawait announce(temporary);\n\t\t\tawait writeFileState(\n\t\t\t\tchange.path,\n\t\t\t\tawait this.readContent(destination.hash),\n\t\t\t\tdestination.mode,\n\t\t\t\ttemporary,\n\t\t\t);\n\t\t\tawait announce(undefined);\n\t\t} else {\n\t\t\tawait removeFile(change.path);\n\t\t\tif (direction === 'undo') await removeEmptyFolders(change.createdFolders);\n\t\t}\n\t\treturn true;\n\t}\n\n\t/** Throws `HistoryExpiredError` if retention removed `runId` or chained it into a later run. */\n\tprivate async assertNotAbsorbed(runId: string): Promise<void> {\n\t\tconst { runs } = await this.listRuns();\n\t\tconst keptIn = runs.find(run => run.absorbed?.includes(runId));\n\t\tif (keptIn) throw new HistoryExpiredError(runId, keptIn.runId);\n\t\tif ((await this.listPruned()).includes(runId)) throw new HistoryExpiredError(runId);\n\t}\n\n\tprivate async listPruned(): Promise<string[]> {\n\t\ttry {\n\t\t\tconst text = await readFile(join(this.directory, 'pruned.jsonl'), 'utf8');\n\t\t\treturn text.split('\\n').flatMap(line => {\n\t\t\t\ttry {\n\t\t\t\t\treturn [JSON.parse(line) as string];\n\t\t\t\t} catch {\n\t\t\t\t\t// Half a line a crash left, whose removal never happened.\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (isNotFound(error)) return [];\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Brings the history down to `keepRuns - 1`, so the run about to start makes `keepRuns`, then\n\t * frees the contents no run kept refers to.\n\t */\n\tprivate async prune(): Promise<void> {\n\t\tawait this.finishChains();\n\t\tconst revisions = await this.listRevisions();\n\t\tfor (;;) {\n\t\t\tconst { head, runs } = await this.listRuns();\n\t\t\tconst step = nextPruneStep(runs, revisions, head, this.keepRuns - 1);\n\t\t\tif (!step) break;\n\t\t\tif (step.kind === 'remove') await this.removeRun(step.runId);\n\t\t\telse await this.chain(step.runId, step.into);\n\t\t}\n\t\tawait this.collectContent();\n\t}\n\n\t/**\n\t * Chains the changes of `older` into `newer`, its child: `newer` then hangs from `older`'s\n\t * parent and goes back to where `older` started. The new record is the commit point. Before\n\t * it, the history is as it was; after it, `finishChains` removes what is left of `older`.\n\t */\n\tprivate async chain(older: string, newer: string): Promise<void> {\n\t\tconst olderRecord = await this.readRecord(older);\n\t\tconst newerRecord = await this.readRecord(newer);\n\t\tconst entries = chainEntries(\n\t\t\tawait this.readEntries(older, olderRecord.journal),\n\t\t\tawait this.readEntries(newer, newerRecord.journal),\n\t\t);\n\t\tconst journal = `journal-${randomBytes(4).toString('hex')}.jsonl`;\n\t\tconst lines = entries.flatMap(({ status, sequence, ...change }): JournalLine[] => [\n\t\t\t{ type: 'prepared', sequence, ...change },\n\t\t\t...(status === 'prepared' ? [] : [{ type: status, sequence } as const]),\n\t\t]);\n\t\tawait writeDurably(\n\t\t\tjoin(this.runDirectory(newer), journal),\n\t\t\tlines.map(line => `${JSON.stringify(line)}\\n`).join(''),\n\t\t);\n\n\t\tconst record: RunRecord = {\n\t\t\t...newerRecord,\n\t\t\tabsorbed: [...(olderRecord.absorbed ?? []), older, ...(newerRecord.absorbed ?? [])],\n\t\t\tjournal,\n\t\t};\n\t\t// It now hangs where `older` did: from its parent, or from the start.\n\t\tif (olderRecord.parentRunId) record.parentRunId = olderRecord.parentRunId;\n\t\telse delete record.parentRunId;\n\t\tawait writeDurably(join(this.runDirectory(newer), 'run.json'), JSON.stringify(record));\n\t\tawait this.finishChains();\n\t}\n\n\t/**\n\t * Removes what a chain or a removal a crash interrupted left behind: the folders of runs\n\t * pruned or absorbed by a kept run, and journals a run no longer reads.\n\t */\n\tprivate async finishChains(): Promise<void> {\n\t\tfor (const runId of await this.listPruned()) {\n\t\t\tawait rm(this.runDirectory(runId), { recursive: true, force: true });\n\t\t}\n\t\tconst { runs } = await this.listRuns();\n\t\tfor (const run of runs) {\n\t\t\tfor (const absorbed of run.absorbed ?? []) {\n\t\t\t\tawait rm(this.runDirectory(absorbed), { recursive: true, force: true });\n\t\t\t}\n\t\t\tconst current = run.journal ?? firstJournal;\n\t\t\tfor (const name of await readdir(this.runDirectory(run.runId))) {\n\t\t\t\tif (name.startsWith('journal') && name.endsWith('.jsonl') && name !== current) {\n\t\t\t\t\tawait rm(join(this.runDirectory(run.runId), name), { force: true });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Removes a run whole, recording its id first so a move to it reports an expired history.\n\t * Its record goes next, so a crash halfway leaves no run behind.\n\t */\n\tprivate async removeRun(runId: string): Promise<void> {\n\t\tawait appendWhole(join(this.directory, 'pruned.jsonl'), [runId]);\n\t\t// The log may be new: its entry in the folder must last before the run it names goes.\n\t\tawait syncDirectory(this.directory);\n\t\tawait rm(join(this.runDirectory(runId), 'run.json'), { force: true });\n\t\tawait syncDirectory(this.runDirectory(runId));\n\t\tawait rm(this.runDirectory(runId), { recursive: true, force: true });\n\t}\n\n\t/**\n\t * Takes a run that changed nothing out of the history, under the lock: the workspace goes back\n\t * to its parent first, so the head never names a run that is gone. Until the run is removed,\n\t * `listRuns` already hides it, and the next run or move finishes removing it. The contents it\n\t * saved are freed by the next prune.\n\t */\n\tprivate async discardRun(record: RunRecord): Promise<void> {\n\t\tconst { runId: headRunId, ...head } = await this.readHead();\n\t\tif (headRunId === record.runId) {\n\t\t\tawait this.writeHead({\n\t\t\t\t...head,\n\t\t\t\t...(record.parentRunId ? { runId: record.parentRunId } : {}),\n\t\t\t});\n\t\t}\n\t\tawait rm(join(this.runDirectory(record.runId), 'run.json'), { force: true });\n\t\tawait syncDirectory(this.runDirectory(record.runId));\n\t\tawait rm(this.runDirectory(record.runId), { recursive: true, force: true });\n\t}\n\n\t/** Removes the stored contents no kept run refers to. */\n\tprivate async collectContent(): Promise<void> {\n\t\tconst referenced = new Set<string>();\n\t\tfor (const run of (await this.listRuns()).runs) {\n\t\t\tfor (const entry of await this.readEntries(run.runId, run.journal)) {\n\t\t\t\tfor (const state of [entry.before, entry.after]) {\n\t\t\t\t\tif (state.exists) referenced.add(state.hash);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst contentDirectory = join(this.directory, 'content');\n\t\tfor (const prefix of await readdir(contentDirectory)) {\n\t\t\tfor (const hash of await readdir(join(contentDirectory, prefix))) {\n\t\t\t\tif (hashPattern.test(hash) && !referenced.has(hash)) {\n\t\t\t\t\tawait rm(join(contentDirectory, prefix, hash), { force: true });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async appendRevision(revision: Revision): Promise<void> {\n\t\tawait appendWhole(join(this.directory, 'revisions.jsonl'), [revision]);\n\t\tawait syncDirectory(this.directory);\n\t}\n\n\t/**\n\t * Marks every other run still recorded as `running` as `interrupted`: this run holds the lock,\n\t * so their processes are gone. Each change one left `prepared` is settled from what its file\n\t * holds now: its `after` means it was made, its `before` that it was not. A file that holds\n\t * neither stays `prepared`, because nothing tells whether the change reached it.\n\t */\n\tprivate async settleInterrupted(ownRunId: string): Promise<void> {\n\t\tconst ids = (await readdir(join(this.directory, 'runs'))).filter(\n\t\t\tid => runIdPattern.test(id) && id !== ownRunId,\n\t\t);\n\t\tfor (const runId of ids) {\n\t\t\tconst record = await this.readRecord(runId).catch((error: unknown) => {\n\t\t\t\tif (isNotFound(error)) return undefined;\n\t\t\t\tthrow error;\n\t\t\t});\n\t\t\tif (record?.status !== 'running') continue;\n\n\t\t\tconst journal = await this.readJournal(runId, record.journal);\n\t\t\tconst settled: JournalLine[] = [];\n\t\t\tfor (const entry of journal.entries) {\n\t\t\t\tif (entry.status !== 'prepared' || !isAbsolute(entry.path)) continue;\n\t\t\t\tconst state = await currentState(entry.path);\n\t\t\t\tif (state && sameState(state, entry.after)) {\n\t\t\t\t\tsettled.push({ type: 'applied', sequence: entry.sequence });\n\t\t\t\t} else if (state && sameState(state, entry.before)) {\n\t\t\t\t\tsettled.push({ type: 'abandoned', sequence: entry.sequence });\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet sequence = journal.lastSequence;\n\t\t\tfor (const observation of journal.observations) {\n\t\t\t\tconst lines = await this.settleObservation(observation, journal.entries, sequence);\n\t\t\t\tsequence += lines.length;\n\t\t\t\tsettled.push(...lines);\n\t\t\t}\n\t\t\tawait appendWhole(join(this.runDirectory(runId), record.journal ?? firstJournal), settled);\n\t\t\tif (changedNothing(await this.readEntries(runId, record.journal))) {\n\t\t\t\tawait this.discardRun(record);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Last, so a crash before it leaves a run that is settled again, and settling is idempotent.\n\t\t\tawait writeDurably(\n\t\t\t\tjoin(this.runDirectory(runId), 'run.json'),\n\t\t\t\tJSON.stringify({ ...record, status: 'interrupted' } satisfies RunRecord),\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * The lines that record what a command an interrupted run was observing changed: every file of\n\t * its manifest that holds something else now, as changed by that command, and then the end of\n\t * the observation. A file recorded after the observation began is left alone: the run\n\t * recorded it itself. One that is now a folder, a link or too large to record is left out.\n\t */\n\tprivate async settleObservation(\n\t\tobservation: OpenObservation,\n\t\tentries: JournalEntry[],\n\t\tlastSequence: number,\n\t): Promise<JournalLine[]> {\n\t\tconst stored = await this.readContent(observation.manifest).catch((error: unknown) => {\n\t\t\tif (isNotFound(error)) return undefined;\n\t\t\tthrow error;\n\t\t});\n\t\t// Its manifest was never stored whole: the command it was saved for never started.\n\t\tif (!stored) return [{ type: 'observed', sequence: observation.sequence }];\n\t\tconst manifest = JSON.parse(stored.toString('utf8')) as Manifest;\n\t\tconst recorded = new Set(\n\t\t\tentries.filter(entry => entry.sequence > observation.sequence).map(entry => entry.path),\n\t\t);\n\t\tconst lines: JournalLine[] = [];\n\t\tlet sequence = lastSequence;\n\t\tfor (const [path, before] of Object.entries(manifest.files)) {\n\t\t\tif (!isAbsolute(path) || recorded.has(path)) continue;\n\t\t\tconst after = await this.saveState(path);\n\t\t\tif (!after || sameState(after, before)) continue;\n\t\t\tsequence++;\n\t\t\tlines.push(\n\t\t\t\t{ type: 'prepared', sequence, path, before, after, observedBy: observation.by },\n\t\t\t\t{ type: 'applied', sequence },\n\t\t\t);\n\t\t}\n\t\tlines.push({ type: 'observed', sequence: observation.sequence });\n\t\treturn lines;\n\t}\n\n\t/** What `path` holds now, with its content stored, or `undefined` for what no entry records. */\n\tprivate async saveState(path: string): Promise<FileState | undefined> {\n\t\tconst state = await currentState(path);\n\t\tif (!state?.exists) return state;\n\t\tconst content = await readFile(path).catch((error: unknown) => {\n\t\t\tif (isNotFound(error)) return undefined;\n\t\t\tthrow error;\n\t\t});\n\t\tif (!content) return { exists: false };\n\t\tconst { hash } = await storeContent(join(this.directory, 'content'), content);\n\t\t// Read again: the file may have changed between hashing it and storing it.\n\t\treturn hash === state.hash ? state : this.saveState(path);\n\t}\n\n\tprivate async readEntries(runId: string, journal = firstJournal): Promise<JournalEntry[]> {\n\t\treturn (await this.readJournal(runId, journal)).entries;\n\t}\n\n\t/**\n\t * A run's changes, the observations it began and never finished, and the highest sequence\n\t * number its journal uses, which the next line it gets must exceed.\n\t */\n\tprivate async readJournal(\n\t\trunId: string,\n\t\tjournal = firstJournal,\n\t): Promise<{ entries: JournalEntry[]; observations: OpenObservation[]; lastSequence: number }> {\n\t\tlet text: string;\n\t\ttry {\n\t\t\ttext = await readFile(join(this.runDirectory(runId), journal), 'utf8');\n\t\t} catch (error) {\n\t\t\t// A run that stopped before opening its journal never changed anything.\n\t\t\tif (isNotFound(error)) return { entries: [], observations: [], lastSequence: 0 };\n\t\t\tthrow error;\n\t\t}\n\t\tconst lines = text.split('\\n');\n\n\t\tconst entries = new Map<number, JournalEntry>();\n\t\tconst observations = new Map<number, OpenObservation>();\n\t\tlet lastSequence = 0;\n\t\tlines.forEach((text, index) => {\n\t\t\tif (text === '') return;\n\t\t\tlet line: JournalLine;\n\t\t\ttry {\n\t\t\t\tline = JSON.parse(text) as JournalLine;\n\t\t\t} catch (error) {\n\t\t\t\t// A crash in the middle of an append leaves half a line, always the last one. Its\n\t\t\t\t// step never returned, so no change was made after it.\n\t\t\t\tif (index === lines.length - 1) return;\n\t\t\t\tthrow new Error(`The journal of run ${runId} is corrupt at line ${String(index + 1)}`, {\n\t\t\t\t\tcause: error,\n\t\t\t\t});\n\t\t\t}\n\t\t\tlastSequence = Math.max(lastSequence, line.sequence);\n\t\t\tif (line.type === 'prepared') {\n\t\t\t\tconst { sequence, path, before, after, createdFolders, observedBy } = line;\n\t\t\t\tentries.set(sequence, {\n\t\t\t\t\tsequence,\n\t\t\t\t\tpath,\n\t\t\t\t\tbefore,\n\t\t\t\t\tafter,\n\t\t\t\t\t...(createdFolders ? { createdFolders } : {}),\n\t\t\t\t\t...(observedBy === undefined ? {} : { observedBy }),\n\t\t\t\t\tstatus: 'prepared',\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (line.type === 'observing') {\n\t\t\t\tconst { sequence, manifest, by } = line;\n\t\t\t\tobservations.set(sequence, { sequence, manifest, by });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (line.type === 'observed') {\n\t\t\t\tobservations.delete(line.sequence);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst entry = entries.get(line.sequence);\n\t\t\tif (entry) entry.status = line.type;\n\t\t});\n\n\t\treturn {\n\t\t\tentries: [...entries.values()],\n\t\t\tobservations: [...observations.values()],\n\t\t\tlastSequence,\n\t\t};\n\t}\n\n\tasync readContent(hash: string): Promise<Buffer> {\n\t\tif (!hashPattern.test(hash)) throw new Error(`Not a content hash: ${hash}`);\n\t\treturn readFile(contentPath(join(this.directory, 'content'), hash));\n\t}\n\n\tprivate async lock(runId: string): Promise<void> {\n\t\tconst path = join(this.directory, 'lock');\n\t\t// Twice at most: once as it is, and once more after clearing a dead run's lock.\n\t\tfor (let attempt = 0; attempt < 2; attempt++) {\n\t\t\ttry {\n\t\t\t\t// Written whole before it appears, so a lock that exists always names its holder.\n\t\t\t\tawait writeDurably(path, JSON.stringify({ runId, pid: process.pid }), { exclusive: true });\n\t\t\t\theldHere.add(runId);\n\t\t\t\treturn;\n\t\t\t} catch (error) {\n\t\t\t\tif ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;\n\t\t\t}\n\n\t\t\tconst holder = await readLock(path);\n\t\t\t// Released meanwhile: try again.\n\t\t\tif (!holder) continue;\n\t\t\tif (isLiveHolder(holder)) throw new WorkspaceBusyError(holder.runId);\n\t\t\t// Its process died, or its run ended, without releasing it. Read again just before\n\t\t\t// removing, so a lock another run has just taken is left alone.\n\t\t\tconst again = await readLock(path);\n\t\t\tif (again !== undefined && again.pid === holder.pid && again.runId === holder.runId) {\n\t\t\t\tawait unlink(path).catch((error: unknown) => {\n\t\t\t\t\tif (!isNotFound(error)) throw error;\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tthrow new WorkspaceBusyError((await readLock(path))?.runId ?? 'unknown');\n\t}\n\n\tprivate async unlock(runId: string): Promise<void> {\n\t\t// First: the run has ended even if removing its lock fails, so that lock is stale.\n\t\theldHere.delete(runId);\n\t\tconst path = join(this.directory, 'lock');\n\t\t// Only its own lock: one cleared as stale and taken by another run is not this run's.\n\t\tif ((await readLock(path))?.runId === runId) await unlink(path);\n\t}\n}\n\n/** No change it recorded may have reached a file: it recorded none, or abandoned each one. */\nfunction changedNothing(entries: JournalEntry[]): boolean {\n\treturn entries.every(entry => entry.status === 'abandoned');\n}\n\n/**\n * A run recorded as `running` only runs while it holds the lock, its process lives, and, in this\n * process, it has not ended. Any other is reported as `interrupted`, before the next run settles\n * it.\n */\nfunction withLiveStatus(\n\trecord: RunRecord,\n\tholder: { runId: string; pid?: number } | undefined,\n): RunRecord {\n\tif (record.status !== 'running') return record;\n\tconst live = holder?.runId === record.runId && holder.pid !== undefined && isLiveHolder(holder);\n\treturn live ? record : { ...record, status: 'interrupted' };\n}\n\n/**\n * Appends `lines`, as JSON, to a file of one line each, created private if missing. A crash may\n * have left its last line without a newline. A whole line, which the readers already count, is\n * kept and ended. Half a line would join the first new line, so it is cut off: whatever was\n * writing it never returned.\n */\nasync function appendWhole(path: string, lines: unknown[]): Promise<void> {\n\tif (lines.length === 0) return;\n\tlet text = '';\n\ttry {\n\t\ttext = await readFile(path, 'utf8');\n\t} catch (error) {\n\t\tif (!isNotFound(error)) throw error;\n\t}\n\tconst last = text.slice(text.lastIndexOf('\\n') + 1);\n\tlet separator = '';\n\tif (last !== '') {\n\t\tif (isWholeLine(last)) separator = '\\n';\n\t\telse await truncate(path, Buffer.byteLength(text) - Buffer.byteLength(last));\n\t}\n\tconst journal = await open(path, 'a', privateFile);\n\ttry {\n\t\tawait journal.appendFile(separator + lines.map(line => `${JSON.stringify(line)}\\n`).join(''));\n\t\tawait journal.sync();\n\t} finally {\n\t\tawait journal.close();\n\t}\n}\n\nfunction isWholeLine(text: string): boolean {\n\ttry {\n\t\tJSON.parse(text);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Who holds the lock, or `undefined` when nobody does. A lock this store did not write whole\n * has no `pid`, so it is never taken for a dead run's.\n */\nasync function readLock(path: string): Promise<{ runId: string; pid?: number } | undefined> {\n\tlet text: string;\n\ttry {\n\t\ttext = await readFile(path, 'utf8');\n\t} catch (error) {\n\t\tif (isNotFound(error)) return undefined;\n\t\tthrow error;\n\t}\n\ttry {\n\t\tconst { runId, pid } = JSON.parse(text) as { runId?: unknown; pid?: unknown };\n\t\tif (typeof runId === 'string' && Number.isInteger(pid)) return { runId, pid: pid as number };\n\t} catch {\n\t\t// Not JSON: named below as unknown.\n\t}\n\treturn { runId: 'unknown' };\n}\n\nfunction contentPath(contentDirectory: string, hash: string): string {\n\t// Two levels, so no folder holds every file a workspace ever stored.\n\treturn join(contentDirectory, hash.slice(0, 2), hash);\n}\n\nclass FileRunJournal implements RunJournal {\n\treadonly runId: string;\n\tprivate readonly record: RunRecord;\n\tprivate readonly runDirectory: string;\n\tprivate readonly contentDirectory: string;\n\tprivate readonly journal: FileHandle;\n\tprivate readonly discard: () => Promise<void>;\n\tprivate readonly release: () => Promise<void>;\n\tprivate sequence = 0;\n\tprivate stored = 0;\n\t// The changes recorded as prepared and not abandoned: those that may have reached a file. One\n\t// whose `prepared` line failed is not here, since nothing writes a file before that line.\n\tprivate readonly effects = new Set<number>();\n\t// Appends run one after another, so the lines never interleave.\n\tprivate pending: Promise<unknown> = Promise.resolve();\n\tprivate finished = false;\n\t// Set when an append fails: it may have left part of a line, and anything after it would be\n\t// joined to that part and unreadable.\n\tprivate broken: unknown;\n\n\tconstructor({\n\t\trecord,\n\t\trunDirectory,\n\t\tcontentDirectory,\n\t\tjournal,\n\t\tdiscard,\n\t\trelease,\n\t}: {\n\t\trecord: RunRecord;\n\t\trunDirectory: string;\n\t\tcontentDirectory: string;\n\t\tjournal: FileHandle;\n\t\tdiscard: () => Promise<void>;\n\t\trelease: () => Promise<void>;\n\t}) {\n\t\tthis.runId = record.runId;\n\t\tthis.record = record;\n\t\tthis.runDirectory = runDirectory;\n\t\tthis.contentDirectory = contentDirectory;\n\t\tthis.journal = journal;\n\t\tthis.discard = discard;\n\t\tthis.release = release;\n\t}\n\n\tasync saveContent(content: Buffer): Promise<string> {\n\t\tthis.assertOpen();\n\t\tconst { hash, written } = await storeContent(this.contentDirectory, content);\n\t\tif (written) this.stored += content.length;\n\t\treturn hash;\n\t}\n\n\tasync prepare(change: Omit<JournalEntry, 'sequence' | 'status'>): Promise<number> {\n\t\tthis.assertOpen();\n\t\tconst sequence = ++this.sequence;\n\t\tawait this.append({ type: 'prepared', sequence, ...change });\n\t\tthis.effects.add(sequence);\n\t\treturn sequence;\n\t}\n\n\tapplied(sequence: number): Promise<void> {\n\t\tthis.assertOpen();\n\t\treturn this.append({ type: 'applied', sequence });\n\t}\n\n\tasync abandoned(sequence: number): Promise<void> {\n\t\tthis.assertOpen();\n\t\tawait this.append({ type: 'abandoned', sequence });\n\t\t// Only once recorded: a change whose abandonment was not may still count as made.\n\t\tthis.effects.delete(sequence);\n\t}\n\n\tasync observe(manifest: string, by: string): Promise<number> {\n\t\tthis.assertOpen();\n\t\tconst sequence = ++this.sequence;\n\t\tawait this.append({ type: 'observing', sequence, manifest, by });\n\t\t// Until it is observed, whatever ran may have changed a file.\n\t\tthis.effects.add(sequence);\n\t\treturn sequence;\n\t}\n\n\tasync observed(sequence: number, measure?: ObservationMeasure): Promise<void> {\n\t\tthis.assertOpen();\n\t\tawait this.append({ type: 'observed', sequence, ...(measure ? { measure } : {}) });\n\t\t// Its changes, if any, are entries of their own now.\n\t\tthis.effects.delete(sequence);\n\t}\n\n\tget storedBytes(): number {\n\t\treturn this.stored;\n\t}\n\n\tget changed(): boolean {\n\t\treturn this.effects.size > 0;\n\t}\n\n\tasync finish(status: Exclude<RunStatus, 'running' | 'interrupted'>): Promise<void> {\n\t\tthis.assertOpen();\n\t\tthis.finished = true;\n\t\ttry {\n\t\t\tawait this.pending;\n\t\t\tawait this.journal.close();\n\t\t\t// Its record is left `running`: if removing it fails, readers already take it as gone.\n\t\t\tif (!this.changed) {\n\t\t\t\tawait this.discard();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst record: RunRecord = { ...this.record, status, finishedAt: new Date().toISOString() };\n\t\t\tawait writeDurably(join(this.runDirectory, 'run.json'), JSON.stringify(record));\n\t\t} finally {\n\t\t\tawait this.release();\n\t\t}\n\t}\n\n\tprivate append(line: JournalLine): Promise<void> {\n\t\tconst write = this.pending.then(async () => {\n\t\t\tif (this.broken !== undefined) {\n\t\t\t\tthrow new Error(`The journal of run ${this.runId} stopped after a failed write`, {\n\t\t\t\t\tcause: this.broken,\n\t\t\t\t});\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait this.journal.appendFile(`${JSON.stringify(line)}\\n`);\n\t\t\t\tawait this.journal.sync();\n\t\t\t} catch (error) {\n\t\t\t\tthis.broken = error ?? new Error('Unknown write failure');\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t});\n\t\t// The chain goes on, so each later append reports the broken journal to its own caller.\n\t\tthis.pending = write.catch(() => undefined);\n\t\treturn write;\n\t}\n\n\tprivate assertOpen(): void {\n\t\tif (this.finished) throw new Error(`Run ${this.runId} has already finished`);\n\t}\n}\n"]}
@@ -0,0 +1,30 @@
1
+ import type { FileState } from '../domain/recoveryStore.ts';
2
+ /**
3
+ * What `path` holds now, or `undefined` when it is something no recorded change leaves: a
4
+ * folder, a link, or a file larger than any change records, which is not read.
5
+ */
6
+ export declare function currentState(path: string): Promise<FileState | undefined>;
7
+ /**
8
+ * Whether every existing folder above `path` is where its name says. A folder replaced by a
9
+ * link since the run would send a write somewhere the run never wrote, maybe outside the
10
+ * workspace, so such a path is not written.
11
+ */
12
+ export declare function hasRealParents(path: string): Promise<boolean>;
13
+ /**
14
+ * Puts `content` at `path` with `mode`, all at once: a crash leaves the old file or the new one.
15
+ * Missing folders above it are created.
16
+ */
17
+ export declare function writeFileState(path: string, content: Buffer, mode: number, temporary: string): Promise<void>;
18
+ /**
19
+ * A new, hidden name beside `path` to build its content in. It is random, so it never names a
20
+ * file of the user's, and the caller records it before the write so a crash can be cleaned up.
21
+ */
22
+ export declare function temporaryPath(path: string): string;
23
+ /**
24
+ * Removes a temporary `temporaryPath` named, which a write a crash interrupted left behind.
25
+ * Nothing is removed through a folder that became a link.
26
+ */
27
+ export declare function removeTemporary(temporary: string): Promise<void>;
28
+ export declare function removeFile(path: string): Promise<void>;
29
+ /** Removes `folders`, innermost first, each only while it is empty. */
30
+ export declare function removeEmptyFolders(folders: string[]): Promise<void>;
@@ -0,0 +1,125 @@
1
+ import { createHash, randomBytes } from 'node:crypto';
2
+ import { lstat, mkdir, open, readFile, realpath, rename, rm, rmdir, unlink, } from 'node:fs/promises';
3
+ import { basename, dirname, join } from 'node:path';
4
+ // Far above the largest file the editor changes, so the history never reads a file whole only
5
+ // to find it differs.
6
+ const maxRecordedBytes = 64 * 1024 * 1024;
7
+ function code(error) {
8
+ return error.code;
9
+ }
10
+ /**
11
+ * What `path` holds now, or `undefined` when it is something no recorded change leaves: a
12
+ * folder, a link, or a file larger than any change records, which is not read.
13
+ */
14
+ export async function currentState(path) {
15
+ let stats;
16
+ try {
17
+ stats = await lstat(path);
18
+ }
19
+ catch (error) {
20
+ if (code(error) === 'ENOENT')
21
+ return { exists: false };
22
+ throw error;
23
+ }
24
+ if (!stats.isFile() || stats.size > maxRecordedBytes)
25
+ return undefined;
26
+ const hash = createHash('sha256')
27
+ .update(await readFile(path))
28
+ .digest('hex');
29
+ return { exists: true, hash, mode: stats.mode & 0o7777 };
30
+ }
31
+ /**
32
+ * Whether every existing folder above `path` is where its name says. A folder replaced by a
33
+ * link since the run would send a write somewhere the run never wrote, maybe outside the
34
+ * workspace, so such a path is not written.
35
+ */
36
+ export async function hasRealParents(path) {
37
+ for (let folder = dirname(path);; folder = dirname(folder)) {
38
+ try {
39
+ return (await realpath(folder)) === folder;
40
+ }
41
+ catch (error) {
42
+ if (code(error) !== 'ENOENT')
43
+ throw error;
44
+ }
45
+ if (dirname(folder) === folder)
46
+ return true;
47
+ }
48
+ }
49
+ /**
50
+ * Puts `content` at `path` with `mode`, all at once: a crash leaves the old file or the new one.
51
+ * Missing folders above it are created.
52
+ */
53
+ export async function writeFileState(path, content, mode, temporary) {
54
+ await mkdir(dirname(path), { recursive: true });
55
+ try {
56
+ // Private while it holds content of a file that may be private too; the file's own mode
57
+ // is set only once it is whole.
58
+ const handle = await open(temporary, 'wx', 0o600);
59
+ try {
60
+ await handle.writeFile(content);
61
+ // Set on the open file, so the umask does not change it.
62
+ await handle.chmod(mode);
63
+ await handle.sync();
64
+ }
65
+ finally {
66
+ await handle.close();
67
+ }
68
+ await rename(temporary, path);
69
+ }
70
+ finally {
71
+ await rm(temporary, { force: true });
72
+ }
73
+ await syncFolder(dirname(path));
74
+ }
75
+ /**
76
+ * A new, hidden name beside `path` to build its content in. It is random, so it never names a
77
+ * file of the user's, and the caller records it before the write so a crash can be cleaned up.
78
+ */
79
+ export function temporaryPath(path) {
80
+ return join(dirname(path), `.${basename(path)}.${randomBytes(6).toString('hex')}.mikode-harness-tmp`);
81
+ }
82
+ /**
83
+ * Removes a temporary `temporaryPath` named, which a write a crash interrupted left behind.
84
+ * Nothing is removed through a folder that became a link.
85
+ */
86
+ export async function removeTemporary(temporary) {
87
+ if (await hasRealParents(temporary))
88
+ await rm(temporary, { force: true });
89
+ }
90
+ export async function removeFile(path) {
91
+ try {
92
+ await unlink(path);
93
+ }
94
+ catch (error) {
95
+ if (code(error) !== 'ENOENT')
96
+ throw error;
97
+ }
98
+ await syncFolder(dirname(path));
99
+ }
100
+ /** Removes `folders`, innermost first, each only while it is empty. */
101
+ export async function removeEmptyFolders(folders) {
102
+ for (const folder of [...folders].reverse()) {
103
+ try {
104
+ await rmdir(folder);
105
+ }
106
+ catch (error) {
107
+ if (code(error) === 'ENOENT')
108
+ continue;
109
+ // Something else is in it now, so it and every folder above it stay.
110
+ if (code(error) === 'ENOTEMPTY' || code(error) === 'EEXIST' || code(error) === 'ENOTDIR')
111
+ return;
112
+ throw error;
113
+ }
114
+ }
115
+ }
116
+ async function syncFolder(path) {
117
+ const folder = await open(path, 'r');
118
+ try {
119
+ await folder.sync();
120
+ }
121
+ finally {
122
+ await folder.close();
123
+ }
124
+ }
125
+ //# sourceMappingURL=workspaceFiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaceFiles.js","sourceRoot":"","sources":["../../../src/recovery/infrastructure/workspaceFiles.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomBytes } from 'node:crypto';\nimport {\n\tlstat,\n\tmkdir,\n\topen,\n\treadFile,\n\trealpath,\n\trename,\n\trm,\n\trmdir,\n\tunlink,\n} from 'node:fs/promises';\nimport { basename, dirname, join } from 'node:path';\nimport type { FileState } from '../domain/recoveryStore.ts';\n\n// Far above the largest file the editor changes, so the history never reads a file whole only\n// to find it differs.\nconst maxRecordedBytes = 64 * 1024 * 1024;\n\nfunction code(error: unknown): string | undefined {\n\treturn (error as NodeJS.ErrnoException).code;\n}\n\n/**\n * What `path` holds now, or `undefined` when it is something no recorded change leaves: a\n * folder, a link, or a file larger than any change records, which is not read.\n */\nexport async function currentState(path: string): Promise<FileState | undefined> {\n\tlet stats;\n\ttry {\n\t\tstats = await lstat(path);\n\t} catch (error) {\n\t\tif (code(error) === 'ENOENT') return { exists: false };\n\t\tthrow error;\n\t}\n\tif (!stats.isFile() || stats.size > maxRecordedBytes) return undefined;\n\tconst hash = createHash('sha256')\n\t\t.update(await readFile(path))\n\t\t.digest('hex');\n\treturn { exists: true, hash, mode: stats.mode & 0o7777 };\n}\n\n/**\n * Whether every existing folder above `path` is where its name says. A folder replaced by a\n * link since the run would send a write somewhere the run never wrote, maybe outside the\n * workspace, so such a path is not written.\n */\nexport async function hasRealParents(path: string): Promise<boolean> {\n\tfor (let folder = dirname(path); ; folder = dirname(folder)) {\n\t\ttry {\n\t\t\treturn (await realpath(folder)) === folder;\n\t\t} catch (error) {\n\t\t\tif (code(error) !== 'ENOENT') throw error;\n\t\t}\n\t\tif (dirname(folder) === folder) return true;\n\t}\n}\n\n/**\n * Puts `content` at `path` with `mode`, all at once: a crash leaves the old file or the new one.\n * Missing folders above it are created.\n */\nexport async function writeFileState(\n\tpath: string,\n\tcontent: Buffer,\n\tmode: number,\n\ttemporary: string,\n): Promise<void> {\n\tawait mkdir(dirname(path), { recursive: true });\n\ttry {\n\t\t// Private while it holds content of a file that may be private too; the file's own mode\n\t\t// is set only once it is whole.\n\t\tconst handle = await open(temporary, 'wx', 0o600);\n\t\ttry {\n\t\t\tawait handle.writeFile(content);\n\t\t\t// Set on the open file, so the umask does not change it.\n\t\t\tawait handle.chmod(mode);\n\t\t\tawait handle.sync();\n\t\t} finally {\n\t\t\tawait handle.close();\n\t\t}\n\t\tawait rename(temporary, path);\n\t} finally {\n\t\tawait rm(temporary, { force: true });\n\t}\n\tawait syncFolder(dirname(path));\n}\n\n/**\n * A new, hidden name beside `path` to build its content in. It is random, so it never names a\n * file of the user's, and the caller records it before the write so a crash can be cleaned up.\n */\nexport function temporaryPath(path: string): string {\n\treturn join(\n\t\tdirname(path),\n\t\t`.${basename(path)}.${randomBytes(6).toString('hex')}.mikode-harness-tmp`,\n\t);\n}\n\n/**\n * Removes a temporary `temporaryPath` named, which a write a crash interrupted left behind.\n * Nothing is removed through a folder that became a link.\n */\nexport async function removeTemporary(temporary: string): Promise<void> {\n\tif (await hasRealParents(temporary)) await rm(temporary, { force: true });\n}\n\nexport async function removeFile(path: string): Promise<void> {\n\ttry {\n\t\tawait unlink(path);\n\t} catch (error) {\n\t\tif (code(error) !== 'ENOENT') throw error;\n\t}\n\tawait syncFolder(dirname(path));\n}\n\n/** Removes `folders`, innermost first, each only while it is empty. */\nexport async function removeEmptyFolders(folders: string[]): Promise<void> {\n\tfor (const folder of [...folders].reverse()) {\n\t\ttry {\n\t\t\tawait rmdir(folder);\n\t\t} catch (error) {\n\t\t\tif (code(error) === 'ENOENT') continue;\n\t\t\t// Something else is in it now, so it and every folder above it stay.\n\t\t\tif (code(error) === 'ENOTEMPTY' || code(error) === 'EEXIST' || code(error) === 'ENOTDIR')\n\t\t\t\treturn;\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n\nasync function syncFolder(path: string): Promise<void> {\n\tconst folder = await open(path, 'r');\n\ttry {\n\t\tawait folder.sync();\n\t} finally {\n\t\tawait folder.close();\n\t}\n}\n"]}
@@ -0,0 +1,30 @@
1
+ export type Access = 'read' | 'write';
2
+ /** A folder the agent may reach, and what it may do inside it. */
3
+ export interface WorkspaceRoot {
4
+ path: string;
5
+ access: Access;
6
+ }
7
+ /** A path the policy allowed, and where it really is. */
8
+ export interface AllowedPath {
9
+ /** Every symlink resolved: the one place to read or write, whatever the model called it. */
10
+ absolute: string;
11
+ /** The real path of the root that holds it. */
12
+ root: string;
13
+ /** Relative to that root, written with `/`. */
14
+ relative: string;
15
+ }
16
+ /**
17
+ * Why a path was refused, worded for the model. It names the path only as the model wrote it,
18
+ * never a path of the host: a host path in an error sends the model looking for it.
19
+ */
20
+ export declare class AccessDeniedError extends Error {
21
+ constructor(message: string);
22
+ }
23
+ /**
24
+ * Decides whether an agent may read or write a path, for every tool that touches files. A
25
+ * path the model sends is relative to the first root, or absolute.
26
+ */
27
+ export interface AccessPolicy {
28
+ /** @throws {AccessDeniedError} when the path may not be accessed this way. */
29
+ check(path: string, access: Access, signal: AbortSignal): Promise<AllowedPath>;
30
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Why a path was refused, worded for the model. It names the path only as the model wrote it,
3
+ * never a path of the host: a host path in an error sends the model looking for it.
4
+ */
5
+ export class AccessDeniedError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = 'AccessDeniedError';
9
+ }
10
+ }
11
+ //# sourceMappingURL=accessPolicy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accessPolicy.js","sourceRoot":"","sources":["../../../src/tools/domain/accessPolicy.ts"],"names":[],"mappings":"AAkBA;;;GAGG;AACH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC3C,YAAY,OAAe;QAC1B,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IACjC,CAAC;CACD","sourcesContent":["export type Access = 'read' | 'write';\n\n/** A folder the agent may reach, and what it may do inside it. */\nexport interface WorkspaceRoot {\n\tpath: string;\n\taccess: Access;\n}\n\n/** A path the policy allowed, and where it really is. */\nexport interface AllowedPath {\n\t/** Every symlink resolved: the one place to read or write, whatever the model called it. */\n\tabsolute: string;\n\t/** The real path of the root that holds it. */\n\troot: string;\n\t/** Relative to that root, written with `/`. */\n\trelative: string;\n}\n\n/**\n * Why a path was refused, worded for the model. It names the path only as the model wrote it,\n * never a path of the host: a host path in an error sends the model looking for it.\n */\nexport class AccessDeniedError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = 'AccessDeniedError';\n\t}\n}\n\n/**\n * Decides whether an agent may read or write a path, for every tool that touches files. A\n * path the model sends is relative to the first root, or absolute.\n */\nexport interface AccessPolicy {\n\t/** @throws {AccessDeniedError} when the path may not be accessed this way. */\n\tcheck(path: string, access: Access, signal: AbortSignal): Promise<AllowedPath>;\n}\n"]}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Something the model fills in a command's arguments. It never writes free arguments: each
3
+ * value is checked against what the consumer declared here, and none can become a flag it did
4
+ * not declare.
5
+ *
6
+ * - `paths`: files or folders inside the roots that the agent may read, each its own argument,
7
+ * relative to the command's working directory. The model may give none.
8
+ * - `choice`: one of `values`, as the consumer wrote them, so a value may be a flag.
9
+ * - `text`: a value that matches `pattern` whole, and never starts with `-`.
10
+ *
11
+ * A `choice` or `text` that is not `required` may be left out, and then adds no argument.
12
+ */
13
+ export type CommandParameter = {
14
+ type: 'paths';
15
+ name: string;
16
+ description: string;
17
+ } | {
18
+ type: 'choice';
19
+ name: string;
20
+ description: string;
21
+ values: string[];
22
+ required?: boolean;
23
+ } | {
24
+ type: 'text';
25
+ name: string;
26
+ description: string;
27
+ pattern: string;
28
+ required?: boolean;
29
+ };
30
+ /** One argument of a command: fixed text, or the place where a parameter goes. */
31
+ export type CommandArgument = string | CommandParameter;
32
+ /** The roles of the model-backed orchestrator a command can be given to. */
33
+ export declare const commandRoles: readonly ["planner", "executor", "reviewer"];
34
+ export type CommandRole = (typeof commandRoles)[number];
35
+ /**
36
+ * A command the consumer lets the agent run, such as the project's tests or its formatter. It
37
+ * runs without a shell, so nothing in an argument is ever read as shell syntax.
38
+ */
39
+ export interface CommandDefinition {
40
+ /** What it does and when to run it, for the model. */
41
+ description: string;
42
+ /**
43
+ * The program: a name looked up in the command's `PATH`, or a path. A relative path is from
44
+ * `cwd`.
45
+ */
46
+ executable: string;
47
+ args?: CommandArgument[];
48
+ /**
49
+ * Where it runs, inside a `write` root: relative to the first root, or absolute. Defaults to
50
+ * the first root.
51
+ */
52
+ cwd?: string;
53
+ /**
54
+ * Variables set for it, on top of the few it inherits: `PATH`, `HOME`, `TMPDIR`, `USER`,
55
+ * `SHELL`, `LANG` and `LC_*`. Nothing else of this process's environment reaches it, so
56
+ * neither do the provider keys.
57
+ */
58
+ env?: Record<string, string>;
59
+ /** How long it may run before its whole process group is stopped. Defaults to 10 minutes. */
60
+ timeoutMs?: number;
61
+ /** How much of the end of its output the model reads. Defaults to 16 KB. */
62
+ outputBytes?: number;
63
+ /**
64
+ * Which roles of `createLLMOrchestrator` may run it, such as the planner for a command that
65
+ * reads an issue. Defaults to the executor only. Whoever runs it, the files are captured
66
+ * around it, so what it changes is in the history. `createFileTools` offers every command.
67
+ */
68
+ roles?: CommandRole[];
69
+ }
70
+ /** The commands an agent may run, by the name the model calls each one. */
71
+ export type Commands = Record<string, CommandDefinition>;
72
+ export declare const defaultCommandTimeoutMs: number;
73
+ export declare const defaultCommandOutputBytes: number;
74
+ /** A parameter's value as the model sent it, with `paths` already checked and resolved. */
75
+ export type ParameterValue = string[] | string | null;
76
+ /**
77
+ * Checks every command before an agent is built, so a mistake in the configuration fails there
78
+ * and never as a refused call in the middle of a run.
79
+ *
80
+ * @throws {InvalidAgentConfigError} for the first thing that is wrong.
81
+ */
82
+ export declare function validateCommands(commands: Commands): void;
83
+ /** The commands `role` may run: those that name it, or, without `roles`, the executor. */
84
+ export declare function commandsFor(commands: Commands, role: CommandRole): Commands;
85
+ /** The parameters of a command, in the order its arguments use them. */
86
+ export declare function parametersOf(definition: CommandDefinition): CommandParameter[];
87
+ /**
88
+ * The arguments a call runs with: the fixed ones as declared, and each parameter replaced by
89
+ * the value the model gave, once checked.
90
+ *
91
+ * @throws {Error} worded for the model, when a value is not one the parameter takes.
92
+ */
93
+ export declare function buildArguments(definition: CommandDefinition, values: Record<string, ParameterValue>): string[];