@aryacode/dsh-engineering 0.0.0-stage → 0.4.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 (284) hide show
  1. package/CHANGELOG.md +128 -0
  2. package/LICENSE +21 -0
  3. package/README.md +230 -2
  4. package/cordis.patch.yml +123 -0
  5. package/lib/client.js +3448 -0
  6. package/lib/index.d.ts +2 -0
  7. package/lib/index.js +9 -0
  8. package/locale/en.json +6 -0
  9. package/locale/zh.json +6 -0
  10. package/package.json +94 -3
  11. package/vendor/ftview/README.md +55 -0
  12. package/vendor/ftview/SKILL.md +74 -0
  13. package/vendor/ftview/lib/checks.d.ts +27 -0
  14. package/vendor/ftview/lib/checks.js +39 -0
  15. package/vendor/ftview/lib/core.d.ts +208 -0
  16. package/vendor/ftview/lib/core.js +160 -0
  17. package/vendor/ftview/lib/edit/drafts.d.ts +49 -0
  18. package/vendor/ftview/lib/edit/drafts.js +84 -0
  19. package/vendor/ftview/lib/edit/operations.d.ts +62 -0
  20. package/vendor/ftview/lib/edit/operations.js +126 -0
  21. package/vendor/ftview/lib/edit/prepare.d.ts +38 -0
  22. package/vendor/ftview/lib/edit/prepare.js +133 -0
  23. package/vendor/ftview/lib/edit/tools.d.ts +25 -0
  24. package/vendor/ftview/lib/edit/tools.js +198 -0
  25. package/vendor/ftview/lib/edit.d.ts +30 -0
  26. package/vendor/ftview/lib/edit.js +38 -0
  27. package/vendor/ftview/lib/index.d.ts +31 -0
  28. package/vendor/ftview/lib/index.js +36 -0
  29. package/vendor/ftview/lib/model.d.ts +80 -0
  30. package/vendor/ftview/lib/model.js +267 -0
  31. package/vendor/ftview/lib/session.d.ts +48 -0
  32. package/vendor/ftview/lib/session.js +98 -0
  33. package/vendor/ftview/lib/skill.d.ts +29 -0
  34. package/vendor/ftview/lib/skill.js +43 -0
  35. package/vendor/ftview/lib/studio/discover.d.ts +36 -0
  36. package/vendor/ftview/lib/studio/discover.js +87 -0
  37. package/vendor/ftview/lib/studio/preflight.d.ts +51 -0
  38. package/vendor/ftview/lib/studio/preflight.js +64 -0
  39. package/vendor/ftview/lib/studio/tools.d.ts +15 -0
  40. package/vendor/ftview/lib/studio/tools.js +83 -0
  41. package/vendor/ftview/lib/studio.d.ts +30 -0
  42. package/vendor/ftview/lib/studio.js +37 -0
  43. package/vendor/ftview/lib/tools.d.ts +14 -0
  44. package/vendor/ftview/lib/tools.js +202 -0
  45. package/vendor/l5x/README.md +62 -0
  46. package/vendor/l5x/SKILL.md +81 -0
  47. package/vendor/l5x/lib/approvals.d.ts +50 -0
  48. package/vendor/l5x/lib/approvals.js +93 -0
  49. package/vendor/l5x/lib/client.js +412 -0
  50. package/vendor/l5x/lib/client.js.map +1 -0
  51. package/vendor/l5x/lib/core/errors.d.ts +38 -0
  52. package/vendor/l5x/lib/core/errors.js +48 -0
  53. package/vendor/l5x/lib/core/params.d.ts +49 -0
  54. package/vendor/l5x/lib/core/params.js +39 -0
  55. package/vendor/l5x/lib/core/result.d.ts +46 -0
  56. package/vendor/l5x/lib/core/result.js +21 -0
  57. package/vendor/l5x/lib/core/tool.d.ts +102 -0
  58. package/vendor/l5x/lib/core/tool.js +19 -0
  59. package/vendor/l5x/lib/drafts.d.ts +66 -0
  60. package/vendor/l5x/lib/drafts.js +98 -0
  61. package/vendor/l5x/lib/editing.d.ts +30 -0
  62. package/vendor/l5x/lib/editing.js +42 -0
  63. package/vendor/l5x/lib/engine/acd-edit.d.ts +13 -0
  64. package/vendor/l5x/lib/engine/acd-edit.js +115 -0
  65. package/vendor/l5x/lib/engine/analysis.d.ts +22 -0
  66. package/vendor/l5x/lib/engine/analysis.js +258 -0
  67. package/vendor/l5x/lib/engine/capabilities.d.ts +9 -0
  68. package/vendor/l5x/lib/engine/capabilities.js +40 -0
  69. package/vendor/l5x/lib/engine/change-set.d.ts +122 -0
  70. package/vendor/l5x/lib/engine/change-set.js +446 -0
  71. package/vendor/l5x/lib/engine/configuration.d.ts +21 -0
  72. package/vendor/l5x/lib/engine/configuration.js +42 -0
  73. package/vendor/l5x/lib/engine/details.d.ts +47 -0
  74. package/vendor/l5x/lib/engine/details.js +173 -0
  75. package/vendor/l5x/lib/engine/direct-polling.d.ts +91 -0
  76. package/vendor/l5x/lib/engine/direct-polling.js +193 -0
  77. package/vendor/l5x/lib/engine/download-review.d.ts +15 -0
  78. package/vendor/l5x/lib/engine/download-review.js +63 -0
  79. package/vendor/l5x/lib/engine/logic-syntax.d.ts +60 -0
  80. package/vendor/l5x/lib/engine/logic-syntax.js +237 -0
  81. package/vendor/l5x/lib/engine/observations.d.ts +41 -0
  82. package/vendor/l5x/lib/engine/observations.js +67 -0
  83. package/vendor/l5x/lib/engine/project-analysis.d.ts +131 -0
  84. package/vendor/l5x/lib/engine/project-analysis.js +314 -0
  85. package/vendor/l5x/lib/engine/review-evidence.d.ts +8 -0
  86. package/vendor/l5x/lib/engine/review-evidence.js +49 -0
  87. package/vendor/l5x/lib/engine/review.d.ts +18 -0
  88. package/vendor/l5x/lib/engine/review.js +123 -0
  89. package/vendor/l5x/lib/engine/studio-sdk.d.ts +101 -0
  90. package/vendor/l5x/lib/engine/studio-sdk.js +571 -0
  91. package/vendor/l5x/lib/engine/tag-resolution.d.ts +20 -0
  92. package/vendor/l5x/lib/engine/tag-resolution.js +169 -0
  93. package/vendor/l5x/lib/engine/usage.d.ts +16 -0
  94. package/vendor/l5x/lib/engine/usage.js +92 -0
  95. package/vendor/l5x/lib/engine/xml-regions.d.ts +23 -0
  96. package/vendor/l5x/lib/engine/xml-regions.js +77 -0
  97. package/vendor/l5x/lib/fs.d.ts +17 -0
  98. package/vendor/l5x/lib/fs.js +36 -0
  99. package/vendor/l5x/lib/index.d.ts +36 -0
  100. package/vendor/l5x/lib/index.js +42 -0
  101. package/vendor/l5x/lib/live.d.ts +48 -0
  102. package/vendor/l5x/lib/live.js +48 -0
  103. package/vendor/l5x/lib/model/aois.d.ts +39 -0
  104. package/vendor/l5x/lib/model/aois.js +112 -0
  105. package/vendor/l5x/lib/model/errors.d.ts +15 -0
  106. package/vendor/l5x/lib/model/errors.js +18 -0
  107. package/vendor/l5x/lib/model/index.d.ts +20 -0
  108. package/vendor/l5x/lib/model/index.js +19 -0
  109. package/vendor/l5x/lib/model/module.d.ts +37 -0
  110. package/vendor/l5x/lib/model/module.js +54 -0
  111. package/vendor/l5x/lib/model/modules.d.ts +24 -0
  112. package/vendor/l5x/lib/model/modules.js +55 -0
  113. package/vendor/l5x/lib/model/parse.d.ts +32 -0
  114. package/vendor/l5x/lib/model/parse.js +116 -0
  115. package/vendor/l5x/lib/model/project.d.ts +15 -0
  116. package/vendor/l5x/lib/model/project.js +31 -0
  117. package/vendor/l5x/lib/model/routines.d.ts +71 -0
  118. package/vendor/l5x/lib/model/routines.js +183 -0
  119. package/vendor/l5x/lib/model/tags.d.ts +51 -0
  120. package/vendor/l5x/lib/model/tags.js +119 -0
  121. package/vendor/l5x/lib/model/types.d.ts +304 -0
  122. package/vendor/l5x/lib/model/types.js +12 -0
  123. package/vendor/l5x/lib/model/udts.d.ts +34 -0
  124. package/vendor/l5x/lib/model/udts.js +81 -0
  125. package/vendor/l5x/lib/model/xml.d.ts +139 -0
  126. package/vendor/l5x/lib/model/xml.js +291 -0
  127. package/vendor/l5x/lib/model/xref.d.ts +28 -0
  128. package/vendor/l5x/lib/model/xref.js +154 -0
  129. package/vendor/l5x/lib/session.d.ts +119 -0
  130. package/vendor/l5x/lib/session.js +236 -0
  131. package/vendor/l5x/lib/skill.d.ts +30 -0
  132. package/vendor/l5x/lib/skill.js +44 -0
  133. package/vendor/l5x/lib/studio-state.d.ts +77 -0
  134. package/vendor/l5x/lib/studio-state.js +79 -0
  135. package/vendor/l5x/lib/studio.d.ts +29 -0
  136. package/vendor/l5x/lib/studio.js +40 -0
  137. package/vendor/l5x/lib/tools/checks.d.ts +19 -0
  138. package/vendor/l5x/lib/tools/checks.js +140 -0
  139. package/vendor/l5x/lib/tools/common.d.ts +41 -0
  140. package/vendor/l5x/lib/tools/common.js +84 -0
  141. package/vendor/l5x/lib/tools/controller.d.ts +21 -0
  142. package/vendor/l5x/lib/tools/controller.js +170 -0
  143. package/vendor/l5x/lib/tools/drafts.d.ts +23 -0
  144. package/vendor/l5x/lib/tools/drafts.js +270 -0
  145. package/vendor/l5x/lib/tools/live.d.ts +21 -0
  146. package/vendor/l5x/lib/tools/live.js +175 -0
  147. package/vendor/l5x/lib/tools/read.d.ts +19 -0
  148. package/vendor/l5x/lib/tools/read.js +245 -0
  149. package/vendor/l5x/lib/tools/references.d.ts +20 -0
  150. package/vendor/l5x/lib/tools/references.js +269 -0
  151. package/vendor/l5x/lib/tools/studio.d.ts +21 -0
  152. package/vendor/l5x/lib/tools/studio.js +193 -0
  153. package/vendor/l5x/poll-worker.mjs +77 -0
  154. package/vendor/l5x/studio-bridge/NuGet.Config +1 -0
  155. package/vendor/l5x/studio-bridge/Program.cs +304 -0
  156. package/vendor/l5x/studio-bridge/StudioBridge.csproj +11 -0
  157. package/vendor/mwi/README.md +60 -0
  158. package/vendor/mwi/SKILL.md +87 -0
  159. package/vendor/mwi/bridge/README.md +8 -0
  160. package/vendor/mwi/bridge/mw_bridge.ps1 +2763 -0
  161. package/vendor/mwi/bridge/sdk-interop-importer.cs +30 -0
  162. package/vendor/mwi/bridge/sdk-variable-reader.cs +22 -0
  163. package/vendor/mwi/bridge/start_bridge.cmd +21 -0
  164. package/vendor/mwi/bridge/watch_dialogs.cmd +13 -0
  165. package/vendor/mwi/bridge/watch_dialogs.ps1 +153 -0
  166. package/vendor/mwi/code/engine/motionworks_iec_mcp/__init__.py +14 -0
  167. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/__init__.cpython-312.pyc +0 -0
  168. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/block_interfaces.cpython-312.pyc +0 -0
  169. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/cfb.cpython-312.pyc +0 -0
  170. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/datatypes.cpython-312.pyc +0 -0
  171. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/declarations.cpython-312.pyc +0 -0
  172. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/errors.cpython-312.pyc +0 -0
  173. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/graphical_listing.cpython-312.pyc +0 -0
  174. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/grid.cpython-312.pyc +0 -0
  175. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/knowledge.cpython-312.pyc +0 -0
  176. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/mwt_bind.cpython-312.pyc +0 -0
  177. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/navigation.cpython-312.pyc +0 -0
  178. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/program_checks.cpython-312.pyc +0 -0
  179. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/project.cpython-312.pyc +0 -0
  180. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/staging.cpython-312.pyc +0 -0
  181. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/structure.cpython-312.pyc +0 -0
  182. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/task_bindings.cpython-312.pyc +0 -0
  183. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/tasks.cpython-312.pyc +0 -0
  184. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/tree.cpython-312.pyc +0 -0
  185. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/validation.cpython-312.pyc +0 -0
  186. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/variable_edit.cpython-312.pyc +0 -0
  187. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/variables.cpython-312.pyc +0 -0
  188. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/workflow.cpython-312.pyc +0 -0
  189. package/vendor/mwi/code/engine/motionworks_iec_mcp/block_interfaces.py +275 -0
  190. package/vendor/mwi/code/engine/motionworks_iec_mcp/build.py +339 -0
  191. package/vendor/mwi/code/engine/motionworks_iec_mcp/capture.py +448 -0
  192. package/vendor/mwi/code/engine/motionworks_iec_mcp/cfb.py +765 -0
  193. package/vendor/mwi/code/engine/motionworks_iec_mcp/com.py +268 -0
  194. package/vendor/mwi/code/engine/motionworks_iec_mcp/datatypes.py +204 -0
  195. package/vendor/mwi/code/engine/motionworks_iec_mcp/declarations.py +399 -0
  196. package/vendor/mwi/code/engine/motionworks_iec_mcp/descriptions.py +30 -0
  197. package/vendor/mwi/code/engine/motionworks_iec_mcp/eip.py +292 -0
  198. package/vendor/mwi/code/engine/motionworks_iec_mcp/errors.py +36 -0
  199. package/vendor/mwi/code/engine/motionworks_iec_mcp/graphical_listing.py +208 -0
  200. package/vendor/mwi/code/engine/motionworks_iec_mcp/grid.py +227 -0
  201. package/vendor/mwi/code/engine/motionworks_iec_mcp/ide.py +317 -0
  202. package/vendor/mwi/code/engine/motionworks_iec_mcp/iec.py +317 -0
  203. package/vendor/mwi/code/engine/motionworks_iec_mcp/installed_help.py +151 -0
  204. package/vendor/mwi/code/engine/motionworks_iec_mcp/knowledge.py +218 -0
  205. package/vendor/mwi/code/engine/motionworks_iec_mcp/libraries.py +250 -0
  206. package/vendor/mwi/code/engine/motionworks_iec_mcp/manuals.py +520 -0
  207. package/vendor/mwi/code/engine/motionworks_iec_mcp/mwt_bind.py +133 -0
  208. package/vendor/mwi/code/engine/motionworks_iec_mcp/navigation.py +44 -0
  209. package/vendor/mwi/code/engine/motionworks_iec_mcp/pou_writer.py +1547 -0
  210. package/vendor/mwi/code/engine/motionworks_iec_mcp/program_checks.py +360 -0
  211. package/vendor/mwi/code/engine/motionworks_iec_mcp/project.py +704 -0
  212. package/vendor/mwi/code/engine/motionworks_iec_mcp/reference_data/catalog.json +672 -0
  213. package/vendor/mwi/code/engine/motionworks_iec_mcp/reference_data/patterns.json +86 -0
  214. package/vendor/mwi/code/engine/motionworks_iec_mcp/restore.py +208 -0
  215. package/vendor/mwi/code/engine/motionworks_iec_mcp/server.py +1913 -0
  216. package/vendor/mwi/code/engine/motionworks_iec_mcp/snapshot.py +138 -0
  217. package/vendor/mwi/code/engine/motionworks_iec_mcp/st_comments.py +25 -0
  218. package/vendor/mwi/code/engine/motionworks_iec_mcp/staging.py +179 -0
  219. package/vendor/mwi/code/engine/motionworks_iec_mcp/stlint.py +676 -0
  220. package/vendor/mwi/code/engine/motionworks_iec_mcp/structure.py +98 -0
  221. package/vendor/mwi/code/engine/motionworks_iec_mcp/task_bindings.py +68 -0
  222. package/vendor/mwi/code/engine/motionworks_iec_mcp/tasks.py +162 -0
  223. package/vendor/mwi/code/engine/motionworks_iec_mcp/transaction.py +157 -0
  224. package/vendor/mwi/code/engine/motionworks_iec_mcp/tree.py +563 -0
  225. package/vendor/mwi/code/engine/motionworks_iec_mcp/tree_writer.py +790 -0
  226. package/vendor/mwi/code/engine/motionworks_iec_mcp/uia.py +465 -0
  227. package/vendor/mwi/code/engine/motionworks_iec_mcp/validation.py +41 -0
  228. package/vendor/mwi/code/engine/motionworks_iec_mcp/variable_edit.py +183 -0
  229. package/vendor/mwi/code/engine/motionworks_iec_mcp/variables.py +472 -0
  230. package/vendor/mwi/code/engine/motionworks_iec_mcp/workflow.py +130 -0
  231. package/vendor/mwi/code/engine/motionworks_iec_mcp/writer.py +666 -0
  232. package/vendor/mwi/code/mw_code.py +1258 -0
  233. package/vendor/mwi/legacy/edit-session.js +50 -0
  234. package/vendor/mwi/legacy/fb-insertion.js +74 -0
  235. package/vendor/mwi/legacy/native-code.js +83 -0
  236. package/vendor/mwi/legacy/native-groups.js +75 -0
  237. package/vendor/mwi/legacy/native-structure.js +143 -0
  238. package/vendor/mwi/legacy/native-variables.js +77 -0
  239. package/vendor/mwi/legacy/pou-conversion.js +47 -0
  240. package/vendor/mwi/legacy/pou-package.js +66 -0
  241. package/vendor/mwi/lib/core/bridge.d.ts +71 -0
  242. package/vendor/mwi/lib/core/bridge.js +53 -0
  243. package/vendor/mwi/lib/core/code-engine.d.ts +47 -0
  244. package/vendor/mwi/lib/core/code-engine.js +109 -0
  245. package/vendor/mwi/lib/core/errors.d.ts +37 -0
  246. package/vendor/mwi/lib/core/errors.js +47 -0
  247. package/vendor/mwi/lib/core/params.d.ts +52 -0
  248. package/vendor/mwi/lib/core/params.js +46 -0
  249. package/vendor/mwi/lib/core/ps-bridge.d.ts +62 -0
  250. package/vendor/mwi/lib/core/ps-bridge.js +127 -0
  251. package/vendor/mwi/lib/core/result.d.ts +45 -0
  252. package/vendor/mwi/lib/core/result.js +20 -0
  253. package/vendor/mwi/lib/core/tool.d.ts +80 -0
  254. package/vendor/mwi/lib/core/tool.js +55 -0
  255. package/vendor/mwi/lib/edit/compare.d.ts +33 -0
  256. package/vendor/mwi/lib/edit/compare.js +70 -0
  257. package/vendor/mwi/lib/edit.d.ts +20 -0
  258. package/vendor/mwi/lib/edit.js +32 -0
  259. package/vendor/mwi/lib/index.d.ts +21 -0
  260. package/vendor/mwi/lib/index.js +33 -0
  261. package/vendor/mwi/lib/read/service.d.ts +117 -0
  262. package/vendor/mwi/lib/read/service.js +229 -0
  263. package/vendor/mwi/lib/read.d.ts +21 -0
  264. package/vendor/mwi/lib/read.js +33 -0
  265. package/vendor/mwi/lib/session/project.d.ts +34 -0
  266. package/vendor/mwi/lib/session/project.js +54 -0
  267. package/vendor/mwi/lib/session/service.d.ts +167 -0
  268. package/vendor/mwi/lib/session/service.js +566 -0
  269. package/vendor/mwi/lib/session/stage.d.ts +84 -0
  270. package/vendor/mwi/lib/session/stage.js +187 -0
  271. package/vendor/mwi/lib/session/workspace.d.ts +52 -0
  272. package/vendor/mwi/lib/session/workspace.js +90 -0
  273. package/vendor/mwi/lib/skill.d.ts +36 -0
  274. package/vendor/mwi/lib/skill.js +56 -0
  275. package/vendor/mwi/lib/tools/edit.d.ts +20 -0
  276. package/vendor/mwi/lib/tools/edit.js +286 -0
  277. package/vendor/mwi/lib/tools/read.d.ts +19 -0
  278. package/vendor/mwi/lib/tools/read.js +161 -0
  279. package/vendor/mwi/lib/tools/session.d.ts +20 -0
  280. package/vendor/mwi/lib/tools/session.js +166 -0
  281. package/vendor/mwi/lib/tools/verify.d.ts +19 -0
  282. package/vendor/mwi/lib/tools/verify.js +85 -0
  283. package/vendor/mwi/lib/verify.d.ts +17 -0
  284. package/vendor/mwi/lib/verify.js +29 -0
