@aryacode/dsh-engineering 0.0.0-stage → 0.3.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 (281) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/LICENSE +21 -0
  3. package/README.md +228 -2
  4. package/cordis.patch.yml +122 -0
  5. package/locale/en.json +6 -0
  6. package/locale/zh.json +6 -0
  7. package/package.json +77 -3
  8. package/vendor/ftview/README.md +55 -0
  9. package/vendor/ftview/SKILL.md +74 -0
  10. package/vendor/ftview/lib/checks.d.ts +27 -0
  11. package/vendor/ftview/lib/checks.js +39 -0
  12. package/vendor/ftview/lib/core.d.ts +208 -0
  13. package/vendor/ftview/lib/core.js +160 -0
  14. package/vendor/ftview/lib/edit/drafts.d.ts +49 -0
  15. package/vendor/ftview/lib/edit/drafts.js +84 -0
  16. package/vendor/ftview/lib/edit/operations.d.ts +62 -0
  17. package/vendor/ftview/lib/edit/operations.js +126 -0
  18. package/vendor/ftview/lib/edit/prepare.d.ts +38 -0
  19. package/vendor/ftview/lib/edit/prepare.js +133 -0
  20. package/vendor/ftview/lib/edit/tools.d.ts +25 -0
  21. package/vendor/ftview/lib/edit/tools.js +198 -0
  22. package/vendor/ftview/lib/edit.d.ts +30 -0
  23. package/vendor/ftview/lib/edit.js +38 -0
  24. package/vendor/ftview/lib/index.d.ts +31 -0
  25. package/vendor/ftview/lib/index.js +36 -0
  26. package/vendor/ftview/lib/model.d.ts +80 -0
  27. package/vendor/ftview/lib/model.js +267 -0
  28. package/vendor/ftview/lib/session.d.ts +48 -0
  29. package/vendor/ftview/lib/session.js +98 -0
  30. package/vendor/ftview/lib/skill.d.ts +29 -0
  31. package/vendor/ftview/lib/skill.js +43 -0
  32. package/vendor/ftview/lib/studio/discover.d.ts +36 -0
  33. package/vendor/ftview/lib/studio/discover.js +87 -0
  34. package/vendor/ftview/lib/studio/preflight.d.ts +51 -0
  35. package/vendor/ftview/lib/studio/preflight.js +64 -0
  36. package/vendor/ftview/lib/studio/tools.d.ts +15 -0
  37. package/vendor/ftview/lib/studio/tools.js +83 -0
  38. package/vendor/ftview/lib/studio.d.ts +30 -0
  39. package/vendor/ftview/lib/studio.js +37 -0
  40. package/vendor/ftview/lib/tools.d.ts +14 -0
  41. package/vendor/ftview/lib/tools.js +202 -0
  42. package/vendor/l5x/README.md +62 -0
  43. package/vendor/l5x/SKILL.md +81 -0
  44. package/vendor/l5x/lib/approvals.d.ts +50 -0
  45. package/vendor/l5x/lib/approvals.js +93 -0
  46. package/vendor/l5x/lib/client.js +412 -0
  47. package/vendor/l5x/lib/client.js.map +1 -0
  48. package/vendor/l5x/lib/core/errors.d.ts +38 -0
  49. package/vendor/l5x/lib/core/errors.js +48 -0
  50. package/vendor/l5x/lib/core/params.d.ts +49 -0
  51. package/vendor/l5x/lib/core/params.js +39 -0
  52. package/vendor/l5x/lib/core/result.d.ts +46 -0
  53. package/vendor/l5x/lib/core/result.js +21 -0
  54. package/vendor/l5x/lib/core/tool.d.ts +102 -0
  55. package/vendor/l5x/lib/core/tool.js +19 -0
  56. package/vendor/l5x/lib/drafts.d.ts +66 -0
  57. package/vendor/l5x/lib/drafts.js +98 -0
  58. package/vendor/l5x/lib/editing.d.ts +30 -0
  59. package/vendor/l5x/lib/editing.js +42 -0
  60. package/vendor/l5x/lib/engine/acd-edit.d.ts +13 -0
  61. package/vendor/l5x/lib/engine/acd-edit.js +115 -0
  62. package/vendor/l5x/lib/engine/analysis.d.ts +22 -0
  63. package/vendor/l5x/lib/engine/analysis.js +258 -0
  64. package/vendor/l5x/lib/engine/capabilities.d.ts +9 -0
  65. package/vendor/l5x/lib/engine/capabilities.js +40 -0
  66. package/vendor/l5x/lib/engine/change-set.d.ts +122 -0
  67. package/vendor/l5x/lib/engine/change-set.js +446 -0
  68. package/vendor/l5x/lib/engine/configuration.d.ts +21 -0
  69. package/vendor/l5x/lib/engine/configuration.js +42 -0
  70. package/vendor/l5x/lib/engine/details.d.ts +47 -0
  71. package/vendor/l5x/lib/engine/details.js +173 -0
  72. package/vendor/l5x/lib/engine/direct-polling.d.ts +91 -0
  73. package/vendor/l5x/lib/engine/direct-polling.js +193 -0
  74. package/vendor/l5x/lib/engine/download-review.d.ts +15 -0
  75. package/vendor/l5x/lib/engine/download-review.js +63 -0
  76. package/vendor/l5x/lib/engine/logic-syntax.d.ts +60 -0
  77. package/vendor/l5x/lib/engine/logic-syntax.js +237 -0
  78. package/vendor/l5x/lib/engine/observations.d.ts +41 -0
  79. package/vendor/l5x/lib/engine/observations.js +67 -0
  80. package/vendor/l5x/lib/engine/project-analysis.d.ts +131 -0
  81. package/vendor/l5x/lib/engine/project-analysis.js +314 -0
  82. package/vendor/l5x/lib/engine/review-evidence.d.ts +8 -0
  83. package/vendor/l5x/lib/engine/review-evidence.js +49 -0
  84. package/vendor/l5x/lib/engine/review.d.ts +18 -0
  85. package/vendor/l5x/lib/engine/review.js +123 -0
  86. package/vendor/l5x/lib/engine/studio-sdk.d.ts +101 -0
  87. package/vendor/l5x/lib/engine/studio-sdk.js +571 -0
  88. package/vendor/l5x/lib/engine/tag-resolution.d.ts +20 -0
  89. package/vendor/l5x/lib/engine/tag-resolution.js +169 -0
  90. package/vendor/l5x/lib/engine/usage.d.ts +16 -0
  91. package/vendor/l5x/lib/engine/usage.js +92 -0
  92. package/vendor/l5x/lib/engine/xml-regions.d.ts +23 -0
  93. package/vendor/l5x/lib/engine/xml-regions.js +77 -0
  94. package/vendor/l5x/lib/fs.d.ts +17 -0
  95. package/vendor/l5x/lib/fs.js +36 -0
  96. package/vendor/l5x/lib/index.d.ts +36 -0
  97. package/vendor/l5x/lib/index.js +42 -0
  98. package/vendor/l5x/lib/live.d.ts +48 -0
  99. package/vendor/l5x/lib/live.js +48 -0
  100. package/vendor/l5x/lib/model/aois.d.ts +39 -0
  101. package/vendor/l5x/lib/model/aois.js +112 -0
  102. package/vendor/l5x/lib/model/errors.d.ts +15 -0
  103. package/vendor/l5x/lib/model/errors.js +18 -0
  104. package/vendor/l5x/lib/model/index.d.ts +20 -0
  105. package/vendor/l5x/lib/model/index.js +19 -0
  106. package/vendor/l5x/lib/model/module.d.ts +37 -0
  107. package/vendor/l5x/lib/model/module.js +54 -0
  108. package/vendor/l5x/lib/model/modules.d.ts +24 -0
  109. package/vendor/l5x/lib/model/modules.js +55 -0
  110. package/vendor/l5x/lib/model/parse.d.ts +32 -0
  111. package/vendor/l5x/lib/model/parse.js +116 -0
  112. package/vendor/l5x/lib/model/project.d.ts +15 -0
  113. package/vendor/l5x/lib/model/project.js +31 -0
  114. package/vendor/l5x/lib/model/routines.d.ts +71 -0
  115. package/vendor/l5x/lib/model/routines.js +183 -0
  116. package/vendor/l5x/lib/model/tags.d.ts +51 -0
  117. package/vendor/l5x/lib/model/tags.js +119 -0
  118. package/vendor/l5x/lib/model/types.d.ts +304 -0
  119. package/vendor/l5x/lib/model/types.js +12 -0
  120. package/vendor/l5x/lib/model/udts.d.ts +34 -0
  121. package/vendor/l5x/lib/model/udts.js +81 -0
  122. package/vendor/l5x/lib/model/xml.d.ts +139 -0
  123. package/vendor/l5x/lib/model/xml.js +291 -0
  124. package/vendor/l5x/lib/model/xref.d.ts +28 -0
  125. package/vendor/l5x/lib/model/xref.js +154 -0
  126. package/vendor/l5x/lib/session.d.ts +119 -0
  127. package/vendor/l5x/lib/session.js +236 -0
  128. package/vendor/l5x/lib/skill.d.ts +30 -0
  129. package/vendor/l5x/lib/skill.js +44 -0
  130. package/vendor/l5x/lib/studio-state.d.ts +77 -0
  131. package/vendor/l5x/lib/studio-state.js +79 -0
  132. package/vendor/l5x/lib/studio.d.ts +29 -0
  133. package/vendor/l5x/lib/studio.js +40 -0
  134. package/vendor/l5x/lib/tools/checks.d.ts +19 -0
  135. package/vendor/l5x/lib/tools/checks.js +140 -0
  136. package/vendor/l5x/lib/tools/common.d.ts +41 -0
  137. package/vendor/l5x/lib/tools/common.js +84 -0
  138. package/vendor/l5x/lib/tools/controller.d.ts +21 -0
  139. package/vendor/l5x/lib/tools/controller.js +170 -0
  140. package/vendor/l5x/lib/tools/drafts.d.ts +23 -0
  141. package/vendor/l5x/lib/tools/drafts.js +270 -0
  142. package/vendor/l5x/lib/tools/live.d.ts +21 -0
  143. package/vendor/l5x/lib/tools/live.js +175 -0
  144. package/vendor/l5x/lib/tools/read.d.ts +19 -0
  145. package/vendor/l5x/lib/tools/read.js +245 -0
  146. package/vendor/l5x/lib/tools/references.d.ts +20 -0
  147. package/vendor/l5x/lib/tools/references.js +269 -0
  148. package/vendor/l5x/lib/tools/studio.d.ts +21 -0
  149. package/vendor/l5x/lib/tools/studio.js +193 -0
  150. package/vendor/l5x/poll-worker.mjs +77 -0
  151. package/vendor/l5x/studio-bridge/NuGet.Config +1 -0
  152. package/vendor/l5x/studio-bridge/Program.cs +304 -0
  153. package/vendor/l5x/studio-bridge/StudioBridge.csproj +11 -0
  154. package/vendor/mwi/README.md +60 -0
  155. package/vendor/mwi/SKILL.md +87 -0
  156. package/vendor/mwi/bridge/README.md +8 -0
  157. package/vendor/mwi/bridge/mw_bridge.ps1 +2763 -0
  158. package/vendor/mwi/bridge/sdk-interop-importer.cs +30 -0
  159. package/vendor/mwi/bridge/sdk-variable-reader.cs +22 -0
  160. package/vendor/mwi/bridge/start_bridge.cmd +21 -0
  161. package/vendor/mwi/bridge/watch_dialogs.cmd +13 -0
  162. package/vendor/mwi/bridge/watch_dialogs.ps1 +153 -0
  163. package/vendor/mwi/code/engine/motionworks_iec_mcp/__init__.py +14 -0
  164. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/__init__.cpython-312.pyc +0 -0
  165. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/block_interfaces.cpython-312.pyc +0 -0
  166. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/cfb.cpython-312.pyc +0 -0
  167. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/datatypes.cpython-312.pyc +0 -0
  168. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/declarations.cpython-312.pyc +0 -0
  169. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/errors.cpython-312.pyc +0 -0
  170. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/graphical_listing.cpython-312.pyc +0 -0
  171. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/grid.cpython-312.pyc +0 -0
  172. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/knowledge.cpython-312.pyc +0 -0
  173. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/mwt_bind.cpython-312.pyc +0 -0
  174. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/navigation.cpython-312.pyc +0 -0
  175. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/program_checks.cpython-312.pyc +0 -0
  176. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/project.cpython-312.pyc +0 -0
  177. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/staging.cpython-312.pyc +0 -0
  178. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/structure.cpython-312.pyc +0 -0
  179. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/task_bindings.cpython-312.pyc +0 -0
  180. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/tasks.cpython-312.pyc +0 -0
  181. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/tree.cpython-312.pyc +0 -0
  182. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/validation.cpython-312.pyc +0 -0
  183. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/variable_edit.cpython-312.pyc +0 -0
  184. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/variables.cpython-312.pyc +0 -0
  185. package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/workflow.cpython-312.pyc +0 -0
  186. package/vendor/mwi/code/engine/motionworks_iec_mcp/block_interfaces.py +275 -0
  187. package/vendor/mwi/code/engine/motionworks_iec_mcp/build.py +339 -0
  188. package/vendor/mwi/code/engine/motionworks_iec_mcp/capture.py +448 -0
  189. package/vendor/mwi/code/engine/motionworks_iec_mcp/cfb.py +765 -0
  190. package/vendor/mwi/code/engine/motionworks_iec_mcp/com.py +268 -0
  191. package/vendor/mwi/code/engine/motionworks_iec_mcp/datatypes.py +204 -0
  192. package/vendor/mwi/code/engine/motionworks_iec_mcp/declarations.py +399 -0
  193. package/vendor/mwi/code/engine/motionworks_iec_mcp/descriptions.py +30 -0
  194. package/vendor/mwi/code/engine/motionworks_iec_mcp/eip.py +292 -0
  195. package/vendor/mwi/code/engine/motionworks_iec_mcp/errors.py +36 -0
  196. package/vendor/mwi/code/engine/motionworks_iec_mcp/graphical_listing.py +208 -0
  197. package/vendor/mwi/code/engine/motionworks_iec_mcp/grid.py +227 -0
  198. package/vendor/mwi/code/engine/motionworks_iec_mcp/ide.py +317 -0
  199. package/vendor/mwi/code/engine/motionworks_iec_mcp/iec.py +317 -0
  200. package/vendor/mwi/code/engine/motionworks_iec_mcp/installed_help.py +151 -0
  201. package/vendor/mwi/code/engine/motionworks_iec_mcp/knowledge.py +218 -0
  202. package/vendor/mwi/code/engine/motionworks_iec_mcp/libraries.py +250 -0
  203. package/vendor/mwi/code/engine/motionworks_iec_mcp/manuals.py +520 -0
  204. package/vendor/mwi/code/engine/motionworks_iec_mcp/mwt_bind.py +133 -0
  205. package/vendor/mwi/code/engine/motionworks_iec_mcp/navigation.py +44 -0
  206. package/vendor/mwi/code/engine/motionworks_iec_mcp/pou_writer.py +1547 -0
  207. package/vendor/mwi/code/engine/motionworks_iec_mcp/program_checks.py +360 -0
  208. package/vendor/mwi/code/engine/motionworks_iec_mcp/project.py +704 -0
  209. package/vendor/mwi/code/engine/motionworks_iec_mcp/reference_data/catalog.json +672 -0
  210. package/vendor/mwi/code/engine/motionworks_iec_mcp/reference_data/patterns.json +86 -0
  211. package/vendor/mwi/code/engine/motionworks_iec_mcp/restore.py +208 -0
  212. package/vendor/mwi/code/engine/motionworks_iec_mcp/server.py +1913 -0
  213. package/vendor/mwi/code/engine/motionworks_iec_mcp/snapshot.py +138 -0
  214. package/vendor/mwi/code/engine/motionworks_iec_mcp/st_comments.py +25 -0
  215. package/vendor/mwi/code/engine/motionworks_iec_mcp/staging.py +179 -0
  216. package/vendor/mwi/code/engine/motionworks_iec_mcp/stlint.py +676 -0
  217. package/vendor/mwi/code/engine/motionworks_iec_mcp/structure.py +98 -0
  218. package/vendor/mwi/code/engine/motionworks_iec_mcp/task_bindings.py +68 -0
  219. package/vendor/mwi/code/engine/motionworks_iec_mcp/tasks.py +162 -0
  220. package/vendor/mwi/code/engine/motionworks_iec_mcp/transaction.py +157 -0
  221. package/vendor/mwi/code/engine/motionworks_iec_mcp/tree.py +563 -0
  222. package/vendor/mwi/code/engine/motionworks_iec_mcp/tree_writer.py +790 -0
  223. package/vendor/mwi/code/engine/motionworks_iec_mcp/uia.py +465 -0
  224. package/vendor/mwi/code/engine/motionworks_iec_mcp/validation.py +41 -0
  225. package/vendor/mwi/code/engine/motionworks_iec_mcp/variable_edit.py +183 -0
  226. package/vendor/mwi/code/engine/motionworks_iec_mcp/variables.py +472 -0
  227. package/vendor/mwi/code/engine/motionworks_iec_mcp/workflow.py +130 -0
  228. package/vendor/mwi/code/engine/motionworks_iec_mcp/writer.py +666 -0
  229. package/vendor/mwi/code/mw_code.py +1258 -0
  230. package/vendor/mwi/legacy/edit-session.js +50 -0
  231. package/vendor/mwi/legacy/fb-insertion.js +74 -0
  232. package/vendor/mwi/legacy/native-code.js +83 -0
  233. package/vendor/mwi/legacy/native-groups.js +75 -0
  234. package/vendor/mwi/legacy/native-structure.js +143 -0
  235. package/vendor/mwi/legacy/native-variables.js +77 -0
  236. package/vendor/mwi/legacy/pou-conversion.js +47 -0
  237. package/vendor/mwi/legacy/pou-package.js +66 -0
  238. package/vendor/mwi/lib/core/bridge.d.ts +71 -0
  239. package/vendor/mwi/lib/core/bridge.js +53 -0
  240. package/vendor/mwi/lib/core/code-engine.d.ts +47 -0
  241. package/vendor/mwi/lib/core/code-engine.js +109 -0
  242. package/vendor/mwi/lib/core/errors.d.ts +37 -0
  243. package/vendor/mwi/lib/core/errors.js +47 -0
  244. package/vendor/mwi/lib/core/params.d.ts +52 -0
  245. package/vendor/mwi/lib/core/params.js +46 -0
  246. package/vendor/mwi/lib/core/ps-bridge.d.ts +62 -0
  247. package/vendor/mwi/lib/core/ps-bridge.js +127 -0
  248. package/vendor/mwi/lib/core/result.d.ts +45 -0
  249. package/vendor/mwi/lib/core/result.js +20 -0
  250. package/vendor/mwi/lib/core/tool.d.ts +80 -0
  251. package/vendor/mwi/lib/core/tool.js +55 -0
  252. package/vendor/mwi/lib/edit/compare.d.ts +33 -0
  253. package/vendor/mwi/lib/edit/compare.js +70 -0
  254. package/vendor/mwi/lib/edit.d.ts +20 -0
  255. package/vendor/mwi/lib/edit.js +32 -0
  256. package/vendor/mwi/lib/index.d.ts +21 -0
  257. package/vendor/mwi/lib/index.js +33 -0
  258. package/vendor/mwi/lib/read/service.d.ts +117 -0
  259. package/vendor/mwi/lib/read/service.js +229 -0
  260. package/vendor/mwi/lib/read.d.ts +21 -0
  261. package/vendor/mwi/lib/read.js +33 -0
  262. package/vendor/mwi/lib/session/project.d.ts +34 -0
  263. package/vendor/mwi/lib/session/project.js +54 -0
  264. package/vendor/mwi/lib/session/service.d.ts +167 -0
  265. package/vendor/mwi/lib/session/service.js +566 -0
  266. package/vendor/mwi/lib/session/stage.d.ts +84 -0
  267. package/vendor/mwi/lib/session/stage.js +187 -0
  268. package/vendor/mwi/lib/session/workspace.d.ts +52 -0
  269. package/vendor/mwi/lib/session/workspace.js +90 -0
  270. package/vendor/mwi/lib/skill.d.ts +36 -0
  271. package/vendor/mwi/lib/skill.js +56 -0
  272. package/vendor/mwi/lib/tools/edit.d.ts +20 -0
  273. package/vendor/mwi/lib/tools/edit.js +286 -0
  274. package/vendor/mwi/lib/tools/read.d.ts +19 -0
  275. package/vendor/mwi/lib/tools/read.js +161 -0
  276. package/vendor/mwi/lib/tools/session.d.ts +20 -0
  277. package/vendor/mwi/lib/tools/session.js +166 -0
  278. package/vendor/mwi/lib/tools/verify.d.ts +19 -0
  279. package/vendor/mwi/lib/tools/verify.js +85 -0
  280. package/vendor/mwi/lib/verify.d.ts +17 -0
  281. package/vendor/mwi/lib/verify.js +29 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","names":["useState"],"sources":["../src/client/locales.ts","../src/client/trend-model.ts","../src/client/TrendCard.tsx","../src/client/index.ts"],"sourcesContent":["/** Copy owned by the Studio 5000 loader console. */\n\n/** Locale namespace this console registers its dictionaries under. */\nexport const NS = 'studio5000'\n\n/** Chinese copy. */\nexport const zh = {\n 'trend.title': 'PLC 实时趋势',\n 'trend.actualInterval': '显示窗口平均实际间隔',\n 'trend.overruns': '观察到的超时周期',\n 'trend.badValue': '读数不可用',\n 'trend.connecting': '正在连接…',\n 'trend.running': '采集中',\n 'trend.completed': '采集完成',\n 'trend.stopped': '已停止',\n 'trend.failed': '采集失败',\n 'trend.unavailable': '实时趋势流不可用',\n 'trend.gap': '部分历史数据不可用',\n 'trend.stopFailed': '无法停止采集,请重试',\n 'trend.stop': '停止',\n 'trend.interval': '请求间隔',\n 'trend.samples': '显示采样数',\n 'trend.source': '源文件',\n 'trend.limitation': '读取并非 PLC 扫描同步,可能遗漏变化;尚未验证在线逻辑与导出一致',\n title: 'Studio 5000',\n workspace: '工作区',\n refresh: '刷新',\n rescan: '重新扫描',\n recent: '最近打开',\n projects: '项目',\n open: '在 Studio 5000 中打开',\n filter: '筛选 ACD 项目',\n 'fallback.open': '使用 Windows 默认应用打开',\n 'fallback.description': '文件处理程序查询不可用或未找到 Studio。此操作将使用此 ACD 的系统默认应用。',\n 'status.defaultOpened': '已发送给系统默认应用。请确认打开的是正确项目。',\n 'launch.description': '在已安装的 Studio 5000 中打开项目。',\n 'status.desktop': '此主机没有可用的桌面。',\n 'status.discovery': '无法检查此文件的应用程序。请更新主机或检查连接。',\n 'status.handler': '没有找到 Studio 5000 文件处理程序。请检查安装和 ACD 文件关联。',\n reveal: '在资源管理器中显示',\n 'empty.none': '此工作区中没有找到 .acd 文件。',\n 'empty.scanning': '正在扫描工作区…',\n 'empty.noSession': '此工作区还没有会话,无法列出文件。',\n 'empty.noWorkspace': '还没有工作区。请先打开一个项目文件夹。',\n 'unavailable.listing': '此配置未提供工作区文件列表功能。',\n 'unavailable.launch': '此主机无法打开本机文件。',\n 'unavailable.desktop': '当前主机没有可用的桌面程序。',\n 'status.opened': '已发送打开请求。请在 Studio 5000 中确认项目已打开。',\n 'status.revealed': '已在资源管理器中显示。',\n 'status.failed': '打开失败。',\n 'status.scanFailed': '部分目录无法读取。',\n 'status.truncated': '列表已被截断。',\n size: '大小',\n truncated: '(已截断)',\n} satisfies Record<string, string>\n\n/** English copy, same keys. */\nexport const en = {\n 'trend.title': 'Live PLC trend',\n 'trend.actualInterval': 'Mean actual interval in displayed window',\n 'trend.overruns': 'Observed sweep overruns',\n 'trend.badValue': 'Reading unavailable',\n 'trend.connecting': 'Connecting…',\n 'trend.running': 'Collecting',\n 'trend.completed': 'Capture complete',\n 'trend.stopped': 'Stopped',\n 'trend.failed': 'Capture failed',\n 'trend.unavailable': 'Live trend stream unavailable',\n 'trend.gap': 'Some history is unavailable',\n 'trend.stopFailed': 'Could not stop capture. Try again.',\n 'trend.stop': 'Stop',\n 'trend.interval': 'Requested interval',\n 'trend.samples': 'Displayed samples',\n 'trend.source': 'Source export',\n 'trend.limitation': 'Reads are not scan-synchronized and may miss transitions. Online logic matching this export is unverified.',\n title: 'Studio 5000',\n workspace: 'Workspace',\n refresh: 'Refresh',\n rescan: 'Rescan',\n recent: 'Recently opened',\n projects: 'Projects',\n open: 'Open in Studio 5000',\n filter: 'Filter ACD projects',\n 'fallback.open': 'Open with Windows default',\n 'fallback.description': 'Handler discovery is unavailable or found no Studio handler. This opens the selected ACD using its system default application.',\n 'status.defaultOpened': 'Sent to the system default application. Confirm the correct project opened.',\n 'launch.description': 'Open projects in installed Studio 5000.',\n 'status.desktop': 'No desktop is available on this host.',\n 'status.discovery': 'Could not check file handlers. Update the host or check the connection.',\n 'status.handler': 'No Studio 5000 file handler found. Check the installation and ACD file association.',\n reveal: 'Reveal in Explorer',\n 'empty.none': 'No .acd files found in this workspace.',\n 'empty.scanning': 'Scanning the workspace…',\n 'empty.noSession': 'This workspace has no Session yet, so its files cannot be listed.',\n 'empty.noWorkspace': 'No workspace yet. Open a project folder first.',\n 'unavailable.listing': 'Workspace file listing is not available in this profile.',\n 'unavailable.launch': 'This host cannot open local files.',\n 'unavailable.desktop': 'No desktop application is available on this host.',\n 'status.opened': 'Open request sent. Confirm the project opened in Studio 5000.',\n 'status.revealed': 'Revealed in the file manager.',\n 'status.failed': 'Could not open the project.',\n 'status.scanFailed': 'Some directories could not be read.',\n 'status.truncated': 'The listing was truncated.',\n size: 'Size',\n truncated: '(truncated)',\n} satisfies Record<keyof typeof zh, string>\n","/** Bounded, gap-preserving plot data from the authenticated job stream. */\nexport interface TrendPoint { elapsed: number; overrun: boolean | undefined; values: { tag: string; value: number | boolean | null; quality: string }[] }\n/** Start receipt persisted in the tool result. */\nexport interface TrendReceipt { jobId: string; sessionId: string; interval: number; sourceHash: string; refresh: number; maxSamples: number }\n\n/** Parse a recorded start receipt. @param content - Logged tool content. @returns Valid receipt or undefined. */\nexport function trendReceipt(content: unknown): TrendReceipt | undefined {\n if (!Array.isArray(content)) return undefined\n for (const entry of content) {\n if (!entry || typeof entry !== 'object' || entry.type !== 'text' || typeof entry.text !== 'string') continue\n try {\n const value: unknown = JSON.parse(entry.text)\n if (value && typeof value === 'object' && 'view' in value && value.view === 'plc-trend'\n && 'job_id' in value && typeof value.job_id === 'string' && /^plc-trend-\\d+$/u.test(value.job_id)\n && 'owner_session_id' in value && typeof value.owner_session_id === 'string'\n && 'requested_interval_ms' in value && typeof value.requested_interval_ms === 'number'\n && 'source_sha256' in value && typeof value.source_sha256 === 'string'\n && 'display_refresh_ms' in value && typeof value.display_refresh_ms === 'number' && value.display_refresh_ms >= 50 && value.display_refresh_ms <= 10000\n && 'display_max_samples' in value && typeof value.display_max_samples === 'number' && value.display_max_samples >= 2 && value.display_max_samples <= 20000)\n return { jobId: value.job_id, sessionId: value.owner_session_id, interval: value.requested_interval_ms, sourceHash: value.source_sha256,\n refresh: value.display_refresh_ms, maxSamples: value.display_max_samples }\n } catch (error) { void error /* Failed tool output is rendered as a state, not plot data. */ }\n }\n return undefined\n}\n\n/** Parse one sampler line. @param line - Retained job output. @returns Plot point or undefined for other frames. */\nexport function trendPoint(line: string): TrendPoint | undefined {\n const value: unknown = JSON.parse(line)\n if (!value || typeof value !== 'object' || !('type' in value) || value.type !== 'sample') return undefined\n if (!('elapsed_ms' in value) || typeof value.elapsed_ms !== 'number' || !Number.isFinite(value.elapsed_ms)\n || !('values' in value) || !Array.isArray(value.values)) throw new Error('Invalid trend sample')\n const values = value.values.map((item: unknown) => {\n if (!item || typeof item !== 'object' || !('tag' in item) || typeof item.tag !== 'string'\n || !('quality' in item) || typeof item.quality !== 'string' || !('value' in item)\n || !(item.value === null || typeof item.value === 'boolean' || typeof item.value === 'number' && Number.isFinite(item.value)))\n throw new Error('Invalid trend value')\n return { tag: item.tag, quality: item.quality, value: item.value }\n })\n return { elapsed: value.elapsed_ms, overrun: 'overrun' in value && typeof value.overrun === 'boolean' ? value.overrun : undefined, values }\n}\n\n/** Build distinct line segments so bad samples do not imply continuity. @param points - Retained samples. @param tag - Scoped tag. @returns SVG line segments and range. */\nexport function trendSegments(points: readonly TrendPoint[], tag: string) {\n const finite = points.flatMap(point => point.values.filter(item => item.tag === tag && item.quality === 'good' && item.value !== null).map(item => Number(item.value)))\n const min = Math.min(0, ...finite); const max = Math.max(1, ...finite)\n const start = points[0]?.elapsed ?? 0; const duration = Math.max(1, (points.at(-1)?.elapsed ?? start) - start)\n const segments: string[] = []; let current: string[] = []\n for (const point of points) {\n const value = point.values.find(item => item.tag === tag)\n if (!value || value.quality !== 'good' || value.value === null) {\n if (current.length) segments.push(current.join(' ')); current = []; continue\n }\n const x = 10 + (point.elapsed - start) / duration * 580\n const y = 100 - (Number(value.value) - min) / (max - min) * 90\n if (typeof value.value === 'boolean' && current.length) current.push(`${x},${current.at(-1)?.split(',')[1]}`)\n current.push(`${x},${y}`)\n }\n if (current.length) segments.push(current.join(' '))\n return { segments, min, max }\n}\n","/** Inline live PLC trend driven by the existing session-authorized job stream. */\nimport { useEffect, useState } from 'react'\nimport type { TrendJobRemote } from './types.ts'\nimport { trendPoint, trendReceipt, trendSegments, type TrendPoint } from './trend-model.ts'\n\n/** Narrow owner/injected props supplied by the keyed tool seat. */\nexport interface TrendCardProps {\n phase: string\n block: { content?: unknown; isError?: boolean }\n trendJobs?: TrendJobRemote | undefined\n t(key: string): string\n}\n\n/** Display a live watch and stop it without cancelling the chat. @param props - Tool seat and existing job Remote. @returns Trend card. */\nexport function TrendCard({ phase, block, trendJobs, t }: TrendCardProps) {\n const receipt = phase === 'result' ? trendReceipt(block.content) : undefined\n const [points, setPoints] = useState<TrendPoint[]>([])\n const [state, setState] = useState('trend.connecting')\n const [stopping, setStopping] = useState(false)\n useEffect(() => {\n if (!receipt || !trendJobs) return\n const abort = new AbortController()\n let pending: TrendPoint[] = []; let dirty = false; let tail = ''\n const flush = () => { if (!dirty || abort.signal.aborted) return; dirty = false; setPoints([...pending]) }\n const timer = setInterval(flush, receipt.refresh)\n const run = async () => {\n try {\n for await (const frame of trendJobs.follow({ jobId: receipt.jobId, sessionId: receipt.sessionId }, abort.signal)) {\n if (abort.signal.aborted) return\n if (!frame || typeof frame !== 'object' || !('type' in frame)) throw new Error('Invalid job frame')\n if (frame.type === 'opened') setState('trend.running')\n if (frame.type === 'output' && 'chunks' in frame && Array.isArray(frame.chunks)) {\n if ('lossy' in frame && frame.lossy === true) { pending = []; tail = ''; setState('trend.gap') }\n for (const chunk of frame.chunks) {\n if (!chunk || typeof chunk !== 'object' || typeof chunk.text !== 'string') throw new Error('Invalid trend output')\n if (chunk.gapBefore === true) { pending = []; tail = ''; setState('trend.gap') }\n tail += chunk.text\n const lines = tail.split('\\n'); tail = lines.pop() ?? ''\n for (const line of lines) {\n const point = trendPoint(line)\n if (point) { pending.push(point); if (pending.length > receipt.maxSamples) pending.shift(); dirty = true }\n }\n }\n }\n if (frame.type === 'status' && 'job' in frame && frame.job && typeof frame.job === 'object' && 'status' in frame.job) {\n flush(); setState(frame.job.status === 'completed' ? 'trend.completed' : frame.job.status === 'killed' ? 'trend.stopped' : 'trend.failed')\n }\n }\n } catch (error) { if (!abort.signal.aborted) { void error; setState('trend.unavailable') } }\n finally { clearInterval(timer); flush() }\n }\n void run()\n return () => { abort.abort(); clearInterval(timer) }\n }, [receipt?.jobId, receipt?.sessionId, receipt?.refresh, receipt?.maxSamples, trendJobs])\n if (!receipt) return <div role=\"status\">{t(block.isError ? 'trend.failed' : 'trend.connecting')}</div>\n const tags = [...new Set(points.flatMap(point => point.values.map(value => value.tag)))]\n const stop = async () => {\n if (!trendJobs || stopping) return\n setStopping(true)\n try {\n const result = await trendJobs.kill({ jobId: receipt.jobId, sessionId: receipt.sessionId })\n if (!result.ok) setState('trend.stopFailed')\n } catch (error) { void error; setState('trend.stopFailed') }\n finally { setStopping(false) }\n }\n return <section aria-label={t('trend.title')} style={{ padding: '12px', border: '1px solid var(--dsw-alias-border-l3)', borderRadius: '8px' }}>\n <div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>\n <span>{t('trend.title')}</span><span role=\"status\">{t(trendJobs ? state : 'trend.unavailable')}</span>\n <button type=\"button\" style={{ color: 'var(--dsw-alias-label-primary)', background: 'transparent', border: '1px solid var(--dsw-alias-border-l3)', borderRadius: '6px', font: 'inherit', padding: '4px 10px' }} disabled={!trendJobs || stopping || ['trend.completed', 'trend.stopped', 'trend.failed'].includes(state)} onClick={() => { void stop() }}>{t('trend.stop')}</button>\n </div>\n <p>{t('trend.interval')}: {receipt.interval} ms · {t('trend.samples')}: {points.length}</p>\n {points.length > 1 && <p>{t('trend.actualInterval')}: {((points.at(-1)!.elapsed - points[0]!.elapsed) / (points.length - 1)).toFixed(1)} ms · {t('trend.overruns')}: {points.filter(point => point.overrun === true).length}</p>}\n {tags.map(tag => {\n const plot = trendSegments(points, tag)\n const latest = points.at(-1)?.values.find(value => value.tag === tag)\n return <figure key={tag} style={{ margin: '12px 0' }}><figcaption>{tag} · {latest?.quality === 'good' ? String(latest.value) : t('trend.badValue')} · {plot.min}–{plot.max}</figcaption>\n <svg viewBox=\"0 0 600 110\" role=\"img\" aria-label={tag} style={{ width: '100%', height: '110px' }}>\n {plot.segments.map((segment, index) => <polyline key={index} points={segment} fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" />)}\n </svg>\n <small>{((points[0]?.elapsed ?? 0) / 1000).toFixed(2)}–{((points.at(-1)?.elapsed ?? 0) / 1000).toFixed(2)} s</small>\n </figure>\n })}\n <small>{t('trend.source')}: {receipt.sourceHash.slice(0, 12)} · {t('trend.limitation')}</small>\n </section>\n}\n","/** Inline PLC trend tool view; data and cancellation use the existing job Remote. */\nimport type { ClientScope } from './types.ts'\nimport { en, NS, zh } from './locales.ts'\nimport { TrendCard } from './TrendCard.tsx'\n\n/** Required client services; job availability is explained inside the card. */\nexport const inject = ['slots', 'locale', 'remote']\n\n/** Register the live trend card without a Studio launcher sidebar. @param ctx - Browser service context. */\nexport function apply(ctx: ClientScope): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'l5x-live: trend copy')\n ctx.slots.inject('tool.call.toolview', () => ctx.slots.register({\n name: 'tool.call.toolview', key: 'start_plc_trend', locale: NS,\n inject: () => ({ trendJobs: ctx.remote.job }),\n }, TrendCard))\n}\n"],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Failures the model can repair from.
