@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.
- package/CHANGELOG.md +115 -0
- package/LICENSE +21 -0
- package/README.md +228 -2
- package/cordis.patch.yml +122 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +77 -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,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: factorytalk-view
|
|
3
|
+
description: Design and support FactoryTalk View ME and PanelView Plus applications from documented text exports: displays, HMI tags, structural checks and export comparison.
|
|
4
|
+
whenToUse: Use when the user asks about FactoryTalk View ME, PanelView Plus, ME display exports, HMI tags, or comparing ME exports. Route FactoryTalk View SE and Optix to their own surfaces.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# FactoryTalk View ME engineering
|
|
8
|
+
|
|
9
|
+
## Boundary
|
|
10
|
+
|
|
11
|
+
This surface reads and stages changes to documented text exports: display XML and the HMI tag CSV.
|
|
12
|
+
A staged edit is written to a NEW export folder; the source is never modified. The Studio entry plans
|
|
13
|
+
a manual import for a human; it does not drive Studio, contact a terminal, or decode MER or MED
|
|
14
|
+
databases.
|
|
15
|
+
|
|
16
|
+
## Start
|
|
17
|
+
|
|
18
|
+
1. Call `ftview_open` with the export folder. Keep the returned `view_id`.
|
|
19
|
+
2. Later calls may omit `view_id` when exactly one export is open.
|
|
20
|
+
3. Ask only for the exports the task needs: display XML for display work, the tag CSV for tag work,
|
|
21
|
+
L5X only when PLC binding matters.
|
|
22
|
+
|
|
23
|
+
## Inspect
|
|
24
|
+
|
|
25
|
+
- `ftview_list` enumerates displays or tags, with a name filter and paging.
|
|
26
|
+
- `ftview_get` reads one display (its named objects) or one tag row.
|
|
27
|
+
- `ftview_find` searches displays, object names, object attribute values and tags.
|
|
28
|
+
|
|
29
|
+
## Check and compare
|
|
30
|
+
|
|
31
|
+
- `ftview_check` reports structural findings: tag CSV integrity, duplicate display/object/tag names,
|
|
32
|
+
and files that did not parse. It is not vendor schema validation and says nothing about PLC
|
|
33
|
+
binding.
|
|
34
|
+
- `ftview_compare` compares two opened exports by display name, tag name and file hash.
|
|
35
|
+
|
|
36
|
+
## Editing
|
|
37
|
+
|
|
38
|
+
The `ftview-edit` entry stages changes; it may be disabled in this profile. If a draft tool is
|
|
39
|
+
unavailable, say editing is not enabled here rather than trying another tool.
|
|
40
|
+
|
|
41
|
+
- `ftview_draft_display_set` stages one attribute change on a display or one of its named objects.
|
|
42
|
+
- `ftview_draft_display_add` stages a new display by copying an existing display file.
|
|
43
|
+
- `ftview_draft_tag_upsert` stages one HMI tag description/type change or a new tag row.
|
|
44
|
+
- One operation per call. Each returns the draft id and the operation count; nothing is written yet.
|
|
45
|
+
- `ftview_validate` applies the staged edits to a re-parsed copy and reports the changed files.
|
|
46
|
+
- `ftview_apply` writes a NEW export folder. It never modifies the source.
|
|
47
|
+
|
|
48
|
+
After applying, reopen the written folder with `ftview_open` and compare it with the source using
|
|
49
|
+
`ftview_compare`.
|
|
50
|
+
|
|
51
|
+
## Studio
|
|
52
|
+
|
|
53
|
+
The `ftview-studio` entry plans a manual import; it may be disabled.
|
|
54
|
+
|
|
55
|
+
- `ftview_studio_status` discovers installed ME tooling, schemas and help files.
|
|
56
|
+
- `ftview_studio_preflight` checks the files that differ between two exports for Studio import
|
|
57
|
+
problems, including name restrictions.
|
|
58
|
+
- `ftview_studio_handoff` returns the ordered manual import plan for a human in FactoryTalk View
|
|
59
|
+
Studio. No vendor utility runs and no file is written.
|
|
60
|
+
|
|
61
|
+
## Reporting
|
|
62
|
+
|
|
63
|
+
- Every result carries `summary`, `data`, `next` and `coverage`. Read `coverage` before claiming
|
|
64
|
+
completeness.
|
|
65
|
+
- State what the export cannot prove: XSD validity, PLC binding, runtime behavior, visual rendering,
|
|
66
|
+
and anything absent from the supplied export.
|
|
67
|
+
- Quote the display file and object name for a finding.
|
|
68
|
+
- Do not call a tag unused from the absence of references in displays; other consumers are invisible
|
|
69
|
+
here.
|
|
70
|
+
|
|
71
|
+
## Out of scope
|
|
72
|
+
|
|
73
|
+
FactoryTalk View SE and FactoryTalk Optix are different products and are not analyzed here. MER/MED
|
|
74
|
+
databases are not decoded, and no tool contacts a PanelView terminal or changes runtime data.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural checks shared by the read and editing entries.
|
|
3
|
+
*
|
|
4
|
+
* @module dsh-engineering-ftview/checks
|
|
5
|
+
*/
|
|
6
|
+
import type { DisplayFile, TagRow } from './model.ts';
|
|
7
|
+
/** One finding the check reports. */
|
|
8
|
+
export interface Finding {
|
|
9
|
+
readonly rule: string;
|
|
10
|
+
readonly severity: 'error' | 'warning' | 'info';
|
|
11
|
+
readonly message: string;
|
|
12
|
+
readonly evidence: unknown;
|
|
13
|
+
}
|
|
14
|
+
/** The application parts the checks read. */
|
|
15
|
+
export interface Checkable {
|
|
16
|
+
readonly displays: readonly DisplayFile[];
|
|
17
|
+
readonly tags: readonly TagRow[];
|
|
18
|
+
readonly tagErrors: readonly string[];
|
|
19
|
+
readonly diagnostics: readonly string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Run the structural checks.
|
|
23
|
+
*
|
|
24
|
+
* @param app - Displays, tags and the diagnostics from scanning.
|
|
25
|
+
* @returns Findings in rule order.
|
|
26
|
+
*/
|
|
27
|
+
export declare function findingsOf(app: Checkable): Finding[];
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural checks shared by the read and editing entries.
|
|
3
|
+
*
|
|
4
|
+
* @module dsh-engineering-ftview/checks
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Run the structural checks.
|
|
8
|
+
*
|
|
9
|
+
* @param app - Displays, tags and the diagnostics from scanning.
|
|
10
|
+
* @returns Findings in rule order.
|
|
11
|
+
*/
|
|
12
|
+
export function findingsOf(app) {
|
|
13
|
+
const findings = [];
|
|
14
|
+
for (const error of app.tagErrors)
|
|
15
|
+
findings.push({ rule: 'TAG_CSV', severity: 'warning', message: error, evidence: { file: 'tag CSV' } });
|
|
16
|
+
for (const diagnostic of app.diagnostics)
|
|
17
|
+
findings.push({ rule: 'UNPARSED_FILE', severity: 'warning', message: diagnostic, evidence: { file: diagnostic.split(':')[0] } });
|
|
18
|
+
const displayNames = new Set();
|
|
19
|
+
for (const display of app.displays) {
|
|
20
|
+
if (displayNames.has(display.name))
|
|
21
|
+
findings.push({ rule: 'DUPLICATE_DISPLAY_NAME', severity: 'warning', message: `Two displays are named ${JSON.stringify(display.name)}.`, evidence: { display: display.name, file: display.file } });
|
|
22
|
+
displayNames.add(display.name);
|
|
23
|
+
const objectNames = new Set();
|
|
24
|
+
for (const object of display.objects) {
|
|
25
|
+
if (object.name === undefined)
|
|
26
|
+
continue;
|
|
27
|
+
if (objectNames.has(object.name))
|
|
28
|
+
findings.push({ rule: 'DUPLICATE_OBJECT_NAME', severity: 'warning', message: `Display ${JSON.stringify(display.name)} has more than one object named ${JSON.stringify(object.name)}.`, evidence: { display: display.name, object: object.name } });
|
|
29
|
+
objectNames.add(object.name);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const tagNames = new Set();
|
|
33
|
+
for (const tag of app.tags) {
|
|
34
|
+
if (tagNames.has(tag.name))
|
|
35
|
+
findings.push({ rule: 'DUPLICATE_TAG_NAME', severity: 'error', message: `The tag CSV declares ${JSON.stringify(tag.name)} more than once.`, evidence: { tag: tag.name } });
|
|
36
|
+
tagNames.add(tag.name);
|
|
37
|
+
}
|
|
38
|
+
return findings;
|
|
39
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared result, error and parameter conventions for the engineering bundle.
|
|
3
|
+
*
|
|
4
|
+
* Every tool answers with `summary`, `data`, `next` and `coverage`, and every
|
|
5
|
+
* parameter is described at the point of declaration. Failures carry a stable
|
|
6
|
+
* code, a message in the reader's terms, and the fix that unblocks the caller.
|
|
7
|
+
*
|
|
8
|
+
* @module dsh-engineering-ftview/core
|
|
9
|
+
*/
|
|
10
|
+
/** How completely an answer covers the request. */
|
|
11
|
+
export interface Coverage {
|
|
12
|
+
readonly complete: boolean;
|
|
13
|
+
readonly unverified: readonly string[];
|
|
14
|
+
}
|
|
15
|
+
/** One suggested follow-up call. */
|
|
16
|
+
export interface NextStep {
|
|
17
|
+
readonly tool: string;
|
|
18
|
+
readonly args?: Readonly<Record<string, unknown>>;
|
|
19
|
+
readonly why: string;
|
|
20
|
+
}
|
|
21
|
+
/** The success document every tool returns. */
|
|
22
|
+
export interface Success {
|
|
23
|
+
readonly summary: string;
|
|
24
|
+
readonly data: unknown;
|
|
25
|
+
readonly next: readonly NextStep[];
|
|
26
|
+
readonly coverage: Coverage;
|
|
27
|
+
}
|
|
28
|
+
/** A failure the caller can usually repair. */
|
|
29
|
+
export declare class EngineeringError extends Error {
|
|
30
|
+
readonly code: string;
|
|
31
|
+
readonly fix: string;
|
|
32
|
+
readonly candidates: readonly string[];
|
|
33
|
+
/**
|
|
34
|
+
* @param code - Stable identifier for tests and logs.
|
|
35
|
+
* @param message - What failed, in the reader's terms.
|
|
36
|
+
* @param fix - The next call or check.
|
|
37
|
+
* @param candidates - Known names the caller probably meant.
|
|
38
|
+
*/
|
|
39
|
+
constructor(code: string, message: string, fix: string, candidates?: readonly string[]);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Convert any thrown value into the error envelope.
|
|
43
|
+
*
|
|
44
|
+
* @param error - The thrown value.
|
|
45
|
+
* @returns The envelope the tool registry reports.
|
|
46
|
+
*/
|
|
47
|
+
export declare function errorEnvelope(error: unknown): {
|
|
48
|
+
error: {
|
|
49
|
+
code: string;
|
|
50
|
+
message: string;
|
|
51
|
+
fix: string;
|
|
52
|
+
candidates: readonly string[];
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
/** Build one success document. */
|
|
56
|
+
export declare function success(summary: string, data: unknown, next: readonly NextStep[], coverage: Coverage): Success;
|
|
57
|
+
/** One JSON Schema property, always described. */
|
|
58
|
+
export interface ParameterSchema {
|
|
59
|
+
readonly type: 'string' | 'integer' | 'number' | 'boolean' | 'array' | 'object';
|
|
60
|
+
readonly description: string;
|
|
61
|
+
readonly enum?: readonly string[];
|
|
62
|
+
readonly items?: ParameterSchema;
|
|
63
|
+
readonly default?: unknown;
|
|
64
|
+
readonly minimum?: number;
|
|
65
|
+
readonly maximum?: number;
|
|
66
|
+
readonly minItems?: number;
|
|
67
|
+
readonly maxItems?: number;
|
|
68
|
+
readonly properties?: Readonly<Record<string, ParameterSchema>>;
|
|
69
|
+
readonly required?: readonly string[];
|
|
70
|
+
readonly additionalProperties?: boolean;
|
|
71
|
+
}
|
|
72
|
+
/** A described string parameter. */
|
|
73
|
+
export declare function string(description: string, extra?: Partial<ParameterSchema>): ParameterSchema;
|
|
74
|
+
/** A described integer parameter with an optional range. */
|
|
75
|
+
export declare function integer(description: string, extra?: Partial<ParameterSchema>): ParameterSchema;
|
|
76
|
+
/** A described enum parameter. */
|
|
77
|
+
export declare function choice(description: string, values: readonly string[], extra?: Partial<ParameterSchema>): ParameterSchema;
|
|
78
|
+
/** One object element of an array parameter. */
|
|
79
|
+
export declare function objectItem(description: string, properties: Readonly<Record<string, ParameterSchema>>, required?: readonly string[]): ParameterSchema;
|
|
80
|
+
/** An array of one parameter type. */
|
|
81
|
+
export declare function list(description: string, items: ParameterSchema, extra?: Partial<ParameterSchema>): ParameterSchema;
|
|
82
|
+
/** The `parameters` object of one tool. */
|
|
83
|
+
export interface Parameters {
|
|
84
|
+
readonly type: 'object';
|
|
85
|
+
readonly properties: Readonly<Record<string, ParameterSchema>>;
|
|
86
|
+
readonly required: readonly string[];
|
|
87
|
+
readonly additionalProperties: false;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Build a parameter object.
|
|
91
|
+
*
|
|
92
|
+
* @param properties - Named parameters, each already described.
|
|
93
|
+
* @param required - Names the caller must supply.
|
|
94
|
+
* @returns The schema a tool definition declares.
|
|
95
|
+
*/
|
|
96
|
+
export declare function object(properties: Readonly<Record<string, ParameterSchema>>, required?: readonly string[]): Parameters;
|
|
97
|
+
/** One directory entry the filesystem provider reports. */
|
|
98
|
+
export interface DirEntry {
|
|
99
|
+
readonly name: string;
|
|
100
|
+
readonly type: string;
|
|
101
|
+
}
|
|
102
|
+
/** The filesystem operations this package uses. */
|
|
103
|
+
export interface FsService {
|
|
104
|
+
resolve(path: string, options?: {
|
|
105
|
+
readonly signal?: AbortSignal;
|
|
106
|
+
readonly cwd?: string;
|
|
107
|
+
}): Promise<string>;
|
|
108
|
+
stat(path: string, signal?: AbortSignal): Promise<{
|
|
109
|
+
readonly type: string;
|
|
110
|
+
} | undefined>;
|
|
111
|
+
readBytes(path: string, signal: AbortSignal | undefined, maxBytes?: number): Promise<Uint8Array>;
|
|
112
|
+
listDir?(path: string, signal?: AbortSignal): Promise<readonly DirEntry[]>;
|
|
113
|
+
writeText?(path: string, text: string, options?: {
|
|
114
|
+
readonly kind?: 'createIfAbsent' | 'overwrite';
|
|
115
|
+
}, signal?: AbortSignal): Promise<void>;
|
|
116
|
+
}
|
|
117
|
+
/** A path resolved by the harness filesystem into its backend identity. */
|
|
118
|
+
export interface FsTarget {
|
|
119
|
+
/** Opaque key for stale guards and target lookup. */
|
|
120
|
+
readonly targetKey: unknown;
|
|
121
|
+
/** Path for model- and UI-facing output. */
|
|
122
|
+
readonly displayPath: string;
|
|
123
|
+
}
|
|
124
|
+
/** The harness filesystem as it is actually provided: operations take resolved targets. */
|
|
125
|
+
export interface RawFsService {
|
|
126
|
+
resolve(path: string, options?: {
|
|
127
|
+
readonly signal?: AbortSignal;
|
|
128
|
+
readonly cwd?: string;
|
|
129
|
+
}): Promise<FsTarget | string>;
|
|
130
|
+
stat(target: FsTarget | string, signal?: AbortSignal): Promise<{
|
|
131
|
+
readonly type: string;
|
|
132
|
+
} | undefined>;
|
|
133
|
+
readBytes(target: FsTarget | string, signal: AbortSignal | undefined, maxBytes?: number): Promise<Uint8Array>;
|
|
134
|
+
listDir?(target: FsTarget | string, signal?: AbortSignal): Promise<readonly DirEntry[]>;
|
|
135
|
+
writeText?(target: FsTarget | string, text: string, options?: {
|
|
136
|
+
readonly kind?: 'createIfAbsent' | 'overwrite';
|
|
137
|
+
}, signal?: AbortSignal): Promise<void>;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Present the harness filesystem with string paths.
|
|
141
|
+
*
|
|
142
|
+
* The model, edits and discovery compose paths (`${root}/${file}`); the harness
|
|
143
|
+
* service takes opaque targets. This adapter resolves each path before calling
|
|
144
|
+
* the service and returns display strings, so path composition stays readable.
|
|
145
|
+
* A provider that already returns strings, such as a test double, passes through.
|
|
146
|
+
*
|
|
147
|
+
* @param service - The harness filesystem service.
|
|
148
|
+
* @returns The same operations addressed by path strings.
|
|
149
|
+
*/
|
|
150
|
+
export declare function stringFs(service: RawFsService): FsService;
|
|
151
|
+
/** The tool registry the plugin registers into. */
|
|
152
|
+
export interface ToolRegistry {
|
|
153
|
+
register(definition: ToolDefinition): void;
|
|
154
|
+
}
|
|
155
|
+
/** The services a composition must provide before this plugin loads. */
|
|
156
|
+
export interface PluginContext {
|
|
157
|
+
readonly tools: ToolRegistry;
|
|
158
|
+
readonly fs: RawFsService;
|
|
159
|
+
provide?(name: string, value: unknown): void;
|
|
160
|
+
get?(name: string): unknown;
|
|
161
|
+
}
|
|
162
|
+
/** The context a tool body receives. */
|
|
163
|
+
export interface ExecContext {
|
|
164
|
+
readonly signal?: AbortSignal;
|
|
165
|
+
readonly cwd?: string;
|
|
166
|
+
readonly chat?: object;
|
|
167
|
+
}
|
|
168
|
+
/** One text block the transcript renders. */
|
|
169
|
+
export interface TextBlock {
|
|
170
|
+
readonly type: 'text';
|
|
171
|
+
readonly text: string;
|
|
172
|
+
}
|
|
173
|
+
/** The output declaration every registered tool carries. */
|
|
174
|
+
export interface ToolOutput {
|
|
175
|
+
readonly schema: {
|
|
176
|
+
readonly type: 'object';
|
|
177
|
+
readonly additionalProperties: boolean;
|
|
178
|
+
};
|
|
179
|
+
render(args: unknown, value: unknown): readonly TextBlock[];
|
|
180
|
+
}
|
|
181
|
+
/** One registered tool. */
|
|
182
|
+
export interface ToolDefinition {
|
|
183
|
+
readonly name: string;
|
|
184
|
+
readonly description: string;
|
|
185
|
+
readonly parameters: Parameters;
|
|
186
|
+
readonly output: ToolOutput;
|
|
187
|
+
execute(args: Readonly<Record<string, unknown>>, exec: ExecContext): Promise<unknown>;
|
|
188
|
+
}
|
|
189
|
+
/** One tool body before the shared envelope and error handling are attached. */
|
|
190
|
+
export interface ToolSpec {
|
|
191
|
+
readonly name: string;
|
|
192
|
+
readonly description: string;
|
|
193
|
+
readonly parameters: Parameters;
|
|
194
|
+
run(args: Readonly<Record<string, unknown>>, exec: ExecContext): Promise<unknown>;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Wrap one tool body in the shared envelope and error handling.
|
|
198
|
+
*
|
|
199
|
+
* @param spec - Tool identity and body.
|
|
200
|
+
* @returns The definition the registry accepts.
|
|
201
|
+
*/
|
|
202
|
+
export declare function tool(spec: ToolSpec): ToolDefinition;
|
|
203
|
+
/** A required string argument. */
|
|
204
|
+
export declare function requiredString(args: Readonly<Record<string, unknown>>, name: string): string;
|
|
205
|
+
/** An optional string argument. */
|
|
206
|
+
export declare function optionalString(args: Readonly<Record<string, unknown>>, name: string): string | undefined;
|
|
207
|
+
/** An optional integer argument. */
|
|
208
|
+
export declare function optionalInteger(args: Readonly<Record<string, unknown>>, name: string): number | undefined;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared result, error and parameter conventions for the engineering bundle.
|
|
3
|
+
*
|
|
4
|
+
* Every tool answers with `summary`, `data`, `next` and `coverage`, and every
|
|
5
|
+
* parameter is described at the point of declaration. Failures carry a stable
|
|
6
|
+
* code, a message in the reader's terms, and the fix that unblocks the caller.
|
|
7
|
+
*
|
|
8
|
+
* @module dsh-engineering-ftview/core
|
|
9
|
+
*/
|
|
10
|
+
/** A failure the caller can usually repair. */
|
|
11
|
+
export class EngineeringError 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 next call or check.
|
|
19
|
+
* @param candidates - Known names the caller probably meant.
|
|
20
|
+
*/
|
|
21
|
+
constructor(code, message, fix, candidates = []) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.name = 'EngineeringError';
|
|
24
|
+
this.code = code;
|
|
25
|
+
this.fix = fix;
|
|
26
|
+
this.candidates = candidates;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Convert any thrown value into the error envelope.
|
|
31
|
+
*
|
|
32
|
+
* @param error - The thrown value.
|
|
33
|
+
* @returns The envelope the tool registry reports.
|
|
34
|
+
*/
|
|
35
|
+
export function errorEnvelope(error) {
|
|
36
|
+
if (error instanceof EngineeringError) {
|
|
37
|
+
return { error: { code: error.code, message: error.message, fix: error.fix, candidates: error.candidates } };
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
error: {
|
|
41
|
+
code: 'INTERNAL',
|
|
42
|
+
message: error instanceof Error ? error.message : String(error),
|
|
43
|
+
fix: 'Retry the call; if it fails the same way, report the message and the arguments used.',
|
|
44
|
+
candidates: [],
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/** Build one success document. */
|
|
49
|
+
export function success(summary, data, next, coverage) {
|
|
50
|
+
return { summary, data, next, coverage };
|
|
51
|
+
}
|
|
52
|
+
/** A described string parameter. */
|
|
53
|
+
export function string(description, extra = {}) {
|
|
54
|
+
return { type: 'string', description, ...extra };
|
|
55
|
+
}
|
|
56
|
+
/** A described integer parameter with an optional range. */
|
|
57
|
+
export function integer(description, extra = {}) {
|
|
58
|
+
return { type: 'integer', description, ...extra };
|
|
59
|
+
}
|
|
60
|
+
/** A described enum parameter. */
|
|
61
|
+
export function choice(description, values, extra = {}) {
|
|
62
|
+
return { type: 'string', description, enum: values, ...extra };
|
|
63
|
+
}
|
|
64
|
+
/** One object element of an array parameter. */
|
|
65
|
+
export function objectItem(description, properties, required = []) {
|
|
66
|
+
return { type: 'object', description, properties, required, additionalProperties: false };
|
|
67
|
+
}
|
|
68
|
+
/** An array of one parameter type. */
|
|
69
|
+
export function list(description, items, extra = {}) {
|
|
70
|
+
return { type: 'array', description, items, ...extra };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Build a parameter object.
|
|
74
|
+
*
|
|
75
|
+
* @param properties - Named parameters, each already described.
|
|
76
|
+
* @param required - Names the caller must supply.
|
|
77
|
+
* @returns The schema a tool definition declares.
|
|
78
|
+
*/
|
|
79
|
+
export function object(properties, required = []) {
|
|
80
|
+
return { type: 'object', properties, required, additionalProperties: false };
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Present the harness filesystem with string paths.
|
|
84
|
+
*
|
|
85
|
+
* The model, edits and discovery compose paths (`${root}/${file}`); the harness
|
|
86
|
+
* service takes opaque targets. This adapter resolves each path before calling
|
|
87
|
+
* the service and returns display strings, so path composition stays readable.
|
|
88
|
+
* A provider that already returns strings, such as a test double, passes through.
|
|
89
|
+
*
|
|
90
|
+
* @param service - The harness filesystem service.
|
|
91
|
+
* @returns The same operations addressed by path strings.
|
|
92
|
+
*/
|
|
93
|
+
export function stringFs(service) {
|
|
94
|
+
const targetOf = async (path, signal) => await service.resolve(path, signal === undefined ? {} : { signal });
|
|
95
|
+
const fs = {
|
|
96
|
+
async resolve(path, options) {
|
|
97
|
+
const value = await service.resolve(path, options);
|
|
98
|
+
return typeof value === 'string' ? value : value.displayPath;
|
|
99
|
+
},
|
|
100
|
+
async stat(path, signal) {
|
|
101
|
+
return await service.stat(await targetOf(path, signal), signal);
|
|
102
|
+
},
|
|
103
|
+
async readBytes(path, signal, maxBytes) {
|
|
104
|
+
return await service.readBytes(await targetOf(path, signal), signal, maxBytes);
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
if (service.listDir !== undefined) {
|
|
108
|
+
fs.listDir = async (path, signal) => await service.listDir(await targetOf(path, signal), signal);
|
|
109
|
+
}
|
|
110
|
+
if (service.writeText !== undefined) {
|
|
111
|
+
fs.writeText = async (path, text, options, signal) => {
|
|
112
|
+
await service.writeText(await targetOf(path, signal), text, options, signal);
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return fs;
|
|
116
|
+
}
|
|
117
|
+
/** Render one tool answer as JSON text for the transcript. */
|
|
118
|
+
function jsonText(_args, value) {
|
|
119
|
+
return [{ type: 'text', text: JSON.stringify(value, null, 2) }];
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Wrap one tool body in the shared envelope and error handling.
|
|
123
|
+
*
|
|
124
|
+
* @param spec - Tool identity and body.
|
|
125
|
+
* @returns The definition the registry accepts.
|
|
126
|
+
*/
|
|
127
|
+
export function tool(spec) {
|
|
128
|
+
return {
|
|
129
|
+
name: spec.name,
|
|
130
|
+
description: spec.description,
|
|
131
|
+
parameters: spec.parameters,
|
|
132
|
+
output: { schema: { type: 'object', additionalProperties: true }, render: jsonText },
|
|
133
|
+
async execute(args, exec) {
|
|
134
|
+
try {
|
|
135
|
+
return await spec.run(args, exec);
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
return errorEnvelope(error);
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/** A required string argument. */
|
|
144
|
+
export function requiredString(args, name) {
|
|
145
|
+
const value = args[name];
|
|
146
|
+
if (typeof value !== 'string' || value === '') {
|
|
147
|
+
throw new EngineeringError('INVALID_ARGUMENT', `${name} is required and must be a non-empty string.`, `Pass ${name}, for example "${name}".`);
|
|
148
|
+
}
|
|
149
|
+
return value;
|
|
150
|
+
}
|
|
151
|
+
/** An optional string argument. */
|
|
152
|
+
export function optionalString(args, name) {
|
|
153
|
+
const value = args[name];
|
|
154
|
+
return typeof value === 'string' && value !== '' ? value : undefined;
|
|
155
|
+
}
|
|
156
|
+
/** An optional integer argument. */
|
|
157
|
+
export function optionalInteger(args, name) {
|
|
158
|
+
const value = args[name];
|
|
159
|
+
return typeof value === 'number' && Number.isInteger(value) ? value : undefined;
|
|
160
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drafts for staged ME edits.
|
|
3
|
+
*
|
|
4
|
+
* One draft per opened export per chat. Operations accumulate until validate or
|
|
5
|
+
* apply; nothing here reads or writes export files.
|
|
6
|
+
*
|
|
7
|
+
* @module dsh-engineering-ftview/edit/drafts
|
|
8
|
+
*/
|
|
9
|
+
import { type ExecContext } from '../core.ts';
|
|
10
|
+
import type { EditOperation } from './operations.ts';
|
|
11
|
+
/** One accumulated edit list. */
|
|
12
|
+
export interface EditDraft {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly viewId: string;
|
|
15
|
+
readonly operations: readonly EditOperation[];
|
|
16
|
+
readonly createdAt: string;
|
|
17
|
+
}
|
|
18
|
+
/** Drafts, scoped to the chat that created them. */
|
|
19
|
+
export declare class EditDrafts {
|
|
20
|
+
private readonly chats;
|
|
21
|
+
private readonly detached;
|
|
22
|
+
/**
|
|
23
|
+
* Append one operation to the draft for a view, creating it on first use.
|
|
24
|
+
*
|
|
25
|
+
* @param exec - Calling context.
|
|
26
|
+
* @param viewId - View the draft edits.
|
|
27
|
+
* @param operation - Operation to append.
|
|
28
|
+
* @param maxOperations - Inclusive cap for one draft.
|
|
29
|
+
* @returns The updated draft.
|
|
30
|
+
*/
|
|
31
|
+
append(exec: ExecContext | undefined, viewId: string, operation: EditOperation, maxOperations: number): EditDraft;
|
|
32
|
+
/**
|
|
33
|
+
* Resolve one draft by handle.
|
|
34
|
+
*
|
|
35
|
+
* @param exec - Calling context.
|
|
36
|
+
* @param id - Draft handle; empty selects the chat's only draft.
|
|
37
|
+
* @returns The draft.
|
|
38
|
+
*/
|
|
39
|
+
get(exec: ExecContext | undefined, id: string | undefined): EditDraft;
|
|
40
|
+
/**
|
|
41
|
+
* Drop one draft after it is applied.
|
|
42
|
+
*
|
|
43
|
+
* @param exec - Calling context.
|
|
44
|
+
* @param id - Draft handle.
|
|
45
|
+
*/
|
|
46
|
+
remove(exec: ExecContext | undefined, id: string): void;
|
|
47
|
+
/** The draft map for one calling chat. */
|
|
48
|
+
private draftsOf;
|
|
49
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drafts for staged ME edits.
|
|
3
|
+
*
|
|
4
|
+
* One draft per opened export per chat. Operations accumulate until validate or
|
|
5
|
+
* apply; nothing here reads or writes export files.
|
|
6
|
+
*
|
|
7
|
+
* @module dsh-engineering-ftview/edit/drafts
|
|
8
|
+
*/
|
|
9
|
+
import { randomUUID } from 'node:crypto';
|
|
10
|
+
import { EngineeringError } from "../core.js";
|
|
11
|
+
/** Drafts, scoped to the chat that created them. */
|
|
12
|
+
export class EditDrafts {
|
|
13
|
+
chats = new WeakMap();
|
|
14
|
+
detached = new Map();
|
|
15
|
+
/**
|
|
16
|
+
* Append one operation to the draft for a view, creating it on first use.
|
|
17
|
+
*
|
|
18
|
+
* @param exec - Calling context.
|
|
19
|
+
* @param viewId - View the draft edits.
|
|
20
|
+
* @param operation - Operation to append.
|
|
21
|
+
* @param maxOperations - Inclusive cap for one draft.
|
|
22
|
+
* @returns The updated draft.
|
|
23
|
+
*/
|
|
24
|
+
append(exec, viewId, operation, maxOperations) {
|
|
25
|
+
const drafts = this.draftsOf(exec);
|
|
26
|
+
const current = [...drafts.values()].find(draft => draft.viewId === viewId);
|
|
27
|
+
if (current === undefined) {
|
|
28
|
+
const created = { id: randomUUID(), viewId, operations: [operation], createdAt: new Date().toISOString() };
|
|
29
|
+
drafts.set(created.id, created);
|
|
30
|
+
return created;
|
|
31
|
+
}
|
|
32
|
+
if (current.operations.length >= maxOperations) {
|
|
33
|
+
throw new EngineeringError('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.');
|
|
34
|
+
}
|
|
35
|
+
const updated = { ...current, operations: [...current.operations, operation] };
|
|
36
|
+
drafts.set(updated.id, updated);
|
|
37
|
+
return updated;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Resolve one draft by handle.
|
|
41
|
+
*
|
|
42
|
+
* @param exec - Calling context.
|
|
43
|
+
* @param id - Draft handle; empty selects the chat's only draft.
|
|
44
|
+
* @returns The draft.
|
|
45
|
+
*/
|
|
46
|
+
get(exec, id) {
|
|
47
|
+
const drafts = this.draftsOf(exec);
|
|
48
|
+
const ids = [...drafts.keys()];
|
|
49
|
+
if (id === undefined || id === '') {
|
|
50
|
+
const only = ids[0];
|
|
51
|
+
if (only === undefined)
|
|
52
|
+
throw new EngineeringError('NO_DRAFT', 'No edit draft exists in this chat.', 'Add an operation with an ftview_draft_* tool first.');
|
|
53
|
+
if (ids.length > 1)
|
|
54
|
+
throw new EngineeringError('AMBIGUOUS_DRAFT', `${ids.length} drafts exist in this chat, so draft_id is required.`, `Pass one of: ${ids.join(', ')}.`, ids);
|
|
55
|
+
return drafts.get(only);
|
|
56
|
+
}
|
|
57
|
+
const draft = drafts.get(id);
|
|
58
|
+
if (draft === undefined) {
|
|
59
|
+
throw new EngineeringError('UNKNOWN_DRAFT', `No draft exists with draft_id ${JSON.stringify(id)} in this chat.`, ids.length === 0 ? 'Add an operation with an ftview_draft_* tool first.' : `Pass one of this chat's draft ids: ${ids.join(', ')}.`, ids);
|
|
60
|
+
}
|
|
61
|
+
return draft;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Drop one draft after it is applied.
|
|
65
|
+
*
|
|
66
|
+
* @param exec - Calling context.
|
|
67
|
+
* @param id - Draft handle.
|
|
68
|
+
*/
|
|
69
|
+
remove(exec, id) {
|
|
70
|
+
this.draftsOf(exec).delete(id);
|
|
71
|
+
}
|
|
72
|
+
/** The draft map for one calling chat. */
|
|
73
|
+
draftsOf(exec) {
|
|
74
|
+
const chat = exec?.chat;
|
|
75
|
+
if (chat === undefined)
|
|
76
|
+
return this.detached;
|
|
77
|
+
const existing = this.chats.get(chat);
|
|
78
|
+
if (existing !== undefined)
|
|
79
|
+
return existing;
|
|
80
|
+
const created = new Map();
|
|
81
|
+
this.chats.set(chat, created);
|
|
82
|
+
return created;
|
|
83
|
+
}
|
|
84
|
+
}
|