@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.
- package/CHANGELOG.md +128 -0
- package/LICENSE +21 -0
- package/README.md +230 -2
- package/cordis.patch.yml +123 -0
- package/lib/client.js +3448 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +9 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +94 -3
- package/vendor/ftview/README.md +55 -0
- package/vendor/ftview/SKILL.md +74 -0
- package/vendor/ftview/lib/checks.d.ts +27 -0
- package/vendor/ftview/lib/checks.js +39 -0
- package/vendor/ftview/lib/core.d.ts +208 -0
- package/vendor/ftview/lib/core.js +160 -0
- package/vendor/ftview/lib/edit/drafts.d.ts +49 -0
- package/vendor/ftview/lib/edit/drafts.js +84 -0
- package/vendor/ftview/lib/edit/operations.d.ts +62 -0
- package/vendor/ftview/lib/edit/operations.js +126 -0
- package/vendor/ftview/lib/edit/prepare.d.ts +38 -0
- package/vendor/ftview/lib/edit/prepare.js +133 -0
- package/vendor/ftview/lib/edit/tools.d.ts +25 -0
- package/vendor/ftview/lib/edit/tools.js +198 -0
- package/vendor/ftview/lib/edit.d.ts +30 -0
- package/vendor/ftview/lib/edit.js +38 -0
- package/vendor/ftview/lib/index.d.ts +31 -0
- package/vendor/ftview/lib/index.js +36 -0
- package/vendor/ftview/lib/model.d.ts +80 -0
- package/vendor/ftview/lib/model.js +267 -0
- package/vendor/ftview/lib/session.d.ts +48 -0
- package/vendor/ftview/lib/session.js +98 -0
- package/vendor/ftview/lib/skill.d.ts +29 -0
- package/vendor/ftview/lib/skill.js +43 -0
- package/vendor/ftview/lib/studio/discover.d.ts +36 -0
- package/vendor/ftview/lib/studio/discover.js +87 -0
- package/vendor/ftview/lib/studio/preflight.d.ts +51 -0
- package/vendor/ftview/lib/studio/preflight.js +64 -0
- package/vendor/ftview/lib/studio/tools.d.ts +15 -0
- package/vendor/ftview/lib/studio/tools.js +83 -0
- package/vendor/ftview/lib/studio.d.ts +30 -0
- package/vendor/ftview/lib/studio.js +37 -0
- package/vendor/ftview/lib/tools.d.ts +14 -0
- package/vendor/ftview/lib/tools.js +202 -0
- package/vendor/l5x/README.md +62 -0
- package/vendor/l5x/SKILL.md +81 -0
- package/vendor/l5x/lib/approvals.d.ts +50 -0
- package/vendor/l5x/lib/approvals.js +93 -0
- package/vendor/l5x/lib/client.js +412 -0
- package/vendor/l5x/lib/client.js.map +1 -0
- package/vendor/l5x/lib/core/errors.d.ts +38 -0
- package/vendor/l5x/lib/core/errors.js +48 -0
- package/vendor/l5x/lib/core/params.d.ts +49 -0
- package/vendor/l5x/lib/core/params.js +39 -0
- package/vendor/l5x/lib/core/result.d.ts +46 -0
- package/vendor/l5x/lib/core/result.js +21 -0
- package/vendor/l5x/lib/core/tool.d.ts +102 -0
- package/vendor/l5x/lib/core/tool.js +19 -0
- package/vendor/l5x/lib/drafts.d.ts +66 -0
- package/vendor/l5x/lib/drafts.js +98 -0
- package/vendor/l5x/lib/editing.d.ts +30 -0
- package/vendor/l5x/lib/editing.js +42 -0
- package/vendor/l5x/lib/engine/acd-edit.d.ts +13 -0
- package/vendor/l5x/lib/engine/acd-edit.js +115 -0
- package/vendor/l5x/lib/engine/analysis.d.ts +22 -0
- package/vendor/l5x/lib/engine/analysis.js +258 -0
- package/vendor/l5x/lib/engine/capabilities.d.ts +9 -0
- package/vendor/l5x/lib/engine/capabilities.js +40 -0
- package/vendor/l5x/lib/engine/change-set.d.ts +122 -0
- package/vendor/l5x/lib/engine/change-set.js +446 -0
- package/vendor/l5x/lib/engine/configuration.d.ts +21 -0
- package/vendor/l5x/lib/engine/configuration.js +42 -0
- package/vendor/l5x/lib/engine/details.d.ts +47 -0
- package/vendor/l5x/lib/engine/details.js +173 -0
- package/vendor/l5x/lib/engine/direct-polling.d.ts +91 -0
- package/vendor/l5x/lib/engine/direct-polling.js +193 -0
- package/vendor/l5x/lib/engine/download-review.d.ts +15 -0
- package/vendor/l5x/lib/engine/download-review.js +63 -0
- package/vendor/l5x/lib/engine/logic-syntax.d.ts +60 -0
- package/vendor/l5x/lib/engine/logic-syntax.js +237 -0
- package/vendor/l5x/lib/engine/observations.d.ts +41 -0
- package/vendor/l5x/lib/engine/observations.js +67 -0
- package/vendor/l5x/lib/engine/project-analysis.d.ts +131 -0
- package/vendor/l5x/lib/engine/project-analysis.js +314 -0
- package/vendor/l5x/lib/engine/review-evidence.d.ts +8 -0
- package/vendor/l5x/lib/engine/review-evidence.js +49 -0
- package/vendor/l5x/lib/engine/review.d.ts +18 -0
- package/vendor/l5x/lib/engine/review.js +123 -0
- package/vendor/l5x/lib/engine/studio-sdk.d.ts +101 -0
- package/vendor/l5x/lib/engine/studio-sdk.js +571 -0
- package/vendor/l5x/lib/engine/tag-resolution.d.ts +20 -0
- package/vendor/l5x/lib/engine/tag-resolution.js +169 -0
- package/vendor/l5x/lib/engine/usage.d.ts +16 -0
- package/vendor/l5x/lib/engine/usage.js +92 -0
- package/vendor/l5x/lib/engine/xml-regions.d.ts +23 -0
- package/vendor/l5x/lib/engine/xml-regions.js +77 -0
- package/vendor/l5x/lib/fs.d.ts +17 -0
- package/vendor/l5x/lib/fs.js +36 -0
- package/vendor/l5x/lib/index.d.ts +36 -0
- package/vendor/l5x/lib/index.js +42 -0
- package/vendor/l5x/lib/live.d.ts +48 -0
- package/vendor/l5x/lib/live.js +48 -0
- package/vendor/l5x/lib/model/aois.d.ts +39 -0
- package/vendor/l5x/lib/model/aois.js +112 -0
- package/vendor/l5x/lib/model/errors.d.ts +15 -0
- package/vendor/l5x/lib/model/errors.js +18 -0
- package/vendor/l5x/lib/model/index.d.ts +20 -0
- package/vendor/l5x/lib/model/index.js +19 -0
- package/vendor/l5x/lib/model/module.d.ts +37 -0
- package/vendor/l5x/lib/model/module.js +54 -0
- package/vendor/l5x/lib/model/modules.d.ts +24 -0
- package/vendor/l5x/lib/model/modules.js +55 -0
- package/vendor/l5x/lib/model/parse.d.ts +32 -0
- package/vendor/l5x/lib/model/parse.js +116 -0
- package/vendor/l5x/lib/model/project.d.ts +15 -0
- package/vendor/l5x/lib/model/project.js +31 -0
- package/vendor/l5x/lib/model/routines.d.ts +71 -0
- package/vendor/l5x/lib/model/routines.js +183 -0
- package/vendor/l5x/lib/model/tags.d.ts +51 -0
- package/vendor/l5x/lib/model/tags.js +119 -0
- package/vendor/l5x/lib/model/types.d.ts +304 -0
- package/vendor/l5x/lib/model/types.js +12 -0
- package/vendor/l5x/lib/model/udts.d.ts +34 -0
- package/vendor/l5x/lib/model/udts.js +81 -0
- package/vendor/l5x/lib/model/xml.d.ts +139 -0
- package/vendor/l5x/lib/model/xml.js +291 -0
- package/vendor/l5x/lib/model/xref.d.ts +28 -0
- package/vendor/l5x/lib/model/xref.js +154 -0
- package/vendor/l5x/lib/session.d.ts +119 -0
- package/vendor/l5x/lib/session.js +236 -0
- package/vendor/l5x/lib/skill.d.ts +30 -0
- package/vendor/l5x/lib/skill.js +44 -0
- package/vendor/l5x/lib/studio-state.d.ts +77 -0
- package/vendor/l5x/lib/studio-state.js +79 -0
- package/vendor/l5x/lib/studio.d.ts +29 -0
- package/vendor/l5x/lib/studio.js +40 -0
- package/vendor/l5x/lib/tools/checks.d.ts +19 -0
- package/vendor/l5x/lib/tools/checks.js +140 -0
- package/vendor/l5x/lib/tools/common.d.ts +41 -0
- package/vendor/l5x/lib/tools/common.js +84 -0
- package/vendor/l5x/lib/tools/controller.d.ts +21 -0
- package/vendor/l5x/lib/tools/controller.js +170 -0
- package/vendor/l5x/lib/tools/drafts.d.ts +23 -0
- package/vendor/l5x/lib/tools/drafts.js +270 -0
- package/vendor/l5x/lib/tools/live.d.ts +21 -0
- package/vendor/l5x/lib/tools/live.js +175 -0
- package/vendor/l5x/lib/tools/read.d.ts +19 -0
- package/vendor/l5x/lib/tools/read.js +245 -0
- package/vendor/l5x/lib/tools/references.d.ts +20 -0
- package/vendor/l5x/lib/tools/references.js +269 -0
- package/vendor/l5x/lib/tools/studio.d.ts +21 -0
- package/vendor/l5x/lib/tools/studio.js +193 -0
- package/vendor/l5x/poll-worker.mjs +77 -0
- package/vendor/l5x/studio-bridge/NuGet.Config +1 -0
- package/vendor/l5x/studio-bridge/Program.cs +304 -0
- package/vendor/l5x/studio-bridge/StudioBridge.csproj +11 -0
- package/vendor/mwi/README.md +60 -0
- package/vendor/mwi/SKILL.md +87 -0
- package/vendor/mwi/bridge/README.md +8 -0
- package/vendor/mwi/bridge/mw_bridge.ps1 +2763 -0
- package/vendor/mwi/bridge/sdk-interop-importer.cs +30 -0
- package/vendor/mwi/bridge/sdk-variable-reader.cs +22 -0
- package/vendor/mwi/bridge/start_bridge.cmd +21 -0
- package/vendor/mwi/bridge/watch_dialogs.cmd +13 -0
- package/vendor/mwi/bridge/watch_dialogs.ps1 +153 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__init__.py +14 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/__init__.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/block_interfaces.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/cfb.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/datatypes.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/declarations.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/errors.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/graphical_listing.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/grid.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/knowledge.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/mwt_bind.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/navigation.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/program_checks.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/project.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/staging.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/structure.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/task_bindings.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/tasks.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/tree.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/validation.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/variable_edit.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/variables.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/__pycache__/workflow.cpython-312.pyc +0 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/block_interfaces.py +275 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/build.py +339 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/capture.py +448 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/cfb.py +765 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/com.py +268 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/datatypes.py +204 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/declarations.py +399 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/descriptions.py +30 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/eip.py +292 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/errors.py +36 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/graphical_listing.py +208 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/grid.py +227 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/ide.py +317 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/iec.py +317 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/installed_help.py +151 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/knowledge.py +218 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/libraries.py +250 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/manuals.py +520 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/mwt_bind.py +133 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/navigation.py +44 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/pou_writer.py +1547 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/program_checks.py +360 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/project.py +704 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/reference_data/catalog.json +672 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/reference_data/patterns.json +86 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/restore.py +208 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/server.py +1913 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/snapshot.py +138 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/st_comments.py +25 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/staging.py +179 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/stlint.py +676 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/structure.py +98 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/task_bindings.py +68 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/tasks.py +162 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/transaction.py +157 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/tree.py +563 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/tree_writer.py +790 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/uia.py +465 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/validation.py +41 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/variable_edit.py +183 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/variables.py +472 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/workflow.py +130 -0
- package/vendor/mwi/code/engine/motionworks_iec_mcp/writer.py +666 -0
- package/vendor/mwi/code/mw_code.py +1258 -0
- package/vendor/mwi/legacy/edit-session.js +50 -0
- package/vendor/mwi/legacy/fb-insertion.js +74 -0
- package/vendor/mwi/legacy/native-code.js +83 -0
- package/vendor/mwi/legacy/native-groups.js +75 -0
- package/vendor/mwi/legacy/native-structure.js +143 -0
- package/vendor/mwi/legacy/native-variables.js +77 -0
- package/vendor/mwi/legacy/pou-conversion.js +47 -0
- package/vendor/mwi/legacy/pou-package.js +66 -0
- package/vendor/mwi/lib/core/bridge.d.ts +71 -0
- package/vendor/mwi/lib/core/bridge.js +53 -0
- package/vendor/mwi/lib/core/code-engine.d.ts +47 -0
- package/vendor/mwi/lib/core/code-engine.js +109 -0
- package/vendor/mwi/lib/core/errors.d.ts +37 -0
- package/vendor/mwi/lib/core/errors.js +47 -0
- package/vendor/mwi/lib/core/params.d.ts +52 -0
- package/vendor/mwi/lib/core/params.js +46 -0
- package/vendor/mwi/lib/core/ps-bridge.d.ts +62 -0
- package/vendor/mwi/lib/core/ps-bridge.js +127 -0
- package/vendor/mwi/lib/core/result.d.ts +45 -0
- package/vendor/mwi/lib/core/result.js +20 -0
- package/vendor/mwi/lib/core/tool.d.ts +80 -0
- package/vendor/mwi/lib/core/tool.js +55 -0
- package/vendor/mwi/lib/edit/compare.d.ts +33 -0
- package/vendor/mwi/lib/edit/compare.js +70 -0
- package/vendor/mwi/lib/edit.d.ts +20 -0
- package/vendor/mwi/lib/edit.js +32 -0
- package/vendor/mwi/lib/index.d.ts +21 -0
- package/vendor/mwi/lib/index.js +33 -0
- package/vendor/mwi/lib/read/service.d.ts +117 -0
- package/vendor/mwi/lib/read/service.js +229 -0
- package/vendor/mwi/lib/read.d.ts +21 -0
- package/vendor/mwi/lib/read.js +33 -0
- package/vendor/mwi/lib/session/project.d.ts +34 -0
- package/vendor/mwi/lib/session/project.js +54 -0
- package/vendor/mwi/lib/session/service.d.ts +167 -0
- package/vendor/mwi/lib/session/service.js +566 -0
- package/vendor/mwi/lib/session/stage.d.ts +84 -0
- package/vendor/mwi/lib/session/stage.js +187 -0
- package/vendor/mwi/lib/session/workspace.d.ts +52 -0
- package/vendor/mwi/lib/session/workspace.js +90 -0
- package/vendor/mwi/lib/skill.d.ts +36 -0
- package/vendor/mwi/lib/skill.js +56 -0
- package/vendor/mwi/lib/tools/edit.d.ts +20 -0
- package/vendor/mwi/lib/tools/edit.js +286 -0
- package/vendor/mwi/lib/tools/read.d.ts +19 -0
- package/vendor/mwi/lib/tools/read.js +161 -0
- package/vendor/mwi/lib/tools/session.d.ts +20 -0
- package/vendor/mwi/lib/tools/session.js +166 -0
- package/vendor/mwi/lib/tools/verify.d.ts +19 -0
- package/vendor/mwi/lib/tools/verify.js +85 -0
- package/vendor/mwi/lib/verify.d.ts +17 -0
- package/vendor/mwi/lib/verify.js +29 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {isDeepStrictEqual as same} from 'node:util';
|
|
2
|
+
const sourceKeys=['pous','tasks','globals','program_sources','translation_files'];
|
|
3
|
+
const identical=(before,after)=>sourceKeys.every(k=>same(before[k],after[k]));
|
|
4
|
+
const exact=(rows,name)=>rows.find(p=>p.name===name);
|
|
5
|
+
const prefix=(file,name)=>file.replaceAll('\\','/').toLowerCase().startsWith('poe/'+name.toLowerCase()+'/');
|
|
6
|
+
export function alignSavedNative(saved,native){
|
|
7
|
+
const fields=['name','type','section','group','address','initial_value','description'];
|
|
8
|
+
const projectRows=rows=>rows.map(v=>Object.fromEntries(fields.map(k=>[k,k==='description'?(v[k]?.trim()||null):v[k]??null]))).sort((a,b)=>a.name.localeCompare(b.name));
|
|
9
|
+
// COM omits worksheet comments on externals. Verify those through the exact
|
|
10
|
+
// saved translation/body baseline, while preserving raw native rows separately.
|
|
11
|
+
const declarationRows=rows=>projectRows(rows.map(v=>v.section==='VAR_EXTERNAL'?{...v,description:null}:v));
|
|
12
|
+
if(saved.pous.length!==native.structure.pous.length||!same(projectRows(saved.globals),projectRows(native.declarations.globals.variables)))throw Error('Saved/native package inventories or globals disagree');
|
|
13
|
+
for(const pou of saved.pous){
|
|
14
|
+
const meta=exact(native.structure.pous,pou.name),declarations=native.declarations['pou:'+pou.name];
|
|
15
|
+
if(!meta||meta.type!==pou.type||meta.language!==({IL:1,ST:2,FBD:3,LD:4}[pou.language])||!declarations||!same(declarationRows(pou.variables),declarationRows(declarations.variables)))throw Error('Saved/native POU declaration identity disagrees: '+pou.name);
|
|
16
|
+
}
|
|
17
|
+
const tasks=rows=>[...rows].sort((a,b)=>a.name.localeCompare(b.name)).map(({name,kind,instances})=>({name,kind,instances}));
|
|
18
|
+
if(!same(tasks(saved.tasks),tasks(native.structure.tasks)))throw Error('Saved/native task inventories disagree');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function exportPouPackage(args,deps){
|
|
22
|
+
if(args.baseline_saved!==true)throw Error('Reconcile/save edits before native export');
|
|
23
|
+
if(!/^[A-Za-z_][A-Za-z_0-9]{0,29}$/.test(args.pou??''))throw Error('Exact POU name required');
|
|
24
|
+
if((await deps.status()).is_modified!==false)throw Error('Unsaved or unknown native baseline');
|
|
25
|
+
const saved=await deps.saved(),native=await deps.snapshot(),pou=exact(saved.pous,args.pou),meta=exact(native.structure.pous,args.pou);
|
|
26
|
+
alignSavedNative(saved,native);
|
|
27
|
+
if(!pou||!meta||meta.read_only||!['ST','LD','FBD'].includes(pou.language))throw Error('Exact writable supported POU required');
|
|
28
|
+
const result=await deps.mutate({operation:'export',pou:args.pou,before_state:native,before_files:saved.file_hashes});
|
|
29
|
+
const after=await deps.saved(),afterNative=await deps.snapshot(),status=await deps.status();
|
|
30
|
+
if(result.return_code!==0||status.is_modified!==false||!identical(saved,after)||!same(native,afterNative))throw Error('Native export or complete source/declaration preservation unverified');
|
|
31
|
+
const manifest=await deps.manifest();
|
|
32
|
+
if(!manifest.length||!manifest.some(f=>f.path.toLowerCase()==='pou.tre')||!manifest.some(f=>f.path.toLowerCase()===args.pou.toLowerCase()+'/src.st1'))throw Error('Native package inventory incomplete');
|
|
33
|
+
return {saved,native,pou,meta,manifest,result};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function importPouPackage(args,receipt,deps){
|
|
37
|
+
if(args.baseline_saved!==true||args.dependencies_reviewed!==true)throw Error('Saved baseline and dependency review required');
|
|
38
|
+
if(receipt.used)throw Error('Package import was already attempted; inspect retained evidence');
|
|
39
|
+
if((await deps.status()).is_modified!==false)throw Error('Unsaved or unknown native baseline');
|
|
40
|
+
const before=await deps.saved(),native=await deps.snapshot(),name=receipt.pou.name;
|
|
41
|
+
alignSavedNative(before,native);
|
|
42
|
+
if(before.pous.some(p=>p.name.toLowerCase()===name.toLowerCase())||native.structure.pous.some(p=>p.name.toLowerCase()===name.toLowerCase()))throw Error('POU name already exists; package import never overwrites');
|
|
43
|
+
if(!same(receipt.manifest,await deps.manifest()))throw Error('Native package changed since export');
|
|
44
|
+
if(!same(native.libraries,receipt.native.libraries))throw Error('Native library bindings changed; inspect dependencies');
|
|
45
|
+
for(const v of receipt.pou.variables.filter(v=>v.section==='VAR_EXTERNAL')){
|
|
46
|
+
if(!before.globals.some(g=>g.name.toUpperCase()===v.name.toUpperCase()&&g.type.toUpperCase()===v.type.toUpperCase()))throw Error('Missing/mismatched external: '+v.name);
|
|
47
|
+
}
|
|
48
|
+
await deps.consume();
|
|
49
|
+
const result=await deps.mutate({operation:'import',pou:name,before_state:native,before_files:before.file_hashes,package_manifest:receipt.manifest});
|
|
50
|
+
const after=await deps.saved(),afterNative=await deps.snapshot(),status=await deps.status(),errors=[];
|
|
51
|
+
if(result.return_code!==0||result.saved!==true||status.is_modified!==false)errors.push('Native import/save not proven');
|
|
52
|
+
if(!same(receipt.pou,exact(after.pous,name)))errors.push('Imported body/declarations differ from native export');
|
|
53
|
+
if(!same([...before.pous,receipt.pou].sort((a,b)=>a.name<b.name?-1:a.name>b.name?1:0),after.pous))errors.push('Saved POU inventory/collateral differs from plan');
|
|
54
|
+
for(const key of ['tasks','globals'])if(!same(before[key],after[key]))errors.push('Unrelated '+key+' changed');
|
|
55
|
+
for(const key of ['program_sources','translation_files']){
|
|
56
|
+
for(const file of new Set([...Object.keys(before[key]),...Object.keys(after[key])])){
|
|
57
|
+
const expected=prefix(file,name)?receipt.saved[key][file]:before[key][file];
|
|
58
|
+
if(!same(expected,after[key][file]))errors.push('Source/translation differs: '+file);
|
|
59
|
+
}
|
|
60
|
+
for(const file of Object.keys(receipt.saved[key]).filter(f=>prefix(f,name)))if(!same(receipt.saved[key][file],after[key][file]))errors.push('Imported source missing/different: '+file);
|
|
61
|
+
}
|
|
62
|
+
const expectedNative=structuredClone(native);expectedNative.structure.pous.push(receipt.meta);
|
|
63
|
+
expectedNative.declarations['pou:'+name]=receipt.native.declarations['pou:'+name];
|
|
64
|
+
if(!same(expectedNative,afterNative))errors.push('Complete native metadata/groups/declaration flags differ from plan');
|
|
65
|
+
return {accepted:!errors.length,errors,result,before,after,native_before:native,native_after:afterNative};
|
|
66
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The typed boundary to the 32-bit COM bridge.
|
|
3
|
+
*
|
|
4
|
+
* The bridge is implementation: it owns the PowerShell process and the vendor
|
|
5
|
+
* automation components, while the tools speak this request/response contract.
|
|
6
|
+
* Phase 0 defines the contract; the PowerShell transport lands with the session
|
|
7
|
+
* row.
|
|
8
|
+
*
|
|
9
|
+
* @module dsh-engineering-mwi/core/bridge
|
|
10
|
+
*/
|
|
11
|
+
/** One operation the bridge understands. */
|
|
12
|
+
export interface BridgeRequest {
|
|
13
|
+
/** Operation name, for example `ide-status` or `pou-read`. */
|
|
14
|
+
readonly operation: string;
|
|
15
|
+
/** Operation arguments; the bridge validates them. */
|
|
16
|
+
readonly arguments: Readonly<Record<string, unknown>>;
|
|
17
|
+
}
|
|
18
|
+
/** The bridge's answer. */
|
|
19
|
+
export interface BridgeResponse {
|
|
20
|
+
/** Whether the operation completed. */
|
|
21
|
+
readonly ok: boolean;
|
|
22
|
+
/** Operation result when `ok` is true. */
|
|
23
|
+
readonly result?: unknown;
|
|
24
|
+
/** Failure when `ok` is false. */
|
|
25
|
+
readonly error?: {
|
|
26
|
+
readonly code: string;
|
|
27
|
+
readonly message: string;
|
|
28
|
+
readonly details?: string;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** The process boundary the client is built over. */
|
|
32
|
+
export interface BridgeTransport {
|
|
33
|
+
/**
|
|
34
|
+
* Send one request and read one response.
|
|
35
|
+
*
|
|
36
|
+
* @param request - Operation and arguments.
|
|
37
|
+
* @param timeoutMs - Hard operation budget.
|
|
38
|
+
* @param signal - Cancellation owned by the caller.
|
|
39
|
+
* @returns The bridge's answer.
|
|
40
|
+
*/
|
|
41
|
+
send(request: BridgeRequest, timeoutMs: number, signal?: AbortSignal): Promise<BridgeResponse>;
|
|
42
|
+
}
|
|
43
|
+
/** Default operation budget; IDE compile operations are allowed to override it. */
|
|
44
|
+
export declare const DEFAULT_TIMEOUT_MS = 120000;
|
|
45
|
+
/** The typed client the tools call. */
|
|
46
|
+
export declare class Bridge {
|
|
47
|
+
private readonly transport;
|
|
48
|
+
private readonly timeoutMs;
|
|
49
|
+
/**
|
|
50
|
+
* @param transport - Process boundary that speaks to the PowerShell bridge.
|
|
51
|
+
* @param timeoutMs - Default operation budget.
|
|
52
|
+
*/
|
|
53
|
+
constructor(transport: BridgeTransport, timeoutMs?: number);
|
|
54
|
+
/**
|
|
55
|
+
* Run one bridge operation.
|
|
56
|
+
*
|
|
57
|
+
* @param operation - Operation name.
|
|
58
|
+
* @param args - Operation arguments.
|
|
59
|
+
* @param timeoutMs - Operation budget; defaults to the client budget.
|
|
60
|
+
* @param signal - Cancellation owned by the caller.
|
|
61
|
+
* @returns The operation result.
|
|
62
|
+
* @throws MwiError when the operation fails or the bridge refuses it.
|
|
63
|
+
*/
|
|
64
|
+
run(operation: string, args?: Readonly<Record<string, unknown>>, timeoutMs?: number, signal?: AbortSignal): Promise<unknown>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Refuse on a host that cannot run the MotionWorks IDE.
|
|
68
|
+
*
|
|
69
|
+
* @param platform - Host platform; defaults to the running process.
|
|
70
|
+
*/
|
|
71
|
+
export declare function assertSupportedPlatform(platform?: NodeJS.Platform): void;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The typed boundary to the 32-bit COM bridge.
|
|
3
|
+
*
|
|
4
|
+
* The bridge is implementation: it owns the PowerShell process and the vendor
|
|
5
|
+
* automation components, while the tools speak this request/response contract.
|
|
6
|
+
* Phase 0 defines the contract; the PowerShell transport lands with the session
|
|
7
|
+
* row.
|
|
8
|
+
*
|
|
9
|
+
* @module dsh-engineering-mwi/core/bridge
|
|
10
|
+
*/
|
|
11
|
+
import { MwiError } from "./errors.js";
|
|
12
|
+
/** Default operation budget; IDE compile operations are allowed to override it. */
|
|
13
|
+
export const DEFAULT_TIMEOUT_MS = 120_000;
|
|
14
|
+
/** The typed client the tools call. */
|
|
15
|
+
export class Bridge {
|
|
16
|
+
transport;
|
|
17
|
+
timeoutMs;
|
|
18
|
+
/**
|
|
19
|
+
* @param transport - Process boundary that speaks to the PowerShell bridge.
|
|
20
|
+
* @param timeoutMs - Default operation budget.
|
|
21
|
+
*/
|
|
22
|
+
constructor(transport, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
23
|
+
this.transport = transport;
|
|
24
|
+
this.timeoutMs = timeoutMs;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Run one bridge operation.
|
|
28
|
+
*
|
|
29
|
+
* @param operation - Operation name.
|
|
30
|
+
* @param args - Operation arguments.
|
|
31
|
+
* @param timeoutMs - Operation budget; defaults to the client budget.
|
|
32
|
+
* @param signal - Cancellation owned by the caller.
|
|
33
|
+
* @returns The operation result.
|
|
34
|
+
* @throws MwiError when the operation fails or the bridge refuses it.
|
|
35
|
+
*/
|
|
36
|
+
async run(operation, args = {}, timeoutMs = this.timeoutMs, signal) {
|
|
37
|
+
const response = await this.transport.send({ operation, arguments: args }, timeoutMs, signal);
|
|
38
|
+
if (!response.ok) {
|
|
39
|
+
throw new MwiError(response.error?.code ?? 'BRIDGE_FAILED', response.error?.message ?? `The MotionWorks bridge refused ${operation}.`, 'Call mw_ide_status, resolve any modal dialog, then retry. If it repeats, restart the IDE and the bridge.');
|
|
40
|
+
}
|
|
41
|
+
return response.result;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Refuse on a host that cannot run the MotionWorks IDE.
|
|
46
|
+
*
|
|
47
|
+
* @param platform - Host platform; defaults to the running process.
|
|
48
|
+
*/
|
|
49
|
+
export function assertSupportedPlatform(platform = process.platform) {
|
|
50
|
+
if (platform !== 'win32') {
|
|
51
|
+
throw new MwiError('PLATFORM_UNSUPPORTED', `MotionWorks IEC 3 Pro is a Windows application; this host is ${platform}.`, 'Enable the MotionWorks rows only on a Windows host with the IDE installed.');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Python code engine.
|
|
3
|
+
*
|
|
4
|
+
* The engine owns the saved-project work the COM bridge does not: binding a
|
|
5
|
+
* staged `.mwt` wrapper to its new directory, reading saved declarations and
|
|
6
|
+
* validating native containers. It is stdlib-only and speaks a file protocol:
|
|
7
|
+
* one request JSON in, one response JSON out.
|
|
8
|
+
*
|
|
9
|
+
* @module dsh-engineering-mwi/core/code-engine
|
|
10
|
+
*/
|
|
11
|
+
/** Where the engine lives and which workspace it serves. */
|
|
12
|
+
export interface CodeEngineOptions {
|
|
13
|
+
/** Absolute workspace root. */
|
|
14
|
+
readonly workspace: string;
|
|
15
|
+
/** The only stage root the engine accepts. */
|
|
16
|
+
readonly stageRoot: string;
|
|
17
|
+
/** Directory holding `mw_code.py` and `engine/`; defaults to the package's `code/`. */
|
|
18
|
+
readonly codeDir: string;
|
|
19
|
+
/** Python interpreter; defaults to MW_PYTHON, the Arya interpreter, then `python`. */
|
|
20
|
+
readonly python?: string;
|
|
21
|
+
}
|
|
22
|
+
/** One engine response after a successful call. */
|
|
23
|
+
export type EngineResult = Readonly<Record<string, unknown>>;
|
|
24
|
+
/** Resolve the first usable Python 3 interpreter. */
|
|
25
|
+
export declare function findPython(): string;
|
|
26
|
+
/** The typed engine client. */
|
|
27
|
+
export declare class CodeEngine {
|
|
28
|
+
private readonly options;
|
|
29
|
+
private readonly python;
|
|
30
|
+
/**
|
|
31
|
+
* @param options - Engine location and workspace authorization.
|
|
32
|
+
*/
|
|
33
|
+
constructor(options: CodeEngineOptions);
|
|
34
|
+
/**
|
|
35
|
+
* Run one engine verb.
|
|
36
|
+
*
|
|
37
|
+
* @param verb - Engine verb, for example `bind_mwt`.
|
|
38
|
+
* @param request - Verb arguments.
|
|
39
|
+
* @param timeoutMs - Hard budget; the engine writes a response file.
|
|
40
|
+
* @param signal - Cancellation owned by the caller.
|
|
41
|
+
* @returns The response body after `ok`.
|
|
42
|
+
* @throws MwiError when the engine refuses or is unavailable.
|
|
43
|
+
*/
|
|
44
|
+
run(verb: string, request: Readonly<Record<string, unknown>>, timeoutMs?: number, signal?: AbortSignal): Promise<EngineResult>;
|
|
45
|
+
/** Read the response file, tolerating a partial write. */
|
|
46
|
+
private readResponse;
|
|
47
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Python code engine.
|
|
3
|
+
*
|
|
4
|
+
* The engine owns the saved-project work the COM bridge does not: binding a
|
|
5
|
+
* staged `.mwt` wrapper to its new directory, reading saved declarations and
|
|
6
|
+
* validating native containers. It is stdlib-only and speaks a file protocol:
|
|
7
|
+
* one request JSON in, one response JSON out.
|
|
8
|
+
*
|
|
9
|
+
* @module dsh-engineering-mwi/core/code-engine
|
|
10
|
+
*/
|
|
11
|
+
import { spawn } from 'node:child_process';
|
|
12
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
13
|
+
import { tmpdir } from 'node:os';
|
|
14
|
+
import { join } from 'node:path';
|
|
15
|
+
import { MwiError } from "./errors.js";
|
|
16
|
+
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
17
|
+
/** Resolve the first usable Python 3 interpreter. */
|
|
18
|
+
export function findPython() {
|
|
19
|
+
if (process.env.MW_PYTHON)
|
|
20
|
+
return process.env.MW_PYTHON;
|
|
21
|
+
const candidates = [
|
|
22
|
+
join(process.env.LOCALAPPDATA ?? '', 'Programs', 'AryaCode', 'resources', 'runtime', 'primary-runtime', 'dependencies', 'python', 'python.exe'),
|
|
23
|
+
join(process.env.USERPROFILE ?? '', '.cache', 'codex-runtimes', 'codex-primary-runtime', 'dependencies', 'python', 'python.exe'),
|
|
24
|
+
];
|
|
25
|
+
for (const candidate of candidates) {
|
|
26
|
+
if (candidate.length > 0 && existsSync(candidate))
|
|
27
|
+
return candidate;
|
|
28
|
+
}
|
|
29
|
+
return 'python';
|
|
30
|
+
}
|
|
31
|
+
/** The typed engine client. */
|
|
32
|
+
export class CodeEngine {
|
|
33
|
+
options;
|
|
34
|
+
python;
|
|
35
|
+
/**
|
|
36
|
+
* @param options - Engine location and workspace authorization.
|
|
37
|
+
*/
|
|
38
|
+
constructor(options) {
|
|
39
|
+
this.options = options;
|
|
40
|
+
this.python = options.python ?? findPython();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Run one engine verb.
|
|
44
|
+
*
|
|
45
|
+
* @param verb - Engine verb, for example `bind_mwt`.
|
|
46
|
+
* @param request - Verb arguments.
|
|
47
|
+
* @param timeoutMs - Hard budget; the engine writes a response file.
|
|
48
|
+
* @param signal - Cancellation owned by the caller.
|
|
49
|
+
* @returns The response body after `ok`.
|
|
50
|
+
* @throws MwiError when the engine refuses or is unavailable.
|
|
51
|
+
*/
|
|
52
|
+
async run(verb, request, timeoutMs = 180_000, signal) {
|
|
53
|
+
const helper = join(this.options.codeDir, 'mw_code.py');
|
|
54
|
+
if (!existsSync(helper)) {
|
|
55
|
+
throw new MwiError('ENGINE_MISSING', `The MotionWorks code engine is missing at ${helper}.`, 'Reinstall the bundle; the package ships code/mw_code.py.');
|
|
56
|
+
}
|
|
57
|
+
const ipc = mkdtempSync(join(tmpdir(), 'mwi-engine-'));
|
|
58
|
+
const requestPath = join(ipc, 'req.json');
|
|
59
|
+
const responsePath = join(ipc, 'res.json');
|
|
60
|
+
try {
|
|
61
|
+
writeFileSync(requestPath, JSON.stringify(request), 'utf8');
|
|
62
|
+
const child = spawn(this.python, [helper, verb, requestPath, responsePath], {
|
|
63
|
+
windowsHide: true,
|
|
64
|
+
stdio: 'ignore',
|
|
65
|
+
env: {
|
|
66
|
+
...process.env,
|
|
67
|
+
MW_SRC: join(this.options.codeDir, 'engine'),
|
|
68
|
+
PYTHONIOENCODING: 'utf-8',
|
|
69
|
+
MOTIONWORKS_MCP_BACKUP_DIR: join(this.options.workspace, '.motionworks', 'backups'),
|
|
70
|
+
MOTIONWORKS_MCP_ROOT: this.options.stageRoot,
|
|
71
|
+
MOTIONWORKS_MCP_CLOSE_IDE: '0',
|
|
72
|
+
MOTIONWORKS_MCP_WORKSPACE: this.options.workspace,
|
|
73
|
+
MOTIONWORKS_MCP_STAGE: this.options.stageRoot,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
const failure = new Promise((_resolve, reject) => {
|
|
77
|
+
child.once('error', error => reject(new MwiError('PYTHON_UNAVAILABLE', `Cannot start the MotionWorks code engine with ${this.python}: ${error.message}`, 'Set MW_PYTHON to a Python 3 interpreter, then retry.')));
|
|
78
|
+
});
|
|
79
|
+
const deadline = Date.now() + timeoutMs;
|
|
80
|
+
while (Date.now() < deadline) {
|
|
81
|
+
if (signal?.aborted === true)
|
|
82
|
+
throw new MwiError('ABORTED', 'The MotionWorks engine call was cancelled.', 'Retry when the IDE is idle.');
|
|
83
|
+
if (existsSync(responsePath)) {
|
|
84
|
+
const payload = await this.readResponse(responsePath);
|
|
85
|
+
if (payload.ok === false) {
|
|
86
|
+
throw new MwiError('ENGINE_REFUSED', typeof payload.error === 'string' ? payload.error : `The MotionWorks engine refused ${verb}.`, 'Read the message, correct the request, and retry. Do not retry the same invalid request.');
|
|
87
|
+
}
|
|
88
|
+
return payload;
|
|
89
|
+
}
|
|
90
|
+
await Promise.race([sleep(120), failure]);
|
|
91
|
+
}
|
|
92
|
+
throw new MwiError('ENGINE_TIMEOUT', `The MotionWorks code engine did not answer ${verb} within ${Math.round(timeoutMs / 1000)} s.`, 'Inspect the project files and retry; a locked or malformed project fails here.');
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
rmSync(ipc, { recursive: true, force: true });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/** Read the response file, tolerating a partial write. */
|
|
99
|
+
async readResponse(path) {
|
|
100
|
+
try {
|
|
101
|
+
const parsed = JSON.parse(readFileSync(path, 'utf8'));
|
|
102
|
+
return parsed;
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
await sleep(50);
|
|
106
|
+
return {};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Failures the model can repair from.
|
|
3
|
+
*
|
|
4
|
+
* Every expected failure carries the next call. An unexpected failure is a
|
|
5
|
+
* plugin defect and says so instead of pretending to be a project condition.
|
|
6
|
+
*
|
|
7
|
+
* @module dsh-engineering-mwi/core/errors
|
|
8
|
+
*/
|
|
9
|
+
/** One expected failure, with everything the reader needs to recover. */
|
|
10
|
+
export declare class MwiError extends Error {
|
|
11
|
+
readonly code: string;
|
|
12
|
+
readonly fix: string;
|
|
13
|
+
readonly candidates: readonly string[];
|
|
14
|
+
/**
|
|
15
|
+
* @param code - Stable identifier for tests and logs.
|
|
16
|
+
* @param message - What failed, in the reader's terms.
|
|
17
|
+
* @param fix - The exact next call or check.
|
|
18
|
+
* @param candidates - Valid names when the request named something absent or ambiguous.
|
|
19
|
+
*/
|
|
20
|
+
constructor(code: string, message: string, fix: string, candidates?: readonly string[]);
|
|
21
|
+
}
|
|
22
|
+
/** The model-facing failure document. */
|
|
23
|
+
export interface ErrorEnvelope {
|
|
24
|
+
readonly error: {
|
|
25
|
+
readonly code: string;
|
|
26
|
+
readonly message: string;
|
|
27
|
+
readonly fix: string;
|
|
28
|
+
readonly candidates: readonly string[];
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Convert a thrown value into the failure document.
|
|
33
|
+
*
|
|
34
|
+
* @param error - Whatever the tool body threw.
|
|
35
|
+
* @returns The failure document; never throws.
|
|
36
|
+
*/
|
|
37
|
+
export declare function errorEnvelope(error: unknown): ErrorEnvelope;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Failures the model can repair from.
|
|
3
|
+
*
|
|
4
|
+
* Every expected failure carries the next call. An unexpected failure is a
|
|
5
|
+
* plugin defect and says so instead of pretending to be a project condition.
|
|
6
|
+
*
|
|
7
|
+
* @module dsh-engineering-mwi/core/errors
|
|
8
|
+
*/
|
|
9
|
+
/** One expected failure, with everything the reader needs to recover. */
|
|
10
|
+
export class MwiError extends Error {
|
|
11
|
+
code;
|
|
12
|
+
fix;
|
|
13
|
+
candidates;
|
|
14
|
+
/**
|
|
15
|
+
* @param code - Stable identifier for tests and logs.
|
|
16
|
+
* @param message - What failed, in the reader's terms.
|
|
17
|
+
* @param fix - The exact next call or check.
|
|
18
|
+
* @param candidates - Valid names when the request named something absent or ambiguous.
|
|
19
|
+
*/
|
|
20
|
+
constructor(code, message, fix, candidates = []) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.code = code;
|
|
23
|
+
this.fix = fix;
|
|
24
|
+
this.candidates = candidates;
|
|
25
|
+
this.name = 'MwiError';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Convert a thrown value into the failure document.
|
|
30
|
+
*
|
|
31
|
+
* @param error - Whatever the tool body threw.
|
|
32
|
+
* @returns The failure document; never throws.
|
|
33
|
+
*/
|
|
34
|
+
export function errorEnvelope(error) {
|
|
35
|
+
if (error instanceof MwiError) {
|
|
36
|
+
return { error: { code: error.code, message: error.message, fix: error.fix, candidates: error.candidates } };
|
|
37
|
+
}
|
|
38
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
39
|
+
return {
|
|
40
|
+
error: {
|
|
41
|
+
code: 'INTERNAL',
|
|
42
|
+
message,
|
|
43
|
+
fix: 'This is a plugin defect, not a project condition. Report it with the arguments used, then retry.',
|
|
44
|
+
candidates: [],
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameter schemas that always describe themselves.
|
|
3
|
+
*
|
|
4
|
+
* MWI's legacy surface had inconsistent parameter descriptions; these helpers
|
|
5
|
+
* make an undescribed parameter impossible to write, as in the other products.
|
|
6
|
+
*
|
|
7
|
+
* @module dsh-engineering-mwi/core/params
|
|
8
|
+
*/
|
|
9
|
+
/** One JSON Schema property, with the description that is mandatory here. */
|
|
10
|
+
export interface ParameterSchema {
|
|
11
|
+
readonly type: 'string' | 'integer' | 'number' | 'boolean' | 'array' | 'object';
|
|
12
|
+
readonly description: string;
|
|
13
|
+
readonly enum?: readonly string[];
|
|
14
|
+
readonly items?: ParameterSchema;
|
|
15
|
+
readonly default?: unknown;
|
|
16
|
+
readonly minimum?: number;
|
|
17
|
+
readonly maximum?: number;
|
|
18
|
+
readonly minItems?: number;
|
|
19
|
+
readonly maxItems?: number;
|
|
20
|
+
readonly properties?: Readonly<Record<string, ParameterSchema>>;
|
|
21
|
+
readonly required?: readonly string[];
|
|
22
|
+
readonly additionalProperties?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/** A string parameter. */
|
|
25
|
+
export declare function string(description: string, extra?: Partial<ParameterSchema>): ParameterSchema;
|
|
26
|
+
/** An integer parameter with an optional range. */
|
|
27
|
+
export declare function integer(description: string, extra?: Partial<ParameterSchema>): ParameterSchema;
|
|
28
|
+
/** A boolean parameter. */
|
|
29
|
+
export declare function boolean(description: string, extra?: Partial<ParameterSchema>): ParameterSchema;
|
|
30
|
+
/** A string parameter restricted to a known set. */
|
|
31
|
+
export declare function choice(description: string, values: readonly string[], extra?: Partial<ParameterSchema>): ParameterSchema;
|
|
32
|
+
/** An array of one parameter type. */
|
|
33
|
+
export declare function list(description: string, items: ParameterSchema, extra?: Partial<ParameterSchema>): ParameterSchema;
|
|
34
|
+
/** A fixed-property object parameter. */
|
|
35
|
+
export declare function record(description: string, properties: Readonly<Record<string, ParameterSchema>>, required?: readonly string[]): ParameterSchema;
|
|
36
|
+
/** One object element of an array parameter. */
|
|
37
|
+
export declare function objectItem(description: string, properties: Readonly<Record<string, ParameterSchema>>, required?: readonly string[]): ParameterSchema;
|
|
38
|
+
/** The `parameters` object of one tool. */
|
|
39
|
+
export interface Parameters {
|
|
40
|
+
readonly type: 'object';
|
|
41
|
+
readonly properties: Readonly<Record<string, ParameterSchema>>;
|
|
42
|
+
readonly required: readonly string[];
|
|
43
|
+
readonly additionalProperties: false;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Build a tool's parameter object.
|
|
47
|
+
*
|
|
48
|
+
* @param properties - Named parameters, each carrying its description.
|
|
49
|
+
* @param required - Names the caller must pass.
|
|
50
|
+
* @returns The open-object parameter schema.
|
|
51
|
+
*/
|
|
52
|
+
export declare function object(properties: Readonly<Record<string, ParameterSchema>>, required?: readonly string[]): Parameters;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameter schemas that always describe themselves.
|
|
3
|
+
*
|
|
4
|
+
* MWI's legacy surface had inconsistent parameter descriptions; these helpers
|
|
5
|
+
* make an undescribed parameter impossible to write, as in the other products.
|
|
6
|
+
*
|
|
7
|
+
* @module dsh-engineering-mwi/core/params
|
|
8
|
+
*/
|
|
9
|
+
/** A string parameter. */
|
|
10
|
+
export function string(description, extra = {}) {
|
|
11
|
+
return { type: 'string', description, ...extra };
|
|
12
|
+
}
|
|
13
|
+
/** An integer parameter with an optional range. */
|
|
14
|
+
export function integer(description, extra = {}) {
|
|
15
|
+
return { type: 'integer', description, ...extra };
|
|
16
|
+
}
|
|
17
|
+
/** A boolean parameter. */
|
|
18
|
+
export function boolean(description, extra = {}) {
|
|
19
|
+
return { type: 'boolean', description, ...extra };
|
|
20
|
+
}
|
|
21
|
+
/** A string parameter restricted to a known set. */
|
|
22
|
+
export function choice(description, values, extra = {}) {
|
|
23
|
+
return { type: 'string', description, enum: values, ...extra };
|
|
24
|
+
}
|
|
25
|
+
/** An array of one parameter type. */
|
|
26
|
+
export function list(description, items, extra = {}) {
|
|
27
|
+
return { type: 'array', description, items, ...extra };
|
|
28
|
+
}
|
|
29
|
+
/** A fixed-property object parameter. */
|
|
30
|
+
export function record(description, properties, required = []) {
|
|
31
|
+
return { type: 'object', description, properties, required, additionalProperties: false };
|
|
32
|
+
}
|
|
33
|
+
/** One object element of an array parameter. */
|
|
34
|
+
export function objectItem(description, properties, required = []) {
|
|
35
|
+
return { type: 'object', description, properties, required, additionalProperties: false };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Build a tool's parameter object.
|
|
39
|
+
*
|
|
40
|
+
* @param properties - Named parameters, each carrying its description.
|
|
41
|
+
* @param required - Names the caller must pass.
|
|
42
|
+
* @returns The open-object parameter schema.
|
|
43
|
+
*/
|
|
44
|
+
export function object(properties, required = []) {
|
|
45
|
+
return { type: 'object', properties, required, additionalProperties: false };
|
|
46
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The PowerShell transport for the MotionWorks COM bridge.
|
|
3
|
+
*
|
|
4
|
+
* The bridge is a 32-bit PowerShell process that polls a request file and writes
|
|
5
|
+
* one response file. Files, not stdio: a confined harness cannot open named
|
|
6
|
+
* pipes, and `Mwt.exe` is a 32-bit LocalServer32 that a 64-bit client cannot
|
|
7
|
+
* instantiate at all.
|
|
8
|
+
*
|
|
9
|
+
* This client owns the mailbox, serializes requests, starts the bridge once and
|
|
10
|
+
* maps the bridge's answer onto the typed bridge contract.
|
|
11
|
+
*
|
|
12
|
+
* @module dsh-engineering-mwi/core/ps-bridge
|
|
13
|
+
*/
|
|
14
|
+
import type { BridgeRequest, BridgeResponse, BridgeTransport } from './bridge.ts';
|
|
15
|
+
/** Where the bridge lives and which workspace it may act on. */
|
|
16
|
+
export interface PowerShellBridgeOptions {
|
|
17
|
+
/** Directory containing `start_bridge.cmd` and `mw_bridge.ps1`. */
|
|
18
|
+
readonly bridgeDir: string;
|
|
19
|
+
/** Absolute workspace the bridge may touch. */
|
|
20
|
+
readonly workspace: string;
|
|
21
|
+
/** The only stage root the bridge accepts: `<workspace>/.motionworks/stage`. */
|
|
22
|
+
readonly stageRoot: string;
|
|
23
|
+
/** Mailbox directory; defaults to a private temp directory. */
|
|
24
|
+
readonly ipcDir?: string;
|
|
25
|
+
/** Startup budget before the bridge must answer. Defaults to 12 s. */
|
|
26
|
+
readonly startupMs?: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A serialized client over the file mailbox, matching the legacy bridge protocol.
|
|
30
|
+
*/
|
|
31
|
+
export declare class PowerShellBridgeTransport implements BridgeTransport {
|
|
32
|
+
private readonly options;
|
|
33
|
+
private readonly ipcDir;
|
|
34
|
+
private readonly requestPath;
|
|
35
|
+
private readonly responsePath;
|
|
36
|
+
private readonly startupMs;
|
|
37
|
+
private spawned;
|
|
38
|
+
private queue;
|
|
39
|
+
/**
|
|
40
|
+
* @param options - Bridge location and workspace authorization.
|
|
41
|
+
*/
|
|
42
|
+
constructor(options: PowerShellBridgeOptions);
|
|
43
|
+
/** The mailbox this client owns; exposed for diagnostics. */
|
|
44
|
+
get mailbox(): string;
|
|
45
|
+
/**
|
|
46
|
+
* Send one request and wait for its response.
|
|
47
|
+
*
|
|
48
|
+
* @param request - Operation and arguments.
|
|
49
|
+
* @param timeoutMs - Hard operation budget.
|
|
50
|
+
* @param signal - Cancellation owned by the caller.
|
|
51
|
+
* @returns The bridge's answer.
|
|
52
|
+
*/
|
|
53
|
+
send(request: BridgeRequest, timeoutMs: number, signal?: AbortSignal): Promise<BridgeResponse>;
|
|
54
|
+
/** Run one request after the previous one settled. */
|
|
55
|
+
private exchange;
|
|
56
|
+
/** Read the current response file, ignoring partial or malformed writes. */
|
|
57
|
+
private readResponse;
|
|
58
|
+
/** Map a bridge refusal to a stable code the model can act on. */
|
|
59
|
+
private codeOf;
|
|
60
|
+
/** Start the 32-bit bridge once per client. */
|
|
61
|
+
private spawnBridge;
|
|
62
|
+
}
|