3
+ *
4
+ * Every expected failure carries the next call, because a refused tool call is
5
+ * a turn the reader has to spend. An unexpected failure is a plugin defect and
6
+ * says so instead of pretending to be a project problem.
7
+ *
8
+ * @module dsh-engineering-l5x/core/errors
9
+ */
10
+ /** One expected failure, with everything the reader needs to recover. */
11
+ export declare class L5xError extends Error {
12
+ readonly code: string;
13
+ readonly fix: string;
14
+ readonly candidates: readonly string[];
15
+ /**
16
+ * @param code - Stable identifier for tests and logs.
17
+ * @param message - What failed, in the reader's terms.
18
+ * @param fix - The exact next call or check.
19
+ * @param candidates - Valid names when the request named something absent or ambiguous.
20
+ */
21
+ constructor(code: string, message: string, fix: string, candidates?: readonly string[]);
22
+ }
23
+ /** The model-facing failure document. */
24
+ export interface ErrorEnvelope {
25
+ readonly error: {
26
+ readonly code: string;
27
+ readonly message: string;
28
+ readonly fix: string;
29
+ readonly candidates: readonly string[];
30
+ };
31
+ }
32
+ /**
33
+ * Convert a thrown value into the failure document.
34
+ *
35
+ * @param error - Whatever the tool body threw.
36
+ * @returns The failure document; never throws.
37
+ */
38
+ export declare function errorEnvelope(error: unknown): ErrorEnvelope;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Failures the model can repair from.
3
+ *
4
+ * Every expected failure carries the next call, because a refused tool call is
5
+ * a turn the reader has to spend. An unexpected failure is a plugin defect and
6
+ * says so instead of pretending to be a project problem.
7
+ *
8
+ * @module dsh-engineering-l5x/core/errors
9
+ */
10
+ /** One expected failure, with everything the reader needs to recover. */
11
+ export class L5xError extends Error {
12
+ code;
13
+ fix;
14
+ candidates;
15
+ /**
16
+ * @param code - Stable identifier for tests and logs.
17
+ * @param message - What failed, in the reader's terms.
18
+ * @param fix - The exact next call or check.
19
+ * @param candidates - Valid names when the request named something absent or ambiguous.
20
+ */
21
+ constructor(code, message, fix, candidates = []) {
22
+ super(message);
23
+ this.code = code;
24
+ this.fix = fix;
25
+ this.candidates = candidates;
26
+ this.name = 'L5xError';
27
+ }
28
+ }
29
+ /**
30
+ * Convert a thrown value into the failure document.
31
+ *
32
+ * @param error - Whatever the tool body threw.
33
+ * @returns The failure document; never throws.
34
+ */
35
+ export function errorEnvelope(error) {
36
+ if (error instanceof L5xError) {
37
+ return { error: { code: error.code, message: error.message, fix: error.fix, candidates: error.candidates } };
38
+ }
39
+ const message = error instanceof Error ? error.message : String(error);
40
+ return {
41
+ error: {
42
+ code: 'INTERNAL',
43
+ message,
44
+ fix: 'This is a plugin defect, not a project condition. Report it with the arguments used, then reopen the project.',
45
+ candidates: [],
46
+ },
47
+ };
48
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Parameter schemas that always describe themselves.
3
+ *
4
+ * The port's first measured failure was 132 parameters with no description.
5
+ * These helpers make an undescribed parameter impossible to write: the
6
+ * description is a required argument, not an optional field.
7
+ *
8
+ * @module dsh-engineering-l5x/core/params
9
+ */
10
+ /** One JSON Schema property, with the description that is mandatory here. */
11
+ export interface ParameterSchema {
12
+ readonly type: 'string' | 'integer' | 'number' | 'boolean' | 'array' | 'object';
13
+ readonly description: string;
14
+ readonly enum?: readonly string[];
15
+ readonly items?: ParameterSchema;
16
+ readonly default?: unknown;
17
+ readonly minimum?: number;
18
+ readonly maximum?: number;
19
+ readonly minItems?: number;
20
+ readonly maxItems?: number;
21
+ readonly properties?: Readonly<Record<string, ParameterSchema>>;
22
+ readonly required?: readonly string[];
23
+ readonly additionalProperties?: boolean;
24
+ }
25
+ /** A string parameter. */
26
+ export declare function string(description: string, extra?: Partial<ParameterSchema>): ParameterSchema;
27
+ /** An integer parameter with an optional range. */
28
+ export declare function integer(description: string, extra?: Partial<ParameterSchema>): ParameterSchema;
29
+ /** A string parameter restricted to a known set. */
30
+ export declare function choice(description: string, values: readonly string[], extra?: Partial<ParameterSchema>): ParameterSchema;
31
+ /** An array of one parameter type. */
32
+ export declare function list(description: string, items: ParameterSchema, extra?: Partial<ParameterSchema>): ParameterSchema;
33
+ /** One object element of an array parameter. */
34
+ export declare function objectItem(description: string, properties: Readonly<Record<string, ParameterSchema>>, required?: readonly string[]): ParameterSchema;
35
+ /** The `parameters` object of one tool. */
36
+ export interface Parameters {
37
+ readonly type: 'object';
38
+ readonly properties: Readonly<Record<string, ParameterSchema>>;
39
+ readonly required: readonly string[];
40
+ readonly additionalProperties: false;
41
+ }
42
+ /**
43
+ * Build a tool's parameter object.
44
+ *
45
+ * @param properties - Named parameters, every one already described.
46
+ * @param required - Names the caller must supply.
47
+ * @returns The schema object a tool definition declares.
48
+ */
49
+ export declare function object(properties: Readonly<Record<string, ParameterSchema>>, required?: readonly string[]): Parameters;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Parameter schemas that always describe themselves.
3
+ *
4
+ * The port's first measured failure was 132 parameters with no description.
5
+ * These helpers make an undescribed parameter impossible to write: the
6
+ * description is a required argument, not an optional field.
7
+ *
8
+ * @module dsh-engineering-l5x/core/params
9
+ */
10
+ /** A string parameter. */
11
+ export function string(description, extra = {}) {
12
+ return { type: 'string', description, ...extra };
13
+ }
14
+ /** An integer parameter with an optional range. */
15
+ export function integer(description, extra = {}) {
16
+ return { type: 'integer', description, ...extra };
17
+ }
18
+ /** A string parameter restricted to a known set. */
19
+ export function choice(description, values, extra = {}) {
20
+ return { type: 'string', description, enum: values, ...extra };
21
+ }
22
+ /** An array of one parameter type. */
23
+ export function list(description, items, extra = {}) {
24
+ return { type: 'array', description, items, ...extra };
25
+ }
26
+ /** One object element of an array parameter. */
27
+ export function objectItem(description, properties, required = []) {
28
+ return { type: 'object', description, properties, required, additionalProperties: false };
29
+ }
30
+ /**
31
+ * Build a tool's parameter object.
32
+ *
33
+ * @param properties - Named parameters, every one already described.
34
+ * @param required - Names the caller must supply.
35
+ * @returns The schema object a tool definition declares.
36
+ */
37
+ export function object(properties, required = []) {
38
+ return { type: 'object', properties, required, additionalProperties: false };
39
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The model-facing success document.
3
+ *
4
+ * Every read answers with a summary first and concrete next calls last. The
5
+ * summary lets a small model decide whether it got what it asked for without
6
+ * reading the whole payload; `next` is the recovery path when its plan is thin.
7
+ *
8
+ * @module dsh-engineering-l5x/core/result
9
+ */
10
+ /** One call the reader can make next, with the reason it is useful. */
11
+ export interface NextStep {
12
+ /** Tool name registered by this plugin. */
13
+ readonly tool: string;
14
+ /** Why this call answers the current question. */
15
+ readonly why: string;
16
+ /** Arguments worth passing; omitted when the tool needs none. */
17
+ readonly args?: Readonly<Record<string, unknown>>;
18
+ }
19
+ /** How much of the requested question the answer actually covers. */
20
+ export interface Coverage {
21
+ /** Whether the requested scope was answered in full. */
22
+ readonly complete: boolean;
23
+ /** What this answer cannot establish, named rather than implied. */
24
+ readonly unverified: readonly string[];
25
+ }
26
+ /** A successful tool answer. */
27
+ export interface Success<T> {
28
+ /** One sentence the reader can act on. */
29
+ readonly summary: string;
30
+ /** Tool-specific payload. */
31
+ readonly data: T;
32
+ /** Present when the answer has limits worth stating. */
33
+ readonly coverage?: Coverage;
34
+ /** Concrete next calls, most useful first. */
35
+ readonly next: readonly NextStep[];
36
+ }
37
+ /**
38
+ * Build a success document.
39
+ *
40
+ * @param summary - One sentence naming what was read.
41
+ * @param data - Tool-specific payload.
42
+ * @param next - Concrete next calls; may be empty when the answer is terminal.
43
+ * @param coverage - Limits of the answer, when it has any.
44
+ * @returns The document the tool returns.
45
+ */
46
+ export declare function success<T>(summary: string, data: T, next?: readonly NextStep[], coverage?: Coverage): Success<T>;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The model-facing success document.
3
+ *
4
+ * Every read answers with a summary first and concrete next calls last. The
5
+ * summary lets a small model decide whether it got what it asked for without
6
+ * reading the whole payload; `next` is the recovery path when its plan is thin.
7
+ *
8
+ * @module dsh-engineering-l5x/core/result
9
+ */
10
+ /**
11
+ * Build a success document.
12
+ *
13
+ * @param summary - One sentence naming what was read.
14
+ * @param data - Tool-specific payload.
15
+ * @param next - Concrete next calls; may be empty when the answer is terminal.
16
+ * @param coverage - Limits of the answer, when it has any.
17
+ * @returns The document the tool returns.
18
+ */
19
+ export function success(summary, data, next = [], coverage) {
20
+ return coverage === undefined ? { summary, data, next } : { summary, data, coverage, next };
21
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * The tool and service surfaces this package registers against.
3
+ *
4
+ * Declared locally, and structurally, so the package compiles without the host
5
+ * packages at build time while still matching what the Cordis registry and the
6
+ * filesystem provider expose at runtime.
7
+ *
8
+ * @module dsh-engineering-l5x/core/tool
9
+ */
10
+ import type { Parameters } from './params.ts';
11
+ /** One content block the registry renders for the model. */
12
+ export interface TextBlock {
13
+ readonly type: 'text';
14
+ readonly text: string;
15
+ }
16
+ /** The canonical output declaration every tool must carry. */
17
+ export interface ToolOutput {
18
+ readonly schema: {
19
+ readonly type: 'object';
20
+ readonly additionalProperties: boolean;
21
+ };
22
+ render(args: unknown, value: unknown): readonly TextBlock[];
23
+ }
24
+ /** The execution context a tool receives from the registry. */
25
+ export interface ToolExec {
26
+ readonly signal?: AbortSignal;
27
+ readonly callId?: unknown;
28
+ readonly sessionId?: string;
29
+ readonly agent?: {
30
+ readonly session?: {
31
+ readonly header?: {
32
+ readonly cwd?: string;
33
+ };
34
+ };
35
+ };
36
+ }
37
+ /** The context a tool body receives: cancellation, workspace, chat identity and approval fields. */
38
+ export interface ExecContext {
39
+ readonly signal?: AbortSignal;
40
+ readonly cwd?: string;
41
+ /** The calling chat; handles are scoped to it. */
42
+ readonly chat?: object;
43
+ /** Registry call id, forwarded to the approval request. */
44
+ readonly callId?: unknown;
45
+ /** Owning session id, used by session-owned jobs. */
46
+ readonly sessionId?: string;
47
+ /** The calling agent, forwarded to the approval request. */
48
+ readonly agent?: unknown;
49
+ }
50
+ /** A registered tool. */
51
+ export interface ToolDefinition {
52
+ readonly name: string;
53
+ readonly description: string;
54
+ readonly parameters: Parameters;
55
+ readonly output: ToolOutput;
56
+ execute(args: Readonly<Record<string, unknown>>, exec: ToolExec): Promise<unknown>;
57
+ }
58
+ /** The registry service. */
59
+ export interface ToolRegistry {
60
+ register(definition: ToolDefinition): unknown;
61
+ }
62
+ /** A path resolved by the filesystem provider into its backend identity. */
63
+ export interface FsTarget {
64
+ /** Opaque key for stale guards and target lookup. */
65
+ readonly targetKey: unknown;
66
+ /** Path for model- and UI-facing output. */
67
+ readonly displayPath: string;
68
+ }
69
+ /** The filesystem service operations this package uses. */
70
+ export interface FsService {
71
+ resolve(path: string, options?: {
72
+ readonly signal?: AbortSignal;
73
+ readonly cwd?: string;
74
+ }): Promise<FsTarget>;
75
+ stat(target: FsTarget, signal?: AbortSignal): Promise<{
76
+ readonly type: string;
77
+ } | undefined>;
78
+ readBytes(target: FsTarget, signal: AbortSignal | undefined, maxBytes?: number): Promise<Uint8Array>;
79
+ writeText?(target: FsTarget, text: string, options?: {
80
+ readonly kind?: 'createIfAbsent';
81
+ }, signal?: AbortSignal): Promise<void>;
82
+ }
83
+ /** The services a composition must provide before this plugin loads. */
84
+ export interface PluginContext {
85
+ readonly tools: ToolRegistry;
86
+ readonly fs: FsService;
87
+ readonly logger?: {
88
+ warn(message: string): void;
89
+ };
90
+ /** Register a service other entries in the same composition can consume. */
91
+ provide?(name: string, value: unknown): void;
92
+ /** Read a service another entry in the same composition provided. */
93
+ get?(name: string): unknown;
94
+ }
95
+ /**
96
+ * Render one tool answer as pretty JSON.
97
+ *
98
+ * @param _args - Accepted arguments; unused by this renderer.
99
+ * @param value - The validated canonical value.
100
+ * @returns One text block.
101
+ */
102
+ export declare function jsonText(_args: unknown, value: unknown): readonly TextBlock[];
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The tool and service surfaces this package registers against.
3
+ *
4
+ * Declared locally, and structurally, so the package compiles without the host
5
+ * packages at build time while still matching what the Cordis registry and the
6
+ * filesystem provider expose at runtime.
7
+ *
8
+ * @module dsh-engineering-l5x/core/tool
9
+ */
10
+ /**
11
+ * Render one tool answer as pretty JSON.
12
+ *
13
+ * @param _args - Accepted arguments; unused by this renderer.
14
+ * @param value - The validated canonical value.
15
+ * @returns One text block.
16
+ */
17
+ export function jsonText(_args, value) {
18
+ return [{ type: 'text', text: JSON.stringify(value, undefined, 2) }];
19
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Drafts: one accumulated edit list per project per chat.
3
+ *
4
+ * The model adds one operation at a time, sees the count grow, then validates
5
+ * and applies. Nothing here writes a file; preparation and application belong
6
+ * to the tools, so an abandoned draft leaves no residue.
7
+ *
8
+ * @module dsh-engineering-l5x/drafts
9
+ */
10
+ import type { ExecContext } from './core/tool.ts';
11
+ /** One version-1 change-set operation, as the engine accepts it. */
12
+ export interface DraftOperation {
13
+ readonly operation: string;
14
+ readonly [field: string]: unknown;
15
+ }
16
+ /** One accumulated draft. */
17
+ export interface Draft {
18
+ /** Stable handle returned to the caller. */
19
+ readonly id: string;
20
+ /** Project handle this draft applies to. */
21
+ readonly projectId: string;
22
+ /** Operations in the order they were added. */
23
+ readonly operations: readonly DraftOperation[];
24
+ /** ISO timestamp of the first operation. */
25
+ readonly createdAt: string;
26
+ }
27
+ /** Drafts, scoped to the chat that created them. */
28
+ export declare class DraftStore {
29
+ private readonly chats;
30
+ private readonly detached;
31
+ /**
32
+ * The draft for one project in this chat, created on first use.
33
+ *
34
+ * @param exec - Calling context; its chat selects the draft set.
35
+ * @param projectId - Project handle the draft edits.
36
+ * @returns The accumulated draft.
37
+ */
38
+ forProject(exec: ExecContext | undefined, projectId: string): Draft;
39
+ /**
40
+ * Append one operation to a project's draft.
41
+ *
42
+ * @param exec - Calling context.
43
+ * @param projectId - Project handle the draft edits.
44
+ * @param operation - Operation to append.
45
+ * @param maxOperations - Inclusive operation cap for one draft.
46
+ * @returns The updated draft.
47
+ */
48
+ append(exec: ExecContext | undefined, projectId: string, operation: DraftOperation, maxOperations: number): Draft;
49
+ /**
50
+ * Resolve one draft by handle.
51
+ *
52
+ * @param exec - Calling context.
53
+ * @param id - Draft handle; empty selects the chat's only draft.
54
+ * @returns The draft.
55
+ */
56
+ get(exec: ExecContext | undefined, id: string | undefined): Draft;
57
+ /**
58
+ * Remove one draft after it is applied.
59
+ *
60
+ * @param exec - Calling context.
61
+ * @param id - Draft handle.
62
+ */
63
+ remove(exec: ExecContext | undefined, id: string): void;
64
+ /** The draft map for one calling chat. */
65
+ private chatsOf;
66
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Drafts: one accumulated edit list per project per chat.
3
+ *
4
+ * The model adds one operation at a time, sees the count grow, then validates
5
+ * and applies. Nothing here writes a file; preparation and application belong
6
+ * to the tools, so an abandoned draft leaves no residue.
7
+ *
8
+ * @module dsh-engineering-l5x/drafts
9
+ */
10
+ import { randomUUID } from 'node:crypto';
11
+ import { L5xError } from "./core/errors.js";
12
+ /** Drafts, scoped to the chat that created them. */
13
+ export class DraftStore {
14
+ chats = new WeakMap();
15
+ detached = new Map();
16
+ /**
17
+ * The draft for one project in this chat, created on first use.
18
+ *
19
+ * @param exec - Calling context; its chat selects the draft set.
20
+ * @param projectId - Project handle the draft edits.
21
+ * @returns The accumulated draft.
22
+ */
23
+ forProject(exec, projectId) {
24
+ const drafts = this.chatsOf(exec);
25
+ for (const draft of drafts.values()) {
26
+ if (draft.projectId === projectId)
27
+ return draft;
28
+ }
29
+ const created = { id: randomUUID(), projectId, operations: [], createdAt: new Date().toISOString() };
30
+ drafts.set(created.id, created);
31
+ return created;
32
+ }
33
+ /**
34
+ * Append one operation to a project's draft.
35
+ *
36
+ * @param exec - Calling context.
37
+ * @param projectId - Project handle the draft edits.
38
+ * @param operation - Operation to append.
39
+ * @param maxOperations - Inclusive operation cap for one draft.
40
+ * @returns The updated draft.
41
+ */
42
+ append(exec, projectId, operation, maxOperations) {
43
+ const current = this.forProject(exec, projectId);
44
+ if (current.operations.length >= maxOperations) {
45
+ throw new L5xError('DRAFT_TOO_LARGE', `This draft already holds ${current.operations.length} operations, the configured maximum.`, 'Validate and apply this draft, then start another for the remaining edits.');
46
+ }
47
+ const updated = { ...current, operations: [...current.operations, operation] };
48
+ this.chatsOf(exec).set(updated.id, updated);
49
+ return updated;
50
+ }
51
+ /**
52
+ * Resolve one draft by handle.
53
+ *
54
+ * @param exec - Calling context.
55
+ * @param id - Draft handle; empty selects the chat's only draft.
56
+ * @returns The draft.
57
+ */
58
+ get(exec, id) {
59
+ const drafts = this.chatsOf(exec);
60
+ const ids = [...drafts.keys()];
61
+ if (id === undefined || id === '') {
62
+ const only = ids[0];
63
+ if (only === undefined) {
64
+ throw new L5xError('NO_DRAFT', 'No draft exists in this chat.', 'Add an operation with a draft_* tool first.');
65
+ }
66
+ if (ids.length > 1) {
67
+ throw new L5xError('AMBIGUOUS_DRAFT', `${ids.length} drafts exist in this chat, so draft_id is required.`, `Pass one of: ${ids.join(', ')}.`, ids);
68
+ }
69
+ return drafts.get(only);
70
+ }
71
+ const draft = drafts.get(id);
72
+ if (draft === undefined) {
73
+ throw new L5xError('UNKNOWN_DRAFT', `No draft exists with draft_id ${JSON.stringify(id)} in this chat.`, ids.length === 0 ? 'Add an operation with a draft_* tool first.' : `Pass one of this chat's draft ids: ${ids.join(', ')}.`, ids);
74
+ }
75
+ return draft;
76
+ }
77
+ /**
78
+ * Remove one draft after it is applied.
79
+ *
80
+ * @param exec - Calling context.
81
+ * @param id - Draft handle.
82
+ */
83
+ remove(exec, id) {
84
+ this.chatsOf(exec).delete(id);
85
+ }
86
+ /** The draft map for one calling chat. */
87
+ chatsOf(exec) {
88
+ const chat = exec?.chat;
89
+ if (chat === undefined)
90
+ return this.detached;
91
+ const existing = this.chats.get(chat);
92
+ if (existing !== undefined)
93
+ return existing;
94
+ const created = new Map();
95
+ this.chats.set(chat, created);
96
+ return created;
97
+ }
98
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The L5X editing entry: drafts over the read entry's project handles.
3
+ *
4
+ * Kept separate so a profile that only reads, checks and compares does not pay
5
+ * for nine draft schemas. It consumes the `l5xProjects` service the read entry
6
+ * provides, so a project is opened once and both entries see the same handle.
7
+ *
8
+ * @module dsh-engineering-l5x/editing
9
+ */
10
+ import type { PluginContext } from './core/tool.ts';
11
+ /** Plugin name in a composition. */
12
+ export declare const name = "l5x-editing";
13
+ /** The read entry's project service must already be mounted. */
14
+ export declare const inject: readonly ["tools", "l5xProjects"];
15
+ /** Configuration for the editing entry. */
16
+ export interface Config {
17
+ /** Largest export, in bytes, one preparation may read. Defaults to 64 MiB. */
18
+ maxFileBytes?: number;
19
+ /** Most operations one draft may accumulate. Defaults to 200. */
20
+ maxDraftOperations?: number;
21
+ }
22
+ /**
23
+ * Register the draft tools.
24
+ *
25
+ * @param ctx - Plugin context carrying the read entry's project service.
26
+ * @param config - Deployment limits.
27
+ */
28
+ export declare function apply(ctx: PluginContext, config?: Config): void;
29
+ export { DraftStore } from './drafts.ts';
30
+ export { draftTools } from './tools/drafts.ts';