@@ -0,0 +1,566 @@
1
+ /**
2
+ * One workspace's MotionWorks runtime: bridge, code engine, stage and the rows
3
+ * that need them.
4
+ *
5
+ * Runtimes are cached per workspace so one chat reuses the bridge it started and
6
+ * one workspace's mailbox never answers another's request.
7
+ *
8
+ * @module dsh-engineering-mwi/session/service
9
+ */
10
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
11
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
12
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
13
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
14
+ });
15
+ }
16
+ return path;
17
+ };
18
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
19
+ import { join, resolve } from 'node:path';
20
+ import { createHash, randomUUID } from 'node:crypto';
21
+ import { fileURLToPath, pathToFileURL } from 'node:url';
22
+ import { Bridge } from "../core/bridge.js";
23
+ import { CodeEngine } from "../core/code-engine.js";
24
+ import { MwiError } from "../core/errors.js";
25
+ import { PowerShellBridgeTransport } from "../core/ps-bridge.js";
26
+ import { StageService } from "./stage.js";
27
+ import { compareVariables } from "../edit/compare.js";
28
+ import { ReadService } from "../read/service.js";
29
+ import { stageRootOf, workspaceOf, isInside } from "./workspace.js";
30
+ /** The bridge directory shipped with this package. */
31
+ export const BRIDGE_DIR = fileURLToPath(new URL('../../bridge/', import.meta.url));
32
+ /** The code engine directory shipped with this package. */
33
+ export const CODE_DIR = fileURLToPath(new URL('../../code/', import.meta.url));
34
+ /** Vendored proven mutation helpers. */
35
+ export const LEGACY_DIR = fileURLToPath(new URL('../../legacy/', import.meta.url));
36
+ /** Hash every file in a native package, refusing links and oversized trees. */
37
+ function nativePackageManifest(directory, workspace) {
38
+ const files = [];
39
+ let bytes = 0;
40
+ const visit = (folder) => {
41
+ if (!isInside(workspace, folder))
42
+ throw new MwiError('REFUSED', 'The package directory escapes the workspace.', 'Export into the workspace stage.');
43
+ for (const entry of readdirSync(folder, { withFileTypes: true })) {
44
+ const path = join(folder, entry.name);
45
+ if (entry.isSymbolicLink() || !isInside(workspace, path))
46
+ throw new MwiError('REFUSED', 'The package contains a link.', 'Re-export the package; links are refused.');
47
+ if (entry.isDirectory()) {
48
+ visit(path);
49
+ continue;
50
+ }
51
+ if (!entry.isFile())
52
+ throw new MwiError('REFUSED', 'The package contains an unsupported item.', 'Re-export the package.');
53
+ const content = readFileSync(path);
54
+ bytes += content.length;
55
+ if (files.length >= 100 || bytes > 64 * 1024 * 1024)
56
+ throw new MwiError('REFUSED', 'The package exceeds the supported size.', 'Export a smaller POU.');
57
+ files.push({ path: path.slice(directory.length + 1).replaceAll('\\', '/'), bytes: content.length, sha256: createHash('sha256').update(content).digest('hex') });
58
+ }
59
+ };
60
+ visit(directory);
61
+ return files.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
62
+ }
63
+ /** A workspace runtime over the real bridge and engine. */
64
+ export class PowerShellSessionRuntime {
65
+ workspace;
66
+ bridge;
67
+ engine;
68
+ stages;
69
+ /** Saved-project reads. */
70
+ reads;
71
+ /** Live POU-package receipts, bound to this runtime. */
72
+ packages = new Map();
73
+ /**
74
+ * @param workspace - Absolute workspace root.
75
+ */
76
+ constructor(workspace) {
77
+ this.workspace = workspace;
78
+ this.bridge = new Bridge(new PowerShellBridgeTransport({
79
+ bridgeDir: BRIDGE_DIR,
80
+ workspace,
81
+ stageRoot: stageRootOf(workspace),
82
+ }));
83
+ this.engine = new CodeEngine({ workspace, stageRoot: stageRootOf(workspace), codeDir: CODE_DIR });
84
+ this.stages = new StageService(this.engine, workspace);
85
+ this.reads = new ReadService(this.engine);
86
+ }
87
+ /** @returns The bridge's status document. */
88
+ async status() {
89
+ return await this.bridge.run('status');
90
+ }
91
+ /** @returns The bridge's live state document. */
92
+ async ideState() {
93
+ return await this.bridge.run('ide_state', { include_window_state: true });
94
+ }
95
+ /** @returns The written stage record. */
96
+ async stage(source, options = {}) {
97
+ return await this.stages.stage(source, {
98
+ ...options,
99
+ assertClosed: async () => {
100
+ let status;
101
+ try {
102
+ status = await this.status();
103
+ }
104
+ catch (error) {
105
+ if (error instanceof MwiError && error.code === 'IDE_NOT_RUNNING')
106
+ return;
107
+ throw error;
108
+ }
109
+ const active = typeof status.active_project === 'string' ? status.active_project : undefined;
110
+ if (active === undefined)
111
+ return;
112
+ const requested = resolve(this.workspace, source);
113
+ const name = requested.replace(/\\/gu, '/').split('/').pop()?.replace(/\.mwt$/iu, '') ?? '';
114
+ if (name !== '')
115
+ StageService.assertClosed(join(stageRootOf(this.workspace), name), { is_project_open: true, active_project: active });
116
+ },
117
+ });
118
+ }
119
+ /** @returns The bridge's open result. */
120
+ async open(path, options) {
121
+ const resolved = resolve(path);
122
+ if (!isInside(stageRootOf(this.workspace), resolved) || !existsSync(resolved)) {
123
+ throw new MwiError('NOT_STAGED', `${resolved} is not a staged project.`, 'Stage the workspace project with mw_project_stage, then open the staged .mwt.');
124
+ }
125
+ const name = resolved.replace(/\\/gu, '/').split('/').pop()?.replace(/\.mwt$/iu, '') ?? '';
126
+ if (this.stages.identityOf(name) === undefined) {
127
+ throw new MwiError('STAGE_IDENTITY_MISSING', `The stage ${name} has no identity record.`, 'Stage the project again; an unproven stage is never opened.');
128
+ }
129
+ const binding = await this.engine.run('check_mwt', { project: resolved });
130
+ return await this.bridge.run('open', {
131
+ path: resolved,
132
+ wrapper_sha256: binding.wrapper_sha256,
133
+ user_approved: options.userApproved === true,
134
+ ...(options.expectedProject === undefined ? {} : { expected_project: options.expectedProject }),
135
+ });
136
+ }
137
+ /** @returns The bridge's start result. */
138
+ async start(project) {
139
+ const staged = project === undefined ? this.singleStage() : this.stageMwt(project);
140
+ const binding = await this.engine.run('check_mwt', { project: staged });
141
+ return await this.bridge.run('start_ide', {
142
+ include_trial_method: true,
143
+ path: staged,
144
+ wrapper_sha256: binding.wrapper_sha256,
145
+ });
146
+ }
147
+ /** @returns The bridge's worksheet result. */
148
+ async worksheet(request) {
149
+ const status = await this.status();
150
+ if (status.is_project_open !== true || typeof status.active_project !== 'string') {
151
+ throw new MwiError('NO_PROJECT', 'No project is open in the IDE.', 'Open a staged project first with mw_project_open.');
152
+ }
153
+ const record = this.stages.stagedAt(status.active_project);
154
+ if (record === undefined) {
155
+ throw new MwiError('NOT_STAGED', `The open project is not a proven stage: ${status.active_project}.`, 'Open a staged project before navigating worksheets.');
156
+ }
157
+ const target = await this.engine.run('worksheet_target', {
158
+ project: record.staged_directory,
159
+ kind: request.kind,
160
+ ...(request.pou === undefined ? {} : { pou: request.pou }),
161
+ });
162
+ return await this.bridge.run('open_worksheet', {
163
+ project: record.staged_directory,
164
+ ...target,
165
+ inspect_only: request.inspectOnly === true,
166
+ });
167
+ }
168
+ /** @returns The bridge's close result. */
169
+ async close(options) {
170
+ if (options.userApproved !== true) {
171
+ throw new MwiError('APPROVAL_REQUIRED', 'Closing the IDE requires explicit user approval.', 'Ask the user, then pass user_approved: true and the exact open project path.');
172
+ }
173
+ return await this.bridge.run('close_ide', {
174
+ user_approved: true,
175
+ ...(options.expectedProject === undefined ? {} : { expected_project: options.expectedProject }),
176
+ });
177
+ }
178
+ /** @returns The stage record for a path. */
179
+ stagedAt(path) {
180
+ return this.stages.stagedAt(path);
181
+ }
182
+ /** @returns The bridge's compile result. */
183
+ async compile(mode) {
184
+ await this.openStagedRecord();
185
+ if (mode === 'state')
186
+ return await this.bridge.run('compile_state', {});
187
+ try {
188
+ return await this.bridge.run(mode, {}, 400_000);
189
+ }
190
+ catch (error) {
191
+ if (error instanceof MwiError && error.code === 'BRIDGE_FAILED') {
192
+ throw new MwiError('COMPILE_FAILED', error.message, 'Read mw_diagnostics for the exact message, fix the reported task or source, then compile again.');
193
+ }
194
+ throw error;
195
+ }
196
+ }
197
+ /** @returns The output pane and the compile verdict when readable. */
198
+ async diagnostics(pane, limit) {
199
+ const read = await this.bridge.run('read_output', { pane, limit }, 60_000);
200
+ const state = await this.bridge.run('compile_state', {}, 30_000).catch(() => null);
201
+ return { ...read, compile_state: state };
202
+ }
203
+ /** @returns A baseline receipt or a comparison against one. */
204
+ async verify(mode, baselineId) {
205
+ const record = await this.openStagedRecord();
206
+ const manifest = await this.engine.run('source_manifest', { project: record.staged_directory });
207
+ const state = await this.bridge.run('compile_state', {}, 30_000).catch(() => null);
208
+ const directory = join(this.workspace, '.motionworks', 'verification');
209
+ if (mode === 'baseline') {
210
+ const id = randomUUID();
211
+ mkdirSync(directory, { recursive: true });
212
+ const baseline = {
213
+ id,
214
+ project: record.staged_directory,
215
+ source_digest: manifest.source_digest,
216
+ files: manifest.files,
217
+ compile_state: state,
218
+ captured_at: new Date().toISOString(),
219
+ };
220
+ writeFileSync(join(directory, `${id}.json`), JSON.stringify(baseline, null, 2));
221
+ return { baseline_id: id, project: record.staged_directory, source_digest: manifest.source_digest, compile_state: state, baseline_path: join(directory, `${id}.json`) };
222
+ }
223
+ if (baselineId === undefined || baselineId === '') {
224
+ throw new MwiError('BASELINE_REQUIRED', 'Comparing needs the baseline_id returned by a baseline capture.', 'Call mw_verify mode baseline, then compare with that id.');
225
+ }
226
+ let baseline;
227
+ try {
228
+ baseline = JSON.parse(readFileSync(join(directory, `${baselineId}.json`), 'utf8'));
229
+ }
230
+ catch {
231
+ throw new MwiError('BASELINE_NOT_FOUND', `No baseline ${baselineId} exists in this workspace.`, 'Capture a new baseline and compare against that id.');
232
+ }
233
+ if (baseline.project === undefined || resolve(baseline.project) !== resolve(record.staged_directory)) {
234
+ throw new MwiError('BASELINE_PROJECT_MISMATCH', 'The baseline belongs to another project.', 'Capture a baseline for the open project and compare that id.');
235
+ }
236
+ const before = baseline.files ?? {};
237
+ const after = manifest.files ?? {};
238
+ const added = Object.keys(after).filter(file => before[file] === undefined);
239
+ const removed = Object.keys(before).filter(file => after[file] === undefined);
240
+ const changed = Object.keys(after).filter(file => before[file] !== undefined && before[file] !== after[file]);
241
+ return {
242
+ baseline_id: baselineId,
243
+ project: record.staged_directory,
244
+ matched: baseline.source_digest === manifest.source_digest,
245
+ source_digest: manifest.source_digest,
246
+ baseline_source_digest: baseline.source_digest,
247
+ added,
248
+ removed,
249
+ changed,
250
+ compile_state: state,
251
+ baseline_compile_state: baseline.compile_state,
252
+ };
253
+ }
254
+ /** Export one POU to a workspace package, or import it into this project. */
255
+ async transferPou(input) {
256
+ const record = await this.openStagedRecord();
257
+ const helpers = await import(__rewriteRelativeImportExtension(pathToFileURL(join(LEGACY_DIR, 'pou-package.js')).href));
258
+ const workspace = this.workspace;
259
+ const project = record.staged_directory;
260
+ const evidenceDirectory = join(workspace, '.motionworks', 'verification');
261
+ mkdirSync(evidenceDirectory, { recursive: true });
262
+ const evidence = join(evidenceDirectory, `pou-package-${randomUUID()}.json`);
263
+ if (input.operation === 'export') {
264
+ const directory = join(workspace, '.motionworks', `pk-${randomUUID().slice(0, 8)}`);
265
+ mkdirSync(directory);
266
+ const deps = {
267
+ status: async () => await this.bridge.run('compile_state'),
268
+ saved: async () => await this.engine.run('structure_snapshot', { project }),
269
+ snapshot: async () => await this.bridge.run('pou_package_snapshot', {}, 120_000),
270
+ manifest: async () => nativePackageManifest(directory, workspace),
271
+ consume: async () => undefined,
272
+ mutate: async (request) => await this.bridge.run('pou_package_mutate', { ...request, project, package_directory: directory }, 120_000),
273
+ };
274
+ try {
275
+ const exported = await helpers.exportPouPackage({ project, pou: input.pou, baseline_saved: true }, deps);
276
+ const token = randomUUID();
277
+ const receipt = {
278
+ ...exported, directory, project, workspace, evidence_path: evidence, used: false,
279
+ };
280
+ this.packages.set(token, receipt);
281
+ writeFileSync(evidence, JSON.stringify({ operation: 'export', token, receipt }, null, 2), 'utf8');
282
+ return {
283
+ accepted: true,
284
+ operation: 'export',
285
+ package_token: token,
286
+ package_directory: directory,
287
+ file_count: exported.manifest.length,
288
+ evidence_path: evidence,
289
+ };
290
+ }
291
+ catch (error) {
292
+ throw new MwiError('EDIT_REFUSED', `${error.message}; evidence at ${evidence}`, 'Inspect the partial package before another attempt.');
293
+ }
294
+ }
295
+ const token = typeof input.package_token === 'string' ? input.package_token : '';
296
+ const receipt = this.packages.get(token);
297
+ if (receipt === undefined || receipt.workspace !== workspace || receipt.project !== project) {
298
+ throw new MwiError('PACKAGE_TOKEN_UNKNOWN', 'No live export receipt matches this token, workspace and project.', 'Export the POU again; tokens do not survive a plugin reload.');
299
+ }
300
+ if (input.dependencies_reviewed !== true) {
301
+ throw new MwiError('APPROVAL_REQUIRED', 'Importing needs dependencies_reviewed:true.', 'Review the package externals, then retry with the flag.');
302
+ }
303
+ const deps = {
304
+ status: async () => await this.bridge.run('compile_state'),
305
+ saved: async () => await this.engine.run('structure_snapshot', { project }),
306
+ snapshot: async () => await this.bridge.run('pou_package_snapshot', {}, 120_000),
307
+ manifest: async () => nativePackageManifest(receipt.directory, workspace),
308
+ consume: async () => {
309
+ receipt.used = true;
310
+ writeFileSync(evidence, JSON.stringify({ operation: 'import', token, phase: 'token_consumed', receipt }, null, 2), 'utf8');
311
+ },
312
+ mutate: async (request) => await this.bridge.run('pou_package_mutate', { ...request, project, package_directory: receipt.directory }, 120_000),
313
+ };
314
+ try {
315
+ const imported = await helpers.importPouPackage({ project, baseline_saved: true, dependencies_reviewed: true }, receipt, deps);
316
+ writeFileSync(evidence, JSON.stringify({ operation: 'import', token, ...imported }, null, 2), 'utf8');
317
+ return { ...imported, evidence_path: evidence };
318
+ }
319
+ catch (error) {
320
+ throw new MwiError('EDIT_REFUSED', `${error.message}; evidence at ${evidence}`, 'Inspect the retained receipt and current project; do not retry a consumed token.');
321
+ }
322
+ }
323
+ /** Insert one FB instance and its ST call into a POU. */
324
+ async insertBlock(input) {
325
+ const record = await this.openStagedRecord();
326
+ const helpers = await import(__rewriteRelativeImportExtension(pathToFileURL(join(LEGACY_DIR, 'fb-insertion.js')).href));
327
+ const project = record.staged_directory;
328
+ const state = await this.bridge.run('compile_state');
329
+ if (state.is_modified !== false) {
330
+ throw new MwiError('EDIT_REFUSED', 'The native project has unsaved changes.', 'Save or reconcile the IDE, then retry.');
331
+ }
332
+ const libraries = await this.bridge.run('library_snapshot');
333
+ const block = await this.engine.run('block_interface', {
334
+ project,
335
+ native_libraries: libraries.libraries ?? [],
336
+ name: input.block,
337
+ ...(typeof input.library === 'string' ? { library: input.library } : {}),
338
+ }, 120_000);
339
+ const read = await this.engine.run('read_st', { project, pou: input.pou }, 60_000);
340
+ const plan = helpers.fbInsertionPlan({ ...input, project, baseline_saved: true }, block, read);
341
+ const variable = await this.editVariable({
342
+ pou: input.pou,
343
+ operation: 'add',
344
+ declaration: plan.declaration,
345
+ ...(typeof input.group === 'string' ? {} : { group: 'Default' }),
346
+ });
347
+ if (variable.verification?.accepted !== true) {
348
+ throw new MwiError('EDIT_REFUSED', `The instance declaration did not verify: ${variable.verification?.errors?.join('; ') ?? 'unknown'}.`, 'Inspect the declaration evidence before another attempt.');
349
+ }
350
+ const code = await this.editCode({
351
+ pou: String(input.pou),
352
+ expectedBody: typeof read.body === 'string' ? read.body : '',
353
+ body: plan.code,
354
+ });
355
+ const accepted = code.verification?.accepted === true;
356
+ return {
357
+ verification: { accepted, errors: code.verification?.errors ?? [], warnings: plan.warnings },
358
+ instance: input.instance,
359
+ call: plan.call,
360
+ completed_phases: accepted ? ['instance_declared', 'call_inserted'] : ['instance_declared'],
361
+ body: code.body,
362
+ evidence: { variable, block },
363
+ };
364
+ }
365
+ /** Add, edit or delete one native declaration. */
366
+ async editVariable(input) {
367
+ const record = await this.openStagedRecord();
368
+ const helpers = await import(__rewriteRelativeImportExtension(pathToFileURL(join(LEGACY_DIR, 'native-variables.js')).href));
369
+ const project = record.staged_directory;
370
+ const pou = typeof input.pou === 'string' ? input.pou : undefined;
371
+ const evidenceDirectory = join(this.workspace, '.motionworks', 'verification');
372
+ mkdirSync(evidenceDirectory, { recursive: true });
373
+ const evidence = join(evidenceDirectory, `native-variable-${randomUUID()}.json`);
374
+ const args = { ...input, project, baseline_saved: true };
375
+ try {
376
+ const result = await helpers.nativeVariableChange(args, {
377
+ status: async () => await this.bridge.run('compile_state'),
378
+ saved: async () => await this.engine.run(pou === undefined ? 'globals' : 'read_st', { project, ...(pou === undefined ? {} : { pou }) }),
379
+ snapshotSaved: async () => await this.bridge.run('variable_snapshot', { ...(pou === undefined ? {} : { pou }), require_saved: true }),
380
+ mutate: async (request) => await this.bridge.run('variable_mutate', { ...request, project }, 60_000),
381
+ compare: compareVariables,
382
+ globals: async () => await this.engine.run('globals', { project }),
383
+ });
384
+ writeFileSync(evidence, JSON.stringify({ args, ...result }, null, 2), { encoding: 'utf8', flag: 'wx' });
385
+ return { ...result, evidence_path: evidence };
386
+ }
387
+ catch (error) {
388
+ throw new MwiError('EDIT_REFUSED', `${error.message}; evidence at ${evidence}`, 'Read the refusal, correct the request, and retry. Do not repeat an unverified edit.');
389
+ }
390
+ }
391
+ /** Create, copy, rename, delete or assign one POU or task. */
392
+ async editStructure(input) {
393
+ const record = await this.openStagedRecord();
394
+ const helpers = await import(__rewriteRelativeImportExtension(pathToFileURL(join(LEGACY_DIR, 'native-structure.js')).href));
395
+ const project = record.staged_directory;
396
+ const scope = input.scope === 'task' ? 'task' : 'pou';
397
+ const args = { ...input, project, baseline_saved: true };
398
+ delete args.scope;
399
+ const evidenceDirectory = join(this.workspace, '.motionworks', 'verification');
400
+ const inputDirectory = join(this.workspace, '.motionworks', 'native-input');
401
+ mkdirSync(evidenceDirectory, { recursive: true });
402
+ const evidence = join(evidenceDirectory, `native-structure-${randomUUID()}.json`);
403
+ try {
404
+ const result = await helpers.nativeStructureChange(scope, args, {
405
+ status: async () => await this.bridge.run('compile_state'),
406
+ saved: async () => await this.engine.run('structure_snapshot', { project }),
407
+ snapshot: async () => await this.bridge.run('structure_snapshot'),
408
+ mutate: async (request) => await this.bridge.run('structure_mutate', { ...request, project }, 60_000),
409
+ retainPlan: async (plan) => {
410
+ writeFileSync(evidence, JSON.stringify({ phase: 'plan_retained', ...plan }, null, 2), { encoding: 'utf8', flag: 'wx' });
411
+ },
412
+ prepareSettings: async (settingsText) => {
413
+ mkdirSync(inputDirectory, { recursive: true });
414
+ const path = join(inputDirectory, `${randomUUID()}.SET`);
415
+ writeFileSync(path, settingsText, { encoding: 'ascii', flag: 'wx' });
416
+ return { settings_import_path: path };
417
+ },
418
+ });
419
+ writeFileSync(evidence, JSON.stringify({ phase: 'result', ...result }, null, 2), 'utf8');
420
+ return { ...result, evidence_path: evidence };
421
+ }
422
+ catch (error) {
423
+ throw new MwiError('EDIT_REFUSED', `${error.message}; evidence at ${evidence}`, 'Read the refusal, correct the request, and retry. Do not repeat an unverified edit.');
424
+ }
425
+ }
426
+ /** Validate the current saved project. */
427
+ async validate(options) {
428
+ const record = await this.openStagedRecord();
429
+ const workflow = await this.engine.run('workflow_check', { project: record.staged_directory }, 120_000);
430
+ const validate = await this.engine.run('validate', { project: record.staged_directory }, 120_000);
431
+ const review = options.pou === undefined && options.body === undefined
432
+ ? undefined
433
+ : await this.engine.run('check_program', {
434
+ project: record.staged_directory,
435
+ ...(options.pou === undefined ? {} : { pou: options.pou }),
436
+ ...(options.body === undefined ? {} : { body: options.body }),
437
+ }, 180_000);
438
+ const state = await this.bridge.run('compile_state', {}, 30_000).catch(() => null);
439
+ const blockers = workflow.blockers ?? [];
440
+ const validation = validate.result;
441
+ return {
442
+ project: record.staged_directory,
443
+ blockers,
444
+ validation_errors: validation?.errors ?? [],
445
+ workflow,
446
+ validate,
447
+ ...(review === undefined ? {} : { review }),
448
+ compile_state: state,
449
+ ready: blockers.length === 0 && (validation?.errors?.length ?? 0) === 0,
450
+ };
451
+ }
452
+ /** Save the open staged project through the IDE. */
453
+ async apply() {
454
+ const record = await this.openStagedRecord();
455
+ const saved = await this.bridge.run('save', {}, 60_000);
456
+ const state = await this.bridge.run('compile_state', {}, 30_000).catch(() => null);
457
+ return { project: record.staged_directory, saved, compile_state: state };
458
+ }
459
+ /** Replace one ST/IL body through the proven native ChangeCodeWS path. */
460
+ async editCode(input) {
461
+ const record = await this.openStagedRecord();
462
+ const helpers = await import(__rewriteRelativeImportExtension(pathToFileURL(join(LEGACY_DIR, 'native-code.js')).href));
463
+ const project = record.staged_directory;
464
+ const evidenceDirectory = join(this.workspace, '.motionworks', 'verification');
465
+ const inputDirectory = join(this.workspace, '.motionworks', 'native-input');
466
+ mkdirSync(evidenceDirectory, { recursive: true });
467
+ const evidence = join(evidenceDirectory, `native-code-${randomUUID()}.json`);
468
+ const args = { project, pou: input.pou, baseline_saved: true };
469
+ if (input.changes !== undefined) {
470
+ args.changes = input.changes;
471
+ if (input.expectedHash !== undefined)
472
+ args.expected_body_sha256 = input.expectedHash;
473
+ }
474
+ else {
475
+ args.code = input.body;
476
+ args.expected_body = input.expectedBody;
477
+ }
478
+ try {
479
+ const result = await helpers.nativeCodeChange(args, {
480
+ status: async () => await this.bridge.run('compile_state'),
481
+ saved: async () => await this.engine.run('structure_snapshot', { project }),
482
+ snapshot: async () => await this.bridge.run('structure_snapshot'),
483
+ read: async () => await this.engine.run('read_text', { project, pou: input.pou }),
484
+ document: async () => {
485
+ const code = await this.engine.run('worksheet_target', { project, pou: input.pou, kind: 'code' });
486
+ const variables = await this.engine.run('worksheet_target', { project, pou: input.pou, kind: 'variables' });
487
+ const urn = String(variables.urn ?? '');
488
+ return { ...code, variable_worksheet: urn.split('.').at(-1) };
489
+ },
490
+ declarations: async () => await this.bridge.run('variable_snapshot', { pou: input.pou }),
491
+ prepare: async (text, language) => {
492
+ mkdirSync(inputDirectory, { recursive: true });
493
+ const path = join(inputDirectory, `${randomUUID()}.${language}`);
494
+ writeFileSync(path, text, { encoding: 'ascii', flag: 'wx' });
495
+ return { code_import_path: path };
496
+ },
497
+ retain: async (plan) => {
498
+ writeFileSync(evidence, JSON.stringify({ phase: 'plan_retained', ...plan }, null, 2), { encoding: 'utf8', flag: 'wx' });
499
+ },
500
+ mutate: async (request) => await this.bridge.run('code_mutate', { ...request, project }, 60_000),
501
+ });
502
+ writeFileSync(evidence, JSON.stringify({ phase: 'result', ...result }, null, 2), 'utf8');
503
+ return result;
504
+ }
505
+ catch (error) {
506
+ throw new MwiError('EDIT_REFUSED', `${error.message}; evidence at ${evidence}`, 'Read the refusal, correct the request, and retry. Do not repeat an unverified edit.');
507
+ }
508
+ }
509
+ /** The open project must be a proven stage; every compile and verify depends on it. */
510
+ async openStagedRecord() {
511
+ const status = await this.status();
512
+ if (status.is_project_open !== true || typeof status.active_project !== 'string') {
513
+ throw new MwiError('NO_PROJECT', 'No project is open in the IDE.', 'Open a staged project with mw_project_open before compiling.');
514
+ }
515
+ const record = this.stages.stagedAt(status.active_project);
516
+ if (record === undefined) {
517
+ throw new MwiError('NOT_STAGED', `The open project is not a proven stage: ${status.active_project}.`, 'Open a staged project; the verify row never compiles a workspace original.');
518
+ }
519
+ return record;
520
+ }
521
+ /** The only staged project, or a refusal that explains the choice. */
522
+ singleStage() {
523
+ let names = [];
524
+ try {
525
+ names = readdirSync(stageRootOf(this.workspace)).filter(name => name.toLowerCase().endsWith('.mwt'));
526
+ }
527
+ catch {
528
+ names = [];
529
+ }
530
+ if (names.length === 0)
531
+ throw new MwiError('NO_STAGE', 'No project is staged in this workspace.', 'Call mw_project_find, then mw_project_stage.');
532
+ if (names.length > 1) {
533
+ throw new MwiError('AMBIGUOUS_STAGE', `${names.length} projects are staged.`, 'Pass project: the staged .mwt to start.', names);
534
+ }
535
+ return join(stageRootOf(this.workspace), names[0]);
536
+ }
537
+ /** Resolve a requested staged project. */
538
+ stageMwt(project) {
539
+ const resolved = resolve(this.workspace, project);
540
+ const mwt = resolved.toLowerCase().endsWith('.mwt') ? resolved : `${resolved}.mwt`;
541
+ if (!isInside(stageRootOf(this.workspace), mwt) || !existsSync(mwt)) {
542
+ throw new MwiError('NOT_STAGED', `${mwt} is not a staged project.`, 'Stage the workspace project first, then pass the staged .mwt.');
543
+ }
544
+ return mwt;
545
+ }
546
+ }
547
+ const runtimes = new Map();
548
+ /**
549
+ * Resolve the runtime for one workspace.
550
+ *
551
+ * @param workspace - Absolute workspace root.
552
+ * @returns The cached runtime.
553
+ */
554
+ export function runtimeFor(workspace) {
555
+ const key = workspace.toLowerCase();
556
+ const existing = runtimes.get(key);
557
+ if (existing !== undefined)
558
+ return existing;
559
+ const created = new PowerShellSessionRuntime(workspace);
560
+ runtimes.set(key, created);
561
+ return created;
562
+ }
563
+ /** Resolve a tool call's workspace. */
564
+ export function workspaceFrom(exec) {
565
+ return workspaceOf(exec.cwd);
566
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Staging: copy one workspace project into `.motionworks/stage` and bind its wrapper.
3
+ *
4
+ * The source is never modified. A stage is refused when it already exists unless
5
+ * the caller explicitly replaces it after review; the previous stage is moved to
6
+ * `backups/stage-<id>` rather than discarded.
7
+ *
8
+ * @module dsh-engineering-mwi/session/stage
9
+ */
10
+ import type { CodeEngine } from '../core/code-engine.ts';
11
+ /** Identity suffix, matching the legacy stage record. */
12
+ export declare const IDENTITY_SUFFIX = ".identity.json";
13
+ /** One staged project. */
14
+ export interface StageRecord {
15
+ /** Project name (the `.mwt` basename). */
16
+ readonly name: string;
17
+ /** Original workspace `.mwt`. */
18
+ readonly source: string;
19
+ /** Original expanded project directory. */
20
+ readonly source_directory: string;
21
+ /** Workspace that owns the stage. */
22
+ readonly workspace: string;
23
+ /** Staged `.mwt`. */
24
+ readonly staged_mwt: string;
25
+ /** Staged expanded directory. */
26
+ readonly staged_directory: string;
27
+ /** Directory the wrapper was bound to. */
28
+ readonly bound_to: string;
29
+ /** The wrapper's previous embedded directory, when it named one. */
30
+ readonly previous_embedded_path: string | null;
31
+ /** When the stage was written. */
32
+ readonly staged_at: string;
33
+ }
34
+ /** Options for one staging request. */
35
+ export interface StageOptions {
36
+ /** Replace an existing stage after review; the previous stage is retained. */
37
+ readonly replace?: boolean;
38
+ /** Refuse when the current IDE project is inside the target stage. */
39
+ readonly assertClosed?: () => Promise<void>;
40
+ }
41
+ /** The service that stages projects for one workspace. */
42
+ export declare class StageService {
43
+ private readonly engine;
44
+ private readonly workspace;
45
+ /**
46
+ * @param engine - Code engine that binds the wrapper.
47
+ * @param workspace - Absolute workspace root.
48
+ */
49
+ constructor(engine: CodeEngine, workspace: string);
50
+ /** The stage root of this workspace. */
51
+ get stageRoot(): string;
52
+ /**
53
+ * Stage one project.
54
+ *
55
+ * @param sourceArg - `.mwt` or project directory inside the workspace.
56
+ * @param options - Replacement and closed-project checks.
57
+ * @returns The written stage record.
58
+ */
59
+ stage(sourceArg: string, options?: StageOptions): Promise<StageRecord>;
60
+ /**
61
+ * Read one identity record.
62
+ *
63
+ * @param name - Project name.
64
+ * @returns The record, or undefined when the name was not staged.
65
+ */
66
+ identityOf(name: string): StageRecord | undefined;
67
+ /**
68
+ * The staged project whose `.mwt` or directory is `path`.
69
+ *
70
+ * @param path - Active or requested project path.
71
+ * @returns Its identity record, or undefined.
72
+ */
73
+ stagedAt(path: string): StageRecord | undefined;
74
+ /**
75
+ * Refuse when the active IDE project is this stage.
76
+ *
77
+ * @param targetDir - Stage directory about to be replaced.
78
+ * @param status - Bridge status document.
79
+ */
80
+ static assertClosed(targetDir: string, status: {
81
+ is_project_open?: boolean;
82
+ active_project?: string;
83
+ }): void;
84
+ }