@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,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Staging: copy one workspace project into `.motionworks/stage` and bind its wrapper.
|
|
3
|
+
*
|
|
4
|
+
* The source is never modified. A stage is refused when it already exists unless
|
|
5
|
+
* the caller explicitly replaces it after review; the previous stage is moved to
|
|
6
|
+
* `backups/stage-<id>` rather than discarded.
|
|
7
|
+
*
|
|
8
|
+
* @module dsh-engineering-mwi/session/stage
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, mkdirSync, readdirSync, renameSync, rmSync, statSync, copyFileSync, lstatSync, writeFileSync, readFileSync } from 'node:fs';
|
|
11
|
+
import { randomUUID } from 'node:crypto';
|
|
12
|
+
import { basename, join, resolve, sep } from 'node:path';
|
|
13
|
+
import { MwiError } from "../core/errors.js";
|
|
14
|
+
import { isInside, stageRootOf } from "./workspace.js";
|
|
15
|
+
/** Identity suffix, matching the legacy stage record. */
|
|
16
|
+
export const IDENTITY_SUFFIX = '.identity.json';
|
|
17
|
+
/** Count and copy one directory tree, refusing links. */
|
|
18
|
+
function copyTree(from, to, count) {
|
|
19
|
+
mkdirSync(to, { recursive: true });
|
|
20
|
+
for (const entry of readdirSync(from, { withFileTypes: true })) {
|
|
21
|
+
const source = join(from, entry.name);
|
|
22
|
+
const destination = join(to, entry.name);
|
|
23
|
+
if (entry.isSymbolicLink())
|
|
24
|
+
throw new MwiError('LINKED_PROJECT', `The project contains a link: ${source}.`, 'Stage a project whose files are all local; links are refused.');
|
|
25
|
+
if (entry.isDirectory()) {
|
|
26
|
+
copyTree(source, destination, count);
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
copyFileSync(source, destination);
|
|
30
|
+
count.files += 1;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Copy one file and count it. */
|
|
34
|
+
function copyFile(from, to, count) {
|
|
35
|
+
copyFileSync(from, to);
|
|
36
|
+
count.files += 1;
|
|
37
|
+
}
|
|
38
|
+
/** The service that stages projects for one workspace. */
|
|
39
|
+
export class StageService {
|
|
40
|
+
engine;
|
|
41
|
+
workspace;
|
|
42
|
+
/**
|
|
43
|
+
* @param engine - Code engine that binds the wrapper.
|
|
44
|
+
* @param workspace - Absolute workspace root.
|
|
45
|
+
*/
|
|
46
|
+
constructor(engine, workspace) {
|
|
47
|
+
this.engine = engine;
|
|
48
|
+
this.workspace = workspace;
|
|
49
|
+
}
|
|
50
|
+
/** The stage root of this workspace. */
|
|
51
|
+
get stageRoot() {
|
|
52
|
+
return stageRootOf(this.workspace);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Stage one project.
|
|
56
|
+
*
|
|
57
|
+
* @param sourceArg - `.mwt` or project directory inside the workspace.
|
|
58
|
+
* @param options - Replacement and closed-project checks.
|
|
59
|
+
* @returns The written stage record.
|
|
60
|
+
*/
|
|
61
|
+
async stage(sourceArg, options = {}) {
|
|
62
|
+
const asked = resolve(this.workspace, sourceArg);
|
|
63
|
+
if (!isInside(this.workspace, asked)) {
|
|
64
|
+
throw new MwiError('OUTSIDE_WORKSPACE', `${asked} is outside the workspace ${this.workspace}.`, 'Call mw_project_find and stage a project from the workspace; outside projects are never opened.');
|
|
65
|
+
}
|
|
66
|
+
const isMwt = asked.toLowerCase().endsWith('.mwt');
|
|
67
|
+
const mwt = isMwt ? asked : `${asked}.mwt`;
|
|
68
|
+
const directory = isMwt ? asked.slice(0, -4) : asked;
|
|
69
|
+
if (!existsSync(mwt))
|
|
70
|
+
throw new MwiError('PROJECT_NOT_FOUND', `No .mwt exists at ${mwt}.`, 'Pass the project folder or its .mwt, both inside the workspace.');
|
|
71
|
+
if (!existsSync(directory) || !statSync(directory).isDirectory()) {
|
|
72
|
+
throw new MwiError('PROJECT_INCOMPLETE', `${mwt} has no expanded project directory beside it.`, 'Stage a complete project: the .mwt and its sibling folder.');
|
|
73
|
+
}
|
|
74
|
+
if (isInside(this.stageRoot, mwt) || isInside(this.stageRoot, directory)) {
|
|
75
|
+
throw new MwiError('ALREADY_STAGED', `${mwt} is already inside the stage.`, 'Stage the original workspace project, not an existing staged copy.');
|
|
76
|
+
}
|
|
77
|
+
const name = basename(mwt, '.mwt');
|
|
78
|
+
const targetMwt = join(this.stageRoot, `${name}.mwt`);
|
|
79
|
+
const targetDir = join(this.stageRoot, name);
|
|
80
|
+
const identity = join(this.stageRoot, `${name}${IDENTITY_SUFFIX}`);
|
|
81
|
+
const previous = [targetMwt, targetDir, identity].filter(path => existsSync(path));
|
|
82
|
+
if (previous.length > 0 && options.replace !== true) {
|
|
83
|
+
throw new MwiError('STAGE_EXISTS', `A staged copy named ${name} already exists.`, 'Continue the existing stage, or pass replace_existing:true after reviewing it; the previous stage is retained under backups/.');
|
|
84
|
+
}
|
|
85
|
+
if (existsSync(targetDir)) {
|
|
86
|
+
for (const entry of readdirSync(targetDir)) {
|
|
87
|
+
if (lstatSync(join(targetDir, entry)).isSymbolicLink()) {
|
|
88
|
+
throw new MwiError('LINKED_STAGE', 'The existing stage contains a link.', 'Remove the stage only after review; links are refused.');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
await options.assertClosed?.();
|
|
93
|
+
mkdirSync(this.stageRoot, { recursive: true });
|
|
94
|
+
const pending = join(this.stageRoot, `.pending-${randomUUID()}`);
|
|
95
|
+
mkdirSync(pending);
|
|
96
|
+
const count = { files: 0 };
|
|
97
|
+
let backup = null;
|
|
98
|
+
try {
|
|
99
|
+
const incomingMwt = join(pending, `${name}.mwt`);
|
|
100
|
+
const incomingDir = join(pending, name);
|
|
101
|
+
copyFile(mwt, incomingMwt, count);
|
|
102
|
+
copyTree(directory, incomingDir, count);
|
|
103
|
+
const bound = await this.engine.run('bind_mwt', { mwt: incomingMwt, directory: targetDir });
|
|
104
|
+
const record = {
|
|
105
|
+
name,
|
|
106
|
+
source: mwt,
|
|
107
|
+
source_directory: directory,
|
|
108
|
+
workspace: this.workspace,
|
|
109
|
+
staged_mwt: targetMwt,
|
|
110
|
+
staged_directory: targetDir,
|
|
111
|
+
bound_to: bound.bound_to ?? targetDir,
|
|
112
|
+
previous_embedded_path: bound.paths?.[0]?.from ?? null,
|
|
113
|
+
staged_at: new Date().toISOString(),
|
|
114
|
+
};
|
|
115
|
+
if (previous.length > 0) {
|
|
116
|
+
backup = join(this.stageRoot, 'backups', `stage-${randomUUID()}`);
|
|
117
|
+
mkdirSync(backup, { recursive: true });
|
|
118
|
+
for (const path of previous)
|
|
119
|
+
renameSync(path, join(backup, basename(path)));
|
|
120
|
+
}
|
|
121
|
+
renameSync(incomingMwt, targetMwt);
|
|
122
|
+
renameSync(incomingDir, targetDir);
|
|
123
|
+
writeFileSync(identity, JSON.stringify(record, null, 2));
|
|
124
|
+
rmSync(pending, { recursive: true, force: true });
|
|
125
|
+
return record;
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
rmSync(pending, { recursive: true, force: true });
|
|
129
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
130
|
+
throw new MwiError('STAGE_FAILED', message, backup === null
|
|
131
|
+
? 'Nothing was written to the stage. Correct the project and retry.'
|
|
132
|
+
: `The previous stage is retained at ${backup}; inspect it before retrying.`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Read one identity record.
|
|
137
|
+
*
|
|
138
|
+
* @param name - Project name.
|
|
139
|
+
* @returns The record, or undefined when the name was not staged.
|
|
140
|
+
*/
|
|
141
|
+
identityOf(name) {
|
|
142
|
+
try {
|
|
143
|
+
return JSON.parse(readFileSync(join(this.stageRoot, `${name}${IDENTITY_SUFFIX}`), 'utf8'));
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The staged project whose `.mwt` or directory is `path`.
|
|
151
|
+
*
|
|
152
|
+
* @param path - Active or requested project path.
|
|
153
|
+
* @returns Its identity record, or undefined.
|
|
154
|
+
*/
|
|
155
|
+
stagedAt(path) {
|
|
156
|
+
const target = resolve(path).toLowerCase().replace(/\.mwt$/u, '');
|
|
157
|
+
let names = [];
|
|
158
|
+
try {
|
|
159
|
+
names = readdirSync(this.stageRoot).filter(name => name.endsWith(IDENTITY_SUFFIX));
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
for (const file of names) {
|
|
165
|
+
const record = this.identityOf(file.slice(0, -IDENTITY_SUFFIX.length));
|
|
166
|
+
if (record === undefined)
|
|
167
|
+
continue;
|
|
168
|
+
if (resolve(record.staged_directory).toLowerCase() === target)
|
|
169
|
+
return record;
|
|
170
|
+
}
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Refuse when the active IDE project is this stage.
|
|
175
|
+
*
|
|
176
|
+
* @param targetDir - Stage directory about to be replaced.
|
|
177
|
+
* @param status - Bridge status document.
|
|
178
|
+
*/
|
|
179
|
+
static assertClosed(targetDir, status) {
|
|
180
|
+
if (status.is_project_open !== true || typeof status.active_project !== 'string')
|
|
181
|
+
return;
|
|
182
|
+
const active = resolve(status.active_project).toLowerCase().replace(/\.mwt$/u, '');
|
|
183
|
+
if (active === resolve(targetDir).toLowerCase() || active.startsWith(resolve(targetDir).toLowerCase() + sep)) {
|
|
184
|
+
throw new MwiError('STAGE_OPEN', `The staged project is open in the IDE: ${status.active_project}.`, 'Save or close the open project with consent before replacing its stage.');
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace and stage paths.
|
|
3
|
+
*
|
|
4
|
+
* MotionWorks work happens on a project inside the calling workspace. The stage
|
|
5
|
+
* is the one writable location: `<workspace>/.motionworks/stage`.
|
|
6
|
+
*
|
|
7
|
+
* @module dsh-engineering-mwi/session/workspace
|
|
8
|
+
*/
|
|
9
|
+
/** One MotionWorks project found in the workspace. */
|
|
10
|
+
export interface FoundProject {
|
|
11
|
+
/** Project name: the `.mwt` basename. */
|
|
12
|
+
readonly name: string;
|
|
13
|
+
/** Absolute path of the wrapper. */
|
|
14
|
+
readonly mwt: string;
|
|
15
|
+
/** Absolute path of the expanded project directory. */
|
|
16
|
+
readonly directory: string;
|
|
17
|
+
/** Absolute path of the staged copy, when one exists. */
|
|
18
|
+
readonly staged: string | null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the caller's workspace.
|
|
22
|
+
*
|
|
23
|
+
* @param cwd - Working directory from the tool call.
|
|
24
|
+
* @returns The absolute workspace root.
|
|
25
|
+
*/
|
|
26
|
+
export declare function workspaceOf(cwd: string | undefined): string;
|
|
27
|
+
/**
|
|
28
|
+
* The stage root of one workspace.
|
|
29
|
+
*
|
|
30
|
+
* @param workspace - Absolute workspace root.
|
|
31
|
+
* @returns `<workspace>/.motionworks/stage`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function stageRootOf(workspace: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Whether a path lies inside a directory.
|
|
36
|
+
*
|
|
37
|
+
* @param parent - Directory that must contain the path.
|
|
38
|
+
* @param child - Path to test.
|
|
39
|
+
* @returns True when `child` equals or lies below `parent`.
|
|
40
|
+
*/
|
|
41
|
+
export declare function isInside(parent: string, child: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Find MotionWorks projects under a workspace.
|
|
44
|
+
*
|
|
45
|
+
* @param workspace - Absolute workspace root.
|
|
46
|
+
* @param options - Optional name filter and result cap.
|
|
47
|
+
* @returns Projects in stable path order.
|
|
48
|
+
*/
|
|
49
|
+
export declare function findProjects(workspace: string, options?: {
|
|
50
|
+
filter?: string;
|
|
51
|
+
limit?: number;
|
|
52
|
+
}): FoundProject[];
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace and stage paths.
|
|
3
|
+
*
|
|
4
|
+
* MotionWorks work happens on a project inside the calling workspace. The stage
|
|
5
|
+
* is the one writable location: `<workspace>/.motionworks/stage`.
|
|
6
|
+
*
|
|
7
|
+
* @module dsh-engineering-mwi/session/workspace
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync, readdirSync } from 'node:fs';
|
|
10
|
+
import { join, resolve, sep } from 'node:path';
|
|
11
|
+
/** Directories never scanned for projects. */
|
|
12
|
+
const SKIP = new Set(['node_modules', '.git', 'stage', 'backups', '_backups', '__pycache__', 'chm_out', 'help_extract', '.dsh']);
|
|
13
|
+
/**
|
|
14
|
+
* Resolve the caller's workspace.
|
|
15
|
+
*
|
|
16
|
+
* @param cwd - Working directory from the tool call.
|
|
17
|
+
* @returns The absolute workspace root.
|
|
18
|
+
*/
|
|
19
|
+
export function workspaceOf(cwd) {
|
|
20
|
+
return resolve(cwd ?? process.cwd());
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The stage root of one workspace.
|
|
24
|
+
*
|
|
25
|
+
* @param workspace - Absolute workspace root.
|
|
26
|
+
* @returns `<workspace>/.motionworks/stage`.
|
|
27
|
+
*/
|
|
28
|
+
export function stageRootOf(workspace) {
|
|
29
|
+
return join(workspace, '.motionworks', 'stage');
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Whether a path lies inside a directory.
|
|
33
|
+
*
|
|
34
|
+
* @param parent - Directory that must contain the path.
|
|
35
|
+
* @param child - Path to test.
|
|
36
|
+
* @returns True when `child` equals or lies below `parent`.
|
|
37
|
+
*/
|
|
38
|
+
export function isInside(parent, child) {
|
|
39
|
+
const base = resolve(parent).toLowerCase();
|
|
40
|
+
const target = resolve(child).toLowerCase();
|
|
41
|
+
return target === base || target.startsWith(base + sep);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Find MotionWorks projects under a workspace.
|
|
45
|
+
*
|
|
46
|
+
* @param workspace - Absolute workspace root.
|
|
47
|
+
* @param options - Optional name filter and result cap.
|
|
48
|
+
* @returns Projects in stable path order.
|
|
49
|
+
*/
|
|
50
|
+
export function findProjects(workspace, options = {}) {
|
|
51
|
+
const limit = options.limit ?? 20;
|
|
52
|
+
const filter = options.filter?.toLowerCase();
|
|
53
|
+
const stage = stageRootOf(workspace);
|
|
54
|
+
const found = [];
|
|
55
|
+
const walk = (directory, depth) => {
|
|
56
|
+
if (found.length >= limit || depth > 6)
|
|
57
|
+
return;
|
|
58
|
+
let entries;
|
|
59
|
+
try {
|
|
60
|
+
entries = readdirSync(directory, { withFileTypes: true });
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
66
|
+
if (found.length >= limit)
|
|
67
|
+
return;
|
|
68
|
+
const absolute = join(directory, entry.name);
|
|
69
|
+
if (entry.isDirectory()) {
|
|
70
|
+
if (SKIP.has(entry.name) || isInside(stage, absolute))
|
|
71
|
+
continue;
|
|
72
|
+
walk(absolute, depth + 1);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (!entry.isFile() || !entry.name.toLowerCase().endsWith('.mwt'))
|
|
76
|
+
continue;
|
|
77
|
+
const name = entry.name.slice(0, -4);
|
|
78
|
+
if (filter !== undefined && !name.toLowerCase().includes(filter) && !absolute.toLowerCase().includes(filter))
|
|
79
|
+
continue;
|
|
80
|
+
found.push({
|
|
81
|
+
name,
|
|
82
|
+
mwt: absolute,
|
|
83
|
+
directory: absolute.slice(0, -4),
|
|
84
|
+
staged: existsSync(join(stage, `${name}.mwt`)) ? join(stage, `${name}.mwt`) : null,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
walk(workspace, 0);
|
|
89
|
+
return found;
|
|
90
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The guidance half of the MotionWorks IEC redesign.
|
|
3
|
+
*
|
|
4
|
+
* The tools land in the row entries; this module registers the
|
|
5
|
+
* `motionworks-iec` skill that tells a model how to use them. It is a separate
|
|
6
|
+
* loader entry, so a profile can run the tools without the guidance or the
|
|
7
|
+
* guidance without the tools.
|
|
8
|
+
*
|
|
9
|
+
* @module dsh-engineering-mwi/skill
|
|
10
|
+
*/
|
|
11
|
+
/** Plugin name in a composition. */
|
|
12
|
+
export declare const name = "mwi-skill";
|
|
13
|
+
/** Services this plugin cannot register without. */
|
|
14
|
+
export declare const inject: readonly ["skills"];
|
|
15
|
+
/** The plugin context this module needs. */
|
|
16
|
+
export interface SkillContext {
|
|
17
|
+
get(name: string): unknown;
|
|
18
|
+
logger?: {
|
|
19
|
+
info?(message: string): void;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/** Registration metadata, kept here so a test can assert it without the file. */
|
|
23
|
+
export declare const SKILL: {
|
|
24
|
+
readonly name: "motionworks-iec";
|
|
25
|
+
readonly description: "Operate a running Yaskawa MotionWorks IEC 3 Pro IDE through staged projects — find and stage a workspace project, read the live object model and POU code, edit declarations and code, compile, read diagnostics, and verify a staged change.";
|
|
26
|
+
readonly whenToUse: "The user has MotionWorks IEC 3 Pro open or asks for work in it — a build or compile verdict, the live project model, reading or changing POU code, variable declarations, tasks, or the IDE error list. Also use when a MotionWorks project is mentioned: find which project is in the workspace before answering. For a question about a project outside the workspace, say it cannot be staged.";
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Register the MotionWorks IEC skill.
|
|
30
|
+
*
|
|
31
|
+
* The IDE is a Windows application, so a host elsewhere skips registration
|
|
32
|
+
* instead of offering guidance no tool can follow.
|
|
33
|
+
*
|
|
34
|
+
* @param ctx - Plugin context whose skill registry receives the registration.
|
|
35
|
+
*/
|
|
36
|
+
export declare function apply(ctx: SkillContext): void;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The guidance half of the MotionWorks IEC redesign.
|
|
3
|
+
*
|
|
4
|
+
* The tools land in the row entries; this module registers the
|
|
5
|
+
* `motionworks-iec` skill that tells a model how to use them. It is a separate
|
|
6
|
+
* loader entry, so a profile can run the tools without the guidance or the
|
|
7
|
+
* guidance without the tools.
|
|
8
|
+
*
|
|
9
|
+
* @module dsh-engineering-mwi/skill
|
|
10
|
+
*/
|
|
11
|
+
import { readFileSync } from 'node:fs';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
/** Plugin name in a composition. */
|
|
14
|
+
export const name = 'mwi-skill';
|
|
15
|
+
/** Services this plugin cannot register without. */
|
|
16
|
+
export const inject = ['skills'];
|
|
17
|
+
/** Registration metadata, kept here so a test can assert it without the file. */
|
|
18
|
+
export const SKILL = {
|
|
19
|
+
name: 'motionworks-iec',
|
|
20
|
+
description: 'Operate a running Yaskawa MotionWorks IEC 3 Pro IDE through staged projects — find and stage a workspace project, read the live object model and POU code, edit declarations and code, compile, read diagnostics, and verify a staged change.',
|
|
21
|
+
whenToUse: 'The user has MotionWorks IEC 3 Pro open or asks for work in it — a build or compile verdict, the live project model, reading or changing POU code, variable declarations, tasks, or the IDE error list. Also use when a MotionWorks project is mentioned: find which project is in the workspace before answering. For a question about a project outside the workspace, say it cannot be staged.',
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Register the MotionWorks IEC skill.
|
|
25
|
+
*
|
|
26
|
+
* The IDE is a Windows application, so a host elsewhere skips registration
|
|
27
|
+
* instead of offering guidance no tool can follow.
|
|
28
|
+
*
|
|
29
|
+
* @param ctx - Plugin context whose skill registry receives the registration.
|
|
30
|
+
*/
|
|
31
|
+
export function apply(ctx) {
|
|
32
|
+
if (process.platform !== 'win32') {
|
|
33
|
+
try {
|
|
34
|
+
ctx.logger?.info?.(`mwi-skill: skipped because this host is ${process.platform}; MotionWorks IEC requires Windows.`);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// A logger that refuses must not turn an unsupported host into a crash.
|
|
38
|
+
}
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const skills = ctx.get('skills');
|
|
42
|
+
if (skills === undefined || typeof skills.register !== 'function') {
|
|
43
|
+
throw new Error('mwi-skill: the skills service is unavailable, so the motionworks-iec guidance cannot register');
|
|
44
|
+
}
|
|
45
|
+
const skillPath = fileURLToPath(new URL('../SKILL.md', import.meta.url));
|
|
46
|
+
const raw = readFileSync(skillPath, 'utf8');
|
|
47
|
+
const content = raw.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n/u, '');
|
|
48
|
+
skills.register({
|
|
49
|
+
...SKILL,
|
|
50
|
+
content,
|
|
51
|
+
path: skillPath,
|
|
52
|
+
source: 'custom',
|
|
53
|
+
provider: '@aryacode/dsh-engineering-mwi',
|
|
54
|
+
invocation: { modelInvocable: true, userInvocable: true },
|
|
55
|
+
});
|
|
56
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The edit row: replace code, edit declarations, change structure and apply.
|
|
3
|
+
*
|
|
4
|
+
* Editing is off by default. Every tool writes only the staged project, and the
|
|
5
|
+
* proven native helpers verify that unrelated saved and native state did not
|
|
6
|
+
* change.
|
|
7
|
+
*
|
|
8
|
+
* @module dsh-engineering-mwi/tools/edit
|
|
9
|
+
*/
|
|
10
|
+
import { type ToolDefinition } from '../core/tool.ts';
|
|
11
|
+
import { type SessionRuntime } from '../session/service.ts';
|
|
12
|
+
/** How the tools reach a workspace runtime; injectable for tests. */
|
|
13
|
+
export type EditRuntimeFactory = (workspace: string) => SessionRuntime;
|
|
14
|
+
/**
|
|
15
|
+
* The edit tools.
|
|
16
|
+
*
|
|
17
|
+
* @param runtimeOf - Workspace runtime factory; defaults to the PowerShell bridge.
|
|
18
|
+
* @returns Tool definitions in registration order.
|
|
19
|
+
*/
|
|
20
|
+
export declare function editTools(runtimeOf?: EditRuntimeFactory): readonly ToolDefinition[];
|